File indexing completed on 2025-01-18 09:42:07
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_MULTI_INDEX_DETAIL_HASH_INDEX_NODE_HPP
0010 #define BOOST_MULTI_INDEX_DETAIL_HASH_INDEX_NODE_HPP
0011
0012 #if defined(_MSC_VER)
0013 #pragma once
0014 #endif
0015
0016 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
0017 #include <boost/multi_index/detail/allocator_traits.hpp>
0018 #include <boost/multi_index/detail/raw_ptr.hpp>
0019 #include <utility>
0020
0021 namespace boost{
0022
0023 namespace multi_index{
0024
0025 namespace detail{
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094 template<typename Allocator>
0095 struct hashed_index_node_impl;
0096
0097
0098
0099 template<typename Allocator>
0100 struct hashed_index_base_node_impl
0101 {
0102 typedef typename rebind_alloc_for<
0103 Allocator,hashed_index_base_node_impl
0104 >::type base_allocator;
0105 typedef typename rebind_alloc_for<
0106 Allocator,hashed_index_node_impl<Allocator>
0107 >::type node_allocator;
0108 typedef allocator_traits<base_allocator> base_alloc_traits;
0109 typedef allocator_traits<node_allocator> node_alloc_traits;
0110 typedef typename base_alloc_traits::pointer base_pointer;
0111 typedef typename base_alloc_traits::const_pointer const_base_pointer;
0112 typedef typename node_alloc_traits::pointer pointer;
0113 typedef typename node_alloc_traits::const_pointer const_pointer;
0114 typedef typename node_alloc_traits::difference_type difference_type;
0115
0116 pointer& prior(){return prior_;}
0117 pointer prior()const{return prior_;}
0118
0119 private:
0120 pointer prior_;
0121 };
0122
0123
0124
0125 template<typename Allocator>
0126 struct hashed_index_node_impl:hashed_index_base_node_impl<Allocator>
0127 {
0128 private:
0129 typedef hashed_index_base_node_impl<Allocator> super;
0130
0131 public:
0132 typedef typename super::base_pointer base_pointer;
0133 typedef typename super::const_base_pointer const_base_pointer;
0134 typedef typename super::pointer pointer;
0135 typedef typename super::const_pointer const_pointer;
0136
0137 base_pointer& next(){return next_;}
0138 base_pointer next()const{return next_;}
0139
0140 static pointer pointer_from(base_pointer x)
0141 {
0142 return static_cast<pointer>(
0143 static_cast<hashed_index_node_impl*>(
0144 raw_ptr<super*>(x)));
0145 }
0146
0147 static base_pointer base_pointer_from(pointer x)
0148 {
0149 return static_cast<base_pointer>(
0150 raw_ptr<hashed_index_node_impl*>(x));
0151 }
0152
0153 private:
0154 base_pointer next_;
0155 };
0156
0157
0158
0159
0160
0161
0162
0163
0164 struct default_assigner
0165 {
0166 template<typename T> void operator()(T& x,const T& val){x=val;}
0167 };
0168
0169 template<typename Node>
0170 struct unlink_undo_assigner
0171 {
0172 typedef typename Node::base_pointer base_pointer;
0173 typedef typename Node::pointer pointer;
0174
0175 unlink_undo_assigner():pointer_track_count(0),base_pointer_track_count(0){}
0176
0177 void operator()(pointer& x,pointer val)
0178 {
0179 pointer_tracks[pointer_track_count].x=&x;
0180 pointer_tracks[pointer_track_count++].val=x;
0181 x=val;
0182 }
0183
0184 void operator()(base_pointer& x,base_pointer val)
0185 {
0186 base_pointer_tracks[base_pointer_track_count].x=&x;
0187 base_pointer_tracks[base_pointer_track_count++].val=x;
0188 x=val;
0189 }
0190
0191 void operator()()
0192 {
0193
0194
0195 while(pointer_track_count--){
0196 *(pointer_tracks[pointer_track_count].x)=
0197 pointer_tracks[pointer_track_count].val;
0198 }
0199 while(base_pointer_track_count--){
0200 *(base_pointer_tracks[base_pointer_track_count].x)=
0201 base_pointer_tracks[base_pointer_track_count].val;
0202 }
0203 }
0204
0205 struct pointer_track {pointer* x; pointer val;};
0206 struct base_pointer_track{base_pointer* x; base_pointer val;};
0207
0208
0209
0210
0211
0212
0213 pointer_track pointer_tracks[3];
0214 int pointer_track_count;
0215 base_pointer_track base_pointer_tracks[2];
0216 int base_pointer_track_count;
0217 };
0218
0219
0220
0221 struct hashed_unique_tag{};
0222 struct hashed_non_unique_tag{};
0223
0224 template<typename Node,typename Category>
0225 struct hashed_index_node_alg;
0226
0227 template<typename Node>
0228 struct hashed_index_node_alg<Node,hashed_unique_tag>
0229 {
0230 typedef typename Node::base_pointer base_pointer;
0231 typedef typename Node::const_base_pointer const_base_pointer;
0232 typedef typename Node::pointer pointer;
0233 typedef typename Node::const_pointer const_pointer;
0234
0235 static bool is_first_of_bucket(pointer x)
0236 {
0237 return x->prior()->next()!=base_pointer_from(x);
0238 }
0239
0240 static pointer after(pointer x)
0241 {
0242 return is_last_of_bucket(x)?x->next()->prior():pointer_from(x->next());
0243 }
0244
0245 static pointer after_local(pointer x)
0246 {
0247 return is_last_of_bucket(x)?pointer(0):pointer_from(x->next());
0248 }
0249
0250 static pointer next_to_inspect(pointer x)
0251 {
0252 return is_last_of_bucket(x)?pointer(0):pointer_from(x->next());
0253 }
0254
0255 static void link(pointer x,base_pointer buc,pointer end)
0256 {
0257 if(buc->prior()==pointer(0)){
0258 x->prior()=end->prior();
0259 x->next()=end->prior()->next();
0260 x->prior()->next()=buc;
0261 buc->prior()=x;
0262 end->prior()=x;
0263 }
0264 else{
0265 x->prior()=buc->prior()->prior();
0266 x->next()=base_pointer_from(buc->prior());
0267 buc->prior()=x;
0268 x->next()->prior()=x;
0269 }
0270 }
0271
0272 static void unlink(pointer x)
0273 {
0274 default_assigner assign;
0275 unlink(x,assign);
0276 }
0277
0278 typedef unlink_undo_assigner<Node> unlink_undo;
0279
0280 template<typename Assigner>
0281 static void unlink(pointer x,Assigner& assign)
0282 {
0283 if(is_first_of_bucket(x)){
0284 if(is_last_of_bucket(x)){
0285 assign(x->prior()->next()->prior(),pointer(0));
0286 assign(x->prior()->next(),x->next());
0287 assign(x->next()->prior()->prior(),x->prior());
0288 }
0289 else{
0290 assign(x->prior()->next()->prior(),pointer_from(x->next()));
0291 assign(x->next()->prior(),x->prior());
0292 }
0293 }
0294 else if(is_last_of_bucket(x)){
0295 assign(x->prior()->next(),x->next());
0296 assign(x->next()->prior()->prior(),x->prior());
0297 }
0298 else{
0299 assign(x->prior()->next(),x->next());
0300 assign(x->next()->prior(),x->prior());
0301 }
0302 }
0303
0304
0305
0306 static void append(pointer x,pointer end)
0307 {
0308 x->prior()=end->prior();
0309 x->next()=end->prior()->next();
0310 x->prior()->next()=base_pointer_from(x);
0311 end->prior()=x;
0312 }
0313
0314 static bool unlink_last(pointer end)
0315 {
0316
0317
0318 pointer x=end->prior();
0319 if(x->prior()->next()==base_pointer_from(x)){
0320 x->prior()->next()=x->next();
0321 end->prior()=x->prior();
0322 return false;
0323 }
0324 else{
0325 x->prior()->next()->prior()=pointer(0);
0326 x->prior()->next()=x->next();
0327 end->prior()=x->prior();
0328 return true;
0329 }
0330 }
0331
0332 private:
0333 static pointer pointer_from(base_pointer x)
0334 {
0335 return Node::pointer_from(x);
0336 }
0337
0338 static base_pointer base_pointer_from(pointer x)
0339 {
0340 return Node::base_pointer_from(x);
0341 }
0342
0343 static bool is_last_of_bucket(pointer x)
0344 {
0345 return x->next()->prior()!=x;
0346 }
0347 };
0348
0349 template<typename Node>
0350 struct hashed_index_node_alg<Node,hashed_non_unique_tag>
0351 {
0352 typedef typename Node::base_pointer base_pointer;
0353 typedef typename Node::const_base_pointer const_base_pointer;
0354 typedef typename Node::pointer pointer;
0355 typedef typename Node::const_pointer const_pointer;
0356
0357 static bool is_first_of_bucket(pointer x)
0358 {
0359 return x->prior()->next()->prior()==x;
0360 }
0361
0362 static bool is_first_of_group(pointer x)
0363 {
0364 return
0365 x->next()->prior()!=x&&
0366 x->next()->prior()->prior()->next()==base_pointer_from(x);
0367 }
0368
0369 static pointer after(pointer x)
0370 {
0371 if(x->next()->prior()==x)return pointer_from(x->next());
0372 if(x->next()->prior()->prior()==x)return x->next()->prior();
0373 if(x->next()->prior()->prior()->next()==base_pointer_from(x))
0374 return pointer_from(x->next());
0375 return pointer_from(x->next())->next()->prior();
0376 }
0377
0378 static pointer after_local(pointer x)
0379 {
0380 if(x->next()->prior()==x)return pointer_from(x->next());
0381 if(x->next()->prior()->prior()==x)return pointer(0);
0382 if(x->next()->prior()->prior()->next()==base_pointer_from(x))
0383 return pointer_from(x->next());
0384 return pointer_from(x->next())->next()->prior();
0385 }
0386
0387 static pointer next_to_inspect(pointer x)
0388 {
0389 if(x->next()->prior()==x)return pointer_from(x->next());
0390 if(x->next()->prior()->prior()==x)return pointer(0);
0391 if(x->next()->prior()->next()->prior()!=x->next()->prior())
0392 return pointer(0);
0393 return pointer_from(x->next()->prior()->next());
0394 }
0395
0396 static void link(pointer x,base_pointer buc,pointer end)
0397 {
0398 if(buc->prior()==pointer(0)){
0399 x->prior()=end->prior();
0400 x->next()=end->prior()->next();
0401 x->prior()->next()=buc;
0402 buc->prior()=x;
0403 end->prior()=x;
0404 }
0405 else{
0406 x->prior()=buc->prior()->prior();
0407 x->next()=base_pointer_from(buc->prior());
0408 buc->prior()=x;
0409 x->next()->prior()=x;
0410 }
0411 }
0412
0413 static void link(pointer x,pointer first,pointer last)
0414 {
0415 x->prior()=first->prior();
0416 x->next()=base_pointer_from(first);
0417 if(is_first_of_bucket(first)){
0418 x->prior()->next()->prior()=x;
0419 }
0420 else{
0421 x->prior()->next()=base_pointer_from(x);
0422 }
0423
0424 if(first==last){
0425 last->prior()=x;
0426 }
0427 else if(first->next()==base_pointer_from(last)){
0428 first->prior()=last;
0429 first->next()=base_pointer_from(x);
0430 }
0431 else{
0432 pointer second=pointer_from(first->next()),
0433 lastbutone=last->prior();
0434 second->prior()=first;
0435 first->prior()=last;
0436 lastbutone->next()=base_pointer_from(x);
0437 }
0438 }
0439
0440 static void unlink(pointer x)
0441 {
0442 default_assigner assign;
0443 unlink(x,assign);
0444 }
0445
0446 typedef unlink_undo_assigner<Node> unlink_undo;
0447
0448 template<typename Assigner>
0449 static void unlink(pointer x,Assigner& assign)
0450 {
0451 if(x->prior()->next()==base_pointer_from(x)){
0452 if(x->next()->prior()==x){
0453 left_unlink(x,assign);
0454 right_unlink(x,assign);
0455 }
0456 else if(x->next()->prior()->prior()==x){
0457 left_unlink(x,assign);
0458 right_unlink_last_of_bucket(x,assign);
0459 }
0460 else if(x->next()->prior()->prior()->next()==
0461 base_pointer_from(x)){
0462 left_unlink(x,assign);
0463 right_unlink_first_of_group(x,assign);
0464 }
0465 else{
0466 unlink_last_but_one_of_group(x,assign);
0467 }
0468 }
0469 else if(x->prior()->next()->prior()==x){
0470 if(x->next()->prior()==x){
0471 left_unlink_first_of_bucket(x,assign);
0472 right_unlink(x,assign);
0473 }
0474 else if(x->next()->prior()->prior()==x){
0475 assign(x->prior()->next()->prior(),pointer(0));
0476 assign(x->prior()->next(),x->next());
0477 assign(x->next()->prior()->prior(),x->prior());
0478 }
0479 else{
0480 left_unlink_first_of_bucket(x,assign);
0481 right_unlink_first_of_group(x,assign);
0482 }
0483 }
0484 else if(x->next()->prior()->prior()==x){
0485 left_unlink_last_of_group(x,assign);
0486 right_unlink_last_of_bucket(x,assign);
0487 }
0488 else if(pointer_from(x->prior()->prior()->next())
0489 ->next()==base_pointer_from(x)){
0490 unlink_second_of_group(x,assign);
0491 }
0492 else{
0493 left_unlink_last_of_group(x,assign);
0494 right_unlink(x,assign);
0495 }
0496 }
0497
0498
0499
0500 static void link_range(
0501 pointer first,pointer last,base_pointer buc,pointer cend)
0502 {
0503 if(buc->prior()==pointer(0)){
0504 first->prior()=cend->prior();
0505 last->next()=cend->prior()->next();
0506 first->prior()->next()=buc;
0507 buc->prior()=first;
0508 cend->prior()=last;
0509 }
0510 else{
0511 first->prior()=buc->prior()->prior();
0512 last->next()=base_pointer_from(buc->prior());
0513 buc->prior()=first;
0514 last->next()->prior()=last;
0515 }
0516 }
0517
0518 static void append_range(pointer first,pointer last,pointer cend)
0519 {
0520 first->prior()=cend->prior();
0521 last->next()=cend->prior()->next();
0522 first->prior()->next()=base_pointer_from(first);
0523 cend->prior()=last;
0524 }
0525
0526 static std::pair<pointer,bool> unlink_last_group(pointer end)
0527 {
0528
0529
0530 pointer x=end->prior();
0531 if(x->prior()->next()==base_pointer_from(x)){
0532 x->prior()->next()=x->next();
0533 end->prior()=x->prior();
0534 return std::make_pair(x,false);
0535 }
0536 else if(x->prior()->next()->prior()==x){
0537 x->prior()->next()->prior()=pointer(0);
0538 x->prior()->next()=x->next();
0539 end->prior()=x->prior();
0540 return std::make_pair(x,true);
0541 }
0542 else{
0543 pointer y=pointer_from(x->prior()->next());
0544
0545 if(y->prior()->next()==base_pointer_from(y)){
0546 y->prior()->next()=x->next();
0547 end->prior()=y->prior();
0548 return std::make_pair(y,false);
0549 }
0550 else{
0551 y->prior()->next()->prior()=pointer(0);
0552 y->prior()->next()=x->next();
0553 end->prior()=y->prior();
0554 return std::make_pair(y,true);
0555 }
0556 }
0557 }
0558
0559 static void unlink_range(pointer first,pointer last)
0560 {
0561 if(is_first_of_bucket(first)){
0562 if(is_last_of_bucket(last)){
0563 first->prior()->next()->prior()=pointer(0);
0564 first->prior()->next()=last->next();
0565 last->next()->prior()->prior()=first->prior();
0566 }
0567 else{
0568 first->prior()->next()->prior()=pointer_from(last->next());
0569 last->next()->prior()=first->prior();
0570 }
0571 }
0572 else if(is_last_of_bucket(last)){
0573 first->prior()->next()=last->next();
0574 last->next()->prior()->prior()=first->prior();
0575 }
0576 else{
0577 first->prior()->next()=last->next();
0578 last->next()->prior()=first->prior();
0579 }
0580 }
0581
0582 private:
0583 static pointer pointer_from(base_pointer x)
0584 {
0585 return Node::pointer_from(x);
0586 }
0587
0588 static base_pointer base_pointer_from(pointer x)
0589 {
0590 return Node::base_pointer_from(x);
0591 }
0592
0593 static bool is_last_of_bucket(pointer x)
0594 {
0595 return x->next()->prior()->prior()==x;
0596 }
0597
0598 template<typename Assigner>
0599 static void left_unlink(pointer x,Assigner& assign)
0600 {
0601 assign(x->prior()->next(),x->next());
0602 }
0603
0604 template<typename Assigner>
0605 static void right_unlink(pointer x,Assigner& assign)
0606 {
0607 assign(x->next()->prior(),x->prior());
0608 }
0609
0610 template<typename Assigner>
0611 static void left_unlink_first_of_bucket(pointer x,Assigner& assign)
0612 {
0613 assign(x->prior()->next()->prior(),pointer_from(x->next()));
0614 }
0615
0616 template<typename Assigner>
0617 static void right_unlink_last_of_bucket(pointer x,Assigner& assign)
0618 {
0619 assign(x->next()->prior()->prior(),x->prior());
0620 }
0621
0622 template<typename Assigner>
0623 static void right_unlink_first_of_group(pointer x,Assigner& assign)
0624 {
0625 pointer second=pointer_from(x->next()),
0626 last=second->prior(),
0627 lastbutone=last->prior();
0628 if(second==lastbutone){
0629 assign(second->next(),base_pointer_from(last));
0630 assign(second->prior(),x->prior());
0631 }
0632 else{
0633 assign(lastbutone->next(),base_pointer_from(second));
0634 assign(second->next()->prior(),last);
0635 assign(second->prior(),x->prior());
0636 }
0637 }
0638
0639 template<typename Assigner>
0640 static void left_unlink_last_of_group(pointer x,Assigner& assign)
0641 {
0642 pointer lastbutone=x->prior(),
0643 first=pointer_from(lastbutone->next()),
0644 second=pointer_from(first->next());
0645 if(lastbutone==second){
0646 assign(lastbutone->prior(),first);
0647 assign(lastbutone->next(),x->next());
0648 }
0649 else{
0650 assign(second->prior(),lastbutone);
0651 assign(lastbutone->prior()->next(),base_pointer_from(first));
0652 assign(lastbutone->next(),x->next());
0653 }
0654 }
0655
0656 template<typename Assigner>
0657 static void unlink_last_but_one_of_group(pointer x,Assigner& assign)
0658 {
0659 pointer first=pointer_from(x->next()),
0660 second=pointer_from(first->next()),
0661 last=second->prior();
0662 if(second==x){
0663 assign(last->prior(),first);
0664 assign(first->next(),base_pointer_from(last));
0665 }
0666 else{
0667 assign(last->prior(),x->prior());
0668 assign(x->prior()->next(),base_pointer_from(first));
0669 }
0670 }
0671
0672 template<typename Assigner>
0673 static void unlink_second_of_group(pointer x,Assigner& assign)
0674 {
0675 pointer last=x->prior(),
0676 lastbutone=last->prior(),
0677 first=pointer_from(lastbutone->next());
0678 if(lastbutone==x){
0679 assign(first->next(),base_pointer_from(last));
0680 assign(last->prior(),first);
0681 }
0682 else{
0683 assign(first->next(),x->next());
0684 assign(x->next()->prior(),last);
0685 }
0686 }
0687 };
0688
0689 template<typename Super>
0690 struct hashed_index_node_trampoline:
0691 hashed_index_node_impl<
0692 typename rebind_alloc_for<
0693 typename Super::allocator_type,char
0694 >::type
0695 >
0696 {
0697 typedef typename rebind_alloc_for<
0698 typename Super::allocator_type,char
0699 >::type impl_allocator_type;
0700 typedef hashed_index_node_impl<impl_allocator_type> impl_type;
0701 };
0702
0703 template<typename Super>
0704 struct hashed_index_node:
0705 Super,hashed_index_node_trampoline<Super>
0706 {
0707 private:
0708 typedef hashed_index_node_trampoline<Super> trampoline;
0709
0710 public:
0711 typedef typename trampoline::impl_type impl_type;
0712 typedef typename trampoline::base_pointer impl_base_pointer;
0713 typedef typename trampoline::const_base_pointer const_impl_base_pointer;
0714 typedef typename trampoline::pointer impl_pointer;
0715 typedef typename trampoline::const_pointer const_impl_pointer;
0716 typedef typename trampoline::difference_type difference_type;
0717
0718 template<typename Category>
0719 struct node_alg{
0720 typedef hashed_index_node_alg<impl_type,Category> type;
0721 };
0722
0723 impl_pointer& prior(){return trampoline::prior();}
0724 impl_pointer prior()const{return trampoline::prior();}
0725 impl_base_pointer& next(){return trampoline::next();}
0726 impl_base_pointer next()const{return trampoline::next();}
0727
0728 impl_pointer impl()
0729 {
0730 return static_cast<impl_pointer>(
0731 static_cast<impl_type*>(static_cast<trampoline*>(this)));
0732 }
0733
0734 const_impl_pointer impl()const
0735 {
0736 return static_cast<const_impl_pointer>(
0737 static_cast<const impl_type*>(static_cast<const trampoline*>(this)));
0738 }
0739
0740 static hashed_index_node* from_impl(impl_pointer x)
0741 {
0742 return
0743 static_cast<hashed_index_node*>(
0744 static_cast<trampoline*>(
0745 raw_ptr<impl_type*>(x)));
0746 }
0747
0748 static const hashed_index_node* from_impl(const_impl_pointer x)
0749 {
0750 return
0751 static_cast<const hashed_index_node*>(
0752 static_cast<const trampoline*>(
0753 raw_ptr<const impl_type*>(x)));
0754 }
0755
0756
0757
0758 template<typename Category>
0759 static void increment(hashed_index_node*& x)
0760 {
0761 x=from_impl(node_alg<Category>::type::after(x->impl()));
0762 }
0763
0764 template<typename Category>
0765 static void increment_local(hashed_index_node*& x)
0766 {
0767 x=from_impl(node_alg<Category>::type::after_local(x->impl()));
0768 }
0769 };
0770
0771 }
0772
0773 }
0774
0775 }
0776
0777 #endif