Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  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@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. #endif
  70. #include <assert.h>
  71.  
  72. #include "ralloc.h"
  73.  
  74. struct exec_node {
  75.    struct exec_node *next;
  76.    struct exec_node *prev;
  77.  
  78. #ifdef __cplusplus
  79.    /* Callers of this ralloc-based new need not call delete. It's
  80.     * easier to just ralloc_free 'ctx' (or any of its ancestors). */
  81.    static void* operator new(size_t size, void *ctx)
  82.    {
  83.       void *node;
  84.  
  85.       node = ralloc_size(ctx, size);
  86.       assert(node != NULL);
  87.  
  88.       return node;
  89.    }
  90.  
  91.    /* If the user *does* call delete, that's OK, we will just
  92.     * ralloc_free in that case. */
  93.    static void operator delete(void *node)
  94.    {
  95.       ralloc_free(node);
  96.    }
  97.  
  98.    exec_node() : next(NULL), prev(NULL)
  99.    {
  100.       /* empty */
  101.    }
  102.  
  103.    const exec_node *get_next() const
  104.    {
  105.       return next;
  106.    }
  107.  
  108.    exec_node *get_next()
  109.    {
  110.       return next;
  111.    }
  112.  
  113.    const exec_node *get_prev() const
  114.    {
  115.       return prev;
  116.    }
  117.  
  118.    exec_node *get_prev()
  119.    {
  120.       return prev;
  121.    }
  122.  
  123.    void remove()
  124.    {
  125.       next->prev = prev;
  126.       prev->next = next;
  127.       next = NULL;
  128.       prev = NULL;
  129.    }
  130.  
  131.    /**
  132.     * Link a node with itself
  133.     *
  134.     * This creates a sort of degenerate list that is occasionally useful.
  135.     */
  136.    void self_link()
  137.    {
  138.       next = this;
  139.       prev = this;
  140.    }
  141.  
  142.    /**
  143.     * Insert a node in the list after the current node
  144.     */
  145.    void insert_after(exec_node *after)
  146.    {
  147.       after->next = this->next;
  148.       after->prev = this;
  149.  
  150.       this->next->prev = after;
  151.       this->next = after;
  152.    }
  153.    /**
  154.     * Insert a node in the list before the current node
  155.     */
  156.    void insert_before(exec_node *before)
  157.    {
  158.       before->next = this;
  159.       before->prev = this->prev;
  160.  
  161.       this->prev->next = before;
  162.       this->prev = before;
  163.    }
  164.  
  165.    /**
  166.     * Insert another list in the list before the current node
  167.     */
  168.    void insert_before(struct exec_list *before);
  169.  
  170.    /**
  171.     * Replace the current node with the given node.
  172.     */
  173.    void replace_with(exec_node *replacement)
  174.    {
  175.       replacement->prev = this->prev;
  176.       replacement->next = this->next;
  177.  
  178.       this->prev->next = replacement;
  179.       this->next->prev = replacement;
  180.    }
  181.  
  182.    /**
  183.     * Is this the sentinel at the tail of the list?
  184.     */
  185.    bool is_tail_sentinel() const
  186.    {
  187.       return this->next == NULL;
  188.    }
  189.  
  190.    /**
  191.     * Is this the sentinel at the head of the list?
  192.     */
  193.    bool is_head_sentinel() const
  194.    {
  195.       return this->prev == NULL;
  196.    }
  197. #endif
  198. };
  199.  
  200.  
  201. #ifdef __cplusplus
  202. /* This macro will not work correctly if `t' uses virtual inheritance.  If you
  203.  * are using virtual inheritance, you deserve a slow and painful death.  Enjoy!
  204.  */
  205. #define exec_list_offsetof(t, f, p) \
  206.    (((char *) &((t *) p)->f) - ((char *) p))
  207. #else
  208. #define exec_list_offsetof(t, f, p) offsetof(t, f)
  209. #endif
  210.  
  211. /**
  212.  * Get a pointer to the structure containing an exec_node
  213.  *
  214.  * Given a pointer to an \c exec_node embedded in a structure, get a pointer to
  215.  * the containing structure.
  216.  *
  217.  * \param type  Base type of the structure containing the node
  218.  * \param node  Pointer to the \c exec_node
  219.  * \param field Name of the field in \c type that is the embedded \c exec_node
  220.  */
  221. #define exec_node_data(type, node, field) \
  222.    ((type *) (((char *) node) - exec_list_offsetof(type, field, node)))
  223.  
  224. #ifdef __cplusplus
  225. struct exec_node;
  226.  
  227. class iterator {
  228. public:
  229.    void next()
  230.    {
  231.    }
  232.  
  233.    void *get()
  234.    {
  235.       return NULL;
  236.    }
  237.  
  238.    bool has_next() const
  239.    {
  240.       return false;
  241.    }
  242. };
  243.  
  244. class exec_list_iterator : public iterator {
  245. public:
  246.    exec_list_iterator(exec_node *n) : node(n), _next(n->next)
  247.    {
  248.       /* empty */
  249.    }
  250.  
  251.    void next()
  252.    {
  253.       node = _next;
  254.       _next = node->next;
  255.    }
  256.  
  257.    void remove()
  258.    {
  259.       node->remove();
  260.    }
  261.  
  262.    exec_node *get()
  263.    {
  264.       return node;
  265.    }
  266.  
  267.    bool has_next() const
  268.    {
  269.       return _next != NULL;
  270.    }
  271.  
  272. private:
  273.    exec_node *node;
  274.    exec_node *_next;
  275. };
  276.  
  277. #define foreach_iter(iter_type, iter, container) \
  278.    for (iter_type iter = (container) . iterator(); iter.has_next(); iter.next())
  279. #endif
  280.  
  281.  
  282. struct exec_list {
  283.    struct exec_node *head;
  284.    struct exec_node *tail;
  285.    struct exec_node *tail_pred;
  286.  
  287. #ifdef __cplusplus
  288.    /* Callers of this ralloc-based new need not call delete. It's
  289.     * easier to just ralloc_free 'ctx' (or any of its ancestors). */
  290.    static void* operator new(size_t size, void *ctx)
  291.    {
  292.       void *node;
  293.  
  294.       node = ralloc_size(ctx, size);
  295.       assert(node != NULL);
  296.  
  297.       return node;
  298.    }
  299.  
  300.    /* If the user *does* call delete, that's OK, we will just
  301.     * ralloc_free in that case. */
  302.    static void operator delete(void *node)
  303.    {
  304.       ralloc_free(node);
  305.    }
  306.  
  307.    exec_list()
  308.    {
  309.       make_empty();
  310.    }
  311.  
  312.    void make_empty()
  313.    {
  314.       head = (exec_node *) & tail;
  315.       tail = NULL;
  316.       tail_pred = (exec_node *) & head;
  317.    }
  318.  
  319.    bool is_empty() const
  320.    {
  321.       /* There are three ways to test whether a list is empty or not.
  322.        *
  323.        * - Check to see if the \c head points to the \c tail.
  324.        * - Check to see if the \c tail_pred points to the \c head.
  325.        * - Check to see if the \c head is the sentinel node by test whether its
  326.        *   \c next pointer is \c NULL.
  327.        *
  328.        * The first two methods tend to generate better code on modern systems
  329.        * because they save a pointer dereference.
  330.        */
  331.       return head == (exec_node *) &tail;
  332.    }
  333.  
  334.    const exec_node *get_head() const
  335.    {
  336.       return !is_empty() ? head : NULL;
  337.    }
  338.  
  339.    exec_node *get_head()
  340.    {
  341.       return !is_empty() ? head : NULL;
  342.    }
  343.  
  344.    const exec_node *get_tail() const
  345.    {
  346.       return !is_empty() ? tail_pred : NULL;
  347.    }
  348.  
  349.    exec_node *get_tail()
  350.    {
  351.       return !is_empty() ? tail_pred : NULL;
  352.    }
  353.  
  354.    void push_head(exec_node *n)
  355.    {
  356.       n->next = head;
  357.       n->prev = (exec_node *) &head;
  358.  
  359.       n->next->prev = n;
  360.       head = n;
  361.    }
  362.  
  363.    void push_tail(exec_node *n)
  364.    {
  365.       n->next = (exec_node *) &tail;
  366.       n->prev = tail_pred;
  367.  
  368.       n->prev->next = n;
  369.       tail_pred = n;
  370.    }
  371.  
  372.    void push_degenerate_list_at_head(exec_node *n)
  373.    {
  374.       assert(n->prev->next == n);
  375.  
  376.       n->prev->next = head;
  377.       head->prev = n->prev;
  378.       n->prev = (exec_node *) &head;
  379.       head = n;
  380.    }
  381.  
  382.    /**
  383.     * Remove the first node from a list and return it
  384.     *
  385.     * \return
  386.     * The first node in the list or \c NULL if the list is empty.
  387.     *
  388.     * \sa exec_list::get_head
  389.     */
  390.    exec_node *pop_head()
  391.    {
  392.       exec_node *const n = this->get_head();
  393.       if (n != NULL)
  394.          n->remove();
  395.  
  396.       return n;
  397.    }
  398.  
  399.    /**
  400.     * Move all of the nodes from this list to the target list
  401.     */
  402.    void move_nodes_to(exec_list *target)
  403.    {
  404.       if (is_empty()) {
  405.          target->make_empty();
  406.       } else {
  407.          target->head = head;
  408.          target->tail = NULL;
  409.          target->tail_pred = tail_pred;
  410.  
  411.          target->head->prev = (exec_node *) &target->head;
  412.          target->tail_pred->next = (exec_node *) &target->tail;
  413.  
  414.          make_empty();
  415.       }
  416.    }
  417.  
  418.    /**
  419.     * Append all nodes from the source list to the target list
  420.     */
  421.    void
  422.    append_list(exec_list *source)
  423.    {
  424.       if (source->is_empty())
  425.          return;
  426.  
  427.       /* Link the first node of the source with the last node of the target list.
  428.        */
  429.       this->tail_pred->next = source->head;
  430.       source->head->prev = this->tail_pred;
  431.  
  432.       /* Make the tail of the source list be the tail of the target list.
  433.        */
  434.       this->tail_pred = source->tail_pred;
  435.       this->tail_pred->next = (exec_node *) &this->tail;
  436.  
  437.       /* Make the source list empty for good measure.
  438.        */
  439.       source->make_empty();
  440.    }
  441.  
  442.    exec_list_iterator iterator()
  443.    {
  444.       return exec_list_iterator(head);
  445.    }
  446.  
  447.    exec_list_iterator iterator() const
  448.    {
  449.       return exec_list_iterator((exec_node *) head);
  450.    }
  451. #endif
  452. };
  453.  
  454.  
  455. #ifdef __cplusplus
  456. inline void exec_node::insert_before(exec_list *before)
  457. {
  458.    if (before->is_empty())
  459.       return;
  460.  
  461.    before->tail_pred->next = this;
  462.    before->head->prev = this->prev;
  463.  
  464.    this->prev->next = before->head;
  465.    this->prev = before->tail_pred;
  466.  
  467.    before->make_empty();
  468. }
  469. #endif
  470.  
  471. /**
  472.  * This version is safe even if the current node is removed.
  473.  */
  474. #define foreach_list_safe(__node, __list)                            \
  475.    for (exec_node * __node = (__list)->head, * __next = __node->next \
  476.         ; __next != NULL                                             \
  477.         ; __node = __next, __next = __next->next)
  478.  
  479. #define foreach_list(__node, __list)                    \
  480.    for (exec_node * __node = (__list)->head             \
  481.         ; (__node)->next != NULL                        \
  482.         ; (__node) = (__node)->next)
  483.  
  484. #define foreach_list_const(__node, __list)              \
  485.    for (const exec_node * __node = (__list)->head       \
  486.         ; (__node)->next != NULL                        \
  487.         ; (__node) = (__node)->next)
  488.  
  489. #define foreach_list_typed(__type, __node, __field, __list)             \
  490.    for (__type * __node =                                               \
  491.            exec_node_data(__type, (__list)->head, __field);             \
  492.         (__node)->__field.next != NULL;                                 \
  493.         (__node) = exec_node_data(__type, (__node)->__field.next, __field))
  494.  
  495. #define foreach_list_typed_const(__type, __node, __field, __list)       \
  496.    for (const __type * __node =                                         \
  497.            exec_node_data(__type, (__list)->head, __field);             \
  498.         (__node)->__field.next != NULL;                                 \
  499.         (__node) = exec_node_data(__type, (__node)->__field.next, __field))
  500.  
  501. #endif /* LIST_CONTAINER_H */
  502.