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
/* |
File: MemoryHandler.c |
Contains: xxx put contents here xxx |
Version: xxx put version here xxx |
Copyright: © 1999 by Apple Computer, Inc., all rights reserved. |
File Ownership: |
DRI: xxx put dri here xxx |
Other Contact: xxx put other contact here xxx |
Technology: xxx put technology here xxx |
Writers: |
(BWS) Brent Schorsch |
Change History (most recent first): |
<SP1> 7/1/99 BWS first checked in |
*/ |
/* |
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 <Dialogs.h> |
#include <Resources.h> |
#include <Windows.h> |
#include <string.h> |
#include "MemoryHandler.h" |
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ Private Definitions |
#define kBlockTag "TBLK" |
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ Private Types |
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ Private Variables |
static UInt32 gAllocatedRam = 0U; |
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ 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(WindowPtr *theWindow) |
{ |
if (nil == theWindow) |
return; |
if (nil == *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); |
gAllocatedRam += size; |
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); |
gAllocatedRam += size; |
return (thePtr + 12); |
} |
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ DisposeTaggedPtr |
void |
DisposeTaggedPtr(Ptr thePtr) |
{ |
Ptr ptr2; |
Size size; |
if (! thePtr) |
return; |
ptr2 = thePtr - 12; |
size = GetPtrSize(ptr2); |
//¥ Confirm that this is one of our tagged blocks first |
if (strncmp(kBlockTag, ptr2, 4) == 0) |
{ |
DisposePtr(ptr2); |
gAllocatedRam -= size; |
} |
else |
{ |
DisposePtr(thePtr); |
} |
} |
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ DisposeTaggedPtrZ |
void |
DisposeTaggedPtrZ(Ptr *thePtr) |
{ |
Ptr ptr2; |
Size size; |
if (! *thePtr) |
return; |
ptr2 = (*thePtr) - 12; |
size = GetPtrSize(ptr2); |
if (strncmp(kBlockTag, ptr2, 4) == 0) |
{ |
DisposePtr(ptr2); |
gAllocatedRam -= size; |
} |
else |
{ |
DisposePtr(*thePtr); |
} |
*thePtr = nil; |
} |
//¥ ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ GetAllocatedRam |
UInt32 |
GetAllocatedRam(void) |
{ |
return (gAllocatedRam); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-10-14