LGrowZone is a PowerPlant class to use for managing any low memory situations that occur during your program's execution. For general information about the Mac OS GrowZone concepts, refer to Inside Macintosh: Memory, published by Addison-Wesley.
LGrowZone's implementation provides two levels of functionality. First, it provides the classic behavior of allocating a user-specified emergency reserve buffer of memory upon creation of the GrowZone. The OS will then notify your application when to draw from this emergency reserve in low-memory situations. Second, LGrowZone can work with other PowerPlant objects to ask them to free memory when it becomes scarce.
Methods :
The methods in the LGrowZone class are:
Data Members:
The data members in the LGrowZone class are:
Operation:
Near the start of your application code you should create a single instance of LGrowZone, as shown here:
main() {
// do init stuff here
// create a memory reserve of 32K bytes
new LGrowZone( 32 * 1024 );
// the rest of your code goes here...
}
LGrowZone inherits from LBroadcaster. Objects which are able to free memory when it is becoming depleted
should be Listeners, and attach themselves to the LGrowZone object
so they will be notified when memory is low. The following code
shows how to add your objects as listeners for this low-memory
notification. This code attaches myObj as a Listener to the LGrowZone messages.
LGrowZone::GetGrowZone()->AddListener(myObj);
When memory is needed, you'll want myObj to be able to respond to a ListenToMessage() call. The call to ListenToMessage() will occur with a msg_GrowZone message, and a pointer to the number of bytes needed. You should
add code similar to the following to your object's class definition
to handle the ListenToMessage() method, that you inherit from LBroadcaster.
MyClass::ListenToMessage( MessageT inMessage,
void *ioParam)
{
if (inMessage == msg_GrowZone) {
// Memory is low, free our cache
SInt32 freedBytes =
::GetHandleSize(myCache);
::DisposeHandle(myCache);
myCache = nil;
// Pass back bytes freed
*(SInt32*)ioParam = freedBytes;
}
}
For example, suppose MyClass stores the myCache Handle with data generated from a lengthy calculation. If memory
gets low, it can dispose of the cached data, meaning that it will
have to recalculate the data if it needs it later. This is a common
trade-off: memory versus speed.
This class also inherits from LPeriodical. LGrowZone's constructor installs the object in the Periodical Repeater queue so that its SpendTime() function gets called each time through the main event loop. This is required so that the LGrowZone object can monitor memory usage and can respond appropriately, perhaps by displaying a warning to the user.
Source files:
See also:
Purpose:
The constructor allocates a memory reserve of the passed-in size, and a GrowZone function for the current process is then registered with the operating system.
The constructor also installs this LGrowZone object in the Periodical Repeater queue defined by LPeriodical, so that the SpendTime() method will get called each time through the application's main event loop.
Access:
Prototype:
LGrowZone(Size inReserveSize);Parameters:
This method has the following parameter:
Return:
Purpose:
The destructor destroys the LGrowZone object. This includes deallocating the previously-allocated memory reserve and deinstalling the GrowZone function.
Access:
Prototype:
virtual ~LGrowZone();Parameters:
Return:
Purpose:
This method broadcasts a message to listeners that they should free up some memory if possible. In order for an object to be a listener, it must have registered with the LGrowZone object using AddListener().
Access:
Prototype:
virtual SInt32 AskListenersToFree(Parameters:
Size inBytesNeeded );
This method has the following parameter:
Return:
SInt32 containing the number of bytes that were freed as a result of
calling this method. If no memory could be freed, then it returns
0.
Remarks:
msg_GrowZone message (via the ListenToMessage() call) to each object that has registered as a Listener, with
a parameter that is a pointer to the number of bytes needed. On
exit, objects that are Listeners should set this pointer equal
to the number of bytes that they deallocated.
Purpose:
This method is called by the GrowZone function installed by the LGrowZone() constructor when the operating system needs more memory.
Access:
Prototype:
virtual DoGrowZone( Size inBytesNeeded );Parameters:
This method has the following parameter:
Return:
SInt32 containing the number of bytes that were freed as a result of
calling this method. If no memory could be freed, then it returns
0.
Remarks:
This method is not normally called directly in your normal application code.
Purpose:
This method is an accessor, designed to return a pointer to the LGrowZone object.
Access:
Prototype:
static LGrowZone* GetGrowZone();Parameters:
Return:
A pointer to the LGrowZone object in your application.
Remarks:
You might need this method if you are going to call AddListener(). This would be done to register an object for future notification of low-memory conditions.
Purpose:
This method sets the mGiveWarning data member to true.
Access:
Prototype:
void GiveWarning();Parameters:
Return:
Remarks:
You might want to call this method if you wish to have the PowerPlant framework display a generic alert to the user when memory is depleted.
Purpose:
This method is called when the System requires more memory.
Access:
Prototype:
static pascal SInt32 GrowZoneCallBack(Parameters:
Size inBytesNeeded );
This method has the following parameter:
Return:
SInt32 containing the number of bytes that were freed by your program.
Remarks:
This is the GrowZone function registered with the System. It sets up the Motorola 68K A5 world so we can access globals, then calls a virtual function for the LGrowZone class.
Purpose:
This method provides a way of determining whether the memory reserve allocated by the LGrowZone() constructor has been utilized.
Access:
Prototype:
virtual Boolean MemoryIsLow();Parameters:
Return:
Return true if the LGrowZone() memory reserve has been used, false otherwise.
Remarks:
Objects in your program can call this method if they wish to behave differently under low memory situations. For example, a program could disable the "New" and "Open" commands to prevent new Documents from being created when memory is low.
Purpose:
This method performs periodic maintenance for the LGrowZone object, including
Access:
Prototype:
virtual void SpendTime(Parameters:
const EventRecord& inMacEvent );
This method has the following parameter:
An EventRecord reference is the parameter to this method, but it is not utilized
by this override.
Return:
Remarks:This method is an override of the SpendTime() base class method from LPeriodical(). This method attempts to reallocate the LGrowZone() memory reserve if necessary, and (optionally) warn the user if memory is getting low. This method is called each time through the main event loop. In order for the framework to provide a warning, the GiveWarning() method must be called first.
Purpose:
This method empties the reserve that was allocated during creation of the LGrowZone object.
Access:
Prototype:
virtual SInt32 UseLocalReserve(Size inBytesNeeded );Parameters:
This method has the following parameter:
Return:
SInt32 containing the number of bytes that were freed.
Remarks:Calling this method is a last chance desperate attempt to free enough memory to proceed. If the memory reserve for LGrowZone exists, it will be freed. Also, mGiveWarning is set to true. The user will receive warning alerts from the framework if memory becomes low again.
Purpose:
This is a pointer to the LGrowZone object. It is accessible using the GetGrowZone() accessor method.
Access:
Prototype:
static LGrowZone* sGrowZone;Remarks:
You do not normally need to directly access this data member, and should use the GetGrowZone() accessor method instead.
Purpose:
This is a Universal Procedure Pointer (UPP) used for pointing to the GrowZone procedure.
Access:
Prototype:
static GrowZoneUPP sGrowZoneUPP;
Purpose:
This member is a Handle to the memory reserve allocated by the LGrowZone() constructor.
Access:
Prototype:
Handle mLocalReserve;
Purpose:
This member is a count of the size (in bytes) of the memory reserve area allocated by the LGrowZone() constructor.
Access:
Prototype:
Size mReserveSize;
Purpose:
This data member is set to true if you want the PowerPlant framework to provide a default warning alert to the user under low-memory conditions.
Access:
Prototype:
Boolean GiveWarning;Remarks:
The default for this data member is false when the LGrowZone() constructor is invoked.