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);
}