Example

Here is some commented sample heap-using code employing reference counting:

typedef struct _foo_t {
        /* heres our message structure */
        char    msg[128];
        int     len;
} foo_t;

server_heap_t   *heap;

heap = server_heap_new("messages",
        sizeof(foo_t), 20, 2000,
        SERVER_HEAP_GROW_EXPONENTIALLY);

if(heap == NULL) {
        fprintf(stderr, "Failed to create messages heap");
        return 0;
}

unit = server_heap_unit_allocate(heap, 1);

/* note at this point our unit would have a ref count of 1 */

/* imaginary function that gets a message from something and
 * populates the foo_t instance with it
 */

recv_message(unit);

/* now, we distribute the message, lets say we have a bunch
 * of consumers in a consumers linked list called c_list, each
 * one has a ServerKit queue attached to it.
 *
 * So the consumer type looks like:
 * struct consumer {
 *      struct consumer *next, *previous;
 *      server_queue_t  *queue;
 * }
 */

/* note that if the c_list is modified by other threads it
 * would have to be protected while we walk it. */
for(c = c_list; c != NULL; c = c->next) {
       server_heap_unit_ref(unit);
       server_queue_push(c->queue, unit);
}

/* it's as easy as that, since we increased the reference
 * count for every queue we pushed it on, there is no risk
 * of the unit getting unref'd down to 0 out from under us by
 * any of the consumers, because we had a reference count of 1
 * ever since the unit was allocated.
 *
 * now that we are finished adding references (queueing), we
 * have to do do our unref because we're finished with it too.
 */

server_heap_unit_unref(unit);

/* now the unit is potentially free, so we can't touch it
 * again in this context!  I say potentially because wether it
 * really is free'd by now is dependant on the consumers, if
 * they have scheduled to run in the mean time and finished
 * their work, decrementing the ref count... it's possible but
 * it's also possible that they have yet to run and the ref
 * count is positive still, regardless, we don't know this
 * in this context and we must forget the unit existed.
 *
 * We would probably just loop back to the top here and get
 * a new unit, receive a new message etc.  Hopefully the next
 * unit is a recycled one, and the heap didnt have to grow,
 * that would be very nice.
 */



2007-12-06