xref: /aosp_15_r20/external/mesa3d/src/compiler/glsl/list.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2008, 2010 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 /**
25  * \file list.h
26  * \brief Doubly-linked list abstract container type.
27  *
28  * Each doubly-linked list has a sentinel head and tail node.  These nodes
29  * contain no data.  The head sentinel can be identified by its \c prev
30  * pointer being \c NULL.  The tail sentinel can be identified by its
31  * \c next pointer being \c NULL.
32  *
33  * A list is empty if either the head sentinel's \c next pointer points to the
34  * tail sentinel or the tail sentinel's \c prev poiner points to the head
35  * sentinel. The head sentinel and tail sentinel nodes are allocated within the
36  * list structure.
37  *
38  * Do note that this means that the list nodes will contain pointers into the
39  * list structure itself and as a result you may not \c realloc() an  \c
40  * exec_list or any structure in which an \c exec_list is embedded.
41  */
42 
43 #ifndef LIST_CONTAINER_H
44 #define LIST_CONTAINER_H
45 
46 #ifndef __cplusplus
47 #include <stddef.h>
48 #endif
49 #include <assert.h>
50 
51 #include "util/ralloc.h"
52 
53 struct exec_node {
54    struct exec_node *next;
55    struct exec_node *prev;
56 
57 #ifdef __cplusplus
58    DECLARE_RZALLOC_CXX_OPERATORS(exec_node)
59 
exec_nodeexec_node60    exec_node() : next(NULL), prev(NULL)
61    {
62       /* empty */
63    }
64 
65    const exec_node *get_next() const;
66    exec_node *get_next();
67 
68    const exec_node *get_prev() const;
69    exec_node *get_prev();
70 
71    void remove();
72 
73    /**
74     * Link a node with itself
75     *
76     * This creates a sort of degenerate list that is occasionally useful.
77     */
78    void self_link();
79 
80    /**
81     * Insert a node in the list after the current node
82     */
83    void insert_after(exec_node *after);
84 
85    /**
86     * Insert another list in the list after the current node
87     */
88    void insert_after(struct exec_list *after);
89 
90    /**
91     * Insert a node in the list before the current node
92     */
93    void insert_before(exec_node *before);
94 
95    /**
96     * Insert another list in the list before the current node
97     */
98    void insert_before(struct exec_list *before);
99 
100    /**
101     * Replace the current node with the given node.
102     */
103    void replace_with(exec_node *replacement);
104 
105    /**
106     * Is this the sentinel at the tail of the list?
107     */
108    bool is_tail_sentinel() const;
109 
110    /**
111     * Is this the sentinel at the head of the list?
112     */
113    bool is_head_sentinel() const;
114 #endif
115 };
116 
117 static inline void
exec_node_init(struct exec_node * n)118 exec_node_init(struct exec_node *n)
119 {
120    n->next = NULL;
121    n->prev = NULL;
122 }
123 
124 static inline const struct exec_node *
exec_node_get_next_const(const struct exec_node * n)125 exec_node_get_next_const(const struct exec_node *n)
126 {
127    return n->next;
128 }
129 
130 static inline struct exec_node *
exec_node_get_next(struct exec_node * n)131 exec_node_get_next(struct exec_node *n)
132 {
133    return n->next;
134 }
135 
136 static inline const struct exec_node *
exec_node_get_prev_const(const struct exec_node * n)137 exec_node_get_prev_const(const struct exec_node *n)
138 {
139    return n->prev;
140 }
141 
142 static inline struct exec_node *
exec_node_get_prev(struct exec_node * n)143 exec_node_get_prev(struct exec_node *n)
144 {
145    return n->prev;
146 }
147 
148 static inline void
exec_node_remove(struct exec_node * n)149 exec_node_remove(struct exec_node *n)
150 {
151    n->next->prev = n->prev;
152    n->prev->next = n->next;
153    n->next = NULL;
154    n->prev = NULL;
155 }
156 
157 static inline void
exec_node_self_link(struct exec_node * n)158 exec_node_self_link(struct exec_node *n)
159 {
160    n->next = n;
161    n->prev = n;
162 }
163 
164 static inline void
exec_node_insert_after(struct exec_node * n,struct exec_node * after)165 exec_node_insert_after(struct exec_node *n, struct exec_node *after)
166 {
167    after->next = n->next;
168    after->prev = n;
169 
170    n->next->prev = after;
171    n->next = after;
172 }
173 
174 static inline void
exec_node_insert_node_before(struct exec_node * n,struct exec_node * before)175 exec_node_insert_node_before(struct exec_node *n, struct exec_node *before)
176 {
177    before->next = n;
178    before->prev = n->prev;
179 
180    n->prev->next = before;
181    n->prev = before;
182 }
183 
184 static inline void
exec_node_replace_with(struct exec_node * n,struct exec_node * replacement)185 exec_node_replace_with(struct exec_node *n, struct exec_node *replacement)
186 {
187    replacement->prev = n->prev;
188    replacement->next = n->next;
189 
190    n->prev->next = replacement;
191    n->next->prev = replacement;
192 }
193 
194 static inline bool
exec_node_is_tail_sentinel(const struct exec_node * n)195 exec_node_is_tail_sentinel(const struct exec_node *n)
196 {
197    return n->next == NULL;
198 }
199 
200 static inline bool
exec_node_is_head_sentinel(const struct exec_node * n)201 exec_node_is_head_sentinel(const struct exec_node *n)
202 {
203    return n->prev == NULL;
204 }
205 
206 #ifdef __cplusplus
get_next()207 inline const exec_node *exec_node::get_next() const
208 {
209    return exec_node_get_next_const(this);
210 }
211 
get_next()212 inline exec_node *exec_node::get_next()
213 {
214    return exec_node_get_next(this);
215 }
216 
get_prev()217 inline const exec_node *exec_node::get_prev() const
218 {
219    return exec_node_get_prev_const(this);
220 }
221 
get_prev()222 inline exec_node *exec_node::get_prev()
223 {
224    return exec_node_get_prev(this);
225 }
226 
remove()227 inline void exec_node::remove()
228 {
229    exec_node_remove(this);
230 }
231 
self_link()232 inline void exec_node::self_link()
233 {
234    exec_node_self_link(this);
235 }
236 
insert_after(exec_node * after)237 inline void exec_node::insert_after(exec_node *after)
238 {
239    exec_node_insert_after(this, after);
240 }
241 
insert_before(exec_node * before)242 inline void exec_node::insert_before(exec_node *before)
243 {
244    exec_node_insert_node_before(this, before);
245 }
246 
replace_with(exec_node * replacement)247 inline void exec_node::replace_with(exec_node *replacement)
248 {
249    exec_node_replace_with(this, replacement);
250 }
251 
is_tail_sentinel()252 inline bool exec_node::is_tail_sentinel() const
253 {
254    return exec_node_is_tail_sentinel(this);
255 }
256 
is_head_sentinel()257 inline bool exec_node::is_head_sentinel() const
258 {
259    return exec_node_is_head_sentinel(this);
260 }
261 #endif
262 
263 #ifdef __cplusplus
264 /* This macro will not work correctly if `t' uses virtual inheritance. */
265 #define exec_list_offsetof(t, f, p) \
266    (((char *) &((t *) p)->f) - ((char *) p))
267 #else
268 #define exec_list_offsetof(t, f, p) offsetof(t, f)
269 #endif
270 
271 /**
272  * Get a pointer to the structure containing an exec_node
273  *
274  * Given a pointer to an \c exec_node embedded in a structure, get a pointer to
275  * the containing structure.
276  *
277  * \param type  Base type of the structure containing the node
278  * \param node  Pointer to the \c exec_node
279  * \param field Name of the field in \c type that is the embedded \c exec_node
280  */
281 #define exec_node_data(type, node, field) \
282    ((type *) (((uintptr_t) node) - exec_list_offsetof(type, field, node)))
283 
284 #ifdef __cplusplus
285 struct exec_node;
286 #endif
287 
288 struct exec_list {
289    struct exec_node head_sentinel;
290    struct exec_node tail_sentinel;
291 
292 #ifdef __cplusplus
293    DECLARE_RALLOC_CXX_OPERATORS(exec_list)
294 
exec_listexec_list295    exec_list()
296    {
297       make_empty();
298    }
299 
300    void make_empty();
301 
302    bool is_empty() const;
303 
304    const exec_node *get_head() const;
305    exec_node *get_head();
306    const exec_node *get_head_raw() const;
307    exec_node *get_head_raw();
308 
309    const exec_node *get_tail() const;
310    exec_node *get_tail();
311    const exec_node *get_tail_raw() const;
312    exec_node *get_tail_raw();
313 
314    unsigned length() const;
315 
316    void push_head(exec_node *n);
317    void push_tail(exec_node *n);
318    void push_degenerate_list_at_head(exec_node *n);
319 
320    /**
321     * Remove the first node from a list and return it
322     *
323     * \return
324     * The first node in the list or \c NULL if the list is empty.
325     *
326     * \sa exec_list::get_head
327     */
328    exec_node *pop_head();
329 
330    /**
331     * Move all of the nodes from this list to the target list
332     */
333    void move_nodes_to(exec_list *target);
334 
335    /**
336     * Append all nodes from the source list to the end of the target list
337     */
338    void append_list(exec_list *source);
339 
340    /**
341     * Prepend all nodes from the source list to the beginning of the target
342     * list
343     */
344    void prepend_list(exec_list *source);
345 #endif
346 };
347 
348 static inline void
exec_list_make_empty(struct exec_list * list)349 exec_list_make_empty(struct exec_list *list)
350 {
351    list->head_sentinel.next = &list->tail_sentinel;
352    list->head_sentinel.prev = NULL;
353    list->tail_sentinel.next = NULL;
354    list->tail_sentinel.prev = &list->head_sentinel;
355 }
356 
357 static inline bool
exec_list_is_empty(const struct exec_list * list)358 exec_list_is_empty(const struct exec_list *list)
359 {
360    /* There are three ways to test whether a list is empty or not.
361     *
362     * - Check to see if the head sentinel's \c next is the tail sentinel.
363     * - Check to see if the tail sentinel's \c prev is the head sentinel.
364     * - Check to see if the head is the sentinel node by test whether its
365     *   \c next pointer is \c NULL.
366     *
367     * The first two methods tend to generate better code on modern systems
368     * because they save a pointer dereference.
369     */
370    return list->head_sentinel.next == &list->tail_sentinel;
371 }
372 
373 static inline bool
exec_list_is_singular(const struct exec_list * list)374 exec_list_is_singular(const struct exec_list *list)
375 {
376    return !exec_list_is_empty(list) &&
377           list->head_sentinel.next->next == &list->tail_sentinel;
378 }
379 
380 static inline const struct exec_node *
exec_list_get_head_const(const struct exec_list * list)381 exec_list_get_head_const(const struct exec_list *list)
382 {
383    return !exec_list_is_empty(list) ? list->head_sentinel.next : NULL;
384 }
385 
386 static inline struct exec_node *
exec_list_get_head(struct exec_list * list)387 exec_list_get_head(struct exec_list *list)
388 {
389    return !exec_list_is_empty(list) ? list->head_sentinel.next : NULL;
390 }
391 
392 static inline const struct exec_node *
exec_list_get_head_raw_const(const struct exec_list * list)393 exec_list_get_head_raw_const(const struct exec_list *list)
394 {
395    return list->head_sentinel.next;
396 }
397 
398 static inline struct exec_node *
exec_list_get_head_raw(struct exec_list * list)399 exec_list_get_head_raw(struct exec_list *list)
400 {
401    return list->head_sentinel.next;
402 }
403 
404 static inline const struct exec_node *
exec_list_get_tail_const(const struct exec_list * list)405 exec_list_get_tail_const(const struct exec_list *list)
406 {
407    return !exec_list_is_empty(list) ? list->tail_sentinel.prev : NULL;
408 }
409 
410 static inline struct exec_node *
exec_list_get_tail(struct exec_list * list)411 exec_list_get_tail(struct exec_list *list)
412 {
413    return !exec_list_is_empty(list) ? list->tail_sentinel.prev : NULL;
414 }
415 
416 static inline const struct exec_node *
exec_list_get_tail_raw_const(const struct exec_list * list)417 exec_list_get_tail_raw_const(const struct exec_list *list)
418 {
419    return list->tail_sentinel.prev;
420 }
421 
422 static inline struct exec_node *
exec_list_get_tail_raw(struct exec_list * list)423 exec_list_get_tail_raw(struct exec_list *list)
424 {
425    return list->tail_sentinel.prev;
426 }
427 
428 static inline unsigned
exec_list_length(const struct exec_list * list)429 exec_list_length(const struct exec_list *list)
430 {
431    unsigned size = 0;
432    struct exec_node *node;
433 
434    for (node = list->head_sentinel.next; node->next != NULL; node = node->next) {
435       size++;
436    }
437 
438    return size;
439 }
440 
441 static inline void
exec_list_push_head(struct exec_list * list,struct exec_node * n)442 exec_list_push_head(struct exec_list *list, struct exec_node *n)
443 {
444    n->next = list->head_sentinel.next;
445    n->prev = &list->head_sentinel;
446 
447    n->next->prev = n;
448    list->head_sentinel.next = n;
449 }
450 
451 static inline void
exec_list_push_tail(struct exec_list * list,struct exec_node * n)452 exec_list_push_tail(struct exec_list *list, struct exec_node *n)
453 {
454    n->next = &list->tail_sentinel;
455    n->prev = list->tail_sentinel.prev;
456 
457    n->prev->next = n;
458    list->tail_sentinel.prev = n;
459 }
460 
461 static inline void
exec_list_push_degenerate_list_at_head(struct exec_list * list,struct exec_node * n)462 exec_list_push_degenerate_list_at_head(struct exec_list *list, struct exec_node *n)
463 {
464    assert(n->prev->next == n);
465 
466    n->prev->next = list->head_sentinel.next;
467    list->head_sentinel.next->prev = n->prev;
468    n->prev = &list->head_sentinel;
469    list->head_sentinel.next = n;
470 }
471 
472 static inline struct exec_node *
exec_list_pop_head(struct exec_list * list)473 exec_list_pop_head(struct exec_list *list)
474 {
475    struct exec_node *const n = exec_list_get_head(list);
476    if (n != NULL)
477       exec_node_remove(n);
478 
479    return n;
480 }
481 
482 static inline void
exec_list_move_nodes_to(struct exec_list * list,struct exec_list * target)483 exec_list_move_nodes_to(struct exec_list *list, struct exec_list *target)
484 {
485    if (exec_list_is_empty(list)) {
486       exec_list_make_empty(target);
487    } else {
488       target->head_sentinel.next = list->head_sentinel.next;
489       target->head_sentinel.prev = NULL;
490       target->tail_sentinel.next = NULL;
491       target->tail_sentinel.prev = list->tail_sentinel.prev;
492 
493       target->head_sentinel.next->prev = &target->head_sentinel;
494       target->tail_sentinel.prev->next = &target->tail_sentinel;
495 
496       exec_list_make_empty(list);
497    }
498 }
499 
500 static inline void
exec_list_append(struct exec_list * list,struct exec_list * source)501 exec_list_append(struct exec_list *list, struct exec_list *source)
502 {
503    if (exec_list_is_empty(source))
504       return;
505 
506    /* Link the first node of the source with the last node of the target list.
507     */
508    list->tail_sentinel.prev->next = source->head_sentinel.next;
509    source->head_sentinel.next->prev = list->tail_sentinel.prev;
510 
511    /* Make the tail of the source list be the tail of the target list.
512     */
513    list->tail_sentinel.prev = source->tail_sentinel.prev;
514    list->tail_sentinel.prev->next = &list->tail_sentinel;
515 
516    /* Make the source list empty for good measure.
517     */
518    exec_list_make_empty(source);
519 }
520 
521 static inline void
exec_node_insert_list_after(struct exec_node * n,struct exec_list * after)522 exec_node_insert_list_after(struct exec_node *n, struct exec_list *after)
523 {
524    if (exec_list_is_empty(after))
525       return;
526 
527    after->tail_sentinel.prev->next = n->next;
528    after->head_sentinel.next->prev = n;
529 
530    n->next->prev = after->tail_sentinel.prev;
531    n->next = after->head_sentinel.next;
532 
533    exec_list_make_empty(after);
534 }
535 
536 static inline void
exec_list_prepend(struct exec_list * list,struct exec_list * source)537 exec_list_prepend(struct exec_list *list, struct exec_list *source)
538 {
539    exec_list_append(source, list);
540    exec_list_move_nodes_to(source, list);
541 }
542 
543 static inline void
exec_node_insert_list_before(struct exec_node * n,struct exec_list * before)544 exec_node_insert_list_before(struct exec_node *n, struct exec_list *before)
545 {
546    if (exec_list_is_empty(before))
547       return;
548 
549    before->tail_sentinel.prev->next = n;
550    before->head_sentinel.next->prev = n->prev;
551 
552    n->prev->next = before->head_sentinel.next;
553    n->prev = before->tail_sentinel.prev;
554 
555    exec_list_make_empty(before);
556 }
557 
558 static inline void
exec_list_validate(const struct exec_list * list)559 exec_list_validate(const struct exec_list *list)
560 {
561    const struct exec_node *node;
562 
563    assert(list->head_sentinel.next->prev == &list->head_sentinel);
564    assert(list->head_sentinel.prev == NULL);
565    assert(list->tail_sentinel.next == NULL);
566    assert(list->tail_sentinel.prev->next == &list->tail_sentinel);
567 
568    /* We could try to use one of the interators below for this but they all
569     * either require C++ or assume the exec_node is embedded in a structure
570     * which is not the case for this function.
571     */
572    for (node = list->head_sentinel.next; node->next != NULL; node = node->next) {
573       assert(node->next->prev == node);
574       assert(node->prev->next == node);
575    }
576 }
577 
578 #ifdef __cplusplus
make_empty()579 inline void exec_list::make_empty()
580 {
581    exec_list_make_empty(this);
582 }
583 
is_empty()584 inline bool exec_list::is_empty() const
585 {
586    return exec_list_is_empty(this);
587 }
588 
get_head()589 inline const exec_node *exec_list::get_head() const
590 {
591    return exec_list_get_head_const(this);
592 }
593 
get_head()594 inline exec_node *exec_list::get_head()
595 {
596    return exec_list_get_head(this);
597 }
598 
get_head_raw()599 inline const exec_node *exec_list::get_head_raw() const
600 {
601    return exec_list_get_head_raw_const(this);
602 }
603 
get_head_raw()604 inline exec_node *exec_list::get_head_raw()
605 {
606    return exec_list_get_head_raw(this);
607 }
608 
get_tail()609 inline const exec_node *exec_list::get_tail() const
610 {
611    return exec_list_get_tail_const(this);
612 }
613 
get_tail()614 inline exec_node *exec_list::get_tail()
615 {
616    return exec_list_get_tail(this);
617 }
618 
get_tail_raw()619 inline const exec_node *exec_list::get_tail_raw() const
620 {
621    return exec_list_get_tail_raw_const(this);
622 }
623 
get_tail_raw()624 inline exec_node *exec_list::get_tail_raw()
625 {
626    return exec_list_get_tail_raw(this);
627 }
628 
length()629 inline unsigned exec_list::length() const
630 {
631    return exec_list_length(this);
632 }
633 
push_head(exec_node * n)634 inline void exec_list::push_head(exec_node *n)
635 {
636    exec_list_push_head(this, n);
637 }
638 
push_tail(exec_node * n)639 inline void exec_list::push_tail(exec_node *n)
640 {
641    exec_list_push_tail(this, n);
642 }
643 
push_degenerate_list_at_head(exec_node * n)644 inline void exec_list::push_degenerate_list_at_head(exec_node *n)
645 {
646    exec_list_push_degenerate_list_at_head(this, n);
647 }
648 
pop_head()649 inline exec_node *exec_list::pop_head()
650 {
651    return exec_list_pop_head(this);
652 }
653 
move_nodes_to(exec_list * target)654 inline void exec_list::move_nodes_to(exec_list *target)
655 {
656    exec_list_move_nodes_to(this, target);
657 }
658 
append_list(exec_list * source)659 inline void exec_list::append_list(exec_list *source)
660 {
661    exec_list_append(this, source);
662 }
663 
insert_after(exec_list * after)664 inline void exec_node::insert_after(exec_list *after)
665 {
666    exec_node_insert_list_after(this, after);
667 }
668 
prepend_list(exec_list * source)669 inline void exec_list::prepend_list(exec_list *source)
670 {
671    exec_list_prepend(this, source);
672 }
673 
insert_before(exec_list * before)674 inline void exec_node::insert_before(exec_list *before)
675 {
676    exec_node_insert_list_before(this, before);
677 }
678 #endif
679 
680 #define exec_node_typed_forward(__node, __type) \
681    (!exec_node_is_tail_sentinel(__node) ? (__type) (__node) : NULL)
682 
683 #define exec_node_typed_backward(__node, __type) \
684    (!exec_node_is_head_sentinel(__node) ? (__type) (__node) : NULL)
685 
686 #define foreach_in_list(__type, __inst, __list)                                           \
687    for (__type *__inst = exec_node_typed_forward((__list)->head_sentinel.next, __type *); \
688         (__inst) != NULL;                                                                 \
689         (__inst) = exec_node_typed_forward((__inst)->next, __type *))
690 
691 #define foreach_in_list_reverse(__type, __inst, __list)                                      \
692    for (__type *__inst = exec_node_typed_backward((__list)->tail_sentinel.prev, __type *);   \
693         (__inst) != NULL;                                                                    \
694         (__inst) = exec_node_typed_backward((__inst)->prev, __type *))
695 
696 /**
697  * This version is safe even if the current node is removed.
698  */
699 
700 #define foreach_in_list_safe(__type, __node, __list)                                                              \
701    for (__type *__node = exec_node_typed_forward((__list)->head_sentinel.next, __type *),                         \
702                *__next = (__node) ? exec_node_typed_forward((__list)->head_sentinel.next->next, __type *) : NULL; \
703         (__node) != NULL;                                                                                         \
704         (__node) = __next, __next = __next ? exec_node_typed_forward(__next->next, __type *) : NULL)
705 
706 #define foreach_in_list_reverse_safe(__type, __node, __list)                                                        \
707    for (__type *__node = exec_node_typed_backward((__list)->tail_sentinel.prev, __type *),                          \
708                *__prev = (__node) ? exec_node_typed_backward((__list)->tail_sentinel.prev->prev, __type *) : NULL;  \
709         (__node) != NULL;                                                                                           \
710         (__node) = __prev, __prev = __prev ? exec_node_typed_backward(__prev->prev, __type *) : NULL)
711 
712 #define foreach_in_list_use_after(__type, __inst, __list)                           \
713    __type *__inst;                                                                  \
714    for ((__inst) = exec_node_typed_forward((__list)->head_sentinel.next, __type *); \
715         (__inst) != NULL;                                                           \
716         (__inst) = exec_node_typed_forward((__inst)->next, __type *))
717 
718 /**
719  * Iterate through two lists at once.  Stops at the end of the shorter list.
720  *
721  * This is safe against either current node being removed or replaced.
722  */
723 #define foreach_two_lists(__node1, __list1, __node2, __list2) \
724    for (struct exec_node * __node1 = (__list1)->head_sentinel.next, \
725                          * __node2 = (__list2)->head_sentinel.next, \
726                          * __next1 = __node1->next,           \
727                          * __next2 = __node2->next            \
728 	; __next1 != NULL && __next2 != NULL                  \
729 	; __node1 = __next1,                                  \
730           __node2 = __next2,                                  \
731           __next1 = __next1->next,                            \
732           __next2 = __next2->next)
733 
734 #define exec_node_data_forward(type, node, field) \
735    (!exec_node_is_tail_sentinel(node) ? exec_node_data(type, node, field) : NULL)
736 
737 #define exec_node_data_backward(type, node, field) \
738    (!exec_node_is_head_sentinel(node) ? exec_node_data(type, node, field) : NULL)
739 
740 #define foreach_list_typed(__type, __node, __field, __list)                     \
741    for (__type * __node =                                                       \
742          exec_node_data_forward(__type, (__list)->head_sentinel.next, __field); \
743    (__node) != NULL;                                                            \
744    (__node) = exec_node_data_forward(__type, (__node)->__field.next, __field))
745 
746 #define foreach_list_typed_from(__type, __node, __field, __list, __start)        \
747    for (__type * __node = exec_node_data_forward(__type, (__start), __field);    \
748    (__node) != NULL;                                                             \
749    (__node) = exec_node_data_forward(__type, (__node)->__field.next, __field))
750 
751 #define foreach_list_typed_reverse(__type, __node, __field, __list)                 \
752    for (__type * __node =                                                           \
753            exec_node_data_backward(__type, (__list)->tail_sentinel.prev, __field);  \
754         (__node) != NULL;                                                           \
755         (__node) = exec_node_data_backward(__type, (__node)->__field.prev, __field))
756 
757 #define foreach_list_typed_safe(__type, __node, __field, __list)                    \
758    for (__type * __node =                                                           \
759            exec_node_data_forward(__type, (__list)->head_sentinel.next, __field),   \
760                * __next = (__node) ?                                                \
761            exec_node_data_forward(__type, (__node)->__field.next, __field) : NULL;  \
762         (__node) != NULL;                                                           \
763         (__node) = __next, __next = (__next && (__next)->__field.next) ?            \
764            exec_node_data_forward(__type, (__next)->__field.next, __field) : NULL)
765 
766 #define foreach_list_typed_reverse_safe(__type, __node, __field, __list)            \
767    for (__type * __node =                                                           \
768            exec_node_data_backward(__type, (__list)->tail_sentinel.prev, __field),  \
769                * __prev = (__node) ?                                                \
770            exec_node_data_backward(__type, (__node)->__field.prev, __field) : NULL; \
771         (__node) != NULL;                                                           \
772         (__node) = __prev, __prev = (__prev && (__prev)->__field.prev) ?            \
773            exec_node_data_backward(__type, (__prev)->__field.prev, __field) : NULL)
774 
775 #endif /* LIST_CONTAINER_H */
776