doc: strcutures: use doxygen to reference functions
Use :c:func:`..` possible to reference and link doxygen documentation. Signed-off-by: Anas Nashif <anas.nashif@intel.com>
This commit is contained in:
parent
e9662c8cf4
commit
d31d6ce0be
5 changed files with 74 additions and 73 deletions
|
@ -11,28 +11,28 @@ the head, tail or any internal node). To do this, the list stores two
|
||||||
pointers per node, and thus has somewhat higher runtime code and
|
pointers per node, and thus has somewhat higher runtime code and
|
||||||
memory space needs.
|
memory space needs.
|
||||||
|
|
||||||
A ``sys_dlist_t`` struct may be instantiated by the user in any
|
A :c:struct:`sys_dlist_t` struct may be instantiated by the user in any
|
||||||
accessible memory. It must be initialized with ``sys_dlist_init()``
|
accessible memory. It must be initialized with :c:func:`sys_dlist_init`
|
||||||
or ``SYS_DLIST_STATIC_INIT()`` before use. The ``sys_dnode_t`` struct
|
or :c:macro:`SYS_DLIST_STATIC_INIT` before use. The :c:struct:`sys_dnode_t` struct
|
||||||
is expected to be provided by the user for any nodes addded to the
|
is expected to be provided by the user for any nodes addded to the
|
||||||
list (typically embedded within the struct to be tracked, as described
|
list (typically embedded within the struct to be tracked, as described
|
||||||
above). It must be initialized in zeroed/bss memory or with
|
above). It must be initialized in zeroed/bss memory or with
|
||||||
``sys_dnode_init()`` before use.
|
:c:func:`sys_dnode_init` before use.
|
||||||
|
|
||||||
Primitive operations may retrieve the head/tail of a list and the
|
Primitive operations may retrieve the head/tail of a list and the
|
||||||
next/prev pointers of a node with ``sys_dlist_peek_head()``,
|
next/prev pointers of a node with :c:func:`sys_dlist_peek_head`,
|
||||||
``sys_dlist_peek_tail()``, ``sys_dlist_peek_next()`` and
|
:c:func:`sys_dlist_peek_tail`, :c:func:`sys_dlist_peek_next` and
|
||||||
``sys_dlist_peek_prev()``. These can all return NULL where
|
:c:func:`sys_dlist_peek_prev`. These can all return NULL where
|
||||||
appropriate (i.e. for empty lists, or nodes at the endpoints of the
|
appropriate (i.e. for empty lists, or nodes at the endpoints of the
|
||||||
list).
|
list).
|
||||||
|
|
||||||
A dlist can be modified in constant time by removing a node with
|
A dlist can be modified in constant time by removing a node with
|
||||||
``sys_dlist_remove()``, by adding a node to the head or tail of a list
|
:c:func:`sys_dlist_remove`, by adding a node to the head or tail of a list
|
||||||
with ``sys_dlist_prepend()`` and ``sys_dlist_append()``, or by
|
with :c:func:`sys_dlist_prepend` and :c:func:`sys_dlist_append`, or by
|
||||||
inserting a node before an existing node with ``sys_dlist_insert()``.
|
inserting a node before an existing node with :c:func:`sys_dlist_insert`.
|
||||||
|
|
||||||
As for slist, each node in a dlist can be processed in a natural code
|
As for slist, each node in a dlist can be processed in a natural code
|
||||||
block style using ``SYS_DLIST_FOR_EACH_NODE()``. This macro also
|
block style using :c:macro:`SYS_DLIST_FOR_EACH_NODE`. This macro also
|
||||||
exists in a "FROM_NODE" form which allows for iterating from a known
|
exists in a "FROM_NODE" form which allows for iterating from a known
|
||||||
starting point, a "SAFE" variant that allows for removing the node
|
starting point, a "SAFE" variant that allows for removing the node
|
||||||
being inspected within the code block, a "CONTAINER" style that
|
being inspected within the code block, a "CONTAINER" style that
|
||||||
|
@ -40,18 +40,18 @@ provides the pointer to a containing struct instead of the raw node,
|
||||||
and a "CONTAINER_SAFE" variant that provides both properties.
|
and a "CONTAINER_SAFE" variant that provides both properties.
|
||||||
|
|
||||||
Convenience utilities provided by dlist include
|
Convenience utilities provided by dlist include
|
||||||
``sys_dlist_insert_at()``, which inserts a node that linearly searches
|
:c:func:`sys_dlist_insert_at`, which inserts a node that linearly searches
|
||||||
through a list to find the right insertion point, which is provided by
|
through a list to find the right insertion point, which is provided by
|
||||||
the user as a C callback function pointer, and
|
the user as a C callback function pointer, and
|
||||||
``sys_dlist_is_linked()``, which will affirmatively return whether or
|
:c:func:`sys_dnode_is_linked`, which will affirmatively return whether or
|
||||||
not a node is currently linked into a dlist or not (via an
|
not a node is currently linked into a dlist or not (via an
|
||||||
implementation that has zero overhead vs. the normal list processing).
|
implementation that has zero overhead vs. the normal list processing).
|
||||||
|
|
||||||
Double-linked List Internals
|
Double-linked List Internals
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
Internally, the dlist implementation is minimal: the ``sys_dlist_t``
|
Internally, the dlist implementation is minimal: the :c:struct:`sys_dlist_t`
|
||||||
struct contains "head" and "tail" pointer fields, the ``sys_dnode_t``
|
struct contains "head" and "tail" pointer fields, the :c:struct:`sys_dnode_t`
|
||||||
contains "prev" and "next" pointers, and no other data is stored. But
|
contains "prev" and "next" pointers, and no other data is stored. But
|
||||||
in practice the two structs are internally identical, and the list
|
in practice the two structs are internally identical, and the list
|
||||||
struct is inserted as a node into the list itself. This allows for a
|
struct is inserted as a node into the list itself. This allows for a
|
||||||
|
|
|
@ -10,15 +10,15 @@ which has runtimes on search and removal operations bounded at
|
||||||
O(log2(N)) for a tree of size N. This is implemented using a
|
O(log2(N)) for a tree of size N. This is implemented using a
|
||||||
conventional red/black tree as described by multiple academic sources.
|
conventional red/black tree as described by multiple academic sources.
|
||||||
|
|
||||||
The ``struct rbtree`` tracking struct for a rbtree may be initialized
|
The :c:struct:`rbtree` tracking struct for a rbtree may be initialized
|
||||||
anywhere in user accessible memory. It should contain only zero bits
|
anywhere in user accessible memory. It should contain only zero bits
|
||||||
before first use. No specific initialization API is needed or
|
before first use. No specific initialization API is needed or
|
||||||
required.
|
required.
|
||||||
|
|
||||||
Unlike a list, where position is explicit, the ordering of nodes
|
Unlike a list, where position is explicit, the ordering of nodes
|
||||||
within an rbtree must be provided as a predicate function by the user.
|
within an rbtree must be provided as a predicate function by the user.
|
||||||
A function of type ``rb_lessthan_t()`` should be assigned to the
|
A function of type :c:func:`rb_lessthan_t` should be assigned to the
|
||||||
``lessthan_fn`` field of the ``struct rbtree`` before any tree
|
``lessthan_fn`` field of the :c:struct`rbtree` struct before any tree
|
||||||
operations are attempted. This function should, as its name suggests,
|
operations are attempted. This function should, as its name suggests,
|
||||||
return a boolean True value if the first node argument is "less than"
|
return a boolean True value if the first node argument is "less than"
|
||||||
the second in the ordering desired by the tree. Note that "equal" is
|
the second in the ordering desired by the tree. Note that "equal" is
|
||||||
|
@ -26,40 +26,40 @@ not allowed, nodes within a tree must have a single fixed order for
|
||||||
the algorithm to work correctly.
|
the algorithm to work correctly.
|
||||||
|
|
||||||
As with the slist and dlist containers, nodes within an rbtree are
|
As with the slist and dlist containers, nodes within an rbtree are
|
||||||
represented as a ``struct rbnode`` structure which exists in
|
represented as a :c:struct:`rbnode` structure which exists in
|
||||||
user-managed memory, typically embedded within the the data structure
|
user-managed memory, typically embedded within the the data structure
|
||||||
being tracked in the tree. Unlike the list code, the data within an
|
being tracked in the tree. Unlike the list code, the data within an
|
||||||
rbnode is entirely opaque. It is not possible for the user to extract
|
rbnode is entirely opaque. It is not possible for the user to extract
|
||||||
the binary tree topology and "manually" traverse the tree as it is for
|
the binary tree topology and "manually" traverse the tree as it is for
|
||||||
a list.
|
a list.
|
||||||
|
|
||||||
Nodes can be inserted into a tree with ``rb_insert()`` and removed
|
Nodes can be inserted into a tree with :c:func:`rb_insert` and removed
|
||||||
with ``rb_remove()``. Access to the "first" and "last" nodes within a
|
with :c:func:`rb_remove`. Access to the "first" and "last" nodes within a
|
||||||
tree (in the sense of the order defined by the comparison function) is
|
tree (in the sense of the order defined by the comparison function) is
|
||||||
provided by ``rb_get_min()`` and ``rb_get_max()``. There is also a
|
provided by :c:func:`rb_get_min` and :c:func:`rb_get_max`. There is also a
|
||||||
predicate, ``rb_contains()``, which returns a boolean True if the
|
predicate, :c:func:`rb_contains`, which returns a boolean True if the
|
||||||
provided node pointer exists as an element within the tree. As
|
provided node pointer exists as an element within the tree. As
|
||||||
described above, all of these routines are guaranteed to have at most
|
described above, all of these routines are guaranteed to have at most
|
||||||
log time complexity in the size of the tree.
|
log time complexity in the size of the tree.
|
||||||
|
|
||||||
There are two mechanisms provided for enumerating all elements in an
|
There are two mechanisms provided for enumerating all elements in an
|
||||||
rbtree. The first, ``rb_walk()``, is a simple callback implementation
|
rbtree. The first, :c:func:`rb_walk`, is a simple callback implementation
|
||||||
where the caller specifies a C function pointer and an untyped
|
where the caller specifies a C function pointer and an untyped
|
||||||
argument to be passed to it, and the tree code calls that function for
|
argument to be passed to it, and the tree code calls that function for
|
||||||
each node in order. This has the advantage of a very simple
|
each node in order. This has the advantage of a very simple
|
||||||
implementation, at the cost of a somewhat more cumbersome API for the
|
implementation, at the cost of a somewhat more cumbersome API for the
|
||||||
user (not unlike ISO C's ``bsearch()`` routine). It is a recursive
|
user (not unlike ISO C's :c:func:`bsearch` routine). It is a recursive
|
||||||
implementation, however, and is thus not always available in
|
implementation, however, and is thus not always available in
|
||||||
environments that forbid the use of unbounded stack techniques like
|
environments that forbid the use of unbounded stack techniques like
|
||||||
recursion.
|
recursion.
|
||||||
|
|
||||||
There is also a ``RB_FOR_EACH()`` iterator provided, which, like the
|
There is also a :c:macro:`RB_FOR_EACH` iterator provided, which, like the
|
||||||
similar APIs for the lists, works to iterate over a list in a more
|
similar APIs for the lists, works to iterate over a list in a more
|
||||||
natural way, using a nested code block instead of a callback. It is
|
natural way, using a nested code block instead of a callback. It is
|
||||||
also nonrecursive, though it requires log-sized space on the stack by
|
also nonrecursive, though it requires log-sized space on the stack by
|
||||||
default (however, this can be configured to use a fixed/maximally size
|
default (however, this can be configured to use a fixed/maximally size
|
||||||
buffer instead where needed to avoid the dynamic allocation). As with
|
buffer instead where needed to avoid the dynamic allocation). As with
|
||||||
the lists, this is also available in a ``RB_FOR_EACH_CONTAINER()``
|
the lists, this is also available in a :c:macro:`RB_FOR_EACH_CONTAINER`
|
||||||
variant which enumerates using a pointer to a container field and not
|
variant which enumerates using a pointer to a container field and not
|
||||||
the raw node pointer.
|
the raw node pointer.
|
||||||
|
|
||||||
|
@ -94,12 +94,12 @@ modification.
|
||||||
These rotations are conceptually implemented on top of a primitive
|
These rotations are conceptually implemented on top of a primitive
|
||||||
that "swaps" the position of one node with another in the list.
|
that "swaps" the position of one node with another in the list.
|
||||||
Typical implementations effect this by simply swapping the nodes
|
Typical implementations effect this by simply swapping the nodes
|
||||||
internal "data" pointers, but because the Zephyr ``struct rbnode`` is
|
internal "data" pointers, but because the Zephyr :c:struct:`rbnode` is
|
||||||
intrusive, that cannot work. Zephyr must include somewhat more
|
intrusive, that cannot work. Zephyr must include somewhat more
|
||||||
elaborate code to handle the edge cases (for example, one swapped node
|
elaborate code to handle the edge cases (for example, one swapped node
|
||||||
can be the root, or the two may already be parent/child).
|
can be the root, or the two may already be parent/child).
|
||||||
|
|
||||||
The ``struct rbnode`` struct for a Zephyr rbtree contains only two
|
The :c:struct:`rbnode` struct for a Zephyr rbtree contains only two
|
||||||
pointers, representing the "left", and "right" children of a node
|
pointers, representing the "left", and "right" children of a node
|
||||||
within the binary tree. Traversal of a tree for rebalancing following
|
within the binary tree. Traversal of a tree for rebalancing following
|
||||||
modification, however, routinely requires the ability to iterate
|
modification, however, routinely requires the ability to iterate
|
||||||
|
|
|
@ -52,62 +52,62 @@ data buffer to empty.
|
||||||
|
|
||||||
|
|
||||||
A ``struct ring_buf`` may be placed anywhere in user-accessible
|
A ``struct ring_buf`` may be placed anywhere in user-accessible
|
||||||
memory, and must be initialized with ``ring_buf_init()`` before use.
|
memory, and must be initialized with :c:func:`ring_buf_init` before use.
|
||||||
This must be provided a region of user-controlled memory for use as
|
This must be provided a region of user-controlled memory for use as
|
||||||
the buffer itself. Note carefully that the units of the size of the
|
the buffer itself. Note carefully that the units of the size of the
|
||||||
buffer passed change (either bytes or words) depending on how the ring
|
buffer passed change (either bytes or words) depending on how the ring
|
||||||
buffer will be used later. Macros for combining these steps in a
|
buffer will be used later. Macros for combining these steps in a
|
||||||
single static declaration exist for convenience.
|
single static declaration exist for convenience.
|
||||||
``RING_BUF_DECLARE()`` will declare and statically initialize a ring
|
:c:macro:`RING_BUF_DECLARE` will declare and statically initialize a ring
|
||||||
buffer with a specified byte count, where
|
buffer with a specified byte count, where
|
||||||
``RING_BUF_ITEM_DECLARE_SIZE()`` will declare and statically
|
:c:macro:`RING_BUF_ITEM_DECLARE_SIZE` will declare and statically
|
||||||
initialize a buffer with a given count of 32 bit words.
|
initialize a buffer with a given count of 32 bit words.
|
||||||
``RING_BUF_ITEM_DECLARE_POW2()`` can be used to initialize an
|
:c:macro:`RING_BUF_ITEM_DECLARE_POW2` can be used to initialize an
|
||||||
items-mode buffer with a memory region guaranteed to be a power of
|
items-mode buffer with a memory region guaranteed to be a power of
|
||||||
two, which enables various optimizations internal to the
|
two, which enables various optimizations internal to the
|
||||||
implementation. No power-of-two initialization is available for
|
implementation. No power-of-two initialization is available for
|
||||||
bytes-mode ring buffers.
|
bytes-mode ring buffers.
|
||||||
|
|
||||||
"Bytes" data may be copied into the ring buffer using
|
"Bytes" data may be copied into the ring buffer using
|
||||||
``ring_buf_put()``, passing a data pointer and byte count. These
|
:c:func:`ring_buf_put`, passing a data pointer and byte count. These
|
||||||
bytes will be copied into the buffer in order, as many as will fit in
|
bytes will be copied into the buffer in order, as many as will fit in
|
||||||
the allocated buffer. The total number of bytes copied (which may be
|
the allocated buffer. The total number of bytes copied (which may be
|
||||||
fewer than provided) will be returned. Likewise ``ring_buf_get()``
|
fewer than provided) will be returned. Likewise :c:func:`ring_buf_get`
|
||||||
will copy bytes out of the ring buffer in the order that they were
|
will copy bytes out of the ring buffer in the order that they were
|
||||||
written, into a user-provided buffer, returning the number of bytes
|
written, into a user-provided buffer, returning the number of bytes
|
||||||
that were transferred.
|
that were transferred.
|
||||||
|
|
||||||
To avoid multiply-copied-data situations, a "claim" API exists for
|
To avoid multiply-copied-data situations, a "claim" API exists for
|
||||||
byte mode. ``ring_buf_put_claim()`` takes a byte size value from the
|
byte mode. :c:func:`ring_buf_put_claim` takes a byte size value from the
|
||||||
user and returns a pointer to memory internal to the ring buffer that
|
user and returns a pointer to memory internal to the ring buffer that
|
||||||
can be used to receive those bytes, along with a size of the
|
can be used to receive those bytes, along with a size of the
|
||||||
contiguous internal region (which may be smaller than requested). The
|
contiguous internal region (which may be smaller than requested). The
|
||||||
user can then copy data into that region at a later time without
|
user can then copy data into that region at a later time without
|
||||||
assembling all the bytes in a single region first. When complete,
|
assembling all the bytes in a single region first. When complete,
|
||||||
``ring_buf_put_finish()`` can be used to signal the buffer that the
|
:c:func:`ring_buf_put_finish` can be used to signal the buffer that the
|
||||||
transfer is complete, passing the number of bytes actually
|
transfer is complete, passing the number of bytes actually
|
||||||
transferred. At this point a new transfer can be initiated.
|
transferred. At this point a new transfer can be initiated.
|
||||||
Similarly, ``ring_buf_get_claim()`` returns a pointer to internal ring
|
Similarly, :c:func:`ring_buf_get_claim` returns a pointer to internal ring
|
||||||
buffer data from which the user can read without making a verbatim
|
buffer data from which the user can read without making a verbatim
|
||||||
copy, and ``ring_buf_get_finish()`` signals the buffer with how many
|
copy, and :c:func:`ring_buf_get_finish` signals the buffer with how many
|
||||||
bytes have been consumed and allows for a new transfer to begin.
|
bytes have been consumed and allows for a new transfer to begin.
|
||||||
|
|
||||||
"Items" mode works similarly to bytes mode, except that all transfers
|
"Items" mode works similarly to bytes mode, except that all transfers
|
||||||
are in units of 32 bit words and all memory is assumed to be aligned
|
are in units of 32 bit words and all memory is assumed to be aligned
|
||||||
on 32 bit boundaries. The write and read operations are
|
on 32 bit boundaries. The write and read operations are
|
||||||
``ring_buf_item_put()`` and ``ring_buf_item_get()``, and work
|
:c:func:`ring_buf_item_put` and :c:func:`ring_buf_item_get`, and work
|
||||||
otherwise identically to the bytes mode APIs. There no "claim" API
|
otherwise identically to the bytes mode APIs. There no "claim" API
|
||||||
provided for items mode. One important difference is that unlike
|
provided for items mode. One important difference is that unlike
|
||||||
``ring_buf_put()``, ``ring_buf_item_put()`` will not do a partial
|
:c:func:`ring_buf_put`, :c:func:`ring_buf_item_put` will not do a partial
|
||||||
transfer; it will return an error in the case where the provided data
|
transfer; it will return an error in the case where the provided data
|
||||||
does not fit in its entirety.
|
does not fit in its entirety.
|
||||||
|
|
||||||
The user can manage the capacity of a ring buffer without modifying it
|
The user can manage the capacity of a ring buffer without modifying it
|
||||||
using the ``ring_buf_space_get()`` call (which returns a value of
|
using the :c:func:`ring_buf_space_get` call (which returns a value of
|
||||||
either bytes or items depending on how the ring buffer has been used),
|
either bytes or items depending on how the ring buffer has been used),
|
||||||
or by testing the ``ring_buf_is_empty()`` predicate.
|
or by testing the :c:func:`ring_buf_is_empty` predicate.
|
||||||
|
|
||||||
Finally, a ``ring_buf_reset()`` call exists to immediately empty a
|
Finally, a :c:func:`ring_buf_reset` call exists to immediately empty a
|
||||||
ring buffer, discarding the tracking of any bytes or items already
|
ring buffer, discarding the tracking of any bytes or items already
|
||||||
written to the buffer. It does not modify the memory contents of the
|
written to the buffer. It does not modify the memory contents of the
|
||||||
buffer itself, however.
|
buffer itself, however.
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
Single-linked List
|
Single-linked List
|
||||||
==================
|
==================
|
||||||
|
|
||||||
Zephyr provides a ``sys_slist_t`` type for storing simple
|
Zephyr provides a :c:struct:`sys_slist_t` type for storing simple
|
||||||
singly-linked list data (i.e. data where each list element stores a
|
singly-linked list data (i.e. data where each list element stores a
|
||||||
pointer to the next element, but not the previous one). This supports
|
pointer to the next element, but not the previous one). This supports
|
||||||
constant-time access to the first (head) and last (tail) elements of
|
constant-time access to the first (head) and last (tail) elements of
|
||||||
|
@ -12,53 +12,53 @@ constant time removal of the head. Removal of subsequent nodes
|
||||||
requires access to the "previous" pointer and thus can only be
|
requires access to the "previous" pointer and thus can only be
|
||||||
performed in linear time by searching the list.
|
performed in linear time by searching the list.
|
||||||
|
|
||||||
The ``sys_slist_t`` struct may be instantiated by the user in any
|
The :c:struct:`sys_slist_t` struct may be instantiated by the user in any
|
||||||
accessible memory. It should be initialized with either
|
accessible memory. It should be initialized with either
|
||||||
``sys_slist_init()`` or by static assignment from SYS_SLIST_STATIC_INIT
|
:c:func:`sys_slist_init` or by static assignment from SYS_SLIST_STATIC_INIT
|
||||||
before use. Its interior fields are opaque and should not be accessed
|
before use. Its interior fields are opaque and should not be accessed
|
||||||
by user code.
|
by user code.
|
||||||
|
|
||||||
The end nodes of a list may be retrieved with
|
The end nodes of a list may be retrieved with
|
||||||
``sys_slist_peek_head()`` and ``sys_slist_peek_tail()``, which will
|
:c:func:`sys_slist_peek_head` and :c:func:`sys_slist_peek_tail`, which will
|
||||||
return NULL if the list is empty, otherwise a pointer to a
|
return NULL if the list is empty, otherwise a pointer to a
|
||||||
``sys_snode_t`` struct.
|
:c:struct:`sys_snode_t` struct.
|
||||||
|
|
||||||
The ``sys_snode_t`` struct represents the data to be inserted. In
|
The :c:struct:`sys_snode_t` struct represents the data to be inserted. In
|
||||||
general, it is expected to be allocated/controlled by the user,
|
general, it is expected to be allocated/controlled by the user,
|
||||||
usually embedded within a struct which is to be added to the list.
|
usually embedded within a struct which is to be added to the list.
|
||||||
The container struct pointer may be retrieved from a list node using
|
The container struct pointer may be retrieved from a list node using
|
||||||
``SYS_SLIST_CONTAINER()``, passing it the struct name of the
|
:c:macro:`SYS_SLIST_CONTAINER`, passing it the struct name of the
|
||||||
containing struct and the field name of the node. Internally, the
|
containing struct and the field name of the node. Internally, the
|
||||||
``sys_snode_t`` struct contains only a next pointer, which may be
|
:c:struct:`sys_snode_t` struct contains only a next pointer, which may be
|
||||||
accessed with ``sys_slist_peek_next()``.
|
accessed with :c:func:`sys_slist_peek_next`.
|
||||||
|
|
||||||
Lists may be modified by adding a single node at the head or tail with
|
Lists may be modified by adding a single node at the head or tail with
|
||||||
``sys_slist_prepend()`` and ``sys_slist_append()``. They may also
|
:c:func:`sys_slist_prepend` and :c:func:`sys_slist_append`. They may also
|
||||||
have a node added to an interior point with ``sys_slist_insert()``,
|
have a node added to an interior point with :c:func:`sys_slist_insert`,
|
||||||
which inserts a new node after an existing one. Similarly
|
which inserts a new node after an existing one. Similarly
|
||||||
``sys_slist_remove()`` will remove a node given a pointer to its
|
:c:func:`sys_slist_remove` will remove a node given a pointer to its
|
||||||
predecessor. These operations are all constant time.
|
predecessor. These operations are all constant time.
|
||||||
|
|
||||||
Convenience routines exist for more complicated modifications to a
|
Convenience routines exist for more complicated modifications to a
|
||||||
list. ``sys_slist_merge_slist()`` will append an entire list to an
|
list. :c:func:`sys_slist_merge_slist` will append an entire list to an
|
||||||
existing one. ``sys_slist_append_list()`` will append a bounded
|
existing one. :c:func:`sys_slist_append_list` will append a bounded
|
||||||
subset of an existing list in constant time. And
|
subset of an existing list in constant time. And
|
||||||
``sys_slist_find_and_remove()`` will search a list (in linear time)
|
:c:func:`sys_slist_find_and_remove` will search a list (in linear time)
|
||||||
for a given node and remove it if present.
|
for a given node and remove it if present.
|
||||||
|
|
||||||
Finally the slist implementation provides a set of "for each" macros
|
Finally the slist implementation provides a set of "for each" macros
|
||||||
that allows for iterating over a list in a natural way without needing
|
that allows for iterating over a list in a natural way without needing
|
||||||
to manually traverse the next pointers. ``SYS_SLIST_FOR_EACH_NODE()``
|
to manually traverse the next pointers. :c:macro:`SYS_SLIST_FOR_EACH_NODE`
|
||||||
will enumerate every node in a list given a local variable to store
|
will enumerate every node in a list given a local variable to store
|
||||||
the node pointer. ``SYS_SLIST_FOR_EACH_NODE_SAFE()`` behaves
|
the node pointer. :c:macro:`SYS_SLIST_FOR_EACH_NODE_SAFE` behaves
|
||||||
similarly, but has a more complicated implementation that requires an
|
similarly, but has a more complicated implementation that requires an
|
||||||
extra scratch variable for storage and allows the user to delete the
|
extra scratch variable for storage and allows the user to delete the
|
||||||
iterated node during the iteration. Each of those macros also exists
|
iterated node during the iteration. Each of those macros also exists
|
||||||
in a "container" variant (``SYS_SLIST_FOR_EACH_CONTAINER()`` and
|
in a "container" variant (:c:macro:`SYS_SLIST_FOR_EACH_CONTAINER` and
|
||||||
``SYS_SLIST_FOR_EACH_CONTAINER_SAFE()``) which assigns a local
|
:c:macro:`SYS_SLIST_FOR_EACH_CONTAINER_SAFE`) which assigns a local
|
||||||
variable of a type that matches the user's container struct and not
|
variable of a type that matches the user's container struct and not
|
||||||
the node struct, performing the required offsets internally. And
|
the node struct, performing the required offsets internally. And
|
||||||
``SYS_SLIST_ITERATE_FROM_NODE()`` exists to allow for enumerating a
|
:c:macro:`SYS_SLIST_ITERATE_FROM_NODE` exists to allow for enumerating a
|
||||||
node and all its successors only, without inspecting the earlier part
|
node and all its successors only, without inspecting the earlier part
|
||||||
of the list.
|
of the list.
|
||||||
|
|
||||||
|
@ -66,8 +66,8 @@ Single-linked List Internals
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
The slist code is designed to be minimal and conventional.
|
The slist code is designed to be minimal and conventional.
|
||||||
Internally, a ``sys_slist_t`` struct is nothing more than a pair of
|
Internally, a :c:struct:`sys_slist_t` struct is nothing more than a pair of
|
||||||
"head" and "tail" pointer fields. And a ``sys_snode_t`` stores only a
|
"head" and "tail" pointer fields. And a :c:struct:`sys_snode_t` stores only a
|
||||||
single "next" pointer.
|
single "next" pointer.
|
||||||
|
|
||||||
.. figure:: slist.png
|
.. figure:: slist.png
|
||||||
|
@ -101,14 +101,14 @@ Only one such variant, sflist, exists in Zephyr at the moment.
|
||||||
Flagged List
|
Flagged List
|
||||||
------------
|
------------
|
||||||
|
|
||||||
The ``sys_sflist_t`` is implemented using the described genlist
|
The :c:struct:`sys_sflist_t` is implemented using the described genlist
|
||||||
template API. With the exception of symbol naming ("sflist" instead
|
template API. With the exception of symbol naming ("sflist" instead
|
||||||
of "slist") and the additional API described next, it operates in all
|
of "slist") and the additional API described next, it operates in all
|
||||||
ways identically to the slist API.
|
ways identically to the slist API.
|
||||||
|
|
||||||
It adds the ability to associate exactly two bits of user defined
|
It adds the ability to associate exactly two bits of user defined
|
||||||
"flags" with each list node. These can be accessed and modified with
|
"flags" with each list node. These can be accessed and modified with
|
||||||
``sys_sflist_flags_get()`` and ``sys_sflist_flags_get()``.
|
:c:func:`sys_sfnode_flags_get` and :c:func:`sys_sfnode_flags_get`.
|
||||||
Internally, the flags are stored unioned with the bottom bits of the
|
Internally, the flags are stored unioned with the bottom bits of the
|
||||||
next pointer and incur no SRAM storage overhead when compared with the
|
next pointer and incur no SRAM storage overhead when compared with the
|
||||||
simpler slist code.
|
simpler slist code.
|
||||||
|
|
|
@ -28,6 +28,12 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup doubly-linked-list_apis Doubly-linked list
|
||||||
|
* @ingroup datastructure_apis
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
struct _dnode {
|
struct _dnode {
|
||||||
union {
|
union {
|
||||||
struct _dnode *head; /* ptr to head of list (sys_dlist_t) */
|
struct _dnode *head; /* ptr to head of list (sys_dlist_t) */
|
||||||
|
@ -42,11 +48,6 @@ struct _dnode {
|
||||||
typedef struct _dnode sys_dlist_t;
|
typedef struct _dnode sys_dlist_t;
|
||||||
typedef struct _dnode sys_dnode_t;
|
typedef struct _dnode sys_dnode_t;
|
||||||
|
|
||||||
/**
|
|
||||||
* @defgroup doubly-linked-list_apis Doubly-linked list
|
|
||||||
* @ingroup datastructure_apis
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Provide the primitive to iterate on a list
|
* @brief Provide the primitive to iterate on a list
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue