hashed_index.hpp 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744
  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/allocator_utilities.hpp>
  18. #include <boost/detail/no_exceptions_support.hpp>
  19. #include <boost/detail/workaround.hpp>
  20. #include <boost/foreach_fwd.hpp>
  21. #include <boost/limits.hpp>
  22. #include <boost/move/core.hpp>
  23. #include <boost/mpl/bool.hpp>
  24. #include <boost/mpl/if.hpp>
  25. #include <boost/mpl/push_front.hpp>
  26. #include <boost/multi_index/detail/access_specifier.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. #include <memory>
  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 tuple<std::size_t,
  109. key_from_value,hasher,key_equal> ctor_args;
  110. typedef typename super::final_allocator_type allocator_type;
  111. #ifdef BOOST_NO_CXX11_ALLOCATOR
  112. typedef typename allocator_type::pointer pointer;
  113. typedef typename allocator_type::const_pointer const_pointer;
  114. typedef typename allocator_type::reference reference;
  115. typedef typename allocator_type::const_reference const_reference;
  116. #else
  117. typedef std::allocator_traits<allocator_type> allocator_traits;
  118. typedef typename allocator_traits::pointer pointer;
  119. typedef typename allocator_traits::const_pointer const_pointer;
  120. typedef value_type& reference;
  121. typedef const value_type& const_reference;
  122. #endif
  123. typedef std::size_t size_type;
  124. typedef std::ptrdiff_t difference_type;
  125. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  126. typedef safe_mode::safe_iterator<
  127. hashed_index_iterator<
  128. node_type,bucket_array_type,
  129. hashed_index_global_iterator_tag>,
  130. hashed_index> iterator;
  131. #else
  132. typedef hashed_index_iterator<
  133. node_type,bucket_array_type,
  134. hashed_index_global_iterator_tag> iterator;
  135. #endif
  136. typedef iterator const_iterator;
  137. typedef hashed_index_iterator<
  138. node_type,bucket_array_type,
  139. hashed_index_local_iterator_tag> local_iterator;
  140. typedef local_iterator const_local_iterator;
  141. typedef TagList tag_list;
  142. protected:
  143. typedef typename super::final_node_type final_node_type;
  144. typedef tuples::cons<
  145. ctor_args,
  146. typename super::ctor_args_list> ctor_args_list;
  147. typedef typename mpl::push_front<
  148. typename super::index_type_list,
  149. hashed_index>::type index_type_list;
  150. typedef typename mpl::push_front<
  151. typename super::iterator_type_list,
  152. iterator>::type iterator_type_list;
  153. typedef typename mpl::push_front<
  154. typename super::const_iterator_type_list,
  155. const_iterator>::type const_iterator_type_list;
  156. typedef typename super::copy_map_type copy_map_type;
  157. #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
  158. typedef typename super::index_saver_type index_saver_type;
  159. typedef typename super::index_loader_type index_loader_type;
  160. #endif
  161. private:
  162. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  163. typedef safe_mode::safe_container<
  164. hashed_index> safe_super;
  165. #endif
  166. typedef typename call_traits<value_type>::param_type value_param_type;
  167. typedef typename call_traits<
  168. key_type>::param_type key_param_type;
  169. /* Needed to avoid commas in BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL
  170. * expansion.
  171. */
  172. typedef std::pair<iterator,bool> emplace_return_type;
  173. public:
  174. /* construct/destroy/copy
  175. * Default and copy ctors are in the protected section as indices are
  176. * not supposed to be created on their own. No range ctor either.
  177. */
  178. hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& operator=(
  179. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
  180. {
  181. this->final()=x.final();
  182. return *this;
  183. }
  184. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  185. hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& operator=(
  186. std::initializer_list<value_type> list)
  187. {
  188. this->final()=list;
  189. return *this;
  190. }
  191. #endif
  192. allocator_type get_allocator()const BOOST_NOEXCEPT
  193. {
  194. return this->final().get_allocator();
  195. }
  196. /* size and capacity */
  197. bool empty()const BOOST_NOEXCEPT{return this->final_empty_();}
  198. size_type size()const BOOST_NOEXCEPT{return this->final_size_();}
  199. size_type max_size()const BOOST_NOEXCEPT{return this->final_max_size_();}
  200. /* iterators */
  201. iterator begin()BOOST_NOEXCEPT
  202. {return make_iterator(node_type::from_impl(header()->next()->prior()));}
  203. const_iterator begin()const BOOST_NOEXCEPT
  204. {return make_iterator(node_type::from_impl(header()->next()->prior()));}
  205. iterator end()BOOST_NOEXCEPT{return make_iterator(header());}
  206. const_iterator end()const BOOST_NOEXCEPT{return make_iterator(header());}
  207. const_iterator cbegin()const BOOST_NOEXCEPT{return begin();}
  208. const_iterator cend()const BOOST_NOEXCEPT{return end();}
  209. iterator iterator_to(const value_type& x)
  210. {
  211. return make_iterator(node_from_value<node_type>(boost::addressof(x)));
  212. }
  213. const_iterator iterator_to(const value_type& x)const
  214. {
  215. return make_iterator(node_from_value<node_type>(boost::addressof(x)));
  216. }
  217. /* modifiers */
  218. BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL(
  219. emplace_return_type,emplace,emplace_impl)
  220. BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL_EXTRA_ARG(
  221. iterator,emplace_hint,emplace_hint_impl,iterator,position)
  222. std::pair<iterator,bool> insert(const value_type& x)
  223. {
  224. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  225. std::pair<final_node_type*,bool> p=this->final_insert_(x);
  226. return std::pair<iterator,bool>(make_iterator(p.first),p.second);
  227. }
  228. std::pair<iterator,bool> insert(BOOST_RV_REF(value_type) x)
  229. {
  230. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  231. std::pair<final_node_type*,bool> p=this->final_insert_rv_(x);
  232. return std::pair<iterator,bool>(make_iterator(p.first),p.second);
  233. }
  234. iterator insert(iterator position,const value_type& x)
  235. {
  236. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  237. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  238. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  239. std::pair<final_node_type*,bool> p=this->final_insert_(
  240. x,static_cast<final_node_type*>(position.get_node()));
  241. return make_iterator(p.first);
  242. }
  243. iterator insert(iterator position,BOOST_RV_REF(value_type) x)
  244. {
  245. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  246. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  247. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  248. std::pair<final_node_type*,bool> p=this->final_insert_rv_(
  249. x,static_cast<final_node_type*>(position.get_node()));
  250. return make_iterator(p.first);
  251. }
  252. template<typename InputIterator>
  253. void insert(InputIterator first,InputIterator last)
  254. {
  255. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  256. for(;first!=last;++first)this->final_insert_ref_(*first);
  257. }
  258. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
  259. void insert(std::initializer_list<value_type> list)
  260. {
  261. insert(list.begin(),list.end());
  262. }
  263. #endif
  264. iterator erase(iterator position)
  265. {
  266. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  267. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  268. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  269. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  270. this->final_erase_(static_cast<final_node_type*>(position++.get_node()));
  271. return position;
  272. }
  273. size_type erase(key_param_type k)
  274. {
  275. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  276. std::size_t buc=buckets.position(hash_(k));
  277. for(node_impl_pointer x=buckets.at(buc)->prior();
  278. x!=node_impl_pointer(0);x=node_alg::next_to_inspect(x)){
  279. if(eq_(k,key(node_type::from_impl(x)->value()))){
  280. node_impl_pointer y=end_of_range(x);
  281. size_type s=0;
  282. do{
  283. node_impl_pointer z=node_alg::after(x);
  284. this->final_erase_(
  285. static_cast<final_node_type*>(node_type::from_impl(x)));
  286. x=z;
  287. ++s;
  288. }while(x!=y);
  289. return s;
  290. }
  291. }
  292. return 0;
  293. }
  294. iterator erase(iterator first,iterator last)
  295. {
  296. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
  297. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
  298. BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
  299. BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
  300. BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
  301. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  302. while(first!=last){
  303. first=erase(first);
  304. }
  305. return first;
  306. }
  307. bool replace(iterator position,const value_type& x)
  308. {
  309. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  310. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  311. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  312. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  313. return this->final_replace_(
  314. x,static_cast<final_node_type*>(position.get_node()));
  315. }
  316. bool replace(iterator position,BOOST_RV_REF(value_type) x)
  317. {
  318. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  319. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  320. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  321. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  322. return this->final_replace_rv_(
  323. x,static_cast<final_node_type*>(position.get_node()));
  324. }
  325. template<typename Modifier>
  326. bool modify(iterator position,Modifier mod)
  327. {
  328. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  329. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  330. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  331. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  332. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  333. /* MSVC++ 6.0 optimizer on safe mode code chokes if this
  334. * this is not added. Left it for all compilers as it does no
  335. * harm.
  336. */
  337. position.detach();
  338. #endif
  339. return this->final_modify_(
  340. mod,static_cast<final_node_type*>(position.get_node()));
  341. }
  342. template<typename Modifier,typename Rollback>
  343. bool modify(iterator position,Modifier mod,Rollback back_)
  344. {
  345. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  346. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  347. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  348. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  349. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  350. /* MSVC++ 6.0 optimizer on safe mode code chokes if this
  351. * this is not added. Left it for all compilers as it does no
  352. * harm.
  353. */
  354. position.detach();
  355. #endif
  356. return this->final_modify_(
  357. mod,back_,static_cast<final_node_type*>(position.get_node()));
  358. }
  359. template<typename Modifier>
  360. bool modify_key(iterator position,Modifier mod)
  361. {
  362. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  363. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  364. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  365. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  366. return modify(
  367. position,modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key));
  368. }
  369. template<typename Modifier,typename Rollback>
  370. bool modify_key(iterator position,Modifier mod,Rollback back_)
  371. {
  372. BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
  373. BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
  374. BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
  375. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  376. return modify(
  377. position,
  378. modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key),
  379. modify_key_adaptor<Rollback,value_type,KeyFromValue>(back_,key));
  380. }
  381. void clear()BOOST_NOEXCEPT
  382. {
  383. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  384. this->final_clear_();
  385. }
  386. void swap(hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
  387. {
  388. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  389. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT_OF(x);
  390. this->final_swap_(x.final());
  391. }
  392. /* observers */
  393. key_from_value key_extractor()const{return key;}
  394. hasher hash_function()const{return hash_;}
  395. key_equal key_eq()const{return eq_;}
  396. /* lookup */
  397. /* Internally, these ops rely on const_iterator being the same
  398. * type as iterator.
  399. */
  400. /* Implementation note: When CompatibleKey is consistently promoted to
  401. * KeyFromValue::result_type for equality comparison, the promotion is made
  402. * once in advance to increase efficiency.
  403. */
  404. template<typename CompatibleKey>
  405. iterator find(const CompatibleKey& k)const
  406. {
  407. return find(k,hash_,eq_);
  408. }
  409. template<
  410. typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
  411. >
  412. iterator find(
  413. const CompatibleKey& k,
  414. const CompatibleHash& hash,const CompatiblePred& eq)const
  415. {
  416. return find(
  417. k,hash,eq,promotes_1st_arg<CompatiblePred,CompatibleKey,key_type>());
  418. }
  419. template<typename CompatibleKey>
  420. size_type count(const CompatibleKey& k)const
  421. {
  422. return count(k,hash_,eq_);
  423. }
  424. template<
  425. typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
  426. >
  427. size_type count(
  428. const CompatibleKey& k,
  429. const CompatibleHash& hash,const CompatiblePred& eq)const
  430. {
  431. return count(
  432. k,hash,eq,promotes_1st_arg<CompatiblePred,CompatibleKey,key_type>());
  433. }
  434. template<typename CompatibleKey>
  435. std::pair<iterator,iterator> equal_range(const CompatibleKey& k)const
  436. {
  437. return equal_range(k,hash_,eq_);
  438. }
  439. template<
  440. typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
  441. >
  442. std::pair<iterator,iterator> equal_range(
  443. const CompatibleKey& k,
  444. const CompatibleHash& hash,const CompatiblePred& eq)const
  445. {
  446. return equal_range(
  447. k,hash,eq,promotes_1st_arg<CompatiblePred,CompatibleKey,key_type>());
  448. }
  449. /* bucket interface */
  450. size_type bucket_count()const BOOST_NOEXCEPT{return buckets.size();}
  451. size_type max_bucket_count()const BOOST_NOEXCEPT{return static_cast<size_type>(-1);}
  452. size_type bucket_size(size_type n)const
  453. {
  454. size_type res=0;
  455. for(node_impl_pointer x=buckets.at(n)->prior();
  456. x!=node_impl_pointer(0);x=node_alg::after_local(x)){
  457. ++res;
  458. }
  459. return res;
  460. }
  461. size_type bucket(key_param_type k)const
  462. {
  463. return buckets.position(hash_(k));
  464. }
  465. local_iterator begin(size_type n)
  466. {
  467. return const_cast<const hashed_index*>(this)->begin(n);
  468. }
  469. const_local_iterator begin(size_type n)const
  470. {
  471. node_impl_pointer x=buckets.at(n)->prior();
  472. if(x==node_impl_pointer(0))return end(n);
  473. return make_local_iterator(node_type::from_impl(x));
  474. }
  475. local_iterator end(size_type n)
  476. {
  477. return const_cast<const hashed_index*>(this)->end(n);
  478. }
  479. const_local_iterator end(size_type)const
  480. {
  481. return make_local_iterator(0);
  482. }
  483. const_local_iterator cbegin(size_type n)const{return begin(n);}
  484. const_local_iterator cend(size_type n)const{return end(n);}
  485. local_iterator local_iterator_to(const value_type& x)
  486. {
  487. return make_local_iterator(
  488. node_from_value<node_type>(boost::addressof(x)));
  489. }
  490. const_local_iterator local_iterator_to(const value_type& x)const
  491. {
  492. return make_local_iterator(
  493. node_from_value<node_type>(boost::addressof(x)));
  494. }
  495. /* hash policy */
  496. float load_factor()const BOOST_NOEXCEPT
  497. {return static_cast<float>(size())/bucket_count();}
  498. float max_load_factor()const BOOST_NOEXCEPT{return mlf;}
  499. void max_load_factor(float z){mlf=z;calculate_max_load();}
  500. void rehash(size_type n)
  501. {
  502. BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
  503. if(size()<=max_load&&n<=bucket_count())return;
  504. size_type bc =(std::numeric_limits<size_type>::max)();
  505. float fbc=1.0f+static_cast<float>(size())/mlf;
  506. if(bc>fbc){
  507. bc=static_cast<size_type>(fbc);
  508. if(bc<n)bc=n;
  509. }
  510. unchecked_rehash(bc);
  511. }
  512. void reserve(size_type n)
  513. {
  514. rehash(static_cast<size_type>(std::ceil(static_cast<float>(n)/mlf)));
  515. }
  516. BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
  517. hashed_index(const ctor_args_list& args_list,const allocator_type& al):
  518. super(args_list.get_tail(),al),
  519. key(tuples::get<1>(args_list.get_head())),
  520. hash_(tuples::get<2>(args_list.get_head())),
  521. eq_(tuples::get<3>(args_list.get_head())),
  522. buckets(al,header()->impl(),tuples::get<0>(args_list.get_head())),
  523. mlf(1.0f)
  524. {
  525. calculate_max_load();
  526. }
  527. hashed_index(
  528. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x):
  529. super(x),
  530. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  531. safe_super(),
  532. #endif
  533. key(x.key),
  534. hash_(x.hash_),
  535. eq_(x.eq_),
  536. buckets(x.get_allocator(),header()->impl(),x.buckets.size()),
  537. mlf(x.mlf),
  538. max_load(x.max_load)
  539. {
  540. /* Copy ctor just takes the internal configuration objects from x. The rest
  541. * is done in subsequent call to copy_().
  542. */
  543. }
  544. hashed_index(
  545. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
  546. do_not_copy_elements_tag):
  547. super(x,do_not_copy_elements_tag()),
  548. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  549. safe_super(),
  550. #endif
  551. key(x.key),
  552. hash_(x.hash_),
  553. eq_(x.eq_),
  554. buckets(x.get_allocator(),header()->impl(),0),
  555. mlf(1.0f)
  556. {
  557. calculate_max_load();
  558. }
  559. ~hashed_index()
  560. {
  561. /* the container is guaranteed to be empty by now */
  562. }
  563. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  564. iterator make_iterator(node_type* node)
  565. {
  566. return iterator(node,this);
  567. }
  568. const_iterator make_iterator(node_type* node)const
  569. {
  570. return const_iterator(node,const_cast<hashed_index*>(this));
  571. }
  572. #else
  573. iterator make_iterator(node_type* node)
  574. {
  575. return iterator(node);
  576. }
  577. const_iterator make_iterator(node_type* node)const
  578. {
  579. return const_iterator(node);
  580. }
  581. #endif
  582. local_iterator make_local_iterator(node_type* node)
  583. {
  584. return local_iterator(node);
  585. }
  586. const_local_iterator make_local_iterator(node_type* node)const
  587. {
  588. return const_local_iterator(node);
  589. }
  590. void copy_(
  591. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
  592. const copy_map_type& map)
  593. {
  594. copy_(x,map,Category());
  595. }
  596. void copy_(
  597. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
  598. const copy_map_type& map,hashed_unique_tag)
  599. {
  600. if(x.size()!=0){
  601. node_impl_pointer end_org=x.header()->impl(),
  602. org=end_org,
  603. cpy=header()->impl();
  604. do{
  605. node_impl_pointer prev_org=org->prior(),
  606. prev_cpy=
  607. static_cast<node_type*>(map.find(static_cast<final_node_type*>(
  608. node_type::from_impl(prev_org))))->impl();
  609. cpy->prior()=prev_cpy;
  610. if(node_alg::is_first_of_bucket(org)){
  611. node_impl_base_pointer buc_org=prev_org->next(),
  612. buc_cpy=
  613. buckets.begin()+(buc_org-x.buckets.begin());
  614. prev_cpy->next()=buc_cpy;
  615. buc_cpy->prior()=cpy;
  616. }
  617. else{
  618. prev_cpy->next()=node_impl_type::base_pointer_from(cpy);
  619. }
  620. org=prev_org;
  621. cpy=prev_cpy;
  622. }while(org!=end_org);
  623. }
  624. super::copy_(x,map);
  625. }
  626. void copy_(
  627. const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
  628. const copy_map_type& map,hashed_non_unique_tag)
  629. {
  630. if(x.size()!=0){
  631. node_impl_pointer end_org=x.header()->impl(),
  632. org=end_org,
  633. cpy=header()->impl();
  634. do{
  635. node_impl_pointer next_org=node_alg::after(org),
  636. next_cpy=
  637. static_cast<node_type*>(map.find(static_cast<final_node_type*>(
  638. node_type::from_impl(next_org))))->impl();
  639. if(node_alg::is_first_of_bucket(next_org)){
  640. node_impl_base_pointer buc_org=org->next(),
  641. buc_cpy=
  642. buckets.begin()+(buc_org-x.buckets.begin());
  643. cpy->next()=buc_cpy;
  644. buc_cpy->prior()=next_cpy;
  645. next_cpy->prior()=cpy;
  646. }
  647. else{
  648. if(org->next()==node_impl_type::base_pointer_from(next_org)){
  649. cpy->next()=node_impl_type::base_pointer_from(next_cpy);
  650. }
  651. else{
  652. cpy->next()=
  653. node_impl_type::base_pointer_from(
  654. static_cast<node_type*>(map.find(static_cast<final_node_type*>(
  655. node_type::from_impl(
  656. node_impl_type::pointer_from(org->next())))))->impl());
  657. }
  658. if(next_org->prior()!=org){
  659. next_cpy->prior()=
  660. static_cast<node_type*>(map.find(static_cast<final_node_type*>(
  661. node_type::from_impl(next_org->prior()))))->impl();
  662. }
  663. else{
  664. next_cpy->prior()=cpy;
  665. }
  666. }
  667. org=next_org;
  668. cpy=next_cpy;
  669. }while(org!=end_org);
  670. }
  671. super::copy_(x,map);
  672. }
  673. template<typename Variant>
  674. final_node_type* insert_(
  675. value_param_type v,final_node_type*& x,Variant variant)
  676. {
  677. reserve_for_insert(size()+1);
  678. std::size_t buc=find_bucket(v);
  679. link_info pos(buckets.at(buc));
  680. if(!link_point(v,pos)){
  681. return static_cast<final_node_type*>(
  682. node_type::from_impl(node_impl_type::pointer_from(pos)));
  683. }
  684. final_node_type* res=super::insert_(v,x,variant);
  685. if(res==x)link(static_cast<node_type*>(x),pos);
  686. return res;
  687. }
  688. template<typename Variant>
  689. final_node_type* insert_(
  690. value_param_type v,node_type* position,final_node_type*& x,Variant variant)
  691. {
  692. reserve_for_insert(size()+1);
  693. std::size_t buc=find_bucket(v);
  694. link_info pos(buckets.at(buc));
  695. if(!link_point(v,pos)){
  696. return static_cast<final_node_type*>(
  697. node_type::from_impl(node_impl_type::pointer_from(pos)));
  698. }
  699. final_node_type* res=super::insert_(v,position,x,variant);
  700. if(res==x)link(static_cast<node_type*>(x),pos);
  701. return res;
  702. }
  703. void erase_(node_type* x)
  704. {
  705. unlink(x);
  706. super::erase_(x);
  707. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  708. detach_iterators(x);
  709. #endif
  710. }
  711. void delete_all_nodes_()
  712. {
  713. delete_all_nodes_(Category());
  714. }
  715. void delete_all_nodes_(hashed_unique_tag)
  716. {
  717. for(node_impl_pointer x_end=header()->impl(),x=x_end->prior();x!=x_end;){
  718. node_impl_pointer y=x->prior();
  719. this->final_delete_node_(
  720. static_cast<final_node_type*>(node_type::from_impl(x)));
  721. x=y;
  722. }
  723. }
  724. void delete_all_nodes_(hashed_non_unique_tag)
  725. {
  726. for(node_impl_pointer x_end=header()->impl(),x=x_end->prior();x!=x_end;){
  727. node_impl_pointer y=x->prior();
  728. if(y->next()!=node_impl_type::base_pointer_from(x)&&
  729. y->next()->prior()!=x){ /* n-1 of group */
  730. /* Make the second node prior() pointer back-linked so that it won't
  731. * refer to a deleted node when the time for its own destruction comes.
  732. */
  733. node_impl_pointer first=node_impl_type::pointer_from(y->next());
  734. first->next()->prior()=first;
  735. }
  736. this->final_delete_node_(
  737. static_cast<final_node_type*>(node_type::from_impl(x)));
  738. x=y;
  739. }
  740. }
  741. void clear_()
  742. {
  743. super::clear_();
  744. buckets.clear(header()->impl());
  745. #if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
  746. safe_super::detach_dereferenceable_iterators();
  747. #endif
  748. }
  749. void swap_(
  750. hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
  751. {
  752. std::swap(key,x.key);
  753. std::swap(hash_,x.hash_);
  754. std::swap(eq_,x.eq_);
  755. buckets.swap(x.buckets);
  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);
  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. std::ptrdiff_t 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