Oscar Papel's Web Log

Thursday, November 11, 2004

Memory management in Damocles

Memory management is a tricky subject when dealing with native code. ObjC uses reference counting similar to COM's. Managed code uses a garbage collector. In order to be flexible, Damocles has to be able to "wrap" buffers it didn't allocate and support multiple pointer references. This way, it can support multiple views/subviews of the same data. as well as be "held" by more than one object.

I came up with a reference counting mechanism that does both and simplifies memory management for non-trivial cases.

Each "object" is really a c-style structure that has fields, a pointer to it's data payload and a reference count.

example:

typedef struct {
void *pData;
S32 RefCount;
U32 width;
U32 height;
} Image;


S32 and U32 have been defined in os.h as a signed and unsigned (respectively) 32bit integer. os.h shields Damocles from platform differences in C's integer definition making the code more portable. Also, void * will be a 32bit value on 32bit systems and a 64bit value on 64bit systems.

When an Image struct is allocated, you have 2 options. You can pass a pointer to an existing buffer in which case RefCount will be set to -1. Calling AddRefCount on Image will cause RefCount to go to -2. Calling Free on Image causes RefCount to go back to -1. Calling Free again causes Image to throw away the pointer and deallocate the structure.

If you DON'T pass a pointer to an existing buffer, one is allocated for you and RefCount=1; Calling AddRefCount on Image will cause RefCount to go to 2. Calling Free on Image causes RefCount to go back to 1. Calling Free again causes the pointer to be freed and then the structure to be freed.

In this way, you can have multiple references to a struct that holds data that may or may not be wrapped. You can Free the Image in an arbitrary order to the order they were Allocated or AddRef'd and the last one will properly give up or deallocate the buffer properly.

This was critical to correct operation where you need to return a linked list of objects. This way, the list holds it's own reference. you can select an object from the list, AddRef it, destroy the list, use the object then Free it and everything works the way it should.

0 Comments:

Post a Comment

<< Home