SuperTinyKernel™ RTOS 1.05.3
Lightweight, high-performance, deterministic, bare-metal C++ RTOS for resource-constrained embedded systems. MIT Open Source License.
Loading...
Searching...
No Matches
stk_linked_list.h
Go to the documentation of this file.
1/*
2 * SuperTinyKernel(TM) RTOS: Lightweight High-Performance Deterministic C++ RTOS for Embedded Systems.
3 *
4 * Source: https://github.com/SuperTinyKernel-RTOS
5 *
6 * Copyright (c) 2022-2026 Neutron Code Limited <stk@neutroncode.com>. All Rights Reserved.
7 * License: MIT License, see LICENSE for a full text.
8 */
9
10#ifndef STK_LINKED_LIST_H_
11#define STK_LINKED_LIST_H_
12
29
30namespace stk {
31namespace util {
32
33// Forward declaration required so DListEntry can reference DListHead as a friend
34// and store a back-pointer to the owning list head.
35template <class T, bool _ClosedLoop> class DListHead;
36
57template <class T, bool _ClosedLoop> class DListEntry
58{
59 friend class DListHead<T, _ClosedLoop>;
60
61public:
64 explicit DListEntry() : m_head(nullptr), m_next(nullptr), m_prev(nullptr)
65 {}
66
71
76
80 DLHeadType *GetHead() const { return m_head; }
81
88 DLEntryType *GetNext() const { return m_next; }
89
96 DLEntryType *GetPrev() const { return m_prev; }
97
101 bool IsLinked() const { return (GetHead() != nullptr); }
102
108 operator T *() { return static_cast<T *>(this); }
109
115 operator const T *() const { return static_cast<const T *>(this); }
116
117protected:
127 {}
128
129private:
137 void Link(DLHeadType *head, DLEntryType *next, DLEntryType *prev)
138 {
139 m_head = head;
140 m_next = next;
141 m_prev = prev;
142
143 if (m_prev != nullptr)
144 m_prev->m_next = this;
145
146 if (m_next != nullptr)
147 m_next->m_prev = this;
148 }
149
157 void Unlink()
158 {
159 if (m_prev != nullptr)
160 m_prev->m_next = m_next;
161
162 if (m_next != nullptr)
163 m_next->m_prev = m_prev;
164
165 m_head = nullptr;
166 m_next = nullptr;
167 m_prev = nullptr;
168 }
169
173};
174
195template <class T, bool _ClosedLoop> class DListHead
196{
197 friend class DListEntry<T, _ClosedLoop>;
198
199public:
204
207 explicit DListHead(): m_count(0), m_first(nullptr), m_last(nullptr)
208 {}
209
213 size_t GetSize() const { return m_count; }
214
218 bool IsEmpty() const { return (m_count == 0); }
219
223 DLEntryType *GetFirst() const { return m_first; }
224
228 DLEntryType *GetLast() const { return m_last; }
229
234 void Clear() { while (!IsEmpty()) Unlink(m_first); }
235
239 void LinkBack(DLEntryType *entry) { Link(entry, nullptr, m_last); }
240
244 void LinkBack(DLEntryType &entry) { Link(&entry, nullptr, m_last); }
245
251 void LinkFront(DLEntryType *entry) { Link(entry, m_last, nullptr); }
252
256 void LinkFront(DLEntryType &entry) { Link(&entry, m_last, nullptr); }
257
264 {
265 DLEntryType *ret = m_last;
266 Unlink(ret);
267 return ret;
268 }
269
276 {
277 DLEntryType *ret = m_first;
278 Unlink(ret);
279 return ret;
280 }
281
287 void Unlink(DLEntryType *entry)
288 {
289 STK_ASSERT(entry != nullptr);
290 STK_ASSERT(entry->IsLinked());
291 STK_ASSERT(entry->GetHead() == this);
292
293 if (m_first == entry)
294 m_first = entry->GetNext();
295
296 if (m_last == entry)
297 m_last = entry->GetPrev();
298
299 entry->Unlink();
300 --m_count;
301
302 UpdateEnds();
303 }
304
312 {
313 STK_ASSERT(&to != this);
314
315 while (!this->IsEmpty())
316 {
317 to.LinkBack(this->PopFront());
318 }
319 }
320
330 void Link(DLEntryType *entry, DLEntryType *next = nullptr, DLEntryType *prev = nullptr)
331 {
332 STK_ASSERT(entry != nullptr);
333 STK_ASSERT(!entry->IsLinked());
334
335 if (prev == nullptr)
336 next = m_first;
337
338 ++m_count;
339 entry->Link(this, next, prev);
340
341 if ((m_first == nullptr) || (m_first == entry->GetNext()))
342 m_first = entry;
343
344 if ((m_last == nullptr) || (m_last == entry->GetPrev()))
345 m_last = entry;
346
347 if (_ClosedLoop)
348 UpdateEnds();
349 }
350
351private:
363 {
364 if (IsEmpty())
365 {
366 m_first = nullptr;
367 m_last = nullptr;
368 }
369 else
370 if (_ClosedLoop)
371 {
372 m_first->m_prev = m_last;
373 m_last->m_next = m_first;
374 }
375 }
376
377 size_t m_count;
380};
381
382} // namespace util
383} // namespace stk
384
385
386#endif /* STK_LINKED_LIST_H_ */
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
Definition stk_defs.h:330
Namespace of STK package.
Internal utility namespace containing data structure helpers (linked lists, etc.) used by the kernel ...
Intrusive doubly-linked list container. Manages a collection of DListEntry nodes embedded in host obj...
size_t GetSize() const
Get the number of entries currently in the list.
void RelinkTo(DListHead &to)
Move all entries from this list to the back of to, preserving order.
DLEntryType * m_first
Pointer to the first (front) entry, or NULL when empty.
size_t m_count
Number of entries currently in the list.
void Link(DLEntryType *entry, DLEntryType *next=nullptr, DLEntryType *prev=nullptr)
Insert entry into the list between prev and next.
DListEntry< T, _ClosedLoop > DLEntryType
Convenience alias for the node type stored in this list.
void Clear()
Remove and unlink all entries. After this call the list is empty.
void LinkFront(DLEntryType &entry)
Prepend entry to the front of the list (reference overload).
DLEntryType * PopBack()
Remove and return the last entry.
void LinkFront(DLEntryType *entry)
Prepend entry to the front of the list (pointer overload).
DLEntryType * GetFirst() const
Get the first (front) entry without removing it.
bool IsEmpty() const
Check whether the list contains no entries.
void UpdateEnds()
Repair the boundary and circular pointers after every structural change.
DListHead()
Construct an empty list head (count = 0, first = last = NULL).
void Unlink(DLEntryType *entry)
Remove entry from this list.
DLEntryType * PopFront()
Remove and return the first entry.
void LinkBack(DLEntryType &entry)
Append entry to the back of the list (reference overload).
DLEntryType * GetLast() const
Get the last (back) entry without removing it.
DLEntryType * m_last
Pointer to the last (back) entry, or NULL when empty.
void LinkBack(DLEntryType *entry)
Append entry to the back of the list (pointer overload).
Intrusive doubly-linked list node. Embed this as a base class in any object (T) that needs to partici...
DLEntryType * m_next
Next entry in the list, or NULL (open list boundary) / first entry (closed loop).
DLEntryType * GetPrev() const
Get the previous entry in the list.
DLHeadType * GetHead() const
Get the list head this entry currently belongs to.
bool IsLinked() const
Check whether this entry is currently a member of any list.
DLEntryType * m_prev
Previous entry in the list, or NULL (open list boundary) / last entry (closed loop).
DListHead< T, _ClosedLoop > DLHeadType
Convenience alias for the corresponding list head type.
DLHeadType * m_head
Owning list head, or NULL when the entry is not linked.
void Link(DLHeadType *head, DLEntryType *next, DLEntryType *prev)
Wire this entry into a list between prev and next.
DLEntryType * GetNext() const
Get the next entry in the list.
DListEntry< T, _ClosedLoop > DLEntryType
Convenience alias for this entry type. Used to avoid repeating the full template spelling.
void Unlink()
Remove this entry from its current list.
DListEntry()
Construct an unlinked entry. All pointers initialised to NULL.
~DListEntry()
Protected non-virtual destructor.