hashed_index.hpp 51 KB

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