Xenomai  3.1
private-list.h
1 /*
2  * Copyright (C) 2010 Philippe Gerum <rpm@xenomai.org>.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13 
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18 
19 #ifndef _BOILERPLATE_PRIVATE_LIST_H
20 #define _BOILERPLATE_PRIVATE_LIST_H
21 
22 #ifndef _BOILERPLATE_LIST_H
23 #error "Do not include this file directly. Use <boilerplate/list.h> instead."
24 #endif
25 
26 struct pvholder {
27  struct pvholder *next;
28  struct pvholder *prev;
29 };
30 
31 struct pvlistobj {
32  struct pvholder head;
33 };
34 
35 #define PRIVATE_LIST_INITIALIZER(__name) \
36  { .head = { .next = &((__name).head), .prev = &((__name).head) } }
37 
38 #define DEFINE_PRIVATE_LIST(__name) \
39  struct pvlistobj __name = PRIVATE_LIST_INITIALIZER(__name)
40 
41 static inline void initpvh(struct pvholder *holder)
42 {
43  holder->next = holder;
44  holder->prev = holder;
45 }
46 
47 static inline void atpvh(struct pvholder *head, struct pvholder *holder)
48 {
49  /* Inserts the new element right after the heading one. */
50  holder->prev = head;
51  holder->next = head->next;
52  holder->next->prev = holder;
53  head->next = holder;
54 }
55 
56 static inline void dtpvh(struct pvholder *holder)
57 {
58  holder->prev->next = holder->next;
59  holder->next->prev = holder->prev;
60 }
61 
62 static inline void pvlist_init(struct pvlistobj *list)
63 {
64  initpvh(&list->head);
65 }
66 
67 static inline void pvholder_init(struct pvholder *holder)
68 {
69  initpvh(holder);
70 }
71 
72 /*
73  * XXX: pvholder_init() is mandatory if you later want to use this
74  * predicate.
75  */
76 static inline int pvholder_linked(const struct pvholder *holder)
77 {
78  return !(holder->prev == holder->next &&
79  holder->prev == holder);
80 }
81 
82 static inline void pvlist_prepend(struct pvholder *holder, struct pvlistobj *list)
83 {
84  atpvh(&list->head, holder);
85 }
86 
87 static inline void pvlist_append(struct pvholder *holder, struct pvlistobj *list)
88 {
89  atpvh(list->head.prev, holder);
90 }
91 
92 static inline void pvlist_insert(struct pvholder *next, struct pvholder *prev)
93 {
94  atpvh(prev, next);
95 }
96 
97 static inline void pvlist_join(struct pvlistobj *lsrc, struct pvlistobj *ldst)
98 {
99  struct pvholder *headsrc = lsrc->head.next;
100  struct pvholder *tailsrc = lsrc->head.prev;
101  struct pvholder *headdst = &ldst->head;
102 
103  headsrc->prev->next = tailsrc->next;
104  tailsrc->next->prev = headsrc->prev;
105  headsrc->prev = headdst;
106  tailsrc->next = headdst->next;
107  headdst->next->prev = tailsrc;
108  headdst->next = headsrc;
109 }
110 
111 static inline void pvlist_remove(struct pvholder *holder)
112 {
113  dtpvh(holder);
114 }
115 
116 static inline void pvlist_remove_init(struct pvholder *holder)
117 {
118  dtpvh(holder);
119  initpvh(holder);
120 }
121 
122 static inline int pvlist_empty(const struct pvlistobj *list)
123 {
124  return list->head.next == &list->head;
125 }
126 
127 static inline struct pvholder *pvlist_pop(struct pvlistobj *list)
128 {
129  struct pvholder *holder = list->head.next;
130  pvlist_remove(holder);
131  return holder;
132 }
133 
134 static inline int pvlist_heading_p(const struct pvholder *holder,
135  const struct pvlistobj *list)
136 {
137  return list->head.next == holder;
138 }
139 
140 #define pvlist_entry(ptr, type, member) \
141  container_of(ptr, type, member)
142 
143 #define pvlist_first_entry(list, type, member) \
144  pvlist_entry((list)->head.next, type, member)
145 
146 #define pvlist_last_entry(list, type, member) \
147  pvlist_entry((list)->head.prev, type, member)
148 
149 #define pvlist_prev_entry(pos, list, member) \
150  ({ \
151  typeof(*pos) *__prev = NULL; \
152  if ((list)->head.next != &(pos)->member) \
153  __prev = pvlist_entry((pos)->member.prev, \
154  typeof(*pos), member); \
155  __prev; \
156  })
157 
158 #define pvlist_next_entry(pos, list, member) \
159  ({ \
160  typeof(*pos) *__next = NULL; \
161  if ((list)->head.prev != &(pos)->member) \
162  __next = pvlist_entry((pos)->member.next, \
163  typeof(*pos), member); \
164  __next; \
165  })
166 
167 #define pvlist_pop_entry(list, type, member) ({ \
168  struct pvholder *__holder = pvlist_pop(list); \
169  pvlist_entry(__holder, type, member); })
170 
171 #define pvlist_for_each(pos, list) \
172  for (pos = (list)->head.next; \
173  pos != &(list)->head; pos = (pos)->next)
174 
175 #define pvlist_for_each_reverse(pos, list) \
176  for (pos = (list)->head.prev; \
177  pos != &(list)->head; pos = (pos)->prev)
178 
179 #define pvlist_for_each_safe(pos, tmp, list) \
180  for (pos = (list)->head.next, \
181  tmp = (pos)->next; \
182  pos != &(list)->head; \
183  pos = tmp, tmp = (pos)->next)
184 
185 #define pvlist_for_each_entry(pos, list, member) \
186  for (pos = pvlist_entry((list)->head.next, \
187  typeof(*pos), member); \
188  &(pos)->member != &(list)->head; \
189  pos = pvlist_entry((pos)->member.next, \
190  typeof(*pos), member))
191 
192 #define pvlist_for_each_entry_safe(pos, tmp, list, member) \
193  for (pos = pvlist_entry((list)->head.next, \
194  typeof(*pos), member), \
195  tmp = pvlist_entry((pos)->member.next, \
196  typeof(*pos), member); \
197  &(pos)->member != &(list)->head; \
198  pos = tmp, tmp = pvlist_entry((pos)->member.next, \
199  typeof(*pos), member))
200 
201 #define pvlist_for_each_entry_reverse(pos, list, member) \
202  for (pos = pvlist_entry((list)->head.prev, \
203  typeof(*pos), member); \
204  &pos->member != &(list)->head; \
205  pos = pvlist_entry(pos->member.prev, \
206  typeof(*pos), member))
207 
208 #define pvlist_for_each_entry_reverse_safe(pos, tmp, list, member) \
209  for (pos = pvlist_entry((list)->head.prev, \
210  typeof(*pos), member), \
211  tmp = pvlist_entry((pos)->member.prev, \
212  typeof(*pos), member); \
213  &(pos)->member != &(list)->head; \
214  pos = tmp, tmp = pvlist_entry((pos)->member.prev, \
215  typeof(*pos), member))
216 
217 #endif /* !_BOILERPLATE_PRIVATE_LIST_H */