xref: /third_party/mesa3d/src/compiler/glsl/list.h (revision bf215546)
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. The head sentinel and tail sentinel nodes are allocated within the
36 * list structure.
37 *
38 * Do note that this means that the list nodes will contain pointers into the
39 * list structure itself and as a result you may not \c realloc() an  \c
40 * exec_list or any structure in which an \c exec_list is embedded.
41 */
42
43#ifndef LIST_CONTAINER_H
44#define LIST_CONTAINER_H
45
46#ifndef __cplusplus
47#include <stddef.h>
48#endif
49#include <assert.h>
50
51#include "util/ralloc.h"
52
53struct exec_node {
54   struct exec_node *next;
55   struct exec_node *prev;
56
57#ifdef __cplusplus
58   DECLARE_RZALLOC_CXX_OPERATORS(exec_node)
59
60   exec_node() : next(NULL), prev(NULL)
61   {
62      /* empty */
63   }
64
65   const exec_node *get_next() const;
66   exec_node *get_next();
67
68   const exec_node *get_prev() const;
69   exec_node *get_prev();
70
71   void remove();
72
73   /**
74    * Link a node with itself
75    *
76    * This creates a sort of degenerate list that is occasionally useful.
77    */
78   void self_link();
79
80   /**
81    * Insert a node in the list after the current node
82    */
83   void insert_after(exec_node *after);
84
85   /**
86    * Insert another list in the list after the current node
87    */
88   void insert_after(struct exec_list *after);
89
90   /**
91    * Insert a node in the list before the current node
92    */
93   void insert_before(exec_node *before);
94
95   /**
96    * Insert another list in the list before the current node
97    */
98   void insert_before(struct exec_list *before);
99
100   /**
101    * Replace the current node with the given node.
102    */
103   void replace_with(exec_node *replacement);
104
105   /**
106    * Is this the sentinel at the tail of the list?
107    */
108   bool is_tail_sentinel() const;
109
110   /**
111    * Is this the sentinel at the head of the list?
112    */
113   bool is_head_sentinel() const;
114#endif
115};
116
117static inline void
118exec_node_init(struct exec_node *n)
119{
120   n->next = NULL;
121   n->prev = NULL;
122}
123
124static inline const struct exec_node *
125exec_node_get_next_const(const struct exec_node *n)
126{
127   return n->next;
128}
129
130static inline struct exec_node *
131exec_node_get_next(struct exec_node *n)
132{
133   return n->next;
134}
135
136static inline const struct exec_node *
137exec_node_get_prev_const(const struct exec_node *n)
138{
139   return n->prev;
140}
141
142static inline struct exec_node *
143exec_node_get_prev(struct exec_node *n)
144{
145   return n->prev;
146}
147
148static inline void
149exec_node_remove(struct exec_node *n)
150{
151   n->next->prev = n->prev;
152   n->prev->next = n->next;
153   n->next = NULL;
154   n->prev = NULL;
155}
156
157static inline void
158exec_node_self_link(struct exec_node *n)
159{
160   n->next = n;
161   n->prev = n;
162}
163
164static inline void
165exec_node_insert_after(struct exec_node *n, struct exec_node *after)
166{
167   after->next = n->next;
168   after->prev = n;
169
170   n->next->prev = after;
171   n->next = after;
172}
173
174static inline void
175exec_node_insert_node_before(struct exec_node *n, struct exec_node *before)
176{
177   before->next = n;
178   before->prev = n->prev;
179
180   n->prev->next = before;
181   n->prev = before;
182}
183
184static inline void
185exec_node_replace_with(struct exec_node *n, struct exec_node *replacement)
186{
187   replacement->prev = n->prev;
188   replacement->next = n->next;
189
190   n->prev->next = replacement;
191   n->next->prev = replacement;
192}
193
194static inline bool
195exec_node_is_tail_sentinel(const struct exec_node *n)
196{
197   return n->next == NULL;
198}
199
200static inline bool
201exec_node_is_head_sentinel(const struct exec_node *n)
202{
203   return n->prev == NULL;
204}
205
206#ifdef __cplusplus
207inline const exec_node *exec_node::get_next() const
208{
209   return exec_node_get_next_const(this);
210}
211
212inline exec_node *exec_node::get_next()
213{
214   return exec_node_get_next(this);
215}
216
217inline const exec_node *exec_node::get_prev() const
218{
219   return exec_node_get_prev_const(this);
220}
221
222inline exec_node *exec_node::get_prev()
223{
224   return exec_node_get_prev(this);
225}
226
227inline void exec_node::remove()
228{
229   exec_node_remove(this);
230}
231
232inline void exec_node::self_link()
233{
234   exec_node_self_link(this);
235}
236
237inline void exec_node::insert_after(exec_node *after)
238{
239   exec_node_insert_after(this, after);
240}
241
242inline void exec_node::insert_before(exec_node *before)
243{
244   exec_node_insert_node_before(this, before);
245}
246
247inline void exec_node::replace_with(exec_node *replacement)
248{
249   exec_node_replace_with(this, replacement);
250}
251
252inline bool exec_node::is_tail_sentinel() const
253{
254   return exec_node_is_tail_sentinel(this);
255}
256
257inline bool exec_node::is_head_sentinel() const
258{
259   return exec_node_is_head_sentinel(this);
260}
261#endif
262
263#ifdef __cplusplus
264/* This macro will not work correctly if `t' uses virtual inheritance.  If you
265 * are using virtual inheritance, you deserve a slow and painful death.  Enjoy!
266 */
267#define exec_list_offsetof(t, f, p) \
268   (((char *) &((t *) p)->f) - ((char *) p))
269#else
270#define exec_list_offsetof(t, f, p) offsetof(t, f)
271#endif
272
273/**
274 * Get a pointer to the structure containing an exec_node
275 *
276 * Given a pointer to an \c exec_node embedded in a structure, get a pointer to
277 * the containing structure.
278 *
279 * \param type  Base type of the structure containing the node
280 * \param node  Pointer to the \c exec_node
281 * \param field Name of the field in \c type that is the embedded \c exec_node
282 */
283#define exec_node_data(type, node, field) \
284   ((type *) (((uintptr_t) node) - exec_list_offsetof(type, field, node)))
285
286#ifdef __cplusplus
287struct exec_node;
288#endif
289
290struct exec_list {
291   struct exec_node head_sentinel;
292   struct exec_node tail_sentinel;
293
294#ifdef __cplusplus
295   DECLARE_RALLOC_CXX_OPERATORS(exec_list)
296
297   exec_list()
298   {
299      make_empty();
300   }
301
302   void make_empty();
303
304   bool is_empty() const;
305
306   const exec_node *get_head() const;
307   exec_node *get_head();
308   const exec_node *get_head_raw() const;
309   exec_node *get_head_raw();
310
311   const exec_node *get_tail() const;
312   exec_node *get_tail();
313   const exec_node *get_tail_raw() const;
314   exec_node *get_tail_raw();
315
316   unsigned length() const;
317
318   void push_head(exec_node *n);
319   void push_tail(exec_node *n);
320   void push_degenerate_list_at_head(exec_node *n);
321
322   /**
323    * Remove the first node from a list and return it
324    *
325    * \return
326    * The first node in the list or \c NULL if the list is empty.
327    *
328    * \sa exec_list::get_head
329    */
330   exec_node *pop_head();
331
332   /**
333    * Move all of the nodes from this list to the target list
334    */
335   void move_nodes_to(exec_list *target);
336
337   /**
338    * Append all nodes from the source list to the end of the target list
339    */
340   void append_list(exec_list *source);
341
342   /**
343    * Prepend all nodes from the source list to the beginning of the target
344    * list
345    */
346   void prepend_list(exec_list *source);
347#endif
348};
349
350static inline void
351exec_list_make_empty(struct exec_list *list)
352{
353   list->head_sentinel.next = &list->tail_sentinel;
354   list->head_sentinel.prev = NULL;
355   list->tail_sentinel.next = NULL;
356   list->tail_sentinel.prev = &list->head_sentinel;
357}
358
359static inline bool
360exec_list_is_empty(const struct exec_list *list)
361{
362   /* There are three ways to test whether a list is empty or not.
363    *
364    * - Check to see if the head sentinel's \c next is the tail sentinel.
365    * - Check to see if the tail sentinel's \c prev is the head sentinel.
366    * - Check to see if the head is the sentinel node by test whether its
367    *   \c next pointer is \c NULL.
368    *
369    * The first two methods tend to generate better code on modern systems
370    * because they save a pointer dereference.
371    */
372   return list->head_sentinel.next == &list->tail_sentinel;
373}
374
375static inline bool
376exec_list_is_singular(const struct exec_list *list)
377{
378   return !exec_list_is_empty(list) &&
379          list->head_sentinel.next->next == &list->tail_sentinel;
380}
381
382static inline const struct exec_node *
383exec_list_get_head_const(const struct exec_list *list)
384{
385   return !exec_list_is_empty(list) ? list->head_sentinel.next : NULL;
386}
387
388static inline struct exec_node *
389exec_list_get_head(struct exec_list *list)
390{
391   return !exec_list_is_empty(list) ? list->head_sentinel.next : NULL;
392}
393
394static inline const struct exec_node *
395exec_list_get_head_raw_const(const struct exec_list *list)
396{
397   return list->head_sentinel.next;
398}
399
400static inline struct exec_node *
401exec_list_get_head_raw(struct exec_list *list)
402{
403   return list->head_sentinel.next;
404}
405
406static inline const struct exec_node *
407exec_list_get_tail_const(const struct exec_list *list)
408{
409   return !exec_list_is_empty(list) ? list->tail_sentinel.prev : NULL;
410}
411
412static inline struct exec_node *
413exec_list_get_tail(struct exec_list *list)
414{
415   return !exec_list_is_empty(list) ? list->tail_sentinel.prev : NULL;
416}
417
418static inline const struct exec_node *
419exec_list_get_tail_raw_const(const struct exec_list *list)
420{
421   return list->tail_sentinel.prev;
422}
423
424static inline struct exec_node *
425exec_list_get_tail_raw(struct exec_list *list)
426{
427   return list->tail_sentinel.prev;
428}
429
430static inline unsigned
431exec_list_length(const struct exec_list *list)
432{
433   unsigned size = 0;
434   struct exec_node *node;
435
436   for (node = list->head_sentinel.next; node->next != NULL; node = node->next) {
437      size++;
438   }
439
440   return size;
441}
442
443static inline void
444exec_list_push_head(struct exec_list *list, struct exec_node *n)
445{
446   n->next = list->head_sentinel.next;
447   n->prev = &list->head_sentinel;
448
449   n->next->prev = n;
450   list->head_sentinel.next = n;
451}
452
453static inline void
454exec_list_push_tail(struct exec_list *list, struct exec_node *n)
455{
456   n->next = &list->tail_sentinel;
457   n->prev = list->tail_sentinel.prev;
458
459   n->prev->next = n;
460   list->tail_sentinel.prev = n;
461}
462
463static inline void
464exec_list_push_degenerate_list_at_head(struct exec_list *list, struct exec_node *n)
465{
466   assert(n->prev->next == n);
467
468   n->prev->next = list->head_sentinel.next;
469   list->head_sentinel.next->prev = n->prev;
470   n->prev = &list->head_sentinel;
471   list->head_sentinel.next = n;
472}
473
474static inline struct exec_node *
475exec_list_pop_head(struct exec_list *list)
476{
477   struct exec_node *const n = exec_list_get_head(list);
478   if (n != NULL)
479      exec_node_remove(n);
480
481   return n;
482}
483
484static inline void
485exec_list_move_nodes_to(struct exec_list *list, struct exec_list *target)
486{
487   if (exec_list_is_empty(list)) {
488      exec_list_make_empty(target);
489   } else {
490      target->head_sentinel.next = list->head_sentinel.next;
491      target->head_sentinel.prev = NULL;
492      target->tail_sentinel.next = NULL;
493      target->tail_sentinel.prev = list->tail_sentinel.prev;
494
495      target->head_sentinel.next->prev = &target->head_sentinel;
496      target->tail_sentinel.prev->next = &target->tail_sentinel;
497
498      exec_list_make_empty(list);
499   }
500}
501
502static inline void
503exec_list_append(struct exec_list *list, struct exec_list *source)
504{
505   if (exec_list_is_empty(source))
506      return;
507
508   /* Link the first node of the source with the last node of the target list.
509    */
510   list->tail_sentinel.prev->next = source->head_sentinel.next;
511   source->head_sentinel.next->prev = list->tail_sentinel.prev;
512
513   /* Make the tail of the source list be the tail of the target list.
514    */
515   list->tail_sentinel.prev = source->tail_sentinel.prev;
516   list->tail_sentinel.prev->next = &list->tail_sentinel;
517
518   /* Make the source list empty for good measure.
519    */
520   exec_list_make_empty(source);
521}
522
523static inline void
524exec_node_insert_list_after(struct exec_node *n, struct exec_list *after)
525{
526   if (exec_list_is_empty(after))
527      return;
528
529   after->tail_sentinel.prev->next = n->next;
530   after->head_sentinel.next->prev = n;
531
532   n->next->prev = after->tail_sentinel.prev;
533   n->next = after->head_sentinel.next;
534
535   exec_list_make_empty(after);
536}
537
538static inline void
539exec_list_prepend(struct exec_list *list, struct exec_list *source)
540{
541   exec_list_append(source, list);
542   exec_list_move_nodes_to(source, list);
543}
544
545static inline void
546exec_node_insert_list_before(struct exec_node *n, struct exec_list *before)
547{
548   if (exec_list_is_empty(before))
549      return;
550
551   before->tail_sentinel.prev->next = n;
552   before->head_sentinel.next->prev = n->prev;
553
554   n->prev->next = before->head_sentinel.next;
555   n->prev = before->tail_sentinel.prev;
556
557   exec_list_make_empty(before);
558}
559
560static inline void
561exec_list_validate(const struct exec_list *list)
562{
563   const struct exec_node *node;
564
565   assert(list->head_sentinel.next->prev == &list->head_sentinel);
566   assert(list->head_sentinel.prev == NULL);
567   assert(list->tail_sentinel.next == NULL);
568   assert(list->tail_sentinel.prev->next == &list->tail_sentinel);
569
570   /* We could try to use one of the interators below for this but they all
571    * either require C++ or assume the exec_node is embedded in a structure
572    * which is not the case for this function.
573    */
574   for (node = list->head_sentinel.next; node->next != NULL; node = node->next) {
575      assert(node->next->prev == node);
576      assert(node->prev->next == node);
577   }
578}
579
580#ifdef __cplusplus
581inline void exec_list::make_empty()
582{
583   exec_list_make_empty(this);
584}
585
586inline bool exec_list::is_empty() const
587{
588   return exec_list_is_empty(this);
589}
590
591inline const exec_node *exec_list::get_head() const
592{
593   return exec_list_get_head_const(this);
594}
595
596inline exec_node *exec_list::get_head()
597{
598   return exec_list_get_head(this);
599}
600
601inline const exec_node *exec_list::get_head_raw() const
602{
603   return exec_list_get_head_raw_const(this);
604}
605
606inline exec_node *exec_list::get_head_raw()
607{
608   return exec_list_get_head_raw(this);
609}
610
611inline const exec_node *exec_list::get_tail() const
612{
613   return exec_list_get_tail_const(this);
614}
615
616inline exec_node *exec_list::get_tail()
617{
618   return exec_list_get_tail(this);
619}
620
621inline const exec_node *exec_list::get_tail_raw() const
622{
623   return exec_list_get_tail_raw_const(this);
624}
625
626inline exec_node *exec_list::get_tail_raw()
627{
628   return exec_list_get_tail_raw(this);
629}
630
631inline unsigned exec_list::length() const
632{
633   return exec_list_length(this);
634}
635
636inline void exec_list::push_head(exec_node *n)
637{
638   exec_list_push_head(this, n);
639}
640
641inline void exec_list::push_tail(exec_node *n)
642{
643   exec_list_push_tail(this, n);
644}
645
646inline void exec_list::push_degenerate_list_at_head(exec_node *n)
647{
648   exec_list_push_degenerate_list_at_head(this, n);
649}
650
651inline exec_node *exec_list::pop_head()
652{
653   return exec_list_pop_head(this);
654}
655
656inline void exec_list::move_nodes_to(exec_list *target)
657{
658   exec_list_move_nodes_to(this, target);
659}
660
661inline void exec_list::append_list(exec_list *source)
662{
663   exec_list_append(this, source);
664}
665
666inline void exec_node::insert_after(exec_list *after)
667{
668   exec_node_insert_list_after(this, after);
669}
670
671inline void exec_list::prepend_list(exec_list *source)
672{
673   exec_list_prepend(this, source);
674}
675
676inline void exec_node::insert_before(exec_list *before)
677{
678   exec_node_insert_list_before(this, before);
679}
680#endif
681
682#define exec_node_typed_forward(__node, __type) \
683   (!exec_node_is_tail_sentinel(__node) ? (__type) (__node) : NULL)
684
685#define exec_node_typed_backward(__node, __type) \
686   (!exec_node_is_head_sentinel(__node) ? (__type) (__node) : NULL)
687
688#define foreach_in_list(__type, __inst, __list)                                           \
689   for (__type *__inst = exec_node_typed_forward((__list)->head_sentinel.next, __type *); \
690        (__inst) != NULL;                                                                 \
691        (__inst) = exec_node_typed_forward((__inst)->next, __type *))
692
693#define foreach_in_list_reverse(__type, __inst, __list)                                      \
694   for (__type *__inst = exec_node_typed_backward((__list)->tail_sentinel.prev, __type *);   \
695        (__inst) != NULL;                                                                    \
696        (__inst) = exec_node_typed_backward((__inst)->prev, __type *))
697
698/**
699 * This version is safe even if the current node is removed.
700 */
701
702#define foreach_in_list_safe(__type, __node, __list)                                                              \
703   for (__type *__node = exec_node_typed_forward((__list)->head_sentinel.next, __type *),                         \
704               *__next = (__node) ? exec_node_typed_forward((__list)->head_sentinel.next->next, __type *) : NULL; \
705        (__node) != NULL;                                                                                         \
706        (__node) = __next, __next = __next ? exec_node_typed_forward(__next->next, __type *) : NULL)
707
708#define foreach_in_list_reverse_safe(__type, __node, __list)                                                        \
709   for (__type *__node = exec_node_typed_backward((__list)->tail_sentinel.prev, __type *),                          \
710               *__prev = (__node) ? exec_node_typed_backward((__list)->tail_sentinel.prev->prev, __type *) : NULL;  \
711        (__node) != NULL;                                                                                           \
712        (__node) = __prev, __prev = __prev ? exec_node_typed_backward(__prev->prev, __type *) : NULL)
713
714#define foreach_in_list_use_after(__type, __inst, __list)                           \
715   __type *__inst;                                                                  \
716   for ((__inst) = exec_node_typed_forward((__list)->head_sentinel.next, __type *); \
717        (__inst) != NULL;                                                           \
718        (__inst) = exec_node_typed_forward((__inst)->next, __type *))
719
720/**
721 * Iterate through two lists at once.  Stops at the end of the shorter list.
722 *
723 * This is safe against either current node being removed or replaced.
724 */
725#define foreach_two_lists(__node1, __list1, __node2, __list2) \
726   for (struct exec_node * __node1 = (__list1)->head_sentinel.next, \
727                         * __node2 = (__list2)->head_sentinel.next, \
728                         * __next1 = __node1->next,           \
729                         * __next2 = __node2->next            \
730	; __next1 != NULL && __next2 != NULL                  \
731	; __node1 = __next1,                                  \
732          __node2 = __next2,                                  \
733          __next1 = __next1->next,                            \
734          __next2 = __next2->next)
735
736#define exec_node_data_forward(type, node, field) \
737   (!exec_node_is_tail_sentinel(node) ? exec_node_data(type, node, field) : NULL)
738
739#define exec_node_data_backward(type, node, field) \
740   (!exec_node_is_head_sentinel(node) ? exec_node_data(type, node, field) : NULL)
741
742#define foreach_list_typed(__type, __node, __field, __list)                     \
743   for (__type * __node =                                                       \
744         exec_node_data_forward(__type, (__list)->head_sentinel.next, __field); \
745   (__node) != NULL;                                                            \
746   (__node) = exec_node_data_forward(__type, (__node)->__field.next, __field))
747
748#define foreach_list_typed_from(__type, __node, __field, __list, __start)        \
749   for (__type * __node = exec_node_data_forward(__type, (__start), __field);    \
750   (__node) != NULL;                                                             \
751   (__node) = exec_node_data_forward(__type, (__node)->__field.next, __field))
752
753#define foreach_list_typed_reverse(__type, __node, __field, __list)                 \
754   for (__type * __node =                                                           \
755           exec_node_data_backward(__type, (__list)->tail_sentinel.prev, __field);  \
756        (__node) != NULL;                                                           \
757        (__node) = exec_node_data_backward(__type, (__node)->__field.prev, __field))
758
759#define foreach_list_typed_safe(__type, __node, __field, __list)                    \
760   for (__type * __node =                                                           \
761           exec_node_data_forward(__type, (__list)->head_sentinel.next, __field),   \
762               * __next = (__node) ?                                                \
763           exec_node_data_forward(__type, (__node)->__field.next, __field) : NULL;  \
764        (__node) != NULL;                                                           \
765        (__node) = __next, __next = (__next && (__next)->__field.next) ?            \
766           exec_node_data_forward(__type, (__next)->__field.next, __field) : NULL)
767
768#define foreach_list_typed_reverse_safe(__type, __node, __field, __list)            \
769   for (__type * __node =                                                           \
770           exec_node_data_backward(__type, (__list)->tail_sentinel.prev, __field),  \
771               * __prev = (__node) ?                                                \
772           exec_node_data_backward(__type, (__node)->__field.prev, __field) : NULL; \
773        (__node) != NULL;                                                           \
774        (__node) = __prev, __prev = (__prev && (__prev)->__field.prev) ?            \
775           exec_node_data_backward(__type, (__prev)->__field.prev, __field) : NULL)
776
777#endif /* LIST_CONTAINER_H */
778