Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add zlist_freefn

  • Loading branch information...
commit dc47c33b9aee8f07a6b44b815e546582b1b5f7e9 1 parent 52225f2
@HughPowell HughPowell authored
Showing with 48 additions and 1 deletion.
  1. +8 −0 include/zlist.h
  2. +40 −1 src/zlist.c
View
8 include/zlist.h
@@ -37,6 +37,9 @@ typedef struct _zlist_t zlist_t;
// Comparison function for zlist_sort method
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
CZMQ_EXPORT zlist_t *
zlist_new (void);
@@ -81,6 +84,11 @@ CZMQ_EXPORT void *
CZMQ_EXPORT void
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
// duplicate all items, which must be strings. Otherwise, the list will hold
// pointers back to the items in the original list.
View
41 src/zlist.c
@@ -41,6 +41,7 @@
typedef struct _node_t {
struct _node_t *next;
void *item;
+ zlist_free_fn *free_fn;
} node_t;
@@ -79,6 +80,9 @@ zlist_destroy (zlist_t **self_p)
node_t *node = (*self_p)->head;
while (node) {
node_t *next = node->next;
+ if (node->free_fn)
+ (node->free_fn) (node->item);
+ else
if (self->autofree)
free (node->item);
free (node);
@@ -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
@@ -457,10 +490,16 @@ zlist_test (int verbose)
assert (item == cheese);
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
zlist_destroy (&list);
zlist_destroy (&list);
- zlist_destroy (&sub_list);
assert (list == NULL);
// @end
Please sign in to comment.
Something went wrong with that request. Please try again.