Xenomai  3.0-rc7
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_pop_entry(list, type, member) ({ \
150  struct pvholder *__holder = pvlist_pop(list); \
151  pvlist_entry(__holder, type, member); })
152 
153 #define pvlist_for_each(pos, list) \
154  for (pos = (list)->head.next; \
155  pos != &(list)->head; pos = (pos)->next)
156 
157 #define pvlist_for_each_reverse(pos, list) \
158  for (pos = (list)->head.prev; \
159  pos != &(list)->head; pos = (pos)->prev)
160 
161 #define pvlist_for_each_safe(pos, tmp, list) \
162  for (pos = (list)->head.next, \
163  tmp = (pos)->next; \
164  pos != &(list)->head; \
165  pos = tmp, tmp = (pos)->next)
166 
167 #define pvlist_for_each_entry(pos, list, member) \
168  for (pos = pvlist_entry((list)->head.next, \
169  typeof(*pos), member); \
170  &(pos)->member != &(list)->head; \
171  pos = pvlist_entry((pos)->member.next, \
172  typeof(*pos), member))
173 
174 #define pvlist_for_each_entry_safe(pos, tmp, list, member) \
175  for (pos = pvlist_entry((list)->head.next, \
176  typeof(*pos), member), \
177  tmp = pvlist_entry((pos)->member.next, \
178  typeof(*pos), member); \
179  &(pos)->member != &(list)->head; \
180  pos = tmp, tmp = pvlist_entry((pos)->member.next, \
181  typeof(*pos), member))
182 
183 #define pvlist_for_each_entry_reverse(pos, list, member) \
184  for (pos = pvlist_entry((list)->head.prev, \
185  typeof(*pos), member); \
186  &pos->member != &(list)->head; \
187  pos = pvlist_entry(pos->member.prev, \
188  typeof(*pos), member))
189 
190 #define pvlist_for_each_entry_reverse_safe(pos, tmp, list, member) \
191  for (pos = pvlist_entry((list)->head.prev, \
192  typeof(*pos), member), \
193  tmp = pvlist_entry((pos)->member.prev, \
194  typeof(*pos), member); \
195  &(pos)->member != &(list)->head; \
196  pos = tmp, tmp = pvlist_entry((pos)->member.prev, \
197  typeof(*pos), member))
198 
199 #endif /* !_BOILERPLATE_PRIVATE_LIST_H */