MINOR: list: add new macro MT_LIST_BEHEAD

This macro atomically cuts the head of a list and returns the list
of elements as a detached list, meaning that they're all linked
together without any head. If the list was empty, NULL is returned.
This commit is contained in:
Willy Tarreau 2019-10-04 18:02:40 +02:00 committed by Olivier Houchard
parent c32a0e522f
commit d7f2bbcbe3
1 changed files with 41 additions and 0 deletions

View File

@ -300,6 +300,47 @@ struct cond_wordlist {
(_ret); \
})
/*
* Detach a list from its head. A pointer to the first element is returned
* and the list is closed. If the list was empty, NULL is returned. This may
* exclusively be used with lists modified by MT_LIST_ADD/MT_LIST_ADDQ. This
* is incompatible with MT_LIST_DEL run concurrently.
*/
#define MT_LIST_BEHEAD(lh) ({ \
struct mt_list *_n; \
struct mt_list *_p; \
while (1) { \
_p = _HA_ATOMIC_XCHG(&(lh)->prev, MT_LIST_BUSY); \
if (_p == MT_LIST_BUSY) \
continue; \
if (_p == (lh)) { \
(lh)->prev = _p; \
_n = NULL; \
break; \
} \
_n = _HA_ATOMIC_XCHG(&(lh)->next, MT_LIST_BUSY); \
if (_n == MT_LIST_BUSY) { \
(lh)->prev = _p; \
__ha_barrier_store(); \
continue; \
} \
if (_n == (lh)) { \
(lh)->next = _n; \
(lh)->prev = _p; \
_n = NULL; \
break; \
} \
(lh)->next = (lh); \
(lh)->prev = (lh); \
_n->prev = _p; \
_p->next = _n; \
__ha_barrier_store(); \
break; \
} \
(_n); \
})
/* Remove an item from a list.
* Returns 1 if we removed the item, 0 otherwise (because it was in no list).
*/