Zephyr API Documentation 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
27
28#ifndef ZEPHYR_INCLUDE_SYS_DLIST_H_
29#define ZEPHYR_INCLUDE_SYS_DLIST_H_
30
31#include <stddef.h>
32#include <stdbool.h>
33
34#ifdef __cplusplus
35extern "C" {
36#endif
37
38
39struct _dnode {
40 union {
41 struct _dnode *head; /* ptr to head of list (sys_dlist_t) */
42 struct _dnode *next; /* ptr to next node (sys_dnode_t) */
43 };
44 union {
45 struct _dnode *tail; /* ptr to tail of list (sys_dlist_t) */
46 struct _dnode *prev; /* ptr to previous node (sys_dnode_t) */
47 };
48};
49
53typedef struct _dnode sys_dlist_t;
57typedef struct _dnode sys_dnode_t;
58
59
75#define SYS_DLIST_FOR_EACH_NODE(__dl, __dn) \
76 for (__dn = sys_dlist_peek_head(__dl); __dn != NULL; \
77 __dn = sys_dlist_peek_next(__dl, __dn))
78
99#define SYS_DLIST_ITERATE_FROM_NODE(__dl, __dn) \
100 for (__dn = __dn ? sys_dlist_peek_next_no_check(__dl, __dn) \
101 : sys_dlist_peek_head(__dl); \
102 __dn != NULL; \
103 __dn = sys_dlist_peek_next(__dl, __dn))
104
121#define SYS_DLIST_FOR_EACH_NODE_SAFE(__dl, __dn, __dns) \
122 for ((__dn) = sys_dlist_peek_head(__dl), \
123 (__dns) = sys_dlist_peek_next((__dl), (__dn)); \
124 (__dn) != NULL; (__dn) = (__dns), \
125 (__dns) = sys_dlist_peek_next(__dl, __dn))
126
135#define SYS_DLIST_CONTAINER(__dn, __cn, __n) \
136 (((__dn) != NULL) ? CONTAINER_OF(__dn, __typeof__(*(__cn)), __n) : NULL)
137
144#define SYS_DLIST_PEEK_HEAD_CONTAINER(__dl, __cn, __n) \
145 SYS_DLIST_CONTAINER(sys_dlist_peek_head(__dl), __cn, __n)
146
154#define SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n) \
155 (((__cn) != NULL) ? \
156 SYS_DLIST_CONTAINER(sys_dlist_peek_next((__dl), &((__cn)->__n)), \
157 __cn, __n) : NULL)
158
173#define SYS_DLIST_FOR_EACH_CONTAINER(__dl, __cn, __n) \
174 for ((__cn) = SYS_DLIST_PEEK_HEAD_CONTAINER(__dl, __cn, __n); \
175 (__cn) != NULL; \
176 (__cn) = SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n))
177
193#define SYS_DLIST_FOR_EACH_CONTAINER_SAFE(__dl, __cn, __cns, __n) \
194 for ((__cn) = SYS_DLIST_PEEK_HEAD_CONTAINER(__dl, __cn, __n), \
195 (__cns) = SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n); \
196 (__cn) != NULL; (__cn) = (__cns), \
197 (__cns) = SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n))
198
204
205static inline void sys_dlist_init(sys_dlist_t *list)
206{
207 list->head = (sys_dnode_t *)list;
208 list->tail = (sys_dnode_t *)list;
209}
210
214#define SYS_DLIST_STATIC_INIT(ptr_to_list) { {(ptr_to_list)}, {(ptr_to_list)} }
215
221
222static inline void sys_dnode_init(sys_dnode_t *node)
223{
224 node->next = NULL;
225 node->prev = NULL;
226}
227
235
236static inline bool sys_dnode_is_linked(const sys_dnode_t *node)
237{
238 return node->next != NULL;
239}
240
249
250static inline bool sys_dlist_is_head(const sys_dlist_t *list, const sys_dnode_t *node)
251{
252 return list->head == node;
253}
254
263
264static inline bool sys_dlist_is_tail(const sys_dlist_t *list, const sys_dnode_t *node)
265{
266 return list->tail == node;
267}
268
276
277static inline bool sys_dlist_is_empty(const sys_dlist_t *list)
278{
279 return list->head == list;
280}
281
291
292static inline bool sys_dlist_has_multiple_nodes(const sys_dlist_t *list)
293{
294 return list->head != list->tail;
295}
296
304
305static inline sys_dnode_t *sys_dlist_peek_head(const sys_dlist_t *list)
306{
307 return sys_dlist_is_empty(list) ? NULL : list->head;
308}
309
319
321{
322 return list->head;
323}
324
335
337 const sys_dnode_t *node)
338{
339 return (node == list->tail) ? NULL : node->next;
340}
341
351
352static inline sys_dnode_t *sys_dlist_peek_next(const sys_dlist_t *list,
353 const sys_dnode_t *node)
354{
355 return (node != NULL) ? sys_dlist_peek_next_no_check(list, node) : NULL;
356}
357
369
371 const sys_dnode_t *node)
372{
373 return (node == list->head) ? NULL : node->prev;
374}
375
386
387static inline sys_dnode_t *sys_dlist_peek_prev(const sys_dlist_t *list,
388 const sys_dnode_t *node)
389{
390 return (node != NULL) ? sys_dlist_peek_prev_no_check(list, node) : NULL;
391}
392
400
401static inline sys_dnode_t *sys_dlist_peek_tail(const sys_dlist_t *list)
402{
403 return sys_dlist_is_empty(list) ? NULL : list->tail;
404}
405
414
415static inline void sys_dlist_append(sys_dlist_t *list, sys_dnode_t *node)
416{
417 sys_dnode_t *const tail = list->tail;
418
419 node->next = list;
420 node->prev = tail;
421
422 tail->next = node;
423 list->tail = node;
424}
425
434
435static inline void sys_dlist_prepend(sys_dlist_t *list, sys_dnode_t *node)
436{
437 sys_dnode_t *const head = list->head;
438
439 node->next = head;
440 node->prev = list;
441
442 head->prev = node;
443 list->head = node;
444}
445
454static inline void sys_dlist_insert(sys_dnode_t *successor, sys_dnode_t *node)
455{
456 sys_dnode_t *const prev = successor->prev;
457
458 node->prev = prev;
459 node->next = successor;
460 prev->next = node;
461 successor->prev = node;
462}
463
478
479static inline void sys_dlist_insert_at(sys_dlist_t *list, sys_dnode_t *node,
480 int (*cond)(sys_dnode_t *node, void *data), void *data)
481{
482 if (sys_dlist_is_empty(list)) {
483 sys_dlist_append(list, node);
484 } else {
485 sys_dnode_t *pos = sys_dlist_peek_head(list);
486
487 while ((pos != NULL) && (cond(pos, data) == 0)) {
488 pos = sys_dlist_peek_next(list, pos);
489 }
490 if (pos != NULL) {
491 sys_dlist_insert(pos, node);
492 } else {
493 sys_dlist_append(list, node);
494 }
495 }
496}
497
512static inline void sys_dlist_dequeue(sys_dnode_t *node)
513{
514 sys_dnode_t *const prev = node->prev;
515 sys_dnode_t *const next = node->next;
516
517 prev->next = next;
518 next->prev = prev;
519}
520
529
530static inline void sys_dlist_remove(sys_dnode_t *node)
531{
532 sys_dnode_t *const prev = node->prev;
533 sys_dnode_t *const next = node->next;
534
535 prev->next = next;
536 next->prev = prev;
537 sys_dnode_init(node);
538}
539
553static inline void sys_dlist_range_prepend(sys_dlist_t *dest,
554 sys_dnode_t *start, sys_dnode_t *last)
555{
556 sys_dnode_t *const head = dest->head;
557 sys_dnode_t *const prev = start->prev;
558 sys_dnode_t *const next = last->next;
559
560 /* Remove the range from its current list. */
561 prev->next = next;
562 next->prev = prev;
563
564 /* Prepend the range to the destination list. */
565 last->next = head;
566 start->prev = dest;
567
568 head->prev = last;
569 dest->head = start;
570}
571
583static inline void sys_dlist_range_append(sys_dlist_t *dest,
584 sys_dnode_t *start, sys_dnode_t *last)
585{
586 sys_dnode_t *const tail = dest->tail;
587 sys_dnode_t *const prev = start->prev;
588 sys_dnode_t *const next = last->next;
589
590 /* Remove the range from its current list. */
591 prev->next = next;
592 next->prev = prev;
593
594 /* Append the range to the destination list. */
595 last->next = dest;
596 start->prev = tail;
597
598 tail->next = start;
599 dest->tail = last;
600}
601
611
613{
614 sys_dnode_t *node = NULL;
615
616 if (!sys_dlist_is_empty(list)) {
617 node = list->head;
618 sys_dlist_remove(node);
619 }
620
621 return node;
622}
623
631static inline size_t sys_dlist_len(const sys_dlist_t *list)
632{
633 size_t len = 0;
634 sys_dnode_t *node = NULL;
635
636 SYS_DLIST_FOR_EACH_NODE(list, node) {
637 len++;
638 }
639 return len;
640}
641
643
644#ifdef __cplusplus
645}
646#endif
647
648#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:530
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:305
static void sys_dlist_append(sys_dlist_t *list, sys_dnode_t *node)
add node to tail of list
Definition dlist.h:415
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:336
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:553
static sys_dnode_t * sys_dlist_get(sys_dlist_t *list)
get the first node in a list
Definition dlist.h:612
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:264
#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:75
static bool sys_dlist_has_multiple_nodes(const sys_dlist_t *list)
check if more than one node present
Definition dlist.h:292
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:370
struct _dnode sys_dnode_t
Doubly-linked list node structure.
Definition dlist.h:57
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:479
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:631
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:352
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:320
static void sys_dlist_prepend(sys_dlist_t *list, sys_dnode_t *node)
add node to head of list
Definition dlist.h:435
static void sys_dlist_insert(sys_dnode_t *successor, sys_dnode_t *node)
Insert a node into a list.
Definition dlist.h:454
struct _dnode sys_dlist_t
Doubly-linked list structure.
Definition dlist.h:53
static bool sys_dlist_is_empty(const sys_dlist_t *list)
check if the list is empty
Definition dlist.h:277
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:387
static bool sys_dnode_is_linked(const sys_dnode_t *node)
check if a node is a member of any list
Definition dlist.h:236
static void sys_dnode_init(sys_dnode_t *node)
initialize node to its state when not in a list
Definition dlist.h:222
static void sys_dlist_dequeue(sys_dnode_t *node)
remove a specific node from a list
Definition dlist.h:512
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:401
static void sys_dlist_init(sys_dlist_t *list)
initialize list to its empty state
Definition dlist.h:205
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:583
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:250