list_del_init/list_node_init: for multiple list_del() calls.
authorRusty Russell <rusty@rustcorp.com.au>
Wed, 27 Aug 2014 06:27:24 +0000 (15:57 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Wed, 27 Aug 2014 06:56:41 +0000 (16:26 +0930)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ccan/list/list.h
ccan/list/test/run.c

index 4d1d34e327090f8bc568a9ea8cf5e4eb79006fa4..cdd5eeb7e6e8523a85e348c7f775a65ca1185260 100644 (file)
@@ -145,6 +145,18 @@ static inline void list_head_init(struct list_head *h)
        h->n.next = h->n.prev = &h->n;
 }
 
+/**
+ * list_node_init - initialize a list_node
+ * @n: the list_node to link to itself.
+ *
+ * You don't need to use this normally!  But it lets you list_del(@n)
+ * safely.
+ */
+static inline void list_node_init(struct list_node *n)
+{
+       n->next = n->prev = n;
+}
+
 /**
  * list_add - add an entry at the start of a linked list.
  * @h: the list_head to add the node to
@@ -237,7 +249,7 @@ static inline bool list_empty_nodebug(const struct list_head *h)
  * another list, but not deleted again.
  *
  * See also:
- *     list_del_from()
+ *     list_del_from(), list_del_init()
  *
  * Example:
  *     list_del(&child->list);
@@ -255,6 +267,27 @@ static inline void list_del_(struct list_node *n, const char* abortstr)
 #endif
 }
 
+/**
+ * list_del_init - delete a node, and reset it so it can be deleted again.
+ * @n: the list_node to be deleted.
+ *
+ * list_del(@n) or list_del_init() again after this will be safe,
+ * which can be useful in some cases.
+ *
+ * See also:
+ *     list_del_from(), list_del()
+ *
+ * Example:
+ *     list_del_init(&child->list);
+ *     parent->num_children--;
+ */
+#define list_del_init(n) list_del_init_(n, LIST_LOC)
+static inline void list_del_init_(struct list_node *n, const char *abortstr)
+{
+       list_del_(n, abortstr);
+       list_node_init(n);
+}
+
 /**
  * list_del_from - delete an entry from a known linked list.
  * @h: the list_head the node is in.
index dad308282f7c14aa77bb2ecd54277770618b0ed5..88c3835b4070b63949f002c44a4416bdef9cada0 100644 (file)
@@ -25,7 +25,7 @@ int main(int argc, char *argv[])
        opaque_t *q, *nq;
        struct list_head opaque_list = LIST_HEAD_INIT(opaque_list);
 
-       plan_tests(68);
+       plan_tests(70);
        /* Test LIST_HEAD, LIST_HEAD_INIT, list_empty and check_list */
        ok1(list_empty(&static_list));
        ok1(list_check(&static_list, NULL));
@@ -155,6 +155,19 @@ int main(int argc, char *argv[])
        ok1(i == 3);
        ok1(list_empty(&parent.children));
 
+       /* Test list_node_init: safe to list_del after this. */
+       list_node_init(&c->list);
+       list_del(&c->list);
+
+       /* Test list_del_init */
+       list_add(&parent.children, &c->list);
+       ok1(!list_empty(&parent.children));
+       list_del_init(&c->list);
+       ok1(list_empty(&parent.children));
+       /* We can call this as many times as we like. */
+       list_del_init(&c->list);
+       list_del_init(&c->list);
+
        /* Test list_for_each_off. */
        list_add_tail(&opaque_list,
                      (struct list_node *)create_opaque_blob());