//@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 {
*/
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;
@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.
/// 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
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 )
{
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;
}
};
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()
{
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;
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 {
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());
}
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;