utils-lists 4.0.0
µOS++ C++ intrusive lists utilities
Loading...
Searching...
No Matches
lists.h
Go to the documentation of this file.
1/*
2 * This file is part of the µOS++ distribution.
3 * (https://github.com/micro-os-plus/)
4 * Copyright (c) 2016 Liviu Ionescu. All rights reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software
7 * for any purpose is hereby granted, under the terms of the MIT license.
8 *
9 * If a copy of the license was not distributed with this file, it can
10 * be obtained from https://opensource.org/licenses/MIT/.
11 */
12
13/*
14 * This library implements several double linked lists, used by some
15 * µOS++ components to keep track of internal objects; however it is
16 * generic enough to be useful in other applications too, thus packing
17 * it as a separate library.
18 *
19 * The main differentiator from `std::list` is that the implementation
20 * does not require dynamic memory allocation for the list links,
21 * hence it does not need an allocator.
22 *
23 * Instead, it uses intrusive lists, which store the links inside the
24 * list elements.
25 *
26 * Another specific feature is statically initialised lists.
27 *
28 * These are lists created in the global scope which do not change the
29 * content of any of their members in the constructors; instead,
30 * they are fully initialized by setting the entire content to zero
31 * during startup (via BSS init).
32 *
33 * This allows other static objects to auto-register themselves to
34 * static registrar objects. This requires the registrar to be
35 * initialised before the clients need to register; since the order
36 * of static constructors is not defined, the only solution that
37 * guarantees this is to initialize the registrar during startup
38 * (via BSS init) before the static constructors.
39 */
40
41#ifndef MICRO_OS_PLUS_UTILS_LISTS_H_
42#define MICRO_OS_PLUS_UTILS_LISTS_H_
43
44// ----------------------------------------------------------------------------
45
46#ifdef __cplusplus
47
48// ----------------------------------------------------------------------------
49
50#if defined(MICRO_OS_PLUS_INCLUDE_CONFIG_H)
51#include <micro-os-plus/config.h>
52#endif // MICRO_OS_PLUS_INCLUDE_CONFIG_H
53
54#include <cstdint>
55#include <cstddef>
56#include <cassert>
57#include <iterator>
58
59// ----------------------------------------------------------------------------
60
61#if defined(__GNUC__)
62#pragma GCC diagnostic push
63
64#pragma GCC diagnostic ignored "-Waggregate-return"
65#if defined(__clang__)
66#pragma clang diagnostic ignored "-Wc++98-compat"
67#endif
68#endif
69
74{
75 // ==========================================================================
76
93 {
94 public:
98 constexpr double_list_links_base ();
99
104 // The rule of five.
108 operator= (const double_list_links_base&)
109 = delete;
111 operator= (double_list_links_base&&)
112 = delete;
113
121 constexpr ~double_list_links_base ();
122
130 bool
131 uninitialized (void) const;
132
140 constexpr void
141 initialize (void);
142
150 void
151 initialize_once (void);
152
160 void
162
170 void
172
178 void
179 unlink (void);
180
186 bool
187 linked (void) const;
188
193 constexpr double_list_links_base*
194 next (void) const;
195
200 constexpr double_list_links_base*
201 previous (void) const;
202
203 protected:
208
213 };
214
215 // ==========================================================================
216
233 {
234 public:
239 using is_statically_allocated = std::false_type;
240
244 constexpr double_list_links ();
245
250 // The rule of five.
251 double_list_links (const double_list_links&) = delete;
254 operator= (const double_list_links&)
255 = delete;
257 operator= (double_list_links&&)
258 = delete;
259
267 constexpr ~double_list_links ();
268 };
269
270 // ==========================================================================
271
307 {
308 public:
312 using is_statically_allocated = std::true_type;
313
318 constexpr static_double_list_links ();
319
324 // The rule of five.
328 operator= (const static_double_list_links&)
329 = delete;
331 operator= (static_double_list_links&&)
332 = delete;
333
341 constexpr ~static_double_list_links ();
342
350 void
351 nullify (void);
352 };
353
354 // ==========================================================================
355
371 template <class T, class N = T, class U = T>
373 {
374 public:
378 using value_type = U;
379
384
389
394
398 using difference_type = ptrdiff_t;
399
403 using iterator_category = std::forward_iterator_tag;
404
405 // ------------------------------------------------------------------------
406 constexpr double_list_iterator ();
407
408 constexpr explicit double_list_iterator (iterator_pointer const node);
409
410 constexpr explicit double_list_iterator (reference element);
411
412 // DO NOT delete the copy constructors, since the default one are
413 // used.
414
415 constexpr pointer
416 operator->() const;
417
418 constexpr reference
419 operator* () const;
420
421 constexpr double_list_iterator&
422 operator++ ();
423
424 constexpr double_list_iterator
425 operator++ (int);
426
427 constexpr double_list_iterator&
428 operator-- ();
429
430 constexpr double_list_iterator
431 operator-- (int);
432
433 constexpr bool
434 operator== (const double_list_iterator& other) const;
435
436 constexpr bool
437 operator!= (const double_list_iterator& other) const;
438
439 constexpr pointer
440 get_pointer () const;
441
442 constexpr iterator_pointer
443 get_iterator_pointer () const;
444
445 protected:
450 };
451
452 // ==========================================================================
453
485 template <class T, class L = double_list_links>
487 {
488 public:
489 static_assert (std::is_base_of<double_list_links_base, L>::value == true,
490 "L must be derived from double_list_links_base!");
491 static_assert (std::is_base_of<double_list_links_base, T>::value == true,
492 "T must be derived from double_list_links_base!");
493
498 using links_type = L;
499
503 using value_type = T;
504
509
514
519
524
529 typename links_type::is_statically_allocated;
530
534 double_list ();
535
540 // The rule of five.
541 double_list (const double_list&) = delete;
542 double_list (double_list&&) = delete;
544 operator= (const double_list&)
545 = delete;
547 operator= (double_list&&)
548 = delete;
549
557 constexpr ~double_list ();
558
559 public:
568 bool
569 uninitialized (void) const;
570
578 void
579 initialize_once (void);
580
588 bool
589 empty (void) const;
590
598 void
599 clear (void);
600
607 constexpr pointer
608 head (void) const;
609
616 constexpr pointer
617 tail (void) const;
618
622 void
623 link_tail (reference node);
624
628 void
629 link_head (reference node);
630
631 // ------------------------------------------------------------------------
632
638 begin () const;
639
645 end () const;
646
647 // Required in derived class iterator end(), where direct
648 // access to member fails.
653 constexpr const links_type*
655 {
656 return &links_;
657 }
658
659 // ------------------------------------------------------------------------
660
661 protected:
674 };
675
676 // ==========================================================================
677
694 template <class T, class N, N T::*MP, class U = T>
696 {
697 public:
701 using value_type = U;
702
707
712
717
721 using difference_type = ptrdiff_t;
722
726 using iterator_category = std::forward_iterator_tag;
727
728 // ------------------------------------------------------------------------
729 constexpr intrusive_list_iterator ();
730
731 constexpr explicit intrusive_list_iterator (iterator_pointer const node);
732
733 constexpr explicit intrusive_list_iterator (reference element);
734
735 // DO NOT delete the copy constructors, since the default one are
736 // used.
737
738 pointer
739 operator->() const;
740
742 operator* () const;
743
745 operator++ ();
746
748 operator++ (int);
749
751 operator-- ();
752
754 operator-- (int);
755
756 bool
757 operator== (const intrusive_list_iterator& other) const;
758
759 bool
760 operator!= (const intrusive_list_iterator& other) const;
761
766 pointer
767 get_pointer (void) const;
768
770 get_iterator_pointer () const;
771
772 protected:
777 };
778
779 // ==========================================================================
780
781#if defined(__clang__)
782#pragma clang diagnostic push
783#pragma clang diagnostic ignored "-Wdocumentation"
784#endif
819#if defined(__clang__)
820#pragma clang diagnostic pop
821#endif
822
823 template <class T, class N, N T::*MP, class L = double_list_links,
824 class U = T>
825 class intrusive_list : public double_list<N, L>
826 {
827 public:
828 static_assert (std::is_base_of<double_list_links_base, L>::value == true,
829 "L must be derived from double_list_links_base!");
830 static_assert (std::is_base_of<double_list_links_base, N>::value == true,
831 "N must be derived from double_list_links_base!");
832
837 using links_type = L;
838
842 using value_type = U;
843
848
853
858
863 typename links_type::is_statically_allocated;
864
869
873 using difference_type = ptrdiff_t;
874
878 constexpr intrusive_list ();
879
884 // The rule of five.
885 intrusive_list (const intrusive_list&) = delete;
886 intrusive_list (intrusive_list&&) = delete;
888 operator= (const intrusive_list&)
889 = delete;
891 operator= (intrusive_list&&)
892 = delete;
893
901 constexpr ~intrusive_list ();
902
903 public:
911 void
912 initialize_once (void);
913
921 constexpr bool
922 empty (void) const;
923
930 void
931 link_tail (reference node);
932
939 void
940 link_head (reference node);
941
946 pointer
947 unlink_tail (void);
948
953 pointer
954 unlink_head (void);
955
956 // ------------------------------------------------------------------------
957
963 begin () const;
964
970 end () const;
971
972 // ------------------------------------------------------------------------
973 protected:
978 pointer
979 get_pointer (iterator_pointer node) const;
980 };
981
982 // --------------------------------------------------------------------------
983} // namespace micro_os_plus::utils
984
985#if defined(__GNUC__)
986#pragma GCC diagnostic pop
987#endif
988
989// ----------------------------------------------------------------------------
990
991#endif // __cplusplus
992
993// ===== Inline & template implementations ====================================
994
995// All other inlines.
996#include "inlines.h"
997
998// ----------------------------------------------------------------------------
999
1000#endif // MICRO_OS_PLUS_UTILS_LISTS_H_
1001
1002// ----------------------------------------------------------------------------
A class template for a double linked list forward iterator.
Definition lists.h:373
constexpr double_list_iterator(reference element)
ptrdiff_t difference_type
Type of pointer difference.
Definition lists.h:398
constexpr bool operator==(const double_list_iterator &other) const
Definition inlines.h:237
constexpr pointer get_pointer() const
constexpr pointer operator->() const
Definition inlines.h:189
value_type * pointer
Type of pointer to object "pointed to" by the iterator.
Definition lists.h:383
constexpr double_list_iterator & operator--()
Definition inlines.h:220
constexpr bool operator!=(const double_list_iterator &other) const
Definition inlines.h:245
std::forward_iterator_tag iterator_category
Category of iterator.
Definition lists.h:403
constexpr iterator_pointer get_iterator_pointer() const
Definition inlines.h:253
constexpr double_list_iterator & operator++()
Definition inlines.h:203
constexpr reference operator*() const
Definition inlines.h:196
value_type & reference
Type of reference to object "pointed to" by the iterator.
Definition lists.h:388
iterator_pointer node_
Pointer to the node.
Definition lists.h:449
U value_type
Type of value "pointed to" by the iterator.
Definition lists.h:378
N * iterator_pointer
Type of reference to the iterator internal pointer.
Definition lists.h:393
A class template for a double linked list of nodes.
Definition lists.h:487
void link_head(reference node)
Add a node to the head of the list.
Definition inlines.h:408
links_type links_
The list top node used to point to head and tail nodes.
Definition lists.h:673
L links_type
Type of the links node object where the pointers to the list head and tail are stored.
Definition lists.h:498
value_type * iterator_pointer
Type of reference to the iterator internal pointer.
Definition lists.h:523
constexpr pointer tail(void) const
Get the list tail.
Definition inlines.h:388
void initialize_once(void)
Initialize the list only at first run.
Definition inlines.h:349
value_type * pointer
Type of pointer to object "pointed to" by the iterator.
Definition lists.h:508
constexpr const links_type * links_pointer() const
Get the address of the node storing the list links.
Definition lists.h:654
constexpr ~double_list()
Destruct the list.
Definition inlines.h:296
value_type & reference
Type of reference to object "pointed to" by the iterator.
Definition lists.h:513
double_list()
Construct a double linked list.
Definition inlines.h:268
void clear(void)
Clear the list.
Definition inlines.h:371
constexpr pointer head(void) const
Get the list head.
Definition inlines.h:381
iterator end() const
Iterator end.
Definition inlines.h:433
T value_type
Type of value "pointed to" by the iterator.
Definition lists.h:503
iterator begin() const
Iterator begin.
Definition inlines.h:421
bool empty(void) const
Check if the list is empty.
Definition inlines.h:359
void link_tail(reference node)
Add a node to the tail of the list.
Definition inlines.h:395
bool uninitialized(void) const
Check if the list is uninitialised (only statically allocated can be).
Definition inlines.h:322
typename links_type::is_statically_allocated is_statically_allocated
Type indicating that the links node is statically allocated.
Definition lists.h:528
A class template for an intrusive list iterator.
Definition lists.h:696
value_type * pointer
Type of pointer to object "pointed to" by the iterator.
Definition lists.h:706
std::forward_iterator_tag iterator_category
Category of iterator.
Definition lists.h:726
pointer get_pointer(void) const
Get the object node from the intrusive node.
Definition inlines.h:532
intrusive_list_iterator & operator++()
Definition inlines.h:482
N * iterator_pointer
Type of reference to the iterator internal pointer.
Definition lists.h:716
bool operator==(const intrusive_list_iterator &other) const
Definition inlines.h:516
iterator_pointer get_iterator_pointer() const
Definition inlines.h:550
value_type & reference
Type of reference to object "pointed to" by the iterator.
Definition lists.h:711
bool operator!=(const intrusive_list_iterator &other) const
Definition inlines.h:524
U value_type
Type of value "pointed to" by the iterator.
Definition lists.h:701
intrusive_list_iterator & operator--()
Definition inlines.h:499
ptrdiff_t difference_type
Type of pointer difference.
Definition lists.h:721
iterator_pointer node_
Pointer to intrusive node.
Definition lists.h:776
A class template for a list of nodes which store the links inside themselves as intrusive nodes.
Definition lists.h:826
constexpr intrusive_list()
Construct an intrusive double linked list.
Definition inlines.h:558
L links_type
Type of the list links node object where the pointers to the list head and tail are stored.
Definition lists.h:837
constexpr bool empty(void) const
Check if the list is empty.
Definition inlines.h:589
void link_tail(reference node)
Add a node to the tail of the list.
Definition inlines.h:596
N * iterator_pointer
Type of reference to the iterator internal pointer.
Definition lists.h:868
iterator begin() const
Iterator begin.
Definition inlines.h:635
typename links_type::is_statically_allocated is_statically_allocated
Type of reference to the iterator internal pointer.
Definition lists.h:862
pointer unlink_head(void)
Unlink the first element from the list.
Definition inlines.h:679
void link_head(reference node)
Add a node to the head of the list.
Definition inlines.h:613
constexpr ~intrusive_list()
Destruct the list.
Definition inlines.h:563
void initialize_once(void)
Initialize the list only at first run.
Definition inlines.h:582
U value_type
Type of value "pointed to" by the iterator.
Definition lists.h:842
iterator end() const
Iterator begin.
Definition inlines.h:645
value_type & reference
Type of reference to object "pointed to" by the iterator.
Definition lists.h:852
ptrdiff_t difference_type
Type of pointer difference.
Definition lists.h:873
value_type * pointer
Type of pointer to object "pointed to" by the iterator.
Definition lists.h:847
pointer unlink_tail(void)
Unlink the last element from the list.
Definition inlines.h:693
pointer get_pointer(iterator_pointer node) const
Get the address of the node.
Definition inlines.h:661
µOS++ utility definitions.
Definition inlines.h:34