Commit 3d74240c authored by Eric Wong's avatar Eric Wong Committed by Rusty Russell

list: list_swap to exchange elements

This allows deleting and re-inserting an element in place
of the deleted element without branching.
Signed-off-by: default avatarEric Wong <normalperson@yhbt.net>
Reviewed-by: default avatarDavid Gibson <david@gibson.dropbear.id.au>
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent e4046df7
......@@ -368,6 +368,39 @@ static inline void list_del_from(struct list_head *h, struct list_node *n)
list_del(n);
}
/**
* list_swap - swap out an entry from an (unknown) linked list for a new one.
* @o: the list_node to replace from the list.
* @n: the list_node to insert in place of the old one.
*
* Note that this leaves @o in an undefined state; it can be added to
* another list, but not deleted/swapped again.
*
* See also:
* list_del()
*
* Example:
* struct child x1, x2;
* LIST_HEAD(xh);
*
* list_add(&xh, &x1.list);
* list_swap(&x1.list, &x2.list);
*/
#define list_swap(o, n) list_swap_(o, n, LIST_LOC)
static inline void list_swap_(struct list_node *o,
struct list_node *n,
const char* abortstr)
{
(void)list_debug_node(o, abortstr);
*n = *o;
n->next->prev = n;
n->prev->next = n;
#ifdef CCAN_LIST_DEBUG
/* Catch use-after-del. */
o->next = o->prev = NULL;
#endif
}
/**
* list_entry - convert a list_node back into the structure containing it.
* @n: the list_node
......
......@@ -19,13 +19,13 @@ static LIST_HEAD(static_list);
int main(int argc, char *argv[])
{
struct parent parent;
struct child c1, c2, c3, *c, *n;
struct child c1, c2, c3, x1, *c, *n;
unsigned int i;
struct list_head list = LIST_HEAD_INIT(list);
opaque_t *q, *nq;
struct list_head opaque_list = LIST_HEAD_INIT(opaque_list);
plan_tests(79);
plan_tests(84);
/* Test LIST_HEAD, LIST_HEAD_INIT, list_empty and check_list */
ok1(list_empty(&static_list));
ok1(list_check(&static_list, NULL));
......@@ -253,5 +253,24 @@ int main(int argc, char *argv[])
}
ok1(i == 3);
/* test list_swap */
list_swap(&c3.list, &x1.list);
ok1(list_check(&parent.children, "list_swap"));
i = 0;
list_for_each(&parent.children, c, list) {
switch (i++) {
case 0:
ok1(c == &c1);
break;
case 1:
ok1(c == &x1);
break;
case 2:
ok1(c == &c2);
break;
}
}
ok1(i == 3);
return exit_status();
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment