File indexing completed on 2025-01-18 09:38:40
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef BOOST_INTRUSIVE_BSTREE_ALGORITHMS_HPP
0015 #define BOOST_INTRUSIVE_BSTREE_ALGORITHMS_HPP
0016
0017 #include <cstddef>
0018 #include <boost/intrusive/detail/config_begin.hpp>
0019 #include <boost/intrusive/intrusive_fwd.hpp>
0020 #include <boost/intrusive/detail/bstree_algorithms_base.hpp>
0021 #include <boost/intrusive/detail/assert.hpp>
0022 #include <boost/intrusive/detail/uncast.hpp>
0023 #include <boost/intrusive/detail/math.hpp>
0024 #include <boost/intrusive/detail/algo_type.hpp>
0025
0026 #include <boost/intrusive/detail/minimal_pair_header.hpp>
0027
0028 #if defined(BOOST_HAS_PRAGMA_ONCE)
0029 # pragma once
0030 #endif
0031
0032 namespace boost {
0033 namespace intrusive {
0034
0035
0036
0037
0038 template <class NodePtr>
0039 struct insert_commit_data_t
0040 {
0041 BOOST_INTRUSIVE_FORCEINLINE insert_commit_data_t()
0042 : link_left(false), node()
0043 {}
0044 bool link_left;
0045 NodePtr node;
0046 };
0047
0048 template <class NodePtr>
0049 struct data_for_rebalance_t
0050 {
0051 NodePtr x;
0052 NodePtr x_parent;
0053 NodePtr y;
0054 };
0055
0056 namespace detail {
0057
0058 template<class ValueTraits, class NodePtrCompare, class ExtraChecker>
0059 struct bstree_node_checker
0060 : public ExtraChecker
0061 {
0062 typedef ExtraChecker base_checker_t;
0063 typedef ValueTraits value_traits;
0064 typedef typename value_traits::node_traits node_traits;
0065 typedef typename node_traits::const_node_ptr const_node_ptr;
0066
0067 struct return_type
0068 : public base_checker_t::return_type
0069 {
0070 BOOST_INTRUSIVE_FORCEINLINE return_type()
0071 : min_key_node_ptr(const_node_ptr()), max_key_node_ptr(const_node_ptr()), node_count(0)
0072 {}
0073
0074 const_node_ptr min_key_node_ptr;
0075 const_node_ptr max_key_node_ptr;
0076 size_t node_count;
0077 };
0078
0079 BOOST_INTRUSIVE_FORCEINLINE bstree_node_checker(const NodePtrCompare& comp, ExtraChecker extra_checker)
0080 : base_checker_t(extra_checker), comp_(comp)
0081 {}
0082
0083 void operator () (const_node_ptr p,
0084 const return_type& check_return_left, const return_type& check_return_right,
0085 return_type& check_return)
0086 {
0087 BOOST_INTRUSIVE_INVARIANT_ASSERT(!check_return_left.max_key_node_ptr || !comp_(p, check_return_left.max_key_node_ptr));
0088 BOOST_INTRUSIVE_INVARIANT_ASSERT(!check_return_right.min_key_node_ptr || !comp_(check_return_right.min_key_node_ptr, p));
0089 check_return.min_key_node_ptr = node_traits::get_left(p)? check_return_left.min_key_node_ptr : p;
0090 check_return.max_key_node_ptr = node_traits::get_right(p)? check_return_right.max_key_node_ptr : p;
0091 check_return.node_count = check_return_left.node_count + check_return_right.node_count + 1;
0092 base_checker_t::operator()(p, check_return_left, check_return_right, check_return);
0093 }
0094
0095 const NodePtrCompare comp_;
0096 };
0097
0098 }
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171 template<class NodeTraits>
0172 class bstree_algorithms : public bstree_algorithms_base<NodeTraits>
0173 {
0174 public:
0175 typedef typename NodeTraits::node node;
0176 typedef NodeTraits node_traits;
0177 typedef typename NodeTraits::node_ptr node_ptr;
0178 typedef typename NodeTraits::const_node_ptr const_node_ptr;
0179 typedef insert_commit_data_t<node_ptr> insert_commit_data;
0180 typedef data_for_rebalance_t<node_ptr> data_for_rebalance;
0181
0182
0183 typedef bstree_algorithms<NodeTraits> this_type;
0184 typedef bstree_algorithms_base<NodeTraits> base_type;
0185 private:
0186 template<class Disposer>
0187 struct dispose_subtree_disposer
0188 {
0189 BOOST_INTRUSIVE_FORCEINLINE dispose_subtree_disposer(Disposer &disp, node_ptr subtree)
0190 : disposer_(&disp), subtree_(subtree)
0191 {}
0192
0193 BOOST_INTRUSIVE_FORCEINLINE void release()
0194 { disposer_ = 0; }
0195
0196 BOOST_INTRUSIVE_FORCEINLINE ~dispose_subtree_disposer()
0197 {
0198 if(disposer_){
0199 dispose_subtree(subtree_, *disposer_);
0200 }
0201 }
0202 Disposer *disposer_;
0203 const node_ptr subtree_;
0204 };
0205
0206
0207
0208 public:
0209
0210
0211
0212
0213
0214
0215
0216 BOOST_INTRUSIVE_FORCEINLINE static node_ptr begin_node(const_node_ptr header) BOOST_NOEXCEPT
0217 { return node_traits::get_left(header); }
0218
0219
0220
0221
0222
0223
0224
0225
0226 BOOST_INTRUSIVE_FORCEINLINE static node_ptr end_node(const_node_ptr header) BOOST_NOEXCEPT
0227 { return detail::uncast(header); }
0228
0229
0230
0231
0232
0233
0234
0235
0236 BOOST_INTRUSIVE_FORCEINLINE static node_ptr root_node(const_node_ptr header) BOOST_NOEXCEPT
0237 {
0238 node_ptr p = node_traits::get_parent(header);
0239 return p ? p : detail::uncast(header);
0240 }
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250 BOOST_INTRUSIVE_FORCEINLINE static bool unique(const_node_ptr n) BOOST_NOEXCEPT
0251 { return !NodeTraits::get_parent(n); }
0252
0253 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
0254
0255
0256
0257
0258
0259
0260
0261 static node_ptr get_header(const_node_ptr n);
0262 #endif
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279 static void swap_nodes(node_ptr node1, node_ptr node2) BOOST_NOEXCEPT
0280 {
0281 if(node1 == node2)
0282 return;
0283
0284 node_ptr header1(base_type::get_header(node1)), header2(base_type::get_header(node2));
0285 swap_nodes(node1, header1, node2, header2);
0286 }
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303 static void swap_nodes(node_ptr node1, node_ptr header1, node_ptr node2, node_ptr header2) BOOST_NOEXCEPT
0304 {
0305 if(node1 == node2)
0306 return;
0307
0308
0309
0310 if(header1 != header2){
0311
0312 if(node1 == NodeTraits::get_left(header1)){
0313 NodeTraits::set_left(header1, node2);
0314 }
0315
0316 if(node1 == NodeTraits::get_right(header1)){
0317 NodeTraits::set_right(header1, node2);
0318 }
0319
0320 if(node1 == NodeTraits::get_parent(header1)){
0321 NodeTraits::set_parent(header1, node2);
0322 }
0323
0324
0325 if(node2 == NodeTraits::get_left(header2)){
0326 NodeTraits::set_left(header2, node1);
0327 }
0328
0329 if(node2 == NodeTraits::get_right(header2)){
0330 NodeTraits::set_right(header2, node1);
0331 }
0332
0333 if(node2 == NodeTraits::get_parent(header2)){
0334 NodeTraits::set_parent(header2, node1);
0335 }
0336 }
0337 else{
0338
0339
0340 if(node1 == NodeTraits::get_left(header1)){
0341 NodeTraits::set_left(header1, node2);
0342 }
0343 else if(node2 == NodeTraits::get_left(header2)){
0344 NodeTraits::set_left(header2, node1);
0345 }
0346
0347 if(node1 == NodeTraits::get_right(header1)){
0348 NodeTraits::set_right(header1, node2);
0349 }
0350 else if(node2 == NodeTraits::get_right(header2)){
0351 NodeTraits::set_right(header2, node1);
0352 }
0353
0354 if(node1 == NodeTraits::get_parent(header1)){
0355 NodeTraits::set_parent(header1, node2);
0356 }
0357 else if(node2 == NodeTraits::get_parent(header2)){
0358 NodeTraits::set_parent(header2, node1);
0359 }
0360
0361
0362
0363 if(node1 == NodeTraits::get_parent(node2)){
0364 NodeTraits::set_parent(node2, node2);
0365
0366 if(node2 == NodeTraits::get_right(node1)){
0367 NodeTraits::set_right(node1, node1);
0368 }
0369 else{
0370 NodeTraits::set_left(node1, node1);
0371 }
0372 }
0373 else if(node2 == NodeTraits::get_parent(node1)){
0374 NodeTraits::set_parent(node1, node1);
0375
0376 if(node1 == NodeTraits::get_right(node2)){
0377 NodeTraits::set_right(node2, node2);
0378 }
0379 else{
0380 NodeTraits::set_left(node2, node2);
0381 }
0382 }
0383 }
0384
0385
0386 node_ptr temp;
0387
0388 temp = NodeTraits::get_left(node1);
0389 NodeTraits::set_left(node1, NodeTraits::get_left(node2));
0390 NodeTraits::set_left(node2, temp);
0391
0392 temp = NodeTraits::get_right(node1);
0393 NodeTraits::set_right(node1, NodeTraits::get_right(node2));
0394 NodeTraits::set_right(node2, temp);
0395
0396 temp = NodeTraits::get_parent(node1);
0397 NodeTraits::set_parent(node1, NodeTraits::get_parent(node2));
0398 NodeTraits::set_parent(node2, temp);
0399
0400
0401 if((temp = NodeTraits::get_left(node1))){
0402 NodeTraits::set_parent(temp, node1);
0403 }
0404 if((temp = NodeTraits::get_right(node1))){
0405 NodeTraits::set_parent(temp, node1);
0406 }
0407
0408 if((temp = NodeTraits::get_left(node2))){
0409 NodeTraits::set_parent(temp, node2);
0410 }
0411 if((temp = NodeTraits::get_right(node2))){
0412 NodeTraits::set_parent(temp, node2);
0413 }
0414
0415
0416 if ((temp = NodeTraits::get_parent(node1)) == NodeTraits::get_parent(node2)) {
0417
0418 const node_ptr left = NodeTraits::get_left(temp);
0419 NodeTraits::set_left(temp, NodeTraits::get_right(temp));
0420 NodeTraits::set_right(temp, left);
0421 } else {
0422 if ((temp = NodeTraits::get_parent(node1)) &&
0423
0424 temp != header2) {
0425 if (NodeTraits::get_left(temp) == node2) {
0426 NodeTraits::set_left(temp, node1);
0427 }
0428 if (NodeTraits::get_right(temp) == node2) {
0429 NodeTraits::set_right(temp, node1);
0430 }
0431 }
0432 if ((temp = NodeTraits::get_parent(node2)) &&
0433
0434 temp != header1) {
0435 if (NodeTraits::get_left(temp) == node1) {
0436 NodeTraits::set_left(temp, node2);
0437 }
0438 if (NodeTraits::get_right(temp) == node1) {
0439 NodeTraits::set_right(temp, node2);
0440 }
0441 }
0442 }
0443 }
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459 BOOST_INTRUSIVE_FORCEINLINE static void replace_node(node_ptr node_to_be_replaced, node_ptr new_node) BOOST_NOEXCEPT
0460 {
0461 replace_node(node_to_be_replaced, base_type::get_header(node_to_be_replaced), new_node);
0462 }
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478 static void replace_node(node_ptr node_to_be_replaced, node_ptr header, node_ptr new_node) BOOST_NOEXCEPT
0479 {
0480 BOOST_ASSERT(node_to_be_replaced != new_node);
0481
0482
0483 if(node_to_be_replaced == NodeTraits::get_left(header)){
0484 NodeTraits::set_left(header, new_node);
0485 }
0486
0487 if(node_to_be_replaced == NodeTraits::get_right(header)){
0488 NodeTraits::set_right(header, new_node);
0489 }
0490
0491 if(node_to_be_replaced == NodeTraits::get_parent(header)){
0492 NodeTraits::set_parent(header, new_node);
0493 }
0494
0495
0496 node_ptr temp;
0497 NodeTraits::set_left(new_node, NodeTraits::get_left(node_to_be_replaced));
0498 NodeTraits::set_right(new_node, NodeTraits::get_right(node_to_be_replaced));
0499 NodeTraits::set_parent(new_node, NodeTraits::get_parent(node_to_be_replaced));
0500
0501
0502 if((temp = NodeTraits::get_left(new_node))){
0503 NodeTraits::set_parent(temp, new_node);
0504 }
0505 if((temp = NodeTraits::get_right(new_node))){
0506 NodeTraits::set_parent(temp, new_node);
0507 }
0508 if((temp = NodeTraits::get_parent(new_node)) &&
0509
0510 temp != header){
0511 if(NodeTraits::get_left(temp) == node_to_be_replaced){
0512 NodeTraits::set_left(temp, new_node);
0513 }
0514 if(NodeTraits::get_right(temp) == node_to_be_replaced){
0515 NodeTraits::set_right(temp, new_node);
0516 }
0517 }
0518 }
0519
0520 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
0521
0522
0523
0524
0525
0526
0527
0528 static node_ptr next_node(node_ptr n) BOOST_NOEXCEPT;
0529
0530
0531
0532
0533
0534
0535
0536
0537 static node_ptr prev_node(node_ptr n) BOOST_NOEXCEPT;
0538
0539
0540
0541
0542
0543
0544
0545
0546 static node_ptr minimum(node_ptr n);
0547
0548
0549
0550
0551
0552
0553
0554
0555 static node_ptr maximum(node_ptr n);
0556 #endif
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567 static void init(node_ptr n) BOOST_NOEXCEPT
0568 {
0569 NodeTraits::set_parent(n, node_ptr());
0570 NodeTraits::set_left(n, node_ptr());
0571 NodeTraits::set_right(n, node_ptr());
0572 }
0573
0574
0575
0576
0577
0578
0579 static bool inited(const_node_ptr n)
0580 {
0581 return !NodeTraits::get_parent(n) &&
0582 !NodeTraits::get_left(n) &&
0583 !NodeTraits::get_right(n) ;
0584 }
0585
0586
0587
0588
0589
0590
0591
0592
0593
0594
0595
0596 static void init_header(node_ptr header) BOOST_NOEXCEPT
0597 {
0598 NodeTraits::set_parent(header, node_ptr());
0599 NodeTraits::set_left(header, header);
0600 NodeTraits::set_right(header, header);
0601 }
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611
0612
0613
0614 template<class Disposer>
0615 static void clear_and_dispose(node_ptr header, Disposer disposer) BOOST_NOEXCEPT
0616 {
0617 node_ptr source_root = NodeTraits::get_parent(header);
0618 if(!source_root)
0619 return;
0620 dispose_subtree(source_root, disposer);
0621 init_header(header);
0622 }
0623
0624
0625
0626
0627
0628
0629
0630
0631
0632
0633
0634
0635
0636
0637 static node_ptr unlink_leftmost_without_rebalance(node_ptr header) BOOST_NOEXCEPT
0638 {
0639 node_ptr leftmost = NodeTraits::get_left(header);
0640 if (leftmost == header)
0641 return node_ptr();
0642 node_ptr leftmost_parent(NodeTraits::get_parent(leftmost));
0643 node_ptr leftmost_right (NodeTraits::get_right(leftmost));
0644 bool is_root = leftmost_parent == header;
0645
0646 if (leftmost_right){
0647 NodeTraits::set_parent(leftmost_right, leftmost_parent);
0648 NodeTraits::set_left(header, base_type::minimum(leftmost_right));
0649
0650 if (is_root)
0651 NodeTraits::set_parent(header, leftmost_right);
0652 else
0653 NodeTraits::set_left(NodeTraits::get_parent(header), leftmost_right);
0654 }
0655 else if (is_root){
0656 NodeTraits::set_parent(header, node_ptr());
0657 NodeTraits::set_left(header, header);
0658 NodeTraits::set_right(header, header);
0659 }
0660 else{
0661 NodeTraits::set_left(leftmost_parent, node_ptr());
0662 NodeTraits::set_left(header, leftmost_parent);
0663 }
0664 return leftmost;
0665 }
0666
0667
0668
0669
0670
0671
0672
0673
0674 static std::size_t size(const_node_ptr header) BOOST_NOEXCEPT
0675 {
0676 node_ptr beg(begin_node(header));
0677 node_ptr end(end_node(header));
0678 std::size_t i = 0;
0679 for(;beg != end; beg = base_type::next_node(beg)) ++i;
0680 return i;
0681 }
0682
0683
0684
0685
0686
0687
0688
0689
0690
0691
0692 static void swap_tree(node_ptr header1, node_ptr header2) BOOST_NOEXCEPT
0693 {
0694 if(header1 == header2)
0695 return;
0696
0697 node_ptr tmp;
0698
0699
0700 tmp = NodeTraits::get_parent(header1);
0701 NodeTraits::set_parent(header1, NodeTraits::get_parent(header2));
0702 NodeTraits::set_parent(header2, tmp);
0703
0704 tmp = NodeTraits::get_left(header1);
0705 NodeTraits::set_left(header1, NodeTraits::get_left(header2));
0706 NodeTraits::set_left(header2, tmp);
0707
0708 tmp = NodeTraits::get_right(header1);
0709 NodeTraits::set_right(header1, NodeTraits::get_right(header2));
0710 NodeTraits::set_right(header2, tmp);
0711
0712
0713 node_ptr h1_parent(NodeTraits::get_parent(header1));
0714 if(h1_parent){
0715 NodeTraits::set_parent(h1_parent, header1);
0716 }
0717 else{
0718 NodeTraits::set_left(header1, header1);
0719 NodeTraits::set_right(header1, header1);
0720 }
0721
0722 node_ptr h2_parent(NodeTraits::get_parent(header2));
0723 if(h2_parent){
0724 NodeTraits::set_parent(h2_parent, header2);
0725 }
0726 else{
0727 NodeTraits::set_left(header2, header2);
0728 NodeTraits::set_right(header2, header2);
0729 }
0730 }
0731
0732 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
0733
0734
0735
0736
0737
0738
0739
0740 static bool is_header(const_node_ptr p) BOOST_NOEXCEPT;
0741 #endif
0742
0743
0744
0745
0746
0747
0748
0749
0750
0751
0752
0753
0754 template<class KeyType, class KeyNodePtrCompare>
0755 static node_ptr find
0756 (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp)
0757 {
0758 node_ptr end = detail::uncast(header);
0759 node_ptr y = lower_bound(header, key, comp);
0760 return (y == end || comp(key, y)) ? end : y;
0761 }
0762
0763
0764
0765
0766
0767
0768
0769
0770
0771
0772
0773
0774
0775
0776
0777
0778
0779
0780
0781
0782
0783
0784 template< class KeyType, class KeyNodePtrCompare>
0785 static std::pair<node_ptr, node_ptr> bounded_range
0786 ( const_node_ptr header
0787 , const KeyType &lower_key
0788 , const KeyType &upper_key
0789 , KeyNodePtrCompare comp
0790 , bool left_closed
0791 , bool right_closed)
0792 {
0793 node_ptr y = detail::uncast(header);
0794 node_ptr x = NodeTraits::get_parent(header);
0795
0796 while(x){
0797
0798
0799 if(comp(x, lower_key)){
0800
0801 BOOST_INTRUSIVE_INVARIANT_ASSERT(comp(x, upper_key));
0802 x = NodeTraits::get_right(x);
0803 }
0804
0805
0806 else if(comp(upper_key, x)){
0807 y = x;
0808 x = NodeTraits::get_left(x);
0809 }
0810 else{
0811
0812
0813
0814
0815 BOOST_INTRUSIVE_INVARIANT_ASSERT(left_closed || right_closed || comp(lower_key, x) || comp(x, upper_key));
0816 return std::pair<node_ptr,node_ptr>(
0817 left_closed
0818
0819
0820
0821 ? lower_bound_loop(NodeTraits::get_left(x), x, lower_key, comp)
0822
0823
0824 : upper_bound_loop(x, y, lower_key, comp)
0825 ,
0826 right_closed
0827
0828
0829
0830 ? upper_bound_loop(NodeTraits::get_right(x), y, upper_key, comp)
0831
0832
0833 : lower_bound_loop(x, y, upper_key, comp)
0834 );
0835 }
0836 }
0837 return std::pair<node_ptr,node_ptr> (y, y);
0838 }
0839
0840
0841
0842
0843
0844
0845
0846
0847
0848
0849
0850
0851 template<class KeyType, class KeyNodePtrCompare>
0852 static std::size_t count
0853 (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp)
0854 {
0855 std::pair<node_ptr, node_ptr> ret = equal_range(header, key, comp);
0856 std::size_t n = 0;
0857 while(ret.first != ret.second){
0858 ++n;
0859 ret.first = base_type::next_node(ret.first);
0860 }
0861 return n;
0862 }
0863
0864
0865
0866
0867
0868
0869
0870
0871
0872
0873
0874
0875
0876
0877 template<class KeyType, class KeyNodePtrCompare>
0878 BOOST_INTRUSIVE_FORCEINLINE static std::pair<node_ptr, node_ptr> equal_range
0879 (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp)
0880 {
0881 return bounded_range(header, key, key, comp, true, true);
0882 }
0883
0884
0885
0886
0887
0888
0889
0890
0891
0892
0893
0894
0895
0896
0897 template<class KeyType, class KeyNodePtrCompare>
0898 static std::pair<node_ptr, node_ptr> lower_bound_range
0899 (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp)
0900 {
0901 node_ptr const lb(lower_bound(header, key, comp));
0902 std::pair<node_ptr, node_ptr> ret_ii(lb, lb);
0903 if(lb != header && !comp(key, lb)){
0904 ret_ii.second = base_type::next_node(ret_ii.second);
0905 }
0906 return ret_ii;
0907 }
0908
0909
0910
0911
0912
0913
0914
0915
0916
0917
0918
0919
0920
0921 template<class KeyType, class KeyNodePtrCompare>
0922 BOOST_INTRUSIVE_FORCEINLINE static node_ptr lower_bound
0923 (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp)
0924 {
0925 return lower_bound_loop(NodeTraits::get_parent(header), detail::uncast(header), key, comp);
0926 }
0927
0928
0929
0930
0931
0932
0933
0934
0935
0936
0937
0938
0939 template<class KeyType, class KeyNodePtrCompare>
0940 BOOST_INTRUSIVE_FORCEINLINE static node_ptr upper_bound
0941 (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp)
0942 {
0943 return upper_bound_loop(NodeTraits::get_parent(header), detail::uncast(header), key, comp);
0944 }
0945
0946
0947
0948
0949
0950
0951
0952
0953
0954
0955
0956
0957
0958
0959
0960
0961
0962
0963 BOOST_INTRUSIVE_FORCEINLINE static void insert_unique_commit
0964 (node_ptr header, node_ptr new_value, const insert_commit_data &commit_data) BOOST_NOEXCEPT
0965 { return insert_commit(header, new_value, commit_data); }
0966
0967
0968
0969
0970
0971
0972
0973
0974
0975
0976
0977
0978
0979
0980
0981
0982
0983
0984
0985
0986
0987
0988
0989
0990
0991
0992
0993
0994
0995
0996
0997
0998
0999
1000
1001 template<class KeyType, class KeyNodePtrCompare>
1002 static std::pair<node_ptr, bool> insert_unique_check
1003 (const_node_ptr header, const KeyType &key
1004 ,KeyNodePtrCompare comp, insert_commit_data &commit_data
1005 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1006 , std::size_t *pdepth = 0
1007 #endif
1008 )
1009 {
1010 std::size_t depth = 0;
1011 node_ptr h(detail::uncast(header));
1012 node_ptr y(h);
1013 node_ptr x(NodeTraits::get_parent(y));
1014 node_ptr prev = node_ptr();
1015
1016
1017
1018 bool left_child = true;
1019 while(x){
1020 ++depth;
1021 y = x;
1022 left_child = comp(key, x);
1023 x = left_child ?
1024 NodeTraits::get_left(x) : (prev = y, NodeTraits::get_right(x));
1025 }
1026
1027 if(pdepth) *pdepth = depth;
1028
1029
1030
1031
1032 const bool not_present = !prev || comp(prev, key);
1033 if(not_present){
1034 commit_data.link_left = left_child;
1035 commit_data.node = y;
1036 }
1037 return std::pair<node_ptr, bool>(prev, not_present);
1038 }
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079 template<class KeyType, class KeyNodePtrCompare>
1080 static std::pair<node_ptr, bool> insert_unique_check
1081 (const_node_ptr header, node_ptr hint, const KeyType &key
1082 ,KeyNodePtrCompare comp, insert_commit_data &commit_data
1083 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1084 , std::size_t *pdepth = 0
1085 #endif
1086 )
1087 {
1088
1089 if(hint == header || comp(key, hint)){
1090 node_ptr prev(hint);
1091
1092 if(hint == begin_node(header) || comp((prev = base_type::prev_node(hint)), key)){
1093 commit_data.link_left = unique(header) || !NodeTraits::get_left(hint);
1094 commit_data.node = commit_data.link_left ? hint : prev;
1095 if(pdepth){
1096 *pdepth = commit_data.node == header ? 0 : depth(commit_data.node) + 1;
1097 }
1098 return std::pair<node_ptr, bool>(node_ptr(), true);
1099 }
1100 }
1101
1102 return insert_unique_check(header, key, comp, commit_data, pdepth);
1103 }
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119 template<class NodePtrCompare>
1120 static node_ptr insert_equal
1121 (node_ptr h, node_ptr hint, node_ptr new_node, NodePtrCompare comp
1122 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1123 , std::size_t *pdepth = 0
1124 #endif
1125 )
1126 {
1127 insert_commit_data commit_data;
1128 insert_equal_check(h, hint, new_node, comp, commit_data, pdepth);
1129 insert_commit(h, new_node, commit_data);
1130 return new_node;
1131 }
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145 template<class NodePtrCompare>
1146 static node_ptr insert_equal_upper_bound
1147 (node_ptr h, node_ptr new_node, NodePtrCompare comp
1148 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1149 , std::size_t *pdepth = 0
1150 #endif
1151 )
1152 {
1153 insert_commit_data commit_data;
1154 insert_equal_upper_bound_check(h, new_node, comp, commit_data, pdepth);
1155 insert_commit(h, new_node, commit_data);
1156 return new_node;
1157 }
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171 template<class NodePtrCompare>
1172 static node_ptr insert_equal_lower_bound
1173 (node_ptr h, node_ptr new_node, NodePtrCompare comp
1174 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1175 , std::size_t *pdepth = 0
1176 #endif
1177 )
1178 {
1179 insert_commit_data commit_data;
1180 insert_equal_lower_bound_check(h, new_node, comp, commit_data, pdepth);
1181 insert_commit(h, new_node, commit_data);
1182 return new_node;
1183 }
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199 static node_ptr insert_before
1200 (node_ptr header, node_ptr pos, node_ptr new_node
1201 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1202 , std::size_t *pdepth = 0
1203 #endif
1204 ) BOOST_NOEXCEPT
1205 {
1206 insert_commit_data commit_data;
1207 insert_before_check(header, pos, commit_data, pdepth);
1208 insert_commit(header, new_node, commit_data);
1209 return new_node;
1210 }
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225 static void push_back
1226 (node_ptr header, node_ptr new_node
1227 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1228 , std::size_t *pdepth = 0
1229 #endif
1230 ) BOOST_NOEXCEPT
1231 {
1232 insert_commit_data commit_data;
1233 push_back_check(header, commit_data, pdepth);
1234 insert_commit(header, new_node, commit_data);
1235 }
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250 static void push_front
1251 (node_ptr header, node_ptr new_node
1252 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1253 , std::size_t *pdepth = 0
1254 #endif
1255 ) BOOST_NOEXCEPT
1256 {
1257 insert_commit_data commit_data;
1258 push_front_check(header, commit_data, pdepth);
1259 insert_commit(header, new_node, commit_data);
1260 }
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271 static std::size_t depth(const_node_ptr n) BOOST_NOEXCEPT
1272 {
1273 std::size_t depth = 0;
1274 node_ptr p_parent;
1275 while(n != NodeTraits::get_parent(p_parent = NodeTraits::get_parent(n))){
1276 ++depth;
1277 n = p_parent;
1278 }
1279 return depth;
1280 }
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299 template <class Cloner, class Disposer>
1300 static void clone
1301 (const_node_ptr source_header, node_ptr target_header, Cloner cloner, Disposer disposer)
1302 {
1303 if(!unique(target_header)){
1304 clear_and_dispose(target_header, disposer);
1305 }
1306
1307 node_ptr leftmost, rightmost;
1308 node_ptr new_root = clone_subtree
1309 (source_header, target_header, cloner, disposer, leftmost, rightmost);
1310
1311
1312 NodeTraits::set_parent(target_header, new_root);
1313 NodeTraits::set_left (target_header, leftmost);
1314 NodeTraits::set_right (target_header, rightmost);
1315 }
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325 BOOST_INTRUSIVE_FORCEINLINE static void erase(node_ptr header, node_ptr z) BOOST_NOEXCEPT
1326 {
1327 data_for_rebalance ignored;
1328 erase(header, z, ignored);
1329 }
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343 template<class NodePtrCompare>
1344 BOOST_INTRUSIVE_FORCEINLINE static bool transfer_unique
1345 (node_ptr header1, NodePtrCompare comp, node_ptr header2, node_ptr z)
1346 {
1347 data_for_rebalance ignored;
1348 return transfer_unique(header1, comp, header2, z, ignored);
1349 }
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360 template<class NodePtrCompare>
1361 BOOST_INTRUSIVE_FORCEINLINE static void transfer_equal
1362 (node_ptr header1, NodePtrCompare comp, node_ptr header2, node_ptr z)
1363 {
1364 data_for_rebalance ignored;
1365 transfer_equal(header1, comp, header2, z, ignored);
1366 }
1367
1368
1369
1370
1371
1372
1373
1374
1375 static void unlink(node_ptr n) BOOST_NOEXCEPT
1376 {
1377 node_ptr x = NodeTraits::get_parent(n);
1378 if(x){
1379 while(!base_type::is_header(x))
1380 x = NodeTraits::get_parent(x);
1381 erase(x, n);
1382 }
1383 }
1384
1385
1386
1387
1388
1389
1390
1391
1392 static void rebalance(node_ptr header) BOOST_NOEXCEPT
1393 {
1394 node_ptr root = NodeTraits::get_parent(header);
1395 if(root){
1396 rebalance_subtree(root);
1397 }
1398 }
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409 static node_ptr rebalance_subtree(node_ptr old_root) BOOST_NOEXCEPT
1410 {
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420 node_ptr super_root = NodeTraits::get_parent(old_root);
1421 BOOST_INTRUSIVE_INVARIANT_ASSERT(super_root);
1422
1423
1424 node_ptr super_root_right_backup = NodeTraits::get_right(super_root);
1425 bool super_root_is_header = NodeTraits::get_parent(super_root) == old_root;
1426 bool old_root_is_right = is_right_child(old_root);
1427 NodeTraits::set_right(super_root, old_root);
1428
1429 std::size_t size;
1430 subtree_to_vine(super_root, size);
1431 vine_to_subtree(super_root, size);
1432 node_ptr new_root = NodeTraits::get_right(super_root);
1433
1434
1435 if(super_root_is_header){
1436 NodeTraits::set_right(super_root, super_root_right_backup);
1437 NodeTraits::set_parent(super_root, new_root);
1438 }
1439 else if(old_root_is_right){
1440 NodeTraits::set_right(super_root, new_root);
1441 }
1442 else{
1443 NodeTraits::set_right(super_root, super_root_right_backup);
1444 NodeTraits::set_left(super_root, new_root);
1445 }
1446 return new_root;
1447 }
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457 template<class Checker>
1458 static void check(const_node_ptr header, Checker checker, typename Checker::return_type& checker_return)
1459 {
1460 const_node_ptr root_node_ptr = NodeTraits::get_parent(header);
1461 if (!root_node_ptr){
1462
1463 BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_left(header) == header);
1464 BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_right(header) == header);
1465 }
1466 else{
1467
1468 BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_parent(root_node_ptr) == header);
1469
1470 check_subtree(root_node_ptr, checker, checker_return);
1471
1472 const_node_ptr p = root_node_ptr;
1473 while (NodeTraits::get_left(p)) { p = NodeTraits::get_left(p); }
1474 BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_left(header) == p);
1475 p = root_node_ptr;
1476 while (NodeTraits::get_right(p)) { p = NodeTraits::get_right(p); }
1477 BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_right(header) == p);
1478 }
1479 }
1480
1481 protected:
1482
1483 template<class NodePtrCompare>
1484 static bool transfer_unique
1485 (node_ptr header1, NodePtrCompare comp, node_ptr header2, node_ptr z, data_for_rebalance &info)
1486 {
1487 insert_commit_data commit_data;
1488 bool const transferable = insert_unique_check(header1, z, comp, commit_data).second;
1489 if(transferable){
1490 erase(header2, z, info);
1491 insert_commit(header1, z, commit_data);
1492 }
1493 return transferable;
1494 }
1495
1496 template<class NodePtrCompare>
1497 static void transfer_equal
1498 (node_ptr header1, NodePtrCompare comp, node_ptr header2, node_ptr z, data_for_rebalance &info)
1499 {
1500 insert_commit_data commit_data;
1501 insert_equal_upper_bound_check(header1, z, comp, commit_data);
1502 erase(header2, z, info);
1503 insert_commit(header1, z, commit_data);
1504 }
1505
1506 static void erase(node_ptr header, node_ptr z, data_for_rebalance &info)
1507 {
1508 node_ptr y(z);
1509 node_ptr x;
1510 const node_ptr z_left(NodeTraits::get_left(z));
1511 const node_ptr z_right(NodeTraits::get_right(z));
1512
1513 if(!z_left){
1514 x = z_right;
1515 }
1516 else if(!z_right){
1517 x = z_left;
1518 BOOST_ASSERT(x);
1519 }
1520 else{
1521
1522 y = base_type::minimum(z_right);
1523 x = NodeTraits::get_right(y);
1524 }
1525
1526 node_ptr x_parent;
1527 const node_ptr z_parent(NodeTraits::get_parent(z));
1528 const bool z_is_leftchild(NodeTraits::get_left(z_parent) == z);
1529
1530 if(y != z){
1531
1532
1533
1534 NodeTraits::set_parent(z_left, y);
1535 NodeTraits::set_left(y, z_left);
1536 if(y != z_right){
1537
1538 NodeTraits::set_right(y, z_right);
1539 NodeTraits::set_parent(z_right, y);
1540
1541 x_parent = NodeTraits::get_parent(y);
1542 BOOST_ASSERT(NodeTraits::get_left(x_parent) == y);
1543 if(x)
1544 NodeTraits::set_parent(x, x_parent);
1545
1546 NodeTraits::set_left(x_parent, x);
1547 }
1548 else{
1549 x_parent = y;
1550 }
1551 NodeTraits::set_parent(y, z_parent);
1552 this_type::set_child(header, y, z_parent, z_is_leftchild);
1553 }
1554 else {
1555
1556 x_parent = z_parent;
1557 if(x)
1558 NodeTraits::set_parent(x, z_parent);
1559 this_type::set_child(header, x, z_parent, z_is_leftchild);
1560
1561
1562 if(NodeTraits::get_left(header) == z){
1563
1564 BOOST_ASSERT(!z_left);
1565 NodeTraits::set_left(header, !z_right ?
1566 z_parent :
1567 base_type::minimum(z_right));
1568 }
1569 if(NodeTraits::get_right(header) == z){
1570
1571 BOOST_ASSERT(!z_right);
1572 NodeTraits::set_right(header, !z_left ?
1573 z_parent :
1574 base_type::maximum(z_left));
1575 }
1576 }
1577
1578
1579
1580 info.x = x;
1581 info.y = y;
1582
1583
1584 BOOST_ASSERT(!x || NodeTraits::get_parent(x) == x_parent);
1585 info.x_parent = x_parent;
1586 }
1587
1588
1589
1590
1591
1592
1593
1594
1595 static std::size_t subtree_size(const_node_ptr subtree) BOOST_NOEXCEPT
1596 {
1597 std::size_t count = 0;
1598 if (subtree){
1599 node_ptr n = detail::uncast(subtree);
1600 node_ptr m = NodeTraits::get_left(n);
1601 while(m){
1602 n = m;
1603 m = NodeTraits::get_left(n);
1604 }
1605
1606 while(1){
1607 ++count;
1608 node_ptr n_right(NodeTraits::get_right(n));
1609 if(n_right){
1610 n = n_right;
1611 m = NodeTraits::get_left(n);
1612 while(m){
1613 n = m;
1614 m = NodeTraits::get_left(n);
1615 }
1616 }
1617 else {
1618 do{
1619 if (n == subtree){
1620 return count;
1621 }
1622 m = n;
1623 n = NodeTraits::get_parent(n);
1624 }while(NodeTraits::get_left(n) != m);
1625 }
1626 }
1627 }
1628 return count;
1629 }
1630
1631
1632
1633
1634
1635
1636
1637
1638 BOOST_INTRUSIVE_FORCEINLINE static bool is_left_child(node_ptr p) BOOST_NOEXCEPT
1639 { return NodeTraits::get_left(NodeTraits::get_parent(p)) == p; }
1640
1641
1642
1643
1644
1645
1646
1647
1648 BOOST_INTRUSIVE_FORCEINLINE static bool is_right_child(node_ptr p) BOOST_NOEXCEPT
1649 { return NodeTraits::get_right(NodeTraits::get_parent(p)) == p; }
1650
1651 static void insert_before_check
1652 (node_ptr header, node_ptr pos
1653 , insert_commit_data &commit_data
1654 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1655 , std::size_t *pdepth = 0
1656 #endif
1657 )
1658 {
1659 node_ptr prev(pos);
1660 if(pos != NodeTraits::get_left(header))
1661 prev = base_type::prev_node(pos);
1662 bool link_left = unique(header) || !NodeTraits::get_left(pos);
1663 commit_data.link_left = link_left;
1664 commit_data.node = link_left ? pos : prev;
1665 if(pdepth){
1666 *pdepth = commit_data.node == header ? 0 : depth(commit_data.node) + 1;
1667 }
1668 }
1669
1670 static void push_back_check
1671 (node_ptr header, insert_commit_data &commit_data
1672 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1673 , std::size_t *pdepth = 0
1674 #endif
1675 ) BOOST_NOEXCEPT
1676 {
1677 node_ptr prev(NodeTraits::get_right(header));
1678 if(pdepth){
1679 *pdepth = prev == header ? 0 : depth(prev) + 1;
1680 }
1681 commit_data.link_left = false;
1682 commit_data.node = prev;
1683 }
1684
1685 static void push_front_check
1686 (node_ptr header, insert_commit_data &commit_data
1687 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
1688 , std::size_t *pdepth = 0
1689 #endif
1690 ) BOOST_NOEXCEPT
1691 {
1692 node_ptr pos(NodeTraits::get_left(header));
1693 if(pdepth){
1694 *pdepth = pos == header ? 0 : depth(pos) + 1;
1695 }
1696 commit_data.link_left = true;
1697 commit_data.node = pos;
1698 }
1699
1700 template<class NodePtrCompare>
1701 static void insert_equal_check
1702 (node_ptr header, node_ptr hint, node_ptr new_node, NodePtrCompare comp
1703 , insert_commit_data &commit_data
1704
1705 , std::size_t *pdepth = 0
1706
1707 )
1708 {
1709 if(hint == header || !comp(hint, new_node)){
1710 node_ptr prev(hint);
1711 if(hint == NodeTraits::get_left(header) ||
1712 !comp(new_node, (prev = base_type::prev_node(hint)))){
1713 bool link_left = unique(header) || !NodeTraits::get_left(hint);
1714 commit_data.link_left = link_left;
1715 commit_data.node = link_left ? hint : prev;
1716 if(pdepth){
1717 *pdepth = commit_data.node == header ? 0 : depth(commit_data.node) + 1;
1718 }
1719 }
1720 else{
1721 insert_equal_upper_bound_check(header, new_node, comp, commit_data, pdepth);
1722 }
1723 }
1724 else{
1725 insert_equal_lower_bound_check(header, new_node, comp, commit_data, pdepth);
1726 }
1727 }
1728
1729 template<class NodePtrCompare>
1730 static void insert_equal_upper_bound_check
1731 (node_ptr h, node_ptr new_node, NodePtrCompare comp, insert_commit_data & commit_data, std::size_t *pdepth = 0)
1732 {
1733 std::size_t depth = 0;
1734 node_ptr y(h);
1735 node_ptr x(NodeTraits::get_parent(y));
1736
1737 while(x){
1738 ++depth;
1739 y = x;
1740 x = comp(new_node, x) ?
1741 NodeTraits::get_left(x) : NodeTraits::get_right(x);
1742 }
1743 if(pdepth) *pdepth = depth;
1744 commit_data.link_left = (y == h) || comp(new_node, y);
1745 commit_data.node = y;
1746 }
1747
1748 template<class NodePtrCompare>
1749 static void insert_equal_lower_bound_check
1750 (node_ptr h, node_ptr new_node, NodePtrCompare comp, insert_commit_data & commit_data, std::size_t *pdepth = 0)
1751 {
1752 std::size_t depth = 0;
1753 node_ptr y(h);
1754 node_ptr x(NodeTraits::get_parent(y));
1755
1756 while(x){
1757 ++depth;
1758 y = x;
1759 x = !comp(x, new_node) ?
1760 NodeTraits::get_left(x) : NodeTraits::get_right(x);
1761 }
1762 if(pdepth) *pdepth = depth;
1763 commit_data.link_left = (y == h) || !comp(y, new_node);
1764 commit_data.node = y;
1765 }
1766
1767 static void insert_commit
1768 (node_ptr header, node_ptr new_node, const insert_commit_data &commit_data) BOOST_NOEXCEPT
1769 {
1770
1771 BOOST_INTRUSIVE_INVARIANT_ASSERT(commit_data.node != node_ptr());
1772 node_ptr parent_node(commit_data.node);
1773 if(parent_node == header){
1774 NodeTraits::set_parent(header, new_node);
1775 NodeTraits::set_right(header, new_node);
1776 NodeTraits::set_left(header, new_node);
1777 }
1778 else if(commit_data.link_left){
1779 NodeTraits::set_left(parent_node, new_node);
1780 if(parent_node == NodeTraits::get_left(header))
1781 NodeTraits::set_left(header, new_node);
1782 }
1783 else{
1784 NodeTraits::set_right(parent_node, new_node);
1785 if(parent_node == NodeTraits::get_right(header))
1786 NodeTraits::set_right(header, new_node);
1787 }
1788 NodeTraits::set_parent(new_node, parent_node);
1789 NodeTraits::set_right(new_node, node_ptr());
1790 NodeTraits::set_left(new_node, node_ptr());
1791 }
1792
1793
1794 static void set_child(node_ptr header, node_ptr new_child, node_ptr new_parent, const bool link_left) BOOST_NOEXCEPT
1795 {
1796 if(new_parent == header)
1797 NodeTraits::set_parent(header, new_child);
1798 else if(link_left)
1799 NodeTraits::set_left(new_parent, new_child);
1800 else
1801 NodeTraits::set_right(new_parent, new_child);
1802 }
1803
1804
1805 static void rotate_left_no_parent_fix(node_ptr p, node_ptr p_right) BOOST_NOEXCEPT
1806 {
1807 node_ptr p_right_left(NodeTraits::get_left(p_right));
1808 NodeTraits::set_right(p, p_right_left);
1809 if(p_right_left){
1810 NodeTraits::set_parent(p_right_left, p);
1811 }
1812 NodeTraits::set_left(p_right, p);
1813 NodeTraits::set_parent(p, p_right);
1814 }
1815
1816
1817 static void rotate_left(node_ptr p, node_ptr p_right, node_ptr p_parent, node_ptr header) BOOST_NOEXCEPT
1818 {
1819 const bool p_was_left(NodeTraits::get_left(p_parent) == p);
1820 rotate_left_no_parent_fix(p, p_right);
1821 NodeTraits::set_parent(p_right, p_parent);
1822 set_child(header, p_right, p_parent, p_was_left);
1823 }
1824
1825
1826 static void rotate_right_no_parent_fix(node_ptr p, node_ptr p_left) BOOST_NOEXCEPT
1827 {
1828 node_ptr p_left_right(NodeTraits::get_right(p_left));
1829 NodeTraits::set_left(p, p_left_right);
1830 if(p_left_right){
1831 NodeTraits::set_parent(p_left_right, p);
1832 }
1833 NodeTraits::set_right(p_left, p);
1834 NodeTraits::set_parent(p, p_left);
1835 }
1836
1837
1838 static void rotate_right(node_ptr p, node_ptr p_left, node_ptr p_parent, node_ptr header) BOOST_NOEXCEPT
1839 {
1840 const bool p_was_left(NodeTraits::get_left(p_parent) == p);
1841 rotate_right_no_parent_fix(p, p_left);
1842 NodeTraits::set_parent(p_left, p_parent);
1843 set_child(header, p_left, p_parent, p_was_left);
1844 }
1845
1846 private:
1847
1848 static void subtree_to_vine(node_ptr vine_tail, std::size_t &size) BOOST_NOEXCEPT
1849 {
1850
1851
1852
1853
1854
1855
1856 std::size_t len = 0;
1857 node_ptr remainder = NodeTraits::get_right(vine_tail);
1858 while(remainder){
1859 node_ptr tempptr = NodeTraits::get_left(remainder);
1860 if(!tempptr){
1861 vine_tail = remainder;
1862 remainder = NodeTraits::get_right(remainder);
1863 ++len;
1864 }
1865 else{
1866 NodeTraits::set_left(remainder, NodeTraits::get_right(tempptr));
1867 NodeTraits::set_right(tempptr, remainder);
1868 remainder = tempptr;
1869 NodeTraits::set_right(vine_tail, tempptr);
1870 }
1871 }
1872 size = len;
1873 }
1874
1875 static void compress_subtree(node_ptr scanner, std::size_t count) BOOST_NOEXCEPT
1876 {
1877 while(count--){
1878 node_ptr child = NodeTraits::get_right(scanner);
1879 node_ptr child_right = NodeTraits::get_right(child);
1880 NodeTraits::set_right(scanner, child_right);
1881
1882 scanner = child_right;
1883 node_ptr scanner_left = NodeTraits::get_left(scanner);
1884 NodeTraits::set_right(child, scanner_left);
1885 if(scanner_left)
1886 NodeTraits::set_parent(scanner_left, child);
1887 NodeTraits::set_left(scanner, child);
1888 NodeTraits::set_parent(child, scanner);
1889 }
1890 }
1891
1892 static void vine_to_subtree(node_ptr super_root, std::size_t count) BOOST_NOEXCEPT
1893 {
1894 const std::size_t one_szt = 1u;
1895 std::size_t leaf_nodes = count + one_szt - std::size_t(one_szt << detail::floor_log2(count + one_szt));
1896 compress_subtree(super_root, leaf_nodes);
1897 std::size_t vine_nodes = count - leaf_nodes;
1898 while(vine_nodes > 1){
1899 vine_nodes /= 2;
1900 compress_subtree(super_root, vine_nodes);
1901 }
1902
1903
1904
1905 for ( node_ptr q = super_root, p = NodeTraits::get_right(super_root)
1906 ; p
1907 ; q = p, p = NodeTraits::get_right(p)){
1908 NodeTraits::set_parent(p, q);
1909 }
1910 }
1911
1912
1913
1914
1915
1916
1917
1918
1919 static node_ptr get_root(node_ptr n) BOOST_NOEXCEPT
1920 {
1921 BOOST_INTRUSIVE_INVARIANT_ASSERT((!inited(n)));
1922 node_ptr x = NodeTraits::get_parent(n);
1923 if(x){
1924 while(!base_type::is_header(x)){
1925 x = NodeTraits::get_parent(x);
1926 }
1927 return x;
1928 }
1929 else{
1930 return n;
1931 }
1932 }
1933
1934 template <class Cloner, class Disposer>
1935 static node_ptr clone_subtree
1936 (const_node_ptr source_parent, node_ptr target_parent
1937 , Cloner cloner, Disposer disposer
1938 , node_ptr &leftmost_out, node_ptr &rightmost_out
1939 )
1940 {
1941 node_ptr target_sub_root = target_parent;
1942 node_ptr source_root = NodeTraits::get_parent(source_parent);
1943 if(!source_root){
1944 leftmost_out = rightmost_out = source_root;
1945 }
1946 else{
1947
1948 node_ptr current = source_root;
1949 node_ptr insertion_point = target_sub_root = cloner(current);
1950
1951
1952 node_ptr leftmost = target_sub_root;
1953 node_ptr rightmost = target_sub_root;
1954
1955
1956 NodeTraits::set_left(target_sub_root, node_ptr());
1957 NodeTraits::set_right(target_sub_root, node_ptr());
1958 NodeTraits::set_parent(target_sub_root, target_parent);
1959
1960 dispose_subtree_disposer<Disposer> rollback(disposer, target_sub_root);
1961 while(true) {
1962
1963 if( NodeTraits::get_left(current) &&
1964 !NodeTraits::get_left(insertion_point)) {
1965 current = NodeTraits::get_left(current);
1966 node_ptr temp = insertion_point;
1967
1968 insertion_point = cloner(current);
1969 NodeTraits::set_left (insertion_point, node_ptr());
1970 NodeTraits::set_right (insertion_point, node_ptr());
1971
1972 NodeTraits::set_parent(insertion_point, temp);
1973 NodeTraits::set_left (temp, insertion_point);
1974
1975 if(rightmost == target_sub_root)
1976 leftmost = insertion_point;
1977 }
1978
1979 else if( NodeTraits::get_right(current) &&
1980 !NodeTraits::get_right(insertion_point)){
1981 current = NodeTraits::get_right(current);
1982 node_ptr temp = insertion_point;
1983
1984 insertion_point = cloner(current);
1985 NodeTraits::set_left (insertion_point, node_ptr());
1986 NodeTraits::set_right (insertion_point, node_ptr());
1987
1988 NodeTraits::set_parent(insertion_point, temp);
1989 NodeTraits::set_right (temp, insertion_point);
1990
1991 rightmost = insertion_point;
1992 }
1993
1994 else if(current == source_root){
1995 break;
1996 }
1997 else{
1998
1999 current = NodeTraits::get_parent(current);
2000 insertion_point = NodeTraits::get_parent(insertion_point);
2001 }
2002 }
2003 rollback.release();
2004 leftmost_out = leftmost;
2005 rightmost_out = rightmost;
2006 }
2007 return target_sub_root;
2008 }
2009
2010 template<class Disposer>
2011 static void dispose_subtree(node_ptr x, Disposer disposer) BOOST_NOEXCEPT
2012 {
2013 while (x){
2014 node_ptr save(NodeTraits::get_left(x));
2015 if (save) {
2016
2017 NodeTraits::set_left(x, NodeTraits::get_right(save));
2018 NodeTraits::set_right(save, x);
2019 }
2020 else {
2021 save = NodeTraits::get_right(x);
2022 init(x);
2023 disposer(x);
2024 }
2025 x = save;
2026 }
2027 }
2028
2029 template<class KeyType, class KeyNodePtrCompare>
2030 static node_ptr lower_bound_loop
2031 (node_ptr x, node_ptr y, const KeyType &key, KeyNodePtrCompare comp)
2032 {
2033 while(x){
2034 if(comp(x, key)){
2035 x = NodeTraits::get_right(x);
2036 }
2037 else{
2038 y = x;
2039 x = NodeTraits::get_left(x);
2040 }
2041 }
2042 return y;
2043 }
2044
2045 template<class KeyType, class KeyNodePtrCompare>
2046 static node_ptr upper_bound_loop
2047 (node_ptr x, node_ptr y, const KeyType &key, KeyNodePtrCompare comp)
2048 {
2049 while(x){
2050 if(comp(key, x)){
2051 y = x;
2052 x = NodeTraits::get_left(x);
2053 }
2054 else{
2055 x = NodeTraits::get_right(x);
2056 }
2057 }
2058 return y;
2059 }
2060
2061 template<class Checker>
2062 static void check_subtree(const_node_ptr n, Checker checker, typename Checker::return_type& check_return)
2063 {
2064 const_node_ptr left = NodeTraits::get_left(n);
2065 const_node_ptr right = NodeTraits::get_right(n);
2066 typename Checker::return_type check_return_left;
2067 typename Checker::return_type check_return_right;
2068 if (left)
2069 {
2070 BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_parent(left) == n);
2071 check_subtree(left, checker, check_return_left);
2072 }
2073 if (right)
2074 {
2075 BOOST_INTRUSIVE_INVARIANT_ASSERT(NodeTraits::get_parent(right) == n);
2076 check_subtree(right, checker, check_return_right);
2077 }
2078 checker(n, check_return_left, check_return_right, check_return);
2079 }
2080 };
2081
2082
2083
2084 template<class NodeTraits>
2085 struct get_algo<BsTreeAlgorithms, NodeTraits>
2086 {
2087 typedef bstree_algorithms<NodeTraits> type;
2088 };
2089
2090 template <class ValueTraits, class NodePtrCompare, class ExtraChecker>
2091 struct get_node_checker<BsTreeAlgorithms, ValueTraits, NodePtrCompare, ExtraChecker>
2092 {
2093 typedef detail::bstree_node_checker<ValueTraits, NodePtrCompare, ExtraChecker> type;
2094 };
2095
2096
2097
2098 }
2099 }
2100
2101 #include <boost/intrusive/detail/config_end.hpp>
2102
2103 #endif