The lists-inlines.h
File Reference
C++ header file with the inline implementations for the µOS++ lists methods. More...
Namespaces Index
namespace | micro_os_plus |
The primary namespace for the µOS++ framework. More... | |
namespace | micro_os_plus::utils |
The µOS++ utilities definitions. More... | |
Description
C++ header file with the inline implementations for the µOS++ lists methods.
The inlines.h
header provides the C++ inline implementations for the µOS++ Intrusive Lists classes.
Class definitions are located in lists.h. Inline methods are separated into this file to improve project structure and maintainability.
File Listing
The file content with the documentation metadata removed is:
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
23
24#ifndef MICRO_OS_PLUS_UTILS_LISTS_INLINES_H_
25#define MICRO_OS_PLUS_UTILS_LISTS_INLINES_H_
26
27// ----------------------------------------------------------------------------
28
29#ifdef __cplusplus
30
31// ----------------------------------------------------------------------------
32
33#if defined(__GNUC__)
34#pragma GCC diagnostic push
35
36#pragma GCC diagnostic ignored "-Waggregate-return"
37#if defined(__clang__)
38#pragma clang diagnostic ignored "-Wc++98-compat"
39#endif
40#endif
41
42// ----------------------------------------------------------------------------
43
44namespace micro_os_plus::utils
45{
46 // ==========================================================================
47
75 constexpr double_list_links_base::double_list_links_base ()
76 {
77 // Must be empty! No members must be changed by this constructor!
78 }
79
93 constexpr double_list_links_base::~double_list_links_base ()
94 {
95 // Must be empty! No members must be changed by this constructor!
96 }
97
112 constexpr void
114 {
115 previous_ = this;
116 next_ = this;
117 }
118
119#pragma GCC diagnostic push
120
121#if defined(__GNUC__) && !defined(__clang__)
122#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
123#endif
124
136 constexpr double_list_links_base*
137 double_list_links_base::next (void) const
138 {
139 return next_;
140 }
141
153 constexpr double_list_links_base*
154 double_list_links_base::previous (void) const
155 {
156 return previous_;
157 }
158
159#pragma GCC diagnostic pop
160
161 // ==========================================================================
162
189 constexpr static_double_list_links::static_double_list_links ()
190 {
191 // Must be empty! No members must be changed by this constructor!
192 }
193
194#pragma GCC diagnostic push
195
196#if defined(__clang__)
197#pragma GCC diagnostic ignored "-Wdocumentation-unknown-command"
198#endif
219#pragma GCC diagnostic pop
220 constexpr static_double_list_links::~static_double_list_links ()
221 {
222 // The goal is to revert the content to a state similar to the
223 // statically initialised state (BSS zero).
224 // Unfortunately GCC does not honour this.
225 // next_ = nullptr;
226 // previous_ = nullptr;
227 }
228
229 // ==========================================================================
230
254 constexpr double_list_links::double_list_links ()
255 {
256 // For regular (non static) classes the members
257 // must be explicitly initialised.
258 initialize ();
259 }
260
266 constexpr double_list_links::~double_list_links ()
267 {
268 }
269
270 // ==========================================================================
271
284 template <class T, class N, class U>
285 constexpr double_list_iterator<T, N, U>::double_list_iterator () : node_{}
286 {
287 }
288
297 template <class T, class N, class U>
299 iterator_pointer const node)
300 : node_{ node }
301 {
302 }
303
304#if 0
305 template <class T, class N, class U>
306 constexpr double_list_iterator<T, N, U>::double_list_iterator (
307 reference element)
308 : node_{ &(element.*MP) }
309 {
310 static_assert (std::is_convertible<U, T>::value == true,
311 "U must be implicitly convertible to T!");
312 }
313#endif
314
323 template <class T, class N, class U>
324 constexpr typename double_list_iterator<T, N, U>::pointer
326 {
327 return get_pointer ();
328 }
329
341 template <class T, class N, class U>
342 constexpr typename double_list_iterator<T, N, U>::reference
344 {
345 return *get_pointer ();
346 }
347
356 template <class T, class N, class U>
357 constexpr double_list_iterator<T, N, U>&
359 {
361 return *this;
362 }
363
372 template <class T, class N, class U>
373 constexpr double_list_iterator<T, N, U>
375 {
376 const auto tmp = *this;
377 node_ = static_cast<iterator_pointer> (node_->next);
378 return tmp;
379 }
380
389 template <class T, class N, class U>
390 constexpr double_list_iterator<T, N, U>&
392 {
393 node_ = static_cast<iterator_pointer> (node_->previous);
394 return *this;
395 }
396
405 template <class T, class N, class U>
406 constexpr double_list_iterator<T, N, U>
408 {
409 const auto tmp = *this;
410 node_ = static_cast<iterator_pointer> (node_->previous);
411 return tmp;
412 }
413
422 template <class T, class N, class U>
423 constexpr bool
425 const double_list_iterator& other) const
426 {
428 }
429
438 template <class T, class N, class U>
439 constexpr bool
441 const double_list_iterator& other) const
442 {
444 }
445
453 template <class T, class N, class U>
454 constexpr typename double_list_iterator<T, N, U>::iterator_pointer
456 {
457 return node_;
458 }
459
460 // ==========================================================================
461
485 template <class T, class L>
487 {
488#if defined(MICRO_OS_PLUS_TRACE_UTILS_LISTS_CONSTRUCT)
489 trace::printf ("%s() @%p \n", __func__, this);
490#endif
491
492 if constexpr (is_statically_allocated::value)
493 {
494 // By all means, do not add any code to clear the pointers, since
495 // the links node was statically initialised.
496 }
497 else
498 {
499 clear ();
500 }
501 }
502
515 template <class T, class L>
516 constexpr double_list<T, L>::~double_list ()
517 {
518#if defined(MICRO_OS_PLUS_TRACE_UTILS_LISTS_CONSTRUCT)
519 trace::printf ("%s() @%p \n", __func__, this);
520#endif
521
522 // Perhaps enable it for non statically allocated lists.
523 // assert (empty ());
524#if defined(MICRO_OS_PLUS_TRACE_UTILS_LISTS)
525 if (!empty ())
526 {
527 trace::printf ("%s() @%p list not empty\n", __func__, this);
528 }
529#endif
530 }
531
540 template <class T, class L>
541 bool
542 double_list<T, L>::uninitialized (void) const
543 {
544 if constexpr (is_statically_allocated::value)
545 {
546 return links_.uninitialized ();
547 }
548 else
549 {
550 return false;
551 }
552 }
553
566 template <class T, class L>
567 void
569 {
570 if constexpr (is_statically_allocated::value)
571 {
572 links_.initialize_once ();
573 }
574 }
575
583 template <class T, class L>
584 bool
585 double_list<T, L>::empty (void) const
586 {
587 // If the links node is not linked, the list is empty.
588 return !links_.linked ();
589 }
590
599 template <class T, class L>
600 void
601 double_list<T, L>::clear (void)
602 {
603#if defined(MICRO_OS_PLUS_TRACE_UTILS_LISTS)
604 trace::printf ("%s() @%p\n", __func__, this);
605#endif
606 links_.initialize ();
607 }
608
617 template <class T, class L>
618 constexpr typename double_list<T, L>::pointer
619 double_list<T, L>::head (void) const
620 {
622 }
623
632 template <class T, class L>
633 constexpr typename double_list<T, L>::pointer
634 double_list<T, L>::tail (void) const
635 {
636 return reinterpret_cast<pointer> (links_.previous ());
637 }
638
647 template <class T, class L>
648 void
650 {
651 if constexpr (is_statically_allocated::value)
652 {
653 assert (!links_.uninitialized ());
654 }
655
656 // Add new node at the end of the list.
657 tail ()->link_next (&node);
658 }
659
668 template <class T, class L>
669 void
671 {
672 if constexpr (is_statically_allocated::value)
673 {
674 assert (!links_.uninitialized ());
675 }
676
677 // Add the new node at the head of the list.
678 head ()->link_previous (&node);
679 }
680
689 template <class T, class L>
690 typename double_list<T, L>::iterator
691 double_list<T, L>::begin () const
692 {
693 if constexpr (is_statically_allocated::value)
694 {
695 assert (!links_.uninitialized ());
696 }
697
698 return iterator{ static_cast<iterator_pointer> (links_.next ()) };
699 }
700
709 template <class T, class L>
710 typename double_list<T, L>::iterator
711 double_list<T, L>::end () const
712 {
713 // The assert would probably be redundant, since it was
714 // already tested in `begin()`.
715
716 return iterator{ reinterpret_cast<iterator_pointer> (
717 const_cast<links_type*> (&links_)) };
718 }
719
720 // ==========================================================================
721
734 template <class T, class N, N T::* MP, class U>
736 : node_{}
737 {
738 }
739
748 template <class T, class N, N T::* MP, class U>
750 N* const node)
751 : node_{ node }
752 {
753 }
754
763 template <class T, class N, N T::* MP, class U>
765 reference element)
766 : node_{ &(element.*MP) }
767 {
768 static_assert (std::is_convertible<U, T>::value == true,
769 "U must be implicitly convertible to T!");
770 }
771
780 template <class T, class N, N T::* MP, class U>
781 inline typename intrusive_list_iterator<T, N, MP, U>::pointer
783 {
784 return get_pointer ();
785 }
786
798 template <class T, class N, N T::* MP, class U>
799 inline typename intrusive_list_iterator<T, N, MP, U>::reference
801 {
802 return *get_pointer ();
803 }
804
813 template <class T, class N, N T::* MP, class U>
814 inline intrusive_list_iterator<T, N, MP, U>&
816 {
817 node_ = static_cast<iterator_pointer> (node_->next ());
818 return *this;
819 }
820
829 template <class T, class N, N T::* MP, class U>
830 inline intrusive_list_iterator<T, N, MP, U>
832 {
833 const auto tmp = *this;
834 node_ = static_cast<iterator_pointer> (node_->next ());
835 return tmp;
836 }
837
846 template <class T, class N, N T::* MP, class U>
847 inline intrusive_list_iterator<T, N, MP, U>&
849 {
850 node_ = static_cast<iterator_pointer> (node_->previous ());
851 return *this;
852 }
853
862 template <class T, class N, N T::* MP, class U>
865 {
866 const auto tmp = *this;
867 node_ = static_cast<iterator_pointer> (node_->previous ());
868 return tmp;
869 }
870
879 template <class T, class N, N T::* MP, class U>
880 inline bool
882 const intrusive_list_iterator& other) const
883 {
885 }
886
895 template <class T, class N, N T::* MP, class U>
896 inline bool
898 const intrusive_list_iterator& other) const
899 {
901 }
902
912 template <class T, class N, N T::* MP, class U>
913 inline typename intrusive_list_iterator<T, N, MP, U>::pointer
914 intrusive_list_iterator<T, N, MP, U>::get_pointer (void) const
915 {
916 // static_assert(std::is_convertible<U, T>::value == true, "U must be
917 // implicitly convertible to T!");
918
919 // Compute the distance between the member intrusive link
920 // node and the class begin.
921 const auto offset = reinterpret_cast<difference_type> (
922 &(static_cast<T*> (nullptr)->*MP));
923
924 // Compute the address of the object which includes the
925 // intrusive node, by adjusting down the node address.
926 return reinterpret_cast<pointer> (reinterpret_cast<difference_type> (node_)
927 - offset);
928 }
929
936 template <class T, class N, N T::* MP, class U>
937 inline typename intrusive_list_iterator<T, N, MP, U>::iterator_pointer
939 {
940 return node_;
941 }
942
943 // ==========================================================================
944
960 template <class T, class N, N T::* MP, class L, class U>
961 constexpr intrusive_list<T, N, MP, L, U>::intrusive_list ()
962 {
963 }
964
972 template <class T, class N, N T::* MP, class L, class U>
973 constexpr intrusive_list<T, N, MP, L, U>::~intrusive_list ()
974 {
975 }
976
988 template <class T, class N, N T::* MP, class L, class U>
989 void
991 {
992 return double_list<N, L>::initialize_once ();
993 }
994
1002 template <class T, class N, N T::* MP, class L, class U>
1003 constexpr bool
1004 intrusive_list<T, N, MP, L, U>::empty (void) const
1005 {
1006 return double_list<N, L>::empty ();
1007 }
1008
1018 template <class T, class N, N T::* MP, class L, class U>
1019 void
1021 {
1022 // The assert(links_.initialised()) is checked by the L class.
1023
1024 // Compute the distance between the member intrusive link
1025 // node and the class begin.
1026 const auto offset = reinterpret_cast<difference_type> (
1027 &(static_cast<T*> (nullptr)->*MP));
1028
1029 // Add thread intrusive node at the end of the list.
1030 (const_cast<N*> (double_list<N, L>::tail ()))
1031 ->link_next (reinterpret_cast<N*> (
1032 reinterpret_cast<difference_type> (&node) + offset));
1033 }
1034
1044 template <class T, class N, N T::* MP, class L, class U>
1045 void
1047 {
1048 // The assert(links_.initialised()) is checked by the L class.
1049
1050 // Compute the distance between the member intrusive link
1051 // node and the class begin.
1052 const auto offset = reinterpret_cast<difference_type> (
1053 &(static_cast<T*> (nullptr)->*MP));
1054
1055 // Add thread intrusive node at the end of the list.
1056 (const_cast<N*> (double_list<N, L>::head ()))
1057 ->link_previous (reinterpret_cast<N*> (
1058 reinterpret_cast<difference_type> (&node) + offset));
1059 }
1060
1061#if defined(__GNUC__)
1062#pragma GCC diagnostic push
1063#pragma GCC diagnostic ignored "-Waggregate-return"
1064#endif
1065
1074 template <class T, class N, N T::* MP, class L, class U>
1075 inline typename intrusive_list<T, N, MP, L, U>::iterator
1077 {
1078 // The assert(links_.initialised()) is checked by the L class.
1079
1080 return iterator{ static_cast<iterator_pointer> (
1081 double_list<N, L>::links_.next ()) };
1082 }
1083
1092 template <class T, class N, N T::* MP, class L, class U>
1093 inline typename intrusive_list<T, N, MP, L, U>::iterator
1094 intrusive_list<T, N, MP, L, U>::end () const
1095 {
1096 // The assert would probably be redundant, since it was
1097 // already tested in `begin()`.
1098
1099 using head_type_ = typename double_list<N, L>::links_type;
1100 return iterator{ reinterpret_cast<iterator_pointer> (
1101 const_cast<head_type_*> (double_list<N, L>::links_pointer ())) };
1102 }
1103
1104#if defined(__GNUC__)
1105#pragma GCC diagnostic pop
1106#endif
1107
1117 template <class T, class N, N T::* MP, class L, class U>
1118 inline typename intrusive_list<T, N, MP, L, U>::pointer
1120 {
1121 // static_assert(std::is_convertible<U, T>::value == true, "U must be
1122 // implicitly convertible to T!");
1123
1124 // Compute the distance between the member intrusive link
1125 // node and the class begin.
1126 const auto offset = reinterpret_cast<difference_type> (
1127 &(static_cast<T*> (nullptr)->*MP));
1128
1129 // Compute the address of the object which includes the
1130 // intrusive node, by adjusting down the node address.
1131 return reinterpret_cast<pointer> (reinterpret_cast<difference_type> (node)
1132 - offset);
1133 }
1134
1143 template <class T, class N, N T::* MP, class L, class U>
1144 typename intrusive_list<T, N, MP, L, U>::pointer
1146 {
1147 // No assert here, treat empty link unlinks as nop.
1148
1149 // The first element in the list.
1150 iterator_pointer it
1151 = static_cast<iterator_pointer> (double_list<N, L>::links_.next ());
1152 it->unlink ();
1153
1154 return get_pointer (it);
1155 }
1156
1165 template <class T, class N, N T::* MP, class L, class U>
1166 typename intrusive_list<T, N, MP, L, U>::pointer
1168 {
1169 // No assert here, treat empty link unlinks as nop.
1170
1171 // The last element in the list.
1172 iterator_pointer it = static_cast<iterator_pointer> (
1173 double_list<N, L>::links_.previous ());
1174 it->unlink ();
1175
1176 return get_pointer (it);
1177 }
1178
1179 // ==========================================================================
1180} // namespace micro_os_plus::utils
1181
1182#if defined(__GNUC__)
1183#pragma GCC diagnostic pop
1184#endif
1185
1186// ----------------------------------------------------------------------------
1187
1188#endif // __cplusplus
1189
1190// ----------------------------------------------------------------------------
1191
1192#endif // MICRO_OS_PLUS_UTILS_LISTS_INLINES_H_
1193
1194// ----------------------------------------------------------------------------
Generated via docusaurus-plugin-doxygen by Doxygen 1.13.2