diff options
author | Andres Freund | 2023-01-18 19:41:14 +0000 |
---|---|---|
committer | Andres Freund | 2023-01-18 19:41:14 +0000 |
commit | 51384cc40c4a72c81d2475089ab8a1cf98ea56ff (patch) | |
tree | a83eabb86284f3d5d5758b710e8e859cdae5880b | |
parent | 2b16208753770318085b1201a6d101cab2697132 (diff) |
Add detached node functions to ilist
These allow to test whether an element is in a list by checking whether
prev/next are NULL. Needed to replace SHMQueueIsDetached() when converting
from SHM_QUEUE to ilist.h style lists.
Reviewed-by: Thomas Munro <[email protected]>
Discussion: https://postgr.es/m/[email protected]
Discussion: https://postgr.es/m/[email protected]
-rw-r--r-- | src/include/lib/ilist.h | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/src/include/lib/ilist.h b/src/include/lib/ilist.h index d33048f3b38..e03aa1c683b 100644 --- a/src/include/lib/ilist.h +++ b/src/include/lib/ilist.h @@ -317,6 +317,17 @@ dlist_init(dlist_head *head) } /* + * Initialize a doubly linked list element. + * + * This is only needed when dlist_node_is_detached() may be needed. + */ +static inline void +dlist_node_init(dlist_node *node) +{ + node->next = node->prev = NULL; +} + +/* * Is the list empty? * * An empty list has either its first 'next' pointer set to NULL, or to itself. @@ -398,6 +409,19 @@ dlist_delete(dlist_node *node) } /* + * Like dlist_delete(), but also sets next/prev to NULL to signal not being in + * a list. + */ +static inline void +dlist_delete_thoroughly(dlist_node *node) +{ + node->prev->next = node->next; + node->next->prev = node->prev; + node->next = NULL; + node->prev = NULL; +} + +/* * Same as dlist_delete, but performs checks in ILIST_DEBUG builds to ensure * that 'node' belongs to 'head'. */ @@ -409,6 +433,17 @@ dlist_delete_from(dlist_head *head, dlist_node *node) } /* + * Like dlist_delete_from, but also sets next/prev to NULL to signal not + * being in a list. + */ +static inline void +dlist_delete_from_thoroughly(dlist_head *head, dlist_node *node) +{ + dlist_member_check(head, node); + dlist_delete_thoroughly(node); +} + +/* * Remove and return the first node from a list (there must be one). */ static inline dlist_node * @@ -481,6 +516,21 @@ dlist_has_prev(const dlist_head *head, const dlist_node *node) } /* + * Check if node is detached. A node is only detached if it either has been + * initialized with dlist_init_node(), or deleted with + * dlist_delete_thoroughly() / dlist_delete_from_thoroughly() / + * dclist_delete_from_thoroughly(). + */ +static inline bool +dlist_node_is_detached(const dlist_node *node) +{ + Assert((node->next == NULL && node->prev == NULL) || + (node->next != NULL && node->prev != NULL)); + + return node->next == NULL; +} + +/* * Return the next node in the list (there must be one). */ static inline dlist_node * @@ -719,6 +769,19 @@ dclist_delete_from(dclist_head *head, dlist_node *node) } /* + * Like dclist_delete_from(), but also sets next/prev to NULL to signal not + * being in a list. + */ +static inline void +dclist_delete_from_thoroughly(dclist_head *head, dlist_node *node) +{ + Assert(head->count > 0); + + dlist_delete_from_thoroughly(&head->dlist, node); + head->count--; +} + +/* * dclist_pop_head_node * Remove and return the first node from a list (there must be one). */ |