101e04c3fSmrg/*
201e04c3fSmrg * Copyright © 2008, 2010 Intel Corporation
301e04c3fSmrg *
401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
501e04c3fSmrg * copy of this software and associated documentation files (the "Software"),
601e04c3fSmrg * to deal in the Software without restriction, including without limitation
701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the
901e04c3fSmrg * Software is furnished to do so, subject to the following conditions:
1001e04c3fSmrg *
1101e04c3fSmrg * The above copyright notice and this permission notice (including the next
1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the
1301e04c3fSmrg * Software.
1401e04c3fSmrg *
1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2101e04c3fSmrg * DEALINGS IN THE SOFTWARE.
2201e04c3fSmrg */
2301e04c3fSmrg
2401e04c3fSmrg/**
2501e04c3fSmrg * \file list.h
2601e04c3fSmrg * \brief Doubly-linked list abstract container type.
2701e04c3fSmrg *
2801e04c3fSmrg * Each doubly-linked list has a sentinel head and tail node.  These nodes
2901e04c3fSmrg * contain no data.  The head sentinel can be identified by its \c prev
3001e04c3fSmrg * pointer being \c NULL.  The tail sentinel can be identified by its
3101e04c3fSmrg * \c next pointer being \c NULL.
3201e04c3fSmrg *
3301e04c3fSmrg * A list is empty if either the head sentinel's \c next pointer points to the
3401e04c3fSmrg * tail sentinel or the tail sentinel's \c prev poiner points to the head
3501e04c3fSmrg * sentinel. The head sentinel and tail sentinel nodes are allocated within the
3601e04c3fSmrg * list structure.
3701e04c3fSmrg *
3801e04c3fSmrg * Do note that this means that the list nodes will contain pointers into the
3901e04c3fSmrg * list structure itself and as a result you may not \c realloc() an  \c
4001e04c3fSmrg * exec_list or any structure in which an \c exec_list is embedded.
4101e04c3fSmrg */
4201e04c3fSmrg
4301e04c3fSmrg#ifndef LIST_CONTAINER_H
4401e04c3fSmrg#define LIST_CONTAINER_H
4501e04c3fSmrg
4601e04c3fSmrg#ifndef __cplusplus
4701e04c3fSmrg#include <stddef.h>
4801e04c3fSmrg#endif
4901e04c3fSmrg#include <assert.h>
5001e04c3fSmrg
5101e04c3fSmrg#include "util/ralloc.h"
5201e04c3fSmrg
5301e04c3fSmrgstruct exec_node {
5401e04c3fSmrg   struct exec_node *next;
5501e04c3fSmrg   struct exec_node *prev;
5601e04c3fSmrg
5701e04c3fSmrg#ifdef __cplusplus
5801e04c3fSmrg   DECLARE_RZALLOC_CXX_OPERATORS(exec_node)
5901e04c3fSmrg
6001e04c3fSmrg   exec_node() : next(NULL), prev(NULL)
6101e04c3fSmrg   {
6201e04c3fSmrg      /* empty */
6301e04c3fSmrg   }
6401e04c3fSmrg
6501e04c3fSmrg   const exec_node *get_next() const;
6601e04c3fSmrg   exec_node *get_next();
6701e04c3fSmrg
6801e04c3fSmrg   const exec_node *get_prev() const;
6901e04c3fSmrg   exec_node *get_prev();
7001e04c3fSmrg
7101e04c3fSmrg   void remove();
7201e04c3fSmrg
7301e04c3fSmrg   /**
7401e04c3fSmrg    * Link a node with itself
7501e04c3fSmrg    *
7601e04c3fSmrg    * This creates a sort of degenerate list that is occasionally useful.
7701e04c3fSmrg    */
7801e04c3fSmrg   void self_link();
7901e04c3fSmrg
8001e04c3fSmrg   /**
8101e04c3fSmrg    * Insert a node in the list after the current node
8201e04c3fSmrg    */
8301e04c3fSmrg   void insert_after(exec_node *after);
84993e1d59Smrg
85993e1d59Smrg   /**
86993e1d59Smrg    * Insert another list in the list after the current node
87993e1d59Smrg    */
88993e1d59Smrg   void insert_after(struct exec_list *after);
89993e1d59Smrg
9001e04c3fSmrg   /**
9101e04c3fSmrg    * Insert a node in the list before the current node
9201e04c3fSmrg    */
9301e04c3fSmrg   void insert_before(exec_node *before);
9401e04c3fSmrg
9501e04c3fSmrg   /**
9601e04c3fSmrg    * Insert another list in the list before the current node
9701e04c3fSmrg    */
9801e04c3fSmrg   void insert_before(struct exec_list *before);
9901e04c3fSmrg
10001e04c3fSmrg   /**
10101e04c3fSmrg    * Replace the current node with the given node.
10201e04c3fSmrg    */
10301e04c3fSmrg   void replace_with(exec_node *replacement);
10401e04c3fSmrg
10501e04c3fSmrg   /**
10601e04c3fSmrg    * Is this the sentinel at the tail of the list?
10701e04c3fSmrg    */
10801e04c3fSmrg   bool is_tail_sentinel() const;
10901e04c3fSmrg
11001e04c3fSmrg   /**
11101e04c3fSmrg    * Is this the sentinel at the head of the list?
11201e04c3fSmrg    */
11301e04c3fSmrg   bool is_head_sentinel() const;
11401e04c3fSmrg#endif
11501e04c3fSmrg};
11601e04c3fSmrg
11701e04c3fSmrgstatic inline void
11801e04c3fSmrgexec_node_init(struct exec_node *n)
11901e04c3fSmrg{
12001e04c3fSmrg   n->next = NULL;
12101e04c3fSmrg   n->prev = NULL;
12201e04c3fSmrg}
12301e04c3fSmrg
12401e04c3fSmrgstatic inline const struct exec_node *
12501e04c3fSmrgexec_node_get_next_const(const struct exec_node *n)
12601e04c3fSmrg{
12701e04c3fSmrg   return n->next;
12801e04c3fSmrg}
12901e04c3fSmrg
13001e04c3fSmrgstatic inline struct exec_node *
13101e04c3fSmrgexec_node_get_next(struct exec_node *n)
13201e04c3fSmrg{
13301e04c3fSmrg   return n->next;
13401e04c3fSmrg}
13501e04c3fSmrg
13601e04c3fSmrgstatic inline const struct exec_node *
13701e04c3fSmrgexec_node_get_prev_const(const struct exec_node *n)
13801e04c3fSmrg{
13901e04c3fSmrg   return n->prev;
14001e04c3fSmrg}
14101e04c3fSmrg
14201e04c3fSmrgstatic inline struct exec_node *
14301e04c3fSmrgexec_node_get_prev(struct exec_node *n)
14401e04c3fSmrg{
14501e04c3fSmrg   return n->prev;
14601e04c3fSmrg}
14701e04c3fSmrg
14801e04c3fSmrgstatic inline void
14901e04c3fSmrgexec_node_remove(struct exec_node *n)
15001e04c3fSmrg{
15101e04c3fSmrg   n->next->prev = n->prev;
15201e04c3fSmrg   n->prev->next = n->next;
15301e04c3fSmrg   n->next = NULL;
15401e04c3fSmrg   n->prev = NULL;
15501e04c3fSmrg}
15601e04c3fSmrg
15701e04c3fSmrgstatic inline void
15801e04c3fSmrgexec_node_self_link(struct exec_node *n)
15901e04c3fSmrg{
16001e04c3fSmrg   n->next = n;
16101e04c3fSmrg   n->prev = n;
16201e04c3fSmrg}
16301e04c3fSmrg
16401e04c3fSmrgstatic inline void
16501e04c3fSmrgexec_node_insert_after(struct exec_node *n, struct exec_node *after)
16601e04c3fSmrg{
16701e04c3fSmrg   after->next = n->next;
16801e04c3fSmrg   after->prev = n;
16901e04c3fSmrg
17001e04c3fSmrg   n->next->prev = after;
17101e04c3fSmrg   n->next = after;
17201e04c3fSmrg}
17301e04c3fSmrg
17401e04c3fSmrgstatic inline void
17501e04c3fSmrgexec_node_insert_node_before(struct exec_node *n, struct exec_node *before)
17601e04c3fSmrg{
17701e04c3fSmrg   before->next = n;
17801e04c3fSmrg   before->prev = n->prev;
17901e04c3fSmrg
18001e04c3fSmrg   n->prev->next = before;
18101e04c3fSmrg   n->prev = before;
18201e04c3fSmrg}
18301e04c3fSmrg
18401e04c3fSmrgstatic inline void
18501e04c3fSmrgexec_node_replace_with(struct exec_node *n, struct exec_node *replacement)
18601e04c3fSmrg{
18701e04c3fSmrg   replacement->prev = n->prev;
18801e04c3fSmrg   replacement->next = n->next;
18901e04c3fSmrg
19001e04c3fSmrg   n->prev->next = replacement;
19101e04c3fSmrg   n->next->prev = replacement;
19201e04c3fSmrg}
19301e04c3fSmrg
19401e04c3fSmrgstatic inline bool
19501e04c3fSmrgexec_node_is_tail_sentinel(const struct exec_node *n)
19601e04c3fSmrg{
19701e04c3fSmrg   return n->next == NULL;
19801e04c3fSmrg}
19901e04c3fSmrg
20001e04c3fSmrgstatic inline bool
20101e04c3fSmrgexec_node_is_head_sentinel(const struct exec_node *n)
20201e04c3fSmrg{
20301e04c3fSmrg   return n->prev == NULL;
20401e04c3fSmrg}
20501e04c3fSmrg
20601e04c3fSmrg#ifdef __cplusplus
20701e04c3fSmrginline const exec_node *exec_node::get_next() const
20801e04c3fSmrg{
20901e04c3fSmrg   return exec_node_get_next_const(this);
21001e04c3fSmrg}
21101e04c3fSmrg
21201e04c3fSmrginline exec_node *exec_node::get_next()
21301e04c3fSmrg{
21401e04c3fSmrg   return exec_node_get_next(this);
21501e04c3fSmrg}
21601e04c3fSmrg
21701e04c3fSmrginline const exec_node *exec_node::get_prev() const
21801e04c3fSmrg{
21901e04c3fSmrg   return exec_node_get_prev_const(this);
22001e04c3fSmrg}
22101e04c3fSmrg
22201e04c3fSmrginline exec_node *exec_node::get_prev()
22301e04c3fSmrg{
22401e04c3fSmrg   return exec_node_get_prev(this);
22501e04c3fSmrg}
22601e04c3fSmrg
22701e04c3fSmrginline void exec_node::remove()
22801e04c3fSmrg{
22901e04c3fSmrg   exec_node_remove(this);
23001e04c3fSmrg}
23101e04c3fSmrg
23201e04c3fSmrginline void exec_node::self_link()
23301e04c3fSmrg{
23401e04c3fSmrg   exec_node_self_link(this);
23501e04c3fSmrg}
23601e04c3fSmrg
23701e04c3fSmrginline void exec_node::insert_after(exec_node *after)
23801e04c3fSmrg{
23901e04c3fSmrg   exec_node_insert_after(this, after);
24001e04c3fSmrg}
24101e04c3fSmrg
24201e04c3fSmrginline void exec_node::insert_before(exec_node *before)
24301e04c3fSmrg{
24401e04c3fSmrg   exec_node_insert_node_before(this, before);
24501e04c3fSmrg}
24601e04c3fSmrg
24701e04c3fSmrginline void exec_node::replace_with(exec_node *replacement)
24801e04c3fSmrg{
24901e04c3fSmrg   exec_node_replace_with(this, replacement);
25001e04c3fSmrg}
25101e04c3fSmrg
25201e04c3fSmrginline bool exec_node::is_tail_sentinel() const
25301e04c3fSmrg{
25401e04c3fSmrg   return exec_node_is_tail_sentinel(this);
25501e04c3fSmrg}
25601e04c3fSmrg
25701e04c3fSmrginline bool exec_node::is_head_sentinel() const
25801e04c3fSmrg{
25901e04c3fSmrg   return exec_node_is_head_sentinel(this);
26001e04c3fSmrg}
26101e04c3fSmrg#endif
26201e04c3fSmrg
26301e04c3fSmrg#ifdef __cplusplus
26401e04c3fSmrg/* This macro will not work correctly if `t' uses virtual inheritance.  If you
26501e04c3fSmrg * are using virtual inheritance, you deserve a slow and painful death.  Enjoy!
26601e04c3fSmrg */
26701e04c3fSmrg#define exec_list_offsetof(t, f, p) \
26801e04c3fSmrg   (((char *) &((t *) p)->f) - ((char *) p))
26901e04c3fSmrg#else
27001e04c3fSmrg#define exec_list_offsetof(t, f, p) offsetof(t, f)
27101e04c3fSmrg#endif
27201e04c3fSmrg
27301e04c3fSmrg/**
27401e04c3fSmrg * Get a pointer to the structure containing an exec_node
27501e04c3fSmrg *
27601e04c3fSmrg * Given a pointer to an \c exec_node embedded in a structure, get a pointer to
27701e04c3fSmrg * the containing structure.
27801e04c3fSmrg *
27901e04c3fSmrg * \param type  Base type of the structure containing the node
28001e04c3fSmrg * \param node  Pointer to the \c exec_node
28101e04c3fSmrg * \param field Name of the field in \c type that is the embedded \c exec_node
28201e04c3fSmrg */
28301e04c3fSmrg#define exec_node_data(type, node, field) \
2847ec681f3Smrg   ((type *) (((uintptr_t) node) - exec_list_offsetof(type, field, node)))
28501e04c3fSmrg
28601e04c3fSmrg#ifdef __cplusplus
28701e04c3fSmrgstruct exec_node;
28801e04c3fSmrg#endif
28901e04c3fSmrg
29001e04c3fSmrgstruct exec_list {
29101e04c3fSmrg   struct exec_node head_sentinel;
29201e04c3fSmrg   struct exec_node tail_sentinel;
29301e04c3fSmrg
29401e04c3fSmrg#ifdef __cplusplus
29501e04c3fSmrg   DECLARE_RALLOC_CXX_OPERATORS(exec_list)
29601e04c3fSmrg
29701e04c3fSmrg   exec_list()
29801e04c3fSmrg   {
29901e04c3fSmrg      make_empty();
30001e04c3fSmrg   }
30101e04c3fSmrg
30201e04c3fSmrg   void make_empty();
30301e04c3fSmrg
30401e04c3fSmrg   bool is_empty() const;
30501e04c3fSmrg
30601e04c3fSmrg   const exec_node *get_head() const;
30701e04c3fSmrg   exec_node *get_head();
30801e04c3fSmrg   const exec_node *get_head_raw() const;
30901e04c3fSmrg   exec_node *get_head_raw();
31001e04c3fSmrg
31101e04c3fSmrg   const exec_node *get_tail() const;
31201e04c3fSmrg   exec_node *get_tail();
31301e04c3fSmrg   const exec_node *get_tail_raw() const;
31401e04c3fSmrg   exec_node *get_tail_raw();
31501e04c3fSmrg
31601e04c3fSmrg   unsigned length() const;
31701e04c3fSmrg
31801e04c3fSmrg   void push_head(exec_node *n);
31901e04c3fSmrg   void push_tail(exec_node *n);
32001e04c3fSmrg   void push_degenerate_list_at_head(exec_node *n);
32101e04c3fSmrg
32201e04c3fSmrg   /**
32301e04c3fSmrg    * Remove the first node from a list and return it
32401e04c3fSmrg    *
32501e04c3fSmrg    * \return
32601e04c3fSmrg    * The first node in the list or \c NULL if the list is empty.
32701e04c3fSmrg    *
32801e04c3fSmrg    * \sa exec_list::get_head
32901e04c3fSmrg    */
33001e04c3fSmrg   exec_node *pop_head();
33101e04c3fSmrg
33201e04c3fSmrg   /**
33301e04c3fSmrg    * Move all of the nodes from this list to the target list
33401e04c3fSmrg    */
33501e04c3fSmrg   void move_nodes_to(exec_list *target);
33601e04c3fSmrg
33701e04c3fSmrg   /**
33801e04c3fSmrg    * Append all nodes from the source list to the end of the target list
33901e04c3fSmrg    */
34001e04c3fSmrg   void append_list(exec_list *source);
34101e04c3fSmrg
34201e04c3fSmrg   /**
34301e04c3fSmrg    * Prepend all nodes from the source list to the beginning of the target
34401e04c3fSmrg    * list
34501e04c3fSmrg    */
34601e04c3fSmrg   void prepend_list(exec_list *source);
34701e04c3fSmrg#endif
34801e04c3fSmrg};
34901e04c3fSmrg
35001e04c3fSmrgstatic inline void
35101e04c3fSmrgexec_list_make_empty(struct exec_list *list)
35201e04c3fSmrg{
35301e04c3fSmrg   list->head_sentinel.next = &list->tail_sentinel;
35401e04c3fSmrg   list->head_sentinel.prev = NULL;
35501e04c3fSmrg   list->tail_sentinel.next = NULL;
35601e04c3fSmrg   list->tail_sentinel.prev = &list->head_sentinel;
35701e04c3fSmrg}
35801e04c3fSmrg
35901e04c3fSmrgstatic inline bool
36001e04c3fSmrgexec_list_is_empty(const struct exec_list *list)
36101e04c3fSmrg{
36201e04c3fSmrg   /* There are three ways to test whether a list is empty or not.
36301e04c3fSmrg    *
36401e04c3fSmrg    * - Check to see if the head sentinel's \c next is the tail sentinel.
36501e04c3fSmrg    * - Check to see if the tail sentinel's \c prev is the head sentinel.
36601e04c3fSmrg    * - Check to see if the head is the sentinel node by test whether its
36701e04c3fSmrg    *   \c next pointer is \c NULL.
36801e04c3fSmrg    *
36901e04c3fSmrg    * The first two methods tend to generate better code on modern systems
37001e04c3fSmrg    * because they save a pointer dereference.
37101e04c3fSmrg    */
37201e04c3fSmrg   return list->head_sentinel.next == &list->tail_sentinel;
37301e04c3fSmrg}
37401e04c3fSmrg
3757e102996Smayastatic inline bool
3767e102996Smayaexec_list_is_singular(const struct exec_list *list)
3777e102996Smaya{
3787e102996Smaya   return !exec_list_is_empty(list) &&
3797e102996Smaya          list->head_sentinel.next->next == &list->tail_sentinel;
3807e102996Smaya}
3817e102996Smaya
38201e04c3fSmrgstatic inline const struct exec_node *
38301e04c3fSmrgexec_list_get_head_const(const struct exec_list *list)
38401e04c3fSmrg{
38501e04c3fSmrg   return !exec_list_is_empty(list) ? list->head_sentinel.next : NULL;
38601e04c3fSmrg}
38701e04c3fSmrg
38801e04c3fSmrgstatic inline struct exec_node *
38901e04c3fSmrgexec_list_get_head(struct exec_list *list)
39001e04c3fSmrg{
39101e04c3fSmrg   return !exec_list_is_empty(list) ? list->head_sentinel.next : NULL;
39201e04c3fSmrg}
39301e04c3fSmrg
39401e04c3fSmrgstatic inline const struct exec_node *
39501e04c3fSmrgexec_list_get_head_raw_const(const struct exec_list *list)
39601e04c3fSmrg{
39701e04c3fSmrg   return list->head_sentinel.next;
39801e04c3fSmrg}
39901e04c3fSmrg
40001e04c3fSmrgstatic inline struct exec_node *
40101e04c3fSmrgexec_list_get_head_raw(struct exec_list *list)
40201e04c3fSmrg{
40301e04c3fSmrg   return list->head_sentinel.next;
40401e04c3fSmrg}
40501e04c3fSmrg
40601e04c3fSmrgstatic inline const struct exec_node *
40701e04c3fSmrgexec_list_get_tail_const(const struct exec_list *list)
40801e04c3fSmrg{
40901e04c3fSmrg   return !exec_list_is_empty(list) ? list->tail_sentinel.prev : NULL;
41001e04c3fSmrg}
41101e04c3fSmrg
41201e04c3fSmrgstatic inline struct exec_node *
41301e04c3fSmrgexec_list_get_tail(struct exec_list *list)
41401e04c3fSmrg{
41501e04c3fSmrg   return !exec_list_is_empty(list) ? list->tail_sentinel.prev : NULL;
41601e04c3fSmrg}
41701e04c3fSmrg
41801e04c3fSmrgstatic inline const struct exec_node *
41901e04c3fSmrgexec_list_get_tail_raw_const(const struct exec_list *list)
42001e04c3fSmrg{
42101e04c3fSmrg   return list->tail_sentinel.prev;
42201e04c3fSmrg}
42301e04c3fSmrg
42401e04c3fSmrgstatic inline struct exec_node *
42501e04c3fSmrgexec_list_get_tail_raw(struct exec_list *list)
42601e04c3fSmrg{
42701e04c3fSmrg   return list->tail_sentinel.prev;
42801e04c3fSmrg}
42901e04c3fSmrg
43001e04c3fSmrgstatic inline unsigned
43101e04c3fSmrgexec_list_length(const struct exec_list *list)
43201e04c3fSmrg{
43301e04c3fSmrg   unsigned size = 0;
43401e04c3fSmrg   struct exec_node *node;
43501e04c3fSmrg
43601e04c3fSmrg   for (node = list->head_sentinel.next; node->next != NULL; node = node->next) {
43701e04c3fSmrg      size++;
43801e04c3fSmrg   }
43901e04c3fSmrg
44001e04c3fSmrg   return size;
44101e04c3fSmrg}
44201e04c3fSmrg
44301e04c3fSmrgstatic inline void
44401e04c3fSmrgexec_list_push_head(struct exec_list *list, struct exec_node *n)
44501e04c3fSmrg{
44601e04c3fSmrg   n->next = list->head_sentinel.next;
44701e04c3fSmrg   n->prev = &list->head_sentinel;
44801e04c3fSmrg
44901e04c3fSmrg   n->next->prev = n;
45001e04c3fSmrg   list->head_sentinel.next = n;
45101e04c3fSmrg}
45201e04c3fSmrg
45301e04c3fSmrgstatic inline void
45401e04c3fSmrgexec_list_push_tail(struct exec_list *list, struct exec_node *n)
45501e04c3fSmrg{
45601e04c3fSmrg   n->next = &list->tail_sentinel;
45701e04c3fSmrg   n->prev = list->tail_sentinel.prev;
45801e04c3fSmrg
45901e04c3fSmrg   n->prev->next = n;
46001e04c3fSmrg   list->tail_sentinel.prev = n;
46101e04c3fSmrg}
46201e04c3fSmrg
46301e04c3fSmrgstatic inline void
46401e04c3fSmrgexec_list_push_degenerate_list_at_head(struct exec_list *list, struct exec_node *n)
46501e04c3fSmrg{
46601e04c3fSmrg   assert(n->prev->next == n);
46701e04c3fSmrg
46801e04c3fSmrg   n->prev->next = list->head_sentinel.next;
46901e04c3fSmrg   list->head_sentinel.next->prev = n->prev;
47001e04c3fSmrg   n->prev = &list->head_sentinel;
47101e04c3fSmrg   list->head_sentinel.next = n;
47201e04c3fSmrg}
47301e04c3fSmrg
47401e04c3fSmrgstatic inline struct exec_node *
47501e04c3fSmrgexec_list_pop_head(struct exec_list *list)
47601e04c3fSmrg{
47701e04c3fSmrg   struct exec_node *const n = exec_list_get_head(list);
47801e04c3fSmrg   if (n != NULL)
47901e04c3fSmrg      exec_node_remove(n);
48001e04c3fSmrg
48101e04c3fSmrg   return n;
48201e04c3fSmrg}
48301e04c3fSmrg
48401e04c3fSmrgstatic inline void
48501e04c3fSmrgexec_list_move_nodes_to(struct exec_list *list, struct exec_list *target)
48601e04c3fSmrg{
48701e04c3fSmrg   if (exec_list_is_empty(list)) {
48801e04c3fSmrg      exec_list_make_empty(target);
48901e04c3fSmrg   } else {
49001e04c3fSmrg      target->head_sentinel.next = list->head_sentinel.next;
49101e04c3fSmrg      target->head_sentinel.prev = NULL;
49201e04c3fSmrg      target->tail_sentinel.next = NULL;
49301e04c3fSmrg      target->tail_sentinel.prev = list->tail_sentinel.prev;
49401e04c3fSmrg
49501e04c3fSmrg      target->head_sentinel.next->prev = &target->head_sentinel;
49601e04c3fSmrg      target->tail_sentinel.prev->next = &target->tail_sentinel;
49701e04c3fSmrg
49801e04c3fSmrg      exec_list_make_empty(list);
49901e04c3fSmrg   }
50001e04c3fSmrg}
50101e04c3fSmrg
50201e04c3fSmrgstatic inline void
50301e04c3fSmrgexec_list_append(struct exec_list *list, struct exec_list *source)
50401e04c3fSmrg{
50501e04c3fSmrg   if (exec_list_is_empty(source))
50601e04c3fSmrg      return;
50701e04c3fSmrg
50801e04c3fSmrg   /* Link the first node of the source with the last node of the target list.
50901e04c3fSmrg    */
51001e04c3fSmrg   list->tail_sentinel.prev->next = source->head_sentinel.next;
51101e04c3fSmrg   source->head_sentinel.next->prev = list->tail_sentinel.prev;
51201e04c3fSmrg
51301e04c3fSmrg   /* Make the tail of the source list be the tail of the target list.
51401e04c3fSmrg    */
51501e04c3fSmrg   list->tail_sentinel.prev = source->tail_sentinel.prev;
51601e04c3fSmrg   list->tail_sentinel.prev->next = &list->tail_sentinel;
51701e04c3fSmrg
51801e04c3fSmrg   /* Make the source list empty for good measure.
51901e04c3fSmrg    */
52001e04c3fSmrg   exec_list_make_empty(source);
52101e04c3fSmrg}
52201e04c3fSmrg
523993e1d59Smrgstatic inline void
524993e1d59Smrgexec_node_insert_list_after(struct exec_node *n, struct exec_list *after)
525993e1d59Smrg{
526993e1d59Smrg   if (exec_list_is_empty(after))
527993e1d59Smrg      return;
528993e1d59Smrg
529993e1d59Smrg   after->tail_sentinel.prev->next = n->next;
530993e1d59Smrg   after->head_sentinel.next->prev = n;
531993e1d59Smrg
532993e1d59Smrg   n->next->prev = after->tail_sentinel.prev;
533993e1d59Smrg   n->next = after->head_sentinel.next;
534993e1d59Smrg
535993e1d59Smrg   exec_list_make_empty(after);
536993e1d59Smrg}
537993e1d59Smrg
53801e04c3fSmrgstatic inline void
53901e04c3fSmrgexec_list_prepend(struct exec_list *list, struct exec_list *source)
54001e04c3fSmrg{
54101e04c3fSmrg   exec_list_append(source, list);
54201e04c3fSmrg   exec_list_move_nodes_to(source, list);
54301e04c3fSmrg}
54401e04c3fSmrg
54501e04c3fSmrgstatic inline void
54601e04c3fSmrgexec_node_insert_list_before(struct exec_node *n, struct exec_list *before)
54701e04c3fSmrg{
54801e04c3fSmrg   if (exec_list_is_empty(before))
54901e04c3fSmrg      return;
55001e04c3fSmrg
55101e04c3fSmrg   before->tail_sentinel.prev->next = n;
55201e04c3fSmrg   before->head_sentinel.next->prev = n->prev;
55301e04c3fSmrg
55401e04c3fSmrg   n->prev->next = before->head_sentinel.next;
55501e04c3fSmrg   n->prev = before->tail_sentinel.prev;
55601e04c3fSmrg
55701e04c3fSmrg   exec_list_make_empty(before);
55801e04c3fSmrg}
55901e04c3fSmrg
56001e04c3fSmrgstatic inline void
56101e04c3fSmrgexec_list_validate(const struct exec_list *list)
56201e04c3fSmrg{
56301e04c3fSmrg   const struct exec_node *node;
56401e04c3fSmrg
56501e04c3fSmrg   assert(list->head_sentinel.next->prev == &list->head_sentinel);
56601e04c3fSmrg   assert(list->head_sentinel.prev == NULL);
56701e04c3fSmrg   assert(list->tail_sentinel.next == NULL);
56801e04c3fSmrg   assert(list->tail_sentinel.prev->next == &list->tail_sentinel);
56901e04c3fSmrg
57001e04c3fSmrg   /* We could try to use one of the interators below for this but they all
57101e04c3fSmrg    * either require C++ or assume the exec_node is embedded in a structure
57201e04c3fSmrg    * which is not the case for this function.
57301e04c3fSmrg    */
57401e04c3fSmrg   for (node = list->head_sentinel.next; node->next != NULL; node = node->next) {
57501e04c3fSmrg      assert(node->next->prev == node);
57601e04c3fSmrg      assert(node->prev->next == node);
57701e04c3fSmrg   }
57801e04c3fSmrg}
57901e04c3fSmrg
58001e04c3fSmrg#ifdef __cplusplus
58101e04c3fSmrginline void exec_list::make_empty()
58201e04c3fSmrg{
58301e04c3fSmrg   exec_list_make_empty(this);
58401e04c3fSmrg}
58501e04c3fSmrg
58601e04c3fSmrginline bool exec_list::is_empty() const
58701e04c3fSmrg{
58801e04c3fSmrg   return exec_list_is_empty(this);
58901e04c3fSmrg}
59001e04c3fSmrg
59101e04c3fSmrginline const exec_node *exec_list::get_head() const
59201e04c3fSmrg{
59301e04c3fSmrg   return exec_list_get_head_const(this);
59401e04c3fSmrg}
59501e04c3fSmrg
59601e04c3fSmrginline exec_node *exec_list::get_head()
59701e04c3fSmrg{
59801e04c3fSmrg   return exec_list_get_head(this);
59901e04c3fSmrg}
60001e04c3fSmrg
60101e04c3fSmrginline const exec_node *exec_list::get_head_raw() const
60201e04c3fSmrg{
60301e04c3fSmrg   return exec_list_get_head_raw_const(this);
60401e04c3fSmrg}
60501e04c3fSmrg
60601e04c3fSmrginline exec_node *exec_list::get_head_raw()
60701e04c3fSmrg{
60801e04c3fSmrg   return exec_list_get_head_raw(this);
60901e04c3fSmrg}
61001e04c3fSmrg
61101e04c3fSmrginline const exec_node *exec_list::get_tail() const
61201e04c3fSmrg{
61301e04c3fSmrg   return exec_list_get_tail_const(this);
61401e04c3fSmrg}
61501e04c3fSmrg
61601e04c3fSmrginline exec_node *exec_list::get_tail()
61701e04c3fSmrg{
61801e04c3fSmrg   return exec_list_get_tail(this);
61901e04c3fSmrg}
62001e04c3fSmrg
62101e04c3fSmrginline const exec_node *exec_list::get_tail_raw() const
62201e04c3fSmrg{
62301e04c3fSmrg   return exec_list_get_tail_raw_const(this);
62401e04c3fSmrg}
62501e04c3fSmrg
62601e04c3fSmrginline exec_node *exec_list::get_tail_raw()
62701e04c3fSmrg{
62801e04c3fSmrg   return exec_list_get_tail_raw(this);
62901e04c3fSmrg}
63001e04c3fSmrg
63101e04c3fSmrginline unsigned exec_list::length() const
63201e04c3fSmrg{
63301e04c3fSmrg   return exec_list_length(this);
63401e04c3fSmrg}
63501e04c3fSmrg
63601e04c3fSmrginline void exec_list::push_head(exec_node *n)
63701e04c3fSmrg{
63801e04c3fSmrg   exec_list_push_head(this, n);
63901e04c3fSmrg}
64001e04c3fSmrg
64101e04c3fSmrginline void exec_list::push_tail(exec_node *n)
64201e04c3fSmrg{
64301e04c3fSmrg   exec_list_push_tail(this, n);
64401e04c3fSmrg}
64501e04c3fSmrg
64601e04c3fSmrginline void exec_list::push_degenerate_list_at_head(exec_node *n)
64701e04c3fSmrg{
64801e04c3fSmrg   exec_list_push_degenerate_list_at_head(this, n);
64901e04c3fSmrg}
65001e04c3fSmrg
65101e04c3fSmrginline exec_node *exec_list::pop_head()
65201e04c3fSmrg{
65301e04c3fSmrg   return exec_list_pop_head(this);
65401e04c3fSmrg}
65501e04c3fSmrg
65601e04c3fSmrginline void exec_list::move_nodes_to(exec_list *target)
65701e04c3fSmrg{
65801e04c3fSmrg   exec_list_move_nodes_to(this, target);
65901e04c3fSmrg}
66001e04c3fSmrg
66101e04c3fSmrginline void exec_list::append_list(exec_list *source)
66201e04c3fSmrg{
66301e04c3fSmrg   exec_list_append(this, source);
66401e04c3fSmrg}
66501e04c3fSmrg
666993e1d59Smrginline void exec_node::insert_after(exec_list *after)
667993e1d59Smrg{
668993e1d59Smrg   exec_node_insert_list_after(this, after);
669993e1d59Smrg}
670993e1d59Smrg
67101e04c3fSmrginline void exec_list::prepend_list(exec_list *source)
67201e04c3fSmrg{
67301e04c3fSmrg   exec_list_prepend(this, source);
67401e04c3fSmrg}
67501e04c3fSmrg
67601e04c3fSmrginline void exec_node::insert_before(exec_list *before)
67701e04c3fSmrg{
67801e04c3fSmrg   exec_node_insert_list_before(this, before);
67901e04c3fSmrg}
68001e04c3fSmrg#endif
68101e04c3fSmrg
6827ec681f3Smrg#define exec_node_typed_forward(__node, __type) \
6837ec681f3Smrg   (!exec_node_is_tail_sentinel(__node) ? (__type) (__node) : NULL)
68401e04c3fSmrg
6857ec681f3Smrg#define exec_node_typed_backward(__node, __type) \
6867ec681f3Smrg   (!exec_node_is_head_sentinel(__node) ? (__type) (__node) : NULL)
6877ec681f3Smrg
6887ec681f3Smrg#define foreach_in_list(__type, __inst, __list)                                           \
6897ec681f3Smrg   for (__type *__inst = exec_node_typed_forward((__list)->head_sentinel.next, __type *); \
6907ec681f3Smrg        (__inst) != NULL;                                                                 \
6917ec681f3Smrg        (__inst) = exec_node_typed_forward((__inst)->next, __type *))
6927ec681f3Smrg
6937ec681f3Smrg#define foreach_in_list_reverse(__type, __inst, __list)                                      \
6947ec681f3Smrg   for (__type *__inst = exec_node_typed_backward((__list)->tail_sentinel.prev, __type *);   \
6957ec681f3Smrg        (__inst) != NULL;                                                                    \
6967ec681f3Smrg        (__inst) = exec_node_typed_backward((__inst)->prev, __type *))
69701e04c3fSmrg
69801e04c3fSmrg/**
69901e04c3fSmrg * This version is safe even if the current node is removed.
7007ec681f3Smrg */
7017ec681f3Smrg
7027ec681f3Smrg#define foreach_in_list_safe(__type, __node, __list)                                                              \
7037ec681f3Smrg   for (__type *__node = exec_node_typed_forward((__list)->head_sentinel.next, __type *),                         \
7047ec681f3Smrg               *__next = (__node) ? exec_node_typed_forward((__list)->head_sentinel.next->next, __type *) : NULL; \
7057ec681f3Smrg        (__node) != NULL;                                                                                         \
7067ec681f3Smrg        (__node) = __next, __next = __next ? exec_node_typed_forward(__next->next, __type *) : NULL)
7077ec681f3Smrg
7087ec681f3Smrg#define foreach_in_list_reverse_safe(__type, __node, __list)                                                        \
7097ec681f3Smrg   for (__type *__node = exec_node_typed_backward((__list)->tail_sentinel.prev, __type *),                          \
7107ec681f3Smrg               *__prev = (__node) ? exec_node_typed_backward((__list)->tail_sentinel.prev->prev, __type *) : NULL;  \
7117ec681f3Smrg        (__node) != NULL;                                                                                           \
7127ec681f3Smrg        (__node) = __prev, __prev = __prev ? exec_node_typed_backward(__prev->prev, __type *) : NULL)
7137ec681f3Smrg
7147ec681f3Smrg#define foreach_in_list_use_after(__type, __inst, __list)                           \
7157ec681f3Smrg   __type *__inst;                                                                  \
7167ec681f3Smrg   for ((__inst) = exec_node_typed_forward((__list)->head_sentinel.next, __type *); \
7177ec681f3Smrg        (__inst) != NULL;                                                           \
7187ec681f3Smrg        (__inst) = exec_node_typed_forward((__inst)->next, __type *))
7197ec681f3Smrg
72001e04c3fSmrg/**
72101e04c3fSmrg * Iterate through two lists at once.  Stops at the end of the shorter list.
72201e04c3fSmrg *
72301e04c3fSmrg * This is safe against either current node being removed or replaced.
72401e04c3fSmrg */
72501e04c3fSmrg#define foreach_two_lists(__node1, __list1, __node2, __list2) \
72601e04c3fSmrg   for (struct exec_node * __node1 = (__list1)->head_sentinel.next, \
72701e04c3fSmrg                         * __node2 = (__list2)->head_sentinel.next, \
72801e04c3fSmrg                         * __next1 = __node1->next,           \
72901e04c3fSmrg                         * __next2 = __node2->next            \
73001e04c3fSmrg	; __next1 != NULL && __next2 != NULL                  \
73101e04c3fSmrg	; __node1 = __next1,                                  \
73201e04c3fSmrg          __node2 = __next2,                                  \
73301e04c3fSmrg          __next1 = __next1->next,                            \
73401e04c3fSmrg          __next2 = __next2->next)
73501e04c3fSmrg
7367ec681f3Smrg#define exec_node_data_forward(type, node, field) \
7377ec681f3Smrg   (!exec_node_is_tail_sentinel(node) ? exec_node_data(type, node, field) : NULL)
7387ec681f3Smrg
7397ec681f3Smrg#define exec_node_data_backward(type, node, field) \
7407ec681f3Smrg   (!exec_node_is_head_sentinel(node) ? exec_node_data(type, node, field) : NULL)
7417ec681f3Smrg
7427ec681f3Smrg#define foreach_list_typed(__type, __node, __field, __list)                     \
7437ec681f3Smrg   for (__type * __node =                                                       \
7447ec681f3Smrg         exec_node_data_forward(__type, (__list)->head_sentinel.next, __field); \
7457ec681f3Smrg   (__node) != NULL;                                                            \
7467ec681f3Smrg   (__node) = exec_node_data_forward(__type, (__node)->__field.next, __field))
7477ec681f3Smrg
7487ec681f3Smrg#define foreach_list_typed_from(__type, __node, __field, __list, __start)        \
7497ec681f3Smrg   for (__type * __node = exec_node_data_forward(__type, (__start), __field);    \
7507ec681f3Smrg   (__node) != NULL;                                                             \
7517ec681f3Smrg   (__node) = exec_node_data_forward(__type, (__node)->__field.next, __field))
7527ec681f3Smrg
7537ec681f3Smrg#define foreach_list_typed_reverse(__type, __node, __field, __list)                 \
7547ec681f3Smrg   for (__type * __node =                                                           \
7557ec681f3Smrg           exec_node_data_backward(__type, (__list)->tail_sentinel.prev, __field);  \
7567ec681f3Smrg        (__node) != NULL;                                                           \
7577ec681f3Smrg        (__node) = exec_node_data_backward(__type, (__node)->__field.prev, __field))
7587ec681f3Smrg
7597ec681f3Smrg#define foreach_list_typed_safe(__type, __node, __field, __list)                    \
7607ec681f3Smrg   for (__type * __node =                                                           \
7617ec681f3Smrg           exec_node_data_forward(__type, (__list)->head_sentinel.next, __field),   \
7627ec681f3Smrg               * __next = (__node) ?                                                \
7637ec681f3Smrg           exec_node_data_forward(__type, (__node)->__field.next, __field) : NULL;  \
7647ec681f3Smrg        (__node) != NULL;                                                           \
7657ec681f3Smrg        (__node) = __next, __next = (__next && (__next)->__field.next) ?            \
7667ec681f3Smrg           exec_node_data_forward(__type, (__next)->__field.next, __field) : NULL)
7677ec681f3Smrg
7687ec681f3Smrg#define foreach_list_typed_reverse_safe(__type, __node, __field, __list)            \
7697ec681f3Smrg   for (__type * __node =                                                           \
7707ec681f3Smrg           exec_node_data_backward(__type, (__list)->tail_sentinel.prev, __field),  \
7717ec681f3Smrg               * __prev = (__node) ?                                                \
7727ec681f3Smrg           exec_node_data_backward(__type, (__node)->__field.prev, __field) : NULL; \
7737ec681f3Smrg        (__node) != NULL;                                                           \
7747ec681f3Smrg        (__node) = __prev, __prev = (__prev && (__prev)->__field.prev) ?            \
7757ec681f3Smrg           exec_node_data_backward(__type, (__prev)->__field.prev, __field) : NULL)
77601e04c3fSmrg
77701e04c3fSmrg#endif /* LIST_CONTAINER_H */
778