µOS++ IIIe Reference 7.0.0
The third edition of µOS++, a POSIX inspired open source framework, written in C++
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.io/).
3 * Copyright (c) 2016-2025 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#ifndef CMSIS_PLUS_UTILS_LISTS_H_
13#define CMSIS_PLUS_UTILS_LISTS_H_
14
15// ----------------------------------------------------------------------------
16
17#ifdef __cplusplus
18
19// ----------------------------------------------------------------------------
20
21#include <cstdint>
22#include <cstddef>
23#include <cassert>
24#include <iterator>
25
26// ----------------------------------------------------------------------------
27
28#pragma GCC diagnostic push
29#if defined(__clang__)
30#pragma clang diagnostic ignored "-Wc++98-compat"
31#endif
32
33// ----------------------------------------------------------------------------
34
35namespace os
36{
37 namespace utils
38 {
39 // ========================================================================
40
48 {
49 public:
59
67 operator= (const static_double_list_links&)
68 = delete;
70 operator= (static_double_list_links&&)
71 = delete;
72
81
96 void
97 unlink (void);
98
104 bool
105 unlinked (void);
106
108 next (void) const;
109
111 prev (void) const;
112
113 void
115
116 void
118
123 protected:
133
138
142 };
143
144 // ========================================================================
145
153 {
154 public:
164
169 double_list_links (const double_list_links&) = delete;
172 operator= (const double_list_links&)
173 = delete;
175 operator= (double_list_links&&)
176 = delete;
177
186
190 };
191
192 // ========================================================================
193
207 template <typename T, typename N, T* N::* MP, typename U = T>
209 {
210 public:
219 using value_type = U;
220
224 using pointer = U*;
225
229 using reference = U&;
230
235
239 using difference_type = ptrdiff_t;
240
244 using iterator_category = std::forward_iterator_tag;
245
250 // ----------------------------------------------------------------------
256 constexpr double_list_iterator ();
257
258 constexpr explicit double_list_iterator (iterator_pointer const node);
259
260 constexpr explicit double_list_iterator (reference element);
261
271 pointer
272 operator->() const;
273
275 operator* () const;
276
278 operator++ ();
279
281 operator++ (int);
282
284 operator-- ();
285
287 operator-- (int);
288
289 bool
290 operator== (const double_list_iterator& other) const;
291
292 bool
293 operator!= (const double_list_iterator& other) const;
294
308 pointer
309 get_pointer (void) const;
310
312 get_iterator_pointer () const;
313
318 protected:
328
332 };
333
334 // ========================================================================
335
342 {
343 public:
353
358 static_double_list (const static_double_list&) = delete;
361 operator= (const static_double_list&)
362 = delete;
364 operator= (static_double_list&&)
365 = delete;
366
375
380 public:
393 bool
394 uninitialized (void) const;
395
403 void
404 clear (void);
405
413 bool
414 empty (void) const;
415
416 // TODO add iterator begin(), end()
417
425 head (void) const;
426
434 tail (void) const;
435
440 protected:
453 void
456
461 protected:
474
478 };
479
480 // ========================================================================
481
488 {
489 public:
498 double_list ();
499
504 double_list (const double_list&) = delete;
505 double_list (double_list&&) = delete;
507 operator= (const double_list&)
508 = delete;
510 operator= (double_list&&)
511 = delete;
512
520 ~double_list ();
521
525 };
526
527 // ========================================================================
528
542 template <typename T, typename N, N T::* MP, typename U = T>
544 {
545 public:
554 using value_type = U;
555
559 using pointer = U*;
560
564 using reference = U&;
565
570
574 using difference_type = ptrdiff_t;
575
579 using iterator_category = std::forward_iterator_tag;
580
585 // ----------------------------------------------------------------------
591 constexpr intrusive_list_iterator ();
592
593 constexpr explicit intrusive_list_iterator (iterator_pointer const node);
594
595 constexpr explicit intrusive_list_iterator (reference element);
596
606 pointer
607 operator->() const;
608
610 operator* () const;
611
613 operator++ ();
614
616 operator++ (int);
617
619 operator-- ();
620
622 operator-- (int);
623
624 bool
625 operator== (const intrusive_list_iterator& other) const;
626
627 bool
628 operator!= (const intrusive_list_iterator& other) const;
629
643 pointer
644 get_pointer (void) const;
645
647 get_iterator_pointer () const;
648
653 protected:
663
667 };
668
669 // ========================================================================
670
688 template <typename T, typename N, N T::* MP, typename U = T>
690 {
691 public:
692 using value_type = U;
693 using pointer = U*;
694 using reference = U&;
695 using difference_type = ptrdiff_t;
696
698
703
713
718 intrusive_list (bool clr);
719
724 intrusive_list (const intrusive_list&) = delete;
725 intrusive_list (intrusive_list&&) = delete;
727 operator= (const intrusive_list&)
728 = delete;
730 operator= (intrusive_list&&)
731 = delete;
732
741
746 protected:
747 pointer
748 get_pointer (iterator_pointer node) const;
749
750 public:
762 void
763 link (reference node);
764
770 begin ();
771
777 end () const;
778
783 pointer
784 unlink_head (void);
785
790 pointer
791 unlink_tail (void);
792
796 };
797
798 // ------------------------------------------------------------------------
799 } /* namespace utils */
800} /* namespace os */
801
802// ----------------------------------------------------------------------------
803
804namespace os
805{
806 namespace utils
807 {
808 // ========================================================================
809
810 // Code analysis may trigger:
811 // "Member 'prev' was not initialized in constructor"
812 // "Member 'next' was not initialized in constructor"
813
815 {
816 }
817
819 {
820 // Revert the content to a state similar to the statically initialised
821 // state (BSS zero).
822 // Unfortunately GCC removes this code as part of
823 // _dead store elimination_.
824 // next_ = nullptr;
825 // prev_ = nullptr;
826 }
827
828 inline bool
830 {
831 return (next_ == nullptr);
832 }
833
836 {
837 return next_;
838 }
839
842 {
843 return prev_;
844 }
845
846 inline void
848 {
849 next_ = n;
850 }
851
852 inline void
854 {
855 prev_ = n;
856 }
857
858 // ========================================================================
859
861 {
862 prev_ = nullptr;
863 next_ = nullptr;
864 }
865
867 {
868 }
869
870 // ========================================================================
871 template <typename T, typename N, T* N::* MP, typename U>
873 : node_{}
874 {
875 }
876
877 template <typename T, typename N, T* N::* MP, typename U>
879 iterator_pointer const node)
880 : node_{ node }
881 {
882 }
883
884 template <typename T, typename N, T* N::* MP, typename U>
886 reference element)
887 : node_{ &(element.*MP) }
888 {
889 static_assert (std::is_convertible<U, T>::value == true,
890 "U must be implicitly convertible to T!");
891 }
892
893 template <typename T, typename N, T* N::* MP, typename U>
896 {
897 return get_pointer ();
898 }
899
900 template <typename T, typename N, T* N::* MP, typename U>
903 {
904 return *get_pointer ();
905 }
906
907 template <typename T, typename N, T* N::* MP, typename U>
910 {
911 node_ = static_cast<N*> (node_->next ());
912 return *this;
913 }
914
915 template <typename T, typename N, T* N::* MP, typename U>
918 {
919 const auto tmp = *this;
920 node_ = static_cast<iterator_pointer> (node_->next);
921 return tmp;
922 }
923
924 template <typename T, typename N, T* N::* MP, typename U>
927 {
928 node_ = static_cast<iterator_pointer> (node_->prev);
929 return *this;
930 }
931
932 template <typename T, typename N, T* N::* MP, typename U>
935 {
936 const auto tmp = *this;
937 node_ = static_cast<iterator_pointer> (node_->prev);
938 return tmp;
939 }
940
941 template <typename T, typename N, T* N::* MP, typename U>
942 inline bool
944 const double_list_iterator& other) const
945 {
946 return node_ == other.node_;
947 }
948
949 template <typename T, typename N, T* N::* MP, typename U>
950 inline bool
952 const double_list_iterator& other) const
953 {
954 return node_ != other.node_;
955 }
956
957#if 1
958 template <typename T, typename N, T* N::* MP, typename U>
961 {
962 return (node_->*MP);
963 }
964
965 template <typename T, typename N, T* N::* MP, typename U>
968 {
969 return node_;
970 }
971#endif
972
973 // ========================================================================
974
980 {
981 // By all means, do not add any code here.
982 // The constructor was not `default` to benefit from inline.
983 }
984
990 {
991 }
992
993 inline bool
995 {
996 // If it points to nowhere, it is not yet initialised.
997 return (head_.prev () == nullptr);
998 }
999
1000 inline bool
1002 {
1003 // If it points to itself, it is empty.
1004 return (head_.next () == &head_) || (head_.next () == nullptr);
1005 }
1006
1007 inline volatile static_double_list_links*
1009 {
1010 return static_cast<volatile static_double_list_links*> (head_.next ());
1011 }
1012
1013 inline volatile static_double_list_links*
1015 {
1016 return (head_.prev ());
1017 }
1018
1019 // ========================================================================
1020
1021 template <typename T, typename N, N T::* MP, typename U>
1023 : node_{}
1024 {
1025 }
1026
1027 template <typename T, typename N, N T::* MP, typename U>
1029 N* const node)
1030 : node_{ node }
1031 {
1032 }
1033
1034 template <typename T, typename N, N T::* MP, typename U>
1036 reference element)
1037 : node_{ &(element.*MP) }
1038 {
1039 static_assert (std::is_convertible<U, T>::value == true,
1040 "U must be implicitly convertible to T!");
1041 }
1042
1043 template <typename T, typename N, N T::* MP, typename U>
1046 {
1047 return get_pointer ();
1048 }
1049
1050 template <typename T, typename N, N T::* MP, typename U>
1053 {
1054 return *get_pointer ();
1055 }
1056
1057 template <typename T, typename N, N T::* MP, typename U>
1060 {
1061 node_ = static_cast<iterator_pointer> (node_->next ());
1062 return *this;
1063 }
1064
1065 template <typename T, typename N, N T::* MP, typename U>
1068 {
1069 const auto tmp = *this;
1070 node_ = static_cast<iterator_pointer> (node_->next ());
1071 return tmp;
1072 }
1073
1074 template <typename T, typename N, N T::* MP, typename U>
1077 {
1078 node_ = static_cast<iterator_pointer> (node_->prev ());
1079 return *this;
1080 }
1081
1082 template <typename T, typename N, N T::* MP, typename U>
1085 {
1086 const auto tmp = *this;
1087 node_ = static_cast<iterator_pointer> (node_->prev ());
1088 return tmp;
1089 }
1090
1091 template <typename T, typename N, N T::* MP, typename U>
1092 inline bool
1094 const intrusive_list_iterator& other) const
1095 {
1096 return node_ == other.node_;
1097 }
1098
1099 template <typename T, typename N, N T::* MP, typename U>
1100 inline bool
1102 const intrusive_list_iterator& other) const
1103 {
1104 return node_ != other.node_;
1105 }
1106
1107 template <typename T, typename N, N T::* MP, typename U>
1110 {
1111 // static_assert(std::is_convertible<U, T>::value == true, "U must be
1112 // implicitly convertible to T!");
1113
1114 // Compute the distance between the member intrusive link
1115 // node and the class begin.
1116 const auto offset = reinterpret_cast<difference_type> (
1117 &(static_cast<T*> (nullptr)->*MP));
1118
1119 // Compute the address of the object which includes the
1120 // intrusive node, by adjusting down the node address.
1121 return reinterpret_cast<pointer> (
1122 reinterpret_cast<difference_type> (node_) - offset);
1123 }
1124
1125 template <typename T, typename N, N T::* MP, typename U>
1128 {
1129 return node_;
1130 }
1131
1132 // ========================================================================
1133
1134 template <typename T, typename N, N T::* MP, typename U>
1136 {
1137 }
1138
1139 template <typename T, typename N, N T::* MP, typename U>
1141 {
1142 if (clr)
1143 {
1144 clear ();
1145 }
1146 }
1147
1148 template <typename T, typename N, N T::* MP, typename U>
1150 {
1151 }
1152
1153 template <typename T, typename N, N T::* MP, typename U>
1154 void
1156 {
1157 if (uninitialized ())
1158 {
1159 // If this is the first time, initialise the list to empty.
1160 clear ();
1161 }
1162
1163 // Compute the distance between the member intrusive link
1164 // node and the class begin.
1165 const auto offset = reinterpret_cast<difference_type> (
1166 &(static_cast<T*> (nullptr)->*MP));
1167
1168 // Add thread intrusive node at the end of the list.
1169 insert_after (*reinterpret_cast<static_double_list_links*> (
1170 reinterpret_cast<difference_type> (&node) + offset),
1171 const_cast<static_double_list_links*> (tail ()));
1172 }
1173
1174#pragma GCC diagnostic push
1175#if defined(__clang__)
1176#elif defined(__GNUC__)
1177#pragma GCC diagnostic ignored "-Waggregate-return"
1178#endif
1179
1183 template <typename T, typename N, N T::* MP, typename U>
1186 {
1187 if (uninitialized ())
1188 {
1189 // If this is the first time, initialise the list to empty.
1190 clear ();
1191 }
1192 return iterator{ static_cast<iterator_pointer> (head_.next ()) };
1193 }
1194
1195 template <typename T, typename N, N T::* MP, typename U>
1198 {
1199 return iterator{ static_cast<iterator_pointer> (
1200 const_cast<static_double_list_links*> (&head_)) };
1201 }
1202
1203#pragma GCC diagnostic pop
1204
1205 template <typename T, typename N, N T::* MP, typename U>
1208 {
1209 // static_assert(std::is_convertible<U, T>::value == true, "U must be
1210 // implicitly convertible to T!");
1211
1212 // Compute the distance between the member intrusive link
1213 // node and the class begin.
1214 const auto offset = reinterpret_cast<difference_type> (
1215 &(static_cast<T*> (nullptr)->*MP));
1216
1217 // Compute the address of the object which includes the
1218 // intrusive node, by adjusting down the node address.
1219 return reinterpret_cast<pointer> (
1220 reinterpret_cast<difference_type> (node) - offset);
1221 }
1222
1223 template <typename T, typename N, N T::* MP, typename U>
1226 {
1227 assert (!empty ());
1228
1229 // The first element in the list.
1230 iterator_pointer link = static_cast<iterator_pointer> (head_.next ());
1231 link->unlink ();
1232
1233 return get_pointer (link);
1234 }
1235
1236 template <typename T, typename N, N T::* MP, typename U>
1239 {
1240 assert (!empty ());
1241
1242 // The last element in the list.
1243 iterator_pointer link = static_cast<iterator_pointer> (head_.prev ());
1244 link->unlink ();
1245
1246 return get_pointer (link);
1247 }
1248
1249 } /* namespace utils */
1250} /* namespace os */
1251
1252#pragma GCC diagnostic pop
1253
1254// ----------------------------------------------------------------------------
1255
1256#endif /* __cplusplus */
1257
1258// ----------------------------------------------------------------------------
1259
1260#endif /* CMSIS_PLUS_RTOS_INTERNAL_OS_LISTS_H_ */
Template for a double linked list iterator.
Definition lists.h:209
reference operator*() const
Definition lists.h:902
double_list_iterator & operator--()
Definition lists.h:926
N * iterator_pointer
Type of reference to the iterator internal pointer.
Definition lists.h:234
pointer get_pointer(void) const
Get the object node from the intrusive node.
Definition lists.h:960
pointer operator->() const
Definition lists.h:895
U value_type
Type of value "pointed to" by the iterator.
Definition lists.h:219
bool operator!=(const double_list_iterator &other) const
Definition lists.h:951
std::forward_iterator_tag iterator_category
Category of iterator.
Definition lists.h:244
iterator_pointer get_iterator_pointer() const
Definition lists.h:967
bool operator==(const double_list_iterator &other) const
Definition lists.h:943
U * pointer
Type of pointer to object "pointed to" by the iterator.
Definition lists.h:224
double_list_iterator & operator++()
Definition lists.h:909
constexpr double_list_iterator()
Definition lists.h:872
ptrdiff_t difference_type
Type of pointer difference.
Definition lists.h:239
iterator_pointer node_
Pointer to intrusive node.
Definition lists.h:327
U & reference
Type of reference to object "pointed to" by the iterator.
Definition lists.h:229
Circular double linked list of nodes.
Definition lists.h:488
double_list()
Construct a list.
Definition lists.cpp:153
~double_list()
Destruct the list.
Definition lists.cpp:166
Template for an intrusive list iterator.
Definition lists.h:544
bool operator!=(const intrusive_list_iterator &other) const
Definition lists.h:1101
std::forward_iterator_tag iterator_category
Category of iterator.
Definition lists.h:579
intrusive_list_iterator & operator++()
Definition lists.h:1059
iterator_pointer node_
Pointer to intrusive node.
Definition lists.h:662
N * iterator_pointer
Type of reference to the iterator internal pointer.
Definition lists.h:569
ptrdiff_t difference_type
Type of pointer difference.
Definition lists.h:574
iterator_pointer get_iterator_pointer() const
Definition lists.h:1127
U value_type
Type of value "pointed to" by the iterator.
Definition lists.h:554
intrusive_list_iterator & operator--()
Definition lists.h:1076
pointer get_pointer(void) const
Get the object node from the intrusive node.
Definition lists.h:1109
reference operator*() const
Definition lists.h:1052
bool operator==(const intrusive_list_iterator &other) const
Definition lists.h:1093
U & reference
Type of reference to object "pointed to" by the iterator.
Definition lists.h:564
U * pointer
Type of pointer to object "pointed to" by the iterator.
Definition lists.h:559
List of intrusive nodes.
Definition lists.h:690
ptrdiff_t difference_type
Definition lists.h:695
pointer get_pointer(iterator_pointer node) const
Definition lists.h:1207
~intrusive_list()
Destruct the list.
Definition lists.h:1149
pointer unlink_tail(void)
Unlink the last element from the list.
Definition lists.h:1238
pointer unlink_head(void)
Unlink the first element from the list.
Definition lists.h:1225
intrusive_list()
Construct an intrusive list.
Definition lists.h:1135
iterator end() const
Iterator begin.
Definition lists.h:1197
N * iterator_pointer
Type of reference to the iterator internal pointer.
Definition lists.h:702
iterator begin()
Iterator begin.
Definition lists.h:1185
void link(reference node)
Add a node to the tail of the list.
Definition lists.h:1155
Statically allocated circular double linked list of nodes.
Definition lists.h:342
static_double_list_links head_
A list node used to point to head and tail.
Definition lists.h:473
void insert_after(static_double_list_links &node, static_double_list_links *after)
Insert a new node after existing node.
Definition lists.cpp:121
bool empty(void) const
Check if the list is empty.
Definition lists.h:1001
~static_double_list()
Destruct the list.
Definition lists.h:989
void clear(void)
Clear the list.
Definition lists.cpp:108
volatile static_double_list_links * tail(void) const
Get the list tail.
Definition lists.h:1014
volatile static_double_list_links * head(void) const
Get the list head.
Definition lists.h:1008
bool uninitialized(void) const
Check if the list is uninitialised.
Definition lists.h:994
static_double_list()
Construct a list.
Definition lists.h:979
int link(const char *existing, const char *_new)
System namespace.