1.. _slist_api:
2
3Single-linked List
4==================
5
6Zephyr provides a :c:struct:`sys_slist_t` type for storing simple
7singly-linked list data (i.e. data where each list element stores a
8pointer to the next element, but not the previous one).  This supports
9constant-time access to the first (head) and last (tail) elements of
10the list, insertion before the head and after the tail of the list and
11constant time removal of the head.  Removal of subsequent nodes
12requires access to the "previous" pointer and thus can only be
13performed in linear time by searching the list.
14
15The :c:struct:`sys_slist_t` struct may be instantiated by the user in any
16accessible memory.  It should be initialized with either
17:c:func:`sys_slist_init` or by static assignment from SYS_SLIST_STATIC_INIT
18before use.  Its interior fields are opaque and should not be accessed
19by user code.
20
21The end nodes of a list may be retrieved with
22:c:func:`sys_slist_peek_head` and :c:func:`sys_slist_peek_tail`, which will
23return NULL if the list is empty, otherwise a pointer to a
24:c:struct:`sys_snode_t` struct.
25
26The :c:struct:`sys_snode_t` struct represents the data to be inserted.  In
27general, it is expected to be allocated/controlled by the user,
28usually embedded within a struct which is to be added to the list.
29The container struct pointer may be retrieved from a list node using
30:c:macro:`SYS_SLIST_CONTAINER`, passing it the struct name of the
31containing struct and the field name of the node.  Internally, the
32:c:struct:`sys_snode_t` struct contains only a next pointer, which may be
33accessed with :c:func:`sys_slist_peek_next`.
34
35Lists may be modified by adding a single node at the head or tail with
36:c:func:`sys_slist_prepend` and :c:func:`sys_slist_append`.  They may also
37have a node added to an interior point with :c:func:`sys_slist_insert`,
38which inserts a new node after an existing one.  Similarly
39:c:func:`sys_slist_remove` will remove a node given a pointer to its
40predecessor.  These operations are all constant time.
41
42Convenience routines exist for more complicated modifications to a
43list.  :c:func:`sys_slist_merge_slist` will append an entire list to an
44existing one.  :c:func:`sys_slist_append_list` will append a bounded
45subset of an existing list in constant time.  And
46:c:func:`sys_slist_find_and_remove` will search a list (in linear time)
47for a given node and remove it if present.
48
49Finally the slist implementation provides a set of "for each" macros
50that allows for iterating over a list in a natural way without needing
51to manually traverse the next pointers.  :c:macro:`SYS_SLIST_FOR_EACH_NODE`
52will enumerate every node in a list given a local variable to store
53the node pointer.  :c:macro:`SYS_SLIST_FOR_EACH_NODE_SAFE` behaves
54similarly, but has a more complicated implementation that requires an
55extra scratch variable for storage and allows the user to delete the
56iterated node during the iteration.  Each of those macros also exists
57in a "container" variant (:c:macro:`SYS_SLIST_FOR_EACH_CONTAINER` and
58:c:macro:`SYS_SLIST_FOR_EACH_CONTAINER_SAFE`) which assigns a local
59variable of a type that matches the user's container struct and not
60the node struct, performing the required offsets internally.  And
61:c:macro:`SYS_SLIST_ITERATE_FROM_NODE` exists to allow for enumerating a
62node and all its successors only, without inspecting the earlier part
63of the list.
64
65Single-linked List Internals
66----------------------------
67
68The slist code is designed to be minimal and conventional.
69Internally, a :c:struct:`sys_slist_t` struct is nothing more than a pair of
70"head" and "tail" pointer fields.  And a :c:struct:`sys_snode_t` stores only a
71single "next" pointer.
72
73.. figure:: slist.png
74    :align: center
75    :alt: slist example
76    :figclass: align-center
77
78    An slist containing three elements.
79
80.. figure:: slist-empty.png
81    :align: center
82    :alt: empty slist example
83    :figclass: align-center
84
85    An empty slist
86
87The specific implementation of the list code, however, is done with an
88internal "Z_GENLIST" template API which allows for extracting those
89fields from arbitrary structures and emits an arbitrarily named set of
90functions.  This allows for implementing more complicated
91single-linked list variants using the same basic primitives.  The
92genlist implementor is responsible for a custom implementation of the
93primitive operations only: an "init" step for each struct, and a "get"
94and "set" primitives for each of head, tail and next pointers on their
95relevant structs.  These inline functions are passed as parameters to
96the genlist macro expansion.
97
98Only one such variant, sflist, exists in Zephyr at the moment.
99
100
101Flagged List
102------------
103
104The :c:struct:`sys_sflist_t` is implemented using the described genlist
105template API.  With the exception of symbol naming ("sflist" instead
106of "slist") and the additional API described next, it operates in all
107ways identically to the slist API.
108
109It adds the ability to associate exactly two bits of user defined
110"flags" with each list node.  These can be accessed and modified with
111:c:func:`sys_sfnode_flags_get` and :c:func:`sys_sfnode_flags_get`.
112Internally, the flags are stored unioned with the bottom bits of the
113next pointer and incur no SRAM storage overhead when compared with the
114simpler slist code.
115
116
117Single-linked List API Reference
118--------------------------------
119
120.. doxygengroup:: single-linked-list_apis
121
122Flagged List API Reference
123--------------------------------
124
125.. doxygengroup:: flagged-single-linked-list_apis
126