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