1 /* Copyright 2003-2007 Joaquín M López Muñoz.
2 * Distributed under the Boost Software License, Version 1.0.
3 * (See accompanying file LICENSE_1_0.txt or copy at
4 * http://www.boost.org/LICENSE_1_0.txt)
6 * See http://www.boost.org/libs/multi_index for library home page.
9 #ifndef BOOST_MULTI_INDEX_HASHED_INDEX_HPP
10 #define BOOST_MULTI_INDEX_HASHED_INDEX_HPP
12 #if defined(_MSC_VER)&&(_MSC_VER>=1200)
16 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
18 #include <boost/call_traits.hpp>
19 #include <boost/detail/allocator_utilities.hpp>
20 #include <boost/detail/no_exceptions_support.hpp>
21 #include <boost/detail/workaround.hpp>
22 #include <boost/limits.hpp>
23 #include <boost/mpl/push_front.hpp>
24 #include <boost/multi_index/detail/access_specifier.hpp>
25 #include <boost/multi_index/detail/auto_space.hpp>
26 #include <boost/multi_index/detail/bucket_array.hpp>
27 #include <boost/multi_index/detail/hash_index_iterator.hpp>
28 #include <boost/multi_index/detail/modify_key_adaptor.hpp>
29 #include <boost/multi_index/detail/safe_ctr_proxy.hpp>
30 #include <boost/multi_index/detail/safe_mode.hpp>
31 #include <boost/multi_index/detail/scope_guard.hpp>
32 #include <boost/multi_index/hashed_index_fwd.hpp>
33 #include <boost/tuple/tuple.hpp>
38 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
39 #include <boost/serialization/nvp.hpp>
42 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
43 #define BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT \
44 detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)= \
45 detail::make_obj_guard(*this,&hashed_index::check_invariant_); \
46 BOOST_JOIN(check_invariant_,__LINE__).touch();
48 #define BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT
53 namespace multi_index{
57 /* hashed_index adds a layer of hashed indexing to a given Super */
59 /* Most of the implementation of unique and non-unique indices is
60 * shared. We tell from one another on instantiation time by using
64 struct hashed_unique_tag{};
65 struct hashed_non_unique_tag{};
68 typename KeyFromValue,typename Hash,typename Pred,
69 typename SuperMeta,typename TagList,typename Category
72 BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type
74 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
75 #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
76 ,public safe_ctr_proxy_impl<
77 hashed_index_iterator<
78 hashed_index_node<typename SuperMeta::type::node_type>,
79 bucket_array<typename SuperMeta::type::final_allocator_type> >,
80 hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category> >
82 ,public safe_mode::safe_container<
83 hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category> >
88 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
89 BOOST_WORKAROUND(__MWERKS__,<=0x3003)
90 /* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
91 * lifetime of const references bound to temporaries --precisely what
95 #pragma parse_mfunc_templ off
98 typedef typename SuperMeta::type super;
101 typedef hashed_index_node<
102 typename super::node_type> node_type;
103 typedef bucket_array<
104 typename super::final_allocator_type> bucket_array_type;
109 typedef typename KeyFromValue::result_type key_type;
110 typedef typename node_type::value_type value_type;
111 typedef KeyFromValue key_from_value;
113 typedef Pred key_equal;
114 typedef tuple<std::size_t,
115 key_from_value,hasher,key_equal> ctor_args;
116 typedef typename super::final_allocator_type allocator_type;
117 typedef typename allocator_type::pointer pointer;
118 typedef typename allocator_type::const_pointer const_pointer;
119 typedef typename allocator_type::reference reference;
120 typedef typename allocator_type::const_reference const_reference;
121 typedef std::size_t size_type;
122 typedef std::ptrdiff_t difference_type;
124 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
125 #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
126 typedef safe_mode::safe_iterator<
127 hashed_index_iterator<
128 node_type,bucket_array_type>,
130 hashed_index_iterator<
131 node_type,bucket_array_type> > > iterator;
133 typedef safe_mode::safe_iterator<
134 hashed_index_iterator<
135 node_type,bucket_array_type>,
136 hashed_index> iterator;
139 typedef hashed_index_iterator<
140 node_type,bucket_array_type> iterator;
143 typedef iterator const_iterator;
145 typedef iterator local_iterator;
146 typedef const_iterator const_local_iterator;
147 typedef TagList tag_list;
150 typedef typename super::final_node_type final_node_type;
151 typedef tuples::cons<
153 typename super::ctor_args_list> ctor_args_list;
154 typedef typename mpl::push_front<
155 typename super::index_type_list,
156 hashed_index>::type index_type_list;
157 typedef typename mpl::push_front<
158 typename super::iterator_type_list,
159 iterator>::type iterator_type_list;
160 typedef typename mpl::push_front<
161 typename super::const_iterator_type_list,
162 const_iterator>::type const_iterator_type_list;
163 typedef typename super::copy_map_type copy_map_type;
165 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
166 typedef typename super::index_saver_type index_saver_type;
167 typedef typename super::index_loader_type index_loader_type;
171 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
172 #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
173 typedef safe_ctr_proxy_impl<
174 hashed_index_iterator<
177 hashed_index> safe_super;
179 typedef safe_mode::safe_container<
180 hashed_index> safe_super;
184 typedef typename call_traits<value_type>::param_type value_param_type;
185 typedef typename call_traits<
186 key_type>::param_type key_param_type;
190 /* construct/destroy/copy
191 * Default and copy ctors are in the protected section as indices are
192 * not supposed to be created on their own. No range ctor either.
195 hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& operator=(
196 const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
198 this->final()=x.final();
202 allocator_type get_allocator()const
204 return this->final().get_allocator();
207 /* size and capacity */
209 bool empty()const{return this->final_empty_();}
210 size_type size()const{return this->final_size_();}
211 size_type max_size()const{return this->final_max_size_();}
217 return make_iterator(
218 node_type::from_impl(buckets.at(first_bucket)->next()));
221 const_iterator begin()const
223 return make_iterator(
224 node_type::from_impl(buckets.at(first_bucket)->next()));
227 iterator end(){return make_iterator(header());}
228 const_iterator end()const{return make_iterator(header());}
232 std::pair<iterator,bool> insert(value_param_type x)
234 BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
235 std::pair<final_node_type*,bool> p=this->final_insert_(x);
236 return std::pair<iterator,bool>(make_iterator(p.first),p.second);
239 iterator insert(iterator position,value_param_type x)
241 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
242 BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
243 BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
244 std::pair<final_node_type*,bool> p=this->final_insert_(
245 x,static_cast<final_node_type*>(position.get_node()));
246 return make_iterator(p.first);
249 template<typename InputIterator>
250 void insert(InputIterator first,InputIterator last)
252 BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
254 for(;first!=last;++first)hint=insert(hint,*first);
257 iterator erase(iterator position)
259 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
260 BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
261 BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
262 BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
263 this->final_erase_(static_cast<final_node_type*>(position++.get_node()));
267 size_type erase(key_param_type k)
269 BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
272 std::size_t buc=buckets.position(hash(k));
273 hashed_index_node_impl* x=buckets.at(buc);
274 hashed_index_node_impl* y=x->next();
276 if(eq(k,key(node_type::from_impl(y)->value()))){
279 hashed_index_node_impl* z=y->next();
281 key(node_type::from_impl(y)->value()),
282 key(node_type::from_impl(z)->value()));
284 static_cast<final_node_type*>(node_type::from_impl(y)));
295 iterator erase(iterator first,iterator last)
297 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
298 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
299 BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
300 BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
301 BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
302 BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
309 bool replace(iterator position,value_param_type x)
311 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
312 BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
313 BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
314 BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
315 return this->final_replace_(
316 x,static_cast<final_node_type*>(position.get_node()));
319 template<typename Modifier>
320 bool modify(iterator position,Modifier mod)
322 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
323 BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
324 BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
325 BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
327 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
328 /* MSVC++ 6.0 optimizer on safe mode code chokes if this
329 * this is not added. Left it for all compilers as it does no
336 return this->final_modify_(
337 mod,static_cast<final_node_type*>(position.get_node()));
340 template<typename Modifier>
341 bool modify_key(iterator position,Modifier mod)
343 BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
344 BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
345 BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
346 BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
348 position,modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key));
353 BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
354 this->final_clear_();
357 void swap(hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
359 BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
360 this->final_swap_(x.final());
365 key_from_value key_extractor()const{return key;}
366 hasher hash_function()const{return hash;}
367 key_equal key_eq()const{return eq;}
371 /* Internally, these ops rely on const_iterator being the same
375 template<typename CompatibleKey>
376 iterator find(const CompatibleKey& k)const
378 return find(k,hash,eq);
382 typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
385 const CompatibleKey& k,
386 const CompatibleHash& hash,const CompatiblePred& eq)const
388 std::size_t buc=buckets.position(hash(k));
389 hashed_index_node_impl* x=buckets.at(buc);
390 hashed_index_node_impl* y=x->next();
392 if(eq(k,key(node_type::from_impl(y)->value()))){
393 return make_iterator(node_type::from_impl(y));
400 template<typename CompatibleKey>
401 size_type count(const CompatibleKey& k)const
403 return count(k,hash,eq);
407 typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
410 const CompatibleKey& k,
411 const CompatibleHash& hash,const CompatiblePred& eq)const
414 std::size_t buc=buckets.position(hash(k));
415 hashed_index_node_impl* x=buckets.at(buc);
416 hashed_index_node_impl* y=x->next();
418 if(eq(k,key(node_type::from_impl(y)->value()))){
422 }while(y!=x&&eq(k,key(node_type::from_impl(y)->value())));
430 template<typename CompatibleKey>
431 std::pair<iterator,iterator> equal_range(const CompatibleKey& k)const
433 return equal_range(k,hash,eq);
437 typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
439 std::pair<iterator,iterator> equal_range(
440 const CompatibleKey& k,
441 const CompatibleHash& hash,const CompatiblePred& eq)const
443 std::size_t buc=buckets.position(hash(k));
444 hashed_index_node_impl* x=buckets.at(buc);
445 hashed_index_node_impl* y=x->next();
447 if(eq(k,key(node_type::from_impl(y)->value()))){
448 hashed_index_node_impl* y0=y;
451 }while(y!=x&&eq(k,key(node_type::from_impl(y)->value())));
455 }while(y==y->next());
458 return std::pair<iterator,iterator>(
459 make_iterator(node_type::from_impl(y0)),
460 make_iterator(node_type::from_impl(y)));
464 return std::pair<iterator,iterator>(end(),end());
467 /* bucket interface */
469 size_type bucket_count()const{return buckets.size();}
470 size_type max_bucket_count()const{return static_cast<size_type>(-1);}
472 size_type bucket_size(size_type n)const
475 hashed_index_node_impl* x=buckets.at(n);
476 hashed_index_node_impl* y=x->next();
484 size_type bucket(key_param_type k)const
486 return buckets.position(hash(k));
489 local_iterator begin(size_type n)
491 return const_cast<const hashed_index*>(this)->begin(n);
494 const_local_iterator begin(size_type n)const
496 hashed_index_node_impl* x=buckets.at(n);
497 hashed_index_node_impl* y=x->next();
498 if(y==x)return end();
499 return make_iterator(node_type::from_impl(y));
502 local_iterator end(size_type n)
504 return const_cast<const hashed_index*>(this)->end(n);
507 const_local_iterator end(size_type n)const
509 hashed_index_node_impl* x=buckets.at(n);
510 if(x==x->next())return end();
513 }while(x==x->next());
514 return make_iterator(node_type::from_impl(x->next()));
519 float load_factor()const{return static_cast<float>(size())/bucket_count();}
520 float max_load_factor()const{return mlf;}
521 void max_load_factor(float z){mlf=z;calculate_max_load();}
523 void rehash(size_type n)
525 BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
526 if(size()<max_load&&n<=bucket_count())return;
528 size_type bc =(std::numeric_limits<size_type>::max)();
529 float fbc=static_cast<float>(1+size()/mlf);
531 bc=static_cast<size_type>(fbc);
534 unchecked_rehash(bc);
537 BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
538 hashed_index(const ctor_args_list& args_list,const allocator_type& al):
539 super(args_list.get_tail(),al),
540 key(tuples::get<1>(args_list.get_head())),
541 hash(tuples::get<2>(args_list.get_head())),
542 eq(tuples::get<3>(args_list.get_head())),
543 buckets(al,header()->impl(),tuples::get<0>(args_list.get_head())),
545 first_bucket(buckets.size())
547 calculate_max_load();
551 const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x):
554 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
561 buckets(x.get_allocator(),header()->impl(),x.buckets.size()),
563 max_load(x.max_load),
564 first_bucket(x.first_bucket)
566 /* Copy ctor just takes the internal configuration objects from x. The rest
567 * is done in subsequent call to copy_().
573 /* the container is guaranteed to be empty by now */
576 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
577 iterator make_iterator(node_type* node)
579 return iterator(node,&buckets,this);
582 const_iterator make_iterator(node_type* node)const
584 return const_iterator(
586 &const_cast<bucket_array_type&>(buckets),
587 const_cast<hashed_index*>(this));
590 iterator make_iterator(node_type* node)
592 return iterator(node,&buckets);
595 const_iterator make_iterator(node_type* node)const
597 return const_iterator(node,&const_cast<bucket_array_type&>(buckets));
602 const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
603 const copy_map_type& map)
605 for(hashed_index_node_impl* begin_org=x.buckets.begin(),
606 * begin_cpy=buckets.begin(),
607 * end_org=x.buckets.end();
608 begin_org!=end_org;++begin_org,++begin_cpy){
610 hashed_index_node_impl* next_org=begin_org->next();
611 hashed_index_node_impl* cpy=begin_cpy;
612 while(next_org!=begin_org){
614 static_cast<node_type*>(
616 static_cast<final_node_type*>(
617 node_type::from_impl(next_org))))->impl();
618 next_org=next_org->next();
621 cpy->next()=begin_cpy;
627 node_type* insert_(value_param_type v,node_type* x)
631 std::size_t buc=find_bucket(v);
632 hashed_index_node_impl* pos=buckets.at(buc);
633 if(!link_point(v,pos,Category()))return node_type::from_impl(pos);
635 node_type* res=static_cast<node_type*>(super::insert_(v,x));
638 if(first_bucket>buc)first_bucket=buc;
643 node_type* insert_(value_param_type v,node_type* position,node_type* x)
647 std::size_t buc=find_bucket(v);
648 hashed_index_node_impl* pos=buckets.at(buc);
649 if(!link_point(v,pos,Category()))return node_type::from_impl(pos);
651 node_type* res=static_cast<node_type*>(super::insert_(v,position,x));
654 if(first_bucket>buc)first_bucket=buc;
659 void erase_(node_type* x)
662 first_bucket=buckets.first_nonempty(first_bucket);
665 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
670 void delete_all_nodes_()
672 for(hashed_index_node_impl* x=buckets.begin(),*x_end=buckets.end();
674 hashed_index_node_impl* y=x->next();
676 hashed_index_node_impl* z=y->next();
677 this->final_delete_node_(
678 static_cast<final_node_type*>(node_type::from_impl(y)));
688 first_bucket=buckets.size();
690 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
691 safe_super::detach_dereferenceable_iterators();
696 hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
698 std::swap(key,x.key);
699 std::swap(hash,x.hash);
701 buckets.swap(x.buckets);
702 std::swap(mlf,x.mlf);
703 std::swap(max_load,x.max_load);
704 std::swap(first_bucket,x.first_bucket);
706 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
713 bool replace_(value_param_type v,node_type* x)
715 if(eq(key(v),key(x->value()))){
716 return super::replace_(v,x);
719 hashed_index_node_impl* y=prev(x);
723 std::size_t buc=find_bucket(v);
724 hashed_index_node_impl* pos=buckets.at(buc);
725 if(link_point(v,pos,Category())&&super::replace_(v,x)){
727 if(first_bucket>buc){
730 else if(first_bucket<buc){
731 first_bucket=buckets.first_nonempty(first_bucket);
745 bool modify_(node_type* x)
750 hashed_index_node_impl* pos;
753 buc=find_bucket(x->value());
755 if(!link_point(x->value(),pos,Category())){
756 first_bucket=buckets.first_nonempty(first_bucket);
759 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
767 first_bucket=buckets.first_nonempty(first_bucket);
770 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
779 if(super::modify_(x)){
781 if(first_bucket>buc){
784 else if(first_bucket<buc){
785 first_bucket=buckets.first_nonempty(first_bucket);
790 first_bucket=buckets.first_nonempty(first_bucket);
792 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
798 first_bucket=buckets.first_nonempty(first_bucket);
800 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
809 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
812 template<typename Archive>
814 Archive& ar,const unsigned int version,const index_saver_type& sm)const
816 ar<<serialization::make_nvp("position",buckets);
817 super::save_(ar,version,sm);
820 template<typename Archive>
821 void load_(Archive& ar,const unsigned int version,const index_loader_type& lm)
823 ar>>serialization::make_nvp("position",buckets);
824 super::load_(ar,version,lm);
828 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
829 /* invariant stuff */
831 bool invariant_()const
833 if(size()==0||begin()==end()){
834 if(size()!=0||begin()!=end())return false;
838 for(const_iterator it=begin(),it_end=end();it!=it_end;++it,++s0){}
839 if(s0!=size())return false;
842 for(size_type buc=0;buc<bucket_count();++buc){
844 for(const_local_iterator it=begin(buc),it_end=end(buc);
845 it!=it_end;++it,++ss1){
846 if(find_bucket(*it)!=buc)return false;
848 if(ss1!=bucket_size(buc))return false;
851 if(s1!=size())return false;
854 if(first_bucket!=buckets.first_nonempty(0))return false;
856 return super::invariant_();
859 /* This forwarding function eases things for the boost::mem_fn construct
860 * in BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT. Actually,
861 * final_check_invariant is already an inherited member function of index.
863 void check_invariant_()const{this->final_check_invariant_();}
867 node_type* header()const{return this->final_header();}
869 std::size_t find_bucket(value_param_type v)const
871 return bucket(key(v));
875 value_param_type v,hashed_index_node_impl*& pos,hashed_unique_tag)
877 hashed_index_node_impl* x=pos->next();
879 if(eq(key(v),key(node_type::from_impl(x)->value()))){
889 value_param_type v,hashed_index_node_impl*& pos,hashed_non_unique_tag)
891 hashed_index_node_impl* prev=pos;
892 hashed_index_node_impl* x=pos->next();
894 if(eq(key(v),key(node_type::from_impl(x)->value()))){
904 void link(node_type* x,hashed_index_node_impl* pos)
906 hashed_index_node_impl::link(x->impl(),pos);
909 void link(hashed_index_node_impl* x,hashed_index_node_impl* pos)
911 hashed_index_node_impl::link(x,pos);
914 void unlink(node_type* x)
916 hashed_index_node_impl::unlink(x->impl());
919 static hashed_index_node_impl* prev(node_type* x)
921 return hashed_index_node_impl::prev(x->impl());
924 static void unlink_next(hashed_index_node_impl* x)
926 hashed_index_node_impl::unlink_next(x);
929 void calculate_max_load()
931 float fml=static_cast<float>(mlf*bucket_count());
932 max_load=(std::numeric_limits<size_type>::max)();
933 if(max_load>fml)max_load=static_cast<size_type>(fml);
936 void reserve(size_type n)
939 size_type bc =(std::numeric_limits<size_type>::max)();
940 float fbc=static_cast<float>(1+n/mlf);
941 if(bc>fbc)bc =static_cast<size_type>(fbc);
942 unchecked_rehash(bc);
946 void unchecked_rehash(size_type n)
948 bucket_array_type buckets1(get_allocator(),header()->impl(),n);
949 auto_space<std::size_t,allocator_type> hashes(get_allocator(),size());
952 hashed_index_node_impl* x=buckets.begin();
953 hashed_index_node_impl* x_end=buckets.end();
955 hashed_index_node_impl* y=x->next();
957 hashes.data()[i++]=hash(key(node_type::from_impl(y)->value()));
965 hashed_index_node_impl* y=x->next();
967 hashed_index_node_impl* z=y->next();
968 std::size_t buc1=buckets1.position(hashes.data()[i++]);
969 hashed_index_node_impl* x1=buckets1.at(buc1);
975 buckets.swap(buckets1);
976 calculate_max_load();
977 first_bucket=buckets.first_nonempty(0);
980 #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
981 void detach_iterators(node_type* x)
983 iterator it=make_iterator(x);
984 safe_mode::detach_equivalent_iterators(it);
991 bucket_array_type buckets;
994 std::size_t first_bucket;
996 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
997 BOOST_WORKAROUND(__MWERKS__,<=0x3003)
998 #pragma parse_mfunc_templ reset
1002 /* specialized algorithms */
1005 typename KeyFromValue,typename Hash,typename Pred,
1006 typename SuperMeta,typename TagList,typename Category
1009 hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
1010 hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& y)
1015 } /* namespace multi_index::detail */
1017 /* sequenced index specifiers */
1019 template<typename Arg1,typename Arg2,typename Arg3,typename Arg4>
1020 struct hashed_unique
1022 typedef typename detail::hashed_index_args<
1023 Arg1,Arg2,Arg3,Arg4> index_args;
1024 typedef typename index_args::tag_list_type::type tag_list_type;
1025 typedef typename index_args::key_from_value_type key_from_value_type;
1026 typedef typename index_args::hash_type hash_type;
1027 typedef typename index_args::pred_type pred_type;
1029 template<typename Super>
1032 typedef detail::hashed_index_node<Super> type;
1035 template<typename SuperMeta>
1038 typedef detail::hashed_index<
1039 key_from_value_type,hash_type,pred_type,
1040 SuperMeta,tag_list_type,detail::hashed_unique_tag> type;
1044 template<typename Arg1,typename Arg2,typename Arg3,typename Arg4>
1045 struct hashed_non_unique
1047 typedef typename detail::hashed_index_args<
1048 Arg1,Arg2,Arg3,Arg4> index_args;
1049 typedef typename index_args::tag_list_type::type tag_list_type;
1050 typedef typename index_args::key_from_value_type key_from_value_type;
1051 typedef typename index_args::hash_type hash_type;
1052 typedef typename index_args::pred_type pred_type;
1054 template<typename Super>
1057 typedef detail::hashed_index_node<Super> type;
1060 template<typename SuperMeta>
1063 typedef detail::hashed_index<
1064 key_from_value_type,hash_type,pred_type,
1065 SuperMeta,tag_list_type,detail::hashed_non_unique_tag> type;
1069 } /* namespace multi_index */
1071 } /* namespace boost */
1073 #undef BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT