µ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++ distribution.
3 * (https://github.com/micro-os-plus)
4 * Copyright (c) 2016-2023 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#ifndef CMSIS_PLUS_UTILS_LISTS_H_
14#define CMSIS_PLUS_UTILS_LISTS_H_
15
16// ----------------------------------------------------------------------------
17
18#ifdef __cplusplus
19
20// ----------------------------------------------------------------------------
21
22#include <cstdint>
23#include <cstddef>
24#include <cassert>
25#include <iterator>
26
27// ----------------------------------------------------------------------------
28
29#pragma GCC diagnostic push
30#if defined(__clang__)
31#pragma clang diagnostic ignored "-Wc++98-compat"
32#endif
33
34// ----------------------------------------------------------------------------
35
36namespace os
37{
38 namespace utils
39 {
40 // ========================================================================
41
49 {
50 public:
51
61
69 operator= (const static_double_list_links&) = delete;
71 operator= (static_double_list_links&&) = 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:
124
134
139
144 };
145
146 // ========================================================================
147
155 {
156 public:
157
167
172 double_list_links (const double_list_links&) = delete;
175 operator= (const double_list_links&) = delete;
177 operator= (double_list_links&&) = delete;
178
187
192 };
193
194 // ========================================================================
195
209 template<typename T, typename N, T* N::* MP, typename U = T>
211 {
212 public:
213
222 using value_type = U;
223
227 using pointer = U*;
228
232 using reference = U&;
233
238
242 using difference_type = ptrdiff_t;
243
247 using iterator_category = std::forward_iterator_tag;
248
253 // --------------------------------------------------------------------
259 constexpr
261
262 constexpr explicit
264
265 constexpr explicit
267
277 pointer
278 operator-> () const;
279
281 operator* () const;
282
284 operator++ ();
285
287 operator++ (int);
288
290 operator-- ();
291
293 operator-- (int);
294
295 bool
296 operator== (const double_list_iterator& other) const;
297
298 bool
299 operator!= (const double_list_iterator& other) const;
300
314 pointer
315 get_pointer (void) const;
316
318 get_iterator_pointer () const;
319
324 protected:
325
335
340 };
341
342 // ========================================================================
343
350 {
351 public:
352
362
367 static_double_list (const static_double_list&) = delete;
370 operator= (const static_double_list&) = delete;
372 operator= (static_double_list&&) = delete;
373
382
387 public:
388
401 bool
402 uninitialized (void) const;
403
411 void
412 clear (void);
413
421 bool
422 empty (void) const;
423
424 // TODO add iterator begin(), end()
425
433 head (void) const;
434
442 tail (void) const;
443
448 protected:
449
462 void
465
470 protected:
471
483
487 };
488
489 // ========================================================================
490
497 {
498 public:
499
508 double_list ();
509
514 double_list (const double_list&) = delete;
515 double_list (double_list&&) = delete;
517 operator= (const double_list&) = delete;
519 operator= (double_list&&) = delete;
520
528 ~double_list ();
529
534 };
535
536 // ========================================================================
537
551 template<typename T, typename N, N T::* MP, typename U = T>
553 {
554 public:
555
564 using value_type = U;
565
569 using pointer = U*;
570
574 using reference = U&;
575
580
584 using difference_type = ptrdiff_t;
585
589 using iterator_category = std::forward_iterator_tag;
590
595 // --------------------------------------------------------------------
601 constexpr
603
604 constexpr explicit
606
607 constexpr explicit
609
619 pointer
620 operator-> () const;
621
623 operator* () const;
624
626 operator++ ();
627
629 operator++ (int);
630
632 operator-- ();
633
635 operator-- (int);
636
637 bool
638 operator== (const intrusive_list_iterator& other) const;
639
640 bool
641 operator!= (const intrusive_list_iterator& other) const;
642
656 pointer
657 get_pointer (void) const;
658
660 get_iterator_pointer () const;
661
666 protected:
667
677
682 };
683
684 // ========================================================================
685
703 template<typename T, typename N, N T::* MP, typename U = T>
705 {
706 public:
707
708 using value_type = U;
709 using pointer = U*;
710 using reference = U&;
711 using difference_type = ptrdiff_t;
712
714
719
729
734 intrusive_list (bool clr);
735
740 intrusive_list (const intrusive_list&) = delete;
741 intrusive_list (intrusive_list&&) = delete;
743 operator= (const intrusive_list&) = delete;
745 operator= (intrusive_list&&) = delete;
746
755
760 protected:
761
762 pointer
763 get_pointer (iterator_pointer node) const;
764
765 public:
766
778 void
779 link (reference node);
780
786 begin ();
787
793 end () const;
794
799 pointer
800 unlink_head (void);
801
806 pointer
807 unlink_tail (void);
808
812 };
813
814 // --------------------------------------------------------------------------
815 } /* namespace utils */
816} /* namespace os */
817
818// ----------------------------------------------------------------------------
819
820namespace os
821{
822 namespace utils
823 {
824 // ========================================================================
825
826 // Code analysis may trigger:
827 // "Member 'prev' was not initialized in constructor"
828 // "Member 'next' was not initialized in constructor"
829
830 inline
832 {
833 }
834
835 inline
837 {
838 // Revert the content to a state similar to the statically initialised
839 // state (BSS zero).
840 // Unfortunately GCC removes this code as part of
841 // _dead store elimination_.
842 // next_ = nullptr;
843 // prev_ = nullptr;
844 }
845
846 inline bool
848 {
849 return (next_ == nullptr);
850 }
851
854 {
855 return next_;
856 }
857
860 {
861 return prev_;
862 }
863
864 inline void
866 {
867 next_ = n;
868 }
869
870 inline void
872 {
873 prev_ = n;
874 }
875
876 // ========================================================================
877
878 inline
880 {
881 prev_ = nullptr;
882 next_ = nullptr;
883 }
884
885 inline
887 {
888 }
889
890 // ========================================================================
891 template<typename T, typename N, T* N::* MP, typename U>
892 constexpr
894 node_
895 { }
896 {
897 }
898
899 template<typename T, typename N, T* N::* MP, typename U>
900 constexpr
902 iterator_pointer const node) :
903 node_
904 { node }
905 {
906 }
907
908 template<typename T, typename N, T* N::* MP, typename U>
909 constexpr
911 reference element) :
912 node_
913 { &(element.*MP) }
914 {
915 static_assert(std::is_convertible<U, T>::value == true, "U must be implicitly convertible to T!");
916 }
917
918 template<typename T, typename N, T* N::* MP, typename U>
921 {
922 return get_pointer ();
923 }
924
925 template<typename T, typename N, T* N::* MP, typename U>
928 {
929 return *get_pointer ();
930 }
931
932 template<typename T, typename N, T* N::* MP, typename U>
935 {
936 node_ = static_cast<N*> (node_->next ());
937 return *this;
938 }
939
940 template<typename T, typename N, T* N::* MP, typename U>
943 {
944 const auto tmp = *this;
945 node_ = static_cast<iterator_pointer> (node_->next);
946 return tmp;
947 }
948
949 template<typename T, typename N, T* N::* MP, typename U>
952 {
953 node_ = static_cast<iterator_pointer> (node_->prev);
954 return *this;
955 }
956
957 template<typename T, typename N, T* N::* MP, typename U>
960 {
961 const auto tmp = *this;
962 node_ = static_cast<iterator_pointer> (node_->prev);
963 return tmp;
964 }
965
966 template<typename T, typename N, T* N::* MP, typename U>
967 inline bool
969 const double_list_iterator& other) const
970 {
971 return node_ == other.node_;
972 }
973
974 template<typename T, typename N, T* N::* MP, typename U>
975 inline bool
977 const double_list_iterator& other) const
978 {
979 return node_ != other.node_;
980 }
981
982#if 1
983 template<typename T, typename N, T* N::* MP, typename U>
986 {
987 return (node_->*MP);
988 }
989
990 template<typename T, typename N, T* N::* MP, typename U>
993 {
994 return node_;
995 }
996#endif
997
998 // ========================================================================
999
1004 inline
1006 {
1007 // By all means, do not add any code here.
1008 // The constructor was not `default` to benefit from inline.
1009 }
1010
1015 inline
1017 {
1018 }
1019
1020 inline bool
1022 {
1023 // If it points to nowhere, it is not yet initialised.
1024 return (head_.prev () == nullptr);
1025 }
1026
1027 inline bool
1029 {
1030 // If it points to itself, it is empty.
1031 return (head_.next () == &head_) || (head_.next () == nullptr);
1032 }
1033
1034 inline volatile static_double_list_links*
1036 {
1037 return static_cast<volatile static_double_list_links*> (head_.next ());
1038 }
1039
1040 inline volatile static_double_list_links*
1042 {
1043 return (head_.prev ());
1044 }
1045
1046 // ========================================================================
1047
1048 template<typename T, typename N, N T::* MP, typename U>
1049 constexpr
1051 node_
1052 { }
1053 {
1054 }
1055
1056 template<typename T, typename N, N T::* MP, typename U>
1057 constexpr
1059 N* const node) :
1060 node_
1061 { node }
1062 {
1063 }
1064
1065 template<typename T, typename N, N T::* MP, typename U>
1066 constexpr
1068 reference element) :
1069 node_
1070 { &(element.*MP) }
1071 {
1072 static_assert(std::is_convertible<U, T>::value == true, "U must be implicitly convertible to T!");
1073 }
1074
1075 template<typename T, typename N, N T::* MP, typename U>
1078 {
1079 return get_pointer ();
1080 }
1081
1082 template<typename T, typename N, N T::* MP, typename U>
1085 {
1086 return *get_pointer ();
1087 }
1088
1089 template<typename T, typename N, N T::* MP, typename U>
1092 {
1093 node_ = static_cast<iterator_pointer> (node_->next ());
1094 return *this;
1095 }
1096
1097 template<typename T, typename N, N T::* MP, typename U>
1100 {
1101 const auto tmp = *this;
1102 node_ = static_cast<iterator_pointer> (node_->next ());
1103 return tmp;
1104 }
1105
1106 template<typename T, typename N, N T::* MP, typename U>
1109 {
1110 node_ = static_cast<iterator_pointer> (node_->prev ());
1111 return *this;
1112 }
1113
1114 template<typename T, typename N, N T::* MP, typename U>
1117 {
1118 const auto tmp = *this;
1119 node_ = static_cast<iterator_pointer> (node_->prev ());
1120 return tmp;
1121 }
1122
1123 template<typename T, typename N, N T::* MP, typename U>
1124 inline bool
1126 const intrusive_list_iterator& other) const
1127 {
1128 return node_ == other.node_;
1129 }
1130
1131 template<typename T, typename N, N T::* MP, typename U>
1132 inline bool
1134 const intrusive_list_iterator& other) const
1135 {
1136 return node_ != other.node_;
1137 }
1138
1139 template<typename T, typename N, N T::* MP, typename U>
1142 {
1143 // static_assert(std::is_convertible<U, T>::value == true, "U must be implicitly convertible to T!");
1144
1145 // Compute the distance between the member intrusive link
1146 // node and the class begin.
1147 const auto offset =
1148 reinterpret_cast<difference_type> (&(static_cast<T*> (nullptr)->*MP));
1149
1150 // Compute the address of the object which includes the
1151 // intrusive node, by adjusting down the node address.
1152 return reinterpret_cast<pointer> (reinterpret_cast<difference_type> (node_)
1153 - offset);
1154 }
1155
1156 template<typename T, typename N, N T::* MP, typename U>
1159 {
1160 return node_;
1161 }
1162
1163 // ========================================================================
1164
1165 template<typename T, typename N, N T::* MP, typename U>
1166 inline
1168 {
1169 }
1170
1171 template<typename T, typename N, N T::* MP, typename U>
1172 inline
1174 {
1175 if (clr)
1176 {
1177 clear ();
1178 }
1179 }
1180
1181 template<typename T, typename N, N T::* MP, typename U>
1182 inline
1184 {
1185 }
1186
1187 template<typename T, typename N, N T::* MP, typename U>
1188 void
1190 {
1191 if (uninitialized ())
1192 {
1193 // If this is the first time, initialise the list to empty.
1194 clear ();
1195 }
1196
1197 // Compute the distance between the member intrusive link
1198 // node and the class begin.
1199 const auto offset =
1200 reinterpret_cast<difference_type> (&(static_cast<T*> (nullptr)->*MP));
1201
1202 // Add thread intrusive node at the end of the list.
1203 insert_after (
1204 *reinterpret_cast<static_double_list_links*> (reinterpret_cast<difference_type> (&node)
1205 + offset),
1206 const_cast<static_double_list_links *> (tail ()));
1207 }
1208
1209#pragma GCC diagnostic push
1210#if defined(__clang__)
1211#elif defined(__GNUC__)
1212#pragma GCC diagnostic ignored "-Waggregate-return"
1213#endif
1214
1218 template<typename T, typename N, N T::* MP, typename U>
1221 {
1222 if (uninitialized ())
1223 {
1224 // If this is the first time, initialise the list to empty.
1225 clear ();
1226 }
1227 return iterator
1228 { static_cast<iterator_pointer> (head_.next ()) };
1229 }
1230
1231 template<typename T, typename N, N T::* MP, typename U>
1234 {
1235 return iterator
1236 {
1237 static_cast<iterator_pointer> (const_cast<static_double_list_links*> (&head_)) };
1238 }
1239
1240#pragma GCC diagnostic pop
1241
1242 template<typename T, typename N, N T::* MP, typename U>
1245 {
1246 // static_assert(std::is_convertible<U, T>::value == true, "U must be implicitly convertible to T!");
1247
1248 // Compute the distance between the member intrusive link
1249 // node and the class begin.
1250 const auto offset =
1251 reinterpret_cast<difference_type> (&(static_cast<T*> (nullptr)->*MP));
1252
1253 // Compute the address of the object which includes the
1254 // intrusive node, by adjusting down the node address.
1255 return reinterpret_cast<pointer> (reinterpret_cast<difference_type> (node)
1256 - offset);
1257 }
1258
1259 template<typename T, typename N, N T::* MP, typename U>
1262 {
1263 assert(!empty ());
1264
1265 // The first element in the list.
1266 iterator_pointer link = static_cast<iterator_pointer> (head_.next ());
1267 link->unlink ();
1268
1269 return get_pointer (link);
1270 }
1271
1272 template<typename T, typename N, N T::* MP, typename U>
1275 {
1276 assert(!empty ());
1277
1278 // The last element in the list.
1279 iterator_pointer link = static_cast<iterator_pointer> (head_.prev ());
1280 link->unlink ();
1281
1282 return get_pointer (link);
1283 }
1284
1285 } /* namespace utils */
1286} /* namespace os */
1287
1288#pragma GCC diagnostic pop
1289
1290// ----------------------------------------------------------------------------
1291
1292#endif /* __cplusplus */
1293
1294// ----------------------------------------------------------------------------
1295
1296#endif /* CMSIS_PLUS_RTOS_INTERNAL_OS_LISTS_H_ */
Template for a double linked list iterator.
Definition lists.h:211
reference operator*() const
Definition lists.h:927
double_list_iterator & operator--()
Definition lists.h:951
N * iterator_pointer
Type of reference to the iterator internal pointer.
Definition lists.h:237
pointer get_pointer(void) const
Get the object node from the intrusive node.
Definition lists.h:985
pointer operator->() const
Definition lists.h:920
U value_type
Type of value "pointed to" by the iterator.
Definition lists.h:222
bool operator!=(const double_list_iterator &other) const
Definition lists.h:976
std::forward_iterator_tag iterator_category
Category of iterator.
Definition lists.h:247
iterator_pointer get_iterator_pointer() const
Definition lists.h:992
bool operator==(const double_list_iterator &other) const
Definition lists.h:968
U * pointer
Type of pointer to object "pointed to" by the iterator.
Definition lists.h:227
double_list_iterator & operator++()
Definition lists.h:934
constexpr double_list_iterator()
Definition lists.h:893
ptrdiff_t difference_type
Type of pointer difference.
Definition lists.h:242
iterator_pointer node_
Pointer to intrusive node.
Definition lists.h:334
U & reference
Type of reference to object "pointed to" by the iterator.
Definition lists.h:232
Circular double linked list of nodes.
Definition lists.h:497
double_list()
Construct a list.
Definition lists.cpp:150
~double_list()
Destruct the list.
Definition lists.cpp:163
Template for an intrusive list iterator.
Definition lists.h:553
bool operator!=(const intrusive_list_iterator &other) const
Definition lists.h:1133
std::forward_iterator_tag iterator_category
Category of iterator.
Definition lists.h:589
intrusive_list_iterator & operator++()
Definition lists.h:1091
iterator_pointer node_
Pointer to intrusive node.
Definition lists.h:676
N * iterator_pointer
Type of reference to the iterator internal pointer.
Definition lists.h:579
ptrdiff_t difference_type
Type of pointer difference.
Definition lists.h:584
iterator_pointer get_iterator_pointer() const
Definition lists.h:1158
U value_type
Type of value "pointed to" by the iterator.
Definition lists.h:564
intrusive_list_iterator & operator--()
Definition lists.h:1108
pointer get_pointer(void) const
Get the object node from the intrusive node.
Definition lists.h:1141
reference operator*() const
Definition lists.h:1084
bool operator==(const intrusive_list_iterator &other) const
Definition lists.h:1125
U & reference
Type of reference to object "pointed to" by the iterator.
Definition lists.h:574
U * pointer
Type of pointer to object "pointed to" by the iterator.
Definition lists.h:569
List of intrusive nodes.
Definition lists.h:705
ptrdiff_t difference_type
Definition lists.h:711
pointer get_pointer(iterator_pointer node) const
Definition lists.h:1244
~intrusive_list()
Destruct the list.
Definition lists.h:1183
pointer unlink_tail(void)
Unlink the last element from the list.
Definition lists.h:1274
pointer unlink_head(void)
Unlink the first element from the list.
Definition lists.h:1261
intrusive_list()
Construct an intrusive list.
Definition lists.h:1167
iterator end() const
Iterator begin.
Definition lists.h:1233
N * iterator_pointer
Type of reference to the iterator internal pointer.
Definition lists.h:718
iterator begin()
Iterator begin.
Definition lists.h:1220
void link(reference node)
Add a node to the tail of the list.
Definition lists.h:1189
Statically allocated circular double linked list of nodes.
Definition lists.h:350
static_double_list_links head_
A list node used to point to head and tail.
Definition lists.h:482
void insert_after(static_double_list_links &node, static_double_list_links *after)
Insert a new node after existing node.
Definition lists.cpp:118
bool empty(void) const
Check if the list is empty.
Definition lists.h:1028
~static_double_list()
Destruct the list.
Definition lists.h:1016
void clear(void)
Clear the list.
Definition lists.cpp:105
volatile static_double_list_links * tail(void) const
Get the list tail.
Definition lists.h:1041
volatile static_double_list_links * head(void) const
Get the list head.
Definition lists.h:1035
bool uninitialized(void) const
Check if the list is uninitialised.
Definition lists.h:1021
static_double_list()
Construct a list.
Definition lists.h:1005
int link(const char *existing, const char *_new)
System namespace.