summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndres Freund2023-01-18 19:41:14 +0000
committerAndres Freund2023-01-18 19:41:14 +0000
commit51384cc40c4a72c81d2475089ab8a1cf98ea56ff (patch)
treea83eabb86284f3d5d5758b710e8e859cdae5880b
parent2b16208753770318085b1201a6d101cab2697132 (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.h63
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).
*/