28#ifndef OZZ_OZZ_BASE_CONTAINERS_INTRUSIVE_LIST_H_
29#define OZZ_OZZ_BASE_CONTAINERS_INTRUSIVE_LIST_H_
76template <LinkMode::Value _LinkMode = LinkMode::kSafe,
int _Unique = 0>
78 static const LinkMode::Value kLinkMode = _LinkMode;
90template <
typename _Ty,
typename _Option = Option<>>
97class IntrusiveNodeList;
110 bool is_linked()
const {
return prev_ !=
this; }
119 return &_list == list_;
140 template <
typename,
typename>
145 void insert(
Node* _where);
152 bool debug_is_end_node()
const {
159 void operator=(
const Node&);
192 bool empty()
const {
return end_.next_ == &end_; }
212 typedef size_t size_type;
215 Node& begin_node() {
return *end_.next_; }
216 const Node& begin_node()
const {
return *end_.next_; }
219 Node& last_node() {
return *end_.prev_; }
220 const Node& last_node()
const {
return *end_.prev_; }
223 Node& end_node() {
return end_; }
224 const Node& end_node()
const {
return end_; }
227 void link_front(
Node* _node) { _node->insert(end_.next_); }
230 void link_back(
Node* _node) { _node->insert(&end_); }
233 void _insert(
Node* _node,
Node* _where) { _node->insert(_where); }
240 bool debug_is_range_valid(
const Node& _begin,
const Node& _end) {
241 if (!_begin.debug_is_linked_in(*
this) || !_end.debug_is_linked_in(*
this)) {
244 const Node* node = &_begin;
245 while (node != &_end) {
246 if (node == &_begin.list_->end_) {
259 void _erase(
Node* _begin,
Node* _end);
262 template <
typename _Pred>
266 template <
typename _Pred>
270 template <
typename _Pred>
274 template <
typename _Pred>
275 void _sort(_Pred _pred);
278 template <
typename _Pred>
279 bool _is_ordered(_Pred _pred)
const;
282 template <
typename _Pred>
283 void _remove_if(_Pred _pred);
287 template <
typename,
typename>
297template <
typename _List>
299 typedef typename _List::pointer pointer;
300 typedef typename _List::reference reference;
302 typedef typename _List::Hook Hook;
303 enum { kReverse = 0 };
307template <
typename _List>
309 typedef typename _List::const_pointer pointer;
310 typedef typename _List::const_reference reference;
312 typedef const typename _List::Hook Hook;
313 enum { kReverse = 0 };
317template <
typename _List>
319 typedef typename _List::pointer pointer;
320 typedef typename _List::reference reference;
322 typedef typename _List::Hook Hook;
323 enum { kReverse = 1 };
327template <
typename _List>
329 typedef typename _List::const_pointer pointer;
330 typedef typename _List::const_reference reference;
332 typedef const typename _List::Hook Hook;
333 enum { kReverse = 1 };
339template <
typename _List,
typename _Config>
343 typedef std::bidirectional_iterator_tag iterator_category;
344 typedef typename _List::value_type value_type;
345 typedef typename _List::difference_type difference_type;
346 typedef typename _Config::pointer pointer;
347 typedef typename _Config::reference reference;
348 typedef typename _Config::ListNode ListNode;
353 assert((!_node || _node->list_) &&
354 "Cannot build an iterator from a node that's unlinked");
360 : node_(_it.node_) {}
365 template <
typename _OConfig>
367 : node_(_it.node_) {}
370 template <
typename _OConfig>
372 assert(node_ && _it.node_ && node_->list_ == _it.node_->list_ &&
373 "List iterators incompatible");
374 return node_ == _it.node_;
378 template <
typename _OConfig>
380 assert(node_ && _it.node_ && node_->list_ == _it.node_->list_ &&
381 "List iterators incompatible");
382 return node_ != _it.node_;
387 reference operator*()
const {
388 assert(node_ && !node_->debug_is_end_node() &&
389 "List iterator not dereferencable");
390 return static_cast<reference
>(
static_cast<typename _Config::Hook&
>(*node_));
397 assert(node_ && !node_->debug_is_end_node() &&
398 "List iterator is already on list boundaries");
399 node_ = _Config::kReverse ? node_->prev_ : node_->next_;
408 node_ != (_Config::kReverse ? node_->list_->end_.prev_
409 : node_->list_->end_.next_) &&
410 "List iterator is already on list boundaries");
411 node_ = _Config::kReverse ? node_->next_ : node_->prev_;
437 template <
typename,
typename>
443 assert(node_ &&
"Iterator isn't initialized");
448 template <
typename,
typename>
458template <
typename _Ty,
typename _Option>
465 if (
void(0), _Option::kLinkMode == LinkMode::kAuto && is_linked()) {
468 assert((_Option::kLinkMode == LinkMode::kUnsafe || !is_linked()) &&
469 "Node is still linked");
474 void operator=(
const Hook&);
478 typedef _Ty value_type;
481 typedef _Ty* pointer;
484 typedef _Ty
const* const_pointer;
487 typedef _Ty& reference;
490 typedef _Ty
const& const_reference;
493 typedef internal::IntrusiveNodeList::size_type size_type;
496 typedef ptrdiff_t difference_type;
524 if (
void(0), _Option::kLinkMode == LinkMode::kAuto) {
527 assert(_Option::kLinkMode == LinkMode::kUnsafe || empty());
531 void push_front(reference _val) { link_front(
static_cast<Hook*
>(&_val)); }
534 void push_back(reference _val) { link_back(
static_cast<Hook*
>(&_val)); }
540 reference pop_front() {
541 assert(!empty() &&
"Invalid function on an empty list");
542 internal::Node& node = begin_node();
544 return static_cast<reference
>(
static_cast<Hook&
>(node));
551 reference pop_back() {
552 assert(!empty() &&
"Invalid function on an empty list");
553 internal::Node& node = last_node();
555 return static_cast<reference
>(
static_cast<Hook&
>(node));
561 assert(!empty() &&
"Invalid function on an empty list");
562 return static_cast<reference
>(
static_cast<Hook&
>(begin_node()));
567 const_reference front()
const {
568 assert(!empty() &&
"Invalid function on an empty list");
569 return static_cast<const_reference
>(
static_cast<const Hook&
>(begin_node()));
575 assert(!empty() &&
"Invalid function on an empty list");
576 return static_cast<reference
>(
static_cast<Hook&
>(last_node()));
581 const_reference back()
const {
582 assert(!empty() &&
"Invalid function on an empty list");
583 return static_cast<const_reference
>(
static_cast<const Hook&
>(last_node()));
587 iterator begin() {
return iterator(&begin_node()); }
590 const_iterator begin()
const {
return const_iterator(&begin_node()); }
594 iterator end() {
return iterator(&end_node()); }
598 const_iterator end()
const {
return const_iterator(&end_node()); }
602 reverse_iterator rbegin() {
return reverse_iterator(&last_node()); }
606 const_reverse_iterator rbegin()
const {
607 return const_reverse_iterator(&last_node());
611 reverse_iterator rend() {
return reverse_iterator(&end_node()); }
614 const_reverse_iterator rend()
const {
615 return const_reverse_iterator(&end_node());
622 void remove(reference _val) {
623 Hook& hook =
static_cast<Hook&
>(_val);
624 assert(hook.debug_is_linked_in(*
this) &&
"The node is linked by this list");
631 template <
typename _Pred>
632 void remove_if(_Pred _pred) {
633 _remove_if(UnnaryPredFw<_Pred>(_pred));
641 iterator erase(iterator _where) {
642 internal::Node& where_node = _where.node();
643 assert(where_node.debug_is_linked_in(*
this) &&
644 "The node is linked by this list");
653 iterator erase(iterator
const& _begin, iterator
const& _end) {
654 internal::Node& begin_node = _begin.node();
655 internal::Node& end_node = _end.node();
656 _erase(&begin_node, &end_node);
663 void insert(iterator
const& _where, reference _val) {
665 _insert(
static_cast<Hook*
>(&_val), &_where.node());
671 void splice(iterator _where,
672 IntrusiveList& _list) {
673 if (
this != &_list && !_list.empty()) {
674 _splice(&_where.node(), &_list.begin_node(), &_list.end_node());
681 void splice(iterator _where,
682 IntrusiveList& _list,
684 reference val =
static_cast<reference
>(
static_cast<Hook&
>(_what.node()));
692 void splice(iterator _where,
693 IntrusiveList& _list,
694 iterator _begin, iterator _end) {
695 internal::Node* where_node = &_where.node();
696 internal::Node* begin_node = &_begin.node();
697 internal::Node* end_node = &_end.node();
698 if (begin_node != end_node && (
this != &_list || where_node != end_node)) {
699 _splice(where_node, begin_node, end_node);
711 template <
typename _Pred>
712 void merge(IntrusiveList& _list,
714 _merge(&_list, BinaryPredFw<_Pred>(_pred));
724 void merge(IntrusiveList& _list) {
725 _merge(&_list, LessTester());
734 template <
class _Pred>
735 void sort(_Pred _pred) {
736 _sort(BinaryPredFw<_Pred>(_pred));
743 void sort() { _sort(LessTester()); }
746 bool operator==(IntrusiveList
const& _list)
const {
747 return _is_equal(_list, EqualTester());
751 bool operator!=(IntrusiveList
const& _list)
const {
752 return !(*
this == _list);
756 bool operator<(IntrusiveList
const& _list)
const {
757 return _is_less(_list, LessTester());
761 bool operator<=(IntrusiveList
const& _list)
const {
return !(_list < *
this); }
764 bool operator>(IntrusiveList
const& _list)
const {
return _list < *
this; }
767 bool operator>=(IntrusiveList
const& _list)
const {
return !(*
this < _list); }
771 template <
typename _Pred>
772 bool is_ordered(_Pred _pred)
const {
773 return _is_ordered(BinaryPredFw<_Pred>(_pred));
778 template <
typename _Pred>
779 struct BinaryPredFw {
780 explicit BinaryPredFw(_Pred _pred) : pred_(_pred) {}
781 bool operator()(
const internal::Node& _left,
const internal::Node& _right) {
782 const_reference left =
783 static_cast<const_reference
>(
static_cast<const Hook&
>(_left));
784 const_reference right =
785 static_cast<const_reference
>(
static_cast<const Hook&
>(_right));
786 return pred_(left, right);
793 template <
typename _Pred>
794 struct UnnaryPredFw {
795 explicit UnnaryPredFw(_Pred _pred) : pred_(_pred) {}
796 bool operator()(
const internal::Node& _node) {
797 const_reference val =
798 static_cast<const_reference
>(
static_cast<const Hook&
>(_node));
806 bool operator()(
const internal::Node& _left,
const internal::Node& _right) {
807 const_reference left =
808 static_cast<const_reference
>(
static_cast<const Hook&
>(_left));
809 const_reference right =
810 static_cast<const_reference
>(
static_cast<const Hook&
>(_right));
811 return left == right;
817 bool operator()(
const internal::Node& _left,
const internal::Node& _right) {
818 const_reference left =
819 static_cast<const_reference
>(
static_cast<const Hook&
>(_left));
820 const_reference right =
821 static_cast<const_reference
>(
static_cast<const Hook&
>(_right));
827 IntrusiveList(
const IntrusiveList&);
828 void operator=(
const IntrusiveList&);
835inline void Node::unlink() {
836 assert(is_linked() &&
"This node is not linked");
837 assert(!debug_is_end_node() &&
"The end_ node cannot be unlinked");
839 next_->prev_ = prev_;
840 prev_->next_ = next_;
851inline void Node::insert(Node* _where) {
852 assert(!is_linked() && _where->list_ &&
854 "*this node must be unlinked and _node must be linked");
855 assert(!debug_is_end_node() &&
"The end_ node cannot be linked");
857 prev_ = _where->prev_;
858 _where->prev_->next_ =
this;
861 _where->prev_ =
this;
864 list_ = _where->list_;
869inline void IntrusiveNodeList::clear() {
870 while (end_.next_ != &end_) {
871 end_.next_->unlink();
877inline void IntrusiveNodeList::_erase(Node* _begin, Node* _end) {
878 assert(debug_is_range_valid(*_begin, *_end) &&
"Invalid iterator range");
879 while (_begin != _end) {
880 internal::Node* next_node = _begin->next_;
888inline void IntrusiveNodeList::reverse() {
889 Node*
const last = end_.prev_;
890 while (end_.next_ != last) {
891 Node* node = end_.next_;
893 node->insert(last->next_);
898inline size_t IntrusiveNodeList::size()
const {
900 for (
const Node *node = end_.next_; node != &end_;
901 node = node->next_, ++size) {
911inline void IntrusiveNodeList::swap(IntrusiveNodeList& _list) {
914#define _SWAP_PTR(_a, _b) \
921 _SWAP_PTR(_list.end_.prev_->next_, end_.prev_->next_);
922 _SWAP_PTR(_list.end_.prev_, end_.prev_);
923 _SWAP_PTR(_list.end_.next_->prev_, end_.next_->prev_);
924 _SWAP_PTR(_list.end_.next_, end_.next_);
929 Node* node = end_.next_;
930 while (node != &end_) {
934 node = _list.end_.next_;
935 while (node != &_list.end_) {
936 node->list_ = &_list;
946inline void IntrusiveNodeList::_splice(Node* _where, Node* _first, Node* _end) {
947 assert(_where->list_ ==
this &&
"_where is not a member of *this list");
948 assert(_first->list_ && _first->list_->debug_is_range_valid(*_first, *_end) &&
949 "Invalid iterator range");
950 assert(_first != _end);
953 Node* last = _end->prev_;
956 _first->prev_->next_ = _end;
957 _end->prev_ = _first->prev_;
960 _first->prev_ = _where->prev_;
961 _where->prev_->next_ = _first;
964 _where->prev_ = last;
965 last->next_ = _where;
970 while (node != _where) {
977template <
typename _Pred>
978inline bool IntrusiveNodeList::_is_equal(IntrusiveNodeList
const& _list,
980 const internal::Node* left_node = end_.next_;
981 const internal::Node* right_node = _list.end_.next_;
982 while (left_node != &end_ && right_node != &_list.end_) {
983 if (!_pred(*left_node, *right_node)) {
986 left_node = left_node->next_;
987 right_node = right_node->next_;
990 return left_node == &end_ && right_node == &_list.end_;
993template <
typename _Pred>
994inline bool IntrusiveNodeList::_is_less(IntrusiveNodeList
const& _list,
996 const internal::Node* left_node = end_.next_;
997 const internal::Node* right_node = _list.end_.next_;
998 while (left_node != &end_ && right_node != &_list.end_) {
999 if (_pred(*left_node, *right_node)) {
1001 }
else if (_pred(*right_node, *left_node)) {
1004 left_node = left_node->next_;
1005 right_node = right_node->next_;
1008 return left_node == &end_ && right_node != &_list.end_;
1013template <
typename _Pred>
1014inline void IntrusiveNodeList::_merge(IntrusiveNodeList* _list, _Pred _pred) {
1015 assert(_is_ordered(_pred) &&
"This list must be ordered");
1016 if (
this == _list) {
1019 assert(_list->_is_ordered(_pred) &&
"The list in argument must be ordered");
1021 internal::Node* node = end_.next_;
1022 internal::Node* to__insertbegin = _list->end_.next_;
1024 while (node != &end_ && to__insertbegin != &_list->end_) {
1025 if (_pred(*node, *to__insertbegin)) {
1028 internal::Node* to__insertend = to__insertbegin->next_;
1029 while (to__insertend != &_list->end_) {
1030 if (_pred(*node, *to__insertend)) {
1033 to__insertend = to__insertend->next_;
1035 _splice(node, to__insertbegin, to__insertend);
1036 to__insertbegin = to__insertend;
1040 if (to__insertbegin != &_list->end_) {
1041 _splice(&end_, to__insertbegin, &_list->end_);
1046template <
typename _Pred>
1047inline void IntrusiveNodeList::_remove_if(_Pred _pred) {
1048 internal::Node* node = end_.next_;
1049 while (node != &end_) {
1050 internal::Node* next_node = node->next_;
1059template <
typename _Pred>
1060inline void IntrusiveNodeList::_sort(_Pred _pred) {
1062 if (end_.next_->next_ == &end_) {
1065 const int kMaxBins = 25;
1066 IntrusiveNodeList bin_lists[kMaxBins + 1];
1067 IntrusiveNodeList temp_list;
1071 internal::Node* node = end_.next_;
1073 temp_list.link_front(node);
1076 for (; bin < used_bins && !bin_lists[bin].empty(); ++bin) {
1078 bin_lists[bin]._merge(&temp_list, _pred);
1079 bin_lists[bin].swap(temp_list);
1082 if (bin == kMaxBins) {
1083 bin_lists[kMaxBins - 1]._merge(&temp_list, _pred);
1085 bin_lists[bin].swap(temp_list);
1086 if (bin == used_bins) {
1092 for (
int bin = 1; bin < used_bins; ++bin) {
1093 bin_lists[bin]._merge(&bin_lists[bin - 1], _pred);
1096 if (used_bins != 0) {
1097 IntrusiveNodeList& last_bin = bin_lists[used_bins - 1];
1098 _splice(end_.next_, last_bin.end_.next_, &last_bin.end_);
1103template <
typename _Pred>
1104inline bool IntrusiveNodeList::_is_ordered(_Pred _pred)
const {
1105 const internal::Node* next_node = end_.next_->next_;
1106 while (next_node != &end_) {
1107 if (!_pred(*next_node->prev_, *next_node)) {
1110 next_node = next_node->next_;
1120template <
typename _Ty,
typename _Option>
Definition intrusive_list.h:461
Definition intrusive_list.h:459
Definition intrusive_list.h:340
Definition intrusive_list.h:174
Definition intrusive_list.h:102
Definition intrusive_list.h:39
Definition intrusive_list.h:77
Definition intrusive_list.h:308
Definition intrusive_list.h:328
Definition intrusive_list.h:298
Definition intrusive_list.h:318