зеркало из https://github.com/mozilla/gecko-dev.git
274 строки
6.7 KiB
C++
274 строки
6.7 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
|
|
#include "fredmem.h"
|
|
|
|
#include "shist.h"
|
|
#include "shistele.h"
|
|
#include "lo_ele.h"
|
|
#include "proto.h"
|
|
#include "net.h"
|
|
#include "libimg.h"
|
|
#include "fe_proto.h"
|
|
#include "uerrmgr.h"
|
|
#include "PascalString.h"
|
|
#include "resgui.h"
|
|
#include "MacMemAllocator.h"
|
|
|
|
//#include "MToolkit.h"
|
|
|
|
enum {
|
|
kEmergencyMemoryFundSize = 64 * 1024
|
|
};
|
|
|
|
|
|
class LMallocFlusherPeriodical : public LPeriodical {
|
|
public:
|
|
LMallocFlusherPeriodical();
|
|
virtual void SpendTime(const EventRecord &inMacEvent);
|
|
void FlushMemory ( void ) { mFlushMemory = true; }
|
|
|
|
private:
|
|
Boolean mFlushMemory;
|
|
};
|
|
|
|
|
|
class LLowMallocWarningPeriodical : public LPeriodical {
|
|
public:
|
|
LLowMallocWarningPeriodical();
|
|
virtual void SpendTime(const EventRecord &inMacEvent);
|
|
void WarnUserMallocLow ( void ) { mWarnUser = true; }
|
|
|
|
private:
|
|
Boolean mWarnUser;
|
|
};
|
|
|
|
|
|
unsigned char MacFEMemoryFlusher ( size_t bytesNeeded );
|
|
void ImageCacheMemoryFlusher(void);
|
|
void LayoutCacheMemoryFlusher(void);
|
|
void NetlibCacheMemoryFlusher(void);
|
|
void LibNeoCacheMemoryFlusher(void);
|
|
|
|
void MallocIsLowWarning(void);
|
|
|
|
static LMallocFlusherPeriodical gMallocFlusher;
|
|
static LLowMallocWarningPeriodical gMallocWarner;
|
|
|
|
void Memory_InitializeMemory()
|
|
{
|
|
new LGrowZone(kEmergencyMemoryFundSize);
|
|
new LMemoryFlusherListener();
|
|
|
|
InstallMemoryCacheFlusher(&MacFEMemoryFlusher);
|
|
|
|
// install our low memory (malloc heap) warning proc
|
|
InstallMallocHeapLowProc ( &MallocIsLowWarning );
|
|
}
|
|
|
|
void Memory_DoneWithMemory()
|
|
{
|
|
// No cleanup necessary
|
|
}
|
|
|
|
size_t Memory_MaxApplMem()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
Boolean Memory_MemoryIsLow()
|
|
{
|
|
return (LGrowZone::GetGrowZone())->MemoryIsLow();
|
|
}
|
|
|
|
//##############################################################################
|
|
//##############################################################################
|
|
#pragma mark MAC FE MEMORY FLUSH PROC
|
|
unsigned char MacFEMemoryFlusher ( size_t bytesNeeded )
|
|
{
|
|
/* signal the flusher to do it's thing. I would rather start the idler here */
|
|
/* but that involves allocating memory (and so could be reentrant)... */
|
|
gMallocFlusher.FlushMemory();
|
|
|
|
return 0;
|
|
}
|
|
|
|
//##############################################################################
|
|
//##############################################################################
|
|
#pragma mark LAYOUT CACHE FLUSHING
|
|
|
|
LArray sFlushableLayoutContextList;
|
|
|
|
void FM_SetFlushable(MWContext* context, Boolean canFlush)
|
|
{
|
|
if (canFlush) {
|
|
if (sFlushableLayoutContextList.FetchIndexOf(&context) == 0)
|
|
sFlushableLayoutContextList.InsertItemsAt(1, LArray::index_Last, &context);
|
|
}
|
|
|
|
else {
|
|
sFlushableLayoutContextList.Remove(&context);
|
|
}
|
|
}
|
|
|
|
void LayoutCacheMemoryFlusher(void)
|
|
{
|
|
MWContext *currentContext = NULL;
|
|
SInt32 bytesFreed = 0;
|
|
|
|
LArrayIterator iter(sFlushableLayoutContextList);
|
|
|
|
// go ahead and empty all the recycling bins
|
|
while ( iter.Previous(¤tContext) )
|
|
{
|
|
bytesFreed += LO_EmptyRecyclingBin(currentContext);
|
|
sFlushableLayoutContextList.RemoveItemsAt( 1, 1 );
|
|
}
|
|
}
|
|
|
|
//##############################################################################
|
|
//##############################################################################
|
|
#pragma mark LIBNEO CACHE FLUSHING
|
|
|
|
void LibNeoCacheMemoryFlusher(void)
|
|
{
|
|
// don't do this yet until we really understand how safe it is
|
|
#if 0
|
|
// we don't really know how much was freed here
|
|
NeoOutOfMemHandler();
|
|
#endif
|
|
}
|
|
|
|
//##############################################################################
|
|
//##############################################################################
|
|
#pragma mark NETLIB CACHE FLUSHING
|
|
|
|
void NetlibCacheMemoryFlusher(void)
|
|
{
|
|
size_t newCacheSize;
|
|
size_t lastCacheSize;
|
|
|
|
newCacheSize = NET_GetMemoryCacheSize();
|
|
|
|
// shrink as much as we can
|
|
do {
|
|
lastCacheSize = newCacheSize;
|
|
newCacheSize = NET_RemoveLastMemoryCacheObject();
|
|
}
|
|
while ( newCacheSize != lastCacheSize );
|
|
}
|
|
|
|
|
|
//##############################################################################
|
|
//##############################################################################
|
|
#pragma mark IMAGE CACHE FLUSHING
|
|
|
|
void ImageCacheMemoryFlusher(void)
|
|
{
|
|
size_t newCacheSize;
|
|
size_t lastCacheSize;
|
|
|
|
newCacheSize = IL_GetCacheSize();
|
|
|
|
// shrink as much as we can
|
|
do {
|
|
lastCacheSize = newCacheSize;
|
|
newCacheSize = IL_ShrinkCache();
|
|
}
|
|
while ( newCacheSize != lastCacheSize );
|
|
}
|
|
|
|
|
|
//##############################################################################
|
|
//##############################################################################
|
|
#pragma mark MALLOC HEAP LOW USER WARNING
|
|
|
|
void MallocIsLowWarning(void)
|
|
{
|
|
gMallocWarner.WarnUserMallocLow();
|
|
}
|
|
|
|
//##############################################################################
|
|
//##############################################################################
|
|
#pragma mark GROW ZONE LISTENER
|
|
|
|
LMemoryFlusherListener::
|
|
LMemoryFlusherListener():LListener()
|
|
{
|
|
(LGrowZone::GetGrowZone())->AddListener(this);
|
|
}
|
|
|
|
|
|
void
|
|
LMemoryFlusherListener::ListenToMessage(MessageT inMessage, void *ioParam)
|
|
{
|
|
Int32 *bytesToFree = (Int32 *)ioParam;
|
|
if (inMessage == msg_GrowZone) {
|
|
UInt8 successfulFlush = false;
|
|
|
|
/* we don't do anything here yet */
|
|
if (!successfulFlush)
|
|
*bytesToFree = 0;
|
|
}
|
|
}
|
|
|
|
//##############################################################################
|
|
//##############################################################################
|
|
#pragma mark MEMORY PERIODICAL
|
|
|
|
LLowMallocWarningPeriodical::LLowMallocWarningPeriodical() : LPeriodical()
|
|
{
|
|
mWarnUser = false;
|
|
|
|
StartIdling();
|
|
}
|
|
|
|
|
|
void
|
|
LLowMallocWarningPeriodical::SpendTime(const EventRecord &inMacEvent)
|
|
{
|
|
if ( mWarnUser )
|
|
{
|
|
StopIdling();
|
|
FE_Alert( NULL, GetPString ( MALLOC_HEAP_LOW_RESID ) );
|
|
}
|
|
}
|
|
|
|
|
|
LMallocFlusherPeriodical::LMallocFlusherPeriodical() : LPeriodical()
|
|
{
|
|
mFlushMemory = false;
|
|
|
|
StartIdling();
|
|
}
|
|
|
|
void
|
|
LMallocFlusherPeriodical::SpendTime(const EventRecord &inMacEvent)
|
|
{
|
|
if ( mFlushMemory )
|
|
{
|
|
ImageCacheMemoryFlusher();
|
|
LayoutCacheMemoryFlusher();
|
|
NetlibCacheMemoryFlusher();
|
|
LibNeoCacheMemoryFlusher();
|
|
|
|
mFlushMemory = false;
|
|
}
|
|
|
|
}
|