root / lab4 / .minix-src / include / sys / gcq.h @ 13
History | View | Annotate | Download (15.8 KB)
1 | 13 | up20180614 | /* $NetBSD: gcq.h,v 1.2 2007/08/19 07:35:32 kiyohara Exp $ */
|
---|---|---|---|
2 | /*
|
||
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 is
|
||
7 | * part of a collection then use in the collection is governed by the terms of
|
||
8 | * the collection.
|
||
9 | */
|
||
10 | |||
11 | /*
|
||
12 | * Generic Circular Queues: Pointer arithmetic is used to recover the
|
||
13 | * enclosing object. Merge operation is provided. Items can be multiply
|
||
14 | * removed, but queue traversal requires separate knowledge of the queue head.
|
||
15 | */
|
||
16 | |||
17 | #ifndef _GCQ_H
|
||
18 | #define _GCQ_H
|
||
19 | |||
20 | #ifdef _KERNEL
|
||
21 | #include <sys/types.h> |
||
22 | #include <sys/null.h> |
||
23 | #include <lib/libkern/libkern.h> |
||
24 | #else
|
||
25 | #include <stdbool.h> |
||
26 | #include <stdint.h> |
||
27 | #include <stddef.h> |
||
28 | #include <assert.h> |
||
29 | #endif
|
||
30 | |||
31 | #ifdef GCQ_USE_ASSERT
|
||
32 | #define GCQ_ASSERT(x) assert(x)
|
||
33 | #else
|
||
34 | #ifdef _KERNEL
|
||
35 | #define GCQ_ASSERT(x) KASSERT(x)
|
||
36 | #else
|
||
37 | #define GCQ_ASSERT(x) _DIAGASSERT(x)
|
||
38 | #endif
|
||
39 | #endif
|
||
40 | |||
41 | struct gcq {
|
||
42 | struct gcq *q_next;
|
||
43 | struct gcq *q_prev;
|
||
44 | }; |
||
45 | |||
46 | struct gcq_head {
|
||
47 | struct gcq hq;
|
||
48 | }; |
||
49 | |||
50 | #define GCQ_INIT(q) { &(q), &(q) }
|
||
51 | #define GCQ_INIT_HEAD(head) { GCQ_INIT((head).hq) }
|
||
52 | |||
53 | __attribute__((nonnull, always_inline)) static inline void |
||
54 | gcq_init(struct gcq *q)
|
||
55 | { |
||
56 | q->q_next = q->q_prev = q; |
||
57 | } |
||
58 | |||
59 | __attribute__((nonnull, const, warn_unused_result, always_inline))
|
||
60 | static inline struct gcq * |
||
61 | gcq_q(struct gcq *q)
|
||
62 | { |
||
63 | return q;
|
||
64 | } |
||
65 | |||
66 | __attribute__((nonnull, const, warn_unused_result, always_inline))
|
||
67 | static inline struct gcq * |
||
68 | gcq_hq(struct gcq_head *head)
|
||
69 | { |
||
70 | return (struct gcq *)head; |
||
71 | } |
||
72 | |||
73 | __attribute__((nonnull, const, warn_unused_result, always_inline))
|
||
74 | static inline struct gcq_head * |
||
75 | gcq_head(struct gcq *q)
|
||
76 | { |
||
77 | return (struct gcq_head *)q; |
||
78 | } |
||
79 | |||
80 | __attribute__((nonnull, always_inline)) static inline void |
||
81 | gcq_init_head(struct gcq_head *head)
|
||
82 | { |
||
83 | gcq_init(gcq_hq(head)); |
||
84 | } |
||
85 | |||
86 | __attribute__((nonnull, pure, warn_unused_result, always_inline)) |
||
87 | static inline bool |
||
88 | gcq_onlist(struct gcq *q)
|
||
89 | { |
||
90 | return (q->q_next != q);
|
||
91 | } |
||
92 | |||
93 | __attribute__((nonnull, pure, warn_unused_result, always_inline)) |
||
94 | static inline bool |
||
95 | gcq_empty(struct gcq_head *head)
|
||
96 | { |
||
97 | return (!gcq_onlist(gcq_hq(head)));
|
||
98 | } |
||
99 | |||
100 | __attribute__((nonnull, pure, warn_unused_result, always_inline)) |
||
101 | static inline bool |
||
102 | gcq_linked(struct gcq *prev, struct gcq *next) |
||
103 | { |
||
104 | return (prev->q_next == next && next->q_prev == prev);
|
||
105 | } |
||
106 | |||
107 | __attribute__((nonnull, always_inline)) static inline void |
||
108 | gcq_insert_after(struct gcq *on, struct gcq *off) |
||
109 | { |
||
110 | struct gcq *on_next;
|
||
111 | GCQ_ASSERT(off->q_next == off && off->q_prev == off); |
||
112 | on_next = on->q_next; |
||
113 | |||
114 | off->q_prev = on; |
||
115 | off->q_next = on_next; |
||
116 | on_next->q_prev = off; |
||
117 | on->q_next = off; |
||
118 | } |
||
119 | |||
120 | __attribute__((nonnull)) static inline void |
||
121 | gcq_insert_before(struct gcq *on, struct gcq *off) |
||
122 | { |
||
123 | struct gcq *on_prev;
|
||
124 | GCQ_ASSERT(off->q_next == off && off->q_prev == off); |
||
125 | on_prev = on->q_prev; |
||
126 | |||
127 | off->q_next = on; |
||
128 | off->q_prev = on_prev; |
||
129 | on_prev->q_next = off; |
||
130 | on->q_prev = off; |
||
131 | } |
||
132 | |||
133 | __attribute__((nonnull, always_inline)) static inline void |
||
134 | gcq_insert_head(struct gcq_head *head, struct gcq *q) |
||
135 | { |
||
136 | gcq_insert_after(gcq_hq(head), q); |
||
137 | } |
||
138 | |||
139 | __attribute__((nonnull, always_inline)) static inline void |
||
140 | gcq_insert_tail(struct gcq_head *head, struct gcq *q) |
||
141 | { |
||
142 | gcq_insert_before(gcq_hq(head), q); |
||
143 | } |
||
144 | |||
145 | __attribute__((nonnull)) static inline void |
||
146 | gcq_tie(struct gcq *dst, struct gcq *src) |
||
147 | { |
||
148 | struct gcq *dst_next, *src_prev;
|
||
149 | dst_next = dst->q_next; |
||
150 | src_prev = src->q_prev; |
||
151 | |||
152 | src_prev->q_next = dst_next; |
||
153 | dst_next->q_prev = src_prev; |
||
154 | src->q_prev = dst; |
||
155 | dst->q_next = src; |
||
156 | } |
||
157 | |||
158 | __attribute__((nonnull, always_inline)) static inline void |
||
159 | gcq_tie_after(struct gcq *dst, struct gcq *src) |
||
160 | { |
||
161 | GCQ_ASSERT(dst != src && dst->q_prev != src); |
||
162 | gcq_tie(dst, src); |
||
163 | } |
||
164 | |||
165 | __attribute__((nonnull, always_inline)) static inline void |
||
166 | gcq_tie_before(struct gcq *dst, struct gcq *src) |
||
167 | { |
||
168 | gcq_tie_after(dst->q_prev, src); |
||
169 | } |
||
170 | |||
171 | __attribute__((nonnull)) static inline struct gcq * |
||
172 | gcq_remove(struct gcq *q)
|
||
173 | { |
||
174 | struct gcq *next, *prev;
|
||
175 | next = q->q_next; |
||
176 | prev = q->q_prev; |
||
177 | |||
178 | prev->q_next = next; |
||
179 | next->q_prev = prev; |
||
180 | gcq_init(q); |
||
181 | return q;
|
||
182 | } |
||
183 | |||
184 | #ifdef GCQ_UNCONDITIONAL_MERGE
|
||
185 | __attribute__((nonnull)) static inline void |
||
186 | gcq_merge(struct gcq *dst, struct gcq *src) |
||
187 | { |
||
188 | GCQ_ASSERT(dst != src && dst->q_prev != src); |
||
189 | gcq_tie(dst, src); |
||
190 | gcq_tie(src, src); |
||
191 | } |
||
192 | |||
193 | __attribute__((nonnull, always_inline)) static inline void |
||
194 | gcq_merge_head(struct gcq_head *dst, struct gcq_head *src) |
||
195 | { |
||
196 | gcq_merge(gcq_hq(dst), gcq_hq(src)); |
||
197 | } |
||
198 | |||
199 | __attribute__((nonnull, always_inline)) static inline void |
||
200 | gcq_merge_tail(struct gcq_head *dst, struct gcq_head *src) |
||
201 | { |
||
202 | gcq_merge(gcq_hq(dst)->q_prev, gcq_hq(src)); |
||
203 | } |
||
204 | #else
|
||
205 | __attribute__((nonnull)) static inline void |
||
206 | gcq_merge(struct gcq *dst, struct gcq *src) |
||
207 | { |
||
208 | struct gcq *dst_next, *src_prev, *src_next;
|
||
209 | GCQ_ASSERT(dst != src && dst->q_prev != src); |
||
210 | |||
211 | if (gcq_onlist(src)) {
|
||
212 | dst_next = dst->q_next; |
||
213 | src_prev = src->q_prev; |
||
214 | src_next = src->q_next; |
||
215 | |||
216 | dst_next->q_prev = src_prev; |
||
217 | src_prev->q_next = dst_next; |
||
218 | dst->q_next = src_next; |
||
219 | src_next->q_prev = dst; |
||
220 | gcq_init(src); |
||
221 | } |
||
222 | } |
||
223 | |||
224 | __attribute__((nonnull, always_inline)) static inline void |
||
225 | gcq_merge_head(struct gcq_head *dst, struct gcq_head *src) |
||
226 | { |
||
227 | gcq_merge(gcq_hq(dst), gcq_hq(src)); |
||
228 | } |
||
229 | |||
230 | __attribute__((nonnull, always_inline)) static inline void |
||
231 | gcq_merge_tail(struct gcq_head *dst, struct gcq_head *src) |
||
232 | { |
||
233 | gcq_merge(gcq_hq(dst)->q_prev, gcq_hq(src)); |
||
234 | } |
||
235 | #endif
|
||
236 | |||
237 | __attribute__((nonnull)) static inline void |
||
238 | gcq_clear(struct gcq *q)
|
||
239 | { |
||
240 | struct gcq *nq, *next;
|
||
241 | nq=q; |
||
242 | do {
|
||
243 | next = nq->q_next; |
||
244 | gcq_init(nq); |
||
245 | nq = next; |
||
246 | } while (next != q);
|
||
247 | } |
||
248 | |||
249 | __attribute__((nonnull, always_inline)) static inline void |
||
250 | gcq_remove_all(struct gcq_head *head)
|
||
251 | { |
||
252 | gcq_clear(gcq_hq(head)); |
||
253 | } |
||
254 | |||
255 | __attribute__((nonnull, always_inline)) static inline struct gcq * |
||
256 | _gcq_next(struct gcq *current, struct gcq_head *head, struct gcq *start) |
||
257 | { |
||
258 | struct gcq *q, *hq;
|
||
259 | hq = gcq_hq(head); |
||
260 | q = current->q_next; |
||
261 | if (hq != start && q == hq)
|
||
262 | q = hq->q_next; |
||
263 | if (current != start)
|
||
264 | GCQ_ASSERT(gcq_onlist(current)); |
||
265 | return q;
|
||
266 | } |
||
267 | |||
268 | __attribute__((nonnull, always_inline)) static inline struct gcq * |
||
269 | _gcq_prev(struct gcq *current, struct gcq_head *head, struct gcq *start) |
||
270 | { |
||
271 | struct gcq *q, *hq;
|
||
272 | hq = gcq_hq(head); |
||
273 | q = current->q_prev; |
||
274 | if (hq != start && q == hq)
|
||
275 | q = hq->q_prev; |
||
276 | if (current != start)
|
||
277 | GCQ_ASSERT(gcq_onlist(current)); |
||
278 | return q;
|
||
279 | } |
||
280 | |||
281 | |||
282 | #define GCQ_ITEM(q, type, name) \
|
||
283 | ((type *)(void *)((uint8_t *)gcq_q(q) - offsetof(type, name)))
|
||
284 | |||
285 | |||
286 | #define _GCQ_GDQ(var, h, ptr, fn) (gcq_hq(h)->ptr != gcq_hq(h) ? \
|
||
287 | (var = fn(gcq_hq(h)->ptr), true) : (var = NULL, false)) |
||
288 | #define _GCQ_GDQ_TYPED(tvar, h, type, name, ptr, fn) \
|
||
289 | (gcq_hq(h)->ptr != gcq_hq(h) ? (tvar = GCQ_ITEM(fn(gcq_hq(h)->ptr), \ |
||
290 | type, name), true) : (tvar = NULL, false)) |
||
291 | #define _GCQ_NP(var, current, head, start, np, fn) \
|
||
292 | (np(current, head, start) != (start) ? \ |
||
293 | (var = fn(np(current, head, start)), true) : (var = NULL, false)) |
||
294 | #define _GCQ_NP_TYPED(tvar, current, head, start, type, name, np, fn) \
|
||
295 | (np(current, head, start) != (start) ? \ |
||
296 | (tvar = GCQ_ITEM(fn(np(current, head, start)), type, name), true) : \
|
||
297 | (tvar = NULL, false)) |
||
298 | |||
299 | #define _GCQ_GDQ_COND(var, h, ptr, rem, cond) \
|
||
300 | (gcq_hq(h)->ptr != gcq_hq(h) ? (var = gcq_hq(h)->ptr, \ |
||
301 | ((cond) ? (rem, true) : (var = NULL, false))) : \ |
||
302 | (var = NULL, false)) |
||
303 | #define _GCQ_GDQ_COND_TYPED(tvar, h, type, name, ptr, rem, cond) \
|
||
304 | (gcq_hq(h)->ptr != gcq_hq(h) ? (tvar = GCQ_ITEM(gcq_hq(h)->ptr, \ |
||
305 | type, name), ((cond) ? (rem, true) : (tvar = NULL, false))) : \ |
||
306 | (tvar = NULL, false)) |
||
307 | #define _GCQ_NP_COND(var, current, head, start, np, rem, cond) \
|
||
308 | (np(current, head, start) != (start) ? \ |
||
309 | (var = fn(np(current, head, start)), ((cond) ? (rem), true) : \
|
||
310 | (var = NULL, false))) : (var = NULL, false)) |
||
311 | #define _GCQ_NP_COND_TYPED(tvar, current, head, start, type, name, np, \
|
||
312 | rem, cond) (np(current, head, start) != (start) ? \ |
||
313 | (tvar = GCQ_ITEM(fn(np(current, head, start)), type, name), \ |
||
314 | ((cond) ? (rem, true) : (var = NULL, false))) : \ |
||
315 | (tvar = NULL, false)) |
||
316 | |||
317 | #define GCQ_GOT_FIRST(var, h) _GCQ_GDQ(var, h, q_next, gcq_q)
|
||
318 | #define GCQ_GOT_LAST(var, h) _GCQ_GDQ(var, h, q_prev, gcq_q)
|
||
319 | #define GCQ_DEQUEUED_FIRST(var, h) _GCQ_GDQ(var, h, q_next, gcq_remove)
|
||
320 | #define GCQ_DEQUEUED_LAST(var, h) _GCQ_GDQ(var, h, q_prev, gcq_remove)
|
||
321 | #define GCQ_GOT_FIRST_TYPED(tvar, h, type, name) \
|
||
322 | _GCQ_GDQ_TYPED(tvar, h, type, name, q_next, gcq_q) |
||
323 | #define GCQ_GOT_LAST_TYPED(tvar, h, type, name) \
|
||
324 | _GCQ_GDQ_TYPED(tvar, h, type, name, q_prev, gcq_q) |
||
325 | #define GCQ_DEQUEUED_FIRST_TYPED(tvar, h, type, name) \
|
||
326 | _GCQ_GDQ_TYPED(tvar, h, type, name, q_next, gcq_remove) |
||
327 | #define GCQ_DEQUEUED_LAST_TYPED(tvar, h, type, name) \
|
||
328 | _GCQ_GDQ_TYPED(tvar, h, type, name, q_prev, gcq_remove) |
||
329 | #define GCQ_GOT_NEXT(var, current, head, start) \
|
||
330 | _GCQ_NP(var, current, head, start, _gcq_next, gcq_q) |
||
331 | #define GCQ_GOT_PREV(var, current, head, start) \
|
||
332 | _GCQ_NP(var, current, head, start, _gcq_prev, gcq_q) |
||
333 | #define GCQ_DEQUEUED_NEXT(var, current, head, start) \
|
||
334 | _GCQ_NP(var, current, head, start, _gcq_next, gcq_remove) |
||
335 | #define GCQ_DEQUEUED_PREV(var, current, head, start) \
|
||
336 | _GCQ_NP(var, current, head, start, _gcq_prev, gcq_remove) |
||
337 | #define GCQ_GOT_NEXT_TYPED(tvar, current, head, start, type, name) \
|
||
338 | _GCQ_NP_TYPED(tvar, current, head, start, type, name, \ |
||
339 | _gcq_next, gcq_q) |
||
340 | #define GCQ_GOT_PREV_TYPED(tvar, current, head, start, type, name) \
|
||
341 | _GCQ_NP_TYPED(tvar, current, head, start, type, name, \ |
||
342 | _gcq_prev, gcq_q) |
||
343 | #define GCQ_DEQUEUED_NEXT_TYPED(tvar, current, head, start, type, name) \
|
||
344 | _GCQ_NP_TYPED(tvar, current, head, start, type, name, \ |
||
345 | _gcq_next, gcq_remove) |
||
346 | #define GCQ_DEQUEUED_PREV_TYPED(tvar, current, head, start, type, name) \
|
||
347 | _GCQ_NP_TYPED(tvar, current, head, start, type, name, \ |
||
348 | _gcq_prev, gcq_remove) |
||
349 | |||
350 | #define GCQ_GOT_FIRST_COND(var, h, cond) \
|
||
351 | _GCQ_GDQ_COND(var, h, q_next, ((void)0), cond) |
||
352 | #define GCQ_GOT_LAST_COND(var, h, cond) \
|
||
353 | _GCQ_GDQ_COND(var, h, q_prev, ((void)0), cond) |
||
354 | #define GCQ_DEQUEUED_FIRST_COND(var, h, cond) \
|
||
355 | _GCQ_GDQ_COND(var, h, q_next, gcq_remove(var), cond) |
||
356 | #define GCQ_DEQUEUED_LAST_COND(var, h, cond) \
|
||
357 | _GCQ_GDQ_COND(var, h, q_prev, gcq_remove(var), cond) |
||
358 | #define GCQ_GOT_FIRST_COND_TYPED(tvar, h, type, name, cond) \
|
||
359 | _GCQ_GDQ_COND_TYPED(tvar, h, type, name, q_next, ((void)0), cond) |
||
360 | #define GCQ_GOT_LAST_COND_TYPED(tvar, h, type, name, cond) \
|
||
361 | _GCQ_GDQ_COND_TYPED(tvar, h, type, name, q_prev, ((void)0), cond) |
||
362 | #define GCQ_DEQUEUED_FIRST_COND_TYPED(tvar, h, type, name, cond) \
|
||
363 | _GCQ_GDQ_COND_TYPED(tvar, h, type, name, q_next, \ |
||
364 | gcq_remove(&(tvar)->name), cond) |
||
365 | #define GCQ_DEQUEUED_LAST_COND_TYPED(tvar, h, type, name, cond) \
|
||
366 | _GCQ_GDQ_COND_TYPED(tvar, h, type, name, q_prev, \ |
||
367 | gcq_remove(&(tvar)->name), cond) |
||
368 | #define GCQ_GOT_NEXT_COND(var, current, head, start, cond) \
|
||
369 | _GCQ_NP_COND(var, current, head, start, _gcq_next, ((void)0), cond) |
||
370 | #define GCQ_GOT_PREV_COND(var, current, head, start, cond) \
|
||
371 | _GCQ_NP_COND(var, current, head, start, _gcq_prev, ((void)0), cond) |
||
372 | #define GCQ_DEQUEUED_NEXT_COND(var, current, head, start, cond) \
|
||
373 | _GCQ_NP_COND(var, current, head, start, _gcq_next, gcq_remove(var), \ |
||
374 | cond) |
||
375 | #define GCQ_DEQUEUED_PREV_COND(var, current, head, start, cond) \
|
||
376 | _GCQ_NP_COND(var, current, head, start, _gcq_prev, gcq_remove(var), \ |
||
377 | cond) |
||
378 | #define GCQ_GOT_NEXT_COND_TYPED(tvar, current, head, start, type, name, \
|
||
379 | cond) _GCQ_NP_COND_TYPED(tvar, current, head, start, type, name, \ |
||
380 | _gcq_next, ((void)0), cond) |
||
381 | #define GCQ_GOT_PREV_COND_TYPED(tvar, current, head, start, type, name, \
|
||
382 | cond) _GCQ_NP_COND_TYPED(tvar, current, head, start, type, name, \ |
||
383 | _gcq_prev, ((void)0), cond) |
||
384 | #define GCQ_DEQUEUED_NEXT_COND_TYPED(tvar, current, head, start, type, \
|
||
385 | name, cond) _GCQ_NP_COND_TYPED(tvar, current, head, start, type, \ |
||
386 | name, _gcq_next, gcq_remove(&(tvar)->name), cond) |
||
387 | #define GCQ_DEQUEUED_PREV_COND_TYPED(tvar, current, head, start, type, \
|
||
388 | name, cond) _GCQ_NP_COND_TYPED(tvar, current, head, start, type, \ |
||
389 | name, _gcq_prev, gcq_remove(&(tvar)->name), cond) |
||
390 | |||
391 | |||
392 | #define _GCQ_FOREACH(var, h, tnull, item, ptr) \
|
||
393 | for ((var)=gcq_hq(h)->ptr; ((var) != gcq_hq(h) && \
|
||
394 | (GCQ_ASSERT(gcq_onlist(var)), item, true)) || \
|
||
395 | (tnull, false); (var)=(var)->ptr)
|
||
396 | #define _GCQ_FOREACH_NVAR(var, nvar, h, tnull, item, ptr, ol, rem, ro) \
|
||
397 | for ((nvar)=gcq_hq(h)->ptr; (((var)=(nvar), (nvar) != gcq_hq(h)) && \
|
||
398 | (ol, (nvar)=(nvar)->ptr, rem, item, true)) || (tnull, false); ro) |
||
399 | |||
400 | #define GCQ_FOREACH(var, h) \
|
||
401 | _GCQ_FOREACH(var, h, ((void)0), ((void)0), q_next) |
||
402 | #define GCQ_FOREACH_REV(var, h) \
|
||
403 | _GCQ_FOREACH(var, h, ((void)0), ((void)0), q_prev) |
||
404 | #define GCQ_FOREACH_NVAR(var, nvar, h) \
|
||
405 | _GCQ_FOREACH_NVAR(var, nvar, h, ((void)0), ((void)0), \ |
||
406 | q_next, GCQ_ASSERT(gcq_onlist(nvar)), ((void)0), ((void)0)) |
||
407 | #define GCQ_FOREACH_NVAR_REV(var, nvar, h) \
|
||
408 | _GCQ_FOREACH_NVAR(var, nvar, h, ((void)0), ((void)0), \ |
||
409 | q_prev, GCQ_ASSERT(gcq_onlist(nvar)), ((void)0), ((void)0)) |
||
410 | #define GCQ_FOREACH_RO(var, nvar, h) \
|
||
411 | _GCQ_FOREACH_NVAR(var, nvar, h, ((void)0), ((void)0), \ |
||
412 | q_next, ((void)0), ((void)0), GCQ_ASSERT(gcq_linked(var, nvar))) |
||
413 | #define GCQ_FOREACH_RO_REV(var, nvar, h) \
|
||
414 | _GCQ_FOREACH_NVAR(var, nvar, h, ((void)0), ((void)0), \ |
||
415 | q_prev, ((void)0), ((void)0), GCQ_ASSERT(gcq_linked(nvar, var))) |
||
416 | #define GCQ_FOREACH_DEQUEUED(var, nvar, h) \
|
||
417 | _GCQ_FOREACH_NVAR(var, nvar, h, ((void)0), ((void)0), \ |
||
418 | q_next, GCQ_ASSERT(gcq_onlist(nvar)), gcq_remove(var), ((void)0) |
||
419 | #define GCQ_FOREACH_DEQUEUED_REV(var, nvar, h) \
|
||
420 | _GCQ_FOREACH_NVAR(var, nvar, h, ((void)0), ((void)0), \ |
||
421 | q_prev, GCQ_ASSERT(gcq_onlist(nvar)), gcq_remove(var), ((void)0) |
||
422 | |||
423 | #define GCQ_FOREACH_TYPED(var, h, tvar, type, name) \
|
||
424 | _GCQ_FOREACH(var, h, (tvar)=NULL, (tvar)=GCQ_ITEM(var, type, name), \
|
||
425 | q_next) |
||
426 | #define GCQ_FOREACH_TYPED_REV(var, h, tvar, type, name) \
|
||
427 | _GCQ_FOREACH(var, h, (tvar)=NULL, (tvar)=GCQ_ITEM(var, type, name), \
|
||
428 | q_prev) |
||
429 | #define GCQ_FOREACH_NVAR_TYPED(var, nvar, h, tvar, type, name) \
|
||
430 | _GCQ_FOREACH_NVAR(var, nvar, h, (tvar)=NULL, \
|
||
431 | (tvar)=GCQ_ITEM(var, type, name), \ |
||
432 | q_next, GCQ_ASSERT(gcq_onlist(nvar)), ((void)0), ((void)0)) |
||
433 | #define GCQ_FOREACH_NVAR_REV_TYPED(var, nvar, h, tvar, type, name) \
|
||
434 | _GCQ_FOREACH_NVAR(var, nvar, h, (tvar)=NULL, \
|
||
435 | (tvar)=GCQ_ITEM(var, type, name), \ |
||
436 | q_prev, GCQ_ASSERT(gcq_onlist(nvar)), ((void)0), ((void)0)) |
||
437 | #define GCQ_FOREACH_RO_TYPED(var, nvar, h, tvar, type, name) \
|
||
438 | _GCQ_FOREACH_NVAR(var, nvar, h, (tvar)=NULL, \
|
||
439 | (tvar)=GCQ_ITEM(var, type, name), \ |
||
440 | q_next, ((void)0), ((void)0), GCQ_ASSERT(gcq_lined(var, nvar))) |
||
441 | #define GCQ_FOREACH_RO_REV_TYPED(var, nvar, h, tvar, type, name) \
|
||
442 | _GCQ_FOREACH_NVAR(var, nvar, h, (tvar)=NULL, \
|
||
443 | (tvar)=GCQ_ITEM(var, type, name), \ |
||
444 | q_prev, ((void)0), ((void)0), GCQ_ASSERT(gcq_linked(nvar, var))) |
||
445 | #define GCQ_FOREACH_DEQUEUED_TYPED(var, nvar, h, tvar, type, name) \
|
||
446 | _GCQ_FOREACH_NVAR(var, nvar, h, (tvar)=NULL, \
|
||
447 | (tvar)=GCQ_ITEM(var, type, name), \ |
||
448 | q_next, GCQ_ASSERT(gcq_onlist(nvar)), gcq_remove(var), ((void)0)) |
||
449 | #define GCQ_FOREACH_DEQUEUED_REV_TYPED(var, nvar, h, tvar, type, name) \
|
||
450 | _GCQ_FOREACH_NVAR(var, nvar, h, (tvar)=NULL, \
|
||
451 | (tvar)=GCQ_ITEM(var, type, name), \ |
||
452 | q_prev, GCQ_ASSERT(gcq_onlist(nvar)), gcq_remove(var), ((void)0)) |
||
453 | |||
454 | #define _GCQ_COND(fe, cond) do { fe { if (cond) break; } } while (0) |
||
455 | |||
456 | #define GCQ_FIND(var, h, cond) _GCQ_COND(GCQ_FOREACH(var, h), cond)
|
||
457 | #define GCQ_FIND_REV(var, h, cond) _GCQ_COND(GCQ_FOREACH_REV(var, h), cond)
|
||
458 | #define GCQ_FIND_TYPED(var, h, tvar, type, name, cond) \
|
||
459 | _GCQ_COND(GCQ_FOREACH_TYPED(var, h, tvar, type, name), cond) |
||
460 | #define GCQ_FIND_TYPED_REV(var, h, tvar, type, name, cond) \
|
||
461 | _GCQ_COND(GCQ_FOREACH_REV_TYPED(var, h, tvar, type, name), cond) |
||
462 | |||
463 | #endif /* _GCQ_H */ |