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