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
|
|
|
|
* sentinel.
|
2010-03-09 07:42:45 +00:00
|
|
|
*
|
|
|
|
* Instead of tracking two separate \c node structures and a \c list structure
|
2010-07-29 21:52:25 +01:00
|
|
|
* that points to them, the sentinel nodes are in a single structure. Noting
|
|
|
|
* that each sentinel node always has one \c NULL pointer, the \c NULL
|
2010-03-09 07:42:45 +00:00
|
|
|
* pointers occupy the same memory location. In the \c list structure
|
|
|
|
* contains a the following:
|
|
|
|
*
|
|
|
|
* - A \c head pointer that represents the \c next pointer of the
|
2010-07-29 21:52:25 +01:00
|
|
|
* head sentinel node.
|
2010-03-09 07:42:45 +00:00
|
|
|
* - A \c tail pointer that represents the \c prev pointer of the head
|
2010-07-29 21:52:25 +01:00
|
|
|
* sentinel node and the \c next pointer of the tail sentinel node. This
|
2010-03-09 07:42:45 +00:00
|
|
|
* pointer is \b always \c NULL.
|
|
|
|
* - A \c tail_prev pointer that represents the \c prev pointer of the
|
2010-07-29 21:52:25 +01:00
|
|
|
* tail sentinel node.
|
2010-03-09 07:42:45 +00:00
|
|
|
*
|
|
|
|
* Therefore, if \c head->next is \c NULL or \c tail_prev->prev is \c NULL,
|
|
|
|
* the list is empty.
|
|
|
|
*
|
|
|
|
* To anyone familiar with "exec lists" on the Amiga, this structure should
|
|
|
|
* be immediately recognizable. See the following link for the original Amiga
|
|
|
|
* operating system documentation on the subject.
|
|
|
|
*
|
|
|
|
* http://www.natami.net/dev/Libraries_Manual_guide/node02D7.html
|
|
|
|
*
|
|
|
|
* \author Ian Romanick <ian.d.romanick@intel.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
#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
|
2013-09-18 22:05:36 +01:00
|
|
|
DECLARE_RALLOC_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);
|
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) \
|
|
|
|
((type *) (((char *) node) - exec_list_offsetof(type, field, node)))
|
|
|
|
|
2010-03-09 07:42:45 +00:00
|
|
|
#ifdef __cplusplus
|
|
|
|
struct exec_node;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
struct exec_list {
|
|
|
|
struct exec_node *head;
|
|
|
|
struct exec_node *tail;
|
|
|
|
struct exec_node *tail_pred;
|
|
|
|
|
|
|
|
#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();
|
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();
|
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)
|
|
|
|
{
|
|
|
|
list->head = (struct exec_node *) & list->tail;
|
|
|
|
list->tail = NULL;
|
|
|
|
list->tail_pred = (struct exec_node *) & list->head;
|
|
|
|
}
|
|
|
|
|
|
|
|
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.
|
|
|
|
*
|
|
|
|
* - Check to see if the \c head points to the \c tail.
|
|
|
|
* - Check to see if the \c tail_pred points to the \c head.
|
|
|
|
* - Check to see if the \c head is the sentinel node by test whether its
|
|
|
|
* \c next pointer is \c NULL.
|
|
|
|
*
|
|
|
|
* The first two methods tend to generate better code on modern systems
|
|
|
|
* because they save a pointer dereference.
|
|
|
|
*/
|
|
|
|
return list->head == (struct exec_node *) &list->tail;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline const struct exec_node *
|
|
|
|
exec_list_get_head_const(const struct exec_list *list)
|
|
|
|
{
|
|
|
|
return !exec_list_is_empty(list) ? list->head : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct exec_node *
|
|
|
|
exec_list_get_head(struct exec_list *list)
|
|
|
|
{
|
|
|
|
return !exec_list_is_empty(list) ? list->head : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline const struct exec_node *
|
|
|
|
exec_list_get_tail_const(const struct exec_list *list)
|
|
|
|
{
|
|
|
|
return !exec_list_is_empty(list) ? list->tail_pred : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct exec_node *
|
|
|
|
exec_list_get_tail(struct exec_list *list)
|
|
|
|
{
|
|
|
|
return !exec_list_is_empty(list) ? list->tail_pred : NULL;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2014-07-15 20:13:22 +01:00
|
|
|
for (node = list->head; 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)
|
|
|
|
{
|
|
|
|
n->next = list->head;
|
|
|
|
n->prev = (struct exec_node *) &list->head;
|
|
|
|
|
|
|
|
n->next->prev = n;
|
|
|
|
list->head = n;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
exec_list_push_tail(struct exec_list *list, struct exec_node *n)
|
|
|
|
{
|
|
|
|
n->next = (struct exec_node *) &list->tail;
|
|
|
|
n->prev = list->tail_pred;
|
|
|
|
|
|
|
|
n->prev->next = n;
|
|
|
|
list->tail_pred = n;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
exec_list_push_degenerate_list_at_head(struct exec_list *list, struct exec_node *n)
|
|
|
|
{
|
|
|
|
assert(n->prev->next == n);
|
|
|
|
|
|
|
|
n->prev->next = list->head;
|
|
|
|
list->head->prev = n->prev;
|
|
|
|
n->prev = (struct exec_node *) &list->head;
|
|
|
|
list->head = n;
|
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
|
|
|
target->head = list->head;
|
|
|
|
target->tail = NULL;
|
|
|
|
target->tail_pred = list->tail_pred;
|
|
|
|
|
|
|
|
target->head->prev = (struct exec_node *) &target->head;
|
|
|
|
target->tail_pred->next = (struct exec_node *) &target->tail;
|
|
|
|
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
list->tail_pred->next = source->head;
|
|
|
|
source->head->prev = list->tail_pred;
|
|
|
|
|
|
|
|
/* Make the tail of the source list be the tail of the target list.
|
|
|
|
*/
|
|
|
|
list->tail_pred = source->tail_pred;
|
|
|
|
list->tail_pred->next = (struct exec_node *) &list->tail;
|
|
|
|
|
|
|
|
/* Make the source list empty for good measure.
|
|
|
|
*/
|
|
|
|
exec_list_make_empty(source);
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
before->tail_pred->next = n;
|
|
|
|
before->head->prev = n->prev;
|
|
|
|
|
|
|
|
n->prev->next = before->head;
|
|
|
|
n->prev = before->tail_pred;
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2014-11-05 21:57:09 +00:00
|
|
|
assert(list->head->prev == (const struct exec_node *) &list->head);
|
|
|
|
assert(list->tail == NULL);
|
|
|
|
assert(list->tail_pred->next == (const struct exec_node *) &list->tail);
|
|
|
|
|
|
|
|
/* 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.
|
|
|
|
*/
|
2014-11-11 18:12:24 +00:00
|
|
|
for (node = list->head; 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
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
2014-06-25 00:36:04 +01:00
|
|
|
#define foreach_in_list(__type, __inst, __list) \
|
|
|
|
for (__type *(__inst) = (__type *)(__list)->head; \
|
|
|
|
!(__inst)->is_tail_sentinel(); \
|
|
|
|
(__inst) = (__type *)(__inst)->next)
|
|
|
|
|
2014-07-06 06:04:45 +01:00
|
|
|
#define foreach_in_list_reverse(__type, __inst, __list) \
|
|
|
|
for (__type *(__inst) = (__type *)(__list)->tail_pred; \
|
|
|
|
!(__inst)->is_head_sentinel(); \
|
2014-06-25 00:36:04 +01:00
|
|
|
(__inst) = (__type *)(__inst)->prev)
|
|
|
|
|
2014-06-25 00:32:29 +01:00
|
|
|
/**
|
|
|
|
* This version is safe even if the current node is removed.
|
|
|
|
*/
|
|
|
|
#define foreach_in_list_safe(__type, __node, __list) \
|
|
|
|
for (__type *__node = (__type *)(__list)->head, \
|
|
|
|
*__next = (__type *)__node->next; \
|
|
|
|
__next != NULL; \
|
|
|
|
__node = __next, __next = (__type *)__next->next)
|
|
|
|
|
2014-12-31 00:14:25 +00:00
|
|
|
#define foreach_in_list_reverse_safe(__type, __node, __list) \
|
|
|
|
for (__type *__node = (__type *)(__list)->tail_pred, \
|
|
|
|
*__prev = (__type *)__node->prev; \
|
|
|
|
__prev != NULL; \
|
|
|
|
__node = __prev, __prev = (__type *)__prev->prev)
|
|
|
|
|
2014-06-25 18:32:38 +01:00
|
|
|
#define foreach_in_list_use_after(__type, __inst, __list) \
|
|
|
|
__type *(__inst); \
|
|
|
|
for ((__inst) = (__type *)(__list)->head; \
|
|
|
|
!(__inst)->is_tail_sentinel(); \
|
|
|
|
(__inst) = (__type *)(__inst)->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
|
|
|
/**
|
|
|
|
* 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) \
|
2014-06-10 09:00:01 +01:00
|
|
|
for (struct exec_node * __node1 = (__list1)->head, \
|
|
|
|
* __node2 = (__list2)->head, \
|
|
|
|
* __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)
|
|
|
|
|
2010-05-11 01:40:41 +01:00
|
|
|
#define foreach_list_typed(__type, __node, __field, __list) \
|
|
|
|
for (__type * __node = \
|
|
|
|
exec_node_data(__type, (__list)->head, __field); \
|
|
|
|
(__node)->__field.next != NULL; \
|
|
|
|
(__node) = exec_node_data(__type, (__node)->__field.next, __field))
|
|
|
|
|
2014-07-22 01:11:53 +01:00
|
|
|
#define foreach_list_typed_reverse(__type, __node, __field, __list) \
|
|
|
|
for (__type * __node = \
|
|
|
|
exec_node_data(__type, (__list)->tail_pred, __field); \
|
|
|
|
(__node)->__field.prev != NULL; \
|
|
|
|
(__node) = exec_node_data(__type, (__node)->__field.prev, __field))
|
|
|
|
|
2014-06-25 18:51:30 +01:00
|
|
|
#define foreach_list_typed_safe(__type, __node, __field, __list) \
|
|
|
|
for (__type * __node = \
|
|
|
|
exec_node_data(__type, (__list)->head, __field), \
|
|
|
|
* __next = \
|
|
|
|
exec_node_data(__type, (__node)->__field.next, __field); \
|
|
|
|
__next != NULL; \
|
|
|
|
__node = __next, __next = \
|
|
|
|
exec_node_data(__type, (__next)->__field.next, __field))
|
|
|
|
|
2014-11-08 02:26:50 +00:00
|
|
|
#define foreach_list_typed_safe_reverse(__type, __node, __field, __list) \
|
|
|
|
for (__type * __node = \
|
|
|
|
exec_node_data(__type, (__list)->tail_pred, __field), \
|
|
|
|
* __prev = \
|
|
|
|
exec_node_data(__type, (__node)->__field.prev, __field); \
|
|
|
|
__prev != NULL; \
|
|
|
|
__node = __prev, __prev = \
|
|
|
|
exec_node_data(__type, (__prev)->__field.prev, __field))
|
|
|
|
|
2010-03-09 07:42:45 +00:00
|
|
|
#endif /* LIST_CONTAINER_H */
|