2010-03-09 07:42:45 +00:00
|
|
|
/*
|
|
|
|
* Copyright © 2008, 2010 Intel Corporation
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice (including the next
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
* Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
* DEALINGS IN THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \file list.h
|
|
|
|
* \brief Doubly-linked list abstract container type.
|
|
|
|
*
|
2010-07-29 21:52:25 +01:00
|
|
|
* Each doubly-linked list has a sentinel head and tail node. These nodes
|
|
|
|
* contain no data. The head sentinel can be identified by its \c prev
|
|
|
|
* pointer being \c NULL. The tail sentinel can be identified by its
|
2010-03-09 07:42:45 +00:00
|
|
|
* \c next pointer being \c NULL.
|
|
|
|
*
|
2010-07-29 21:52:25 +01:00
|
|
|
* A list is empty if either the head sentinel's \c next pointer points to the
|
|
|
|
* tail sentinel or the tail sentinel's \c prev poiner points to the head
|
2016-06-27 22:42:57 +01:00
|
|
|
* sentinel. The head sentinel and tail sentinel nodes are allocated within the
|
|
|
|
* list structure.
|
2010-03-09 07:42:45 +00:00
|
|
|
*
|
2015-02-03 01:23:25 +00:00
|
|
|
* Do note that this means that the list nodes will contain pointers into the
|
|
|
|
* list structure itself and as a result you may not \c realloc() an \c
|
|
|
|
* exec_list or any structure in which an \c exec_list is embedded.
|
2010-03-09 07:42:45 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef LIST_CONTAINER_H
|
|
|
|
#define LIST_CONTAINER_H
|
|
|
|
|
2010-05-10 19:16:24 +01:00
|
|
|
#ifndef __cplusplus
|
|
|
|
#include <stddef.h>
|
|
|
|
#endif
|
2010-03-09 07:42:45 +00:00
|
|
|
#include <assert.h>
|
|
|
|
|
2014-02-25 07:39:14 +00:00
|
|
|
#include "util/ralloc.h"
|
2011-01-21 22:32:31 +00:00
|
|
|
|
2010-03-09 07:42:45 +00:00
|
|
|
struct exec_node {
|
|
|
|
struct exec_node *next;
|
|
|
|
struct exec_node *prev;
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
2016-10-06 23:34:26 +01:00
|
|
|
DECLARE_RZALLOC_CXX_OPERATORS(exec_node)
|
2010-06-24 02:11:51 +01:00
|
|
|
|
2010-03-09 07:42:45 +00:00
|
|
|
exec_node() : next(NULL), prev(NULL)
|
|
|
|
{
|
|
|
|
/* empty */
|
|
|
|
}
|
|
|
|
|
2014-06-10 06:37:44 +01:00
|
|
|
const exec_node *get_next() const;
|
|
|
|
exec_node *get_next();
|
2010-03-09 07:42:45 +00:00
|
|
|
|
2014-06-10 06:37:44 +01:00
|
|
|
const exec_node *get_prev() const;
|
|
|
|
exec_node *get_prev();
|
2010-03-09 07:42:45 +00:00
|
|
|
|
2014-06-10 06:37:44 +01:00
|
|
|
void remove();
|
2010-03-09 07:42:45 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Link a node with itself
|
|
|
|
*
|
|
|
|
* This creates a sort of degenerate list that is occasionally useful.
|
|
|
|
*/
|
2014-06-10 06:37:44 +01:00
|
|
|
void self_link();
|
2010-03-09 07:42:45 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Insert a node in the list after the current node
|
|
|
|
*/
|
2014-06-10 06:37:44 +01:00
|
|
|
void insert_after(exec_node *after);
|
2019-03-12 02:01:34 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Insert another list in the list after the current node
|
|
|
|
*/
|
|
|
|
void insert_after(struct exec_list *after);
|
|
|
|
|
2010-04-07 19:46:26 +01:00
|
|
|
/**
|
|
|
|
* Insert a node in the list before the current node
|
|
|
|
*/
|
2014-06-10 06:37:44 +01:00
|
|
|
void insert_before(exec_node *before);
|
2010-08-27 21:53:56 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Insert another list in the list before the current node
|
|
|
|
*/
|
2010-09-03 22:25:50 +01:00
|
|
|
void insert_before(struct exec_list *before);
|
2010-08-27 21:53:56 +01:00
|
|
|
|
2010-07-14 20:14:26 +01:00
|
|
|
/**
|
|
|
|
* Replace the current node with the given node.
|
|
|
|
*/
|
2014-06-10 06:37:44 +01:00
|
|
|
void replace_with(exec_node *replacement);
|
2010-06-05 00:35:42 +01:00
|
|
|
|
|
|
|
/**
|
2010-07-29 21:52:25 +01:00
|
|
|
* Is this the sentinel at the tail of the list?
|
2010-06-05 00:35:42 +01:00
|
|
|
*/
|
2014-06-10 06:37:44 +01:00
|
|
|
bool is_tail_sentinel() const;
|
2010-06-05 00:35:42 +01:00
|
|
|
|
|
|
|
/**
|
2010-07-29 21:52:25 +01:00
|
|
|
* Is this the sentinel at the head of the list?
|
2010-06-05 00:35:42 +01:00
|
|
|
*/
|
2014-06-10 06:37:44 +01:00
|
|
|
bool is_head_sentinel() const;
|
2010-03-09 07:42:45 +00:00
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
2014-06-10 10:06:23 +01:00
|
|
|
static inline void
|
|
|
|
exec_node_init(struct exec_node *n)
|
|
|
|
{
|
|
|
|
n->next = NULL;
|
|
|
|
n->prev = NULL;
|
|
|
|
}
|
|
|
|
|
2014-06-10 08:14:24 +01:00
|
|
|
static inline const struct exec_node *
|
|
|
|
exec_node_get_next_const(const struct exec_node *n)
|
|
|
|
{
|
|
|
|
return n->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct exec_node *
|
|
|
|
exec_node_get_next(struct exec_node *n)
|
|
|
|
{
|
|
|
|
return n->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline const struct exec_node *
|
|
|
|
exec_node_get_prev_const(const struct exec_node *n)
|
|
|
|
{
|
|
|
|
return n->prev;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct exec_node *
|
|
|
|
exec_node_get_prev(struct exec_node *n)
|
|
|
|
{
|
|
|
|
return n->prev;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
exec_node_remove(struct exec_node *n)
|
|
|
|
{
|
|
|
|
n->next->prev = n->prev;
|
|
|
|
n->prev->next = n->next;
|
|
|
|
n->next = NULL;
|
|
|
|
n->prev = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
exec_node_self_link(struct exec_node *n)
|
|
|
|
{
|
|
|
|
n->next = n;
|
|
|
|
n->prev = n;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
exec_node_insert_after(struct exec_node *n, struct exec_node *after)
|
|
|
|
{
|
|
|
|
after->next = n->next;
|
|
|
|
after->prev = n;
|
|
|
|
|
|
|
|
n->next->prev = after;
|
|
|
|
n->next = after;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
exec_node_insert_node_before(struct exec_node *n, struct exec_node *before)
|
|
|
|
{
|
|
|
|
before->next = n;
|
|
|
|
before->prev = n->prev;
|
|
|
|
|
|
|
|
n->prev->next = before;
|
|
|
|
n->prev = before;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
exec_node_replace_with(struct exec_node *n, struct exec_node *replacement)
|
|
|
|
{
|
|
|
|
replacement->prev = n->prev;
|
|
|
|
replacement->next = n->next;
|
|
|
|
|
|
|
|
n->prev->next = replacement;
|
|
|
|
n->next->prev = replacement;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
exec_node_is_tail_sentinel(const struct exec_node *n)
|
|
|
|
{
|
|
|
|
return n->next == NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
exec_node_is_head_sentinel(const struct exec_node *n)
|
|
|
|
{
|
|
|
|
return n->prev == NULL;
|
|
|
|
}
|
|
|
|
|
2014-06-10 06:37:44 +01:00
|
|
|
#ifdef __cplusplus
|
|
|
|
inline const exec_node *exec_node::get_next() const
|
|
|
|
{
|
2014-06-10 08:28:53 +01:00
|
|
|
return exec_node_get_next_const(this);
|
2014-06-10 06:37:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline exec_node *exec_node::get_next()
|
|
|
|
{
|
2014-06-10 08:28:53 +01:00
|
|
|
return exec_node_get_next(this);
|
2014-06-10 06:37:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline const exec_node *exec_node::get_prev() const
|
|
|
|
{
|
2014-06-10 08:28:53 +01:00
|
|
|
return exec_node_get_prev_const(this);
|
2014-06-10 06:37:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline exec_node *exec_node::get_prev()
|
|
|
|
{
|
2014-06-10 08:28:53 +01:00
|
|
|
return exec_node_get_prev(this);
|
2014-06-10 06:37:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void exec_node::remove()
|
|
|
|
{
|
2014-06-10 08:28:53 +01:00
|
|
|
exec_node_remove(this);
|
2014-06-10 06:37:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void exec_node::self_link()
|
|
|
|
{
|
2014-06-10 08:28:53 +01:00
|
|
|
exec_node_self_link(this);
|
2014-06-10 06:37:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void exec_node::insert_after(exec_node *after)
|
|
|
|
{
|
2014-06-10 08:28:53 +01:00
|
|
|
exec_node_insert_after(this, after);
|
2014-06-10 06:37:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void exec_node::insert_before(exec_node *before)
|
|
|
|
{
|
2014-06-10 08:28:53 +01:00
|
|
|
exec_node_insert_node_before(this, before);
|
2014-06-10 06:37:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void exec_node::replace_with(exec_node *replacement)
|
|
|
|
{
|
2014-06-10 08:28:53 +01:00
|
|
|
exec_node_replace_with(this, replacement);
|
2014-06-10 06:37:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline bool exec_node::is_tail_sentinel() const
|
|
|
|
{
|
2014-06-10 08:28:53 +01:00
|
|
|
return exec_node_is_tail_sentinel(this);
|
2014-06-10 06:37:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline bool exec_node::is_head_sentinel() const
|
|
|
|
{
|
2014-06-10 08:28:53 +01:00
|
|
|
return exec_node_is_head_sentinel(this);
|
2014-06-10 06:37:44 +01:00
|
|
|
}
|
|
|
|
#endif
|
2010-05-10 19:16:24 +01:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
/* This macro will not work correctly if `t' uses virtual inheritance. If you
|
|
|
|
* are using virtual inheritance, you deserve a slow and painful death. Enjoy!
|
|
|
|
*/
|
|
|
|
#define exec_list_offsetof(t, f, p) \
|
|
|
|
(((char *) &((t *) p)->f) - ((char *) p))
|
|
|
|
#else
|
|
|
|
#define exec_list_offsetof(t, f, p) offsetof(t, f)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a pointer to the structure containing an exec_node
|
|
|
|
*
|
|
|
|
* Given a pointer to an \c exec_node embedded in a structure, get a pointer to
|
|
|
|
* the containing structure.
|
|
|
|
*
|
|
|
|
* \param type Base type of the structure containing the node
|
|
|
|
* \param node Pointer to the \c exec_node
|
|
|
|
* \param field Name of the field in \c type that is the embedded \c exec_node
|
|
|
|
*/
|
|
|
|
#define exec_node_data(type, node, field) \
|
2020-02-19 15:09:38 +00:00
|
|
|
((type *) (((uintptr_t) node) - exec_list_offsetof(type, field, node)))
|
2010-05-10 19:16:24 +01:00
|
|
|
|
2010-03-09 07:42:45 +00:00
|
|
|
#ifdef __cplusplus
|
|
|
|
struct exec_node;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
struct exec_list {
|
2016-06-27 22:42:57 +01:00
|
|
|
struct exec_node head_sentinel;
|
|
|
|
struct exec_node tail_sentinel;
|
2010-03-09 07:42:45 +00:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
2013-09-18 22:05:36 +01:00
|
|
|
DECLARE_RALLOC_CXX_OPERATORS(exec_list)
|
2010-06-30 19:05:43 +01:00
|
|
|
|
2010-03-09 07:42:45 +00:00
|
|
|
exec_list()
|
|
|
|
{
|
|
|
|
make_empty();
|
|
|
|
}
|
|
|
|
|
2014-06-10 06:44:56 +01:00
|
|
|
void make_empty();
|
2010-03-09 07:42:45 +00:00
|
|
|
|
2014-06-10 06:44:56 +01:00
|
|
|
bool is_empty() const;
|
2010-03-09 07:42:45 +00:00
|
|
|
|
2014-06-10 06:44:56 +01:00
|
|
|
const exec_node *get_head() const;
|
|
|
|
exec_node *get_head();
|
2016-06-27 22:42:57 +01:00
|
|
|
const exec_node *get_head_raw() const;
|
|
|
|
exec_node *get_head_raw();
|
2010-03-09 07:42:45 +00:00
|
|
|
|
2014-06-10 06:44:56 +01:00
|
|
|
const exec_node *get_tail() const;
|
|
|
|
exec_node *get_tail();
|
2016-06-27 22:42:57 +01:00
|
|
|
const exec_node *get_tail_raw() const;
|
|
|
|
exec_node *get_tail_raw();
|
2010-03-09 07:42:45 +00:00
|
|
|
|
2014-07-08 20:20:59 +01:00
|
|
|
unsigned length() const;
|
|
|
|
|
2014-06-10 06:44:56 +01:00
|
|
|
void push_head(exec_node *n);
|
|
|
|
void push_tail(exec_node *n);
|
|
|
|
void push_degenerate_list_at_head(exec_node *n);
|
2010-03-09 07:42:45 +00:00
|
|
|
|
2010-08-17 02:02:11 +01:00
|
|
|
/**
|
|
|
|
* Remove the first node from a list and return it
|
|
|
|
*
|
|
|
|
* \return
|
|
|
|
* The first node in the list or \c NULL if the list is empty.
|
|
|
|
*
|
|
|
|
* \sa exec_list::get_head
|
|
|
|
*/
|
2014-06-10 06:44:56 +01:00
|
|
|
exec_node *pop_head();
|
2010-08-17 02:02:11 +01:00
|
|
|
|
2010-03-09 07:42:45 +00:00
|
|
|
/**
|
|
|
|
* Move all of the nodes from this list to the target list
|
|
|
|
*/
|
2014-06-10 06:44:56 +01:00
|
|
|
void move_nodes_to(exec_list *target);
|
2010-03-09 07:42:45 +00:00
|
|
|
|
2010-07-07 20:12:48 +01:00
|
|
|
/**
|
2014-07-08 20:20:58 +01:00
|
|
|
* Append all nodes from the source list to the end of the target list
|
2010-07-07 20:12:48 +01:00
|
|
|
*/
|
2014-06-10 06:44:56 +01:00
|
|
|
void append_list(exec_list *source);
|
2014-07-08 20:20:58 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Prepend all nodes from the source list to the beginning of the target
|
|
|
|
* list
|
|
|
|
*/
|
|
|
|
void prepend_list(exec_list *source);
|
2010-03-09 07:42:45 +00:00
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
2014-06-10 08:14:41 +01:00
|
|
|
static inline void
|
|
|
|
exec_list_make_empty(struct exec_list *list)
|
|
|
|
{
|
2016-06-27 22:42:57 +01:00
|
|
|
list->head_sentinel.next = &list->tail_sentinel;
|
|
|
|
list->head_sentinel.prev = NULL;
|
|
|
|
list->tail_sentinel.next = NULL;
|
|
|
|
list->tail_sentinel.prev = &list->head_sentinel;
|
2014-06-10 08:14:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
exec_list_is_empty(const struct exec_list *list)
|
|
|
|
{
|
|
|
|
/* There are three ways to test whether a list is empty or not.
|
|
|
|
*
|
2016-06-27 22:42:57 +01:00
|
|
|
* - Check to see if the head sentinel's \c next is the tail sentinel.
|
|
|
|
* - Check to see if the tail sentinel's \c prev is the head sentinel.
|
|
|
|
* - Check to see if the head is the sentinel node by test whether its
|
2014-06-10 08:14:41 +01:00
|
|
|
* \c next pointer is \c NULL.
|
|
|
|
*
|
|
|
|
* The first two methods tend to generate better code on modern systems
|
|
|
|
* because they save a pointer dereference.
|
|
|
|
*/
|
2016-06-27 22:42:57 +01:00
|
|
|
return list->head_sentinel.next == &list->tail_sentinel;
|
2014-06-10 08:14:41 +01:00
|
|
|
}
|
|
|
|
|
2019-04-08 19:10:08 +01:00
|
|
|
static inline bool
|
|
|
|
exec_list_is_singular(const struct exec_list *list)
|
|
|
|
{
|
|
|
|
return !exec_list_is_empty(list) &&
|
|
|
|
list->head_sentinel.next->next == &list->tail_sentinel;
|
|
|
|
}
|
|
|
|
|
2014-06-10 08:14:41 +01:00
|
|
|
static inline const struct exec_node *
|
|
|
|
exec_list_get_head_const(const struct exec_list *list)
|
|
|
|
{
|
2016-06-27 22:42:57 +01:00
|
|
|
return !exec_list_is_empty(list) ? list->head_sentinel.next : NULL;
|
2014-06-10 08:14:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct exec_node *
|
|
|
|
exec_list_get_head(struct exec_list *list)
|
|
|
|
{
|
2016-06-27 22:42:57 +01:00
|
|
|
return !exec_list_is_empty(list) ? list->head_sentinel.next : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline const struct exec_node *
|
|
|
|
exec_list_get_head_raw_const(const struct exec_list *list)
|
|
|
|
{
|
|
|
|
return list->head_sentinel.next;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct exec_node *
|
|
|
|
exec_list_get_head_raw(struct exec_list *list)
|
|
|
|
{
|
|
|
|
return list->head_sentinel.next;
|
2014-06-10 08:14:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline const struct exec_node *
|
|
|
|
exec_list_get_tail_const(const struct exec_list *list)
|
|
|
|
{
|
2016-06-27 22:42:57 +01:00
|
|
|
return !exec_list_is_empty(list) ? list->tail_sentinel.prev : NULL;
|
2014-06-10 08:14:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct exec_node *
|
|
|
|
exec_list_get_tail(struct exec_list *list)
|
|
|
|
{
|
2016-06-27 22:42:57 +01:00
|
|
|
return !exec_list_is_empty(list) ? list->tail_sentinel.prev : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline const struct exec_node *
|
|
|
|
exec_list_get_tail_raw_const(const struct exec_list *list)
|
|
|
|
{
|
|
|
|
return list->tail_sentinel.prev;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct exec_node *
|
|
|
|
exec_list_get_tail_raw(struct exec_list *list)
|
|
|
|
{
|
|
|
|
return list->tail_sentinel.prev;
|
2014-06-10 08:14:41 +01:00
|
|
|
}
|
|
|
|
|
2014-07-08 20:20:59 +01:00
|
|
|
static inline unsigned
|
|
|
|
exec_list_length(const struct exec_list *list)
|
|
|
|
{
|
|
|
|
unsigned size = 0;
|
2014-07-15 20:13:22 +01:00
|
|
|
struct exec_node *node;
|
2014-07-08 20:20:59 +01:00
|
|
|
|
2016-06-27 22:42:57 +01:00
|
|
|
for (node = list->head_sentinel.next; node->next != NULL; node = node->next) {
|
2014-07-08 20:20:59 +01:00
|
|
|
size++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2014-06-10 08:14:41 +01:00
|
|
|
static inline void
|
|
|
|
exec_list_push_head(struct exec_list *list, struct exec_node *n)
|
|
|
|
{
|
2016-06-27 22:42:57 +01:00
|
|
|
n->next = list->head_sentinel.next;
|
|
|
|
n->prev = &list->head_sentinel;
|
2014-06-10 08:14:41 +01:00
|
|
|
|
|
|
|
n->next->prev = n;
|
2016-06-27 22:42:57 +01:00
|
|
|
list->head_sentinel.next = n;
|
2014-06-10 08:14:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
exec_list_push_tail(struct exec_list *list, struct exec_node *n)
|
|
|
|
{
|
2016-06-27 22:42:57 +01:00
|
|
|
n->next = &list->tail_sentinel;
|
|
|
|
n->prev = list->tail_sentinel.prev;
|
2014-06-10 08:14:41 +01:00
|
|
|
|
|
|
|
n->prev->next = n;
|
2016-06-27 22:42:57 +01:00
|
|
|
list->tail_sentinel.prev = n;
|
2014-06-10 08:14:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
exec_list_push_degenerate_list_at_head(struct exec_list *list, struct exec_node *n)
|
|
|
|
{
|
|
|
|
assert(n->prev->next == n);
|
|
|
|
|
2016-06-27 22:42:57 +01:00
|
|
|
n->prev->next = list->head_sentinel.next;
|
|
|
|
list->head_sentinel.next->prev = n->prev;
|
|
|
|
n->prev = &list->head_sentinel;
|
|
|
|
list->head_sentinel.next = n;
|
2014-06-10 08:14:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct exec_node *
|
|
|
|
exec_list_pop_head(struct exec_list *list)
|
|
|
|
{
|
|
|
|
struct exec_node *const n = exec_list_get_head(list);
|
|
|
|
if (n != NULL)
|
|
|
|
exec_node_remove(n);
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
exec_list_move_nodes_to(struct exec_list *list, struct exec_list *target)
|
|
|
|
{
|
|
|
|
if (exec_list_is_empty(list)) {
|
|
|
|
exec_list_make_empty(target);
|
|
|
|
} else {
|
2016-06-27 22:42:57 +01:00
|
|
|
target->head_sentinel.next = list->head_sentinel.next;
|
|
|
|
target->head_sentinel.prev = NULL;
|
|
|
|
target->tail_sentinel.next = NULL;
|
|
|
|
target->tail_sentinel.prev = list->tail_sentinel.prev;
|
2014-06-10 08:14:41 +01:00
|
|
|
|
2016-06-27 22:42:57 +01:00
|
|
|
target->head_sentinel.next->prev = &target->head_sentinel;
|
|
|
|
target->tail_sentinel.prev->next = &target->tail_sentinel;
|
2014-06-10 08:14:41 +01:00
|
|
|
|
|
|
|
exec_list_make_empty(list);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
exec_list_append(struct exec_list *list, struct exec_list *source)
|
|
|
|
{
|
|
|
|
if (exec_list_is_empty(source))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Link the first node of the source with the last node of the target list.
|
|
|
|
*/
|
2016-06-27 22:42:57 +01:00
|
|
|
list->tail_sentinel.prev->next = source->head_sentinel.next;
|
|
|
|
source->head_sentinel.next->prev = list->tail_sentinel.prev;
|
2014-06-10 08:14:41 +01:00
|
|
|
|
|
|
|
/* Make the tail of the source list be the tail of the target list.
|
|
|
|
*/
|
2016-06-27 22:42:57 +01:00
|
|
|
list->tail_sentinel.prev = source->tail_sentinel.prev;
|
|
|
|
list->tail_sentinel.prev->next = &list->tail_sentinel;
|
2014-06-10 08:14:41 +01:00
|
|
|
|
|
|
|
/* Make the source list empty for good measure.
|
|
|
|
*/
|
|
|
|
exec_list_make_empty(source);
|
|
|
|
}
|
|
|
|
|
2019-03-12 02:01:34 +00:00
|
|
|
static inline void
|
|
|
|
exec_node_insert_list_after(struct exec_node *n, struct exec_list *after)
|
|
|
|
{
|
|
|
|
if (exec_list_is_empty(after))
|
|
|
|
return;
|
|
|
|
|
|
|
|
after->tail_sentinel.prev->next = n->next;
|
|
|
|
after->head_sentinel.next->prev = n;
|
|
|
|
|
|
|
|
n->next->prev = after->tail_sentinel.prev;
|
|
|
|
n->next = after->head_sentinel.next;
|
|
|
|
|
|
|
|
exec_list_make_empty(after);
|
|
|
|
}
|
|
|
|
|
2014-07-08 20:20:58 +01:00
|
|
|
static inline void
|
|
|
|
exec_list_prepend(struct exec_list *list, struct exec_list *source)
|
|
|
|
{
|
|
|
|
exec_list_append(source, list);
|
|
|
|
exec_list_move_nodes_to(source, list);
|
|
|
|
}
|
|
|
|
|
2014-06-10 08:14:41 +01:00
|
|
|
static inline void
|
|
|
|
exec_node_insert_list_before(struct exec_node *n, struct exec_list *before)
|
|
|
|
{
|
|
|
|
if (exec_list_is_empty(before))
|
|
|
|
return;
|
|
|
|
|
2016-06-27 22:42:57 +01:00
|
|
|
before->tail_sentinel.prev->next = n;
|
|
|
|
before->head_sentinel.next->prev = n->prev;
|
2014-06-10 08:14:41 +01:00
|
|
|
|
2016-06-27 22:42:57 +01:00
|
|
|
n->prev->next = before->head_sentinel.next;
|
|
|
|
n->prev = before->tail_sentinel.prev;
|
2014-06-10 08:14:41 +01:00
|
|
|
|
|
|
|
exec_list_make_empty(before);
|
|
|
|
}
|
2010-08-27 21:53:56 +01:00
|
|
|
|
2014-11-05 21:57:09 +00:00
|
|
|
static inline void
|
|
|
|
exec_list_validate(const struct exec_list *list)
|
|
|
|
{
|
2014-11-07 23:33:41 +00:00
|
|
|
const struct exec_node *node;
|
|
|
|
|
2016-06-27 22:42:57 +01:00
|
|
|
assert(list->head_sentinel.next->prev == &list->head_sentinel);
|
|
|
|
assert(list->head_sentinel.prev == NULL);
|
|
|
|
assert(list->tail_sentinel.next == NULL);
|
|
|
|
assert(list->tail_sentinel.prev->next == &list->tail_sentinel);
|
2014-11-05 21:57:09 +00:00
|
|
|
|
|
|
|
/* We could try to use one of the interators below for this but they all
|
|
|
|
* either require C++ or assume the exec_node is embedded in a structure
|
|
|
|
* which is not the case for this function.
|
|
|
|
*/
|
2016-06-27 22:42:57 +01:00
|
|
|
for (node = list->head_sentinel.next; node->next != NULL; node = node->next) {
|
2014-11-05 21:57:09 +00:00
|
|
|
assert(node->next->prev == node);
|
|
|
|
assert(node->prev->next == node);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-27 21:53:56 +01:00
|
|
|
#ifdef __cplusplus
|
2014-06-10 06:44:56 +01:00
|
|
|
inline void exec_list::make_empty()
|
|
|
|
{
|
2014-06-10 08:23:41 +01:00
|
|
|
exec_list_make_empty(this);
|
2014-06-10 06:44:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline bool exec_list::is_empty() const
|
|
|
|
{
|
2014-06-10 08:23:41 +01:00
|
|
|
return exec_list_is_empty(this);
|
2014-06-10 06:44:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline const exec_node *exec_list::get_head() const
|
|
|
|
{
|
2014-06-10 08:23:41 +01:00
|
|
|
return exec_list_get_head_const(this);
|
2014-06-10 06:44:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline exec_node *exec_list::get_head()
|
|
|
|
{
|
2014-06-10 08:23:41 +01:00
|
|
|
return exec_list_get_head(this);
|
2014-06-10 06:44:56 +01:00
|
|
|
}
|
|
|
|
|
2016-06-27 22:42:57 +01:00
|
|
|
inline const exec_node *exec_list::get_head_raw() const
|
|
|
|
{
|
|
|
|
return exec_list_get_head_raw_const(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline exec_node *exec_list::get_head_raw()
|
|
|
|
{
|
|
|
|
return exec_list_get_head_raw(this);
|
|
|
|
}
|
|
|
|
|
2014-06-10 06:44:56 +01:00
|
|
|
inline const exec_node *exec_list::get_tail() const
|
|
|
|
{
|
2014-06-10 08:23:41 +01:00
|
|
|
return exec_list_get_tail_const(this);
|
2014-06-10 06:44:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline exec_node *exec_list::get_tail()
|
|
|
|
{
|
2014-06-10 08:23:41 +01:00
|
|
|
return exec_list_get_tail(this);
|
2014-06-10 06:44:56 +01:00
|
|
|
}
|
|
|
|
|
2016-06-27 22:42:57 +01:00
|
|
|
inline const exec_node *exec_list::get_tail_raw() const
|
|
|
|
{
|
|
|
|
return exec_list_get_tail_raw_const(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline exec_node *exec_list::get_tail_raw()
|
|
|
|
{
|
|
|
|
return exec_list_get_tail_raw(this);
|
|
|
|
}
|
|
|
|
|
2014-07-08 20:20:59 +01:00
|
|
|
inline unsigned exec_list::length() const
|
|
|
|
{
|
|
|
|
return exec_list_length(this);
|
|
|
|
}
|
|
|
|
|
2014-06-10 06:44:56 +01:00
|
|
|
inline void exec_list::push_head(exec_node *n)
|
|
|
|
{
|
2014-06-10 08:23:41 +01:00
|
|
|
exec_list_push_head(this, n);
|
2014-06-10 06:44:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void exec_list::push_tail(exec_node *n)
|
|
|
|
{
|
2014-06-10 08:23:41 +01:00
|
|
|
exec_list_push_tail(this, n);
|
2014-06-10 06:44:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void exec_list::push_degenerate_list_at_head(exec_node *n)
|
|
|
|
{
|
2014-06-10 08:23:41 +01:00
|
|
|
exec_list_push_degenerate_list_at_head(this, n);
|
2014-06-10 06:44:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline exec_node *exec_list::pop_head()
|
|
|
|
{
|
2014-06-10 08:23:41 +01:00
|
|
|
return exec_list_pop_head(this);
|
2014-06-10 06:44:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void exec_list::move_nodes_to(exec_list *target)
|
|
|
|
{
|
2014-06-10 08:23:41 +01:00
|
|
|
exec_list_move_nodes_to(this, target);
|
2014-06-10 06:44:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void exec_list::append_list(exec_list *source)
|
|
|
|
{
|
2014-06-10 08:23:41 +01:00
|
|
|
exec_list_append(this, source);
|
2014-06-10 06:44:56 +01:00
|
|
|
}
|
|
|
|
|
2019-03-12 02:01:34 +00:00
|
|
|
inline void exec_node::insert_after(exec_list *after)
|
|
|
|
{
|
|
|
|
exec_node_insert_list_after(this, after);
|
|
|
|
}
|
|
|
|
|
2014-07-08 20:20:58 +01:00
|
|
|
inline void exec_list::prepend_list(exec_list *source)
|
|
|
|
{
|
|
|
|
exec_list_prepend(this, source);
|
|
|
|
}
|
|
|
|
|
2010-08-27 21:53:56 +01:00
|
|
|
inline void exec_node::insert_before(exec_list *before)
|
|
|
|
{
|
2014-06-10 08:23:41 +01:00
|
|
|
exec_node_insert_list_before(this, before);
|
2010-08-27 21:53:56 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-03-10 12:21:34 +00:00
|
|
|
#define exec_node_typed_forward(__node, __type) \
|
|
|
|
(!exec_node_is_tail_sentinel(__node) ? (__type) (__node) : NULL)
|
2014-06-25 00:36:04 +01:00
|
|
|
|
2020-03-10 12:21:34 +00:00
|
|
|
#define exec_node_typed_backward(__node, __type) \
|
|
|
|
(!exec_node_is_head_sentinel(__node) ? (__type) (__node) : NULL)
|
|
|
|
|
|
|
|
#define foreach_in_list(__type, __inst, __list) \
|
|
|
|
for (__type *__inst = exec_node_typed_forward((__list)->head_sentinel.next, __type *); \
|
|
|
|
(__inst) != NULL; \
|
|
|
|
(__inst) = exec_node_typed_forward((__inst)->next, __type *))
|
|
|
|
|
|
|
|
#define foreach_in_list_reverse(__type, __inst, __list) \
|
|
|
|
for (__type *__inst = exec_node_typed_backward((__list)->tail_sentinel.prev, __type *); \
|
|
|
|
(__inst) != NULL; \
|
|
|
|
(__inst) = exec_node_typed_backward((__inst)->prev, __type *))
|
2014-06-25 00:36:04 +01:00
|
|
|
|
2014-06-25 00:32:29 +01:00
|
|
|
/**
|
|
|
|
* This version is safe even if the current node is removed.
|
2020-03-10 12:21:34 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#define foreach_in_list_safe(__type, __node, __list) \
|
|
|
|
for (__type *__node = exec_node_typed_forward((__list)->head_sentinel.next, __type *), \
|
|
|
|
*__next = (__node) ? exec_node_typed_forward((__list)->head_sentinel.next->next, __type *) : NULL; \
|
|
|
|
(__node) != NULL; \
|
|
|
|
(__node) = __next, __next = __next ? exec_node_typed_forward(__next->next, __type *) : NULL)
|
|
|
|
|
|
|
|
#define foreach_in_list_reverse_safe(__type, __node, __list) \
|
|
|
|
for (__type *__node = exec_node_typed_backward((__list)->tail_sentinel.prev, __type *), \
|
|
|
|
*__prev = (__node) ? exec_node_typed_backward((__list)->tail_sentinel.prev->prev, __type *) : NULL; \
|
|
|
|
(__node) != NULL; \
|
|
|
|
(__node) = __prev, __prev = __prev ? exec_node_typed_backward(__prev->prev, __type *) : NULL)
|
|
|
|
|
|
|
|
#define foreach_in_list_use_after(__type, __inst, __list) \
|
|
|
|
__type *__inst; \
|
|
|
|
for ((__inst) = exec_node_typed_forward((__list)->head_sentinel.next, __type *); \
|
|
|
|
(__inst) != NULL; \
|
|
|
|
(__inst) = exec_node_typed_forward((__inst)->next, __type *))
|
|
|
|
|
glsl: Use a new foreach_two_lists macro for walking two lists at once.
When handling function calls, we often want to walk through the list of
formal parameters and list of actual parameters at the same time.
(Both are guaranteed to be the same length.)
Previously, we used a pattern of:
exec_list_iterator 1st_iter = <1st list>.iterator();
foreach_iter(exec_list_iterator, 2nd_iter, <2nd list>) {
...
1st_iter.next();
}
This was awkward, since you had to manually iterate through one of
the two lists.
This patch introduces a foreach_two_lists macro which safely walks
through two lists at the same time, so you can simply do:
foreach_two_lists(1st_node, <1st list>, 2nd_node, <2nd list>) {
...
}
v2: Rename macro from foreach_list2 to foreach_two_lists, as suggested
by Ian Romanick.
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Matt Turner <mattst88@gmail.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
2014-01-11 00:39:17 +00:00
|
|
|
/**
|
|
|
|
* Iterate through two lists at once. Stops at the end of the shorter list.
|
|
|
|
*
|
|
|
|
* This is safe against either current node being removed or replaced.
|
|
|
|
*/
|
|
|
|
#define foreach_two_lists(__node1, __list1, __node2, __list2) \
|
2016-06-27 22:42:57 +01:00
|
|
|
for (struct exec_node * __node1 = (__list1)->head_sentinel.next, \
|
|
|
|
* __node2 = (__list2)->head_sentinel.next, \
|
2014-06-10 09:00:01 +01:00
|
|
|
* __next1 = __node1->next, \
|
|
|
|
* __next2 = __node2->next \
|
glsl: Use a new foreach_two_lists macro for walking two lists at once.
When handling function calls, we often want to walk through the list of
formal parameters and list of actual parameters at the same time.
(Both are guaranteed to be the same length.)
Previously, we used a pattern of:
exec_list_iterator 1st_iter = <1st list>.iterator();
foreach_iter(exec_list_iterator, 2nd_iter, <2nd list>) {
...
1st_iter.next();
}
This was awkward, since you had to manually iterate through one of
the two lists.
This patch introduces a foreach_two_lists macro which safely walks
through two lists at the same time, so you can simply do:
foreach_two_lists(1st_node, <1st list>, 2nd_node, <2nd list>) {
...
}
v2: Rename macro from foreach_list2 to foreach_two_lists, as suggested
by Ian Romanick.
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Matt Turner <mattst88@gmail.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
2014-01-11 00:39:17 +00:00
|
|
|
; __next1 != NULL && __next2 != NULL \
|
|
|
|
; __node1 = __next1, \
|
|
|
|
__node2 = __next2, \
|
|
|
|
__next1 = __next1->next, \
|
|
|
|
__next2 = __next2->next)
|
|
|
|
|
2020-03-10 12:21:34 +00:00
|
|
|
#define exec_node_data_forward(type, node, field) \
|
|
|
|
(!exec_node_is_tail_sentinel(node) ? exec_node_data(type, node, field) : NULL)
|
|
|
|
|
|
|
|
#define exec_node_data_backward(type, node, field) \
|
|
|
|
(!exec_node_is_head_sentinel(node) ? exec_node_data(type, node, field) : NULL)
|
|
|
|
|
|
|
|
#define foreach_list_typed(__type, __node, __field, __list) \
|
|
|
|
for (__type * __node = \
|
|
|
|
exec_node_data_forward(__type, (__list)->head_sentinel.next, __field); \
|
|
|
|
(__node) != NULL; \
|
|
|
|
(__node) = exec_node_data_forward(__type, (__node)->__field.next, __field))
|
|
|
|
|
|
|
|
#define foreach_list_typed_from(__type, __node, __field, __list, __start) \
|
|
|
|
for (__type * __node = exec_node_data_forward(__type, (__start), __field); \
|
|
|
|
(__node) != NULL; \
|
|
|
|
(__node) = exec_node_data_forward(__type, (__node)->__field.next, __field))
|
|
|
|
|
|
|
|
#define foreach_list_typed_reverse(__type, __node, __field, __list) \
|
|
|
|
for (__type * __node = \
|
|
|
|
exec_node_data_backward(__type, (__list)->tail_sentinel.prev, __field); \
|
|
|
|
(__node) != NULL; \
|
|
|
|
(__node) = exec_node_data_backward(__type, (__node)->__field.prev, __field))
|
|
|
|
|
|
|
|
#define foreach_list_typed_safe(__type, __node, __field, __list) \
|
|
|
|
for (__type * __node = \
|
|
|
|
exec_node_data_forward(__type, (__list)->head_sentinel.next, __field), \
|
|
|
|
* __next = (__node) ? \
|
|
|
|
exec_node_data_forward(__type, (__node)->__field.next, __field) : NULL; \
|
|
|
|
(__node) != NULL; \
|
|
|
|
(__node) = __next, __next = (__next && (__next)->__field.next) ? \
|
|
|
|
exec_node_data_forward(__type, (__next)->__field.next, __field) : NULL)
|
|
|
|
|
|
|
|
#define foreach_list_typed_reverse_safe(__type, __node, __field, __list) \
|
|
|
|
for (__type * __node = \
|
|
|
|
exec_node_data_backward(__type, (__list)->tail_sentinel.prev, __field), \
|
|
|
|
* __prev = (__node) ? \
|
|
|
|
exec_node_data_backward(__type, (__node)->__field.prev, __field) : NULL; \
|
|
|
|
(__node) != NULL; \
|
|
|
|
(__node) = __prev, __prev = (__prev && (__prev)->__field.prev) ? \
|
|
|
|
exec_node_data_backward(__type, (__prev)->__field.prev, __field) : NULL)
|
2014-11-08 02:26:50 +00:00
|
|
|
|
2010-03-09 07:42:45 +00:00
|
|
|
#endif /* LIST_CONTAINER_H */
|