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