• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #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). */
newexec_node85    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. */
deleteexec_node97    static void operator delete(void *node)
98    {
99       hieralloc_free(node);
100    }
101 
exec_nodeexec_node102    exec_node() : next(NULL), prev(NULL)
103    {
104       /* empty */
105    }
106 
get_nextexec_node107    const exec_node *get_next() const
108    {
109       return next;
110    }
111 
get_nextexec_node112    exec_node *get_next()
113    {
114       return next;
115    }
116 
get_prevexec_node117    const exec_node *get_prev() const
118    {
119       return prev;
120    }
121 
get_prevexec_node122    exec_node *get_prev()
123    {
124       return prev;
125    }
126 
removeexec_node127    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     */
self_linkexec_node140    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     */
insert_afterexec_node149    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     */
insert_beforeexec_node160    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     */
replace_withexec_node177    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     */
is_tail_sentinelexec_node189    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     */
is_head_sentinelexec_node197    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:
next()233    void next()
234    {
235    }
236 
get()237    void *get()
238    {
239       return NULL;
240    }
241 
has_next()242    bool has_next() const
243    {
244       return false;
245    }
246 };
247 
248 class exec_list_iterator : public iterator {
249 public:
exec_list_iterator(exec_node * n)250    exec_list_iterator(exec_node *n) : node(n), _next(n->next)
251    {
252       /* empty */
253    }
254 
next()255    void next()
256    {
257       node = _next;
258       _next = node->next;
259    }
260 
remove()261    void remove()
262    {
263       node->remove();
264    }
265 
get()266    exec_node *get()
267    {
268       return node;
269    }
270 
has_next()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). */
newexec_list294    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. */
deleteexec_list306    static void operator delete(void *node)
307    {
308       hieralloc_free(node);
309    }
310 
exec_listexec_list311    exec_list()
312    {
313       make_empty();
314    }
315 
make_emptyexec_list316    void make_empty()
317    {
318       head = (exec_node *) & tail;
319       tail = NULL;
320       tail_pred = (exec_node *) & head;
321    }
322 
is_emptyexec_list323    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 
get_headexec_list338    const exec_node *get_head() const
339    {
340       return !is_empty() ? head : NULL;
341    }
342 
get_headexec_list343    exec_node *get_head()
344    {
345       return !is_empty() ? head : NULL;
346    }
347 
get_tailexec_list348    const exec_node *get_tail() const
349    {
350       return !is_empty() ? tail_pred : NULL;
351    }
352 
get_tailexec_list353    exec_node *get_tail()
354    {
355       return !is_empty() ? tail_pred : NULL;
356    }
357 
push_headexec_list358    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 
push_tailexec_list367    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 
push_degenerate_list_at_headexec_list376    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     */
pop_headexec_list394    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     */
move_nodes_toexec_list406    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
append_listexec_list426    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 
iteratorexec_list446    exec_list_iterator iterator()
447    {
448       return exec_list_iterator(head);
449    }
450 
iteratorexec_list451    exec_list_iterator iterator() const
452    {
453       return exec_list_iterator((exec_node *) head);
454    }
455 #endif
456 };
457 
458 
459 #ifdef __cplusplus
insert_before(exec_list * before)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