@@ -316,6 +316,17 @@ dlist_init(dlist_head *head)
316316 head -> head .next = head -> head .prev = & head -> head ;
317317}
318318
319+ /*
320+ * Initialize a doubly linked list element.
321+ *
322+ * This is only needed when dlist_node_is_detached() may be needed.
323+ */
324+ static inline void
325+ dlist_node_init (dlist_node * node )
326+ {
327+ node -> next = node -> prev = NULL ;
328+ }
329+
319330/*
320331 * Is the list empty?
321332 *
@@ -397,6 +408,19 @@ dlist_delete(dlist_node *node)
397408 node -> next -> prev = node -> prev ;
398409}
399410
411+ /*
412+ * Like dlist_delete(), but also sets next/prev to NULL to signal not being in
413+ * a list.
414+ */
415+ static inline void
416+ dlist_delete_thoroughly (dlist_node * node )
417+ {
418+ node -> prev -> next = node -> next ;
419+ node -> next -> prev = node -> prev ;
420+ node -> next = NULL ;
421+ node -> prev = NULL ;
422+ }
423+
400424/*
401425 * Same as dlist_delete, but performs checks in ILIST_DEBUG builds to ensure
402426 * that 'node' belongs to 'head'.
@@ -408,6 +432,17 @@ dlist_delete_from(dlist_head *head, dlist_node *node)
408432 dlist_delete (node );
409433}
410434
435+ /*
436+ * Like dlist_delete_from, but also sets next/prev to NULL to signal not
437+ * being in a list.
438+ */
439+ static inline void
440+ dlist_delete_from_thoroughly (dlist_head * head , dlist_node * node )
441+ {
442+ dlist_member_check (head , node );
443+ dlist_delete_thoroughly (node );
444+ }
445+
411446/*
412447 * Remove and return the first node from a list (there must be one).
413448 */
@@ -480,6 +515,21 @@ dlist_has_prev(const dlist_head *head, const dlist_node *node)
480515 return node -> prev != & head -> head ;
481516}
482517
518+ /*
519+ * Check if node is detached. A node is only detached if it either has been
520+ * initialized with dlist_init_node(), or deleted with
521+ * dlist_delete_thoroughly() / dlist_delete_from_thoroughly() /
522+ * dclist_delete_from_thoroughly().
523+ */
524+ static inline bool
525+ dlist_node_is_detached (const dlist_node * node )
526+ {
527+ Assert ((node -> next == NULL && node -> prev == NULL ) ||
528+ (node -> next != NULL && node -> prev != NULL ));
529+
530+ return node -> next == NULL ;
531+ }
532+
483533/*
484534 * Return the next node in the list (there must be one).
485535 */
@@ -718,6 +768,19 @@ dclist_delete_from(dclist_head *head, dlist_node *node)
718768 head -> count -- ;
719769}
720770
771+ /*
772+ * Like dclist_delete_from(), but also sets next/prev to NULL to signal not
773+ * being in a list.
774+ */
775+ static inline void
776+ dclist_delete_from_thoroughly (dclist_head * head , dlist_node * node )
777+ {
778+ Assert (head -> count > 0 );
779+
780+ dlist_delete_from_thoroughly (& head -> dlist , node );
781+ head -> count -- ;
782+ }
783+
721784/*
722785 * dclist_pop_head_node
723786 * Remove and return the first node from a list (there must be one).
0 commit comments