From d4c68f3898dfd0a491af3417e53ea8421a478932 Mon Sep 17 00:00:00 2001 From: khizmax Date: Sun, 2 Aug 2015 22:50:42 +0300 Subject: [PATCH] intrusive MultiLevelHashSet fixes, tests Added MS VC++ linker flag --- .gitignore | 1 - cds/algo/split_bitstring.h | 138 ++++++++++++++++++ .../details/multilevel_hashset_base.h | 107 ++------------ cds/intrusive/impl/multilevel_hashset.h | 38 ++--- projects/Win/vc12/cds.vcxproj | 1 + projects/Win/vc12/cds.vcxproj.filters | 3 + projects/Win/vc12/hdr-test-deque.vcxproj | 6 + projects/Win/vc12/hdr-test-list.vcxproj | 6 + projects/Win/vc12/hdr-test-map.vcxproj | 6 + projects/Win/vc12/hdr-test-misc.vcxproj | 7 + .../Win/vc12/hdr-test-priority_queue.vcxproj | 6 + projects/Win/vc12/hdr-test-queue.vcxproj | 6 + projects/Win/vc12/hdr-test-set.vcxproj | 8 + .../Win/vc12/hdr-test-set.vcxproj.filters | 9 ++ projects/Win/vc12/hdr-test-stack.vcxproj | 6 + .../Win/vc12/hdr-test-striped-set.vcxproj | 6 + projects/Win/vc12/hdr-test-tree.vcxproj | 6 + projects/source.test-hdr.mk | 1 + .../set/hdr_intrusive_michael_set_hp.cpp | 3 +- .../set/hdr_intrusive_multilevel_hashset.h | 50 +++++++ .../hdr_intrusive_multilevel_hashset_hp.cpp | 33 +++++ 21 files changed, 333 insertions(+), 114 deletions(-) create mode 100644 cds/algo/split_bitstring.h create mode 100644 tests/test-hdr/set/hdr_intrusive_multilevel_hashset.h create mode 100644 tests/test-hdr/set/hdr_intrusive_multilevel_hashset_hp.cpp diff --git a/.gitignore b/.gitignore index 1b5d9a11..ef8a1bd4 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,6 @@ /tests/cppunit/*.o *.o *.d -/todo-2.0.txt /tests/data/dictionary.txt /bin obj diff --git a/cds/algo/split_bitstring.h b/cds/algo/split_bitstring.h new file mode 100644 index 00000000..51590e2f --- /dev/null +++ b/cds/algo/split_bitstring.h @@ -0,0 +1,138 @@ +//$$CDS-header$$ + +#ifndef CDSLIB_ALGO_SPLIT_BITSTRING_H +#define CDSLIB_ALGO_SPLIT_BITSTRING_H + +#include + +namespace cds { namespace algo { + + /// Cuts a bit sequence from fixed-size bit-string + /** + The splitter an be used as iterator over bit-string. + Each call of \p cut() or \p safe_cut() cuts the bit count specified + and keeps the position inside bit-string for the next call. + + The splitter stores a const reference to bit-string, not a copy. + The maximum count of bits that can be cut for single call is sizeof(UInt) * 8 + */ + template + class split_bitstring + { + public: + typedef BitString bitstring; ///< Bit-string type + typedef UInt uint_type; ///< Bit-string portion type + + //@cond + static CDS_CONSTEXPR size_t const c_nHashSize = (sizeof(bitstring) + sizeof(uint_type) - 1) / sizeof(uint_type); + static CDS_CONSTEXPR size_t const c_nBitPerByte = 8; + static CDS_CONSTEXPR size_t const c_nBitPerHash = sizeof(bitstring) * c_nBitPerByte; + static CDS_CONSTEXPR size_t const c_nBitPerInt = sizeof(uint_type) * c_nBitPerByte; + //@endcond + + public: + /// Initializises the splitter with reference to \p h + explicit split_bitstring( bitstring const& h ) + : m_ptr(reinterpret_cast( &h )) + , m_pos(0) + , m_first( m_ptr ) +# ifdef _DEBUG + , m_last( m_ptr + c_nHashSize ) +# endif + {} + + /// Returns \p true if end-of-string is not reached yet + explicit operator bool() const + { + return !eos(); + } + + /// Returns \p true if end-of-stream encountered + bool eos() const + { + return m_pos >= c_nBitPerHash; + } + + /// Cuts next \p nBits from bit-string + /** + Precondition: nBits <= sizeof(uint_type) * 8 + + This function does not manage out-of-bound condition. + To control that use \p safe_cut(). + */ + uint_type cut( size_t nBits ) + { + assert( !eos() ); + assert( nBits <= c_nBitPerInt ); + assert( m_pos + nBits <= c_nBitPerHash ); +# ifdef _DEBUG + assert( m_ptr < m_last ); +# endif + uint_type result; + + size_t const nRest = c_nBitPerInt - m_pos % c_nBitPerInt; + m_pos += nBits; + if ( nBits < nRest ) { + result = *m_ptr << ( nRest - nBits ); + result = result >> ( c_nBitPerInt - nBits ); + } + else if ( nBits == nRest ) { + result = *m_ptr >> ( c_nBitPerInt - nRest ); + ++m_ptr; + } + else { + size_t const lsb = *m_ptr >> ( c_nBitPerInt - nRest ); + nBits -= nRest; + ++m_ptr; + + result = *m_ptr << ( c_nBitPerInt - nBits ); + result = result >> ( c_nBitPerInt - nBits ); + result = (result << nRest) + lsb; + } + + assert( m_pos <= c_nBitPerHash ); +# ifdef _DEBUG + assert( m_ptr <= m_last ); +# endif + return result; + } + + /// Cuts up to \p nBits from the bit-string + /** + Analog of \p cut() but if \p nBits is more than the rest of bit-string, + only the rest is returned. + If \p eos() is \p true the function returns 0. + */ + uint_type safe_cut( size_t nBits ) + { + if ( eos() ) + return 0; + + assert( nBits <= sizeof(uint_type) * c_nBitPerByte ); + + if ( m_pos + nBits > c_nBitPerHash ) + nBits = c_nBitPerHash - m_pos; + return nBits ? cut( nBits ) : 0; + } + + /// Resets the splitter + void reset() + { + m_ptr = m_first; + m_pos = 0; + } + + private: + //@cond + uint_type const* m_ptr; ///< current position in the hash + size_t m_pos; ///< current position in bits + uint_type const* m_first; ///< first position +# ifdef _DEBUG + uint_type const* m_last; ///< last position +# endif + //@endcond + }; + +}} // namespace cds::algo + +#endif // #ifndef CDSLIB_ALGO_SPLIT_BITSTRING_H diff --git a/cds/intrusive/details/multilevel_hashset_base.h b/cds/intrusive/details/multilevel_hashset_base.h index 6bb87688..63d57bb4 100644 --- a/cds/intrusive/details/multilevel_hashset_base.h +++ b/cds/intrusive/details/multilevel_hashset_base.h @@ -5,9 +5,11 @@ #include // memcmp, memcpy #include + #include #include #include +#include #include #include @@ -83,6 +85,7 @@ namespace cds { namespace intrusive { event_counter m_nSlotChanged; ///< Number of array node slot changing by other thread during an operation event_counter m_nSlotConverting; ///< Number of events when we encounter a slot while it is converting to array node + //@cond void onInsertSuccess() { ++m_nInsertSuccess; } void onInserFailed() { ++m_nInsertFailed; } void onInsertRetry() { ++m_nInsertRetry; } @@ -93,13 +96,14 @@ namespace cds { namespace intrusive { void onEraseSuccess() { ++m_nEraseSuccess; } void onEraseFailed() { ++m_nEraseFailed; } void onEraseRetry() { ++m_nEraseRetry; } - void onFindSuccess() { ++m_nFinSuccess; } + void onFindSuccess() { ++m_nFindSuccess; } void onFindFailed() { ++m_nFindFailed; } void onExpandNodeSuccess() { ++m_nExpandNodeSuccess; } void onExpandNodeFailed() { ++m_nExpandNodeFailed; } void onSlotChanged() { ++m_nSlotChanged; } void onSlotConverting() { ++m_nSlotConverting; } + //@endcond }; /// \p MultiLevelHashSet empty internal statistics @@ -266,6 +270,13 @@ namespace cds { namespace intrusive { template struct bitwise_compare { + /// Compares \p lhs and \p rhs + /** + Returns: + - < 0 if lhs < rhs + - 0 if lhs == rhs + - > 0 if lhs > rhs + */ int operator()( T const& lhs, T const& rhs ) const { return memcmp( &lhs, &rhs, sizeof(T)); @@ -275,99 +286,7 @@ namespace cds { namespace intrusive { //@cond namespace details { template - class hash_splitter - { - public: - typedef HashType hash_type; - typedef UInt uint_type; - - static CDS_CONSTEXPR size_t const c_nHashSize = (sizeof(hash_type) + sizeof(uint_type) - 1) / sizeof(uint_type); - static CDS_CONSTEXPR size_t const c_nBitPerByte = 8; - static CDS_CONSTEXPR size_t const c_nBitPerHash = sizeof(hash_type) * c_nBitPerByte; - static CDS_CONSTEXPR size_t const c_nBitPerInt = sizeof(uint_type) * c_nBitPerByte; - - public: - explicit hash_splitter( hash_type const& h ) - : m_ptr(reinterpret_cast( &h )) - , m_pos(0) - , m_first( m_ptr ) -# ifdef _DEBUG - , m_last( m_ptr + c_nHashSize ) -# endif - {} - - explicit operator bool() const - { - return !eos(); - } - - // end-of-bitstring - bool eos() const - { - return m_pos >= c_nBitPerHash; - } - - uint_type cut( size_t nBits ) - { - assert( !eos() ); - assert( nBits <= c_nBitPerInt ); - assert( m_pos + nBits <= c_nBitPerHash ); -# ifdef _DEBUG - assert( m_ptr < m_last ); -# endif - uint_type result; - - size_t const nRest = c_nBitPerInt - m_pos % c_nBitPerInt; - m_pos += nBits; - if ( nBits < nRest ) { - result = *m_ptr << ( nRest - nBits ); - result = result >> ( c_nBitPerInt - nBits ); - } - else if ( nBits == nRest ) { - result = *m_ptr >> ( c_nBitPerInt - nRest ); - ++m_ptr; - } - else { - size_t const lsb = *m_ptr >> ( c_nBitPerInt - nRest ); - nBits -= nRest; - ++m_ptr; - - result = *m_ptr << ( c_nBitPerInt - nBits ); - result = result >> ( c_nBitPerInt - nBits ); - result = (result << nRest) + lsb; - } - - assert( m_pos <= c_nBitPerHash ); -# ifdef _DEBUG - assert( m_ptr < m_last ); -# endif - return result; - } - - uint_type safe_cut( size_t nBits ) - { - assert( !eos() ); - assert( nBits <= sizeof(uint_type) * c_nBitPerByte ); - - if ( m_pos + nBits > c_nBitPerHash ) - nBits = c_nBitPerHash - m_pos; - return nBits ? cut( nBits ) : 0; - } - - void reset() - { - m_ptr = m_first; - m_pos = 0; - } - - private: - uint_type const* m_ptr; ///< current position in the hash - size_t m_pos; ///< current position in bits - uint_type const* m_first; ///< first position -# ifdef _DEBUG - uint_type const* m_last; ///< last position -# endif - }; + using hash_splitter = cds::algo::split_bitstring< HashType, UInt >; } // namespace details //@endcond diff --git a/cds/intrusive/impl/multilevel_hashset.h b/cds/intrusive/impl/multilevel_hashset.h index f0516ef0..9f0db90a 100644 --- a/cds/intrusive/impl/multilevel_hashset.h +++ b/cds/intrusive/impl/multilevel_hashset.h @@ -65,11 +65,14 @@ namespace cds { namespace intrusive { have identical hash then you cannot insert both that keys in the set. \p %MultiLevelHashSet does not maintain the key, it maintains its fixed-size hash value. + Template parameters: + - \p GC - safe memory reclamation schema. Can be \p gc::HP, \p gc::DHP or one of \ref cds_urcu_type "RCU type" + - \p T - a value type to be stored in the set + - \p Traits - type traits, the structure based on \p multilevel_hashset::traits or result of \p multilevel_hashset::make_traits metafunction There are several specializations of \p %MultiLevelHashSet for each \p GC. You should include: - for \p gc::HP garbage collector - for \p gc::DHP garbage collector - - for \ref cds_intrusive_MultiLevelHashSet_nogc for append-only set - for \ref cds_intrusive_MultiLevelHashSet_rcu "RCU type" */ template < @@ -97,7 +100,7 @@ namespace cds { namespace intrusive { decltype( hash_accessor()( std::declval()) ) >::type >::type hash_type; - static_assert( !std::is_pointer, "hash_accessor should return a reference to hash value" ); + static_assert( !std::is_pointer::value, "hash_accessor should return a reference to hash value" ); typedef typename traits::disposer disposer; ///< data node disposer @@ -218,7 +221,7 @@ namespace cds { namespace intrusive { hash_type const& hash = hash_accessor()( val ); hash_splitter splitter( hash ); hash_comparator cmp; - gc::Guard guard; + typename gc::Guard guard; back_off bkoff; atomic_node_ptr * pArr = m_Head; @@ -267,7 +270,7 @@ namespace cds { namespace intrusive { else { // the slot is empty, try to insert data node node_ptr pNull; - if ( pArr[nSlot].compare_exchange_strong( pNull, node_ptr( &val ), memory_model::memory_order_release, atomics::memory_order_relaxed ) + if ( pArr[nSlot].compare_exchange_strong( pNull, node_ptr( &val ), memory_model::memory_order_release, atomics::memory_order_relaxed )) { // the new data node has been inserted f( val ); @@ -305,7 +308,7 @@ namespace cds { namespace intrusive { hash_type const& hash = hash_accessor()( val ); hash_splitter splitter( hash ); hash_comparator cmp; - gc::Guard guard; + typename gc::Guard guard; back_off bkoff; atomic_node_ptr * pArr = m_Head; @@ -363,7 +366,7 @@ namespace cds { namespace intrusive { // the slot is empty, try to insert data node if ( bInsert ) { node_ptr pNull; - if ( pArr[nSlot].compare_exchange_strong( pNull, node_ptr( &val ), memory_model::memory_order_release, atomics::memory_order_relaxed ) + if ( pArr[nSlot].compare_exchange_strong( pNull, node_ptr( &val ), memory_model::memory_order_release, atomics::memory_order_relaxed )) { // the new data node has been inserted f( val ); @@ -374,7 +377,7 @@ namespace cds { namespace intrusive { } else { m_Stat.onUpdateFailed(); - return std:make_pair( false, false ); + return std::make_pair( false, false ); } // insert failed - slot has been changed by another thread @@ -396,7 +399,7 @@ namespace cds { namespace intrusive { { typename gc::Guard guard; auto pred = [&val](value_type const& item) -> bool { return &item == &val; }; - value_type * p = do_erase( hash, guard, std::ref( pred )); + value_type * p = do_erase( hash_accessor()( val ), guard, std::ref( pred )); // p is guarded by HP if ( p ) { @@ -637,21 +640,21 @@ namespace cds { namespace intrusive { metrics m; m.head_node_size_log = head_bits; - m.head_node_size = 1 << head_bits; + m.head_node_size = size_t(1) << head_bits; m.array_node_size_log = array_bits; - m.array_node_size = 1 << array_bits; + m.array_node_size = size_t(1) << array_bits; return m; } - template - static bool check_node_alignment( T * p ) + template + static bool check_node_alignment( Q const* p ) { return (reinterpret_cast(p) & node_ptr::bitmask) == 0; } atomic_node_ptr * alloc_array_node() const { - return cxx_array_node_allocator().NewArray( array_node_size(), nullptr ) + return cxx_array_node_allocator().NewArray( array_node_size(), nullptr ); } void free_array_node( atomic_node_ptr * parr ) const @@ -709,8 +712,8 @@ namespace cds { namespace intrusive { } else { // data node - if ( pArr->compare_exchange_strong( slot, node_ptr(), memory_model::memory_order_acquire, atomics::memory_order_relaxed ) ) { - gc::template retire( p ); + if ( pArr->compare_exchange_strong( slot, node_ptr(), memory_model::memory_order_acquire, atomics::memory_order_relaxed )) { + gc::template retire( slot.ptr() ); --m_ItemCounter; m_Stat.onEraseSuccess(); break; @@ -755,7 +758,9 @@ namespace cds { namespace intrusive { pArr[idx].store( current, memory_model::memory_order_release ); cur = cur | array_converting; - CDS_VERIFY( slot.compare_exchange_strong( cur, node_ptr( to_node( pArr ), array_node ), memory_model::memory_order_release, atomics::memory_order_relaxed ))); + CDS_VERIFY( + slot.compare_exchange_strong( cur, node_ptr( to_node( pArr ), array_node ), memory_model::memory_order_release, atomics::memory_order_relaxed ) + ); return std::make_pair( pArr, idx ); } @@ -863,4 +868,3 @@ namespace cds { namespace intrusive { }} // namespace cds::intrusive #endif // #ifndef CDSLIB_INTRUSIVE_IMPL_MULTILEVEL_HASHSET_H -1 \ No newline at end of file diff --git a/projects/Win/vc12/cds.vcxproj b/projects/Win/vc12/cds.vcxproj index bb711f02..1a24a6b6 100644 --- a/projects/Win/vc12/cds.vcxproj +++ b/projects/Win/vc12/cds.vcxproj @@ -635,6 +635,7 @@ + diff --git a/projects/Win/vc12/cds.vcxproj.filters b/projects/Win/vc12/cds.vcxproj.filters index 2548ad54..1e2b3db7 100644 --- a/projects/Win/vc12/cds.vcxproj.filters +++ b/projects/Win/vc12/cds.vcxproj.filters @@ -1196,5 +1196,8 @@ Header Files\cds\intrusive + + Header Files\cds\algo + \ No newline at end of file diff --git a/projects/Win/vc12/hdr-test-deque.vcxproj b/projects/Win/vc12/hdr-test-deque.vcxproj index 1193a1eb..0a00c9c4 100644 --- a/projects/Win/vc12/hdr-test-deque.vcxproj +++ b/projects/Win/vc12/hdr-test-deque.vcxproj @@ -233,6 +233,7 @@ MachineX86 + MultiplyDefinedSymbolOnly @@ -294,6 +295,7 @@ MachineX64 + MultiplyDefinedSymbolOnly @@ -362,6 +364,7 @@ MachineX86 true + MultiplyDefinedSymbolOnly @@ -439,6 +442,7 @@ MachineX64 true + MultiplyDefinedSymbolOnly @@ -510,6 +514,7 @@ MachineX86 + MultiplyDefinedSymbolOnly @@ -542,6 +547,7 @@ MachineX64 + MultiplyDefinedSymbolOnly diff --git a/projects/Win/vc12/hdr-test-list.vcxproj b/projects/Win/vc12/hdr-test-list.vcxproj index 20990826..59ea903f 100644 --- a/projects/Win/vc12/hdr-test-list.vcxproj +++ b/projects/Win/vc12/hdr-test-list.vcxproj @@ -294,6 +294,7 @@ MachineX86 + MultiplyDefinedSymbolOnly @@ -353,6 +354,7 @@ MachineX64 + MultiplyDefinedSymbolOnly @@ -420,6 +422,7 @@ MachineX86 true + MultiplyDefinedSymbolOnly @@ -495,6 +498,7 @@ MachineX64 true + MultiplyDefinedSymbolOnly @@ -563,6 +567,7 @@ MachineX86 + MultiplyDefinedSymbolOnly @@ -594,6 +599,7 @@ MachineX64 + MultiplyDefinedSymbolOnly diff --git a/projects/Win/vc12/hdr-test-map.vcxproj b/projects/Win/vc12/hdr-test-map.vcxproj index 1956ce57..9b26328d 100644 --- a/projects/Win/vc12/hdr-test-map.vcxproj +++ b/projects/Win/vc12/hdr-test-map.vcxproj @@ -232,6 +232,7 @@ MachineX86 + MultiplyDefinedSymbolOnly @@ -291,6 +292,7 @@ MachineX64 + MultiplyDefinedSymbolOnly @@ -358,6 +360,7 @@ MachineX86 true + MultiplyDefinedSymbolOnly @@ -433,6 +436,7 @@ MachineX64 true + MultiplyDefinedSymbolOnly @@ -501,6 +505,7 @@ MachineX86 + MultiplyDefinedSymbolOnly @@ -532,6 +537,7 @@ MachineX64 + MultiplyDefinedSymbolOnly diff --git a/projects/Win/vc12/hdr-test-misc.vcxproj b/projects/Win/vc12/hdr-test-misc.vcxproj index bb5e6142..0abdd391 100644 --- a/projects/Win/vc12/hdr-test-misc.vcxproj +++ b/projects/Win/vc12/hdr-test-misc.vcxproj @@ -232,6 +232,7 @@ MachineX86 + MultiplyDefinedSymbolOnly @@ -291,6 +292,7 @@ MachineX64 + MultiplyDefinedSymbolOnly @@ -358,6 +360,7 @@ MachineX86 true + MultiplyDefinedSymbolOnly @@ -433,6 +436,7 @@ MachineX64 true + MultiplyDefinedSymbolOnly @@ -501,6 +505,7 @@ MachineX86 + MultiplyDefinedSymbolOnly @@ -532,6 +537,7 @@ MachineX64 + MultiplyDefinedSymbolOnly @@ -542,6 +548,7 @@ + diff --git a/projects/Win/vc12/hdr-test-priority_queue.vcxproj b/projects/Win/vc12/hdr-test-priority_queue.vcxproj index 325b0cfe..4ab19ad1 100644 --- a/projects/Win/vc12/hdr-test-priority_queue.vcxproj +++ b/projects/Win/vc12/hdr-test-priority_queue.vcxproj @@ -246,6 +246,7 @@ MachineX86 + MultiplyDefinedSymbolOnly @@ -305,6 +306,7 @@ MachineX64 + MultiplyDefinedSymbolOnly @@ -372,6 +374,7 @@ MachineX86 true + MultiplyDefinedSymbolOnly @@ -447,6 +450,7 @@ MachineX64 true + MultiplyDefinedSymbolOnly @@ -515,6 +519,7 @@ MachineX86 + MultiplyDefinedSymbolOnly @@ -546,6 +551,7 @@ MachineX64 + MultiplyDefinedSymbolOnly diff --git a/projects/Win/vc12/hdr-test-queue.vcxproj b/projects/Win/vc12/hdr-test-queue.vcxproj index 5a7920e3..c72ace29 100644 --- a/projects/Win/vc12/hdr-test-queue.vcxproj +++ b/projects/Win/vc12/hdr-test-queue.vcxproj @@ -232,6 +232,7 @@ MachineX86 + MultiplyDefinedSymbolOnly @@ -291,6 +292,7 @@ MachineX64 + MultiplyDefinedSymbolOnly @@ -358,6 +360,7 @@ MachineX86 true + MultiplyDefinedSymbolOnly @@ -433,6 +436,7 @@ MachineX64 true + MultiplyDefinedSymbolOnly @@ -501,6 +505,7 @@ MachineX86 + MultiplyDefinedSymbolOnly @@ -532,6 +537,7 @@ MachineX64 + MultiplyDefinedSymbolOnly diff --git a/projects/Win/vc12/hdr-test-set.vcxproj b/projects/Win/vc12/hdr-test-set.vcxproj index 3eab4e97..afbd90e8 100644 --- a/projects/Win/vc12/hdr-test-set.vcxproj +++ b/projects/Win/vc12/hdr-test-set.vcxproj @@ -232,6 +232,7 @@ MachineX86 + MultiplyDefinedSymbolOnly @@ -291,6 +292,7 @@ MachineX64 + MultiplyDefinedSymbolOnly @@ -358,6 +360,7 @@ MachineX86 true + MultiplyDefinedSymbolOnly @@ -433,6 +436,7 @@ MachineX64 true + MultiplyDefinedSymbolOnly @@ -501,6 +505,7 @@ MachineX86 + MultiplyDefinedSymbolOnly @@ -532,9 +537,11 @@ MachineX64 + MultiplyDefinedSymbolOnly + @@ -559,6 +566,7 @@ + diff --git a/projects/Win/vc12/hdr-test-set.vcxproj.filters b/projects/Win/vc12/hdr-test-set.vcxproj.filters index e579d1ac..24772ff9 100644 --- a/projects/Win/vc12/hdr-test-set.vcxproj.filters +++ b/projects/Win/vc12/hdr-test-set.vcxproj.filters @@ -19,6 +19,9 @@ container\skip_list + + intrusive\multilevel_hashset + @@ -45,6 +48,9 @@ {61f94a40-c964-4233-af67-66a1be1e0aab} + + {a878aed0-83c9-4ca7-95bb-74f10aad8bde} + @@ -311,5 +317,8 @@ container\skip_list + + intrusive\multilevel_hashset + \ No newline at end of file diff --git a/projects/Win/vc12/hdr-test-stack.vcxproj b/projects/Win/vc12/hdr-test-stack.vcxproj index 28f258c1..77ca8cb5 100644 --- a/projects/Win/vc12/hdr-test-stack.vcxproj +++ b/projects/Win/vc12/hdr-test-stack.vcxproj @@ -232,6 +232,7 @@ MachineX86 + MultiplyDefinedSymbolOnly @@ -291,6 +292,7 @@ MachineX64 + MultiplyDefinedSymbolOnly @@ -358,6 +360,7 @@ MachineX86 true + MultiplyDefinedSymbolOnly @@ -433,6 +436,7 @@ MachineX64 true + MultiplyDefinedSymbolOnly @@ -501,6 +505,7 @@ MachineX86 + MultiplyDefinedSymbolOnly @@ -532,6 +537,7 @@ MachineX64 + MultiplyDefinedSymbolOnly diff --git a/projects/Win/vc12/hdr-test-striped-set.vcxproj b/projects/Win/vc12/hdr-test-striped-set.vcxproj index d62e3008..b7ee1625 100644 --- a/projects/Win/vc12/hdr-test-striped-set.vcxproj +++ b/projects/Win/vc12/hdr-test-striped-set.vcxproj @@ -283,6 +283,7 @@ MachineX86 + MultiplyDefinedSymbolOnly @@ -342,6 +343,7 @@ MachineX64 + MultiplyDefinedSymbolOnly @@ -409,6 +411,7 @@ MachineX86 true + MultiplyDefinedSymbolOnly @@ -484,6 +487,7 @@ MachineX64 true + MultiplyDefinedSymbolOnly @@ -552,6 +556,7 @@ MachineX86 + MultiplyDefinedSymbolOnly @@ -583,6 +588,7 @@ MachineX64 + MultiplyDefinedSymbolOnly diff --git a/projects/Win/vc12/hdr-test-tree.vcxproj b/projects/Win/vc12/hdr-test-tree.vcxproj index a6d325d3..be40b2c7 100644 --- a/projects/Win/vc12/hdr-test-tree.vcxproj +++ b/projects/Win/vc12/hdr-test-tree.vcxproj @@ -232,6 +232,7 @@ MachineX86 + MultiplyDefinedSymbolOnly @@ -291,6 +292,7 @@ MachineX64 + MultiplyDefinedSymbolOnly @@ -358,6 +360,7 @@ MachineX86 true + MultiplyDefinedSymbolOnly @@ -433,6 +436,7 @@ MachineX64 true + MultiplyDefinedSymbolOnly @@ -501,6 +505,7 @@ MachineX86 + MultiplyDefinedSymbolOnly @@ -532,6 +537,7 @@ MachineX64 + MultiplyDefinedSymbolOnly diff --git a/projects/source.test-hdr.mk b/projects/source.test-hdr.mk index 0f27e11f..f352589b 100644 --- a/projects/source.test-hdr.mk +++ b/projects/source.test-hdr.mk @@ -129,6 +129,7 @@ CDS_TESTHDR_QUEUE := \ tests/test-hdr/queue/hdr_vyukov_mpmc_cyclic.cpp CDS_TESTHDR_SET := \ + tests/test-hdr/set/hdr_intrusive_multilevel_hashset_hp.cpp \ tests/test-hdr/set/hdr_intrusive_refinable_hashset_avlset.cpp \ tests/test-hdr/set/hdr_intrusive_refinable_hashset_list.cpp \ tests/test-hdr/set/hdr_intrusive_refinable_hashset_set.cpp \ diff --git a/tests/test-hdr/set/hdr_intrusive_michael_set_hp.cpp b/tests/test-hdr/set/hdr_intrusive_michael_set_hp.cpp index 2753b2de..1500a030 100644 --- a/tests/test-hdr/set/hdr_intrusive_michael_set_hp.cpp +++ b/tests/test-hdr/set/hdr_intrusive_michael_set_hp.cpp @@ -144,7 +144,6 @@ namespace set { test_int(); } - - } // namespace set + CPPUNIT_TEST_SUITE_REGISTRATION(set::IntrusiveHashSetHdrTest); diff --git a/tests/test-hdr/set/hdr_intrusive_multilevel_hashset.h b/tests/test-hdr/set/hdr_intrusive_multilevel_hashset.h new file mode 100644 index 00000000..8eb17e37 --- /dev/null +++ b/tests/test-hdr/set/hdr_intrusive_multilevel_hashset.h @@ -0,0 +1,50 @@ +//$$CDS-header$$ + +#ifndef CDSTEST_HDR_INTRUSIVE_MULTILEVEL_HASHSET_H +#define CDSTEST_HDR_INTRUSIVE_MULTILEVEL_HASHSET_H + +#include "cppunit/cppunit_proxy.h" + +// forward declaration +namespace cds { + namespace intrusive {} + namespace opt {} +} + +namespace set { + namespace ci = cds::intrusive; + namespace co = cds::opt; + + class IntrusiveMultiLevelHashSetHdrTest: public CppUnitMini::TestCase + { + template + struct Item + { + unsigned int nDisposeCount ; // count of disposer calling + Hash hash; + }; + + template + struct get_hash + { + Hash const& operator()( Item const& i ) const + { + return i.hash; + } + }; + + template + void test_hp() + { + Set s; + } + + void hp_stdhash(); + + CPPUNIT_TEST_SUITE(IntrusiveMultiLevelHashSetHdrTest) + CPPUNIT_TEST(hp_stdhash) + CPPUNIT_TEST_SUITE_END() + }; +} // namespace set + +#endif // #ifndef CDSTEST_HDR_INTRUSIVE_MULTILEVEL_HASHSET_H diff --git a/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_hp.cpp b/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_hp.cpp new file mode 100644 index 00000000..fb80ee16 --- /dev/null +++ b/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_hp.cpp @@ -0,0 +1,33 @@ +//$$CDS-header$$ + +#include "set/hdr_intrusive_multilevel_hashset.h" +#include + +namespace set { + namespace { + typedef cds::gc::HP gc_type; + } // namespace + + void IntrusiveMultiLevelHashSetHdrTest::hp_stdhash() + { + typedef size_t hash_type; + + struct traits: public ci::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + }; + typedef ci::MultiLevelHashSet< gc_type, Item, traits > set_type; + test_hp(); + + typedef ci::MultiLevelHashSet< + gc_type, + Item, + typename ci::multilevel_hashset::make_traits< + ci::multilevel_hashset::hash_accessor< get_hash> + >::type + > set_type2; + test_hp(); + } +} // namespace set + +CPPUNIT_TEST_SUITE_REGISTRATION(set::IntrusiveMultiLevelHashSetHdrTest); -- 2.34.1