µ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 Liviu Ionescu.
5 *
6 * Permission is hereby granted, free of charge, to any person
7 * obtaining a copy of this software and associated documentation
8 * files (the "Software"), to deal in the Software without
9 * restriction, including without limitation the rights to use,
10 * copy, modify, merge, publish, distribute, sublicense, and/or
11 * sell copies of the Software, and to permit persons to whom
12 * the Software is furnished to do so, subject to the following
13 * conditions:
14 *
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28#ifndef CMSIS_PLUS_UTILS_LISTS_H_
29#define CMSIS_PLUS_UTILS_LISTS_H_
30
31// ----------------------------------------------------------------------------
32
33#ifdef __cplusplus
34
35// ----------------------------------------------------------------------------
36
37#include <cstdint>
38#include <cstddef>
39#include <cassert>
40#include <iterator>
41
42// ----------------------------------------------------------------------------
43
44#pragma GCC diagnostic push
45
46#if defined(__clang__)
47#pragma clang diagnostic ignored "-Wc++98-compat"
48#endif
49
50// ----------------------------------------------------------------------------
51
52namespace os
53{
54 namespace utils
55 {
56 // ========================================================================
57
65 {
66 public:
67
77
85 operator= (const static_double_list_links&) = delete;
87 operator= (static_double_list_links&&) = delete;
88
97
112 void
113 unlink (void);
114
120 bool
121 unlinked (void);
122
124 next (void) const;
125
127 prev (void) const;
128
129 void
131
132 void
134
139 protected:
140
150
155
160 };
161
162 // ========================================================================
163
171 {
172 public:
173
183
188 double_list_links (const double_list_links&) = delete;
191 operator= (const double_list_links&) = delete;
193 operator= (double_list_links&&) = delete;
194
203
208 };
209
210 // ========================================================================
211
225 template<typename T, typename N, T* N::* MP, typename U = T>
227 {
228 public:
229
238 using value_type = U;
239
243 using pointer = U*;
244
248 using reference = U&;
249
254
258 using difference_type = ptrdiff_t;
259
263 using iterator_category = std::forward_iterator_tag;
264
269 // --------------------------------------------------------------------
275 constexpr
277
278 constexpr explicit
280
281 constexpr explicit
283
293 pointer
294 operator-> () const;
295
297 operator* () const;
298
300 operator++ ();
301
303 operator++ (int);
304
306 operator-- ();
307
309 operator-- (int);
310
311 bool
312 operator== (const double_list_iterator& other) const;
313
314 bool
315 operator!= (const double_list_iterator& other) const;
316
330 pointer
331 get_pointer (void) const;
332
334 get_iterator_pointer () const;
335
340 protected:
341
351
356 };
357
358 // ========================================================================
359
366 {
367 public:
368
378
383 static_double_list (const static_double_list&) = delete;
386 operator= (const static_double_list&) = delete;
388 operator= (static_double_list&&) = delete;
389
398
403 public:
404
417 bool
418 uninitialized (void) const;
419
427 void
428 clear (void);
429
437 bool
438 empty (void) const;
439
440 // TODO add iterator begin(), end()
441
449 head (void) const;
450
458 tail (void) const;
459
464 protected:
465
478 void
481
486 protected:
487
499
503 };
504
505 // ========================================================================
506
513 {
514 public:
515
524 double_list ();
525
530 double_list (const double_list&) = delete;
531 double_list (double_list&&) = delete;
533 operator= (const double_list&) = delete;
535 operator= (double_list&&) = delete;
536
544 ~double_list ();
545
550 };
551
552 // ========================================================================
553
567 template<typename T, typename N, N T::* MP, typename U = T>
569 {
570 public:
571
580 using value_type = U;
581
585 using pointer = U*;
586
590 using reference = U&;
591
596
600 using difference_type = ptrdiff_t;
601
605 using iterator_category = std::forward_iterator_tag;
606
611 // --------------------------------------------------------------------
617 constexpr
619
620 constexpr explicit
622
623 constexpr explicit
625
635 pointer
636 operator-> () const;
637
639 operator* () const;
640
642 operator++ ();
643
645 operator++ (int);
646
648 operator-- ();
649
651 operator-- (int);
652
653 bool
654 operator== (const intrusive_list_iterator& other) const;
655
656 bool
657 operator!= (const intrusive_list_iterator& other) const;
658
672 pointer
673 get_pointer (void) const;
674
676 get_iterator_pointer () const;
677
682 protected:
683
693
698 };
699
700 // ========================================================================
701
719 template<typename T, typename N, N T::* MP, typename U = T>
721 {
722 public:
723
724 using value_type = U;
725 using pointer = U*;
726 using reference = U&;
727 using difference_type = ptrdiff_t;
728
730
735
745
750 intrusive_list (bool clr);
751
756 intrusive_list (const intrusive_list&) = delete;
757 intrusive_list (intrusive_list&&) = delete;
759 operator= (const intrusive_list&) = delete;
761 operator= (intrusive_list&&) = delete;
762
771
776 protected:
777
778 pointer
779 get_pointer (iterator_pointer node) const;
780
781 public:
782
794 void
795 link (reference node);
796
802 begin ();
803
809 end () const;
810
815 pointer
816 unlink_head (void);
817
822 pointer
823 unlink_tail (void);
824
828 };
829
830 // --------------------------------------------------------------------------
831 } /* namespace utils */
832} /* namespace os */
833
834// ----------------------------------------------------------------------------
835
836namespace os
837{
838 namespace utils
839 {
840 // ========================================================================
841
842 // Code analysis may trigger:
843 // "Member 'prev' was not initialized in constructor"
844 // "Member 'next' was not initialized in constructor"
845
846 inline
848 {
849 ;
850 }
851
852 inline
854 {
855 // Revert the content to a state similar to the statically initialised
856 // state (BSS zero).
857 // Unfortunately GCC removes this code as part of
858 // _dead store elimination_.
859 // next_ = nullptr;
860 // prev_ = nullptr;
861 }
862
863 inline bool
865 {
866 return (next_ == nullptr);
867 }
868
871 {
872 return next_;
873 }
874
877 {
878 return prev_;
879 }
880
881 inline void
883 {
884 next_ = n;
885 }
886
887 inline void
889 {
890 prev_ = n;
891 }
892
893 // ========================================================================
894
895 inline
897 {
898 prev_ = nullptr;
899 next_ = nullptr;
900 }
901
902 inline
904 {
905 ;
906 }
907
908 // ========================================================================
909 template<typename T, typename N, T* N::* MP, typename U>
910 constexpr
912 node_
913 { }
914 {
915 ;
916 }
917
918 template<typename T, typename N, T* N::* MP, typename U>
919 constexpr
921 iterator_pointer const node) :
922 node_
923 { node }
924 {
925 ;
926 }
927
928 template<typename T, typename N, T* N::* MP, typename U>
929 constexpr
931 reference element) :
932 node_
933 { &(element.*MP) }
934 {
935 static_assert(std::is_convertible<U, T>::value == true, "U must be implicitly convertible to T!");
936 }
937
938 template<typename T, typename N, T* N::* MP, typename U>
941 {
942 return get_pointer ();
943 }
944
945 template<typename T, typename N, T* N::* MP, typename U>
948 {
949 return *get_pointer ();
950 }
951
952 template<typename T, typename N, T* N::* MP, typename U>
955 {
956 node_ = static_cast<N*> (node_->next ());
957 return *this;
958 }
959
960 template<typename T, typename N, T* N::* MP, typename U>
963 {
964 const auto tmp = *this;
965 node_ = static_cast<iterator_pointer> (node_->next);
966 return tmp;
967 }
968
969 template<typename T, typename N, T* N::* MP, typename U>
972 {
973 node_ = static_cast<iterator_pointer> (node_->prev);
974 return *this;
975 }
976
977 template<typename T, typename N, T* N::* MP, typename U>
980 {
981 const auto tmp = *this;
982 node_ = static_cast<iterator_pointer> (node_->prev);
983 return tmp;
984 }
985
986 template<typename T, typename N, T* N::* MP, typename U>
987 inline bool
989 const double_list_iterator& other) const
990 {
991 return node_ == other.node_;
992 }
993
994 template<typename T, typename N, T* N::* MP, typename U>
995 inline bool
997 const double_list_iterator& other) const
998 {
999 return node_ != other.node_;
1000 }
1001
1002#if 1
1003 template<typename T, typename N, T* N::* MP, typename U>
1006 {
1007 return (node_->*MP);
1008 }
1009
1010 template<typename T, typename N, T* N::* MP, typename U>
1013 {
1014 return node_;
1015 }
1016#endif
1017
1018 // ========================================================================
1019
1024 inline
1026 {
1027 // By all means, do not add any code here.
1028 // The constructor was not `default` to benefit from inline.
1029 }
1030
1035 inline
1037 {
1038 ;
1039 }
1040
1041 inline bool
1043 {
1044 // If it points to nowhere, it is not yet initialised.
1045 return (head_.prev () == nullptr);
1046 }
1047
1048 inline bool
1050 {
1051 // If it points to itself, it is empty.
1052 return (head_.next () == &head_) || (head_.next () == nullptr);
1053 }
1054
1055 inline volatile static_double_list_links*
1057 {
1058 return static_cast<volatile static_double_list_links*> (head_.next ());
1059 }
1060
1061 inline volatile static_double_list_links*
1063 {
1064 return (head_.prev ());
1065 }
1066
1067 // ========================================================================
1068
1069 template<typename T, typename N, N T::* MP, typename U>
1070 constexpr
1072 node_
1073 { }
1074 {
1075 ;
1076 }
1077
1078 template<typename T, typename N, N T::* MP, typename U>
1079 constexpr
1081 N* const node) :
1082 node_
1083 { node }
1084 {
1085 ;
1086 }
1087
1088 template<typename T, typename N, N T::* MP, typename U>
1089 constexpr
1091 reference element) :
1092 node_
1093 { &(element.*MP) }
1094 {
1095 static_assert(std::is_convertible<U, T>::value == true, "U must be implicitly convertible to T!");
1096 }
1097
1098 template<typename T, typename N, N T::* MP, typename U>
1101 {
1102 return get_pointer ();
1103 }
1104
1105 template<typename T, typename N, N T::* MP, typename U>
1108 {
1109 return *get_pointer ();
1110 }
1111
1112 template<typename T, typename N, N T::* MP, typename U>
1115 {
1116 node_ = static_cast<iterator_pointer> (node_->next ());
1117 return *this;
1118 }
1119
1120 template<typename T, typename N, N T::* MP, typename U>
1123 {
1124 const auto tmp = *this;
1125 node_ = static_cast<iterator_pointer> (node_->next ());
1126 return tmp;
1127 }
1128
1129 template<typename T, typename N, N T::* MP, typename U>
1132 {
1133 node_ = static_cast<iterator_pointer> (node_->prev ());
1134 return *this;
1135 }
1136
1137 template<typename T, typename N, N T::* MP, typename U>
1140 {
1141 const auto tmp = *this;
1142 node_ = static_cast<iterator_pointer> (node_->prev ());
1143 return tmp;
1144 }
1145
1146 template<typename T, typename N, N T::* MP, typename U>
1147 inline bool
1149 const intrusive_list_iterator& other) const
1150 {
1151 return node_ == other.node_;
1152 }
1153
1154 template<typename T, typename N, N T::* MP, typename U>
1155 inline bool
1157 const intrusive_list_iterator& other) const
1158 {
1159 return node_ != other.node_;
1160 }
1161
1162 template<typename T, typename N, N T::* MP, typename U>
1165 {
1166 // static_assert(std::is_convertible<U, T>::value == true, "U must be implicitly convertible to T!");
1167
1168 // Compute the distance between the member intrusive link
1169 // node and the class begin.
1170 const auto offset =
1171 reinterpret_cast<difference_type> (&(static_cast<T*> (nullptr)->*MP));
1172
1173 // Compute the address of the object which includes the
1174 // intrusive node, by adjusting down the node address.
1175 return reinterpret_cast<pointer> (reinterpret_cast<difference_type> (node_)
1176 - offset);
1177 }
1178
1179 template<typename T, typename N, N T::* MP, typename U>
1182 {
1183 return node_;
1184 }
1185
1186 // ========================================================================
1187
1188 template<typename T, typename N, N T::* MP, typename U>
1189 inline
1191 {
1192 ;
1193 }
1194
1195 template<typename T, typename N, N T::* MP, typename U>
1196 inline
1198 {
1199 if (clr)
1200 {
1201 clear ();
1202 }
1203 }
1204
1205 template<typename T, typename N, N T::* MP, typename U>
1206 inline
1208 {
1209 ;
1210 }
1211
1212 template<typename T, typename N, N T::* MP, typename U>
1213 void
1215 {
1216 if (uninitialized ())
1217 {
1218 // If this is the first time, initialise the list to empty.
1219 clear ();
1220 }
1221
1222 // Compute the distance between the member intrusive link
1223 // node and the class begin.
1224 const auto offset =
1225 reinterpret_cast<difference_type> (&(static_cast<T*> (nullptr)->*MP));
1226
1227 // Add thread intrusive node at the end of the list.
1228 insert_after (
1229 *reinterpret_cast<static_double_list_links*> (reinterpret_cast<difference_type> (&node)
1230 + offset),
1231 const_cast<static_double_list_links *> (tail ()));
1232 }
1233
1237 template<typename T, typename N, N T::* MP, typename U>
1240 {
1241 if (uninitialized ())
1242 {
1243 // If this is the first time, initialise the list to empty.
1244 clear ();
1245 }
1246 return iterator
1247 { static_cast<iterator_pointer> (head_.next ()) };
1248 }
1249
1250 template<typename T, typename N, N T::* MP, typename U>
1253 {
1254 return iterator
1255 {
1256 static_cast<iterator_pointer> (const_cast<static_double_list_links*> (&head_)) };
1257 }
1258
1259 template<typename T, typename N, N T::* MP, typename U>
1262 {
1263 // static_assert(std::is_convertible<U, T>::value == true, "U must be implicitly convertible to T!");
1264
1265 // Compute the distance between the member intrusive link
1266 // node and the class begin.
1267 const auto offset =
1268 reinterpret_cast<difference_type> (&(static_cast<T*> (nullptr)->*MP));
1269
1270 // Compute the address of the object which includes the
1271 // intrusive node, by adjusting down the node address.
1272 return reinterpret_cast<pointer> (reinterpret_cast<difference_type> (node)
1273 - offset);
1274 }
1275
1276 template<typename T, typename N, N T::* MP, typename U>
1279 {
1280 assert(!empty ());
1281
1282 // The first element in the list.
1283 iterator_pointer link = static_cast<iterator_pointer> (head_.next ());
1284 link->unlink ();
1285
1286 return get_pointer (link);
1287 }
1288
1289 template<typename T, typename N, N T::* MP, typename U>
1292 {
1293 assert(!empty ());
1294
1295 // The last element in the list.
1296 iterator_pointer link = static_cast<iterator_pointer> (head_.prev ());
1297 link->unlink ();
1298
1299 return get_pointer (link);
1300 }
1301
1302 } /* namespace utils */
1303} /* namespace os */
1304
1305#pragma GCC diagnostic pop
1306
1307// ----------------------------------------------------------------------------
1308
1309#endif /* __cplusplus */
1310
1311// ----------------------------------------------------------------------------
1312
1313#endif /* CMSIS_PLUS_RTOS_INTERNAL_OS_LISTS_H_ */
Template for a double linked list iterator.
Definition lists.h:227
reference operator*() const
Definition lists.h:947
double_list_iterator & operator--()
Definition lists.h:971
N * iterator_pointer
Type of reference to the iterator internal pointer.
Definition lists.h:253
pointer get_pointer(void) const
Get the object node from the intrusive node.
Definition lists.h:1005
pointer operator->() const
Definition lists.h:940
U value_type
Type of value "pointed to" by the iterator.
Definition lists.h:238
bool operator!=(const double_list_iterator &other) const
Definition lists.h:996
std::forward_iterator_tag iterator_category
Category of iterator.
Definition lists.h:263
iterator_pointer get_iterator_pointer() const
Definition lists.h:1012
bool operator==(const double_list_iterator &other) const
Definition lists.h:988
U * pointer
Type of pointer to object "pointed to" by the iterator.
Definition lists.h:243
double_list_iterator & operator++()
Definition lists.h:954
constexpr double_list_iterator()
Definition lists.h:911
ptrdiff_t difference_type
Type of pointer difference.
Definition lists.h:258
iterator_pointer node_
Pointer to intrusive node.
Definition lists.h:350
U & reference
Type of reference to object "pointed to" by the iterator.
Definition lists.h:248
Circular double linked list of nodes.
Definition lists.h:513
double_list()
Construct a list.
Definition lists.cpp:155
~double_list()
Destruct the list.
Definition lists.cpp:168
Template for an intrusive list iterator.
Definition lists.h:569
bool operator!=(const intrusive_list_iterator &other) const
Definition lists.h:1156
std::forward_iterator_tag iterator_category
Category of iterator.
Definition lists.h:605
intrusive_list_iterator & operator++()
Definition lists.h:1114
iterator_pointer node_
Pointer to intrusive node.
Definition lists.h:692
N * iterator_pointer
Type of reference to the iterator internal pointer.
Definition lists.h:595
ptrdiff_t difference_type
Type of pointer difference.
Definition lists.h:600
iterator_pointer get_iterator_pointer() const
Definition lists.h:1181
U value_type
Type of value "pointed to" by the iterator.
Definition lists.h:580
intrusive_list_iterator & operator--()
Definition lists.h:1131
pointer get_pointer(void) const
Get the object node from the intrusive node.
Definition lists.h:1164
reference operator*() const
Definition lists.h:1107
bool operator==(const intrusive_list_iterator &other) const
Definition lists.h:1148
U & reference
Type of reference to object "pointed to" by the iterator.
Definition lists.h:590
U * pointer
Type of pointer to object "pointed to" by the iterator.
Definition lists.h:585
List of intrusive nodes.
Definition lists.h:721
ptrdiff_t difference_type
Definition lists.h:727
pointer get_pointer(iterator_pointer node) const
Definition lists.h:1261
~intrusive_list()
Destruct the list.
Definition lists.h:1207
pointer unlink_tail(void)
Unlink the last element from the list.
Definition lists.h:1291
pointer unlink_head(void)
Unlink the first element from the list.
Definition lists.h:1278
intrusive_list()
Construct an intrusive list.
Definition lists.h:1190
iterator end() const
Iterator begin.
Definition lists.h:1252
N * iterator_pointer
Type of reference to the iterator internal pointer.
Definition lists.h:734
iterator begin()
Iterator begin.
Definition lists.h:1239
void link(reference node)
Add a node to the tail of the list.
Definition lists.h:1214
Statically allocated circular double linked list of nodes.
Definition lists.h:366
static_double_list_links head_
A list node used to point to head and tail.
Definition lists.h:498
void insert_after(static_double_list_links &node, static_double_list_links *after)
Insert a new node after existing node.
Definition lists.cpp:123
bool empty(void) const
Check if the list is empty.
Definition lists.h:1049
~static_double_list()
Destruct the list.
Definition lists.h:1036
void clear(void)
Clear the list.
Definition lists.cpp:116
volatile static_double_list_links * tail(void) const
Get the list tail.
Definition lists.h:1062
volatile static_double_list_links * head(void) const
Get the list head.
Definition lists.h:1056
bool uninitialized(void) const
Check if the list is uninitialised.
Definition lists.h:1042
static_double_list()
Construct a list.
Definition lists.h:1025
int link(const char *existing, const char *_new)
System namespace.