hashed_index.hpp 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743
  1. /* Copyright 2003-2018 Joaquin M Lopez Munoz.
  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)
  5. *
  6. * See http://www.boost.org/libs/multi_index for library home page.
  7. */
  8. #ifndef BOOST_MULTI_INDEX_HASHED_INDEX_HPP
  9. #define BOOST_MULTI_INDEX_HASHED_INDEX_HPP
  10. #if defined(_MSC_VER)
  11. #pragma once
  12. #endif
  13. #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
  14. #include <algorithm>
  15. #include <boost/call_traits.hpp>
  16. #include <boost/core/addressof.hpp>
  17. #include <boost/detail/no_exceptions_support.hpp>
  18. #include <boost/detail/workaround.hpp>
  19. #include <boost/foreach_fwd.hpp>
  20. #include <boost/limits.hpp>
  21. #include <boost/move/core.hpp>
  22. #include <boost/mpl/bool.hpp>
  23. #include <boost/mpl/if.hpp>
  24. #include <boost/mpl/push_front.hpp>
  25. #include <boost/multi_index/detail/access_specifier.hpp>
  26. #include <boost/multi_index/detail/allocator_traits.hpp>
  27. #include <boost/multi_index/detail/auto_space.hpp>
  28. #include <boost/multi_index/detail/bucket_array.hpp>
  29. #include <boost/multi_index/detail/do_not_copy_elements_tag.hpp>
  30. #include <boost/multi_index/detail/hash_index_iterator.hpp>
  31. #include <boost/multi_index/detail/index_node_base.hpp>
  32. #include <boost/multi_index/detail/modify_key_adaptor.hpp>
  33. #include <boost/multi_index/detail/promotes_arg.hpp>
  34. #include <boost/multi_index/detail/safe_mode.hpp>
  35. #include <boost/multi_index/detail/scope_guard.hpp>
  36. #include <boost/multi_index/detail/vartempl_support.hpp>
  37. #include <boost/multi_index/hashed_index_fwd.hpp>
  38. #include <boost/tuple/tuple.hpp>
  39. #include <boost/type_traits/is_same.hpp>
  40. #include <cmath>
  41. #include <cstddef>
  42. #include <functional>
  43. #include <iterator>
  44. #include <utility>
  45. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  46. #include <initializer_list>
  47. #endif
  48. #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
  49. #include <boost/serialization/nvp.hpp>
  50. #endif
  51. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
  52. #define BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT_OF(x) \
  53. detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)= \
  54. detail::make_obj_guard(x,&hashed_index::check_invariant_); \
  55. BOOST_JOIN(check_invariant_,__LINE__).touch();
  56. #define BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT \
  57. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT_OF(*this)
  58. #else
  59. #define BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT_OF(x)
  60. #define BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT
  61. #endif
  62. namespace boost{
  63. namespace multi_index{
  64. namespace detail{
  65. /* hashed_index adds a layer of hashed indexing to a given Super */
  66. /* Most of the implementation of unique and non-unique indices is
  67. * shared. We tell from one another on instantiation time by using
  68. * Category tags defined in hash_index_node.hpp.
  69. */
  70. template<
  71. typename KeyFromValue,typename Hash,typename Pred,
  72. typename SuperMeta,typename TagList,typename Category
  73. >
  74. class hashed_index:
  75. BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type
  76. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  77. ,public safe_mode::safe_container<
  78. hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category> >
  79. #endif
  80. {
  81. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
  82. BOOST_WORKAROUND(__MWERKS__,<=0x3003)
  83. /* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
  84. * lifetime of const references bound to temporaries --precisely what
  85. * scopeguards are.
  86. */
  87. #pragma parse_mfunc_templ off
  88. #endif
  89. typedef typename SuperMeta::type super;
  90. protected:
  91. typedef hashed_index_node<
  92. typename super::node_type,Category> node_type;
  93. private:
  94. typedef typename node_type::node_alg node_alg;
  95. typedef typename node_type::impl_type node_impl_type;
  96. typedef typename node_impl_type::pointer node_impl_pointer;
  97. typedef typename node_impl_type::base_pointer node_impl_base_pointer;
  98. typedef bucket_array<
  99. typename super::final_allocator_type> bucket_array_type;
  100. public:
  101. /* types */
  102. typedef typename KeyFromValue::result_type key_type;
  103. typedef typename node_type::value_type value_type;
  104. typedef KeyFromValue key_from_value;
  105. typedef Hash hasher;
  106. typedef Pred key_equal;
  107. typedef typename super::final_allocator_type allocator_type;
  108. private:
  109. typedef allocator_traits<allocator_type> alloc_traits;
  110. public:
  111. typedef typename alloc_traits::pointer pointer;
  112. typedef typename alloc_traits::const_pointer const_pointer;
  113. typedef value_type& reference;
  114. typedef const value_type& const_reference;
  115. typedef typename alloc_traits::size_type size_type;
  116. typedef typename alloc_traits::difference_type difference_type;
  117. typedef tuple<size_type,
  118. key_from_value,hasher,key_equal> ctor_args;
  119. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  120. typedef safe_mode::safe_iterator<
  121. hashed_index_iterator<
  122. node_type,bucket_array_type,
  123. hashed_index_global_iterator_tag>,
  124. hashed_index> iterator;
  125. #else
  126. typedef hashed_index_iterator<
  127. node_type,bucket_array_type,
  128. hashed_index_global_iterator_tag> iterator;
  129. #endif
  130. typedef iterator const_iterator;
  131. typedef hashed_index_iterator<
  132. node_type,bucket_array_type,
  133. hashed_index_local_iterator_tag> local_iterator;
  134. typedef local_iterator const_local_iterator;
  135. typedef TagList tag_list;
  136. protected:
  137. typedef typename super::final_node_type final_node_type;
  138. typedef tuples::cons<
  139. ctor_args,
  140. typename super::ctor_args_list> ctor_args_list;
  141. typedef typename mpl::push_front<
  142. typename super::index_type_list,
  143. hashed_index>::type index_type_list;
  144. typedef typename mpl::push_front<
  145. typename super::iterator_type_list,
  146. iterator>::type iterator_type_list;
  147. typedef typename mpl::push_front<
  148. typename super::const_iterator_type_list,
  149. const_iterator>::type const_iterator_type_list;
  150. typedef typename super::copy_map_type copy_map_type;
  151. #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
  152. typedef typename super::index_saver_type index_saver_type;
  153. typedef typename super::index_loader_type index_loader_type;
  154. #endif
  155. private:
  156. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  157. typedef safe_mode::safe_container<
  158. hashed_index> safe_super;
  159. #endif
  160. typedef typename call_traits<value_type>::param_type value_param_type;
  161. typedef typename call_traits<
  162. key_type>::param_type key_param_type;
  163. /* Needed to avoid commas in BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL
  164. * expansion.
  165. */
  166. typedef std::pair<iterator,bool> emplace_return_type;
  167. public:
  168. /* construct/destroy/copy
  169. * Default and copy ctors are in the protected section as indices are
  170. * not supposed to be created on their own. No range ctor either.
  171. */
  172. hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& operator=(
  173. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
  174. {
  175. this->final()=x.final();
  176. return *this;
  177. }
  178. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  179. hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& operator=(
  180. std::initializer_list<value_type> list)
  181. {
  182. this->final()=list;
  183. return *this;
  184. }
  185. #endif
  186. allocator_type get_allocator()const BOOST_NOEXCEPT
  187. {
  188. return this->final().get_allocator();
  189. }
  190. /* size and capacity */
  191. bool empty()const BOOST_NOEXCEPT{return this->final_empty_();}
  192. size_type size()const BOOST_NOEXCEPT{return this->final_size_();}
  193. size_type max_size()const BOOST_NOEXCEPT{return this->final_max_size_();}
  194. /* iterators */
  195. iterator begin()BOOST_NOEXCEPT
  196. {return make_iterator(node_type::from_impl(header()->next()->prior()));}
  197. const_iterator begin()const BOOST_NOEXCEPT
  198. {return make_iterator(node_type::from_impl(header()->next()->prior()));}
  199. iterator end()BOOST_NOEXCEPT{return make_iterator(header());}
  200. const_iterator end()const BOOST_NOEXCEPT{return make_iterator(header());}
  201. const_iterator cbegin()const BOOST_NOEXCEPT{return begin();}
  202. const_iterator cend()const BOOST_NOEXCEPT{return end();}
  203. iterator iterator_to(const value_type& x)
  204. {
  205. return make_iterator(node_from_value<node_type>(boost::addressof(x)));
  206. }
  207. const_iterator iterator_to(const value_type& x)const
  208. {
  209. return make_iterator(node_from_value<node_type>(boost::addressof(x)));
  210. }
  211. /* modifiers */
  212. BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL(
  213. emplace_return_type,emplace,emplace_impl)
  214. BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL_EXTRA_ARG(
  215. iterator,emplace_hint,emplace_hint_impl,iterator,position)
  216. std::pair<iterator,bool> insert(const value_type& x)
  217. {
  218. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  219. std::pair<final_node_type*,bool> p=this->final_insert_(x);
  220. return std::pair<iterator,bool>(make_iterator(p.first),p.second);
  221. }
  222. std::pair<iterator,bool> insert(BOOST_RV_REF(value_type) x)
  223. {
  224. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  225. std::pair<final_node_type*,bool> p=this->final_insert_rv_(x);
  226. return std::pair<iterator,bool>(make_iterator(p.first),p.second);
  227. }
  228. iterator insert(iterator position,const value_type& x)
  229. {
  230. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  231. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  232. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  233. std::pair<final_node_type*,bool> p=this->final_insert_(
  234. x,static_cast<final_node_type*>(position.get_node()));
  235. return make_iterator(p.first);
  236. }
  237. iterator insert(iterator position,BOOST_RV_REF(value_type) x)
  238. {
  239. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  240. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  241. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  242. std::pair<final_node_type*,bool> p=this->final_insert_rv_(
  243. x,static_cast<final_node_type*>(position.get_node()));
  244. return make_iterator(p.first);
  245. }
  246. template<typename InputIterator>
  247. void insert(InputIterator first,InputIterator last)
  248. {
  249. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  250. for(;first!=last;++first)this->final_insert_ref_(*first);
  251. }
  252. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  253. void insert(std::initializer_list<value_type> list)
  254. {
  255. insert(list.begin(),list.end());
  256. }
  257. #endif
  258. iterator erase(iterator position)
  259. {
  260. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  261. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  262. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  263. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  264. this->final_erase_(static_cast<final_node_type*>(position++.get_node()));
  265. return position;
  266. }
  267. size_type erase(key_param_type k)
  268. {
  269. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  270. std::size_t buc=buckets.position(hash_(k));
  271. for(node_impl_pointer x=buckets.at(buc)->prior();
  272. x!=node_impl_pointer(0);x=node_alg::next_to_inspect(x)){
  273. if(eq_(k,key(node_type::from_impl(x)->value()))){
  274. node_impl_pointer y=end_of_range(x);
  275. size_type s=0;
  276. do{
  277. node_impl_pointer z=node_alg::after(x);
  278. this->final_erase_(
  279. static_cast<final_node_type*>(node_type::from_impl(x)));
  280. x=z;
  281. ++s;
  282. }while(x!=y);
  283. return s;
  284. }
  285. }
  286. return 0;
  287. }
  288. iterator erase(iterator first,iterator last)
  289. {
  290. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
  291. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
  292. BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
  293. BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
  294. BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
  295. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  296. while(first!=last){
  297. first=erase(first);
  298. }
  299. return first;
  300. }
  301. bool replace(iterator position,const value_type& x)
  302. {
  303. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  304. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  305. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  306. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  307. return this->final_replace_(
  308. x,static_cast<final_node_type*>(position.get_node()));
  309. }
  310. bool replace(iterator position,BOOST_RV_REF(value_type) x)
  311. {
  312. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  313. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  314. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  315. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  316. return this->final_replace_rv_(
  317. x,static_cast<final_node_type*>(position.get_node()));
  318. }
  319. template<typename Modifier>
  320. bool modify(iterator position,Modifier mod)
  321. {
  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;
  326. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  327. /* MSVC++ 6.0 optimizer on safe mode code chokes if this
  328. * this is not added. Left it for all compilers as it does no
  329. * harm.
  330. */
  331. position.detach();
  332. #endif
  333. return this->final_modify_(
  334. mod,static_cast<final_node_type*>(position.get_node()));
  335. }
  336. template<typename Modifier,typename Rollback>
  337. bool modify(iterator position,Modifier mod,Rollback back_)
  338. {
  339. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  340. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  341. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  342. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  343. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  344. /* MSVC++ 6.0 optimizer on safe mode code chokes if this
  345. * this is not added. Left it for all compilers as it does no
  346. * harm.
  347. */
  348. position.detach();
  349. #endif
  350. return this->final_modify_(
  351. mod,back_,static_cast<final_node_type*>(position.get_node()));
  352. }
  353. template<typename Modifier>
  354. bool modify_key(iterator position,Modifier mod)
  355. {
  356. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  357. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  358. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  359. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  360. return modify(
  361. position,modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key));
  362. }
  363. template<typename Modifier,typename Rollback>
  364. bool modify_key(iterator position,Modifier mod,Rollback back_)
  365. {
  366. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  367. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  368. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  369. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  370. return modify(
  371. position,
  372. modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key),
  373. modify_key_adaptor<Rollback,value_type,KeyFromValue>(back_,key));
  374. }
  375. void clear()BOOST_NOEXCEPT
  376. {
  377. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  378. this->final_clear_();
  379. }
  380. void swap(hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
  381. {
  382. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  383. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT_OF(x);
  384. this->final_swap_(x.final());
  385. }
  386. /* observers */
  387. key_from_value key_extractor()const{return key;}
  388. hasher hash_function()const{return hash_;}
  389. key_equal key_eq()const{return eq_;}
  390. /* lookup */
  391. /* Internally, these ops rely on const_iterator being the same
  392. * type as iterator.
  393. */
  394. /* Implementation note: When CompatibleKey is consistently promoted to
  395. * KeyFromValue::result_type for equality comparison, the promotion is made
  396. * once in advance to increase efficiency.
  397. */
  398. template<typename CompatibleKey>
  399. iterator find(const CompatibleKey& k)const
  400. {
  401. return find(k,hash_,eq_);
  402. }
  403. template<
  404. typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
  405. >
  406. iterator find(
  407. const CompatibleKey& k,
  408. const CompatibleHash& hash,const CompatiblePred& eq)const
  409. {
  410. return find(
  411. k,hash,eq,promotes_1st_arg<CompatiblePred,CompatibleKey,key_type>());
  412. }
  413. template<typename CompatibleKey>
  414. size_type count(const CompatibleKey& k)const
  415. {
  416. return count(k,hash_,eq_);
  417. }
  418. template<
  419. typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
  420. >
  421. size_type count(
  422. const CompatibleKey& k,
  423. const CompatibleHash& hash,const CompatiblePred& eq)const
  424. {
  425. return count(
  426. k,hash,eq,promotes_1st_arg<CompatiblePred,CompatibleKey,key_type>());
  427. }
  428. template<typename CompatibleKey>
  429. std::pair<iterator,iterator> equal_range(const CompatibleKey& k)const
  430. {
  431. return equal_range(k,hash_,eq_);
  432. }
  433. template<
  434. typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
  435. >
  436. std::pair<iterator,iterator> equal_range(
  437. const CompatibleKey& k,
  438. const CompatibleHash& hash,const CompatiblePred& eq)const
  439. {
  440. return equal_range(
  441. k,hash,eq,promotes_1st_arg<CompatiblePred,CompatibleKey,key_type>());
  442. }
  443. /* bucket interface */
  444. size_type bucket_count()const BOOST_NOEXCEPT
  445. {
  446. return static_cast<size_type>(buckets.size());
  447. }
  448. size_type max_bucket_count()const BOOST_NOEXCEPT{return static_cast<size_type>(-1);}
  449. size_type bucket_size(size_type n)const
  450. {
  451. size_type res=0;
  452. for(node_impl_pointer x=buckets.at(n)->prior();
  453. x!=node_impl_pointer(0);x=node_alg::after_local(x)){
  454. ++res;
  455. }
  456. return res;
  457. }
  458. size_type bucket(key_param_type k)const
  459. {
  460. return static_cast<size_type>(buckets.position(hash_(k)));
  461. }
  462. local_iterator begin(size_type n)
  463. {
  464. return const_cast<const hashed_index*>(this)->begin(n);
  465. }
  466. const_local_iterator begin(size_type n)const
  467. {
  468. node_impl_pointer x=buckets.at(n)->prior();
  469. if(x==node_impl_pointer(0))return end(n);
  470. return make_local_iterator(node_type::from_impl(x));
  471. }
  472. local_iterator end(size_type n)
  473. {
  474. return const_cast<const hashed_index*>(this)->end(n);
  475. }
  476. const_local_iterator end(size_type)const
  477. {
  478. return make_local_iterator(0);
  479. }
  480. const_local_iterator cbegin(size_type n)const{return begin(n);}
  481. const_local_iterator cend(size_type n)const{return end(n);}
  482. local_iterator local_iterator_to(const value_type& x)
  483. {
  484. return make_local_iterator(
  485. node_from_value<node_type>(boost::addressof(x)));
  486. }
  487. const_local_iterator local_iterator_to(const value_type& x)const
  488. {
  489. return make_local_iterator(
  490. node_from_value<node_type>(boost::addressof(x)));
  491. }
  492. /* hash policy */
  493. float load_factor()const BOOST_NOEXCEPT
  494. {return static_cast<float>(size())/bucket_count();}
  495. float max_load_factor()const BOOST_NOEXCEPT{return mlf;}
  496. void max_load_factor(float z){mlf=z;calculate_max_load();}
  497. void rehash(size_type n)
  498. {
  499. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  500. if(size()<=max_load&&n<=bucket_count())return;
  501. size_type bc =(std::numeric_limits<size_type>::max)();
  502. float fbc=1.0f+static_cast<float>(size())/mlf;
  503. if(bc>fbc){
  504. bc=static_cast<size_type>(fbc);
  505. if(bc<n)bc=n;
  506. }
  507. unchecked_rehash(bc);
  508. }
  509. void reserve(size_type n)
  510. {
  511. rehash(static_cast<size_type>(std::ceil(static_cast<float>(n)/mlf)));
  512. }
  513. BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
  514. hashed_index(const ctor_args_list& args_list,const allocator_type& al):
  515. super(args_list.get_tail(),al),
  516. key(tuples::get<1>(args_list.get_head())),
  517. hash_(tuples::get<2>(args_list.get_head())),
  518. eq_(tuples::get<3>(args_list.get_head())),
  519. buckets(al,header()->impl(),tuples::get<0>(args_list.get_head())),
  520. mlf(1.0f)
  521. {
  522. calculate_max_load();
  523. }
  524. hashed_index(
  525. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x):
  526. super(x),
  527. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  528. safe_super(),
  529. #endif
  530. key(x.key),
  531. hash_(x.hash_),
  532. eq_(x.eq_),
  533. buckets(x.get_allocator(),header()->impl(),x.buckets.size()),
  534. mlf(x.mlf),
  535. max_load(x.max_load)
  536. {
  537. /* Copy ctor just takes the internal configuration objects from x. The rest
  538. * is done in subsequent call to copy_().
  539. */
  540. }
  541. hashed_index(
  542. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
  543. do_not_copy_elements_tag):
  544. super(x,do_not_copy_elements_tag()),
  545. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  546. safe_super(),
  547. #endif
  548. key(x.key),
  549. hash_(x.hash_),
  550. eq_(x.eq_),
  551. buckets(x.get_allocator(),header()->impl(),0),
  552. mlf(1.0f)
  553. {
  554. calculate_max_load();
  555. }
  556. ~hashed_index()
  557. {
  558. /* the container is guaranteed to be empty by now */
  559. }
  560. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  561. iterator make_iterator(node_type* node)
  562. {
  563. return iterator(node,this);
  564. }
  565. const_iterator make_iterator(node_type* node)const
  566. {
  567. return const_iterator(node,const_cast<hashed_index*>(this));
  568. }
  569. #else
  570. iterator make_iterator(node_type* node)
  571. {
  572. return iterator(node);
  573. }
  574. const_iterator make_iterator(node_type* node)const
  575. {
  576. return const_iterator(node);
  577. }
  578. #endif
  579. local_iterator make_local_iterator(node_type* node)
  580. {
  581. return local_iterator(node);
  582. }
  583. const_local_iterator make_local_iterator(node_type* node)const
  584. {
  585. return const_local_iterator(node);
  586. }
  587. void copy_(
  588. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
  589. const copy_map_type& map)
  590. {
  591. copy_(x,map,Category());
  592. }
  593. void copy_(
  594. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
  595. const copy_map_type& map,hashed_unique_tag)
  596. {
  597. if(x.size()!=0){
  598. node_impl_pointer end_org=x.header()->impl(),
  599. org=end_org,
  600. cpy=header()->impl();
  601. do{
  602. node_impl_pointer prev_org=org->prior(),
  603. prev_cpy=
  604. static_cast<node_type*>(map.find(static_cast<final_node_type*>(
  605. node_type::from_impl(prev_org))))->impl();
  606. cpy->prior()=prev_cpy;
  607. if(node_alg::is_first_of_bucket(org)){
  608. node_impl_base_pointer buc_org=prev_org->next(),
  609. buc_cpy=
  610. buckets.begin()+(buc_org-x.buckets.begin());
  611. prev_cpy->next()=buc_cpy;
  612. buc_cpy->prior()=cpy;
  613. }
  614. else{
  615. prev_cpy->next()=node_impl_type::base_pointer_from(cpy);
  616. }
  617. org=prev_org;
  618. cpy=prev_cpy;
  619. }while(org!=end_org);
  620. }
  621. super::copy_(x,map);
  622. }
  623. void copy_(
  624. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
  625. const copy_map_type& map,hashed_non_unique_tag)
  626. {
  627. if(x.size()!=0){
  628. node_impl_pointer end_org=x.header()->impl(),
  629. org=end_org,
  630. cpy=header()->impl();
  631. do{
  632. node_impl_pointer next_org=node_alg::after(org),
  633. next_cpy=
  634. static_cast<node_type*>(map.find(static_cast<final_node_type*>(
  635. node_type::from_impl(next_org))))->impl();
  636. if(node_alg::is_first_of_bucket(next_org)){
  637. node_impl_base_pointer buc_org=org->next(),
  638. buc_cpy=
  639. buckets.begin()+(buc_org-x.buckets.begin());
  640. cpy->next()=buc_cpy;
  641. buc_cpy->prior()=next_cpy;
  642. next_cpy->prior()=cpy;
  643. }
  644. else{
  645. if(org->next()==node_impl_type::base_pointer_from(next_org)){
  646. cpy->next()=node_impl_type::base_pointer_from(next_cpy);
  647. }
  648. else{
  649. cpy->next()=
  650. node_impl_type::base_pointer_from(
  651. static_cast<node_type*>(map.find(static_cast<final_node_type*>(
  652. node_type::from_impl(
  653. node_impl_type::pointer_from(org->next())))))->impl());
  654. }
  655. if(next_org->prior()!=org){
  656. next_cpy->prior()=
  657. static_cast<node_type*>(map.find(static_cast<final_node_type*>(
  658. node_type::from_impl(next_org->prior()))))->impl();
  659. }
  660. else{
  661. next_cpy->prior()=cpy;
  662. }
  663. }
  664. org=next_org;
  665. cpy=next_cpy;
  666. }while(org!=end_org);
  667. }
  668. super::copy_(x,map);
  669. }
  670. template<typename Variant>
  671. final_node_type* insert_(
  672. value_param_type v,final_node_type*& x,Variant variant)
  673. {
  674. reserve_for_insert(size()+1);
  675. std::size_t buc=find_bucket(v);
  676. link_info pos(buckets.at(buc));
  677. if(!link_point(v,pos)){
  678. return static_cast<final_node_type*>(
  679. node_type::from_impl(node_impl_type::pointer_from(pos)));
  680. }
  681. final_node_type* res=super::insert_(v,x,variant);
  682. if(res==x)link(static_cast<node_type*>(x),pos);
  683. return res;
  684. }
  685. template<typename Variant>
  686. final_node_type* insert_(
  687. value_param_type v,node_type* position,final_node_type*& x,Variant variant)
  688. {
  689. reserve_for_insert(size()+1);
  690. std::size_t buc=find_bucket(v);
  691. link_info pos(buckets.at(buc));
  692. if(!link_point(v,pos)){
  693. return static_cast<final_node_type*>(
  694. node_type::from_impl(node_impl_type::pointer_from(pos)));
  695. }
  696. final_node_type* res=super::insert_(v,position,x,variant);
  697. if(res==x)link(static_cast<node_type*>(x),pos);
  698. return res;
  699. }
  700. void erase_(node_type* x)
  701. {
  702. unlink(x);
  703. super::erase_(x);
  704. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  705. detach_iterators(x);
  706. #endif
  707. }
  708. void delete_all_nodes_()
  709. {
  710. delete_all_nodes_(Category());
  711. }
  712. void delete_all_nodes_(hashed_unique_tag)
  713. {
  714. for(node_impl_pointer x_end=header()->impl(),x=x_end->prior();x!=x_end;){
  715. node_impl_pointer y=x->prior();
  716. this->final_delete_node_(
  717. static_cast<final_node_type*>(node_type::from_impl(x)));
  718. x=y;
  719. }
  720. }
  721. void delete_all_nodes_(hashed_non_unique_tag)
  722. {
  723. for(node_impl_pointer x_end=header()->impl(),x=x_end->prior();x!=x_end;){
  724. node_impl_pointer y=x->prior();
  725. if(y->next()!=node_impl_type::base_pointer_from(x)&&
  726. y->next()->prior()!=x){ /* n-1 of group */
  727. /* Make the second node prior() pointer back-linked so that it won't
  728. * refer to a deleted node when the time for its own destruction comes.
  729. */
  730. node_impl_pointer first=node_impl_type::pointer_from(y->next());
  731. first->next()->prior()=first;
  732. }
  733. this->final_delete_node_(
  734. static_cast<final_node_type*>(node_type::from_impl(x)));
  735. x=y;
  736. }
  737. }
  738. void clear_()
  739. {
  740. super::clear_();
  741. buckets.clear(header()->impl());
  742. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  743. safe_super::detach_dereferenceable_iterators();
  744. #endif
  745. }
  746. void swap_(
  747. hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
  748. {
  749. std::swap(key,x.key);
  750. std::swap(hash_,x.hash_);
  751. std::swap(eq_,x.eq_);
  752. buckets.swap(x.buckets);
  753. std::swap(mlf,x.mlf);
  754. std::swap(max_load,x.max_load);
  755. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  756. safe_super::swap(x);
  757. #endif
  758. super::swap_(x);
  759. }
  760. void swap_elements_(
  761. hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
  762. {
  763. buckets.swap(x.buckets);
  764. std::swap(mlf,x.mlf);
  765. std::swap(max_load,x.max_load);
  766. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  767. safe_super::swap(x);
  768. #endif
  769. super::swap_elements_(x);
  770. }
  771. template<typename Variant>
  772. bool replace_(value_param_type v,node_type* x,Variant variant)
  773. {
  774. if(eq_(key(v),key(x->value()))){
  775. return super::replace_(v,x,variant);
  776. }
  777. unlink_undo undo;
  778. unlink(x,undo);
  779. BOOST_TRY{
  780. std::size_t buc=find_bucket(v);
  781. link_info pos(buckets.at(buc));
  782. if(link_point(v,pos)&&super::replace_(v,x,variant)){
  783. link(x,pos);
  784. return true;
  785. }
  786. undo();
  787. return false;
  788. }
  789. BOOST_CATCH(...){
  790. undo();
  791. BOOST_RETHROW;
  792. }
  793. BOOST_CATCH_END
  794. }
  795. bool modify_(node_type* x)
  796. {
  797. std::size_t buc;
  798. bool b;
  799. BOOST_TRY{
  800. buc=find_bucket(x->value());
  801. b=in_place(x->impl(),key(x->value()),buc);
  802. }
  803. BOOST_CATCH(...){
  804. erase_(x);
  805. BOOST_RETHROW;
  806. }
  807. BOOST_CATCH_END
  808. if(!b){
  809. unlink(x);
  810. BOOST_TRY{
  811. link_info pos(buckets.at(buc));
  812. if(!link_point(x->value(),pos)){
  813. super::erase_(x);
  814. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  815. detach_iterators(x);
  816. #endif
  817. return false;
  818. }
  819. link(x,pos);
  820. }
  821. BOOST_CATCH(...){
  822. super::erase_(x);
  823. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  824. detach_iterators(x);
  825. #endif
  826. BOOST_RETHROW;
  827. }
  828. BOOST_CATCH_END
  829. }
  830. BOOST_TRY{
  831. if(!super::modify_(x)){
  832. unlink(x);
  833. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  834. detach_iterators(x);
  835. #endif
  836. return false;
  837. }
  838. else return true;
  839. }
  840. BOOST_CATCH(...){
  841. unlink(x);
  842. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  843. detach_iterators(x);
  844. #endif
  845. BOOST_RETHROW;
  846. }
  847. BOOST_CATCH_END
  848. }
  849. bool modify_rollback_(node_type* x)
  850. {
  851. std::size_t buc=find_bucket(x->value());
  852. if(in_place(x->impl(),key(x->value()),buc)){
  853. return super::modify_rollback_(x);
  854. }
  855. unlink_undo undo;
  856. unlink(x,undo);
  857. BOOST_TRY{
  858. link_info pos(buckets.at(buc));
  859. if(link_point(x->value(),pos)&&super::modify_rollback_(x)){
  860. link(x,pos);
  861. return true;
  862. }
  863. undo();
  864. return false;
  865. }
  866. BOOST_CATCH(...){
  867. undo();
  868. BOOST_RETHROW;
  869. }
  870. BOOST_CATCH_END
  871. }
  872. bool check_rollback_(node_type* x)const
  873. {
  874. std::size_t buc=find_bucket(x->value());
  875. return in_place(x->impl(),key(x->value()),buc)&&super::check_rollback_(x);
  876. }
  877. /* comparison */
  878. #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
  879. /* defect macro refers to class, not function, templates, but anyway */
  880. template<typename K,typename H,typename P,typename S,typename T,typename C>
  881. friend bool operator==(
  882. const hashed_index<K,H,P,S,T,C>&,const hashed_index<K,H,P,S,T,C>& y);
  883. #endif
  884. bool equals(const hashed_index& x)const{return equals(x,Category());}
  885. bool equals(const hashed_index& x,hashed_unique_tag)const
  886. {
  887. if(size()!=x.size())return false;
  888. for(const_iterator it=begin(),it_end=end(),it2_end=x.end();
  889. it!=it_end;++it){
  890. const_iterator it2=x.find(key(*it));
  891. if(it2==it2_end||!(*it==*it2))return false;
  892. }
  893. return true;
  894. }
  895. bool equals(const hashed_index& x,hashed_non_unique_tag)const
  896. {
  897. if(size()!=x.size())return false;
  898. for(const_iterator it=begin(),it_end=end();it!=it_end;){
  899. const_iterator it2,it2_last;
  900. boost::tie(it2,it2_last)=x.equal_range(key(*it));
  901. if(it2==it2_last)return false;
  902. const_iterator it_last=make_iterator(
  903. node_type::from_impl(end_of_range(it.get_node()->impl())));
  904. if(std::distance(it,it_last)!=std::distance(it2,it2_last))return false;
  905. /* From is_permutation code in
  906. * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3068.pdf
  907. */
  908. for(;it!=it_last;++it,++it2){
  909. if(!(*it==*it2))break;
  910. }
  911. if(it!=it_last){
  912. for(const_iterator scan=it;scan!=it_last;++scan){
  913. if(std::find(it,scan,*scan)!=scan)continue;
  914. difference_type matches=std::count(it2,it2_last,*scan);
  915. if(matches==0||matches!=std::count(scan,it_last,*scan))return false;
  916. }
  917. it=it_last;
  918. }
  919. }
  920. return true;
  921. }
  922. #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
  923. /* serialization */
  924. template<typename Archive>
  925. void save_(
  926. Archive& ar,const unsigned int version,const index_saver_type& sm)const
  927. {
  928. ar<<serialization::make_nvp("position",buckets);
  929. super::save_(ar,version,sm);
  930. }
  931. template<typename Archive>
  932. void load_(Archive& ar,const unsigned int version,const index_loader_type& lm)
  933. {
  934. ar>>serialization::make_nvp("position",buckets);
  935. super::load_(ar,version,lm);
  936. }
  937. #endif
  938. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
  939. /* invariant stuff */
  940. bool invariant_()const
  941. {
  942. if(size()==0||begin()==end()){
  943. if(size()!=0||begin()!=end())return false;
  944. }
  945. else{
  946. size_type s0=0;
  947. for(const_iterator it=begin(),it_end=end();it!=it_end;++it,++s0){}
  948. if(s0!=size())return false;
  949. size_type s1=0;
  950. for(size_type buc=0;buc<bucket_count();++buc){
  951. size_type ss1=0;
  952. for(const_local_iterator it=begin(buc),it_end=end(buc);
  953. it!=it_end;++it,++ss1){
  954. if(find_bucket(*it)!=buc)return false;
  955. }
  956. if(ss1!=bucket_size(buc))return false;
  957. s1+=ss1;
  958. }
  959. if(s1!=size())return false;
  960. }
  961. return super::invariant_();
  962. }
  963. /* This forwarding function eases things for the boost::mem_fn construct
  964. * in BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT. Actually,
  965. * final_check_invariant is already an inherited member function of index.
  966. */
  967. void check_invariant_()const{this->final_check_invariant_();}
  968. #endif
  969. private:
  970. node_type* header()const{return this->final_header();}
  971. std::size_t find_bucket(value_param_type v)const
  972. {
  973. return bucket(key(v));
  974. }
  975. struct link_info_non_unique
  976. {
  977. link_info_non_unique(node_impl_base_pointer pos):
  978. first(pos),last(node_impl_base_pointer(0)){}
  979. operator const node_impl_base_pointer&()const{return this->first;}
  980. node_impl_base_pointer first,last;
  981. };
  982. typedef typename mpl::if_<
  983. is_same<Category,hashed_unique_tag>,
  984. node_impl_base_pointer,
  985. link_info_non_unique
  986. >::type link_info;
  987. bool link_point(value_param_type v,link_info& pos)
  988. {
  989. return link_point(v,pos,Category());
  990. }
  991. bool link_point(
  992. value_param_type v,node_impl_base_pointer& pos,hashed_unique_tag)
  993. {
  994. for(node_impl_pointer x=pos->prior();x!=node_impl_pointer(0);
  995. x=node_alg::after_local(x)){
  996. if(eq_(key(v),key(node_type::from_impl(x)->value()))){
  997. pos=node_impl_type::base_pointer_from(x);
  998. return false;
  999. }
  1000. }
  1001. return true;
  1002. }
  1003. bool link_point(
  1004. value_param_type v,link_info_non_unique& pos,hashed_non_unique_tag)
  1005. {
  1006. for(node_impl_pointer x=pos.first->prior();x!=node_impl_pointer(0);
  1007. x=node_alg::next_to_inspect(x)){
  1008. if(eq_(key(v),key(node_type::from_impl(x)->value()))){
  1009. pos.first=node_impl_type::base_pointer_from(x);
  1010. pos.last=node_impl_type::base_pointer_from(last_of_range(x));
  1011. return true;
  1012. }
  1013. }
  1014. return true;
  1015. }
  1016. node_impl_pointer last_of_range(node_impl_pointer x)const
  1017. {
  1018. return last_of_range(x,Category());
  1019. }
  1020. node_impl_pointer last_of_range(node_impl_pointer x,hashed_unique_tag)const
  1021. {
  1022. return x;
  1023. }
  1024. node_impl_pointer last_of_range(
  1025. node_impl_pointer x,hashed_non_unique_tag)const
  1026. {
  1027. node_impl_base_pointer y=x->next();
  1028. node_impl_pointer z=y->prior();
  1029. if(z==x){ /* range of size 1 or 2 */
  1030. node_impl_pointer yy=node_impl_type::pointer_from(y);
  1031. return
  1032. eq_(
  1033. key(node_type::from_impl(x)->value()),
  1034. key(node_type::from_impl(yy)->value()))?yy:x;
  1035. }
  1036. else if(z->prior()==x) /* last of bucket */
  1037. return x;
  1038. else /* group of size>2 */
  1039. return z;
  1040. }
  1041. node_impl_pointer end_of_range(node_impl_pointer x)const
  1042. {
  1043. return end_of_range(x,Category());
  1044. }
  1045. node_impl_pointer end_of_range(node_impl_pointer x,hashed_unique_tag)const
  1046. {
  1047. return node_alg::after(last_of_range(x));
  1048. }
  1049. node_impl_pointer end_of_range(
  1050. node_impl_pointer x,hashed_non_unique_tag)const
  1051. {
  1052. node_impl_base_pointer y=x->next();
  1053. node_impl_pointer z=y->prior();
  1054. if(z==x){ /* range of size 1 or 2 */
  1055. node_impl_pointer yy=node_impl_type::pointer_from(y);
  1056. if(!eq_(
  1057. key(node_type::from_impl(x)->value()),
  1058. key(node_type::from_impl(yy)->value())))yy=x;
  1059. return yy->next()->prior()==yy?
  1060. node_impl_type::pointer_from(yy->next()):
  1061. yy->next()->prior();
  1062. }
  1063. else if(z->prior()==x) /* last of bucket */
  1064. return z;
  1065. else /* group of size>2 */
  1066. return z->next()->prior()==z?
  1067. node_impl_type::pointer_from(z->next()):
  1068. z->next()->prior();
  1069. }
  1070. void link(node_type* x,const link_info& pos)
  1071. {
  1072. link(x,pos,Category());
  1073. }
  1074. void link(node_type* x,node_impl_base_pointer pos,hashed_unique_tag)
  1075. {
  1076. node_alg::link(x->impl(),pos,header()->impl());
  1077. }
  1078. void link(node_type* x,const link_info_non_unique& pos,hashed_non_unique_tag)
  1079. {
  1080. if(pos.last==node_impl_base_pointer(0)){
  1081. node_alg::link(x->impl(),pos.first,header()->impl());
  1082. }
  1083. else{
  1084. node_alg::link(
  1085. x->impl(),
  1086. node_impl_type::pointer_from(pos.first),
  1087. node_impl_type::pointer_from(pos.last));
  1088. }
  1089. }
  1090. void unlink(node_type* x)
  1091. {
  1092. node_alg::unlink(x->impl());
  1093. }
  1094. typedef typename node_alg::unlink_undo unlink_undo;
  1095. void unlink(node_type* x,unlink_undo& undo)
  1096. {
  1097. node_alg::unlink(x->impl(),undo);
  1098. }
  1099. void calculate_max_load()
  1100. {
  1101. float fml=mlf*static_cast<float>(bucket_count());
  1102. max_load=(std::numeric_limits<size_type>::max)();
  1103. if(max_load>fml)max_load=static_cast<size_type>(fml);
  1104. }
  1105. void reserve_for_insert(size_type n)
  1106. {
  1107. if(n>max_load){
  1108. size_type bc =(std::numeric_limits<size_type>::max)();
  1109. float fbc=1.0f+static_cast<float>(n)/mlf;
  1110. if(bc>fbc)bc =static_cast<size_type>(fbc);
  1111. unchecked_rehash(bc);
  1112. }
  1113. }
  1114. void unchecked_rehash(size_type n){unchecked_rehash(n,Category());}
  1115. void unchecked_rehash(size_type n,hashed_unique_tag)
  1116. {
  1117. node_impl_type cpy_end_node;
  1118. node_impl_pointer cpy_end=node_impl_pointer(&cpy_end_node),
  1119. end_=header()->impl();
  1120. bucket_array_type buckets_cpy(get_allocator(),cpy_end,n);
  1121. if(size()!=0){
  1122. auto_space<
  1123. std::size_t,allocator_type> hashes(get_allocator(),size());
  1124. auto_space<
  1125. node_impl_pointer,allocator_type> node_ptrs(get_allocator(),size());
  1126. std::size_t i=0,size_=size();
  1127. bool within_bucket=false;
  1128. BOOST_TRY{
  1129. for(;i!=size_;++i){
  1130. node_impl_pointer x=end_->prior();
  1131. /* only this can possibly throw */
  1132. std::size_t h=hash_(key(node_type::from_impl(x)->value()));
  1133. hashes.data()[i]=h;
  1134. node_ptrs.data()[i]=x;
  1135. within_bucket=!node_alg::unlink_last(end_);
  1136. node_alg::link(x,buckets_cpy.at(buckets_cpy.position(h)),cpy_end);
  1137. }
  1138. }
  1139. BOOST_CATCH(...){
  1140. if(i!=0){
  1141. std::size_t prev_buc=buckets.position(hashes.data()[i-1]);
  1142. if(!within_bucket)prev_buc=~prev_buc;
  1143. for(std::size_t j=i;j--;){
  1144. std::size_t buc=buckets.position(hashes.data()[j]);
  1145. node_impl_pointer x=node_ptrs.data()[j];
  1146. if(buc==prev_buc)node_alg::append(x,end_);
  1147. else node_alg::link(x,buckets.at(buc),end_);
  1148. prev_buc=buc;
  1149. }
  1150. }
  1151. BOOST_RETHROW;
  1152. }
  1153. BOOST_CATCH_END
  1154. }
  1155. end_->prior()=cpy_end->prior()!=cpy_end?cpy_end->prior():end_;
  1156. end_->next()=cpy_end->next();
  1157. end_->prior()->next()->prior()=end_->next()->prior()->prior()=end_;
  1158. buckets.swap(buckets_cpy);
  1159. calculate_max_load();
  1160. }
  1161. void unchecked_rehash(size_type n,hashed_non_unique_tag)
  1162. {
  1163. node_impl_type cpy_end_node;
  1164. node_impl_pointer cpy_end=node_impl_pointer(&cpy_end_node),
  1165. end_=header()->impl();
  1166. bucket_array_type buckets_cpy(get_allocator(),cpy_end,n);
  1167. if(size()!=0){
  1168. auto_space<
  1169. std::size_t,allocator_type> hashes(get_allocator(),size());
  1170. auto_space<
  1171. node_impl_pointer,allocator_type> node_ptrs(get_allocator(),size());
  1172. std::size_t i=0;
  1173. bool within_bucket=false;
  1174. BOOST_TRY{
  1175. for(;;++i){
  1176. node_impl_pointer x=end_->prior();
  1177. if(x==end_)break;
  1178. /* only this can possibly throw */
  1179. std::size_t h=hash_(key(node_type::from_impl(x)->value()));
  1180. hashes.data()[i]=h;
  1181. node_ptrs.data()[i]=x;
  1182. std::pair<node_impl_pointer,bool> p=
  1183. node_alg::unlink_last_group(end_);
  1184. node_alg::link_range(
  1185. p.first,x,buckets_cpy.at(buckets_cpy.position(h)),cpy_end);
  1186. within_bucket=!(p.second);
  1187. }
  1188. }
  1189. BOOST_CATCH(...){
  1190. if(i!=0){
  1191. std::size_t prev_buc=buckets.position(hashes.data()[i-1]);
  1192. if(!within_bucket)prev_buc=~prev_buc;
  1193. for(std::size_t j=i;j--;){
  1194. std::size_t buc=buckets.position(hashes.data()[j]);
  1195. node_impl_pointer x=node_ptrs.data()[j],
  1196. y=
  1197. x->prior()->next()!=node_impl_type::base_pointer_from(x)&&
  1198. x->prior()->next()->prior()!=x?
  1199. node_impl_type::pointer_from(x->prior()->next()):x;
  1200. node_alg::unlink_range(y,x);
  1201. if(buc==prev_buc)node_alg::append_range(y,x,end_);
  1202. else node_alg::link_range(y,x,buckets.at(buc),end_);
  1203. prev_buc=buc;
  1204. }
  1205. }
  1206. BOOST_RETHROW;
  1207. }
  1208. BOOST_CATCH_END
  1209. }
  1210. end_->prior()=cpy_end->prior()!=cpy_end?cpy_end->prior():end_;
  1211. end_->next()=cpy_end->next();
  1212. end_->prior()->next()->prior()=end_->next()->prior()->prior()=end_;
  1213. buckets.swap(buckets_cpy);
  1214. calculate_max_load();
  1215. }
  1216. bool in_place(node_impl_pointer x,key_param_type k,std::size_t buc)const
  1217. {
  1218. return in_place(x,k,buc,Category());
  1219. }
  1220. bool in_place(
  1221. node_impl_pointer x,key_param_type k,std::size_t buc,
  1222. hashed_unique_tag)const
  1223. {
  1224. bool found=false;
  1225. for(node_impl_pointer y=buckets.at(buc)->prior();
  1226. y!=node_impl_pointer(0);y=node_alg::after_local(y)){
  1227. if(y==x)found=true;
  1228. else if(eq_(k,key(node_type::from_impl(y)->value())))return false;
  1229. }
  1230. return found;
  1231. }
  1232. bool in_place(
  1233. node_impl_pointer x,key_param_type k,std::size_t buc,
  1234. hashed_non_unique_tag)const
  1235. {
  1236. bool found=false;
  1237. int range_size=0;
  1238. for(node_impl_pointer y=buckets.at(buc)->prior();y!=node_impl_pointer(0);){
  1239. if(node_alg::is_first_of_group(y)){ /* group of 3 or more */
  1240. if(y==x){
  1241. /* in place <-> equal to some other member of the group */
  1242. return eq_(
  1243. k,
  1244. key(node_type::from_impl(
  1245. node_impl_type::pointer_from(y->next()))->value()));
  1246. }
  1247. else{
  1248. node_impl_pointer z=
  1249. node_alg::after_local(y->next()->prior()); /* end of range */
  1250. if(eq_(k,key(node_type::from_impl(y)->value()))){
  1251. if(found)return false; /* x lies outside */
  1252. do{
  1253. if(y==x)return true;
  1254. y=node_alg::after_local(y);
  1255. }while(y!=z);
  1256. return false; /* x not found */
  1257. }
  1258. else{
  1259. if(range_size==1&&!found)return false;
  1260. if(range_size==2)return found;
  1261. range_size=0;
  1262. y=z; /* skip range (and potentially x, too, which is fine) */
  1263. }
  1264. }
  1265. }
  1266. else{ /* group of 1 or 2 */
  1267. if(y==x){
  1268. if(range_size==1)return true;
  1269. range_size=1;
  1270. found=true;
  1271. }
  1272. else if(eq_(k,key(node_type::from_impl(y)->value()))){
  1273. if(range_size==0&&found)return false;
  1274. if(range_size==1&&!found)return false;
  1275. if(range_size==2)return false;
  1276. ++range_size;
  1277. }
  1278. else{
  1279. if(range_size==1&&!found)return false;
  1280. if(range_size==2)return found;
  1281. range_size=0;
  1282. }
  1283. y=node_alg::after_local(y);
  1284. }
  1285. }
  1286. return found;
  1287. }
  1288. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  1289. void detach_iterators(node_type* x)
  1290. {
  1291. iterator it=make_iterator(x);
  1292. safe_mode::detach_equivalent_iterators(it);
  1293. }
  1294. #endif
  1295. template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
  1296. std::pair<iterator,bool> emplace_impl(BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
  1297. {
  1298. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  1299. std::pair<final_node_type*,bool>p=
  1300. this->final_emplace_(BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
  1301. return std::pair<iterator,bool>(make_iterator(p.first),p.second);
  1302. }
  1303. template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK>
  1304. iterator emplace_hint_impl(
  1305. iterator position,BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)
  1306. {
  1307. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  1308. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  1309. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  1310. std::pair<final_node_type*,bool>p=
  1311. this->final_emplace_hint_(
  1312. static_cast<final_node_type*>(position.get_node()),
  1313. BOOST_MULTI_INDEX_FORWARD_PARAM_PACK);
  1314. return make_iterator(p.first);
  1315. }
  1316. template<
  1317. typename CompatibleHash,typename CompatiblePred
  1318. >
  1319. iterator find(
  1320. const key_type& k,
  1321. const CompatibleHash& hash,const CompatiblePred& eq,mpl::true_)const
  1322. {
  1323. return find(k,hash,eq,mpl::false_());
  1324. }
  1325. template<
  1326. typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
  1327. >
  1328. iterator find(
  1329. const CompatibleKey& k,
  1330. const CompatibleHash& hash,const CompatiblePred& eq,mpl::false_)const
  1331. {
  1332. std::size_t buc=buckets.position(hash(k));
  1333. for(node_impl_pointer x=buckets.at(buc)->prior();
  1334. x!=node_impl_pointer(0);x=node_alg::next_to_inspect(x)){
  1335. if(eq(k,key(node_type::from_impl(x)->value()))){
  1336. return make_iterator(node_type::from_impl(x));
  1337. }
  1338. }
  1339. return end();
  1340. }
  1341. template<
  1342. typename CompatibleHash,typename CompatiblePred
  1343. >
  1344. size_type count(
  1345. const key_type& k,
  1346. const CompatibleHash& hash,const CompatiblePred& eq,mpl::true_)const
  1347. {
  1348. return count(k,hash,eq,mpl::false_());
  1349. }
  1350. template<
  1351. typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
  1352. >
  1353. size_type count(
  1354. const CompatibleKey& k,
  1355. const CompatibleHash& hash,const CompatiblePred& eq,mpl::false_)const
  1356. {
  1357. std::size_t buc=buckets.position(hash(k));
  1358. for(node_impl_pointer x=buckets.at(buc)->prior();
  1359. x!=node_impl_pointer(0);x=node_alg::next_to_inspect(x)){
  1360. if(eq(k,key(node_type::from_impl(x)->value()))){
  1361. size_type res=0;
  1362. node_impl_pointer y=end_of_range(x);
  1363. do{
  1364. ++res;
  1365. x=node_alg::after(x);
  1366. }while(x!=y);
  1367. return res;
  1368. }
  1369. }
  1370. return 0;
  1371. }
  1372. template<
  1373. typename CompatibleHash,typename CompatiblePred
  1374. >
  1375. std::pair<iterator,iterator> equal_range(
  1376. const key_type& k,
  1377. const CompatibleHash& hash,const CompatiblePred& eq,mpl::true_)const
  1378. {
  1379. return equal_range(k,hash,eq,mpl::false_());
  1380. }
  1381. template<
  1382. typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
  1383. >
  1384. std::pair<iterator,iterator> equal_range(
  1385. const CompatibleKey& k,
  1386. const CompatibleHash& hash,const CompatiblePred& eq,mpl::false_)const
  1387. {
  1388. std::size_t buc=buckets.position(hash(k));
  1389. for(node_impl_pointer x=buckets.at(buc)->prior();
  1390. x!=node_impl_pointer(0);x=node_alg::next_to_inspect(x)){
  1391. if(eq(k,key(node_type::from_impl(x)->value()))){
  1392. return std::pair<iterator,iterator>(
  1393. make_iterator(node_type::from_impl(x)),
  1394. make_iterator(node_type::from_impl(end_of_range(x))));
  1395. }
  1396. }
  1397. return std::pair<iterator,iterator>(end(),end());
  1398. }
  1399. key_from_value key;
  1400. hasher hash_;
  1401. key_equal eq_;
  1402. bucket_array_type buckets;
  1403. float mlf;
  1404. size_type max_load;
  1405. #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
  1406. BOOST_WORKAROUND(__MWERKS__,<=0x3003)
  1407. #pragma parse_mfunc_templ reset
  1408. #endif
  1409. };
  1410. /* comparison */
  1411. template<
  1412. typename KeyFromValue,typename Hash,typename Pred,
  1413. typename SuperMeta,typename TagList,typename Category
  1414. >
  1415. bool operator==(
  1416. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
  1417. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& y)
  1418. {
  1419. return x.equals(y);
  1420. }
  1421. template<
  1422. typename KeyFromValue,typename Hash,typename Pred,
  1423. typename SuperMeta,typename TagList,typename Category
  1424. >
  1425. bool operator!=(
  1426. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
  1427. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& y)
  1428. {
  1429. return !(x==y);
  1430. }
  1431. /* specialized algorithms */
  1432. template<
  1433. typename KeyFromValue,typename Hash,typename Pred,
  1434. typename SuperMeta,typename TagList,typename Category
  1435. >
  1436. void swap(
  1437. hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
  1438. hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& y)
  1439. {
  1440. x.swap(y);
  1441. }
  1442. } /* namespace multi_index::detail */
  1443. /* hashed index specifiers */
  1444. template<typename Arg1,typename Arg2,typename Arg3,typename Arg4>
  1445. struct hashed_unique
  1446. {
  1447. typedef typename detail::hashed_index_args<
  1448. Arg1,Arg2,Arg3,Arg4> index_args;
  1449. typedef typename index_args::tag_list_type::type tag_list_type;
  1450. typedef typename index_args::key_from_value_type key_from_value_type;
  1451. typedef typename index_args::hash_type hash_type;
  1452. typedef typename index_args::pred_type pred_type;
  1453. template<typename Super>
  1454. struct node_class
  1455. {
  1456. typedef detail::hashed_index_node<Super,detail::hashed_unique_tag> type;
  1457. };
  1458. template<typename SuperMeta>
  1459. struct index_class
  1460. {
  1461. typedef detail::hashed_index<
  1462. key_from_value_type,hash_type,pred_type,
  1463. SuperMeta,tag_list_type,detail::hashed_unique_tag> type;
  1464. };
  1465. };
  1466. template<typename Arg1,typename Arg2,typename Arg3,typename Arg4>
  1467. struct hashed_non_unique
  1468. {
  1469. typedef typename detail::hashed_index_args<
  1470. Arg1,Arg2,Arg3,Arg4> index_args;
  1471. typedef typename index_args::tag_list_type::type tag_list_type;
  1472. typedef typename index_args::key_from_value_type key_from_value_type;
  1473. typedef typename index_args::hash_type hash_type;
  1474. typedef typename index_args::pred_type pred_type;
  1475. template<typename Super>
  1476. struct node_class
  1477. {
  1478. typedef detail::hashed_index_node<
  1479. Super,detail::hashed_non_unique_tag> type;
  1480. };
  1481. template<typename SuperMeta>
  1482. struct index_class
  1483. {
  1484. typedef detail::hashed_index<
  1485. key_from_value_type,hash_type,pred_type,
  1486. SuperMeta,tag_list_type,detail::hashed_non_unique_tag> type;
  1487. };
  1488. };
  1489. } /* namespace multi_index */
  1490. } /* namespace boost */
  1491. /* Boost.Foreach compatibility */
  1492. template<
  1493. typename KeyFromValue,typename Hash,typename Pred,
  1494. typename SuperMeta,typename TagList,typename Category
  1495. >
  1496. inline boost::mpl::true_* boost_foreach_is_noncopyable(
  1497. boost::multi_index::detail::hashed_index<
  1498. KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>*&,
  1499. boost_foreach_argument_dependent_lookup_hack)
  1500. {
  1501. return 0;
  1502. }
  1503. #undef BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT
  1504. #undef BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT_OF
  1505. #endif