From ec8654d94d3c5c47aa5f82698f7e8048c79765b1 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 27 Aug 2014 15:57:24 +0930 Subject: [PATCH] list_del_init/list_node_init: for multiple list_del() calls. Signed-off-by: Rusty Russell --- ccan/list/list.h | 35 ++++++++++++++++++++++++++++++++++- ccan/list/test/run.c | 15 ++++++++++++++- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/ccan/list/list.h b/ccan/list/list.h index 4d1d34e3..cdd5eeb7 100644 --- a/ccan/list/list.h +++ b/ccan/list/list.h @@ -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. diff --git a/ccan/list/test/run.c b/ccan/list/test/run.c index dad30828..88c3835b 100644 --- a/ccan/list/test/run.c +++ b/ccan/list/test/run.c @@ -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()); -- 2.39.2