Introduce REMOVE_NEXT() macro's for SLIST and STAILQ.
Even though single linked lists allow items to be removed at constant time (when the previous element is known), the queue macro's don't allow this. Implement new REMOVE_NEXT() macro's. Because the REMOVE() macro's also contain the same code, make it call REMOVE_NEXT(). The OpenBSD version of SLIST_REMOVE_NEXT() needs a reference to the list head, even though it is unused. We'd better mimic this. The STAILQ version also needs a reference to the list. This means the prototypes of both macro's are the same. Approved by: philip (mentor) PR: kern/121117
This commit is contained in:
parent
55eff7704c
commit
e2fd72de44
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=179210
@ -63,6 +63,7 @@ MLINKS+= queue.3 LIST_EMPTY.3 \
|
||||
queue.3 SLIST_NEXT.3 \
|
||||
queue.3 SLIST_REMOVE.3 \
|
||||
queue.3 SLIST_REMOVE_HEAD.3 \
|
||||
queue.3 SLIST_REMOVE_NEXT.3 \
|
||||
queue.3 STAILQ_CONCAT.3 \
|
||||
queue.3 STAILQ_EMPTY.3 \
|
||||
queue.3 STAILQ_ENTRY.3 \
|
||||
@ -79,6 +80,7 @@ MLINKS+= queue.3 LIST_EMPTY.3 \
|
||||
queue.3 STAILQ_NEXT.3 \
|
||||
queue.3 STAILQ_REMOVE.3 \
|
||||
queue.3 STAILQ_REMOVE_HEAD.3 \
|
||||
queue.3 STAILQ_REMOVE_NEXT.3 \
|
||||
queue.3 TAILQ_CONCAT.3 \
|
||||
queue.3 TAILQ_EMPTY.3 \
|
||||
queue.3 TAILQ_ENTRY.3 \
|
||||
|
@ -48,6 +48,7 @@
|
||||
.Nm SLIST_INSERT_HEAD ,
|
||||
.Nm SLIST_NEXT ,
|
||||
.Nm SLIST_REMOVE_HEAD ,
|
||||
.Nm SLIST_REMOVE_NEXT ,
|
||||
.Nm SLIST_REMOVE ,
|
||||
.Nm STAILQ_CONCAT ,
|
||||
.Nm STAILQ_EMPTY ,
|
||||
@ -64,6 +65,7 @@
|
||||
.Nm STAILQ_LAST ,
|
||||
.Nm STAILQ_NEXT ,
|
||||
.Nm STAILQ_REMOVE_HEAD ,
|
||||
.Nm STAILQ_REMOVE_NEXT ,
|
||||
.Nm STAILQ_REMOVE ,
|
||||
.Nm LIST_EMPTY ,
|
||||
.Nm LIST_ENTRY ,
|
||||
@ -114,6 +116,7 @@ lists and tail queues
|
||||
.Fn SLIST_INSERT_HEAD "SLIST_HEAD *head" "TYPE *elm" "SLIST_ENTRY NAME"
|
||||
.Fn SLIST_NEXT "TYPE *elm" "SLIST_ENTRY NAME"
|
||||
.Fn SLIST_REMOVE_HEAD "SLIST_HEAD *head" "SLIST_ENTRY NAME"
|
||||
.Fn SLIST_REMOVE_NEXT "SLIST_HEAD *head" "TYPE *elm" "SLIST_ENTRY NAME"
|
||||
.Fn SLIST_REMOVE "SLIST_HEAD *head" "TYPE *elm" "TYPE" "SLIST_ENTRY NAME"
|
||||
.\"
|
||||
.Fn STAILQ_CONCAT "STAILQ_HEAD *head1" "STAILQ_HEAD *head2"
|
||||
@ -131,6 +134,7 @@ lists and tail queues
|
||||
.Fn STAILQ_LAST "STAILQ_HEAD *head" "TYPE" "STAILQ_ENTRY NAME"
|
||||
.Fn STAILQ_NEXT "TYPE *elm" "STAILQ_ENTRY NAME"
|
||||
.Fn STAILQ_REMOVE_HEAD "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
|
||||
.Fn STAILQ_REMOVE_NEXT "STAILQ_HEAD *head" "TYPE *elm" "STAILQ_ENTRY NAME"
|
||||
.Fn STAILQ_REMOVE "STAILQ_HEAD *head" "TYPE *elm" "TYPE" "STAILQ_ENTRY NAME"
|
||||
.\"
|
||||
.Fn LIST_EMPTY "LIST_HEAD *head"
|
||||
@ -387,6 +391,14 @@ this macro instead of the generic
|
||||
macro.
|
||||
.Pp
|
||||
The macro
|
||||
.Nm SLIST_REMOVE_NEXT
|
||||
removes the element after
|
||||
.Fa elm
|
||||
from the list. Unlike
|
||||
.Fa SLIST_REMOVE ,
|
||||
this macro does not traverse the entire list.
|
||||
.Pp
|
||||
The macro
|
||||
.Nm SLIST_REMOVE
|
||||
removes the element
|
||||
.Fa elm
|
||||
@ -561,6 +573,14 @@ use this macro explicitly rather than the generic
|
||||
macro.
|
||||
.Pp
|
||||
The macro
|
||||
.Nm STAILQ_REMOVE_NEXT
|
||||
removes the element after
|
||||
.Fa elm
|
||||
from the tail queue. Unlike
|
||||
.Fa STAILQ_REMOVE ,
|
||||
this macro does not traverse the entire tail queue.
|
||||
.Pp
|
||||
The macro
|
||||
.Nm STAILQ_REMOVE
|
||||
removes the element
|
||||
.Fa elm
|
||||
|
@ -97,6 +97,7 @@
|
||||
* _INSERT_TAIL - - + +
|
||||
* _CONCAT - - + +
|
||||
* _REMOVE_HEAD + - + -
|
||||
* _REMOVE_NEXT + - + -
|
||||
* _REMOVE + + + +
|
||||
*
|
||||
*/
|
||||
@ -195,12 +196,16 @@ struct { \
|
||||
struct type *curelm = SLIST_FIRST((head)); \
|
||||
while (SLIST_NEXT(curelm, field) != (elm)) \
|
||||
curelm = SLIST_NEXT(curelm, field); \
|
||||
SLIST_NEXT(curelm, field) = \
|
||||
SLIST_NEXT(SLIST_NEXT(curelm, field), field); \
|
||||
SLIST_REMOVE_NEXT(head, curelm, field); \
|
||||
} \
|
||||
TRASHIT((elm)->field.sle_next); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_REMOVE_NEXT(head, elm, field) do { \
|
||||
SLIST_NEXT(elm, field) = \
|
||||
SLIST_NEXT(SLIST_NEXT(elm, field), field); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_REMOVE_HEAD(head, field) do { \
|
||||
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
|
||||
} while (0)
|
||||
@ -287,9 +292,7 @@ struct { \
|
||||
struct type *curelm = STAILQ_FIRST((head)); \
|
||||
while (STAILQ_NEXT(curelm, field) != (elm)) \
|
||||
curelm = STAILQ_NEXT(curelm, field); \
|
||||
if ((STAILQ_NEXT(curelm, field) = \
|
||||
STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
|
||||
(head)->stqh_last = &STAILQ_NEXT((curelm), field);\
|
||||
STAILQ_REMOVE_NEXT(head, curelm, field); \
|
||||
} \
|
||||
TRASHIT((elm)->field.stqe_next); \
|
||||
} while (0)
|
||||
@ -300,6 +303,12 @@ struct { \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_REMOVE_NEXT(head, elm, field) do { \
|
||||
if ((STAILQ_NEXT(elm, field) = \
|
||||
STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* List declarations.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user