File indexing completed on 2025-01-18 09:42:08
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #ifndef BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_NODE_HPP
0037 #define BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_NODE_HPP
0038
0039 #if defined(_MSC_VER)
0040 #pragma once
0041 #endif
0042
0043 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
0044 #include <cstddef>
0045 #include <boost/multi_index/detail/allocator_traits.hpp>
0046 #include <boost/multi_index/detail/raw_ptr.hpp>
0047
0048 #if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES)
0049 #include <boost/mpl/and.hpp>
0050 #include <boost/mpl/if.hpp>
0051 #include <boost/multi_index/detail/uintptr_type.hpp>
0052 #include <boost/type_traits/alignment_of.hpp>
0053 #include <boost/type_traits/is_same.hpp>
0054 #endif
0055
0056 namespace boost{
0057
0058 namespace multi_index{
0059
0060 namespace detail{
0061
0062
0063
0064 enum ordered_index_color{red=false,black=true};
0065 enum ordered_index_side{to_left=false,to_right=true};
0066
0067 template<typename AugmentPolicy,typename Allocator>
0068 struct ordered_index_node_impl;
0069
0070 template<typename AugmentPolicy,typename Allocator>
0071 struct ordered_index_node_traits
0072 {
0073 typedef typename rebind_alloc_for<
0074 Allocator,
0075 ordered_index_node_impl<AugmentPolicy,Allocator>
0076 >::type allocator;
0077 typedef allocator_traits<allocator> alloc_traits;
0078 typedef typename alloc_traits::pointer pointer;
0079 typedef typename alloc_traits::const_pointer const_pointer;
0080 typedef typename alloc_traits::difference_type difference_type;
0081 typedef typename alloc_traits::size_type size_type;
0082 };
0083
0084 template<typename AugmentPolicy,typename Allocator>
0085 struct ordered_index_node_std_base
0086 {
0087 typedef ordered_index_node_traits<
0088 AugmentPolicy,Allocator> node_traits;
0089 typedef typename node_traits::allocator node_allocator;
0090 typedef typename node_traits::pointer pointer;
0091 typedef typename node_traits::const_pointer const_pointer;
0092 typedef typename node_traits::difference_type difference_type;
0093 typedef typename node_traits::size_type size_type;
0094 typedef ordered_index_color& color_ref;
0095 typedef pointer& parent_ref;
0096
0097 ordered_index_color& color(){return color_;}
0098 ordered_index_color color()const{return color_;}
0099 pointer& parent(){return parent_;}
0100 pointer parent()const{return parent_;}
0101 pointer& left(){return left_;}
0102 pointer left()const{return left_;}
0103 pointer& right(){return right_;}
0104 pointer right()const{return right_;}
0105
0106 private:
0107 ordered_index_color color_;
0108 pointer parent_;
0109 pointer left_;
0110 pointer right_;
0111 };
0112
0113 #if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES)
0114
0115
0116
0117
0118
0119
0120 #if defined(BOOST_MSVC)
0121
0122
0123
0124
0125
0126
0127 #pragma warning(push)
0128 #pragma warning(disable:4312 4311)
0129 #endif
0130
0131 template<typename AugmentPolicy,typename Allocator>
0132 struct ordered_index_node_compressed_base
0133 {
0134 typedef ordered_index_node_traits<
0135 AugmentPolicy,Allocator> node_traits;
0136 typedef ordered_index_node_impl<
0137 AugmentPolicy,Allocator>* pointer;
0138 typedef const ordered_index_node_impl<
0139 AugmentPolicy,Allocator>* const_pointer;
0140 typedef typename node_traits::difference_type difference_type;
0141 typedef typename node_traits::size_type size_type;
0142
0143 struct color_ref
0144 {
0145 color_ref(uintptr_type* r_):r(r_){}
0146 color_ref(const color_ref& x):r(x.r){}
0147
0148 operator ordered_index_color()const
0149 {
0150 return ordered_index_color(*r&uintptr_type(1));
0151 }
0152
0153 color_ref& operator=(ordered_index_color c)
0154 {
0155 *r&=~uintptr_type(1);
0156 *r|=uintptr_type(c);
0157 return *this;
0158 }
0159
0160 color_ref& operator=(const color_ref& x)
0161 {
0162 return operator=(x.operator ordered_index_color());
0163 }
0164
0165 private:
0166 uintptr_type* r;
0167 };
0168
0169 struct parent_ref
0170 {
0171 parent_ref(uintptr_type* r_):r(r_){}
0172 parent_ref(const parent_ref& x):r(x.r){}
0173
0174 operator pointer()const
0175 {
0176 return (pointer)(void*)(*r&~uintptr_type(1));
0177 }
0178
0179 parent_ref& operator=(pointer p)
0180 {
0181 *r=((uintptr_type)(void*)p)|(*r&uintptr_type(1));
0182 return *this;
0183 }
0184
0185 parent_ref& operator=(const parent_ref& x)
0186 {
0187 return operator=(x.operator pointer());
0188 }
0189
0190 pointer operator->()const
0191 {
0192 return operator pointer();
0193 }
0194
0195 private:
0196 uintptr_type* r;
0197 };
0198
0199 color_ref color(){return color_ref(&parentcolor_);}
0200 ordered_index_color color()const
0201 {
0202 return ordered_index_color(parentcolor_&uintptr_type(1));
0203 }
0204
0205 parent_ref parent(){return parent_ref(&parentcolor_);}
0206 pointer parent()const
0207 {
0208 return (pointer)(void*)(parentcolor_&~uintptr_type(1));
0209 }
0210
0211 pointer& left(){return left_;}
0212 pointer left()const{return left_;}
0213 pointer& right(){return right_;}
0214 pointer right()const{return right_;}
0215
0216 private:
0217 uintptr_type parentcolor_;
0218 pointer left_;
0219 pointer right_;
0220 };
0221 #if defined(BOOST_MSVC)
0222 #pragma warning(pop)
0223 #endif
0224 #endif
0225
0226 template<typename AugmentPolicy,typename Allocator>
0227 struct ordered_index_node_impl_base:
0228
0229 #if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES)
0230 AugmentPolicy::template augmented_node<
0231 typename mpl::if_c<
0232 !(has_uintptr_type::value)||
0233 (alignment_of<
0234 ordered_index_node_compressed_base<AugmentPolicy,Allocator>
0235 >::value%2)||
0236 !(is_same<
0237 typename ordered_index_node_traits<AugmentPolicy,Allocator>::pointer,
0238 ordered_index_node_impl<AugmentPolicy,Allocator>*>::value),
0239 ordered_index_node_std_base<AugmentPolicy,Allocator>,
0240 ordered_index_node_compressed_base<AugmentPolicy,Allocator>
0241 >::type
0242 >::type
0243 #else
0244 AugmentPolicy::template augmented_node<
0245 ordered_index_node_std_base<AugmentPolicy,Allocator>
0246 >::type
0247 #endif
0248
0249 {};
0250
0251 template<typename AugmentPolicy,typename Allocator>
0252 struct ordered_index_node_impl:
0253 ordered_index_node_impl_base<AugmentPolicy,Allocator>
0254 {
0255 private:
0256 typedef ordered_index_node_impl_base<AugmentPolicy,Allocator> super;
0257
0258 public:
0259 typedef typename super::color_ref color_ref;
0260 typedef typename super::parent_ref parent_ref;
0261 typedef typename super::pointer pointer;
0262 typedef typename super::const_pointer const_pointer;
0263
0264
0265
0266 static void increment(pointer& x)
0267 {
0268 if(x->right()!=pointer(0)){
0269 x=x->right();
0270 while(x->left()!=pointer(0))x=x->left();
0271 }
0272 else{
0273 pointer y=x->parent();
0274 while(x==y->right()){
0275 x=y;
0276 y=y->parent();
0277 }
0278 if(x->right()!=y)x=y;
0279 }
0280 }
0281
0282 static void decrement(pointer& x)
0283 {
0284 if(x->color()==red&&x->parent()->parent()==x){
0285 x=x->right();
0286 }
0287 else if(x->left()!=pointer(0)){
0288 pointer y=x->left();
0289 while(y->right()!=pointer(0))y=y->right();
0290 x=y;
0291 }else{
0292 pointer y=x->parent();
0293 while(x==y->left()){
0294 x=y;
0295 y=y->parent();
0296 }
0297 x=y;
0298 }
0299 }
0300
0301
0302
0303 static void rotate_left(pointer x,parent_ref root)
0304 {
0305 pointer y=x->right();
0306 x->right()=y->left();
0307 if(y->left()!=pointer(0))y->left()->parent()=x;
0308 y->parent()=x->parent();
0309
0310 if(x==root) root=y;
0311 else if(x==x->parent()->left())x->parent()->left()=y;
0312 else x->parent()->right()=y;
0313 y->left()=x;
0314 x->parent()=y;
0315 AugmentPolicy::rotate_left(x,y);
0316 }
0317
0318 static pointer minimum(pointer x)
0319 {
0320 while(x->left()!=pointer(0))x=x->left();
0321 return x;
0322 }
0323
0324 static pointer maximum(pointer x)
0325 {
0326 while(x->right()!=pointer(0))x=x->right();
0327 return x;
0328 }
0329
0330 static void rotate_right(pointer x,parent_ref root)
0331 {
0332 pointer y=x->left();
0333 x->left()=y->right();
0334 if(y->right()!=pointer(0))y->right()->parent()=x;
0335 y->parent()=x->parent();
0336
0337 if(x==root) root=y;
0338 else if(x==x->parent()->right())x->parent()->right()=y;
0339 else x->parent()->left()=y;
0340 y->right()=x;
0341 x->parent()=y;
0342 AugmentPolicy::rotate_right(x,y);
0343 }
0344
0345 static void rebalance(pointer x,parent_ref root)
0346 {
0347 x->color()=red;
0348 while(x!=root&&x->parent()->color()==red){
0349 if(x->parent()==x->parent()->parent()->left()){
0350 pointer y=x->parent()->parent()->right();
0351 if(y!=pointer(0)&&y->color()==red){
0352 x->parent()->color()=black;
0353 y->color()=black;
0354 x->parent()->parent()->color()=red;
0355 x=x->parent()->parent();
0356 }
0357 else{
0358 if(x==x->parent()->right()){
0359 x=x->parent();
0360 rotate_left(x,root);
0361 }
0362 x->parent()->color()=black;
0363 x->parent()->parent()->color()=red;
0364 rotate_right(x->parent()->parent(),root);
0365 }
0366 }
0367 else{
0368 pointer y=x->parent()->parent()->left();
0369 if(y!=pointer(0)&&y->color()==red){
0370 x->parent()->color()=black;
0371 y->color()=black;
0372 x->parent()->parent()->color()=red;
0373 x=x->parent()->parent();
0374 }
0375 else{
0376 if(x==x->parent()->left()){
0377 x=x->parent();
0378 rotate_right(x,root);
0379 }
0380 x->parent()->color()=black;
0381 x->parent()->parent()->color()=red;
0382 rotate_left(x->parent()->parent(),root);
0383 }
0384 }
0385 }
0386 root->color()=black;
0387 }
0388
0389 static void link(
0390 pointer x,ordered_index_side side,pointer position,pointer header)
0391 {
0392 if(side==to_left){
0393 position->left()=x;
0394 if(position==header){
0395 header->parent()=x;
0396 header->right()=x;
0397 }
0398 else if(position==header->left()){
0399 header->left()=x;
0400 }
0401 }
0402 else{
0403 position->right()=x;
0404 if(position==header->right()){
0405 header->right()=x;
0406 }
0407 }
0408 x->parent()=position;
0409 x->left()=pointer(0);
0410 x->right()=pointer(0);
0411 AugmentPolicy::add(x,pointer(header->parent()));
0412 ordered_index_node_impl::rebalance(x,header->parent());
0413 }
0414
0415 static pointer rebalance_for_extract(
0416 pointer z,parent_ref root,pointer& leftmost,pointer& rightmost)
0417 {
0418 pointer y=z;
0419 pointer x=pointer(0);
0420 pointer x_parent=pointer(0);
0421 if(y->left()==pointer(0)){
0422 x=y->right();
0423 }
0424 else{
0425 if(y->right()==pointer(0)){
0426 x=y->left();
0427 }
0428 else{
0429 y=y->right();
0430 while(y->left()!=pointer(0))y=y->left();
0431 x=y->right();
0432 }
0433 }
0434 AugmentPolicy::remove(y,pointer(root));
0435 if(y!=z){
0436 AugmentPolicy::copy(z,y);
0437 z->left()->parent()=y;
0438 y->left()=z->left();
0439 if(y!=z->right()){
0440 x_parent=y->parent();
0441 if(x!=pointer(0))x->parent()=y->parent();
0442 y->parent()->left()=x;
0443 y->right()=z->right();
0444 z->right()->parent()=y;
0445 }
0446 else{
0447 x_parent=y;
0448 }
0449
0450 if(root==z) root=y;
0451 else if(z->parent()->left()==z)z->parent()->left()=y;
0452 else z->parent()->right()=y;
0453 y->parent()=z->parent();
0454 ordered_index_color c=y->color();
0455 y->color()=z->color();
0456 z->color()=c;
0457 y=z;
0458 }
0459 else{
0460 x_parent=y->parent();
0461 if(x!=pointer(0))x->parent()=y->parent();
0462 if(root==z){
0463 root=x;
0464 }
0465 else{
0466 if(z->parent()->left()==z)z->parent()->left()=x;
0467 else z->parent()->right()=x;
0468 }
0469 if(leftmost==z){
0470 if(z->right()==pointer(0)){
0471 leftmost=z->parent();
0472 }
0473 else{
0474 leftmost=minimum(x);
0475 }
0476 }
0477 if(rightmost==z){
0478 if(z->left()==pointer(0)){
0479 rightmost=z->parent();
0480 }
0481 else{
0482 rightmost=maximum(x);
0483 }
0484 }
0485 }
0486 if(y->color()!=red){
0487 while(x!=root&&(x==pointer(0)|| x->color()==black)){
0488 if(x==x_parent->left()){
0489 pointer w=x_parent->right();
0490 if(w->color()==red){
0491 w->color()=black;
0492 x_parent->color()=red;
0493 rotate_left(x_parent,root);
0494 w=x_parent->right();
0495 }
0496 if((w->left()==pointer(0)||w->left()->color()==black) &&
0497 (w->right()==pointer(0)||w->right()->color()==black)){
0498 w->color()=red;
0499 x=x_parent;
0500 x_parent=x_parent->parent();
0501 }
0502 else{
0503 if(w->right()==pointer(0 )
0504 || w->right()->color()==black){
0505 if(w->left()!=pointer(0)) w->left()->color()=black;
0506 w->color()=red;
0507 rotate_right(w,root);
0508 w=x_parent->right();
0509 }
0510 w->color()=x_parent->color();
0511 x_parent->color()=black;
0512 if(w->right()!=pointer(0))w->right()->color()=black;
0513 rotate_left(x_parent,root);
0514 break;
0515 }
0516 }
0517 else{
0518 pointer w=x_parent->left();
0519 if(w->color()==red){
0520 w->color()=black;
0521 x_parent->color()=red;
0522 rotate_right(x_parent,root);
0523 w=x_parent->left();
0524 }
0525 if((w->right()==pointer(0)||w->right()->color()==black) &&
0526 (w->left()==pointer(0)||w->left()->color()==black)){
0527 w->color()=red;
0528 x=x_parent;
0529 x_parent=x_parent->parent();
0530 }
0531 else{
0532 if(w->left()==pointer(0)||w->left()->color()==black){
0533 if(w->right()!=pointer(0))w->right()->color()=black;
0534 w->color()=red;
0535 rotate_left(w,root);
0536 w=x_parent->left();
0537 }
0538 w->color()=x_parent->color();
0539 x_parent->color()=black;
0540 if(w->left()!=pointer(0))w->left()->color()=black;
0541 rotate_right(x_parent,root);
0542 break;
0543 }
0544 }
0545 }
0546 if(x!=pointer(0))x->color()=black;
0547 }
0548 return y;
0549 }
0550
0551 static void restore(pointer x,pointer position,pointer header)
0552 {
0553 if(position->left()==pointer(0)||position->left()==header){
0554 link(x,to_left,position,header);
0555 }
0556 else{
0557 decrement(position);
0558 link(x,to_right,position,header);
0559 }
0560 }
0561
0562 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
0563
0564
0565 static std::size_t black_count(pointer node,pointer root)
0566 {
0567 if(node==pointer(0))return 0;
0568 std::size_t sum=0;
0569 for(;;){
0570 if(node->color()==black)++sum;
0571 if(node==root)break;
0572 node=node->parent();
0573 }
0574 return sum;
0575 }
0576 #endif
0577 };
0578
0579 template<typename AugmentPolicy,typename Super>
0580 struct ordered_index_node_trampoline:
0581 ordered_index_node_impl<
0582 AugmentPolicy,
0583 typename rebind_alloc_for<
0584 typename Super::allocator_type,
0585 char
0586 >::type
0587 >
0588 {
0589 typedef ordered_index_node_impl<
0590 AugmentPolicy,
0591 typename rebind_alloc_for<
0592 typename Super::allocator_type,
0593 char
0594 >::type
0595 > impl_type;
0596 };
0597
0598 template<typename AugmentPolicy,typename Super>
0599 struct ordered_index_node:
0600 Super,ordered_index_node_trampoline<AugmentPolicy,Super>
0601 {
0602 private:
0603 typedef ordered_index_node_trampoline<AugmentPolicy,Super> trampoline;
0604
0605 public:
0606 typedef typename trampoline::impl_type impl_type;
0607 typedef typename trampoline::color_ref impl_color_ref;
0608 typedef typename trampoline::parent_ref impl_parent_ref;
0609 typedef typename trampoline::pointer impl_pointer;
0610 typedef typename trampoline::const_pointer const_impl_pointer;
0611 typedef typename trampoline::difference_type difference_type;
0612 typedef typename trampoline::size_type size_type;
0613
0614 impl_color_ref color(){return trampoline::color();}
0615 ordered_index_color color()const{return trampoline::color();}
0616 impl_parent_ref parent(){return trampoline::parent();}
0617 impl_pointer parent()const{return trampoline::parent();}
0618 impl_pointer& left(){return trampoline::left();}
0619 impl_pointer left()const{return trampoline::left();}
0620 impl_pointer& right(){return trampoline::right();}
0621 impl_pointer right()const{return trampoline::right();}
0622
0623 impl_pointer impl()
0624 {
0625 return static_cast<impl_pointer>(
0626 static_cast<impl_type*>(static_cast<trampoline*>(this)));
0627 }
0628
0629 const_impl_pointer impl()const
0630 {
0631 return static_cast<const_impl_pointer>(
0632 static_cast<const impl_type*>(static_cast<const trampoline*>(this)));
0633 }
0634
0635 static ordered_index_node* from_impl(impl_pointer x)
0636 {
0637 return
0638 static_cast<ordered_index_node*>(
0639 static_cast<trampoline*>(
0640 raw_ptr<impl_type*>(x)));
0641 }
0642
0643 static const ordered_index_node* from_impl(const_impl_pointer x)
0644 {
0645 return
0646 static_cast<const ordered_index_node*>(
0647 static_cast<const trampoline*>(
0648 raw_ptr<const impl_type*>(x)));
0649 }
0650
0651
0652
0653 static void increment(ordered_index_node*& x)
0654 {
0655 impl_pointer xi=x->impl();
0656 trampoline::increment(xi);
0657 x=from_impl(xi);
0658 }
0659
0660 static void decrement(ordered_index_node*& x)
0661 {
0662 impl_pointer xi=x->impl();
0663 trampoline::decrement(xi);
0664 x=from_impl(xi);
0665 }
0666 };
0667
0668 }
0669
0670 }
0671
0672 }
0673
0674 #endif