Home | History | Annotate | Download | only in glsl
      1 /*
      2  * Copyright  2008, 2010 Intel Corporation
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     21  * DEALINGS IN THE SOFTWARE.
     22  */
     23 
     24 /**
     25  * \file list.h
     26  * \brief Doubly-linked list abstract container type.
     27  *
     28  * Each doubly-linked list has a sentinel head and tail node.  These nodes
     29  * contain no data.  The head sentinel can be identified by its \c prev
     30  * pointer being \c NULL.  The tail sentinel can be identified by its
     31  * \c next pointer being \c NULL.
     32  *
     33  * A list is empty if either the head sentinel's \c next pointer points to the
     34  * tail sentinel or the tail sentinel's \c prev poiner points to the head
     35  * sentinel.
     36  *
     37  * Instead of tracking two separate \c node structures and a \c list structure
     38  * that points to them, the sentinel nodes are in a single structure.  Noting
     39  * that each sentinel node always has one \c NULL pointer, the \c NULL
     40  * pointers occupy the same memory location.  In the \c list structure
     41  * contains a the following:
     42  *
     43  *   - A \c head pointer that represents the \c next pointer of the
     44  *     head sentinel node.
     45  *   - A \c tail pointer that represents the \c prev pointer of the head
     46  *     sentinel node and the \c next pointer of the tail sentinel node.  This
     47  *     pointer is \b always \c NULL.
     48  *   - A \c tail_prev pointer that represents the \c prev pointer of the
     49  *     tail sentinel node.
     50  *
     51  * Therefore, if \c head->next is \c NULL or \c tail_prev->prev is \c NULL,
     52  * the list is empty.
     53  *
     54  * To anyone familiar with "exec lists" on the Amiga, this structure should
     55  * be immediately recognizable.  See the following link for the original Amiga
     56  * operating system documentation on the subject.
     57  *
     58  * http://www.natami.net/dev/Libraries_Manual_guide/node02D7.html
     59  *
     60  * \author Ian Romanick <ian.d.romanick (at) intel.com>
     61  */
     62 
     63 #pragma once
     64 #ifndef LIST_CONTAINER_H
     65 #define LIST_CONTAINER_H
     66 
     67 #ifndef __cplusplus
     68 #include <stddef.h>
     69 #include <hieralloc.h>
     70 #else
     71 extern "C" {
     72 #include <hieralloc.h>
     73 }
     74 #endif
     75 
     76 #include <assert.h>
     77 
     78 struct exec_node {
     79    struct exec_node *next;
     80    struct exec_node *prev;
     81 
     82 #ifdef __cplusplus
     83    /* Callers of this hieralloc-based new need not call delete. It's
     84     * easier to just hieralloc_free 'ctx' (or any of its ancestors). */
     85    static void* operator new(size_t size, void *ctx)
     86    {
     87       void *node;
     88 
     89       node = hieralloc_size(ctx, size);
     90       assert(node != NULL);
     91 
     92       return node;
     93    }
     94 
     95    /* If the user *does* call delete, that's OK, we will just
     96     * hieralloc_free in that case. */
     97    static void operator delete(void *node)
     98    {
     99       hieralloc_free(node);
    100    }
    101 
    102    exec_node() : next(NULL), prev(NULL)
    103    {
    104       /* empty */
    105    }
    106 
    107    const exec_node *get_next() const
    108    {
    109       return next;
    110    }
    111 
    112    exec_node *get_next()
    113    {
    114       return next;
    115    }
    116 
    117    const exec_node *get_prev() const
    118    {
    119       return prev;
    120    }
    121 
    122    exec_node *get_prev()
    123    {
    124       return prev;
    125    }
    126 
    127    void remove()
    128    {
    129       next->prev = prev;
    130       prev->next = next;
    131       next = NULL;
    132       prev = NULL;
    133    }
    134 
    135    /**
    136     * Link a node with itself
    137     *
    138     * This creates a sort of degenerate list that is occasionally useful.
    139     */
    140    void self_link()
    141    {
    142       next = this;
    143       prev = this;
    144    }
    145 
    146    /**
    147     * Insert a node in the list after the current node
    148     */
    149    void insert_after(exec_node *after)
    150    {
    151       after->next = this->next;
    152       after->prev = this;
    153 
    154       this->next->prev = after;
    155       this->next = after;
    156    }
    157    /**
    158     * Insert a node in the list before the current node
    159     */
    160    void insert_before(exec_node *before)
    161    {
    162       before->next = this;
    163       before->prev = this->prev;
    164 
    165       this->prev->next = before;
    166       this->prev = before;
    167    }
    168 
    169    /**
    170     * Insert another list in the list before the current node
    171     */
    172    void insert_before(struct exec_list *before);
    173 
    174    /**
    175     * Replace the current node with the given node.
    176     */
    177    void replace_with(exec_node *replacement)
    178    {
    179       replacement->prev = this->prev;
    180       replacement->next = this->next;
    181 
    182       this->prev->next = replacement;
    183       this->next->prev = replacement;
    184    }
    185 
    186    /**
    187     * Is this the sentinel at the tail of the list?
    188     */
    189    bool is_tail_sentinel() const
    190    {
    191       return this->next == NULL;
    192    }
    193 
    194    /**
    195     * Is this the sentinel at the head of the list?
    196     */
    197    bool is_head_sentinel() const
    198    {
    199       return this->prev == NULL;
    200    }
    201 #endif
    202 };
    203 
    204 
    205 #ifdef __cplusplus
    206 /* This macro will not work correctly if `t' uses virtual inheritance.  If you
    207  * are using virtual inheritance, you deserve a slow and painful death.  Enjoy!
    208  */
    209 #define exec_list_offsetof(t, f, p) \
    210    (((char *) &((t *) p)->f) - ((char *) p))
    211 #else
    212 #define exec_list_offsetof(t, f, p) offsetof(t, f)
    213 #endif
    214 
    215 /**
    216  * Get a pointer to the structure containing an exec_node
    217  *
    218  * Given a pointer to an \c exec_node embedded in a structure, get a pointer to
    219  * the containing structure.
    220  *
    221  * \param type  Base type of the structure containing the node
    222  * \param node  Pointer to the \c exec_node
    223  * \param field Name of the field in \c type that is the embedded \c exec_node
    224  */
    225 #define exec_node_data(type, node, field) \
    226    ((type *) (((char *) node) - exec_list_offsetof(type, field, node)))
    227 
    228 #ifdef __cplusplus
    229 struct exec_node;
    230 
    231 class iterator {
    232 public:
    233    void next()
    234    {
    235    }
    236 
    237    void *get()
    238    {
    239       return NULL;
    240    }
    241 
    242    bool has_next() const
    243    {
    244       return false;
    245    }
    246 };
    247 
    248 class exec_list_iterator : public iterator {
    249 public:
    250    exec_list_iterator(exec_node *n) : node(n), _next(n->next)
    251    {
    252       /* empty */
    253    }
    254 
    255    void next()
    256    {
    257       node = _next;
    258       _next = node->next;
    259    }
    260 
    261    void remove()
    262    {
    263       node->remove();
    264    }
    265 
    266    exec_node *get()
    267    {
    268       return node;
    269    }
    270 
    271    bool has_next() const
    272    {
    273       return _next != NULL;
    274    }
    275 
    276 private:
    277    exec_node *node;
    278    exec_node *_next;
    279 };
    280 
    281 #define foreach_iter(iter_type, iter, container) \
    282    for (iter_type iter = (container) . iterator(); iter.has_next(); iter.next())
    283 #endif
    284 
    285 
    286 struct exec_list {
    287    struct exec_node *head;
    288    struct exec_node *tail;
    289    struct exec_node *tail_pred;
    290 
    291 #ifdef __cplusplus
    292    /* Callers of this hieralloc-based new need not call delete. It's
    293     * easier to just hieralloc_free 'ctx' (or any of its ancestors). */
    294    static void* operator new(size_t size, void *ctx)
    295    {
    296       void *node;
    297 
    298       node = hieralloc_size(ctx, size);
    299       assert(node != NULL);
    300 
    301       return node;
    302    }
    303 
    304    /* If the user *does* call delete, that's OK, we will just
    305     * hieralloc_free in that case. */
    306    static void operator delete(void *node)
    307    {
    308       hieralloc_free(node);
    309    }
    310 
    311    exec_list()
    312    {
    313       make_empty();
    314    }
    315 
    316    void make_empty()
    317    {
    318       head = (exec_node *) & tail;
    319       tail = NULL;
    320       tail_pred = (exec_node *) & head;
    321    }
    322 
    323    bool is_empty() const
    324    {
    325       /* There are three ways to test whether a list is empty or not.
    326        *
    327        * - Check to see if the \c head points to the \c tail.
    328        * - Check to see if the \c tail_pred points to the \c head.
    329        * - Check to see if the \c head is the sentinel node by test whether its
    330        *   \c next pointer is \c NULL.
    331        *
    332        * The first two methods tend to generate better code on modern systems
    333        * because they save a pointer dereference.
    334        */
    335       return head == (exec_node *) &tail;
    336    }
    337 
    338    const exec_node *get_head() const
    339    {
    340       return !is_empty() ? head : NULL;
    341    }
    342 
    343    exec_node *get_head()
    344    {
    345       return !is_empty() ? head : NULL;
    346    }
    347 
    348    const exec_node *get_tail() const
    349    {
    350       return !is_empty() ? tail_pred : NULL;
    351    }
    352 
    353    exec_node *get_tail()
    354    {
    355       return !is_empty() ? tail_pred : NULL;
    356    }
    357 
    358    void push_head(exec_node *n)
    359    {
    360       n->next = head;
    361       n->prev = (exec_node *) &head;
    362 
    363       n->next->prev = n;
    364       head = n;
    365    }
    366 
    367    void push_tail(exec_node *n)
    368    {
    369       n->next = (exec_node *) &tail;
    370       n->prev = tail_pred;
    371 
    372       n->prev->next = n;
    373       tail_pred = n;
    374    }
    375 
    376    void push_degenerate_list_at_head(exec_node *n)
    377    {
    378       assert(n->prev->next == n);
    379 
    380       n->prev->next = head;
    381       head->prev = n->prev;
    382       n->prev = (exec_node *) &head;
    383       head = n;
    384    }
    385 
    386    /**
    387     * Remove the first node from a list and return it
    388     *
    389     * \return
    390     * The first node in the list or \c NULL if the list is empty.
    391     *
    392     * \sa exec_list::get_head
    393     */
    394    exec_node *pop_head()
    395    {
    396       exec_node *const n = this->get_head();
    397       if (n != NULL)
    398 	 n->remove();
    399 
    400       return n;
    401    }
    402 
    403    /**
    404     * Move all of the nodes from this list to the target list
    405     */
    406    void move_nodes_to(exec_list *target)
    407    {
    408       if (is_empty()) {
    409 	 target->make_empty();
    410       } else {
    411 	 target->head = head;
    412 	 target->tail = NULL;
    413 	 target->tail_pred = tail_pred;
    414 
    415 	 target->head->prev = (exec_node *) &target->head;
    416 	 target->tail_pred->next = (exec_node *) &target->tail;
    417 
    418 	 make_empty();
    419       }
    420    }
    421 
    422    /**
    423     * Append all nodes from the source list to the target list
    424     */
    425    void
    426    append_list(exec_list *source)
    427    {
    428       if (source->is_empty())
    429 	 return;
    430 
    431       /* Link the first node of the source with the last node of the target list.
    432        */
    433       this->tail_pred->next = source->head;
    434       source->head->prev = this->tail_pred;
    435 
    436       /* Make the tail of the source list be the tail of the target list.
    437        */
    438       this->tail_pred = source->tail_pred;
    439       this->tail_pred->next = (exec_node *) &this->tail;
    440 
    441       /* Make the source list empty for good measure.
    442        */
    443       source->make_empty();
    444    }
    445 
    446    exec_list_iterator iterator()
    447    {
    448       return exec_list_iterator(head);
    449    }
    450 
    451    exec_list_iterator iterator() const
    452    {
    453       return exec_list_iterator((exec_node *) head);
    454    }
    455 #endif
    456 };
    457 
    458 
    459 #ifdef __cplusplus
    460 inline void exec_node::insert_before(exec_list *before)
    461 {
    462    if (before->is_empty())
    463       return;
    464 
    465    before->tail_pred->next = this;
    466    before->head->prev = this->prev;
    467 
    468    this->prev->next = before->head;
    469    this->prev = before->tail_pred;
    470 
    471    before->make_empty();
    472 }
    473 #endif
    474 
    475 /**
    476  * This version is safe even if the current node is removed.
    477  */
    478 #define foreach_list_safe(__node, __list)			     \
    479    for (exec_node * __node = (__list)->head, * __next = __node->next \
    480 	; __next != NULL					     \
    481 	; __node = __next, __next = __next->next)
    482 
    483 #define foreach_list(__node, __list)			\
    484    for (exec_node * __node = (__list)->head		\
    485 	; (__node)->next != NULL 			\
    486 	; (__node) = (__node)->next)
    487 
    488 #define foreach_list_const(__node, __list)		\
    489    for (const exec_node * __node = (__list)->head	\
    490 	; (__node)->next != NULL 			\
    491 	; (__node) = (__node)->next)
    492 
    493 #define foreach_list_typed(__type, __node, __field, __list)		\
    494    for (__type * __node =						\
    495 	   exec_node_data(__type, (__list)->head, __field);		\
    496 	(__node)->__field.next != NULL; 				\
    497 	(__node) = exec_node_data(__type, (__node)->__field.next, __field))
    498 
    499 #define foreach_list_typed_const(__type, __node, __field, __list)	\
    500    for (const __type * __node =						\
    501 	   exec_node_data(__type, (__list)->head, __field);		\
    502 	(__node)->__field.next != NULL; 				\
    503 	(__node) = exec_node_data(__type, (__node)->__field.next, __field))
    504 
    505 #endif /* LIST_CONTAINER_H */
    506