slist_check(head);
}
-#ifdef ILIST_DEBUG
/*
* Verify integrity of a doubly linked list
*/
-void
-dlist_check(dlist_head *head)
+dlist_head*
+dlist_check_force(dlist_head *head)
{
dlist_node *cur;
if (head == NULL)
- elog(ERROR, "doubly linked list head address is NULL");
+ elog(PANIC, "doubly linked list head address is NULL");
if (head->head.next == NULL && head->head.prev == NULL)
- return; /* OK, initialized as zeroes */
+ return head; /* OK, initialized as zeroes */
/* iterate in forward direction */
for (cur = head->head.next; cur != &head->head; cur = cur->next)
cur->prev == NULL ||
cur->prev->next != cur ||
cur->next->prev != cur)
- elog(ERROR, "doubly linked list is corrupted");
+ elog(PANIC, "doubly linked list is corrupted");
}
/* iterate in backward direction */
cur->prev == NULL ||
cur->prev->next != cur ||
cur->next->prev != cur)
- elog(ERROR, "doubly linked list is corrupted");
+ elog(PANIC, "doubly linked list is corrupted");
}
+
+ return head;
}
/*
* Verify integrity of a singly linked list
*/
-void
-slist_check(slist_head *head)
+slist_head *
+slist_check_force(slist_head *head)
{
slist_node *cur;
if (head == NULL)
- elog(ERROR, "singly linked list head address is NULL");
+ elog(PANIC, "singly linked list head address is NULL");
/*
* there isn't much we can test in a singly linked list except that it
*/
for (cur = head->head.next; cur != NULL; cur = cur->next)
;
+
+ return head;
}
-#endif /* ILIST_DEBUG */
+bool
+dlist_is_member(dlist_head *head, dlist_node *node)
+{
+ dlist_iter iter;
+
+ dlist_foreach(iter, head)
+ {
+ if (iter.cur == node)
+ return true;
+ }
+
+ return false;
+}
/* Caution: this is O(n); consider using slist_delete_current() instead */
extern void slist_delete(slist_head *head, slist_node *node);
+extern dlist_head* dlist_check_force(dlist_head *head);
+extern slist_head* slist_check_force(slist_head *head);
+
#ifdef ILIST_DEBUG
-extern void dlist_check(dlist_head *head);
-extern void slist_check(slist_head *head);
+static inline dlist_head* dlist_check(dlist_head *head)
+{
+ return dlist_check_force(head);
+}
+static inline slist_head* slist_check(slist_head *head)
+{
+ return slist_check_force(head);
+}
#else
/*
* These seemingly useless casts to void are here to keep the compiler quiet
* in which functions the only point of passing the list head pointer is to be
* able to run these checks.
*/
-#define dlist_check(head) ((void) (head))
+static inline dlist_head *dlist_check(dlist_head *head)
+{
+ return head;
+}
#define slist_check(head) ((void) (head))
#endif /* ILIST_DEBUG */
return head->head.next == NULL || head->head.next == &(head->head);
}
+/*
+ * Is node member of the list?
+ *
+ * NB: This is O(N)!
+ */
+extern bool dlist_is_member(dlist_head *head, dlist_node *node);
+
/*
* Insert a node at the beginning of the list.
*/
static inline void
dlist_push_head(dlist_head *head, dlist_node *node)
{
+#ifdef ILIST_DEBUG
+ Assert(!dlist_is_member(head, node));
+#endif
+
if (head->head.next == NULL) /* convert NULL header to circular */
dlist_init(head);
static inline void
dlist_push_tail(dlist_head *head, dlist_node *node)
{
+#ifdef ILIST_DEBUG
+ Assert(!dlist_is_member(head, node));
+#endif
+ dlist_check(head);
+
if (head->head.next == NULL) /* convert NULL header to circular */
dlist_init(head);
node->next->prev = node->prev;
}
+/*
+ * Delete 'node' from its list (it must be in one).
+ */
+static inline void
+dlist_delete_from(dlist_head *head, dlist_node *node)
+{
+ dlist_check(head);
+#ifdef ILIST_DEBUG
+ Assert(dlist_is_member(head, node));
+#endif
+ node->prev->next = node->next;
+ node->next->prev = node->prev;
+}
+
/*
* Remove and return the first node from a list (there must be one).
*/
{
dlist_node *node;
+ dlist_check(head);
+
+#ifdef ILIST_DEBUG
Assert(!dlist_is_empty(head));
+#endif
+
node = head->head.next;
dlist_delete(node);
+
+ dlist_check(head);
+
return node;
}
#define dlist_foreach(iter, lhead) \
for (AssertVariableIsOfTypeMacro(iter, dlist_iter), \
AssertVariableIsOfTypeMacro(lhead, dlist_head *), \
- (iter).end = &(lhead)->head, \
+ (iter).end = &dlist_check(lhead)->head, \
(iter).cur = (iter).end->next ? (iter).end->next : (iter).end; \
(iter).cur != (iter).end; \
(iter).cur = (iter).cur->next)
#define dlist_foreach_modify(iter, lhead) \
for (AssertVariableIsOfTypeMacro(iter, dlist_mutable_iter), \
AssertVariableIsOfTypeMacro(lhead, dlist_head *), \
- (iter).end = &(lhead)->head, \
+ (iter).end = &dlist_check(lhead)->head, \
(iter).cur = (iter).end->next ? (iter).end->next : (iter).end, \
(iter).next = (iter).cur->next; \
(iter).cur != (iter).end; \