ChibiOS 21.11.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 */
50typedef struct ch_list ch_list_t;
51
52/**
53 * @brief Structure representing a generic single link list header
54 * and element.
55 */
56struct 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 */
63typedef struct ch_queue ch_queue_t;
64
65/**
66 * @brief Structure representing a generic bidirectional linked list header
67 * and element.
68 */
69struct 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 queue. */
87 ch_priority_queue_t *prev; /**< @brief Previous in the queue. */
88 tprio_t prio; /**< @brief Priority of this element. */
89};
90
91/**
92 * @brief Type of a generic bidirectional linked delta list
93 * header and element.
94 */
96
97/**
98 * @brief Delta list element and header structure.
99 */
101 ch_delta_list_t *next; /**< @brief Next in the delta list. */
102 ch_delta_list_t *prev; /**< @brief Previous in the delta list. */
103 sysinterval_t delta; /**< @brief Time interval from previous.*/
104};
105
106/*===========================================================================*/
107/* Module macros. */
108/*===========================================================================*/
109
110/**
111 * @brief Data part of a static queue object initializer.
112 * @details This macro should be used when statically initializing a
113 * queue that is part of a bigger structure.
114 *
115 * @param[in] name the name of the queue variable
116 */
117#define __CH_QUEUE_DATA(name) {(ch_queue_t *)&name, (ch_queue_t *)&name}
118
119/**
120 * @brief Static queue object initializer.
121 * @details Statically initialized queues require no explicit
122 * initialization using @p queue_init().
123 *
124 * @param[in] name the name of the queue variable
125 */
126#define CH_QUEUE_DECL(name) \
127 ch_queue_t name = __CH_QUEUE_DATA(name)
128
129/*===========================================================================*/
130/* External declarations. */
131/*===========================================================================*/
132
133/* Early function prototypes required by the following headers.*/
134#ifdef __cplusplus
135extern "C" {
136#endif
137
138#ifdef __cplusplus
139}
140#endif
141
142/*===========================================================================*/
143/* Module inline functions. */
144/*===========================================================================*/
145
146/**
147 * @brief List initialization.
148 *
149 * @param[out] lp pointer to the list header
150 *
151 * @notapi
152 */
153static inline void ch_list_init(ch_list_t *lp) {
154
155 lp->next = lp;
156}
157
158/**
159 * @brief Evaluates to @p true if the specified list is empty.
160 *
161 * @param[in] lp pointer to the list header
162 * @return The status of the list.
163 *
164 * @notapi
165 */
166static inline bool ch_list_isempty(ch_list_t *lp) {
167
168 return (bool)(lp->next == lp);
169}
170
171/**
172 * @brief Evaluates to @p true if the specified list is not empty.
173 *
174 * @param[in] lp pointer to the list header
175 * @return The status of the list.
176 *
177 * @notapi
178 */
179static inline bool ch_list_notempty(ch_list_t *lp) {
180
181 return (bool)(lp->next != lp);
182}
183
184/**
185 * @brief Pushes an element on top of a stack list.
186 *
187 * @param[in] lp the pointer to the list header
188 * @param[in] p the pointer to the element to be inserted in the list
189 *
190 * @notapi
191 */
192static inline void ch_list_link(ch_list_t *lp, ch_list_t *p) {
193
194 p->next = lp->next;
195 lp->next = p;
196}
197
198/**
199 * @brief Pops an element from the top of a stack list and returns it.
200 * @pre The list must be non-empty before calling this function.
201 *
202 * @param[in] lp the pointer to the list header
203 * @return The removed element pointer.
204 *
205 * @notapi
206 */
207static inline ch_list_t *ch_list_unlink(ch_list_t *lp) {
208
209 ch_list_t *p = lp->next;
210 lp->next = p->next;
211
212 return p;
213}
214
215/**
216 * @brief Queue initialization.
217 *
218 * @param[out] qp pointer to the queue header
219 *
220 * @notapi
221 */
222static inline void ch_queue_init(ch_queue_t *qp) {
223
224 qp->next = qp;
225 qp->prev = qp;
226}
227
228/**
229 * @brief Evaluates to @p true if the specified queue is empty.
230 *
231 * @param[in] qp pointer to the queue header
232 * @return The status of the queue.
233 *
234 * @notapi
235 */
236static inline bool ch_queue_isempty(const ch_queue_t *qp) {
237
238 return (bool)(qp->next == qp);
239}
240
241/**
242 * @brief Evaluates to @p true if the specified queue is not empty.
243 *
244 * @param[in] qp pointer to the queue header
245 * @return The status of the queue.
246 *
247 * @notapi
248 */
249static inline bool ch_queue_notempty(const ch_queue_t *qp) {
250
251 return (bool)(qp->next != qp);
252}
253
254/**
255 * @brief Inserts an element into a queue.
256 *
257 * @param[in] qp the pointer to the queue header
258 * @param[in] p the pointer to the element to be inserted in the queue
259 *
260 * @notapi
261 */
262static inline void ch_queue_insert(ch_queue_t *qp, ch_queue_t *p) {
263
264 p->next = qp;
265 p->prev = qp->prev;
266 p->prev->next = p;
267 qp->prev = p;
268}
269
270/**
271 * @brief Removes the first-out element from a queue and returns it.
272 * @note If the queue is priority ordered then this function returns the
273 * element with the highest priority.
274 *
275 * @param[in] qp the pointer to the queue list header
276 * @return The removed element pointer.
277 *
278 * @notapi
279 */
281 ch_queue_t *p = qp->next;
282
283 qp->next = p->next;
284 qp->next->prev = qp;
285
286 return p;
287}
288
289/**
290 * @brief Removes the last-out element from a queue and returns it.
291 * @note If the queue is priority ordered then this function returns the
292 * element with the lowest priority.
293 *
294 * @param[in] qp the pointer to the queue list header
295 * @return The removed element pointer.
296 *
297 * @notapi
298 */
300 ch_queue_t *p = qp->prev;
301
302 qp->prev = p->prev;
303 qp->prev->next = qp;
304
305 return p;
306}
307
308/**
309 * @brief Removes an element from a queue and returns it.
310 * @details The element is removed from the queue regardless of its relative
311 * position and regardless the used insertion method.
312 *
313 * @param[in] p the pointer to the element to be removed from the queue
314 * @return The removed element pointer.
315 *
316 * @notapi
317 */
319
320 p->prev->next = p->next;
321 p->next->prev = p->prev;
322
323 return p;
324}
325
326/**
327 * @brief Priority queue initialization.
328 * @note The queue header priority is initialized to zero, all other
329 * elements in the queue are assumed to have priority greater
330 * than zero.
331 *
332 * @param[out] pqp pointer to the priority queue header
333 *
334 * @notapi
335 */
336static inline void ch_pqueue_init(ch_priority_queue_t *pqp) {
337
338 pqp->next = pqp;
339 pqp->prev = pqp;
340 pqp->prio = (tprio_t)0;
341}
342
343/**
344 * @brief Removes the highest priority element from a priority queue and
345 * returns it.
346 *
347 * @param[in] pqp the pointer to the priority queue list header
348 * @return The removed element pointer.
349 *
350 * @notapi
351 */
353 ch_priority_queue_t *p = pqp->next;
354
355 pqp->next = p->next;
356 pqp->next->prev = pqp;
357
358 return p;
359}
360
361/**
362 * @brief Inserts an element in the priority queue placing it behind
363 * its peers.
364 * @details The element is positioned behind all elements with higher or
365 * equal priority.
366 *
367 * @param[in] pqp the pointer to the priority queue list header
368 * @param[in] p the pointer to the element to be inserted in the queue
369 * @return The inserted element pointer.
370 *
371 * @notapi
372 */
375
376 /* Scanning priority queue, the list is assumed to be mostly empty.*/
377 do {
378 pqp = pqp->next;
379 } while (unlikely(pqp->prio >= p->prio));
380
381 /* Insertion on prev.*/
382 p->next = pqp;
383 p->prev = pqp->prev;
384 p->prev->next = p;
385 pqp->prev = p;
386
387 return p;
388}
389
390/**
391 * @brief Inserts an element in the priority queue placing it ahead of
392 * its peers.
393 * @details The element is positioned ahead of all elements with higher or
394 * equal priority.
395 *
396 * @param[in] pqp the pointer to the priority queue list header
397 * @param[in] p the pointer to the element to be inserted in the queue
398 * @return The inserted element pointer.
399 *
400 * @notapi
401 */
404
405 /* Scanning priority queue, the list is assumed to be mostly empty.*/
406 do {
407 pqp = pqp->next;
408 } while (unlikely(pqp->prio > p->prio));
409
410 /* Insertion on prev.*/
411 p->next = pqp;
412 p->prev = pqp->prev;
413 p->prev->next = p;
414 pqp->prev = p;
415
416 return p;
417}
418
419/**
420 * @brief Delta list initialization.
421 *
422 * @param[out] dlhp pointer to the delta list header
423 *
424 * @notapi
425 */
426static inline void ch_dlist_init(ch_delta_list_t *dlhp) {
427
428 dlhp->next = dlhp;
429 dlhp->prev = dlhp;
430 dlhp->delta = (sysinterval_t)-1;
431}
432
433/**
434 * @brief Evaluates to @p true if the specified delta list is empty.
435 *
436 * @param[in] dlhp pointer to the delta list header
437 * @return The status of the delta list.
438 *
439 * @notapi
440 */
441static inline bool ch_dlist_isempty(ch_delta_list_t *dlhp) {
442
443 return (bool)(dlhp == dlhp->next);
444}
445
446/**
447 * @brief Evaluates to @p true if the specified queue is not empty.
448 *
449 * @param[in] dlhp pointer to the delta list header
450 * @return The status of the delta list.
451 *
452 * @notapi
453 */
454static inline bool ch_dlist_notempty(ch_delta_list_t *dlhp) {
455
456 return (bool)(dlhp != dlhp->next);
457}
458
459/**
460 * @brief Last element in the delta list check.
461 *
462 * @param[in] dlhp pointer to the delta list header
463 * @param[in] dlp pointer to the delta list element
464 *
465 * @notapi
466 */
467static inline bool ch_dlist_islast(ch_delta_list_t *dlhp,
468 ch_delta_list_t *dlp) {
469
470 return (bool)(dlp->next == dlhp);
471}
472
473/**
474 * @brief Fist element in the delta list check.
475 *
476 * @param[in] dlhp pointer to the delta list header
477 * @param[in] dlp pointer to the delta list element
478 *
479 * @notapi
480 */
481static inline bool ch_dlist_isfirst(ch_delta_list_t *dlhp,
482 ch_delta_list_t *dlp) {
483
484 return (bool)(dlhp->next == dlp);
485}
486
487/**
488 * @brief Inserts an element after another header element.
489 *
490 * @param[in] dlhp pointer to the delta list header element
491 * @param[in] dlp element to be inserted after the header element
492 * @param[in] delta delta of the element to be inserted
493 *
494 * @notapi
495 */
496static inline void ch_dlist_insert_after(ch_delta_list_t *dlhp,
497 ch_delta_list_t *dlp,
498 sysinterval_t delta) {
499
500 dlp->delta = delta;
501 dlp->prev = dlhp;
502 dlp->next = dlp->prev->next;
503 dlp->next->prev = dlp;
504 dlhp->next = dlp;
505}
506
507/**
508 * @brief Inserts an element before another header element.
509 *
510 * @param[in] dlhp pointer to the delta list header element
511 * @param[in] dlp element to be inserted before the header element
512 * @param[in] delta delta of the element to be inserted
513 *
514 * @notapi
515 */
517 ch_delta_list_t *dlp,
518 sysinterval_t delta) {
519
520 dlp->delta = delta;
521 dlp->next = dlhp;
522 dlp->prev = dlp->next->prev;
523 dlp->prev->next = dlp;
524 dlhp->prev = dlp;
525}
526
527/**
528 * @brief Inserts an element in a delta list.
529 *
530 * @param[in] dlhp pointer to the delta list header element
531 * @param[in] dlep element to be inserted before the header element
532 * @param[in] delta delta of the element to be inserted
533 *
534 * @notapi
535 */
536static inline void ch_dlist_insert(ch_delta_list_t *dlhp,
537 ch_delta_list_t *dlep,
538 sysinterval_t delta) {
539 ch_delta_list_t *dlp;
540
541 /* The delta list is scanned in order to find the correct position for
542 this element. */
543 dlp = dlhp->next;
544 while (likely(dlp->delta < delta)) {
545 /* Debug assert if the element is already in the list.*/
546 chDbgAssert(dlp != dlep, "element already in list");
547
548 delta -= dlp->delta;
549 dlp = dlp->next;
550 }
551
552 /* The timer is inserted in the delta list.*/
553 ch_dlist_insert_before(dlp, dlep, delta);
554
555 /* Adjusting delta for the following element.*/
556 dlp->delta -= delta;
557
558 /* Special case when the inserted element is in last position in the list,
559 the value in the header must be restored, just doing it is faster than
560 checking then doing.*/
561 dlhp->delta = (sysinterval_t)-1;
562}
563
564/**
565 * @brief Dequeues an element from the delta list.
566 *
567 * @param[in] dlhp pointer to the delta list header
568 *
569 * @notapi
570 */
572 ch_delta_list_t *dlp = dlhp->next;
573
574 dlhp->next = dlp->next;
575 dlhp->next->prev = dlhp;
576
577 return dlp;
578}
579
580/**
581 * @brief Dequeues an element from the delta list.
582 *
583 * @param[in] dlp pointer to the delta list element
584 *
585 * @notapi
586 */
588
589 dlp->prev->next = dlp->next;
590 dlp->next->prev = dlp->prev;
591
592 return dlp;
593}
594
595#endif /* CHLISTS_H */
596
597/** @} */
#define chDbgAssert(c, r)
Condition assertion.
Definition chdebug.h:144
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:402
static ch_list_t * ch_list_unlink(ch_list_t *lp)
Pops an element from the top of a stack list and returns it.
Definition chlists.h:207
static void ch_list_init(ch_list_t *lp)
List initialization.
Definition chlists.h:153
static void ch_queue_init(ch_queue_t *qp)
Queue initialization.
Definition chlists.h:222
static ch_delta_list_t * ch_dlist_remove_first(ch_delta_list_t *dlhp)
Dequeues an element from the delta list.
Definition chlists.h:571
static bool ch_dlist_islast(ch_delta_list_t *dlhp, ch_delta_list_t *dlp)
Last element in the delta list check.
Definition chlists.h:467
static void ch_dlist_init(ch_delta_list_t *dlhp)
Delta list initialization.
Definition chlists.h:426
static bool ch_queue_notempty(const ch_queue_t *qp)
Evaluates to true if the specified queue is not empty.
Definition chlists.h:249
static void ch_pqueue_init(ch_priority_queue_t *pqp)
Priority queue initialization.
Definition chlists.h:336
static void ch_dlist_insert_after(ch_delta_list_t *dlhp, ch_delta_list_t *dlp, sysinterval_t delta)
Inserts an element after another header element.
Definition chlists.h:496
static void ch_dlist_insert_before(ch_delta_list_t *dlhp, ch_delta_list_t *dlp, sysinterval_t delta)
Inserts an element before another header element.
Definition chlists.h:516
static bool ch_dlist_notempty(ch_delta_list_t *dlhp)
Evaluates to true if the specified queue is not empty.
Definition chlists.h:454
static bool ch_dlist_isfirst(ch_delta_list_t *dlhp, ch_delta_list_t *dlp)
Fist element in the delta list check.
Definition chlists.h:481
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:352
static ch_delta_list_t * ch_dlist_dequeue(ch_delta_list_t *dlp)
Dequeues an element from the delta list.
Definition chlists.h:587
struct ch_priority_queue ch_priority_queue_t
Type of a generic priority-ordered bidirectional linked list header and element.
Definition chlists.h:78
static bool ch_queue_isempty(const ch_queue_t *qp)
Evaluates to true if the specified queue is empty.
Definition chlists.h:236
static ch_queue_t * ch_queue_dequeue(ch_queue_t *p)
Removes an element from a queue and returns it.
Definition chlists.h:318
struct ch_list ch_list_t
Type of a generic single link list header and element.
Definition chlists.h:50
static bool ch_list_notempty(ch_list_t *lp)
Evaluates to true if the specified list is not empty.
Definition chlists.h:179
struct ch_delta_list ch_delta_list_t
Type of a generic bidirectional linked delta list header and element.
Definition chlists.h:95
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:299
static bool ch_dlist_isempty(ch_delta_list_t *dlhp)
Evaluates to true if the specified delta list is empty.
Definition chlists.h:441
static void ch_queue_insert(ch_queue_t *qp, ch_queue_t *p)
Inserts an element into a queue.
Definition chlists.h:262
struct ch_queue ch_queue_t
Type of a generic bidirectional linked list header and element.
Definition chlists.h:63
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:280
static void ch_dlist_insert(ch_delta_list_t *dlhp, ch_delta_list_t *dlep, sysinterval_t delta)
Inserts an element in a delta list.
Definition chlists.h:536
static bool ch_list_isempty(ch_list_t *lp)
Evaluates to true if the specified list is empty.
Definition chlists.h:166
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:373
static void ch_list_link(ch_list_t *lp, ch_list_t *p)
Pushes an element on top of a stack list.
Definition chlists.h:192
#define likely(x)
Marks a boolean expression as likely true.
Definition chearly.h:178
uint32_t tprio_t
Definition chearly.h:87
#define unlikely(x)
Marks a boolean expression as likely false.
Definition chearly.h:191
uint64_t sysinterval_t
Type of time interval.
Definition chtime.h:119
Delta list element and header structure.
Definition chlists.h:100
ch_delta_list_t * next
Next in the delta list.
Definition chlists.h:101
sysinterval_t delta
Time interval from previous.
Definition chlists.h:103
ch_delta_list_t * prev
Previous in the delta list.
Definition chlists.h:102
Structure representing a generic single link list header and element.
Definition chlists.h:56
ch_list_t * next
Next in the list/queue.
Definition chlists.h:57
Structure representing a generic priority-ordered bidirectional linked list header and element.
Definition chlists.h:85
ch_priority_queue_t * next
Next in the queue.
Definition chlists.h:86
tprio_t prio
Priority of this element.
Definition chlists.h:88
ch_priority_queue_t * prev
Previous in the queue.
Definition chlists.h:87
Structure representing a generic bidirectional linked list header and element.
Definition chlists.h:69
ch_queue_t * prev
Previous in the queue.
Definition chlists.h:71
ch_queue_t * next
Next in the list/queue.
Definition chlists.h:70