Fixed minor compiler warning
[libcds.git] / cds / intrusive / details / feldman_hashset_base.h
index 00707e068a2d5b7a370b4473aaaa4367d05d4e0f..691e2af3b4af4fc9f82a20fd9ea27f35f2c223d0 100644 (file)
@@ -77,6 +77,21 @@ namespace cds { namespace intrusive {
             //@endcond
         };
 
+        /// Hash splitter option
+        /**
+            @copydetails traits::hash_splitter
+        */
+        template <typename Splitter>
+        struct hash_splitter {
+            //@cond
+            template <typename Base> struct pack: public Base
+            {
+                typedef Splitter hash_splitter;
+            };
+            //@endcond
+        };
+
+
         /// \p FeldmanHashSet internal statistics
         template <typename EventCounter = cds::atomicity::event_counter>
         struct stat {
@@ -197,6 +212,14 @@ namespace cds { namespace intrusive {
             */
             static CDS_CONSTEXPR size_t const hash_size = 0;
 
+            /// Hash splitter
+            /**
+                This trait specifies hash bit-string splitter algorithm.
+                By default, \p cds::algo::number_splitter is used if \p HashType is a number,
+                \p cds::algo::split_bitstring otherwise.
+            */
+            typedef cds::opt::none hash_splitter;
+
             /// Disposer for removing data nodes
             typedef cds::intrusive::opt::v::empty_disposer disposer;
 
@@ -262,6 +285,8 @@ namespace cds { namespace intrusive {
                 @copydetails traits::hash_accessor
             - \p feldman_hashset::hash_size - the size of hash value in bytes.
                 @copydetails traits::hash_size
+            - \p feldman_hashset::hash_splitter - a hash splitter algorithm
+                @copydetails traits::hash_splitter
             - \p opt::node_allocator - array node allocator.
                 @copydetails traits::node_allocator
             - \p opt::compare - hash comparison functor. No default functor is provided.
@@ -404,7 +429,11 @@ namespace cds { namespace intrusive {
             /// The size of hash_type in bytes, see \p traits::hash_size for explanation
             static CDS_CONSTEXPR size_t const c_hash_size = traits::hash_size == 0 ? sizeof( hash_type ) : static_cast<size_t>( traits::hash_size );
 
-            typedef feldman_hashset::details::hash_splitter< hash_type, c_hash_size > hash_splitter;
+            typedef typename std::conditional<
+                std::is_same< typename traits::hash_splitter, cds::opt::none >::value,
+                typename cds::algo::select_splitter< hash_type, c_hash_size >::type,
+                typename traits::hash_splitter
+            >::type hash_splitter;
 
             enum node_flags {
                 flag_array_converting = 1,   ///< the cell is converting from data node to an array node
@@ -436,7 +465,7 @@ namespace cds { namespace intrusive {
             struct traverse_data {
                 hash_splitter splitter;
                 array_node * pArr;
-                size_t nSlot;
+                typename hash_splitter::uint_type nSlot;
                 size_t nHeight;
 
                 traverse_data( hash_type const& hash, multilevel_array& arr )
@@ -449,7 +478,8 @@ namespace cds { namespace intrusive {
                 {
                     splitter.reset();
                     pArr = arr.head();
-                    nSlot = splitter.cut( arr.metrics().head_node_size_log );
+                    nSlot = splitter.cut( static_cast<unsigned>( arr.metrics().head_node_size_log ));
+                    assert( static_cast<size_t>( nSlot ) < arr.metrics().head_node_size );
                     nHeight = 1;
                 }
             };
@@ -463,7 +493,10 @@ namespace cds { namespace intrusive {
             multilevel_array(size_t head_bits, size_t array_bits )
                 : m_Metrics(feldman_hashset::details::metrics::make( head_bits, array_bits, c_hash_size ))
                 , m_Head( alloc_head_node())
-            {}
+            {
+                assert( hash_splitter::is_correct( static_cast<unsigned>( metrics().head_node_size_log )));
+                assert( hash_splitter::is_correct( static_cast<unsigned>( metrics().array_node_size_log )));
+            }
 
             ~multilevel_array()
             {
@@ -476,11 +509,11 @@ namespace cds { namespace intrusive {
                 back_off bkoff;
                 while (true) {
                     node_ptr slot = pos.pArr->nodes[pos.nSlot].load(memory_model::memory_order_acquire);
-                    if (slot.bits() == flag_array_node) {
+                    if ( slot.bits() == flag_array_node ) {
                         // array node, go down the tree
                         assert(slot.ptr() != nullptr);
                         assert( !pos.splitter.eos());
-                        pos.nSlot = pos.splitter.cut( metrics().array_node_size_log );
+                        pos.nSlot = pos.splitter.cut( static_cast<unsigned>( metrics().array_node_size_log ));
                         assert( pos.nSlot < metrics().array_node_size );
                         pos.pArr = to_array(slot.ptr());
                         ++pos.nHeight;
@@ -566,9 +599,9 @@ namespace cds { namespace intrusive {
                 return alloc_array_node(array_node_size(), pParent, idxParent);
             }
 
-            static void free_array_node( array_node * parr, size_t nSize )
+            static void free_array_node( array_node * parr, size_t /*nSize*/ )
             {
-                cxx_array_node_allocator().Delete( parr, nSize );
+                cxx_array_node_allocator().Delete( parr, 1 );
             }
 
             union converter {
@@ -617,6 +650,7 @@ namespace cds { namespace intrusive {
 
             bool expand_slot( traverse_data& pos, node_ptr current)
             {
+                assert( !pos.splitter.eos() );
                 return expand_slot( pos.pArr, pos.nSlot, current, pos.splitter.bit_offset());
             }
 
@@ -637,7 +671,8 @@ namespace cds { namespace intrusive {
                     return false;
                 }
 
-                size_t idx = hash_splitter( hash_accessor()(*current.ptr()), nOffset ).cut( m_Metrics.array_node_size_log );
+                typename hash_splitter::uint_type idx = hash_splitter( hash_accessor()(*current.ptr()), nOffset ).cut( 
+                    static_cast<unsigned>( m_Metrics.array_node_size_log ));
                 pArr->nodes[idx].store(current, memory_model::memory_order_release);
 
                 cur = cur | flag_array_converting;