0e9e1854bb43387a9fea37c763bdd4d4f49375c0
[vpp.git] / vppinfra / vppinfra / dlist.h
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * 
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15 */
16
17 #ifndef included_dlist_h
18 #define included_dlist_h
19
20 #include <stdarg.h>
21 #include <vppinfra/clib.h>
22 #include <vppinfra/vec.h>
23 #include <vppinfra/pool.h>
24 #include <vppinfra/error.h>
25 #include <vppinfra/format.h>
26 #include <vppinfra/cache.h>
27
28 typedef struct {
29   u32 next;
30   u32 prev;
31   u32 value;
32 } dlist_elt_t;
33
34 static inline void 
35 clib_dlist_init (dlist_elt_t * pool, u32 index)
36 {
37   dlist_elt_t * head = pool_elt_at_index (pool, index);
38   memset (head, 0xFF, sizeof (*head));
39 }
40
41 static inline void 
42 clib_dlist_addtail (dlist_elt_t * pool, u32 head_index, u32 new_index)
43 {
44   dlist_elt_t * head = pool_elt_at_index (pool, head_index);
45   u32 old_last_index;
46   dlist_elt_t * old_last;
47   dlist_elt_t * new;
48
49   ASSERT(head->value == ~0);
50
51   new = pool_elt_at_index (pool, new_index);
52
53   if (PREDICT_FALSE(head->next == ~0))
54     {
55       head->next = head->prev = new_index;
56       new->next = new->prev = head_index;
57       return;
58     }
59
60   old_last_index = head->prev;
61   old_last = pool_elt_at_index (pool, old_last_index);
62
63   new->next = old_last->next;
64   new->prev = old_last_index;
65   old_last->next = new_index;
66   head->prev = new_index;
67 }
68
69 static inline void 
70 clib_dlist_addhead (dlist_elt_t * pool, u32 head_index, u32 new_index)
71 {
72   dlist_elt_t * head = pool_elt_at_index (pool, head_index);
73   dlist_elt_t * old_first;
74   u32 old_first_index;
75   dlist_elt_t * new;
76   
77   ASSERT(head->value == ~0);
78
79   new = pool_elt_at_index (pool, new_index);
80
81   if (PREDICT_FALSE(head->next == ~0))
82     {
83       head->next = head->prev = new_index;
84       new->next = new->prev = head_index;
85       return;
86     }
87
88   old_first_index = head->next;
89   old_first = pool_elt_at_index (pool, old_first_index);
90
91   new->next = old_first_index;
92   new->prev = old_first->prev;
93   old_first->prev = new_index;
94   head->next = new_index;
95 }
96
97 static inline void
98 clib_dlist_remove (dlist_elt_t * pool, u32 index)
99 {
100   dlist_elt_t * elt = pool_elt_at_index (pool, index);
101   dlist_elt_t * next_elt, * prev_elt;
102   
103   /* listhead, not so much */
104   ASSERT(elt->value != ~0);
105
106   next_elt = pool_elt_at_index (pool, elt->next);
107   prev_elt = pool_elt_at_index (pool, elt->prev);
108
109   next_elt->prev = elt->prev;
110   prev_elt->next = elt->next;
111
112   elt->prev = elt->next = ~0;
113 }
114
115 static inline u32 clib_dlist_remove_head (dlist_elt_t * pool, u32 head_index)
116 {
117   dlist_elt_t * head = pool_elt_at_index (pool, head_index);
118   u32 rv;
119
120   ASSERT(head->value == ~0);
121
122   if (head->next == ~0)
123     return ~0;
124
125   rv = head->next;
126   clib_dlist_remove (pool, rv);
127   return rv;
128 }
129
130 static inline u32 clib_dlist_remove_tail (dlist_elt_t * pool, u32 head_index)
131 {
132   dlist_elt_t * head = pool_elt_at_index (pool, head_index);
133   u32 rv;
134
135   ASSERT(head->value == ~0);
136
137   if (head->prev == ~0)
138     return ~0;
139
140   rv = head->prev;
141   clib_dlist_remove (pool, rv);
142   return rv;
143 }
144
145 #endif /* included_dlist_h */