+
+ void inc_item_count()
+ {
+ size_t nMaxCount = m_nMaxItemCount.load( memory_model::memory_order_relaxed );
+ if ( ++m_ItemCounter <= nMaxCount )
+ return;
+
+ size_t sz = m_nBucketCountLog2.load( memory_model::memory_order_relaxed );
+ const size_t nBucketCount = static_cast<size_t>(1) << sz;
+ if ( nBucketCount < m_Buckets.capacity()) {
+ // we may grow the bucket table
+ const size_t nLoadFactor = m_Buckets.load_factor();
+ if ( nMaxCount < max_item_count( nBucketCount, nLoadFactor ))
+ return; // someone already have updated m_nBucketCountLog2, so stop here
+
+ m_nMaxItemCount.compare_exchange_strong( nMaxCount, max_item_count( nBucketCount << 1, nLoadFactor ),
+ memory_model::memory_order_relaxed, atomics::memory_order_relaxed );
+ m_nBucketCountLog2.compare_exchange_strong( sz, sz + 1, memory_model::memory_order_relaxed, atomics::memory_order_relaxed );
+ }
+ else
+ m_nMaxItemCount.store( std::numeric_limits<size_t>::max(), memory_model::memory_order_relaxed );
+ }
+
+ template <typename Q, typename Compare, typename Func>
+ bool find_( Q& val, Compare cmp, Func f )
+ {
+ size_t nHash = hash_value( val );
+ split_list::details::search_value_type<Q> sv( val, split_list::regular_hash<bit_reversal>( nHash ));
+ aux_node_type * pHead = get_bucket( nHash );
+ assert( pHead != nullptr );
+
+ return m_Stat.onFind(
+ m_List.find_at( pHead, sv, cmp,
+ [&f]( value_type& item, split_list::details::search_value_type<Q>& val ) { f( item, val.val ); } )
+ );
+ }
+
+ template <typename Q, typename Compare>
+ bool find_( Q const& val, Compare cmp )
+ {
+ size_t nHash = hash_value( val );
+ split_list::details::search_value_type<Q const> sv( val, split_list::regular_hash<bit_reversal>( nHash ));
+ aux_node_type * pHead = get_bucket( nHash );
+ assert( pHead != nullptr );
+
+ return m_Stat.onFind( m_List.find_at( pHead, sv, cmp ));
+ }
+
+ template <typename Q, typename Compare>
+ iterator find_iterator_( Q const& val, Compare cmp )
+ {
+ size_t nHash = hash_value( val );
+ split_list::details::search_value_type<Q const> sv( val, split_list::regular_hash<bit_reversal>( nHash ));
+ aux_node_type * pHead = get_bucket( nHash );
+ assert( pHead != nullptr );
+
+ return iterator( m_List.find_iterator_at( pHead, sv, cmp ), m_List.end());
+ }
+
+ template <typename Q, typename Compare>
+ guarded_ptr get_( Q const& val, Compare cmp )
+ {
+ size_t nHash = hash_value( val );
+ split_list::details::search_value_type<Q const> sv( val, split_list::regular_hash<bit_reversal>( nHash ));
+ aux_node_type * pHead = get_bucket( nHash );
+ assert( pHead != nullptr );
+
+ guarded_ptr gp = m_List.get_at( pHead, sv, cmp );
+ m_Stat.onFind( !gp.empty());
+ return gp;
+ }
+
+ template <typename Q>
+ guarded_ptr get_( Q const& key )
+ {
+ return get_( key, key_comparator());
+ }
+
+ template <typename Q, typename Less>
+ guarded_ptr get_with_( Q const& key, Less )
+ {
+ return get_( key, typename ordered_list_adapter::template make_compare_from_less<Less>());
+ }
+
+ template <typename Q, typename Compare, typename Func>
+ bool erase_( Q const& val, Compare cmp, Func f )
+ {
+ size_t nHash = hash_value( val );
+ split_list::details::search_value_type<Q const> sv( val, split_list::regular_hash<bit_reversal>( nHash ));
+ aux_node_type * pHead = get_bucket( nHash );
+ assert( pHead != nullptr );
+
+ if ( m_List.erase_at( pHead, sv, cmp, f )) {
+ --m_ItemCounter;
+ m_Stat.onEraseSuccess();
+ return true;
+ }
+ m_Stat.onEraseFailed();
+ return false;
+ }
+
+ template <typename Q, typename Compare>
+ bool erase_( Q const& val, Compare cmp )