зеркало из https://github.com/mozilla/gecko-dev.git
Fix for bug 20743 -- implement a memory cushion for Mac, to better handle low memory conditions. r=pinkerton
This commit is contained in:
Родитель
76dcb92bfe
Коммит
6ebca7150d
|
@ -84,6 +84,15 @@ NS_IMETHODIMP nsAppShell::Create(int* argc, char ** argv)
|
|||
mMacSink = auto_ptr<nsMacMessageSink>( new nsMacMessageSink() );
|
||||
nsIToolkit* toolkit = mToolkit.get();
|
||||
mMacPump = auto_ptr<nsMacMessagePump>( new nsMacMessagePump(static_cast<nsToolkit*>(toolkit), mMacSink.get()) );
|
||||
mMacMemoryCushion = auto_ptr<nsMacMemoryCushion>( new nsMacMemoryCushion() );
|
||||
|
||||
if (!mMacSink.get() || !mMacPump.get() || !mMacMemoryCushion.get())
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
OSErr err = mMacMemoryCushion->Init(nsMacMemoryCushion::kMemoryReserveSize);
|
||||
if (err != noErr)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -97,6 +106,7 @@ NS_IMETHODIMP nsAppShell::Run(void)
|
|||
if (!mMacPump.get())
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
mMacMemoryCushion->StartRepeating();
|
||||
mMacPump->StartRunning();
|
||||
mMacPump->DoMessagePump();
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ using std::auto_ptr;
|
|||
|
||||
class nsMacMessagePump;
|
||||
class nsMacMessageSink;
|
||||
class nsMacMemoryCushion;
|
||||
class nsIToolkit;
|
||||
|
||||
|
||||
|
@ -57,7 +58,8 @@ class nsAppShell : public nsIAppShell
|
|||
nsDispatchListener *mDispatchListener; // note: we don't own this, but it can be NULL
|
||||
nsCOMPtr<nsIToolkit> mToolkit;
|
||||
auto_ptr<nsMacMessagePump> mMacPump;
|
||||
auto_ptr<nsMacMessageSink> mMacSink; //€€€ this will be COM, so use scc's COM_auto_ptr
|
||||
auto_ptr<nsMacMessageSink> mMacSink; // this will be COM, so use scc's COM_auto_ptr
|
||||
auto_ptr<nsMacMemoryCushion> mMacMemoryCushion;
|
||||
PRBool mExitCalled;
|
||||
static PRBool mInitializedToolbox;
|
||||
};
|
||||
|
|
|
@ -30,7 +30,8 @@
|
|||
#include "nsIEventQueue.h"
|
||||
#include "nsIEventQueueService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
|
||||
#include "nsIImageManager.h"
|
||||
#include "nsGfxCIID.h"
|
||||
|
||||
//#define MAC_PL_EVENT_TWEAKING
|
||||
|
||||
|
@ -38,6 +39,7 @@
|
|||
static NS_DEFINE_CID(kEventQueueCID, NS_EVENTQUEUE_CID);
|
||||
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
||||
|
||||
static NS_DEFINE_IID(kImageManagerCID, NS_IMAGEMANAGER_CID);
|
||||
|
||||
static nsMacNSPREventQueueHandler* gEventQueueHandler = nsnull;
|
||||
|
||||
|
@ -285,3 +287,70 @@ NS_METHOD NS_GetCurrentToolkit(nsIToolkit* *aResult)
|
|||
return rv;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
Handle nsMacMemoryCushion::sMemoryReserve;
|
||||
|
||||
nsMacMemoryCushion::nsMacMemoryCushion()
|
||||
{
|
||||
}
|
||||
|
||||
nsMacMemoryCushion::~nsMacMemoryCushion()
|
||||
{
|
||||
::SetGrowZone(nsnull);
|
||||
if (sMemoryReserve)
|
||||
::DisposeHandle(sMemoryReserve);
|
||||
}
|
||||
|
||||
|
||||
OSErr nsMacMemoryCushion::Init(Size reserveSize)
|
||||
{
|
||||
sMemoryReserve = ::NewHandle(reserveSize);
|
||||
if (sMemoryReserve == nsnull)
|
||||
return ::MemError();
|
||||
|
||||
::SetGrowZone(NewGrowZoneProc(GrowZoneProc));
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
||||
void nsMacMemoryCushion::RepeatAction(const EventRecord &aMacEvent)
|
||||
{
|
||||
if (!RecoverMemoryReserve(kMemoryReserveSize))
|
||||
{
|
||||
nsMemory::HeapMinimize();
|
||||
|
||||
// until imglib implements nsIMemoryPressureObserver (bug 46337)
|
||||
// manually flush the imglib cache here
|
||||
nsCOMPtr<nsIImageManager> imageManager = do_GetService(kImageManagerCID);
|
||||
if (imageManager)
|
||||
{
|
||||
imageManager->FlushCache();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Boolean nsMacMemoryCushion::RecoverMemoryReserve(Size reserveSize)
|
||||
{
|
||||
if (!sMemoryReserve) return true; // not initted yet
|
||||
if (*sMemoryReserve != nsnull) return true; // everything is OK
|
||||
|
||||
::ReallocateHandle(sMemoryReserve, reserveSize);
|
||||
if (::MemError() != noErr) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
pascal long nsMacMemoryCushion::GrowZoneProc(Size amountNeeded)
|
||||
{
|
||||
long freedMem = 0;
|
||||
|
||||
if (sMemoryReserve && *sMemoryReserve && sMemoryReserve != ::GZSaveHnd())
|
||||
{
|
||||
freedMem = ::GetHandleSize(sMemoryReserve);
|
||||
::EmptyHandle(sMemoryReserve);
|
||||
}
|
||||
|
||||
return freedMem;
|
||||
}
|
||||
|
||||
|
|
|
@ -101,5 +101,40 @@ protected:
|
|||
};
|
||||
|
||||
|
||||
// class for low memory detection and handling
|
||||
class nsMacMemoryCushion : public Repeater
|
||||
{
|
||||
public:
|
||||
|
||||
enum {
|
||||
kMemoryReserveSize = 32 * 1024 // 32k memory reserve
|
||||
};
|
||||
|
||||
nsMacMemoryCushion();
|
||||
~nsMacMemoryCushion();
|
||||
|
||||
OSErr Init(Size reserveSize);
|
||||
|
||||
|
||||
void RepeatAction(const EventRecord &aMacEvent);
|
||||
|
||||
protected:
|
||||
|
||||
// allocate or recover the memory reserve. Returns true on success
|
||||
Boolean RecoverMemoryReserve(Size reserveSize);
|
||||
|
||||
public:
|
||||
|
||||
static pascal long GrowZoneProc(Size amountNeeded);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
static Handle sMemoryReserve;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // TOOLKIT_H
|
||||
|
|
Загрузка…
Ссылка в новой задаче