21namespace swoc {
inline namespace SWOC_VERSION_NS {
71template <
typename L>
class IntrusiveDList {
72 friend class iterator;
75 using self_type = IntrusiveDList;
80 using value_type =
typename std::remove_pointer<
81 typename std::remove_reference<
typename std::invoke_result<
decltype(L::next_ptr), std::nullptr_t>::type>::type>::type;
84 class const_iterator {
85 using self_type = const_iterator;
86 friend class IntrusiveDList;
89 using list_type = IntrusiveDList;
90 using value_type =
const typename list_type::value_type;
92 using iterator_category = std::bidirectional_iterator_tag;
93 using pointer = value_type *;
94 using reference = value_type &;
95 using difference_type = int;
103 self_type &operator++();
108 self_type &operator--();
113 self_type operator++(
int);
118 self_type operator--(
int);
122 value_type &operator*()
const;
126 value_type *operator->()
const;
131 operator value_type *()
const;
142 bool has_prev()
const;
146 bool has_next()
const;
151 bool has_predecessor()
const;
158 bool has_successor()
const;
163 list_type *_list{
nullptr};
164 typename list_type::value_type *_v{
nullptr};
167 const_iterator(
const list_type *list, value_type *v);
171 class iterator :
public const_iterator {
172 using self_type = iterator;
173 using super_type = const_iterator;
175 friend class IntrusiveDList;
178 using list_type = IntrusiveDList;
179 using value_type =
typename list_type::value_type;
181 using iterator_category = std::bidirectional_iterator_tag;
182 using pointer = value_type *;
183 using reference = value_type &;
191 self_type &operator++();
196 self_type &operator--();
201 self_type operator++(
int);
206 self_type operator--(
int);
210 value_type &operator*()
const;
214 value_type *operator->()
const;
219 operator value_type *()
const;
223 iterator(list_type *list, value_type *v);
227 IntrusiveDList() =
default;
229 IntrusiveDList(self_type
const &that) =
delete;
232 IntrusiveDList(self_type &&that);
235 self_type &operator=(
const self_type &that) =
delete;
238 self_type &operator=(self_type &&that);
246 bool contains(
const value_type *v)
const;
250 self_type &prepend(value_type *v);
254 self_type &append(value_type *v);
258 value_type *take_head();
262 value_type *take_tail();
267 self_type &insert_after(value_type *target, value_type *v);
272 self_type &insert_before(value_type *target, value_type *v);
277 self_type &insert_after(iterator
const &target, value_type *v);
282 self_type &insert_before(iterator
const &target, value_type *v);
286 value_type *erase(value_type *v);
290 iterator erase(
const iterator &loc);
295 iterator erase(
const iterator &start,
const iterator &limit);
304 iterator nth(
unsigned n);
313 self_type take_prefix(
unsigned n);
322 self_type split_prefix(
unsigned n);
331 self_type take_suffix(
unsigned n);
340 self_type split_suffix(
unsigned n);
349 self_type &append(self_type &src);
358 self_type &prepend(self_type &src);
366 self_type &insert_after(value_type *target, self_type &src);
374 self_type &insert_before(value_type *target, self_type &src);
382 self_type &insert_after(iterator
const &target, self_type &src);
390 self_type &insert_before(iterator
const &target, self_type &src);
398 size_t count()
const;
404 const_iterator begin()
const;
410 const_iterator end()
const;
420 iterator iterator_for(value_type *v);
422 const_iterator iterator_for(
const value_type *v)
const;
427 const value_type *head()
const;
432 const value_type *tail()
const;
437 template <
typename F> self_type &apply(F &&f);
440 value_type *_head{
nullptr};
441 value_type *_tail{
nullptr};
465template <
typename T, T *(T::*NEXT) = &T::_next, T *(T::*PREV) = &T::_prev>
struct IntrusiveLinkage {
466 static T *&next_ptr(T *thing);
467 static T *&prev_ptr(T *thing);
470template <
typename T, T *(T::*NEXT), T *(T::*PREV)>
472IntrusiveLinkage<T, NEXT, PREV>::next_ptr(T *thing) {
476template <
typename T, T *(T::*NEXT), T *(T::*PREV)>
478IntrusiveLinkage<T, NEXT, PREV>::prev_ptr(T *thing) {
508template <
typename T,
typename P>
538template <
typename T,
typename L>
struct IntrusiveLinkageRebind {
539 static T *&next_ptr(T *thing);
540 static T *&prev_ptr(T *thing);
543template <
typename T,
typename L>
545IntrusiveLinkageRebind<T, L>::next_ptr(T *thing) {
546 return ptr_ref_cast<T>(L::next_ptr(thing));
549template <
typename T,
typename L>
551IntrusiveLinkageRebind<T, L>::prev_ptr(T *thing) {
552 return ptr_ref_cast<T>(L::prev_ptr(thing));
555template <
typename T>
struct IntrusiveLinks {
560template <typename T, IntrusiveLinks<T>(T::*links)>
struct IntrusiveLinkDescriptor {
561 static T *&next_ptr(T *thing);
562 static T *&prev_ptr(T *thing);
567template <
typename L> IntrusiveDList<L>::const_iterator::const_iterator() {}
570IntrusiveDList<L>::const_iterator::const_iterator(
const list_type *list, value_type *v)
571 : _list(const_cast<list_type *>(list)), _v(const_cast<typename list_type::value_type *>(v)) {}
573template <
typename L> IntrusiveDList<L>::iterator::iterator() {}
575template <
typename L> IntrusiveDList<L>::iterator::iterator(list_type *list, value_type *v) : super_type(list, v) {}
579IntrusiveDList<L>::const_iterator::operator++() -> self_type & {
580 _v = L::next_ptr(_v);
586IntrusiveDList<L>::iterator::operator++() -> self_type & {
587 this->super_type::operator++();
593IntrusiveDList<L>::const_iterator::operator++(
int) -> self_type {
594 self_type tmp(*
this);
601IntrusiveDList<L>::iterator::operator++(
int) -> self_type {
602 self_type tmp(*
this);
609IntrusiveDList<L>::const_iterator::operator--() -> self_type & {
611 _v = L::prev_ptr(_v);
620IntrusiveDList<L>::iterator::operator--() -> self_type & {
621 this->super_type::operator--();
627IntrusiveDList<L>::const_iterator::operator--(
int) -> self_type {
628 self_type tmp(*
this);
635IntrusiveDList<L>::iterator::operator--(
int) -> self_type {
636 self_type tmp(*
this);
643IntrusiveDList<L>::const_iterator::operator->() const -> value_type * {
649IntrusiveDList<L>::iterator::operator->() const -> value_type * {
650 return super_type::_v;
653template <
typename L> IntrusiveDList<L>::const_iterator::operator value_type *()
const {
659IntrusiveDList<L>::const_iterator::operator*() const -> value_type & {
665IntrusiveDList<L>::iterator::operator*() const -> value_type & {
666 return *super_type::_v;
669template <
typename L> IntrusiveDList<L>::iterator::operator value_type *()
const {
670 return super_type::_v;
676IntrusiveDList<L>::IntrusiveDList(self_type &&that) : _head(that._head), _tail(that._tail), _count(that._count) {
682IntrusiveDList<L>::empty()
const {
683 return _head ==
nullptr;
688IntrusiveDList<L>::contains(
const value_type *v)
const {
689 for (
auto thing = _head; thing; thing = L::next_ptr(thing)) {
698IntrusiveDList<L>::const_iterator::operator==(self_type
const &that)
const {
699 return this->_v == that._v;
704IntrusiveDList<L>::const_iterator::operator!=(self_type
const &that)
const {
705 return this->_v != that._v;
710IntrusiveDList<L>::const_iterator::has_predecessor()
const {
711 return _v ?
nullptr != L::prev_ptr(_v) : !_list->empty();
716IntrusiveDList<L>::const_iterator::has_prev()
const {
717 return _v ?
nullptr != L::prev_ptr(_v) : !_list->empty();
722IntrusiveDList<L>::const_iterator::has_successor()
const {
723 return _v &&
nullptr != L::next_ptr(_v);
728IntrusiveDList<L>::const_iterator::has_next()
const {
729 return nullptr != _v;
734IntrusiveDList<L>::prepend(value_type *v) -> self_type & {
735 L::prev_ptr(v) =
nullptr;
736 if (
nullptr != (L::next_ptr(v) = _head)) {
737 L::prev_ptr(_head) = v;
748IntrusiveDList<L>::append(value_type *v) -> self_type & {
749 L::next_ptr(v) =
nullptr;
750 if (
nullptr != (L::prev_ptr(v) = _tail)) {
751 L::next_ptr(_tail) = v;
762IntrusiveDList<L>::take_head() -> value_type * {
763 value_type *zret = _head;
765 if (
nullptr == (_head = L::next_ptr(_head))) {
768 L::prev_ptr(_head) =
nullptr;
770 L::next_ptr(zret) = L::prev_ptr(zret) =
nullptr;
778IntrusiveDList<L>::take_tail() -> value_type * {
779 value_type *zret = _tail;
781 if (
nullptr == (_tail = L::prev_ptr(_tail))) {
784 L::next_ptr(_tail) =
nullptr;
786 L::next_ptr(zret) = L::prev_ptr(zret) =
nullptr;
794IntrusiveDList<L>::insert_after(value_type *target, value_type *v) -> self_type & {
796 if (
nullptr != (L::next_ptr(v) = L::next_ptr(target))) {
797 L::prev_ptr(L::next_ptr(v)) = v;
798 }
else if (_tail == target) {
801 L::prev_ptr(v) = target;
802 L::next_ptr(target) = v;
813IntrusiveDList<L>::insert_after(iterator
const &target, value_type *v) -> self_type & {
814 return this->insert_after(target._v, v);
819IntrusiveDList<L>::insert_before(value_type *target, value_type *v) -> self_type & {
821 if (
nullptr != (L::prev_ptr(v) = L::prev_ptr(target))) {
822 L::next_ptr(L::prev_ptr(v)) = v;
823 }
else if (target == _head) {
826 L::next_ptr(v) = target;
827 L::prev_ptr(target) = v;
838IntrusiveDList<L>::insert_before(iterator
const &target, value_type *v) -> self_type & {
839 return this->insert_before(target._v, v);
844IntrusiveDList<L>::insert_after(value_type *target, self_type &src) -> self_type & {
845 if (target && src._count > 0) {
846 if (_tail == target) {
849 L::next_ptr(src._tail) = L::next_ptr(target);
850 L::prev_ptr(L::next_ptr(src._tail)) = src._tail;
852 L::prev_ptr(src._head) = target;
853 L::next_ptr(target) = src._head;
855 _count += src._count;
864IntrusiveDList<L>::insert_after(iterator
const &target, self_type &src) -> self_type & {
865 return this->insert_after(target._v, src);
870IntrusiveDList<L>::insert_before(value_type *target, self_type &src) -> self_type & {
871 if (target && src._count > 0) {
872 if (_head == target) {
875 L::prev_ptr(src._head) = L::prev_ptr(target);
876 L::next_ptr(L::prev_ptr(target)) = src._head;
878 L::next_ptr(src._tail) = target;
879 L::prev_ptr(target) = src._tail;
881 _count += src._count;
890IntrusiveDList<L>::insert_before(iterator
const &target, self_type &src) -> self_type & {
891 return this->insert_before(target._v, src);
896IntrusiveDList<L>::erase(value_type *v) -> value_type * {
897 value_type *zret{
nullptr};
899 if (L::prev_ptr(v)) {
900 L::next_ptr(L::prev_ptr(v)) = L::next_ptr(v);
902 if (L::next_ptr(v)) {
903 zret = L::next_ptr(v);
904 L::prev_ptr(L::next_ptr(v)) = L::prev_ptr(v);
907 _head = L::next_ptr(v);
910 _tail = L::prev_ptr(v);
912 L::prev_ptr(v) = L::next_ptr(v) =
nullptr;
920IntrusiveDList<L>::erase(
const iterator &loc) -> iterator {
921 return this->iterator_for(this->erase(loc._v));
926IntrusiveDList<L>::erase(
const iterator &first,
const iterator &limit) -> iterator {
927 value_type *spot = first;
928 value_type *prev{L::prev_ptr(spot)};
930 L::next_ptr(prev) = limit;
936 if (
nullptr == limit) {
939 L::prev_ptr(limit) = prev;
942 while (spot != limit) {
943 value_type *target{spot};
944 spot = L::next_ptr(spot);
945 L::prev_ptr(target) = L::next_ptr(target) =
nullptr;
948 return {limit._v,
this};
953IntrusiveDList<L>::operator=(self_type &&that) -> self_type & {
955 this->_head = that._head;
956 this->_tail = that._tail;
957 this->_count = that._count;
965IntrusiveDList<L>::count()
const {
971IntrusiveDList<L>::begin() const -> const_iterator {
972 return const_iterator{
this, _head};
977IntrusiveDList<L>::begin() -> iterator {
978 return iterator{
this, _head};
983IntrusiveDList<L>::end() const -> const_iterator {
984 return const_iterator{
this,
nullptr};
989IntrusiveDList<L>::end() -> iterator {
990 return iterator{
this,
nullptr};
995IntrusiveDList<L>::iterator_for(value_type *v) -> iterator {
996 return iterator{
this, v};
1001IntrusiveDList<L>::iterator_for(
const value_type *v)
const -> const_iterator {
1002 return const_iterator{
this, v};
1005template <
typename L>
1007IntrusiveDList<L>::tail() -> value_type * {
1011template <
typename L>
1013IntrusiveDList<L>::tail() const -> const value_type * {
1017template <
typename L>
1019IntrusiveDList<L>::head() -> value_type * {
1023template <
typename L>
1025IntrusiveDList<L>::head() const -> const value_type * {
1029template <
typename L>
1031IntrusiveDList<L>::clear() -> self_type & {
1032 _head = _tail =
nullptr;
1037template <
typename L>
1039IntrusiveDList<L>::nth(
unsigned int n) -> iterator {
1045 if (n < _count / 2) {
1048 spot = L::next_ptr(spot);
1052 unsigned idx = _count - 1;
1054 spot = L::prev_ptr(spot);
1057 return iterator_for(spot);
1060template <
typename L>
1062IntrusiveDList<L>::take_prefix(
unsigned int n) -> self_type {
1068 return std::move(*
this);
1074 value_type *spot = this->nth(n);
1078 zret._tail = L::prev_ptr(spot);
1079 L::next_ptr(zret._tail) =
nullptr;
1083 L::prev_ptr(_head) =
nullptr;
1088template <
typename L>
1090IntrusiveDList<L>::split_prefix(
unsigned int n) -> self_type {
1092 return this->take_prefix(n);
1097template <
typename L>
1099IntrusiveDList<L>::take_suffix(
unsigned int n) -> self_type {
1105 return std::move(*
this);
1111 value_type *spot = this->nth(_count - n - 1);
1114 zret._head = L::next_ptr(spot);
1115 L::prev_ptr(zret._head) =
nullptr;
1120 L::next_ptr(_tail) =
nullptr;
1125template <
typename L>
1127IntrusiveDList<L>::split_suffix(
unsigned int n) -> self_type {
1129 return this->take_suffix(n);
1134template <
typename L>
1136IntrusiveDList<L>::prepend(IntrusiveDList::self_type &src) -> self_type & {
1137 if (src._count > 0) {
1139 *
this = std::move(src);
1141 L::prev_ptr(_head) = src._tail;
1142 L::next_ptr(src._tail) = _head;
1143 _count += src._count;
1151template <
typename L>
1153IntrusiveDList<L>::append(IntrusiveDList::self_type &src) -> self_type & {
1154 if (src._count > 0) {
1156 *
this = std::move(src);
1158 L::next_ptr(_tail) = src._head;
1159 L::prev_ptr(src._head) = _tail;
1160 _count += src._count;
1177template <
typename L,
typename F>
1179Intrusive_DList_Apply(IntrusiveDList<L> &list, F &&f)
1180 ->
decltype(f(*
static_cast<typename IntrusiveDList<L>::value_type *
>(
nullptr)), list) {
1181 return list.apply([&f](
typename IntrusiveDList<L>::value_type *v) {
return f(*v); });
1184template <
typename L,
typename F>
1186Intrusive_DList_Apply(IntrusiveDList<L> &list, F &&f)
1187 ->
decltype(f(
static_cast<typename IntrusiveDList<L>::value_type *
>(
nullptr)), list) {
1188 auto spot{list.begin()};
1189 auto limit{list.end()};
1190 while (spot != limit) {
1197template <
typename L>
1198template <
typename F>
1200IntrusiveDList<L>::apply(F &&f) -> self_type & {
1201 return detail::Intrusive_DList_Apply(*
this, f);
bool operator==(RBNode *n, RBNode::Color c)
For template deduction guides.
bool operator!=(IP4Addr const &lhs, IP4Addr const &rhs)