@@ -316,6 +316,17 @@ dlist_init(dlist_head *head)
316
316
head -> head .next = head -> head .prev = & head -> head ;
317
317
}
318
318
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
+
319
330
/*
320
331
* Is the list empty?
321
332
*
@@ -397,6 +408,19 @@ dlist_delete(dlist_node *node)
397
408
node -> next -> prev = node -> prev ;
398
409
}
399
410
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
+
400
424
/*
401
425
* Same as dlist_delete, but performs checks in ILIST_DEBUG builds to ensure
402
426
* that 'node' belongs to 'head'.
@@ -408,6 +432,17 @@ dlist_delete_from(dlist_head *head, dlist_node *node)
408
432
dlist_delete (node );
409
433
}
410
434
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
+
411
446
/*
412
447
* Remove and return the first node from a list (there must be one).
413
448
*/
@@ -480,6 +515,21 @@ dlist_has_prev(const dlist_head *head, const dlist_node *node)
480
515
return node -> prev != & head -> head ;
481
516
}
482
517
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
+
483
533
/*
484
534
* Return the next node in the list (there must be one).
485
535
*/
@@ -718,6 +768,19 @@ dclist_delete_from(dclist_head *head, dlist_node *node)
718
768
head -> count -- ;
719
769
}
720
770
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
+
721
784
/*
722
785
* dclist_pop_head_node
723
786
* Remove and return the first node from a list (there must be one).
0 commit comments