ChibiOS/RT  6.1.4
chlists.h
Go to the documentation of this file.
1 /*
2  ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014,
3  2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio.
4 
5  This file is part of ChibiOS.
6 
7  ChibiOS is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation version 3 of the License.
10 
11  ChibiOS is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 /**
21  * @file chlists.h
22  * @brief Lists and Queues header.
23  *
24  * @addtogroup os_lists
25  * @{
26  */
27 
28 #ifndef CHLISTS_H
29 #define CHLISTS_H
30 
31 /*===========================================================================*/
32 /* Module constants. */
33 /*===========================================================================*/
34 
35 /*===========================================================================*/
36 /* Module pre-compile time settings. */
37 /*===========================================================================*/
38 
39 /*===========================================================================*/
40 /* Derived constants and error checks. */
41 /*===========================================================================*/
42 
43 /*===========================================================================*/
44 /* Module data structures and types. */
45 /*===========================================================================*/
46 
47 /**
48  * @brief Type of a generic single link list header and element.
49  */
50 typedef struct ch_list ch_list_t;
51 
52 /**
53  * @brief Structure representing a generic single link list header
54  * and element.
55  */
56 struct ch_list {
57  ch_list_t *next; /**< @brief Next in the list/queue. */
58 };
59 
60 /**
61  * @brief Type of a generic bidirectional linked list header and element.
62  */
63 typedef struct ch_queue ch_queue_t;
64 
65 /**
66  * @brief Structure representing a generic bidirectional linked list header
67  * and element.
68  */
69 struct ch_queue {
70  ch_queue_t *next; /**< @brief Next in the list/queue. */
71  ch_queue_t *prev; /**< @brief Previous in the queue. */
72 };
73 
74 /**
75  * @brief Type of a generic priority-ordered bidirectional linked list
76  * header and element.
77  */
79 
80 /**
81  * @brief Structure representing a generic priority-ordered bidirectional
82  * linked list header and element.
83  * @note Link fields are void pointers in order to avoid aliasing issues.
84  */
86  ch_priority_queue_t *next; /**< @brief Next in the list/queue. */
87  ch_priority_queue_t *prev; /**< @brief Previous in the queue. */
88  tprio_t prio;
89 };
90 
91 /*===========================================================================*/
92 /* Module macros. */
93 /*===========================================================================*/
94 
95 /**
96  * @brief Data part of a static queue object initializer.
97  * @details This macro should be used when statically initializing a
98  * queue that is part of a bigger structure.
99  *
100  * @param[in] name the name of the queue variable
101  */
102 #define _CH_QUEUE_DATA(name) {(ch_queue_t *)&name, (ch_queue_t *)&name}
103 
104 /**
105  * @brief Static queue object initializer.
106  * @details Statically initialized queues require no explicit
107  * initialization using @p queue_init().
108  *
109  * @param[in] name the name of the queue variable
110  */
111 #define CH_QUEUE_DECL(name) \
112  ch_queue_t name = _CH_QUEUE_DATA(name)
113 
114 /*===========================================================================*/
115 /* External declarations. */
116 /*===========================================================================*/
117 
118 /* Early function prototypes required by the following headers.*/
119 #ifdef __cplusplus
120 extern "C" {
121 #endif
122 
123 #ifdef __cplusplus
124 }
125 #endif
126 
127 /*===========================================================================*/
128 /* Module inline functions. */
129 /*===========================================================================*/
130 
131 /**
132  * @brief List initialization.
133  *
134  * @param[out] lp pointer to the list header
135  *
136  * @notapi
137  */
138 static inline void ch_list_init(ch_list_t *lp) {
139 
140  lp->next = lp;
141 }
142 
143 /**
144  * @brief Evaluates to @p true if the specified list is empty.
145  *
146  * @param[in] lp pointer to the list header
147  * @return The status of the list.
148  *
149  * @notapi
150  */
151 static inline bool ch_list_isempty(ch_list_t *lp) {
152 
153  return (bool)(lp->next == lp);
154 }
155 
156 /**
157  * @brief Evaluates to @p true if the specified list is not empty.
158  *
159  * @param[in] lp pointer to the list header
160  * @return The status of the list.
161  *
162  * @notapi
163  */
164 static inline bool ch_list_notempty(ch_list_t *lp) {
165 
166  return (bool)(lp->next != lp);
167 }
168 
169 /**
170  * @brief Pushes an element on top of a stack list.
171  *
172  * @param[in] p the pointer to the element to be inserted in the list
173  * @param[in] lp the pointer to the list header
174  *
175  * @notapi
176  */
177 static inline void ch_list_push(ch_list_t *p, ch_list_t *lp) {
178 
179  p->next = lp->next;
180  lp->next = p;
181 }
182 
183 /**
184  * @brief Pops an element from the top of a stack list and returns it.
185  * @pre The list must be non-empty before calling this function.
186  *
187  * @param[in] lp the pointer to the list header
188  * @return The removed element pointer.
189  *
190  * @notapi
191  */
192 static inline ch_list_t *ch_list_pop(ch_list_t *lp) {
193 
194  ch_list_t *p = lp->next;
195  lp->next = p->next;
196 
197  return p;
198 }
199 
200 /**
201  * @brief Queue initialization.
202  *
203  * @param[out] qp pointer to the queue header
204  *
205  * @notapi
206  */
207 static inline void ch_queue_init(ch_queue_t *qp) {
208 
209  qp->next = qp;
210  qp->prev = qp;
211 }
212 
213 /**
214  * @brief Evaluates to @p true if the specified queue is empty.
215  *
216  * @param[in] qp pointer to the queue header
217  * @return The status of the queue.
218  *
219  * @notapi
220  */
221 static inline bool ch_queue_isempty(const ch_queue_t *qp) {
222 
223  return (bool)(qp->next == qp);
224 }
225 
226 /**
227  * @brief Evaluates to @p true if the specified queue is not empty.
228  *
229  * @param[in] qp pointer to the queue header
230  * @return The status of the queue.
231  *
232  * @notapi
233  */
234 static inline bool ch_queue_notempty(const ch_queue_t *qp) {
235 
236  return (bool)(qp->next != qp);
237 }
238 
239 /**
240  * @brief Inserts an element into a queue.
241  *
242  * @param[in] p the pointer to the element to be inserted in the queue
243  * @param[in] qp the pointer to the queue header
244  *
245  * @notapi
246  */
247 static inline void ch_queue_insert(ch_queue_t *p, ch_queue_t *qp) {
248 
249  p->next = qp;
250  p->prev = qp->prev;
251  p->prev->next = p;
252  qp->prev = p;
253 }
254 
255 /**
256  * @brief Removes the first-out element from a queue and returns it.
257  * @note If the queue is priority ordered then this function returns the
258  * element with the highest priority.
259  *
260  * @param[in] qp the pointer to the queue list header
261  * @return The removed element pointer.
262  *
263  * @notapi
264  */
266  ch_queue_t *p = qp->next;
267 
268  qp->next = p->next;
269  qp->next->prev = qp;
270 
271  return p;
272 }
273 
274 /**
275  * @brief Removes the last-out element from a queue and returns it.
276  * @note If the queue is priority ordered then this function returns the
277  * element with the lowest priority.
278  *
279  * @param[in] qp the pointer to the queue list header
280  * @return The removed element pointer.
281  *
282  * @notapi
283  */
285  ch_queue_t *p = qp->prev;
286 
287  qp->prev = p->prev;
288  qp->prev->next = qp;
289 
290  return p;
291 }
292 
293 /**
294  * @brief Removes an element from a queue and returns it.
295  * @details The element is removed from the queue regardless of its relative
296  * position and regardless the used insertion method.
297  *
298  * @param[in] p the pointer to the element to be removed from the queue
299  * @return The removed element pointer.
300  *
301  * @notapi
302  */
304 
305  p->prev->next = p->next;
306  p->next->prev = p->prev;
307 
308  return p;
309 }
310 
311 /**
312  * @brief Priority queue initialization.
313  * @note The queue header priority is initialized to zero, all other
314  * elements in the queue are assumed to have priority greater
315  * than zero.
316  *
317  * @param[out] pqp pointer to the priority queue header
318  *
319  * @notapi
320  */
321 static inline void ch_pqueue_init(ch_priority_queue_t *pqp) {
322 
323  pqp->next = pqp;
324  pqp->prev = pqp;
325  pqp->prio = (tprio_t)0;
326 }
327 
328 /**
329  * @brief Removes the highest priority element from a priority queue and
330  * returns it.
331  *
332  * @param[in] pqp the pointer to the priority queue list header
333  * @return The removed element pointer.
334  *
335  * @notapi
336  */
338  ch_priority_queue_t *p = pqp->next;
339 
340  pqp->next = p->next;
341  pqp->next->prev = pqp;
342 
343  return p;
344 }
345 
346 /**
347  * @brief Inserts an element in the priority queue placing it behind
348  * its peers.
349  * @details The element is positioned behind all elements with higher or
350  * equal priority.
351  *
352  * @param[in] pqp the pointer to the priority queue list header
353  * @param[in] p the pointer to the element to be inserted in the queue
354  * @return The inserted element pointer.
355  *
356  * @notapi
357  */
359  ch_priority_queue_t *p) {
360 
361  /* Scanning priority queue.*/
362  do {
363  pqp = pqp->next;
364  } while (pqp->prio >= p->prio);
365 
366  /* Insertion on prev.*/
367  p->next = pqp;
368  p->prev = pqp->prev;
369  p->prev->next = p;
370  pqp->prev = p;
371 
372  return p;
373 }
374 
375 /**
376  * @brief Inserts an element in the priority queue placing it ahead of
377  * its peers.
378  * @details The element is positioned ahead of all elements with higher or
379  * equal priority.
380  *
381  * @param[in] pqp the pointer to the priority queue list header
382  * @param[in] p the pointer to the element to be inserted in the queue
383  * @return The inserted element pointer.
384  *
385  * @notapi
386  */
388  ch_priority_queue_t *p) {
389 
390  /* Scanning priority queue.*/
391  do {
392  pqp = pqp->next;
393  } while (pqp->prio > p->prio);
394 
395  /* Insertion on prev.*/
396  p->next = pqp;
397  p->prev = pqp->prev;
398  p->prev->next = p;
399  pqp->prev = p;
400 
401  return p;
402 }
403 
404 #endif /* CHLISTS_H */
405 
406 /** @} */
ch_queue::next
ch_queue_t * next
Next in the list/queue.
Definition: chlists.h:70
ch_list::next
ch_list_t * next
Next in the list/queue.
Definition: chlists.h:57
ch_queue_notempty
static bool ch_queue_notempty(const ch_queue_t *qp)
Evaluates to true if the specified queue is not empty.
Definition: chlists.h:234
ch_queue_isempty
static bool ch_queue_isempty(const ch_queue_t *qp)
Evaluates to true if the specified queue is empty.
Definition: chlists.h:221
ch_list_push
static void ch_list_push(ch_list_t *p, ch_list_t *lp)
Pushes an element on top of a stack list.
Definition: chlists.h:177
ch_list_notempty
static bool ch_list_notempty(ch_list_t *lp)
Evaluates to true if the specified list is not empty.
Definition: chlists.h:164
ch_pqueue_insert_ahead
static ch_priority_queue_t * ch_pqueue_insert_ahead(ch_priority_queue_t *pqp, ch_priority_queue_t *p)
Inserts an element in the priority queue placing it ahead of its peers.
Definition: chlists.h:387
ch_queue_fifo_remove
static ch_queue_t * ch_queue_fifo_remove(ch_queue_t *qp)
Removes the first-out element from a queue and returns it.
Definition: chlists.h:265
ch_pqueue_remove_highest
static ch_priority_queue_t * ch_pqueue_remove_highest(ch_priority_queue_t *pqp)
Removes the highest priority element from a priority queue and returns it.
Definition: chlists.h:337
ch_pqueue_insert_behind
static ch_priority_queue_t * ch_pqueue_insert_behind(ch_priority_queue_t *pqp, ch_priority_queue_t *p)
Inserts an element in the priority queue placing it behind its peers.
Definition: chlists.h:358
ch_queue
Structure representing a generic bidirectional linked list header and element.
Definition: chlists.h:69
ch_list_pop
static ch_list_t * ch_list_pop(ch_list_t *lp)
Pops an element from the top of a stack list and returns it.
Definition: chlists.h:192
ch_queue_init
static void ch_queue_init(ch_queue_t *qp)
Queue initialization.
Definition: chlists.h:207
ch_queue_lifo_remove
static ch_queue_t * ch_queue_lifo_remove(ch_queue_t *qp)
Removes the last-out element from a queue and returns it.
Definition: chlists.h:284
ch_list_isempty
static bool ch_list_isempty(ch_list_t *lp)
Evaluates to true if the specified list is empty.
Definition: chlists.h:151
ch_pqueue_init
static void ch_pqueue_init(ch_priority_queue_t *pqp)
Priority queue initialization.
Definition: chlists.h:321
ch_priority_queue::next
ch_priority_queue_t * next
Next in the list/queue.
Definition: chlists.h:86
ch_queue::prev
ch_queue_t * prev
Previous in the queue.
Definition: chlists.h:71
ch_priority_queue::prev
ch_priority_queue_t * prev
Previous in the queue.
Definition: chlists.h:87
ch_queue_dequeue
static ch_queue_t * ch_queue_dequeue(ch_queue_t *p)
Removes an element from a queue and returns it.
Definition: chlists.h:303
ch_list
Structure representing a generic single link list header and element.
Definition: chlists.h:56
ch_priority_queue
Structure representing a generic priority-ordered bidirectional linked list header and element.
Definition: chlists.h:85
ch_queue_insert
static void ch_queue_insert(ch_queue_t *p, ch_queue_t *qp)
Inserts an element into a queue.
Definition: chlists.h:247
ch_list_init
static void ch_list_init(ch_list_t *lp)
List initialization.
Definition: chlists.h:138