Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
Source/MemoryHandler.c
//¥ ------------------------------------------------------------------------------------------ ¥ |
//¥ |
//¥ Copyright © 1996 Apple Computer, Inc., All Rights Reserved |
//¥ |
//¥ |
//¥ You may incorporate this sample code into your applications without |
//¥ restriction, though the sample code has been provided "AS IS" and the |
//¥ responsibility for its operation is 100% yours. However, what you are |
//¥ not permitted to do is to redistribute the source as "DSC Sample Code" |
//¥ after having made changes. If you're going to re-distribute the source, |
//¥ we require that you make it clear in the source that the code was |
//¥ descended from Apple Sample Code, but that you've made changes. |
//¥ |
//¥ Authors: |
//¥ Chris De Salvo |
//¥ |
//¥ ------------------------------------------------------------------------------------------ ¥ |
/* |
These memory routines are kinda handy and solve a lot of problems on the Mac when dealing |
with memory. For instance, people often call DisposeHandle() when they mean to call |
ReleaseResource() and it screws up their resource chain. DisposeHandleZ() checks to see |
if the handle is locked or not, and whether it's a resource or not and takes the appropriate |
action. |
All functions ending in 'Z' take the ADDRESS of the Ptr/Handle and set it to nil when it |
disposes of the memory. This is handy because you can then do things like this: |
foo = NewPtr(); |
DisposePtrZ(&foo); |
... |
... |
if (foo) |
... |
Probably the most useful of all this stuff are the tagged Ptr and tagged Handle functions. |
Basically what they do is add 12 bytes to the beginning of every block of memory that you |
allocate. The first four bytes are the value kBlockTag. The second is an OSType that |
you provide. The 3rd group of four bytes is a refcon that you provide. This is really |
usefull when working with ZoneRanger or other memory watching tool because when you view |
a block of memory you can see your type and refcon and get a clue as to what the memory |
is. It's really great when you have a memory leak and can't tell what's not getting |
deallocated. Another use is for tracking resources. Pass in the resource type as the |
OSType field and the resource number in the refcon. Then in ZoneRanger you can see |
exactly which resource and number a handle is. |
Another use is for reference counting list of similar objects. If you allocate 200 foos |
then set the OSType to 'foo ' and make the refcon the index of which foo it is. This is |
helpful for finding off-by-one loop errors when deallocating lists and arrays. |
One other thing that has come in really handy is to set the OSType to some identifier saying |
which source file the block was allocated in and setting the refcon to the line number in |
that source file. That way in ZoneRanger you can tell exactly where that mystery block |
came from. |
*/ |
//¥ ------------------------------ Includes |
#include <Resources.h> |
#include <string.h> |
#include "MemoryHandler.h" |
//¥ ------------------------------ Private Definitions |
#define kBlockTag "TBLK" |
//¥ ------------------------------ Private Types |
//¥ ------------------------------ Private Variables |
//¥ ------------------------------ Private Functions |
//¥ ------------------------------ Public Variables |
//¥ -------------------- IsResourceHandle |
Boolean |
IsResourceHandle(Handle theHandle) |
{ |
SInt8 memState; |
memState = HGetState(theHandle); |
//¥ Check the resource bit in the handle info |
if (memState & 0x20) |
return (true); |
return (false); |
} |
//¥ -------------------- IsLockedHandle |
Boolean |
IsLockedHandle(Handle theHandle) |
{ |
SInt8 memState; |
//¥ Check the lock bit in the handle info |
memState = HGetState(theHandle); |
if (memState & 0x80) |
return (true); |
return (false); |
} |
//¥ -------------------- DisposeControlZ |
void |
DisposeControlZ(ControlHandle *theControl) |
{ |
if (! (**theControl)) |
return; |
if (IsLockedHandle((Handle) *theControl)) |
HUnlock((Handle) *theControl); |
DisposeControl(*theControl); |
*theControl = nil; |
} |
//¥ -------------------- DisposeWindowZ |
void |
DisposeWindowZ(WindowRef *theWindow) |
{ |
if (! *theWindow) |
return; |
DisposeWindow(*theWindow); |
*theWindow = nil; |
} |
//¥ -------------------- DisposeDialogZ |
void |
DisposeDialogZ(DialogPtr *theWindow) |
{ |
if (! *theWindow) |
return; |
DisposeDialog(*theWindow); |
*theWindow = nil; |
} |
//¥ -------------------- DisposeGWorldZ |
void |
DisposeGWorldZ(GWorldPtr *theGWorld) |
{ |
if (! *theGWorld) |
return; |
if (IsLockedHandle((Handle) GetGWorldPixMap(*theGWorld))) |
UnlockPixels(GetGWorldPixMap(*theGWorld)); |
DisposeGWorld(*theGWorld); |
*theGWorld = nil; |
} |
//¥ -------------------- DisposePaletteZ |
void |
DisposePaletteZ(PaletteHandle *thePal) |
{ |
if (! *thePal) |
return; |
if (IsResourceHandle((Handle) *thePal)) |
ReleaseResource((Handle) *thePal); |
else |
DisposePalette(*thePal); |
*thePal = nil; |
} |
//¥ -------------------- KillPictureZ |
void |
KillPictureZ(PicHandle *thePicture) |
{ |
if (! (**thePicture)) |
return; |
if (IsLockedHandle((Handle) *thePicture)) |
HUnlock((Handle) *thePicture); |
if (IsResourceHandle((Handle) *thePicture)) |
ReleaseResource((Handle) *thePicture); |
else |
KillPicture(*thePicture); |
*thePicture = nil; |
} |
//¥ -------------------- DisposePtrZ |
void |
DisposePtrZ(Ptr *thePtr) |
{ |
if (! *thePtr) |
return; |
DisposePtr(*thePtr); |
*thePtr = nil; |
} |
//¥ -------------------- DisposeHandleZ |
void |
DisposeHandleZ(Handle *theHandle) |
{ |
if (! (**theHandle)) |
return; |
if (IsLockedHandle(*theHandle)) |
HUnlock(*theHandle); |
if (IsResourceHandle(*theHandle)) |
ReleaseResource(*theHandle); |
else |
DisposeHandle(*theHandle); |
*theHandle = nil; |
} |
//¥ -------------------- TEDisposeZ |
void |
TEDisposeZ(TEHandle *theHandle) |
{ |
if (! (**theHandle)) |
return; |
if (IsLockedHandle((Handle) *theHandle)) |
HUnlock((Handle) *theHandle); |
if (IsResourceHandle((Handle) *theHandle)) |
ReleaseResource((Handle) *theHandle); |
else |
TEDispose(*theHandle); |
} |
//¥ -------------------- LDisposeZ |
void |
LDisposeZ(ListHandle *theHandle) |
{ |
if (! (**theHandle)) |
return; |
if (IsLockedHandle((Handle) *theHandle)) |
HUnlock((Handle) *theHandle); |
if (IsResourceHandle((Handle) *theHandle)) |
ReleaseResource((Handle) *theHandle); |
else |
LDispose(*theHandle); |
} |
//¥ -------------------- PurgeAndCompactMem |
void |
PurgeAndCompactMem() |
{ |
Size growSize; |
MaxMem(&growSize); |
} |
//¥ -------------------- NewTaggedPtr |
Ptr |
NewTaggedPtr(Size size, OSType tag, UInt32 refCon) |
{ |
Ptr thePtr; |
size += 12; |
thePtr = NewPtr(size); |
if (! thePtr) |
return (nil); |
BlockMoveData(kBlockTag, thePtr, 4); |
BlockMoveData(&tag, thePtr + 4, 4); |
BlockMoveData(&refCon, thePtr + 8, 4); |
return (thePtr + 12); |
} |
//¥ -------------------- NewTaggedPtrClear |
Ptr |
NewTaggedPtrClear(Size size, OSType tag, UInt32 refCon) |
{ |
Ptr thePtr; |
size += 12; |
thePtr = NewPtrClear(size); |
if (! thePtr) |
return (nil); |
BlockMoveData(kBlockTag, thePtr, 4); |
BlockMoveData(&tag, thePtr + 4, 4); |
BlockMoveData(&refCon, thePtr + 8, 4); |
return (thePtr + 12); |
} |
//¥ -------------------- DisposeTaggedPtr |
void |
DisposeTaggedPtr(Ptr thePtr) |
{ |
Ptr ptr2; |
if (! thePtr) |
return; |
ptr2 = thePtr - 12; |
//¥ Confirm that this is one of our tagged blocks first |
if (strncmp(kBlockTag, ptr2, 4) == 0) |
DisposePtr(ptr2); |
else |
DisposePtr(thePtr); |
} |
//¥ -------------------- DisposeTaggedPtrZ |
void |
DisposeTaggedPtrZ(Ptr *thePtr) |
{ |
Ptr ptr2; |
if (! *thePtr) |
return; |
ptr2 = (*thePtr) - 12; |
if (strncmp(kBlockTag, ptr2, 4) == 0) |
DisposePtr(ptr2); |
else |
DisposePtr(*thePtr); |
*thePtr = nil; |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-10-14