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