Skip to main content

static_doubly_list_links Class

A class for the core of a statically allocated doubly linked list (pointers to neighbours). More...

Declaration

class micro_os_plus::utils::static_doubly_list_links { ... }

Included Headers

Base class

classdoubly_list_links_base

A base class for a doubly linked list node. More...

Public Member Typedefs Index

usingis_statically_allocated = std::true_type

Type indicating that the links node is statically allocated. More...

Public Constructors Index

constexprstatic_doubly_list_links () noexcept

Construct a statically allocated list node (BSS initialised). More...

static_doubly_list_links (const static_doubly_list_links &)=delete

Deleted copy constructor. More...

static_doubly_list_links (static_doubly_list_links &&)=delete

Deleted move constructor. More...

Public Destructor Index

constexpr~static_doubly_list_links ()

Destruct the node. More...

Public Operators Index

static_doubly_list_links &operator= (const static_doubly_list_links &)=delete

Deleted copy assignment operator. More...

static_doubly_list_links &operator= (static_doubly_list_links &&)=delete

Deleted move assignment operator. More...

Public Member Functions Index

constexpr voidinitialise (void) noexcept

Initialise the node links. More...

boolinitialise_once (void) noexcept

Initialise the node links only if not already initialised. More...

boolinitialised (void) const noexcept

Check if the node is initialised. More...

voidlink_next (doubly_list_links_base *node) noexcept

Link the new node as next. More...

voidlink_previous (doubly_list_links_base *node) noexcept

Link the new node as previous. More...

constexpr boollinked (void) const noexcept

Check if the node is linked to a doubly linked list. More...

constexpr doubly_list_links_base *next (void) const noexcept

Get the link to the next node. More...

constexpr doubly_list_links_base *previous (void) const noexcept

Get the link to the previous node. More...

constexpr voidreset (void) noexcept

Reset the two pointers to nullptr. More...

voidunlink (void) noexcept

Remove this node from the list. More...

Protected Member Attributes Index

doubly_list_links_base *next_

Pointer to the next node. More...

doubly_list_links_base *previous_

Pointer to the previous node. More...

Description

A class for the core of a statically allocated doubly linked list (pointers to neighbours).

The static_doubly_list_links class inherits a pair of uninitialised pointers to the next and previous list elements, as well as methods to access and manipulate these pointers, from its base class.

Instances of this class are intended to be statically allocated in the BSS section and automatically cleared (set to zero) during startup. This design enables reliable initialisation before any static constructors are executed, which is essential because the order of static initialisation is not defined by the C++ standard.

Statically allocated lists are commonly used by registrar objects to automate the self-registration of other statically allocated objects, such as drivers, threads, and similar components. By leveraging BSS initialisation, the registrar is guaranteed to be ready before any static objects attempt to register themselves.

As a consequence, list initialisation cannot be performed in the constructor, but must be done manually before invoking any method that adds elements to the list. This approach ensures robust and predictable behaviour in embedded and system-level applications where static object registration is required.

Definition at line 380 of file doubly-list-links.h.

Public Member Typedefs

is_statically_allocated

using micro_os_plus::utils::static_doubly_list_links::is_statically_allocated = std::true_type

Type indicating that the links node is statically allocated.

Definition at line 386 of file doubly-list-links.h.

386 using is_statically_allocated = std::true_type;

Public Constructors

static_doubly_list_links()

micro_os_plus::utils::static_doubly_list_links::static_doubly_list_links ()
constexpr noexcept

Construct a statically allocated list node (BSS initialised).

This constructor is intended for statically allocated list link nodes. It must be empty and must not modify the member pointers, leaving them unchanged. For statically allocated objects, the entire memory region is zero-initialised at startup (via BSS initialisation), so both previous_ and next_ pointers are set to nullptr, representing an uninitialised state.

This approach ensures that statically allocated lists are in a known, safe state before any constructors run, and avoids unnecessary writes or side effects during construction.

warning

Code analysis tools may report:

  • Member previous_ was not initialized in constructor
  • Member next_ was not initialized in constructor These warnings are expected and can be safely ignored in this context.
The rule of five

The copy constructor, move constructor, copy assignment operator, and move assignment operator are explicitly deleted to prevent accidental copying or moving of static_doubly_list_links objects. This ensures the integrity of the list structure, as duplicating or moving nodes could result in invalid or inconsistent links within the list.

Declaration at line 392 of file doubly-list-links.h, definition at line 220 of file doubly-list-links-inlines.h.

221 {
222 // Must be empty! No members must be changed by this constructor!
223 }

Referenced by static_doubly_list_links, static_doubly_list_links, operator= and operator=.

static_doubly_list_links()

micro_os_plus::utils::static_doubly_list_links::static_doubly_list_links (const static_doubly_list_links &)
delete

Deleted copy constructor.

Copying of statically allocated list node objects is explicitly disallowed to prevent accidental duplication, which could compromise the integrity of the list structure.

Definition at line 402 of file doubly-list-links.h.

Reference static_doubly_list_links.

static_doubly_list_links()

micro_os_plus::utils::static_doubly_list_links::static_doubly_list_links (static_doubly_list_links &&)
delete

Deleted move constructor.

Moving of statically allocated list node objects is explicitly disallowed to avoid invalid or inconsistent links within the list that could result from moving nodes.

Definition at line 412 of file doubly-list-links.h.

Reference static_doubly_list_links.

Public Destructor

~static_doubly_list_links()

micro_os_plus::utils::static_doubly_list_links::~static_doubly_list_links ()
constexpr

Destruct the node.

The destructor for static_doubly_list_links is used to revert the content to a state similar to the statically initialised state (BSS zero).

Declaration at line 440 of file doubly-list-links.h, definition at line 231 of file doubly-list-links-inlines.h.

Reference reset.

Public Operators

operator=()

static_doubly_list_links & micro_os_plus::utils::static_doubly_list_links::operator= (const static_doubly_list_links &)
delete

Deleted copy assignment operator.

Copy assignment is explicitly disallowed to prevent accidental overwriting of list node objects, which could lead to corruption of the list structure.

Definition at line 423 of file doubly-list-links.h.

Reference static_doubly_list_links.

operator=()

static_doubly_list_links & micro_os_plus::utils::static_doubly_list_links::operator= (static_doubly_list_links &&)
delete

Deleted move assignment operator.

Move assignment is explicitly disallowed to avoid invalid or inconsistent links within the list that could result from moving nodes.

Definition at line 434 of file doubly-list-links.h.

References static_doubly_list_links and reset.

Public Member Functions

initialise()

void micro_os_plus::utils::doubly_list_links_base::initialise (void)
constexpr noexcept

Initialise the node links.

Parameters

None.

Returns

Nothing.

Sets both the previous_ and next_ pointers to point to this node itself, marking the node as unlinked. This state is used to indicate that the node is not currently part of any list.

This method is called during initialisation and after a node is unlinked from a list, ensuring the node is in a safe, standalone state and cannot be traversed as part of a list.

info

After unlinking a node from a list, it must be returned to this state to prevent accidental access through stale links.

Declaration at line 174 of file doubly-list-links.h, definition at line 120 of file doubly-list-links-inlines.h.

121 {
122 previous_ = this;
123 next_ = this;
124 }

References micro_os_plus::utils::doubly_list_links_base::next_ and micro_os_plus::utils::doubly_list_links_base::previous_.

Referenced by micro_os_plus::utils::doubly_list_links::doubly_list_links, micro_os_plus::utils::doubly_list_links_base::initialise_once and micro_os_plus::utils::doubly_list_links_base::unlink.

initialise_once()

bool micro_os_plus::utils::doubly_list_links_base::initialise_once (void)
noexcept

Initialise the node links only if not already initialised.

Parameters

None.

Returns

true if the node was initialised, false otherwise.

If the statically allocated list is still in the initial uninitialised state (with both pointers nullptr), this method initialises the list to the empty state, with both pointers pointing to itself.

For non-statically initialised lists, this method is ineffective, since the node is always initialised at construct time.

info

This method must be manually called for a statically allocated list before inserting elements or performing any other operations.

Declaration at line 185 of file doubly-list-links.h, definition at line 81 of file doubly-list-links.cpp.

82 {
83 if (!initialised ())
84 {
85 initialise ();
86 return true;
87 }
88 return false;
89 }

References micro_os_plus::utils::doubly_list_links_base::initialise and micro_os_plus::utils::doubly_list_links_base::initialised.

initialised()

bool micro_os_plus::utils::doubly_list_links_base::initialised (void)
nodiscard noexcept

Check if the node is initialised.

Parameters

None.

Return Values
true

The links are initialised.

false

The links are not initialised.

An uninitialised node is a node with its pointers set to nullptr. Only statically allocated nodes in their initial state are considered uninitialised. Regular (dynamically or automatically allocated) nodes are always initialised during construction, so this method will only return false for statically allocated nodes that have not yet been initialised.

Declaration at line 163 of file doubly-list-links.h, definition at line 56 of file doubly-list-links.cpp.

57 {
58 if (previous_ == nullptr || next_ == nullptr)
59 {
60 assert (previous_ == nullptr);
61 assert (next_ == nullptr);
62 return false;
63 }
64 return true;
65 }

References micro_os_plus::utils::doubly_list_links_base::next_ and micro_os_plus::utils::doubly_list_links_base::previous_.

Referenced by micro_os_plus::utils::doubly_list_links_base::initialise_once.

link_next()

void micro_os_plus::utils::doubly_list_links_base::link_next (doubly_list_links_base * node)
noexcept

Link the new node as next.

Parameters
[in] node

Pointer to the node to be linked as next.

Returns

Nothing.

Insert the new node between the next pointer and the node pointed by it. This operation is used by lists to link new nodes to the list head. The new node's previous_ pointer is set to the current node, and its next_ pointer is set to the current node's next_. The neighbouring nodes are updated to point to the new node, maintaining the integrity of the doubly-linked list.

Declaration at line 195 of file doubly-list-links.h, definition at line 101 of file doubly-list-links.cpp.

102 {
103#if defined(MICRO_OS_PLUS_UTILS_LISTS_TRACE_ENABLED)
104 trace::printf ("%s() link %p after %p\n", __func__,
105 static_cast<const void*> (node),
106 static_cast<const void*> (this));
107#endif // defined(MICRO_OS_PLUS_UTILS_LISTS_TRACE_ENABLED)
108 assert (next_ != nullptr);
109 assert (next_->previous_ != nullptr);
110
111 // Make the new node point to its new neighbours.
112 node->previous_ = this;
113 node->next_ = next_;
114
115 next_->previous_ = node;
116 next_ = node;
117 }

References micro_os_plus::utils::doubly_list_links_base::doubly_list_links_base and micro_os_plus::utils::doubly_list_links_base::next_.

link_previous()

void micro_os_plus::utils::doubly_list_links_base::link_previous (doubly_list_links_base * node)
noexcept

Link the new node as previous.

Parameters
[in] node

Pointer to the node to be linked as previous.

Returns

Nothing.

Insert the new node between the previous pointer and the node pointed by it. Used by lists to link new nodes to the list tail. The new node's next_ pointer is set to the current node, and its previous_ pointer is set to the current node's previous_. The neighbouring nodes are updated to point to the new node, maintaining the integrity of the doubly-linked list.

Declaration at line 205 of file doubly-list-links.h, definition at line 129 of file doubly-list-links.cpp.

130 {
131#if defined(MICRO_OS_PLUS_UTILS_LISTS_TRACE_ENABLED)
132 trace::printf ("%s() link %p before %p\n", __func__,
133 static_cast<const void*> (node),
134 static_cast<const void*> (this));
135#endif // defined(MICRO_OS_PLUS_UTILS_LISTS_TRACE_ENABLED)
136 assert (previous_ != nullptr);
137 assert (previous_->next_ != nullptr);
138
139 // Make the new node point to its new neighbours.
140 node->next_ = this;
141 node->previous_ = previous_;
142
143 previous_->next_ = node;
144 previous_ = node;
145 }

References micro_os_plus::utils::doubly_list_links_base::doubly_list_links_base and micro_os_plus::utils::doubly_list_links_base::previous_.

linked()

bool micro_os_plus::utils::doubly_list_links_base::linked (void)
nodiscard constexpr noexcept

Check if the node is linked to a doubly linked list.

Parameters

None.

Return Values
true

The node is linked with both pointers.

false

The node is not linked.

To be linked, both pointers must point to different nodes than itself (double list requirement). If either next_ or previous_ points to this, the node is considered unlinked (empty state). This method checks the node's linkage status for safe list operations.

Declaration at line 227 of file doubly-list-links.h, definition at line 177 of file doubly-list-links-inlines.h.

177 doubly_list_links_base::linked (void) const noexcept
178 {
179 if (next_ == this || previous_ == this)
180 {
181 assert (next_ == this);
182 assert (previous_ == this);
183 return false;
184 }
185 return true;
186 }

References micro_os_plus::utils::doubly_list_links_base::next_ and micro_os_plus::utils::doubly_list_links_base::previous_.

next()

doubly_list_links_base * micro_os_plus::utils::doubly_list_links_base::next (void)
nodiscard constexpr noexcept

Get the link to the next node.

Parameters

None.

Returns

Pointer to the next node.

Returns a pointer to the next node in the list. If this node is the last in the list, the returned pointer may refer back to the list's sentinel node (for example, the links node in the list container) or to itself if the list is empty.

info

The returned pointer is of type doubly_list_links_base* and may need to be cast to the appropriate derived type by the caller.

Declaration at line 237 of file doubly-list-links.h, definition at line 147 of file doubly-list-links-inlines.h.

147 doubly_list_links_base::next (void) const noexcept
148 {
149 return next_;
150 }

Reference micro_os_plus::utils::doubly_list_links_base::next_.

previous()

doubly_list_links_base * micro_os_plus::utils::doubly_list_links_base::previous (void)
nodiscard constexpr noexcept

Get the link to the previous node.

Parameters

None.

Returns

Pointer to the previous node.

Returns a pointer to the previous node in the list. If this node is the first in the list, the returned pointer may refer back to the list's sentinel node (such as the links node in the list container) or to itself if the list is empty.

info

The returned pointer is of type doubly_list_links_base* and may need to be cast to the appropriate derived type by the caller.

Declaration at line 247 of file doubly-list-links.h, definition at line 164 of file doubly-list-links-inlines.h.

165 {
166 return previous_;
167 }

Reference micro_os_plus::utils::doubly_list_links_base::previous_.

reset()

void micro_os_plus::utils::static_doubly_list_links::reset (void)
constexpr noexcept

Reset the two pointers to nullptr.

Parameters

None.

Returns

Nothing.

Sets both the next_ and previous_ pointers to nullptr, marking the node as uninitialised. This is typically used for statically allocated nodes to explicitly place them in an uninitialised state.

info

The assignments are performed through volatile-qualified pointers. The standard guarantees accesses to volatile objects to be observable side effects, so the compiler is not permitted to prove them dead and optimise them away, regardless of vendor (GCC, Clang, or otherwise). The same approach is used in the destructor.

Declaration at line 451 of file doubly-list-links.h, definition at line 250 of file doubly-list-links-inlines.h.

251 {
252 // Force actual writes, even if the compiler could otherwise prove that
253 // the values are never read afterwards (dead store elimination).
254 *const_cast<doubly_list_links_base* volatile*> (&next_) = nullptr;
255 *const_cast<doubly_list_links_base* volatile*> (&previous_) = nullptr;
256 }

References micro_os_plus::utils::doubly_list_links_base::doubly_list_links_base, micro_os_plus::utils::doubly_list_links_base::next_ and micro_os_plus::utils::doubly_list_links_base::previous_.

Referenced by ~static_doubly_list_links and operator=.

unlink()

void micro_os_plus::utils::doubly_list_links_base::unlink (void)
noexcept

Remove this node from the list.

Parameters

None.

Returns

Nothing.

Update both neighbours to point to each other, effectively removing the node from the list. The node is then returned to the initial state (empty), with both pointers pointing to itself. This operation is safe to call even if the node is already unlinked.

Declaration at line 216 of file doubly-list-links.h, definition at line 155 of file doubly-list-links.cpp.

156 {
157#if defined(MICRO_OS_PLUS_UTILS_LISTS_TRACE_ENABLED)
158 trace::printf ("%s() %p \n", __func__, static_cast<const void*> (this));
159#endif // defined(MICRO_OS_PLUS_UTILS_LISTS_TRACE_ENABLED)
160 assert (previous_ != nullptr);
161 assert (next_ != nullptr);
162
163 // Make neighbours point to each other.
164 // This works even if the node is already unlinked,
165 // so no need for an extra test.
166 previous_->next_ = next_;
167 next_->previous_ = previous_;
168
169 // Reset the unlinked node to the initial state,
170 // with both pointers pointing to itself.
171 initialise ();
172 }

References micro_os_plus::utils::doubly_list_links_base::initialise, micro_os_plus::utils::doubly_list_links_base::next_ and micro_os_plus::utils::doubly_list_links_base::previous_.


The documentation for this class was generated from the following files:


Generated via doxygen2docusaurus 2.2.2 by Doxygen 1.17.0.