Zephyr Project API 4.4.99
A Scalable Open Source RTOS
Loading...
Searching...
No Matches
dlist.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2013-2015 Wind River Systems, Inc.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
29
30#ifndef ZEPHYR_INCLUDE_SYS_DLIST_H_
31#define ZEPHYR_INCLUDE_SYS_DLIST_H_
32
33#include <stddef.h>
34#include <stdbool.h>
35
36#ifdef __cplusplus
37extern "C" {
38#endif
39
40
41struct _dnode {
42 union {
43 struct _dnode *head; /* ptr to head of list (sys_dlist_t) */
44 struct _dnode *next; /* ptr to next node (sys_dnode_t) */
45 };
46 union {
47 struct _dnode *tail; /* ptr to tail of list (sys_dlist_t) */
48 struct _dnode *prev; /* ptr to previous node (sys_dnode_t) */
49 };
50};
51
55typedef struct _dnode sys_dlist_t;
59typedef struct _dnode sys_dnode_t;
60
61
77#define SYS_DLIST_FOR_EACH_NODE(__dl, __dn) \
78 for (__dn = sys_dlist_peek_head(__dl); __dn != NULL; \
79 __dn = sys_dlist_peek_next(__dl, __dn))
80
101#define SYS_DLIST_ITERATE_FROM_NODE(__dl, __dn) \
102 for (__dn = __dn ? sys_dlist_peek_next_no_check(__dl, __dn) \
103 : sys_dlist_peek_head(__dl); \
104 __dn != NULL; \
105 __dn = sys_dlist_peek_next(__dl, __dn))
106
123#define SYS_DLIST_FOR_EACH_NODE_SAFE(__dl, __dn, __dns) \
124 for ((__dn) = sys_dlist_peek_head(__dl), \
125 (__dns) = sys_dlist_peek_next((__dl), (__dn)); \
126 (__dn) != NULL; (__dn) = (__dns), \
127 (__dns) = sys_dlist_peek_next(__dl, __dn))
128
137#define SYS_DLIST_CONTAINER(__dn, __cn, __n) \
138 (((__dn) != NULL) ? CONTAINER_OF(__dn, __typeof__(*(__cn)), __n) : NULL)
139
146#define SYS_DLIST_PEEK_HEAD_CONTAINER(__dl, __cn, __n) \
147 SYS_DLIST_CONTAINER(sys_dlist_peek_head(__dl), __cn, __n)
148
156#define SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n) \
157 (((__cn) != NULL) ? \
158 SYS_DLIST_CONTAINER(sys_dlist_peek_next((__dl), &((__cn)->__n)), \
159 __cn, __n) : NULL)
160
175#define SYS_DLIST_FOR_EACH_CONTAINER(__dl, __cn, __n) \
176 for ((__cn) = SYS_DLIST_PEEK_HEAD_CONTAINER(__dl, __cn, __n); \
177 (__cn) != NULL; \
178 (__cn) = SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n))
179
195#define SYS_DLIST_FOR_EACH_CONTAINER_SAFE(__dl, __cn, __cns, __n) \
196 for ((__cn) = SYS_DLIST_PEEK_HEAD_CONTAINER(__dl, __cn, __n), \
197 (__cns) = SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n); \
198 (__cn) != NULL; (__cn) = (__cns), \
199 (__cns) = SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n))
200
206
207static inline void sys_dlist_init(sys_dlist_t *list)
208{
209 list->head = (sys_dnode_t *)list;
210 list->tail = (sys_dnode_t *)list;
211}
212
216#define SYS_DLIST_STATIC_INIT(ptr_to_list) { {(ptr_to_list)}, {(ptr_to_list)} }
217
223
224static inline void sys_dnode_init(sys_dnode_t *node)
225{
226 node->next = NULL;
227 node->prev = NULL;
228}
229
237
238static inline bool sys_dnode_is_linked(const sys_dnode_t *node)
239{
240 return node->next != NULL;
241}
242
251
252static inline bool sys_dlist_is_head(const sys_dlist_t *list, const sys_dnode_t *node)
253{
254 return list->head == node;
255}
256
265
266static inline bool sys_dlist_is_tail(const sys_dlist_t *list, const sys_dnode_t *node)
267{
268 return list->tail == node;
269}
270
278
279static inline bool sys_dlist_is_empty(const sys_dlist_t *list)
280{
281 return list->head == list;
282}
283
293
294static inline bool sys_dlist_has_multiple_nodes(const sys_dlist_t *list)
295{
296 return list->head != list->tail;
297}
298
306
307static inline sys_dnode_t *sys_dlist_peek_head(const sys_dlist_t *list)
308{
309 return sys_dlist_is_empty(list) ? NULL : list->head;
310}
311
321
323{
324 return list->head;
325}
326
337
339 const sys_dnode_t *node)
340{
341 return (node == list->tail) ? NULL : node->next;
342}
343
353
354static inline sys_dnode_t *sys_dlist_peek_next(const sys_dlist_t *list,
355 const sys_dnode_t *node)
356{
357 return (node != NULL) ? sys_dlist_peek_next_no_check(list, node) : NULL;
358}
359
371
373 const sys_dnode_t *node)
374{
375 return (node == list->head) ? NULL : node->prev;
376}
377
388
389static inline sys_dnode_t *sys_dlist_peek_prev(const sys_dlist_t *list,
390 const sys_dnode_t *node)
391{
392 return (node != NULL) ? sys_dlist_peek_prev_no_check(list, node) : NULL;
393}
394
402
403static inline sys_dnode_t *sys_dlist_peek_tail(const sys_dlist_t *list)
404{
405 return sys_dlist_is_empty(list) ? NULL : list->tail;
406}
407
416
417static inline void sys_dlist_append(sys_dlist_t *list, sys_dnode_t *node)
418{
419 sys_dnode_t *const tail = list->tail;
420
421 node->next = list;
422 node->prev = tail;
423
424 tail->next = node;
425 list->tail = node;
426}
427
436
437static inline void sys_dlist_prepend(sys_dlist_t *list, sys_dnode_t *node)
438{
439 sys_dnode_t *const head = list->head;
440
441 node->next = head;
442 node->prev = list;
443
444 head->prev = node;
445 list->head = node;
446}
447
456static inline void sys_dlist_insert(sys_dnode_t *successor, sys_dnode_t *node)
457{
458 sys_dnode_t *const prev = successor->prev;
459
460 node->prev = prev;
461 node->next = successor;
462 prev->next = node;
463 successor->prev = node;
464}
465
480
481static inline void sys_dlist_insert_at(sys_dlist_t *list, sys_dnode_t *node,
482 int (*cond)(sys_dnode_t *node, void *data), void *data)
483{
484 if (sys_dlist_is_empty(list)) {
485 sys_dlist_append(list, node);
486 } else {
487 sys_dnode_t *pos = sys_dlist_peek_head(list);
488
489 while ((pos != NULL) && (cond(pos, data) == 0)) {
490 pos = sys_dlist_peek_next(list, pos);
491 }
492 if (pos != NULL) {
493 sys_dlist_insert(pos, node);
494 } else {
495 sys_dlist_append(list, node);
496 }
497 }
498}
499
514static inline void sys_dlist_dequeue(sys_dnode_t *node)
515{
516 sys_dnode_t *const prev = node->prev;
517 sys_dnode_t *const next = node->next;
518
519 prev->next = next;
520 next->prev = prev;
521}
522
531
532static inline void sys_dlist_remove(sys_dnode_t *node)
533{
534 sys_dnode_t *const prev = node->prev;
535 sys_dnode_t *const next = node->next;
536
537 prev->next = next;
538 next->prev = prev;
539 sys_dnode_init(node);
540}
541
555static inline void sys_dlist_range_prepend(sys_dlist_t *dest,
556 sys_dnode_t *start, sys_dnode_t *last)
557{
558 sys_dnode_t *const head = dest->head;
559 sys_dnode_t *const prev = start->prev;
560 sys_dnode_t *const next = last->next;
561
562 /* Remove the range from its current list. */
563 prev->next = next;
564 next->prev = prev;
565
566 /* Prepend the range to the destination list. */
567 last->next = head;
568 start->prev = dest;
569
570 head->prev = last;
571 dest->head = start;
572}
573
585static inline void sys_dlist_range_append(sys_dlist_t *dest,
586 sys_dnode_t *start, sys_dnode_t *last)
587{
588 sys_dnode_t *const tail = dest->tail;
589 sys_dnode_t *const prev = start->prev;
590 sys_dnode_t *const next = last->next;
591
592 /* Remove the range from its current list. */
593 prev->next = next;
594 next->prev = prev;
595
596 /* Append the range to the destination list. */
597 last->next = dest;
598 start->prev = tail;
599
600 tail->next = start;
601 dest->tail = last;
602}
603
613
615{
616 sys_dnode_t *node = NULL;
617
618 if (!sys_dlist_is_empty(list)) {
619 node = list->head;
620 sys_dlist_remove(node);
621 }
622
623 return node;
624}
625
633static inline size_t sys_dlist_len(const sys_dlist_t *list)
634{
635 size_t len = 0;
636 sys_dnode_t *node = NULL;
637
638 SYS_DLIST_FOR_EACH_NODE(list, node) {
639 len++;
640 }
641 return len;
642}
643
645
646#ifdef __cplusplus
647}
648#endif
649
650#endif /* ZEPHYR_INCLUDE_SYS_DLIST_H_ */
static void sys_dlist_remove(sys_dnode_t *node)
remove a specific node from a list
Definition dlist.h:532
static sys_dnode_t * sys_dlist_peek_head(const sys_dlist_t *list)
get a reference to the head item in the list
Definition dlist.h:307
static void sys_dlist_append(sys_dlist_t *list, sys_dnode_t *node)
add node to tail of list
Definition dlist.h:417
static sys_dnode_t * sys_dlist_peek_next_no_check(const sys_dlist_t *list, const sys_dnode_t *node)
get a reference to the next item in the list, node is not NULL
Definition dlist.h:338
static void sys_dlist_range_prepend(sys_dlist_t *dest, sys_dnode_t *start, sys_dnode_t *last)
Move a range of nodes to the head of the specified list.
Definition dlist.h:555
static sys_dnode_t * sys_dlist_get(sys_dlist_t *list)
get the first node in a list
Definition dlist.h:614
static bool sys_dlist_is_tail(const sys_dlist_t *list, const sys_dnode_t *node)
check if a node is the list's tail
Definition dlist.h:266
#define SYS_DLIST_FOR_EACH_NODE(__dl, __dn)
Provide the primitive to iterate on a list Note: the loop is unsafe and thus __dn should not be remov...
Definition dlist.h:77
static bool sys_dlist_has_multiple_nodes(const sys_dlist_t *list)
check if more than one node present
Definition dlist.h:294
static sys_dnode_t * sys_dlist_peek_prev_no_check(const sys_dlist_t *list, const sys_dnode_t *node)
get a reference to the previous item in the list, node is not NULL
Definition dlist.h:372
struct _dnode sys_dnode_t
Doubly-linked list node structure.
Definition dlist.h:59
static void sys_dlist_insert_at(sys_dlist_t *list, sys_dnode_t *node, int(*cond)(sys_dnode_t *node, void *data), void *data)
insert node at position
Definition dlist.h:481
static size_t sys_dlist_len(const sys_dlist_t *list)
Compute the size of the given list in O(n) time.
Definition dlist.h:633
static sys_dnode_t * sys_dlist_peek_next(const sys_dlist_t *list, const sys_dnode_t *node)
get a reference to the next item in the list
Definition dlist.h:354
static sys_dnode_t * sys_dlist_peek_head_not_empty(const sys_dlist_t *list)
get a reference to the head item in the list
Definition dlist.h:322
static void sys_dlist_prepend(sys_dlist_t *list, sys_dnode_t *node)
add node to head of list
Definition dlist.h:437
static void sys_dlist_insert(sys_dnode_t *successor, sys_dnode_t *node)
Insert a node into a list.
Definition dlist.h:456
struct _dnode sys_dlist_t
Doubly-linked list structure.
Definition dlist.h:55
static bool sys_dlist_is_empty(const sys_dlist_t *list)
check if the list is empty
Definition dlist.h:279
static sys_dnode_t * sys_dlist_peek_prev(const sys_dlist_t *list, const sys_dnode_t *node)
get a reference to the previous item in the list
Definition dlist.h:389
static bool sys_dnode_is_linked(const sys_dnode_t *node)
check if a node is a member of any list
Definition dlist.h:238
static void sys_dnode_init(sys_dnode_t *node)
initialize node to its state when not in a list
Definition dlist.h:224
static void sys_dlist_dequeue(sys_dnode_t *node)
remove a specific node from a list
Definition dlist.h:514
static sys_dnode_t * sys_dlist_peek_tail(const sys_dlist_t *list)
get a reference to the tail item in the list
Definition dlist.h:403
static void sys_dlist_init(sys_dlist_t *list)
initialize list to its empty state
Definition dlist.h:207
static void sys_dlist_range_append(sys_dlist_t *dest, sys_dnode_t *start, sys_dnode_t *last)
Move a range of nodes to the end of the specified list.
Definition dlist.h:585
static bool sys_dlist_is_head(const sys_dlist_t *list, const sys_dnode_t *node)
check if a node is the list's head
Definition dlist.h:252
#define NULL
Definition iar_missing_defs.h:20