From 8a4620da17b8afcd340584c04a687773fb53497b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Mon, 13 Jun 2022 00:50:37 +0200 Subject: [PATCH] Add experimental fastmod_buckets support --- include/boost/container/detail/hash_table.hpp | 205 ++++++++++-------- .../container/detail/node_alloc_holder.hpp | 68 +++--- include/boost/container/options.hpp | 9 +- 3 files changed, 146 insertions(+), 136 deletions(-) diff --git a/include/boost/container/detail/hash_table.hpp b/include/boost/container/detail/hash_table.hpp index 1d70766..306606d 100644 --- a/include/boost/container/detail/hash_table.hpp +++ b/include/boost/container/detail/hash_table.hpp @@ -26,6 +26,7 @@ #include #include #include +#include // container/detail #include //algo_equal(), algo_lexicographical_compare @@ -152,12 +153,14 @@ class hash_insert_equal_end_hint_functor namespace dtl { -template< class NodeType, class NodeHashType, class NodeCompareType - , class SizeType, class HookType, bool CompareHash, bool CacheBegin, bool LinearBuckets> +template< class NodeType, class KeyOfNode, class NodeHashType, class NodeCompareType + , class SizeType, class HookType, bool CompareHash + , bool CacheBegin, bool LinearBuckets, bool FastmodBuckets> struct intrusive_hash_table_dispatch { typedef typename dtl::bi::make_hashtable ,dtl::bi::hash ,dtl::bi::equal ,dtl::bi::base_hook @@ -166,11 +169,12 @@ struct intrusive_hash_table_dispatch ,dtl::bi::cache_begin ,dtl::bi::compare_hash ,dtl::bi::linear_buckets + ,dtl::bi::fastmod_buckets >::type type; }; -template +template struct intrusive_hash_table_type { private: @@ -182,20 +186,20 @@ struct intrusive_hash_table_type allocator_traits::size_type size_type; typedef base_node > node_t; - typedef value_to_node_compare - node_hash_type; - typedef value_to_node_compare - node_equal_type; //Deducing the hook type from node_t (e.g. node_t::hook_type) would //provoke an early instantiation of node_t that could ruin recursive //hash_table definitions, so retype the complete type to avoid any problem. typedef typename intrusive_hash_table_hook ::type hook_type; + + typedef key_of_node + key_of_node_t; + public: typedef typename intrusive_hash_table_dispatch - < node_t, node_hash_type, node_equal_type + < node_t, key_of_node_t, KeyHash, KeyCompare , size_type, hook_type, StoreHash - , CacheBegin, LinearBuckets>::type type; + , CacheBegin, LinearBuckets, FastmodBuckets>::type type; }; } //namespace dtl { @@ -263,30 +267,31 @@ struct hash_table_types { typedef typename hash_key_of_value < typename allocator_traits::value_type - , KeyOfValue>::type key_of_value_t; + , KeyOfValue>::type key_of_value_t; typedef tree_value_compare < typename allocator_traits::pointer - , KeyHash, key_of_value_t, std::size_t> ValHash; + , KeyHash, key_of_value_t, std::size_t> ValHash; typedef tree_value_compare < typename allocator_traits::pointer - , KeyEqual, key_of_value_t, bool> ValEqual; - typedef typename get_hash_opt::type options_type; + , KeyEqual, key_of_value_t, bool> ValEqual; + typedef typename get_hash_opt::type options_type; typedef typename dtl::intrusive_hash_table_type - < Allocator, ValHash, ValEqual + < Allocator, key_of_value_t, KeyHash, ValEqual , options_type::store_hash , options_type::cache_begin , options_type::linear_buckets + , options_type::fastmod_buckets >::type Icont; typedef typename Icont::bucket_type bucket_type; typedef typename Icont::bucket_traits bucket_traits; - typedef dtl::node_alloc_holder - AllocHolder; typedef typename boost::container:: allocator_traits::template portable_rebind_alloc::type bucket_allocator; - typedef std::vector bucket_holder_t; - + typedef boost::container::vector + bucket_holder_t; + typedef dtl::node_alloc_holder + AllocHolder; }; template @@ -296,10 +301,12 @@ struct static_buckets Bucket buckets_[N]; }; +const std::size_t SmallestBucketSize = 3u; + template class hash_table : public static_buckets< typename hash_table_types::bucket_type - , hash_table_types::Icont::bucket_overhead+1u> + , hash_table_types::Icont::bucket_overhead+SmallestBucketSize> , public hash_table_types::bucket_holder_t , public hash_table_types::AllocHolder { @@ -330,7 +337,7 @@ class hash_table ::bucket_holder_t bucket_holder_t; typedef static_buckets< typename Icont::bucket_type - , Icont::bucket_overhead + 1u > static_buckets_t; + , Icont::bucket_overhead + SmallestBucketSize > static_buckets_t; BOOST_COPYABLE_AND_MOVABLE(hash_table) @@ -538,7 +545,7 @@ class hash_table //Optimized allocation and construction this->allocate_many_and_construct ( first, boost::container::iterator_udistance(first, last) - , hash_insert_equal_end_hint_functor(this->icont())); + , hash_insert_equal_end_hint_functor(this->m_icont)); } public: @@ -546,7 +553,7 @@ class hash_table BOOST_CONTAINER_FORCEINLINE hash_table(const hash_table& x) : AllocHolder(x, x.value_hash_function(), x.value_eq()) { - this->icont().clone_from + this->m_icont.clone_from (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); } @@ -559,19 +566,19 @@ class hash_table BOOST_CONTAINER_FORCEINLINE hash_table(const hash_table& x, const allocator_type &a) : AllocHolder(x.value_hash_function(), x.value_eq(), a) { - this->icont().clone_from + this->m_icont.clone_from (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); //AllocHolder clears in case of exception } hash_table(BOOST_RV_REF(hash_table) x, const allocator_type &a) - : AllocHolder(x.value_hash_function(), x.value_eq(), a) + : AllocHolder(x.hash_function(), x.key_eq(), a) { if(this->node_alloc() == x.node_alloc()){ - this->icont().swap(x.icont()); + this->m_icont.swap(x.icont()); } else{ - this->icont().clone_from + this->m_icont.clone_from (boost::move(x.icont()), typename AllocHolder::move_cloner(*this), Destroyer(this->node_alloc())); } //AllocHolder clears in case of exception @@ -595,10 +602,10 @@ class hash_table //Transfer all the nodes to a temporary hash_table //If anything goes wrong, all the nodes will be destroyed //automatically - Icont other_hash_table(::boost::move(this->icont())); + Icont other_hash_table(::boost::move(this->m_icont)); //Now recreate the source hash_table reusing nodes stored by other_hash_table - this->icont().clone_from + this->m_icont.clone_from (x.icont() , HashRecyclingCloner(*this, other_hash_table) , Destroyer(this->node_alloc())); @@ -629,17 +636,17 @@ class hash_table //Move allocator if needed this->AllocHolder::move_assign_alloc(x); //Obtain resources - this->icont() = boost::move(x.icont()); + this->m_icont = boost::move(x.icont()); } //Else do a one by one move else{ //Transfer all the nodes to a temporary hash_table //If anything goes wrong, all the nodes will be destroyed //automatically - Icont other_hash_table(::boost::move(this->icont())); + Icont other_hash_table(::boost::move(this->m_icont)); //Now recreate the source hash_table reusing nodes stored by other_hash_table - this->icont().clone_from + this->m_icont.clone_from (::boost::move(x.icont()) , HashRecyclingCloner(*this, other_hash_table) , Destroyer(this->node_alloc())); @@ -653,13 +660,13 @@ class hash_table public: // accessors: BOOST_CONTAINER_FORCEINLINE key_equal key_eq() const - { return this->icont().key_eq().predicate().key_comp(); } + { return this->m_icont.key_eq(); } BOOST_CONTAINER_FORCEINLINE value_equal value_eq() const { return value_equal(this->key_eq()); } BOOST_CONTAINER_FORCEINLINE hasher hash_function() const - { return this->icont().hash_function().predicate().key_comp(); } + { return this->m_icont.hash_function(); } BOOST_CONTAINER_FORCEINLINE value_hasher value_hash_function() const { return value_hasher(this->hash_function()); } @@ -674,13 +681,13 @@ class hash_table { return this->node_alloc(); } BOOST_CONTAINER_FORCEINLINE iterator begin() - { return iterator(this->icont().begin()); } + { return iterator(this->m_icont.begin()); } BOOST_CONTAINER_FORCEINLINE const_iterator begin() const { return this->cbegin(); } BOOST_CONTAINER_FORCEINLINE iterator end() - { return iterator(this->icont().end()); } + { return iterator(this->m_icont.end()); } BOOST_CONTAINER_FORCEINLINE const_iterator end() const { return this->cend(); } @@ -705,7 +712,7 @@ class hash_table { return !this->size(); } BOOST_CONTAINER_FORCEINLINE size_type size() const - { return this->icont().size(); } + { return this->m_icont.size(); } BOOST_CONTAINER_FORCEINLINE size_type max_size() const { return AllocHolder::max_size(); } @@ -725,8 +732,8 @@ class hash_table (const key_type& key, insert_commit_data &data) { std::pair ret = - this->icont().insert_unique_check - (key, KeyNodeHash(hash_function()), KeyNodeEqual(key_eq()), data); + this->m_icont.insert_unique_check + (key, data); return std::pair(iterator(ret.first), ret.second); } @@ -737,8 +744,8 @@ class hash_table (void)hint; BOOST_ASSERT((priv_is_linked)(hint)); std::pair ret = - this->icont().insert_unique_check - (key, KeyNodeHash(hash_function()), KeyNodeEqual(key_eq()), data); + this->m_icont.insert_unique_check + (key, data); return std::pair(iterator(ret.first), ret.second); } @@ -747,7 +754,7 @@ class hash_table (BOOST_FWD_REF(MovableConvertible) v, insert_commit_data &data) { NodePtr tmp = AllocHolder::create_node(boost::forward(v)); - return iterator(this->icont().insert_unique_commit(*tmp, data)); + return iterator(this->m_icont.insert_unique_commit(*tmp, data)); } template @@ -770,7 +777,7 @@ class hash_table { NodePtr tmp = AllocHolder::create_node(boost::forward(key), boost::forward(obj)); scoped_node_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); - iiterator ret(this->icont().insert_unique_commit(*tmp, data)); + iiterator ret(this->m_icont.insert_unique_commit(*tmp, data)); destroy_deallocator.release(); return ret; } @@ -778,7 +785,7 @@ class hash_table bool priv_is_linked(const_iterator const position) const { iiterator const cur(position.get()); - return cur == this->icont().end() || + return cur == this->m_icont.end() || (++iiterator(cur) != cur && ++iiterator(cur) != iiterator()); } @@ -788,7 +795,7 @@ class hash_table { NodePtr tmp(AllocHolder::create_node(boost::forward(v))); //push_back has no-throw guarantee so avoid any deallocator/destroyer - this->icont().push_back(*tmp); + this->m_icont.push_back(*tmp); } std::pair emplace_unique_impl(NodePtr p) @@ -804,7 +811,7 @@ class hash_table //No throw insertion part, release rollback destroy_deallocator.release(); return std::pair - ( iterator(this->icont().insert_unique_commit(*p, data)) + ( iterator(this->m_icont.insert_unique_commit(*p, data)) , true ); } @@ -819,7 +826,7 @@ class hash_table Destroyer(this->node_alloc())(p); return ret.first; } - return iterator(this->icont().insert_unique_commit(*p, data)); + return iterator(this->m_icont.insert_unique_commit(*p, data)); } public: @@ -839,7 +846,7 @@ class hash_table { NodePtr tmp(AllocHolder::create_node(boost::forward(args)...)); scoped_node_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); - iterator ret(this->icont().insert_equal(*tmp)); + iterator ret(this->m_icont.insert_equal(*tmp)); destroy_deallocator.release(); return ret; } @@ -851,7 +858,7 @@ class hash_table NodePtr tmp(AllocHolder::create_node(boost::forward(args)...)); scoped_node_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); //to-do: take advantage of hint: just check for equality and insert after if equal - iterator ret(this->icont().insert_equal(*tmp)); + iterator ret(this->m_icont.insert_equal(*tmp)); destroy_deallocator.release(); return ret; } @@ -863,12 +870,12 @@ class hash_table insert_commit_data data; const key_type & k = key; //Support emulated rvalue references std::pair ret = - hint == const_iterator() ? this->icont().insert_unique_check\ - (k, KeyNodeHash(hash_function()), KeyNodeEqual(key_eq()), data) - : this->icont().insert_unique_check\ - (hint.get(), k, KeyNodeHash(hash_function()), KeyNodeEqual(key_eq()), data); + hint == const_iterator() ? this->m_icont.insert_unique_check\ + (k, data) + : this->m_icont.insert_unique_check\ + (hint.get(), k, data); if(ret.second){ - ret.first = this->icont().insert_unique_commit + ret.first = this->m_icont.insert_unique_commit (*AllocHolder::create_node(try_emplace_t(), boost::forward(key), boost::forward(args)...), data); } return std::pair(iterator(ret.first), ret.second); @@ -890,7 +897,7 @@ class hash_table {\ NodePtr tmp(AllocHolder::create_node(BOOST_MOVE_FWD##N));\ scoped_node_destroy_deallocator destroy_deallocator(tmp, this->node_alloc());\ - iterator ret(this->icont().insert_equal(this->icont().end(), *tmp));\ + iterator ret(this->m_icont.insert_equal(this->m_icont.end(), *tmp));\ destroy_deallocator.release();\ return ret;\ }\ @@ -901,7 +908,7 @@ class hash_table BOOST_ASSERT((priv_is_linked)(hint));\ NodePtr tmp(AllocHolder::create_node(BOOST_MOVE_FWD##N));\ scoped_node_destroy_deallocator destroy_deallocator(tmp, this->node_alloc());\ - iterator ret(this->icont().insert_equal(hint.get(), *tmp));\ + iterator ret(this->m_icont.insert_equal(hint.get(), *tmp));\ destroy_deallocator.release();\ return ret;\ }\ @@ -913,12 +920,12 @@ class hash_table insert_commit_data data;\ const key_type & k = key;\ std::pair ret =\ - hint == const_iterator() ? this->icont().insert_unique_check\ - ( k, KeyNodeHash(hash_function()), KeyNodeEqual(key_eq()), data)\ - : this->icont().insert_unique_check\ - (hint.get(), k, KeyNodeHash(hash_function()), KeyNodeEqual(key_eq()), data);\ + hint == const_iterator() ? this->m_icont.insert_unique_check\ + ( k, data)\ + : this->m_icont.insert_unique_check\ + (hint.get(), k, data);\ if(ret.second){\ - ret.first = this->icont().insert_unique_commit\ + ret.first = this->m_icont.insert_unique_commit\ (*AllocHolder::create_node(try_emplace_t(), boost::forward(key) BOOST_MOVE_I##N BOOST_MOVE_FWD##N), data);\ }\ return std::pair(iterator(ret.first), ret.second);\ @@ -955,7 +962,7 @@ class hash_table NodePtr tmp(AllocHolder::create_node(v)); scoped_node_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); //to-do: take advantage of hint: just check for equality and insert after if equal - iterator ret(this->icont().insert_equal(*tmp)); // + iterator ret(this->m_icont.insert_equal(*tmp)); // destroy_deallocator.release(); return ret; } @@ -973,7 +980,7 @@ class hash_table { NodePtr tmp(AllocHolder::create_node(boost::forward(v))); scoped_node_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); - iterator ret(this->icont().insert_equal(*tmp)); + iterator ret(this->m_icont.insert_equal(*tmp)); destroy_deallocator.release(); return ret; } @@ -986,7 +993,7 @@ class hash_table scoped_node_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); //to-do: take advantage of hint: just check for equality and insert after if equal (void)hint; - iterator ret(this->icont().insert_equal(*tmp)); + iterator ret(this->m_icont.insert_equal(*tmp)); destroy_deallocator.release(); return ret; } @@ -1006,10 +1013,10 @@ class hash_table insert_commit_data data; const key_type & k = key; //Support emulated rvalue references std::pair ret = - hint == const_iterator() ? this->icont().insert_unique_check\ - (k, KeyNodeHash(hash_function()), KeyNodeEqual(key_eq()), data) - : this->icont().insert_unique_check\ - (hint.get(), k, KeyNodeHash(hash_function()), KeyNodeEqual(key_eq()), data); + hint == const_iterator() ? this->m_icont.insert_unique_check\ + (k, data) + : this->m_icont.insert_unique_check\ + (hint.get(), k, data); if(ret.second){ ret.first = this->priv_insert_or_assign_commit(boost::forward(key), boost::forward(obj), data); } @@ -1022,11 +1029,11 @@ class hash_table BOOST_CONTAINER_FORCEINLINE void erase(const_iterator position) { BOOST_ASSERT(position != this->cend() && (priv_is_linked)(position)); - return this->icont().erase_and_dispose(position.get(), Destroyer(this->node_alloc())); + return this->m_icont.erase_and_dispose(position.get(), Destroyer(this->node_alloc())); } BOOST_CONTAINER_FORCEINLINE size_type erase(const key_type& k) - { return AllocHolder::erase_key(k, KeyNodeHash(hash_function()), KeyNodeEqual(key_eq()), alloc_version()); } + { return AllocHolder::erase_key(k, alloc_version()); } iterator erase(const_iterator first, const_iterator last) { @@ -1048,7 +1055,7 @@ class hash_table { BOOST_ASSERT(position != this->cend() && (priv_is_linked)(position)); iiterator const iit(position.get()); - this->icont().erase(iit); + this->m_icont.erase(iit); return node_type(iit.operator->(), this->node_alloc()); } @@ -1066,7 +1073,7 @@ class hash_table this->insert_unique_check(hint, key_of_value_type()(nh.value()), data); if(ret.second){ irt.inserted = true; - irt.position = iterator(this->icont().insert_unique_commit(*nh.get(), data)); + irt.position = iterator(this->m_icont.insert_unique_commit(*nh.get(), data)); nh.release(); } else{ @@ -1087,7 +1094,7 @@ class hash_table } else{ NodePtr const p(nh.release()); - return iterator(this->icont().insert_equal(*p)); + return iterator(this->m_icont.insert_equal(*p)); } } @@ -1099,7 +1106,7 @@ class hash_table else{ NodePtr const p(nh.release()); //to-do: take advantage of hint: just check for equality and insert after if equal - return iterator(this->icont().insert_equal(*p)); (void)hint; + return iterator(this->m_icont.insert_equal(*p)); (void)hint; } } @@ -1117,13 +1124,13 @@ class hash_table // search operations. Const and non-const overloads even if no iterator is returned // so splay implementations can to their rebalancing when searching in non-const versions BOOST_CONTAINER_FORCEINLINE iterator find(const key_type& k) - { return iterator(this->icont().find(k, KeyNodeHash(hash_function()), KeyNodeEqual(key_eq()))); } + { return iterator(this->m_icont.find(k)); } BOOST_CONTAINER_FORCEINLINE const_iterator find(const key_type& k) const - { return const_iterator(this->non_const_icont().find(k, KeyNodeHash(hash_function()), KeyNodeEqual(key_eq()))); } + { return const_iterator(this->non_const_icont().find(k)); } BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& k) const - { return size_type(this->icont().count(k, KeyNodeHash(hash_function()), KeyNodeEqual(key_eq()))); } + { return size_type(this->m_icont.count(k)); } BOOST_CONTAINER_FORCEINLINE bool contains(const key_type& x) const { return this->find(x) != this->cend(); } @@ -1131,14 +1138,14 @@ class hash_table std::pair equal_range(const key_type& k) { std::pair ret = - this->icont().equal_range(k, KeyNodeHash(hash_function()), KeyNodeEqual(key_eq())); + this->m_icont.equal_range(k); return std::pair(iterator(ret.first), iterator(ret.second)); } std::pair equal_range(const key_type& k) const { std::pair ret = - this->non_const_icont().equal_range(k, KeyNodeHash(hash_function()), KeyNodeEqual(key_eq())); + this->non_const_icont().equal_range(k); return std::pair (const_iterator(ret.first), const_iterator(ret.second)); } @@ -1150,42 +1157,48 @@ class hash_table { return priv_equal_range_unique(*this, k); } BOOST_CONTAINER_FORCEINLINE size_type bucket_count() const BOOST_NOEXCEPT - { return this->icont().bucket_count(); } + { return this->m_icont.bucket_count(); } BOOST_CONTAINER_FORCEINLINE size_type max_bucket_count() const BOOST_NOEXCEPT { return this->max_size(); } BOOST_CONTAINER_FORCEINLINE size_type bucket_size(size_type n) const - { return this->icont().bucket_size(n); } + { return this->m_icont.bucket_size(n); } BOOST_CONTAINER_FORCEINLINE size_type bucket(const key_type& k) const - { return this->icont().bucket(k, KeyNodeHash(hash_function())); } - + { return this->m_icont.bucket(k, KeyNodeHash()); } +/* BOOST_CONTAINER_FORCEINLINE local_iterator begin(size_type n) - { return local_iterator(this->icont().begin(n)); } + { return local_iterator(this->m_icont.begin(n)); } BOOST_CONTAINER_FORCEINLINE const_local_iterator begin(size_type n) const - { return const_local_iterator(this->non_const_icont().begin(n)); } - - BOOST_CONTAINER_FORCEINLINE const_local_iterator cbegin(size_type n) const { return this->cbegin(n); } + BOOST_CONTAINER_FORCEINLINE const_local_iterator cbegin(size_type n) const + { return const_local_iterator(this->non_const_icont().begin(n)); } + BOOST_CONTAINER_FORCEINLINE local_iterator end(size_type n) - { return local_iterator(this->icont().end(n)); } + { return local_iterator(this->m_icont.end(n)); } BOOST_CONTAINER_FORCEINLINE const_local_iterator end(size_type n) const - { return const_local_iterator(this->non_const_icont().end(n)); } - - BOOST_CONTAINER_FORCEINLINE const_local_iterator cend(size_type n) const { return this->cend(n); } + BOOST_CONTAINER_FORCEINLINE const_local_iterator cend(size_type n) const + { return const_local_iterator(this->non_const_icont().end(n)); } +*/ float load_factor() const BOOST_NOEXCEPT - { return this->icont().load_factor(); } + { + assert(0); + return 0.0f; + } float max_load_factor() const BOOST_NOEXCEPT - { return this->icont().max_load_factor(); } + { + assert(0); + return 0.0f; + } - void max_load_factor(float z) + void max_load_factor(float) { assert(0); } @@ -1200,10 +1213,10 @@ class hash_table void reserve(size_type n) { if (this->bucket_count() < n) { - std::size_t sc = Icont::suggested_upper_bucket_count(n); + std::size_t sc = Icont::suggested_lower_bucket_count(n); bucket_holder_t& this_buckets = *this; bucket_holder_t new_buckets(sc + Icont::bucket_overhead, this_buckets.get_allocator()); - this->icont().rehash(bucket_traits(new_buckets.data(), new_buckets.size())); + this->m_icont.rehash(bucket_traits(new_buckets.data(), new_buckets.size())); this_buckets.swap(new_buckets); } } diff --git a/include/boost/container/detail/node_alloc_holder.hpp b/include/boost/container/detail/node_alloc_holder.hpp index e5d9e50..24d9e46 100644 --- a/include/boost/container/detail/node_alloc_holder.hpp +++ b/include/boost/container/detail/node_alloc_holder.hpp @@ -138,7 +138,7 @@ struct base_node # endif template - void destructor(Alloc &a) BOOST_NOEXCEPT + BOOST_CONTAINER_FORCEINLINE void destructor(Alloc &a) BOOST_NOEXCEPT { allocator_traits::destroy (a, &this->get_real_data()); @@ -203,13 +203,7 @@ struct node_alloc_holder //be of type node_compare<>. If not an associative container val_compare will be a "nat" type. typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT ( boost::container::dtl:: - , ICont, key_compare, dtl::nat) intrusive_val_compare; - //In that case obtain the value predicate from the node predicate via predicate_type - //if intrusive_val_compare is node_compare<>, nat otherwise - typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT - ( boost::container::dtl:: - , intrusive_val_compare - , predicate_type, dtl::nat) val_compare; + , ICont, key_compare, dtl::nat) intrusive_key_compare; //If the intrusive container is a hash container, obtain the predicate, which will //be of type node_compare<>. If not an associative container val_equal will be a "nat" type. @@ -226,7 +220,7 @@ struct node_alloc_holder (boost::container::dtl:: , ICont, bucket_type, dtl::natN<1>) intrusive_bucket_type; //In that case obtain the value predicate from the node predicate via predicate_type - //if intrusive_val_compare is node_compare<>, nat otherwise + //if intrusive_key_compare is node_compare<>, nat otherwise typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT (boost::container::dtl:: , intrusive_val_equal @@ -281,8 +275,8 @@ struct node_alloc_holder {} //Constructors for associative containers - node_alloc_holder(const val_compare &c, const ValAlloc &a) - : NodeAlloc(a), m_icont(typename ICont::key_compare(c)) + node_alloc_holder(const intrusive_key_compare &c, const ValAlloc &a) + : NodeAlloc(a), m_icont(c) {} node_alloc_holder(const intrusive_bucket_traits & bt, const val_hasher &hf, const val_equal &eql, const ValAlloc &a) @@ -309,9 +303,9 @@ struct node_alloc_holder : NodeAlloc(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc())) {} - node_alloc_holder(const node_alloc_holder &x, const val_compare &c) + node_alloc_holder(const node_alloc_holder &x, const intrusive_key_compare &c) : NodeAlloc(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc())) - , m_icont(typename ICont::key_compare(c)) + , m_icont(c) {} node_alloc_holder(const node_alloc_holder &x, const intrusive_bucket_traits& bt, const val_hasher &hf, const val_equal &eql) @@ -331,13 +325,13 @@ struct node_alloc_holder : NodeAlloc(boost::move(BOOST_MOVE_TO_LV(x).node_alloc())) { this->icont().swap(x.icont()); } - explicit node_alloc_holder(const val_compare &c) - : m_icont(typename ICont::key_compare(c)) + explicit node_alloc_holder(const intrusive_key_compare &c) + : m_icont(c) {} //helpers for move assignments - explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const val_compare &c) - : NodeAlloc(boost::move(BOOST_MOVE_TO_LV(x).node_alloc())), m_icont(typename ICont::key_compare(c)) + explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const intrusive_key_compare &c) + : NodeAlloc(boost::move(BOOST_MOVE_TO_LV(x).node_alloc())), m_icont(c) { this->icont().swap(x.icont()); } explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const intrusive_bucket_traits& bt, const val_hasher &hf, const val_equal &eql) @@ -531,28 +525,15 @@ struct node_alloc_holder return ret_it; } - template - BOOST_CONTAINER_FORCEINLINE size_type erase_key(const Key& k, const Comparator &comp, version_1) - { return this->icont().erase_and_dispose(k, comp, Destroyer(this->node_alloc())); } + template + BOOST_CONTAINER_FORCEINLINE size_type erase_key(const Key& k, version_1) + { return this->icont().erase_and_dispose(k, Destroyer(this->node_alloc())); } - template - BOOST_CONTAINER_FORCEINLINE size_type erase_key(const Key& k, const Comparator &comp, version_2) + template + BOOST_CONTAINER_FORCEINLINE size_type erase_key(const Key& k, version_2) { allocator_multialloc_chain_node_deallocator chain_holder(this->node_alloc()); - return this->icont().erase_and_dispose(k, comp, chain_holder.get_chain_builder()); - } - - template - BOOST_CONTAINER_FORCEINLINE size_type erase_key(const Key& k, const Equality& eq, const Hasher &h, version_1) - { - return this->icont().erase_and_dispose(k, eq, h, Destroyer(this->node_alloc())); - } - - template - size_type erase_key(const Key& k, const Equality& eq, const Hasher& h, version_2) - { - allocator_multialloc_chain_node_deallocator chain_holder(this->node_alloc()); - return this->icont().erase_and_dispose(k, eq, h, chain_holder.get_chain_builder()); + return this->icont().erase_and_dispose(k, chain_holder.get_chain_builder()); } protected: @@ -598,11 +579,24 @@ struct node_alloc_holder BOOST_CONTAINER_FORCEINLINE const ICont &icont() const { return this->m_icont; } - private: + protected: //The intrusive container ICont m_icont; }; +template +struct key_of_node : KeyOfValue +{ + typedef typename KeyOfValue::type type; + + BOOST_CONTAINER_FORCEINLINE key_of_node() + {} + + BOOST_CONTAINER_FORCEINLINE const type& operator()(const Node& x) const + { return this->KeyOfValue::operator()(x.get_data()); } +}; + + } //namespace dtl { } //namespace container { } //namespace boost { diff --git a/include/boost/container/options.hpp b/include/boost/container/options.hpp index 3a292df..4bdd33e 100644 --- a/include/boost/container/options.hpp +++ b/include/boost/container/options.hpp @@ -113,15 +113,16 @@ using tree_assoc_options_t = typename boost::container::tree_assoc_options +template struct hash_opt { static const bool store_hash = StoreHash; static const bool cache_begin = CacheBegin; static const bool linear_buckets = LinearBuckets; + static const bool fastmod_buckets = FastmodBuckets; }; -typedef hash_opt hash_assoc_defaults; +typedef hash_opt hash_assoc_defaults; #endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED) @@ -135,9 +136,10 @@ BOOST_INTRUSIVE_OPTION_CONSTANT(store_hash, bool, Enabled, store_hash) //!first non-empty bucket (which can be O(bucket_size())) BOOST_INTRUSIVE_OPTION_CONSTANT(cache_begin, bool, Enabled, cache_begin) - BOOST_INTRUSIVE_OPTION_CONSTANT(linear_buckets, bool, Enabled, linear_buckets) +BOOST_INTRUSIVE_OPTION_CONSTANT(fastmod_buckets, bool, Enabled, fastmod_buckets) + //! Helper metafunction to combine options into a single type to be used //! by \c boost::container::hash_set, \c boost::container::hash_multiset //! \c boost::container::hash_map and \c boost::container::hash_multimap. @@ -161,6 +163,7 @@ struct hash_assoc_options typedef hash_opt implementation_defined; /// @endcond typedef implementation_defined type;