Skip to content

Commit

Permalink
Add zlist_freefn
Browse files Browse the repository at this point in the history
  • Loading branch information
HughPowell committed Mar 5, 2014
1 parent 52225f2 commit dc47c33
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 1 deletion.
8 changes: 8 additions & 0 deletions include/zlist.h
Expand Up @@ -37,6 +37,9 @@ typedef struct _zlist_t zlist_t;
// Comparison function for zlist_sort method // Comparison function for zlist_sort method
typedef bool (zlist_compare_fn) (void *item1, void *item2); typedef bool (zlist_compare_fn) (void *item1, void *item2);


// Callback function for zlist_freefn method
typedef void (zlist_free_fn) (void *data);

// Create a new list container // Create a new list container
CZMQ_EXPORT zlist_t * CZMQ_EXPORT zlist_t *
zlist_new (void); zlist_new (void);
Expand Down Expand Up @@ -81,6 +84,11 @@ CZMQ_EXPORT void *
CZMQ_EXPORT void CZMQ_EXPORT void
zlist_remove (zlist_t *self, void *item); zlist_remove (zlist_t *self, void *item);


// Add an explicit free function to the item including a hint as to
// whether it can be found at the tail
CZMQ_EXPORT void *
zlist_freefn (zlist_t *self, void *item, zlist_free_fn *fn, bool at_tail);

// Make a copy of list. If the list has autofree set, the copied list will // Make a copy of list. If the list has autofree set, the copied list will
// duplicate all items, which must be strings. Otherwise, the list will hold // duplicate all items, which must be strings. Otherwise, the list will hold
// pointers back to the items in the original list. // pointers back to the items in the original list.
Expand Down
41 changes: 40 additions & 1 deletion src/zlist.c
Expand Up @@ -41,6 +41,7 @@
typedef struct _node_t { typedef struct _node_t {
struct _node_t *next; struct _node_t *next;
void *item; void *item;
zlist_free_fn *free_fn;
} node_t; } node_t;




Expand Down Expand Up @@ -79,6 +80,9 @@ zlist_destroy (zlist_t **self_p)
node_t *node = (*self_p)->head; node_t *node = (*self_p)->head;
while (node) { while (node) {
node_t *next = node->next; node_t *next = node->next;
if (node->free_fn)
(node->free_fn) (node->item);
else
if (self->autofree) if (self->autofree)
free (node->item); free (node->item);
free (node); free (node);
Expand Down Expand Up @@ -269,6 +273,35 @@ zlist_remove (zlist_t *self, void *item)
} }
} }


// --------------------------------------------------------------------------
// Set a free function for the specified list item. When the item is
// destroyed, the free function, if any, is called on that item.
// Use this when list items are dynamically allocated, to ensure that
// you don't have memory leaks. You can pass 'free' or NULL as a free_fn.
// Returns the item, or NULL if there is no such item.

void *
zlist_freefn (zlist_t *self, void *item, zlist_free_fn *fn, bool at_tail)
{
node_t *node = self->head;
if (at_tail)
node = self->tail;
while (node) {
if (node->item == item) {
node->free_fn = fn;
return item;
}
node = node->next;
}
return NULL;
}

static void
s_zlist_free (void *data)
{
zlist_t *self = (zlist_t *)data;
zlist_destroy (&self);
}


// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// Make a copy of list. If the list has autofree set, the copied list will // Make a copy of list. If the list has autofree set, the copied list will
Expand Down Expand Up @@ -457,10 +490,16 @@ zlist_test (int verbose)
assert (item == cheese); assert (item == cheese);
assert (zlist_size (list) == 0); assert (zlist_size (list) == 0);


assert (zlist_size (sub_list) == 3);
zlist_push (list, sub_list);
zlist_t *sub_list_2 = zlist_dup (sub_list);
zlist_append (list, sub_list_2);
assert (zlist_freefn (list, sub_list, &s_zlist_free, false) == sub_list);
assert (zlist_freefn (list, sub_list_2, &s_zlist_free, true) == sub_list_2);

// Destructor should be safe to call twice // Destructor should be safe to call twice
zlist_destroy (&list); zlist_destroy (&list);
zlist_destroy (&list); zlist_destroy (&list);
zlist_destroy (&sub_list);
assert (list == NULL); assert (list == NULL);
// @end // @end


Expand Down

0 comments on commit dc47c33

Please sign in to comment.