1 .\" $NetBSD: gcq.3,v 1.2 2009/05/27 17:47:46 snj Exp $
3 .\" Not (c) 2007 Matthew Orgass
4 .\" This file is public domain, meaning anyone can make any use of part or all
5 .\" of this file including copying into other works without credit. Any use,
6 .\" modified or not, is solely the responsibility of the user. If this file
7 .\" is part of a collection then use in the collection is governed by the
8 .\" terms of the collection.
25 .Nm gcq_insert_after ,
26 .Nm gcq_insert_before ,
42 .Nm GCQ_DEQUEUED_FIRST ,
43 .Nm GCQ_DEQUEUED_LAST ,
44 .Nm GCQ_DEQUEUED_NEXT ,
45 .Nm GCQ_DEQUEUED_PREV ,
46 .Nm GCQ_GOT_FIRST_TYPED ,
47 .Nm GCQ_GOT_LAST_TYPED ,
48 .Nm GCQ_GOT_NEXT_TYPED ,
49 .Nm GCQ_GOT_PREV_TYPED ,
50 .Nm GCQ_DEQUEUED_FIRST_TYPED ,
51 .Nm GCQ_DEQUEUED_LAST_TYPED ,
52 .Nm GCQ_DEQUEUED_NEXT_TYPED ,
53 .Nm GCQ_DEQUEUED_PREV_TYPED ,
54 .Nm GCQ_GOT_FIRST_COND ,
55 .Nm GCQ_GOT_LAST_COND ,
56 .Nm GCQ_GOT_NEXT_COND ,
57 .Nm GCQ_GOT_PREV_COND ,
58 .Nm GCQ_DEQUEUED_FIRST_COND ,
59 .Nm GCQ_DEQUEUED_LAST_COND ,
60 .Nm GCQ_DEQUEUED_NEXT_COND ,
61 .Nm GCQ_DEQUEUED_PREV_COND ,
62 .Nm GCQ_GOT_FIRST_COND_TYPED ,
63 .Nm GCQ_GOT_LAST_COND_TYPED ,
64 .Nm GCQ_GOT_NEXT_COND_TYPED ,
65 .Nm GCQ_GOT_PREV_COND_TYPED ,
66 .Nm GCQ_DEQUEUED_FIRST_COND_TYPED ,
67 .Nm GCQ_DEQUEUED_LAST_COND_TYPED ,
68 .Nm GCQ_DEQUEUED_NEXT_COND_TYPED ,
69 .Nm GCQ_DEQUEUED_PREV_COND_TYPED ,
72 .Nm GCQ_FOREACH_NVAR ,
73 .Nm GCQ_FOREACH_NVAR_REV ,
75 .Nm GCQ_FOREACH_RO_REV ,
76 .Nm GCQ_FOREACH_DEQUEUED ,
77 .Nm GCQ_FOREACH_DEQUEUED_REV ,
78 .Nm GCQ_FOREACH_TYPED ,
79 .Nm GCQ_FOREACH_REV_TYPED ,
80 .Nm GCQ_FOREACH_NVAR_TYPED ,
81 .Nm GCQ_FOREACH_NVAR_REV_TYPED ,
82 .Nm GCQ_FOREACH_RO_TYPED ,
83 .Nm GCQ_FOREACH_RO_REV_TYPED ,
84 .Nm GCQ_FOREACH_DEQUEUED_TYPED ,
85 .Nm GCQ_FOREACH_DEQUEUED_REV_TYPED ,
89 .Nm GCQ_FIND_REV_TYPED
90 .Nd "Generic Circular Queues"
98 .Fn GCQ_INIT_HEAD name
100 .Ft static inline void
101 .Fn gcq_init "struct gcq *q"
102 .Ft static inline void
103 .Fn gcq_init_head "struct gcq_head *head"
104 .Ft static inline struct gcq *
105 .Fn gcq_q "struct gcq_head *head"
106 .Ft static inline struct gcq *
107 .Fn gcq_hq "struct gcq_head *head"
108 .Ft static inline struct gcq_head *
109 .Fn gcq_head "struct gcq *q"
110 .Ft static inline struct gcq *
111 .Fn gcq_remove "struct gcq *q"
112 .Ft static inline bool
113 .Fn gcq_onlist "struct gcq *q"
114 .Ft static inline bool
115 .Fn gcq_empty "struct gcq_head *head"
116 .Ft static inline bool
117 .Fn gcq_linked "struct gcq *prev" "struct gcq *next"
118 .Ft static inline void
119 .Fn gcq_insert_after "struct gcq *on" "struct gcq *off"
120 .Ft static inline void
121 .Fn gcq_insert_before "struct gcq *on" "struct gcq *off"
122 .Ft static inline void
123 .Fn gcq_insert_head "struct gcq_head *head" "struct gcq *q"
124 .Ft static inline void
125 .Fn gcq_insert_tail "struct gcq_head *head" "struct gcq *q"
126 .Ft static inline void
127 .Fn gcq_tie "struct gcq *dst" "struct gcq *src"
128 .Ft static inline void
129 .Fn gcq_tie_after "struct gcq *dst" "struct gcq *src"
130 .Ft static inline void
131 .Fn gcq_tie_before "struct gcq *dst" "struct gcq *src"
132 .Ft static inline void
133 .Fn gcq_merge "struct gcq *dst" "struct gcq *src"
134 .Ft static inline void
135 .Fn gcq_merge_tail "struct gcq_head *dst" "struct gcq_head *src"
136 .Ft static inline void
137 .Fn gcq_merge_head "struct gcq_head *dst" "struct gcq_head *src"
138 .Ft static inline void
139 .Fn gcq_clear "struct gcq *q"
140 .Ft static inline void
141 .Fn gcq_remove_all "struct gcq_head *head"
144 .Fn GCQ_ITEM q type name
146 .Fn GCQ_GOT_FIRST var head
148 .Fn GCQ_GOT_LAST var head
150 .Fn GCQ_GOT_NEXT var current head start
152 .Fn GCQ_GOT_PREV var current head start
154 .Fn GCQ_DEQUEUED_FIRST var head
156 .Fn GCQ_DEQUEUED_LAST var head
158 .Fn GCQ_DEQUEUED_NEXT var current head start
160 .Fn GCQ_DEQUEUED_PREV var current head start
162 .Fn GCQ_GOT_FIRST_TYPED tvar head type name
164 .Fn GCQ_GOT_LAST_TYPED tvar head type name
166 .Fn GCQ_GOT_NEXT_TYPED tvar current head start type name
168 .Fn GCQ_GOT_PREV_TYPED tvar current head start type name
170 .Fn GCQ_DEQUEUED_FIRST_TYPED tvar head type name
172 .Fn GCQ_DEQUEUED_LAST_TYPED tvar head type name
174 .Fn GCQ_DEQUEUED_NEXT_TYPED tvar current head start type name
176 .Fn GCQ_DEQUEUED_PREV_TYPED tvar current head start type name
178 .Fn GCQ_GOT_FIRST_COND var head cond
180 .Fn GCQ_GOT_LAST_COND var head cond
182 .Fn GCQ_GOT_NEXT_COND var current head start cond
184 .Fn GCQ_GOT_PREV_COND var current head start cond
186 .Fn GCQ_DEQUEUED_FIRST_COND var head cond
188 .Fn GCQ_DEQUEUED_LAST_COND var head cond
190 .Fn GCQ_DEQUEUED_NEXT_COND var current head start cond
192 .Fn GCQ_DEQUEUED_PREV_COND var current head start cond
194 .Fn GCQ_GOT_FIRST_COND_TYPED tvar head type name cond
196 .Fn GCQ_GOT_LAST_COND_TYPED tvar head type name cond
198 .Fn GCQ_GOT_NEXT_COND_TYPED tvar current head start type name cond
200 .Fn GCQ_GOT_PREV_COND_TYPED tvar current head start type name cond
202 .Fn GCQ_DEQUEUED_FIRST_COND_TYPED tvar head type name cond
204 .Fn GCQ_DEQUEUED_LAST_COND_TYPED tvar head type name cond
206 .Fn GCQ_DEQUEUED_NEXT_COND_TYPED tvar current head start type name cond
208 .Fn GCQ_DEQUEUED_PREV_COND_TYPED tvar current head start type name cond
209 .Fn GCQ_FOREACH var head
210 .Fn GCQ_FOREACH_REV var head
211 .Fn GCQ_FOREACH_NVAR var nvar head
212 .Fn GCQ_FOREACH_NVAR_REV var nvar head
213 .Fn GCQ_FOREACH_RO var nvar head
214 .Fn GCQ_FOREACH_RO_REV var nvar head
215 .Fn GCQ_FOREACH_DEQUEUED var nvar head
216 .Fn GCQ_FOREACH_DEQUEUED_REV var nvar head
217 .Fn GCQ_FOREACH_TYPED var head tvar type name
218 .Fn GCQ_FOREACH_REV_TYPED var head tvar type name
219 .Fn GCQ_FOREACH_NVAR_TYPED var nvar head tvar type name
220 .Fn GCQ_FOREACH_NVAR_REV_TYPED var nvar head tvar type name
221 .Fn GCQ_FOREACH_RO_TYPED var nvar head tvar type name
222 .Fn GCQ_FOREACH_RO_REV_TYPED var nvar head tvar type name
223 .Fn GCQ_FOREACH_DEQUEUED_TYPED var nvar head tvar type name
224 .Fn GCQ_FOREACH_DEQUEUED_REV_TYPED var nvar head tvar type name
225 .Fn GCQ_FIND var head cond
226 .Fn GCQ_FIND_REV var head cond
227 .Fn GCQ_FIND_TYPED var head tvar type name cond
228 .Fn GCQ_FIND_REV_TYPED var head tvar type name cond
231 The generic circular queue is a doubly linked list designed for efficient
232 merge operations and unconditional removal.
233 All basic operations can be performed with or without use of a separate head,
234 allowing easy replacement of any pointers where efficient removal is desired.
235 The meaning of the data type will not change; direct use and defined
236 operations can be mixed when convenient.
238 .Bd -literal -offset indent
245 The structure must first be initialized such that the
249 members point to the beginning of the
251 This can be done with
255 or with constant initializers
267 The structure containing the
269 can be retrieved by pointer arithmetic in the
272 List traversal normally requires knowledge of the list head to safely
275 Capitalized operation names are macros and should be assumed to cause multiple
276 evaluation of arguments.
278 variants of macros set a typed pointer variable instead of or in addition to
281 Additional type specific inlines and macros around some GCQ operations can be
284 A few assertions are provided when
286 is defined in the kernel or
288 is defined in userland.
291 is defined prior to header inclusions
294 will be used for assertions and
296 can be used to turn them off.
298 is a wrapper around the used assertion function.
299 None of the operations accept
301 arguments, however this is not tested by assertion.
303 The head is separately named for type checking but contains only a
305 a pointer to which can be retrieved via
307 The reverse operation is performed by
312 .Vt struct gcq_head * .
316 argument and is used for type checking in
318 There are no functions for retrieving the raw
322 pointers as these are usually clearer when used directly (if at all).
325 returns the element removed and is always a valid operation after
330 if the structure links to itself and
334 is the negation of this operation performed on a head.
337 .Li "prev-\*[Gt]q_next == next \*[Am]\*[Am] next-\*[Gt]q_prev == prev" .
344 such that that if the old lists are DST, DST2 and SRC, SRC2, the new list is
345 DST, SRC, SRC2, DST2.
350 are on the same list then any elements between but not including
354 are cut from the list.
357 then the result is the same as
362 except that the latter must only be used with arguments on separate lists or
363 not on lists and asserts that
364 .Li "src != dst \*[Am]\*[Am] dst-\*[Gt]q_prev != src" .
366 performs the same operation on
367 .Li dst-\*[Gt]q_prev .
370 moves any elements on list
376 It is normally used with two heads via
381 .Dv GCQ_UNCONDITIONAL_MERGE
382 is defined prior to header inclusion then the merge operations will always
383 perform a tie then remove
385 from the new list, which may reduce code size slightly.
388 initializes all elements currently linked with
390 and is normally used with a head as
395 .Fn gcq_insert_before
396 are slightly optimized versions of
400 is not on a list and include assertions to this effect, which are also useful
401 to detect missing initialization.
405 are the same operations applied to a head.
412 to a pointer to the first or last
417 if the list is empty and return
422 The boolean return is to emphasise that it is not normally safe and useful to
423 directly pass the raw first/next/etc. pointer to another function.
424 The macros are written such that the
426 values will be optimized out if not otherwise used.
428 variants also remove the member from the list.
430 variants take an additional condition that is evaluated when the macro would
433 If the condition is false
439 and no dequeue is performed.
442 and variants take pointers to the current position, list head, and starting
444 The list head will be skipped when it is reached unless it is equal to the
445 starting point; upon reaching the starting point
449 and the macro will return
451 The next and prev macros also assert that
453 is on the list unless it is equal to
455 These macros are the only provided method for iterating through the list from
457 Traversal macros are only provided for list heads, however
459 can be used to treat any item as a head.
461 Foreach variants contain an embedded
463 statement for iterating over a list.
468 pointer for traversal, others use
472 uses a single variable.
474 variants save the next pointer at the top of the loop so that the current
475 element can be removed without adjusting
479 is passed to a function that might remove it but will not otherwise modify
481 When the head is reached both
485 elements are left pointing to the list head.
493 does not point to itself when starting the next loop.
494 This assertion takes place after the variable is tested against the head so
495 it is safe to remove all elements from the list.
499 but assert that the two variables are linked at the end of each iteration.
500 This is useful when calling a function that is not supposed to remove the
505 but remove each element before the code block is executed.
507 variants are equivalent to the untyped versions except that they take three
508 extra arguments: a typed pointer, the type name, and the member name of the
514 when the head is reached.
517 is a foreach loop that does nothing except break when the supplied condition
522 variants are available.