root / lab4 / .minix-src / include / sys / gcq.h @ 14
History | View | Annotate | Download (15.8 KB)
1 |
/* $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 */ |