12. Memory Collections

Memory-allocated things are managed in a data type known as a collection. Data allocated in a collection can be then used on things like targets, ramp trees, phrases, and extra things needed by behaviors.

12.1. Struct Declarations

<<typedefs>>=
typedef struct gest_collection gest_collection;

A collection is a linked list of generic pointers.

<<struct_collection>>=
<<struct_collection_entry>>
struct gest_collection {
    struct gest_entry *tail;
    int nitems;
};

A linked list entry contains a generic pointer and an optional destructor callback that can free any additional memory allocated and bound to the pointer by the user.

<<struct_collection_entry>>=
struct gest_entry {
    void *ptr;
    void (*free)(void *);
    struct gest_entry *prev;
};

12.2. Initialization

The collection is initialized with collection_init.

<<static_funcdefs>>=
static void collection_init(gest_collection *col);
<<funcs>>=
static void collection_init(gest_collection *col)
{
    col->tail = NULL;
    col->nitems = 0;
}

12.3. Allocating Memory

Anytime Gest needs to allocate memory, the gesture system uses an instance of the allocator.

12.3.1. Allocation with Destructor Callback

The core function for memory allocation is collection_alloc_dtor. In addition to providing the size, an a user-defined destructor callback function. Note that the allocated memory here is already being managed, and that this is only used for any additional memory allocated inside of it.

<<static_funcdefs>>=
static void * collection_alloc_dtor(gest_collection *col,
                                    size_t sz,
                                    void (*free)(void*));
<<funcs>>=
static void * collection_alloc_dtor(gest_collection *col,
                                    size_t sz,
                                    void (*free)(void*))
{
    struct gest_entry *ent;

    ent = malloc(sizeof(struct gest_entry));

    ent->ptr = calloc(1, sz);
    ent->free = free;

    ent->prev = col->tail;
    col->tail = ent;
    col->nitems++;

    return ent->ptr;
}

12.3.2. Memory allocation only

Much of the time the destructor is not needed, so a more convenient collection_alloc function is provided.

<<static_funcdefs>>=
static void * collection_alloc(gest_collection *col, size_t sz);

Creates a new entry, allocates a void pointer, appends the entry to the list, then returns the pointer.

<<funcs>>=
static void * collection_alloc(gest_collection *col, size_t sz)
{
    return collection_alloc_dtor(col, sz, NULL);
}

12.3.3. Gesture Allocator Helper functions

The static function gest_alloc is a helper function which mostly exists to make code look cleaner.

<<static_funcdefs>>=
static void * gest_alloc(gest_d *gest, size_t sz);
<<funcs>>=
static void * gest_alloc(gest_d *gest, size_t sz)
{
    return collection_alloc(&gest->col, sz);
}

12.4. Freeing The Collection

All previously allocated memory in Gest can be freed with the function collection_cleanup.

<<static_funcdefs>>=
static void collection_cleanup(gest_collection *col);

Iterate through the linked list and free it all.

Note that the linked list moves backwards from the tail to the head so that the most recently allocated stuff gets freed first. This is done to minimize situations where allocated items are somehow required to exist before being freed.

<<funcs>>=
static void collection_cleanup(gest_collection *col)
{
    int n;
    struct gest_entry *ent, *prev;

    ent = col->tail;

    for (n = 0; n < col->nitems; n++) {
        prev = ent->prev;
        if (ent->free != NULL) ent->free(ent->ptr);
        free(ent->ptr);
        free(ent);
        ent = prev;
    }
}



prev | home | next