utils-lists 4.0.2
The µOS++ Intrusive Lists
Loading...
Searching...
No Matches
lists.h
Go to the documentation of this file.
1/*
2 * This file is part of the µOS++ project (https://micro-os-plus.github.com/).
3 * Copyright (c) 2016 Liviu Ionescu. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software
6 * for any purpose is hereby granted, under the terms of the MIT license.
7 *
8 * If a copy of the license was not distributed with this file, it can
9 * be obtained from https://opensource.org/licenses/mit.
10 */
11
12/*
13 * This library implements several doubly linked lists, used by some
14 * µOS++ components to keep track of internal objects; however it is
15 * generic enough to be useful in other applications too, thus packing
16 * it as a separate library.
17 *
18 * The main differentiator from `std::list` is that the implementation
19 * does not require dynamic memory allocation for the list links,
20 * hence it does not need an allocator.
21 *
22 * Instead, it uses intrusive lists, which store the links inside the
23 * list elements.
24 *
25 * Another specific feature is statically initialised lists.
26 *
27 * These are lists created in the global scope which do not change the
28 * content of any of their members in the constructors; instead,
29 * they are fully initialized by setting the entire content to zero
30 * during startup (via BSS init).
31 *
32 * This allows other static objects to auto-register themselves to
33 * static registrar objects. This requires the registrar to be
34 * initialised before the clients need to register; since the order
35 * of static constructors is not defined, the only solution that
36 * guarantees this is to initialize the registrar during startup
37 * (via BSS init) before the static constructors.
38 */
39
40#ifndef MICRO_OS_PLUS_UTILS_LISTS_H_
41#define MICRO_OS_PLUS_UTILS_LISTS_H_
42
43// ----------------------------------------------------------------------------
44
45#ifdef __cplusplus
46
47// ----------------------------------------------------------------------------
48
49#if defined(MICRO_OS_PLUS_INCLUDE_CONFIG_H)
50#include <micro-os-plus/config.h>
51#endif // MICRO_OS_PLUS_INCLUDE_CONFIG_H
52
53#include <cstdint>
54#include <cstddef>
55#include <cassert>
56#include <iterator>
57
58// ----------------------------------------------------------------------------
59
60#if defined(__GNUC__)
61#pragma GCC diagnostic push
62
63#pragma GCC diagnostic ignored "-Waggregate-return"
64#if defined(__clang__)
65#pragma clang diagnostic ignored "-Wc++98-compat"
66#endif
67#endif
68
73{
74 // ==========================================================================
75
91 {
92 public:
96 constexpr double_list_links_base ();
97
101
102 // The rule of five.
106 operator= (const double_list_links_base&)
107 = delete;
109 operator= (double_list_links_base&&)
110 = delete;
111
115
119 constexpr ~double_list_links_base ();
120
128 bool
129 uninitialized (void) const;
130
138 constexpr void
139 initialize (void);
140
148 void
149 initialize_once (void);
150
158 void
160
168 void
170
176 void
177 unlink (void);
178
184 bool
185 linked (void) const;
186
191 constexpr double_list_links_base*
192 next (void) const;
193
198 constexpr double_list_links_base*
199 previous (void) const;
200
201 protected:
206
211 };
212
213 // ==========================================================================
214
230 {
231 public:
236 using is_statically_allocated = std::false_type;
237
241 constexpr double_list_links ();
242
246
247 // The rule of five.
248 double_list_links (const double_list_links&) = delete;
251 operator= (const double_list_links&)
252 = delete;
254 operator= (double_list_links&&)
255 = delete;
256
260
264 constexpr ~double_list_links ();
265 };
266
267 // ==========================================================================
268
303 {
304 public:
308 using is_statically_allocated = std::true_type;
309
314 constexpr static_double_list_links ();
315
319
320 // The rule of five.
324 operator= (const static_double_list_links&)
325 = delete;
327 operator= (static_double_list_links&&)
328 = delete;
329
333
337 constexpr ~static_double_list_links ();
338
346 void
347 nullify (void);
348 };
349
350 // ==========================================================================
351
366 template <class T, class N = T, class U = T>
368 {
369 public:
373 using value_type = U;
374
379
384
389
393 using difference_type = ptrdiff_t;
394
398 using iterator_category = std::forward_iterator_tag;
399
400 // ------------------------------------------------------------------------
402
403 constexpr explicit double_list_iterator (iterator_pointer const node);
404
405 constexpr explicit double_list_iterator (reference element);
406
407 // DO NOT delete the copy constructors, since the default ones are
408 // used.
409
410 constexpr pointer
411 operator->() const;
412
413 constexpr reference
414 operator* () const;
415
416 constexpr double_list_iterator&
418
419 constexpr double_list_iterator
421
422 constexpr double_list_iterator&
424
425 constexpr double_list_iterator
427
428 constexpr bool
430
431 constexpr bool
433
434 constexpr pointer
435 get_pointer () const;
436
437 constexpr iterator_pointer
439
440 protected:
445 };
446
447 // ==========================================================================
448
479 template <class T, class L = double_list_links>
481 {
482 public:
483 static_assert (std::is_base_of<double_list_links_base, L>::value == true,
484 "L must be derived from double_list_links_base!");
485 static_assert (std::is_base_of<double_list_links_base, T>::value == true,
486 "T must be derived from double_list_links_base!");
487
492 using links_type = L;
493
497 using value_type = T;
498
503
508
513
518
523 typename links_type::is_statically_allocated;
524
528 double_list ();
529
533
534 // The rule of five.
535 double_list (const double_list&) = delete;
536 double_list (double_list&&) = delete;
538 operator= (const double_list&)
539 = delete;
541 operator= (double_list&&)
542 = delete;
543
547
551 constexpr ~double_list ();
552
553 public:
562 bool
563 uninitialized (void) const;
564
572 void
573 initialize_once (void);
574
582 bool
583 empty (void) const;
584
592 void
593 clear (void);
594
601 constexpr pointer
602 head (void) const;
603
610 constexpr pointer
611 tail (void) const;
612
616 void
617 link_tail (reference node);
618
622 void
623 link_head (reference node);
624
625 // ------------------------------------------------------------------------
626
632 begin () const;
633
639 end () const;
640
641 // Required in derived class iterator end(), where direct
642 // access to member fails.
647 constexpr const links_type*
649 {
650 return &links_;
651 }
652
653 // ------------------------------------------------------------------------
654
655 protected:
668 };
669
670 // ==========================================================================
671
687 template <class T, class N, N T::*MP, class U = T>
689 {
690 public:
694 using value_type = U;
695
700
705
710
714 using difference_type = ptrdiff_t;
715
719 using iterator_category = std::forward_iterator_tag;
720
721 // ------------------------------------------------------------------------
723
724 constexpr explicit intrusive_list_iterator (iterator_pointer const node);
725
726 constexpr explicit intrusive_list_iterator (reference element);
727
728 // DO NOT delete the copy constructors, since the default ones are
729 // used.
730
731 pointer
732 operator->() const;
733
735 operator* () const;
736
739
742
745
748
749 bool
751
752 bool
754
759 pointer
760 get_pointer (void) const;
761
764
765 protected:
770 };
771
772 // ==========================================================================
773
774#if defined(__clang__)
775#pragma clang diagnostic push
776#pragma clang diagnostic ignored "-Wdocumentation"
777#endif
811#if defined(__clang__)
812#pragma clang diagnostic pop
813#endif
814
815 template <class T, class N, N T::*MP, class L = double_list_links,
816 class U = T>
817 class intrusive_list : public double_list<N, L>
818 {
819 public:
820 static_assert (std::is_base_of<double_list_links_base, L>::value == true,
821 "L must be derived from double_list_links_base!");
822 static_assert (std::is_base_of<double_list_links_base, N>::value == true,
823 "N must be derived from double_list_links_base!");
824
829 using links_type = L;
830
834 using value_type = U;
835
840
845
850
855 typename links_type::is_statically_allocated;
856
861
865 using difference_type = ptrdiff_t;
866
870 constexpr intrusive_list ();
871
875
876 // The rule of five.
877 intrusive_list (const intrusive_list&) = delete;
878 intrusive_list (intrusive_list&&) = delete;
880 operator= (const intrusive_list&)
881 = delete;
883 operator= (intrusive_list&&)
884 = delete;
885
889
893 constexpr ~intrusive_list ();
894
895 public:
903 void
904 initialize_once (void);
905
913 constexpr bool
914 empty (void) const;
915
922 void
923 link_tail (reference node);
924
931 void
932 link_head (reference node);
933
938 pointer
939 unlink_tail (void);
940
945 pointer
946 unlink_head (void);
947
948 // ------------------------------------------------------------------------
949
955 begin () const;
956
962 end () const;
963
964 // ------------------------------------------------------------------------
965 protected:
970 pointer
971 get_pointer (iterator_pointer node) const;
972 };
973
974 // --------------------------------------------------------------------------
975} // namespace micro_os_plus::utils
976
977#if defined(__GNUC__)
978#pragma GCC diagnostic pop
979#endif
980
981// ----------------------------------------------------------------------------
982
983#endif // __cplusplus
984
985// ===== Inline & template implementations ====================================
986
987// All other inlines.
988#include "inlines.h"
989
990// ----------------------------------------------------------------------------
991
992#endif // MICRO_OS_PLUS_UTILS_LISTS_H_
993
994// ----------------------------------------------------------------------------
A class template for a doubly linked list forward iterator.
Definition lists.h:368
constexpr double_list_iterator(reference element)
ptrdiff_t difference_type
Type of pointer difference.
Definition lists.h:393
constexpr bool operator==(const double_list_iterator &other) const
Definition inlines.h:236
constexpr pointer get_pointer() const
constexpr pointer operator->() const
Definition inlines.h:188
value_type * pointer
Type of pointer to object "pointed to" by the iterator.
Definition lists.h:378
constexpr double_list_iterator & operator--()
Definition inlines.h:219
constexpr bool operator!=(const double_list_iterator &other) const
Definition inlines.h:244
std::forward_iterator_tag iterator_category
Category of iterator.
Definition lists.h:398
constexpr iterator_pointer get_iterator_pointer() const
Definition inlines.h:252
constexpr double_list_iterator & operator++()
Definition inlines.h:202
constexpr reference operator*() const
Definition inlines.h:195
constexpr double_list_iterator(iterator_pointer const node)
Definition inlines.h:169
value_type & reference
Type of reference to object "pointed to" by the iterator.
Definition lists.h:383
U value_type
Type of value "pointed to" by the iterator.
Definition lists.h:373
N * iterator_pointer
Type of reference to the iterator internal pointer.
Definition lists.h:388
void link_head(reference node)
Add a node to the head of the list.
Definition inlines.h:407
links_type links_
The list top node used to point to head and tail nodes.
Definition lists.h:667
L links_type
Type of the links node object where the pointers to the list head and tail are stored.
Definition lists.h:492
value_type * iterator_pointer
Type of reference to the iterator internal pointer.
Definition lists.h:517
constexpr pointer tail(void) const
Get the list tail.
Definition inlines.h:387
void initialize_once(void)
Initialize the list only at first run.
Definition inlines.h:348
value_type * pointer
Type of pointer to object "pointed to" by the iterator.
Definition lists.h:502
constexpr const links_type * links_pointer() const
Get the address of the node storing the list links.
Definition lists.h:648
constexpr ~double_list()
Destruct the list.
Definition inlines.h:295
value_type & reference
Type of reference to object "pointed to" by the iterator.
Definition lists.h:507
double_list()
Construct a doubly linked list.
Definition inlines.h:267
void clear(void)
Clear the list.
Definition inlines.h:370
constexpr pointer head(void) const
Get the list head.
Definition inlines.h:380
iterator end() const
Iterator end.
Definition inlines.h:432
T value_type
Type of value "pointed to" by the iterator.
Definition lists.h:497
iterator begin() const
Iterator begin.
Definition inlines.h:420
double_list_iterator< value_type > iterator
Type of iterator over the values.
Definition lists.h:512
bool empty(void) const
Check if the list is empty.
Definition inlines.h:358
void link_tail(reference node)
Add a node to the tail of the list.
Definition inlines.h:394
bool uninitialized(void) const
Check if the list is uninitialised (only statically allocated can be).
Definition inlines.h:321
typename links_type::is_statically_allocated is_statically_allocated
Type indicating that the links node is statically allocated.
Definition lists.h:522
A class template for an intrusive list iterator.
Definition lists.h:689
value_type * pointer
Type of pointer to object "pointed to" by the iterator.
Definition lists.h:699
std::forward_iterator_tag iterator_category
Category of iterator.
Definition lists.h:719
pointer get_pointer(void) const
Get the object node from the intrusive node.
Definition inlines.h:531
intrusive_list_iterator & operator++()
Definition inlines.h:481
N * iterator_pointer
Type of reference to the iterator internal pointer.
Definition lists.h:709
bool operator==(const intrusive_list_iterator &other) const
Definition inlines.h:515
iterator_pointer get_iterator_pointer() const
Definition inlines.h:549
value_type & reference
Type of reference to object "pointed to" by the iterator.
Definition lists.h:704
bool operator!=(const intrusive_list_iterator &other) const
Definition inlines.h:523
U value_type
Type of value "pointed to" by the iterator.
Definition lists.h:694
constexpr intrusive_list_iterator(iterator_pointer const node)
Definition inlines.h:450
constexpr intrusive_list_iterator(reference element)
Definition inlines.h:457
intrusive_list_iterator & operator--()
Definition inlines.h:498
ptrdiff_t difference_type
Type of pointer difference.
Definition lists.h:714
constexpr intrusive_list()
Construct an intrusive doubly linked list.
Definition inlines.h:557
L links_type
Type of the list links node object where the pointers to the list head and tail are stored.
Definition lists.h:829
constexpr bool empty(void) const
Check if the list is empty.
Definition inlines.h:588
void link_tail(reference node)
Add a node to the tail of the list.
Definition inlines.h:595
N * iterator_pointer
Type of reference to the iterator internal pointer.
Definition lists.h:860
iterator begin() const
Iterator begin.
Definition inlines.h:634
typename links_type::is_statically_allocated is_statically_allocated
Type of reference to the iterator internal pointer.
Definition lists.h:854
pointer unlink_head(void)
Unlink the first element from the list.
Definition inlines.h:678
void link_head(reference node)
Add a node to the head of the list.
Definition inlines.h:612
constexpr ~intrusive_list()
Destruct the list.
Definition inlines.h:562
intrusive_list_iterator< T, N, MP, U > iterator
Type of iterator over the values.
Definition lists.h:849
void initialize_once(void)
Initialize the list only at first run.
Definition inlines.h:581
U value_type
Type of value "pointed to" by the iterator.
Definition lists.h:834
iterator end() const
Iterator begin.
Definition inlines.h:644
value_type & reference
Type of reference to object "pointed to" by the iterator.
Definition lists.h:844
ptrdiff_t difference_type
Type of pointer difference.
Definition lists.h:865
value_type * pointer
Type of pointer to object "pointed to" by the iterator.
Definition lists.h:839
pointer unlink_tail(void)
Unlink the last element from the list.
Definition inlines.h:692
pointer get_pointer(iterator_pointer node) const
Get the address of the node.
Definition inlines.h:660
µOS++ utility definitions.
Definition inlines.h:33