• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.  If you
265  * are using virtual inheritance, you deserve a slow and painful death.  Enjoy!
266  */
267 #define exec_list_offsetof(t, f, p) \
268    (((char *) &((t *) p)->f) - ((char *) p))
269 #else
270 #define exec_list_offsetof(t, f, p) offsetof(t, f)
271 #endif
272 
273 /**
274  * Get a pointer to the structure containing an exec_node
275  *
276  * Given a pointer to an \c exec_node embedded in a structure, get a pointer to
277  * the containing structure.
278  *
279  * \param type  Base type of the structure containing the node
280  * \param node  Pointer to the \c exec_node
281  * \param field Name of the field in \c type that is the embedded \c exec_node
282  */
283 #define exec_node_data(type, node, field) \
284    ((type *) (((uintptr_t) node) - exec_list_offsetof(type, field, node)))
285 
286 #ifdef __cplusplus
287 struct exec_node;
288 #endif
289 
290 struct exec_list {
291    struct exec_node head_sentinel;
292    struct exec_node tail_sentinel;
293 
294 #ifdef __cplusplus
295    DECLARE_RALLOC_CXX_OPERATORS(exec_list)
296 
exec_listexec_list297    exec_list()
298    {
299       make_empty();
300    }
301 
302    void make_empty();
303 
304    bool is_empty() const;
305 
306    const exec_node *get_head() const;
307    exec_node *get_head();
308    const exec_node *get_head_raw() const;
309    exec_node *get_head_raw();
310 
311    const exec_node *get_tail() const;
312    exec_node *get_tail();
313    const exec_node *get_tail_raw() const;
314    exec_node *get_tail_raw();
315 
316    unsigned length() const;
317 
318    void push_head(exec_node *n);
319    void push_tail(exec_node *n);
320    void push_degenerate_list_at_head(exec_node *n);
321 
322    /**
323     * Remove the first node from a list and return it
324     *
325     * \return
326     * The first node in the list or \c NULL if the list is empty.
327     *
328     * \sa exec_list::get_head
329     */
330    exec_node *pop_head();
331 
332    /**
333     * Move all of the nodes from this list to the target list
334     */
335    void move_nodes_to(exec_list *target);
336 
337    /**
338     * Append all nodes from the source list to the end of the target list
339     */
340    void append_list(exec_list *source);
341 
342    /**
343     * Prepend all nodes from the source list to the beginning of the target
344     * list
345     */
346    void prepend_list(exec_list *source);
347 #endif
348 };
349 
350 static inline void
exec_list_make_empty(struct exec_list * list)351 exec_list_make_empty(struct exec_list *list)
352 {
353    list->head_sentinel.next = &list->tail_sentinel;
354    list->head_sentinel.prev = NULL;
355    list->tail_sentinel.next = NULL;
356    list->tail_sentinel.prev = &list->head_sentinel;
357 }
358 
359 static inline bool
exec_list_is_empty(const struct exec_list * list)360 exec_list_is_empty(const struct exec_list *list)
361 {
362    /* There are three ways to test whether a list is empty or not.
363     *
364     * - Check to see if the head sentinel's \c next is the tail sentinel.
365     * - Check to see if the tail sentinel's \c prev is the head sentinel.
366     * - Check to see if the head is the sentinel node by test whether its
367     *   \c next pointer is \c NULL.
368     *
369     * The first two methods tend to generate better code on modern systems
370     * because they save a pointer dereference.
371     */
372    return list->head_sentinel.next == &list->tail_sentinel;
373 }
374 
375 static inline bool
exec_list_is_singular(const struct exec_list * list)376 exec_list_is_singular(const struct exec_list *list)
377 {
378    return !exec_list_is_empty(list) &&
379           list->head_sentinel.next->next == &list->tail_sentinel;
380 }
381 
382 static inline const struct exec_node *
exec_list_get_head_const(const struct exec_list * list)383 exec_list_get_head_const(const struct exec_list *list)
384 {
385    return !exec_list_is_empty(list) ? list->head_sentinel.next : NULL;
386 }
387 
388 static inline struct exec_node *
exec_list_get_head(struct exec_list * list)389 exec_list_get_head(struct exec_list *list)
390 {
391    return !exec_list_is_empty(list) ? list->head_sentinel.next : NULL;
392 }
393 
394 static inline const struct exec_node *
exec_list_get_head_raw_const(const struct exec_list * list)395 exec_list_get_head_raw_const(const struct exec_list *list)
396 {
397    return list->head_sentinel.next;
398 }
399 
400 static inline struct exec_node *
exec_list_get_head_raw(struct exec_list * list)401 exec_list_get_head_raw(struct exec_list *list)
402 {
403    return list->head_sentinel.next;
404 }
405 
406 static inline const struct exec_node *
exec_list_get_tail_const(const struct exec_list * list)407 exec_list_get_tail_const(const struct exec_list *list)
408 {
409    return !exec_list_is_empty(list) ? list->tail_sentinel.prev : NULL;
410 }
411 
412 static inline struct exec_node *
exec_list_get_tail(struct exec_list * list)413 exec_list_get_tail(struct exec_list *list)
414 {
415    return !exec_list_is_empty(list) ? list->tail_sentinel.prev : NULL;
416 }
417 
418 static inline const struct exec_node *
exec_list_get_tail_raw_const(const struct exec_list * list)419 exec_list_get_tail_raw_const(const struct exec_list *list)
420 {
421    return list->tail_sentinel.prev;
422 }
423 
424 static inline struct exec_node *
exec_list_get_tail_raw(struct exec_list * list)425 exec_list_get_tail_raw(struct exec_list *list)
426 {
427    return list->tail_sentinel.prev;
428 }
429 
430 static inline unsigned
exec_list_length(const struct exec_list * list)431 exec_list_length(const struct exec_list *list)
432 {
433    unsigned size = 0;
434    struct exec_node *node;
435 
436    for (node = list->head_sentinel.next; node->next != NULL; node = node->next) {
437       size++;
438    }
439 
440    return size;
441 }
442 
443 static inline void
exec_list_push_head(struct exec_list * list,struct exec_node * n)444 exec_list_push_head(struct exec_list *list, struct exec_node *n)
445 {
446    n->next = list->head_sentinel.next;
447    n->prev = &list->head_sentinel;
448 
449    n->next->prev = n;
450    list->head_sentinel.next = n;
451 }
452 
453 static inline void
exec_list_push_tail(struct exec_list * list,struct exec_node * n)454 exec_list_push_tail(struct exec_list *list, struct exec_node *n)
455 {
456    n->next = &list->tail_sentinel;
457    n->prev = list->tail_sentinel.prev;
458 
459    n->prev->next = n;
460    list->tail_sentinel.prev = n;
461 }
462 
463 static inline void
exec_list_push_degenerate_list_at_head(struct exec_list * list,struct exec_node * n)464 exec_list_push_degenerate_list_at_head(struct exec_list *list, struct exec_node *n)
465 {
466    assert(n->prev->next == n);
467 
468    n->prev->next = list->head_sentinel.next;
469    list->head_sentinel.next->prev = n->prev;
470    n->prev = &list->head_sentinel;
471    list->head_sentinel.next = n;
472 }
473 
474 static inline struct exec_node *
exec_list_pop_head(struct exec_list * list)475 exec_list_pop_head(struct exec_list *list)
476 {
477    struct exec_node *const n = exec_list_get_head(list);
478    if (n != NULL)
479       exec_node_remove(n);
480 
481    return n;
482 }
483 
484 static inline void
exec_list_move_nodes_to(struct exec_list * list,struct exec_list * target)485 exec_list_move_nodes_to(struct exec_list *list, struct exec_list *target)
486 {
487    if (exec_list_is_empty(list)) {
488       exec_list_make_empty(target);
489    } else {
490       target->head_sentinel.next = list->head_sentinel.next;
491       target->head_sentinel.prev = NULL;
492       target->tail_sentinel.next = NULL;
493       target->tail_sentinel.prev = list->tail_sentinel.prev;
494 
495       target->head_sentinel.next->prev = &target->head_sentinel;
496       target->tail_sentinel.prev->next = &target->tail_sentinel;
497 
498       exec_list_make_empty(list);
499    }
500 }
501 
502 static inline void
exec_list_append(struct exec_list * list,struct exec_list * source)503 exec_list_append(struct exec_list *list, struct exec_list *source)
504 {
505    if (exec_list_is_empty(source))
506       return;
507 
508    /* Link the first node of the source with the last node of the target list.
509     */
510    list->tail_sentinel.prev->next = source->head_sentinel.next;
511    source->head_sentinel.next->prev = list->tail_sentinel.prev;
512 
513    /* Make the tail of the source list be the tail of the target list.
514     */
515    list->tail_sentinel.prev = source->tail_sentinel.prev;
516    list->tail_sentinel.prev->next = &list->tail_sentinel;
517 
518    /* Make the source list empty for good measure.
519     */
520    exec_list_make_empty(source);
521 }
522 
523 static inline void
exec_node_insert_list_after(struct exec_node * n,struct exec_list * after)524 exec_node_insert_list_after(struct exec_node *n, struct exec_list *after)
525 {
526    if (exec_list_is_empty(after))
527       return;
528 
529    after->tail_sentinel.prev->next = n->next;
530    after->head_sentinel.next->prev = n;
531 
532    n->next->prev = after->tail_sentinel.prev;
533    n->next = after->head_sentinel.next;
534 
535    exec_list_make_empty(after);
536 }
537 
538 static inline void
exec_list_prepend(struct exec_list * list,struct exec_list * source)539 exec_list_prepend(struct exec_list *list, struct exec_list *source)
540 {
541    exec_list_append(source, list);
542    exec_list_move_nodes_to(source, list);
543 }
544 
545 static inline void
exec_node_insert_list_before(struct exec_node * n,struct exec_list * before)546 exec_node_insert_list_before(struct exec_node *n, struct exec_list *before)
547 {
548    if (exec_list_is_empty(before))
549       return;
550 
551    before->tail_sentinel.prev->next = n;
552    before->head_sentinel.next->prev = n->prev;
553 
554    n->prev->next = before->head_sentinel.next;
555    n->prev = before->tail_sentinel.prev;
556 
557    exec_list_make_empty(before);
558 }
559 
560 static inline void
exec_list_validate(const struct exec_list * list)561 exec_list_validate(const struct exec_list *list)
562 {
563    const struct exec_node *node;
564 
565    assert(list->head_sentinel.next->prev == &list->head_sentinel);
566    assert(list->head_sentinel.prev == NULL);
567    assert(list->tail_sentinel.next == NULL);
568    assert(list->tail_sentinel.prev->next == &list->tail_sentinel);
569 
570    /* We could try to use one of the interators below for this but they all
571     * either require C++ or assume the exec_node is embedded in a structure
572     * which is not the case for this function.
573     */
574    for (node = list->head_sentinel.next; node->next != NULL; node = node->next) {
575       assert(node->next->prev == node);
576       assert(node->prev->next == node);
577    }
578 }
579 
580 #ifdef __cplusplus
make_empty()581 inline void exec_list::make_empty()
582 {
583    exec_list_make_empty(this);
584 }
585 
is_empty()586 inline bool exec_list::is_empty() const
587 {
588    return exec_list_is_empty(this);
589 }
590 
get_head()591 inline const exec_node *exec_list::get_head() const
592 {
593    return exec_list_get_head_const(this);
594 }
595 
get_head()596 inline exec_node *exec_list::get_head()
597 {
598    return exec_list_get_head(this);
599 }
600 
get_head_raw()601 inline const exec_node *exec_list::get_head_raw() const
602 {
603    return exec_list_get_head_raw_const(this);
604 }
605 
get_head_raw()606 inline exec_node *exec_list::get_head_raw()
607 {
608    return exec_list_get_head_raw(this);
609 }
610 
get_tail()611 inline const exec_node *exec_list::get_tail() const
612 {
613    return exec_list_get_tail_const(this);
614 }
615 
get_tail()616 inline exec_node *exec_list::get_tail()
617 {
618    return exec_list_get_tail(this);
619 }
620 
get_tail_raw()621 inline const exec_node *exec_list::get_tail_raw() const
622 {
623    return exec_list_get_tail_raw_const(this);
624 }
625 
get_tail_raw()626 inline exec_node *exec_list::get_tail_raw()
627 {
628    return exec_list_get_tail_raw(this);
629 }
630 
length()631 inline unsigned exec_list::length() const
632 {
633    return exec_list_length(this);
634 }
635 
push_head(exec_node * n)636 inline void exec_list::push_head(exec_node *n)
637 {
638    exec_list_push_head(this, n);
639 }
640 
push_tail(exec_node * n)641 inline void exec_list::push_tail(exec_node *n)
642 {
643    exec_list_push_tail(this, n);
644 }
645 
push_degenerate_list_at_head(exec_node * n)646 inline void exec_list::push_degenerate_list_at_head(exec_node *n)
647 {
648    exec_list_push_degenerate_list_at_head(this, n);
649 }
650 
pop_head()651 inline exec_node *exec_list::pop_head()
652 {
653    return exec_list_pop_head(this);
654 }
655 
move_nodes_to(exec_list * target)656 inline void exec_list::move_nodes_to(exec_list *target)
657 {
658    exec_list_move_nodes_to(this, target);
659 }
660 
append_list(exec_list * source)661 inline void exec_list::append_list(exec_list *source)
662 {
663    exec_list_append(this, source);
664 }
665 
insert_after(exec_list * after)666 inline void exec_node::insert_after(exec_list *after)
667 {
668    exec_node_insert_list_after(this, after);
669 }
670 
prepend_list(exec_list * source)671 inline void exec_list::prepend_list(exec_list *source)
672 {
673    exec_list_prepend(this, source);
674 }
675 
insert_before(exec_list * before)676 inline void exec_node::insert_before(exec_list *before)
677 {
678    exec_node_insert_list_before(this, before);
679 }
680 #endif
681 
682 #define exec_node_typed_forward(__node, __type) \
683    (!exec_node_is_tail_sentinel(__node) ? (__type) (__node) : NULL)
684 
685 #define exec_node_typed_backward(__node, __type) \
686    (!exec_node_is_head_sentinel(__node) ? (__type) (__node) : NULL)
687 
688 #define foreach_in_list(__type, __inst, __list)                                           \
689    for (__type *__inst = exec_node_typed_forward((__list)->head_sentinel.next, __type *); \
690         (__inst) != NULL;                                                                 \
691         (__inst) = exec_node_typed_forward((__inst)->next, __type *))
692 
693 #define foreach_in_list_reverse(__type, __inst, __list)                                      \
694    for (__type *__inst = exec_node_typed_backward((__list)->tail_sentinel.prev, __type *);   \
695         (__inst) != NULL;                                                                    \
696         (__inst) = exec_node_typed_backward((__inst)->prev, __type *))
697 
698 /**
699  * This version is safe even if the current node is removed.
700  */
701 
702 #define foreach_in_list_safe(__type, __node, __list)                                                              \
703    for (__type *__node = exec_node_typed_forward((__list)->head_sentinel.next, __type *),                         \
704                *__next = (__node) ? exec_node_typed_forward((__list)->head_sentinel.next->next, __type *) : NULL; \
705         (__node) != NULL;                                                                                         \
706         (__node) = __next, __next = __next ? exec_node_typed_forward(__next->next, __type *) : NULL)
707 
708 #define foreach_in_list_reverse_safe(__type, __node, __list)                                                        \
709    for (__type *__node = exec_node_typed_backward((__list)->tail_sentinel.prev, __type *),                          \
710                *__prev = (__node) ? exec_node_typed_backward((__list)->tail_sentinel.prev->prev, __type *) : NULL;  \
711         (__node) != NULL;                                                                                           \
712         (__node) = __prev, __prev = __prev ? exec_node_typed_backward(__prev->prev, __type *) : NULL)
713 
714 #define foreach_in_list_use_after(__type, __inst, __list)                           \
715    __type *__inst;                                                                  \
716    for ((__inst) = exec_node_typed_forward((__list)->head_sentinel.next, __type *); \
717         (__inst) != NULL;                                                           \
718         (__inst) = exec_node_typed_forward((__inst)->next, __type *))
719 
720 /**
721  * Iterate through two lists at once.  Stops at the end of the shorter list.
722  *
723  * This is safe against either current node being removed or replaced.
724  */
725 #define foreach_two_lists(__node1, __list1, __node2, __list2) \
726    for (struct exec_node * __node1 = (__list1)->head_sentinel.next, \
727                          * __node2 = (__list2)->head_sentinel.next, \
728                          * __next1 = __node1->next,           \
729                          * __next2 = __node2->next            \
730 	; __next1 != NULL && __next2 != NULL                  \
731 	; __node1 = __next1,                                  \
732           __node2 = __next2,                                  \
733           __next1 = __next1->next,                            \
734           __next2 = __next2->next)
735 
736 #define exec_node_data_forward(type, node, field) \
737    (!exec_node_is_tail_sentinel(node) ? exec_node_data(type, node, field) : NULL)
738 
739 #define exec_node_data_backward(type, node, field) \
740    (!exec_node_is_head_sentinel(node) ? exec_node_data(type, node, field) : NULL)
741 
742 #define foreach_list_typed(__type, __node, __field, __list)                     \
743    for (__type * __node =                                                       \
744          exec_node_data_forward(__type, (__list)->head_sentinel.next, __field); \
745    (__node) != NULL;                                                            \
746    (__node) = exec_node_data_forward(__type, (__node)->__field.next, __field))
747 
748 #define foreach_list_typed_from(__type, __node, __field, __list, __start)        \
749    for (__type * __node = exec_node_data_forward(__type, (__start), __field);    \
750    (__node) != NULL;                                                             \
751    (__node) = exec_node_data_forward(__type, (__node)->__field.next, __field))
752 
753 #define foreach_list_typed_reverse(__type, __node, __field, __list)                 \
754    for (__type * __node =                                                           \
755            exec_node_data_backward(__type, (__list)->tail_sentinel.prev, __field);  \
756         (__node) != NULL;                                                           \
757         (__node) = exec_node_data_backward(__type, (__node)->__field.prev, __field))
758 
759 #define foreach_list_typed_safe(__type, __node, __field, __list)                    \
760    for (__type * __node =                                                           \
761            exec_node_data_forward(__type, (__list)->head_sentinel.next, __field),   \
762                * __next = (__node) ?                                                \
763            exec_node_data_forward(__type, (__node)->__field.next, __field) : NULL;  \
764         (__node) != NULL;                                                           \
765         (__node) = __next, __next = (__next && (__next)->__field.next) ?            \
766            exec_node_data_forward(__type, (__next)->__field.next, __field) : NULL)
767 
768 #define foreach_list_typed_reverse_safe(__type, __node, __field, __list)            \
769    for (__type * __node =                                                           \
770            exec_node_data_backward(__type, (__list)->tail_sentinel.prev, __field),  \
771                * __prev = (__node) ?                                                \
772            exec_node_data_backward(__type, (__node)->__field.prev, __field) : NULL; \
773         (__node) != NULL;                                                           \
774         (__node) = __prev, __prev = (__prev && (__prev)->__field.prev) ?            \
775            exec_node_data_backward(__type, (__prev)->__field.prev, __field) : NULL)
776 
777 #endif /* LIST_CONTAINER_H */
778