Fix for bug 20743 -- implement a memory cushion for Mac, to better handle low memory conditions. r=pinkerton

This commit is contained in:
sfraser%netscape.com 2000-07-25 01:04:55 +00:00
Родитель 76dcb92bfe
Коммит 6ebca7150d
4 изменённых файлов: 118 добавлений и 2 удалений

Просмотреть файл

@ -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