From b092e1849d74e72cd43a14f70032f7251d38f094 Mon Sep 17 00:00:00 2001 From: khizmax Date: Thu, 13 Aug 2015 23:50:37 +0300 Subject: [PATCH] Improving intrusive MultiLevelHashSet: - added erase_at() function - unified guarded_ptr interface for gc::HP and gc::DHP - added gc::DHP tests - fixed gc::DHP::forced_scan() unlimited memory consumption when no free retired ptr is found --- cds/gc/impl/dhp_decl.h | 8 + .../details/multilevel_hashset_base.h | 12 +- cds/intrusive/impl/multilevel_hashset.h | 38 ++- projects/Win/vc12/hdr-test-set.vcxproj | 1 + .../Win/vc12/hdr-test-set.vcxproj.filters | 3 + .../Win/vc12/hdr-test-striped-set.vcxproj | 1 + .../vc12/hdr-test-striped-set.vcxproj.filters | 1 + projects/source.test-hdr.mk | 1 + src/dhp_gc.cpp | 4 +- tests/test-hdr/CMakeLists.txt | 3 + .../set/hdr_intrusive_multilevel_hashset.h | 83 +++++++ .../hdr_intrusive_multilevel_hashset_dhp.cpp | 224 ++++++++++++++++++ .../hdr_intrusive_multilevel_hashset_hp.cpp | 110 +++++++++ 13 files changed, 480 insertions(+), 9 deletions(-) create mode 100644 tests/test-hdr/set/hdr_intrusive_multilevel_hashset_dhp.cpp diff --git a/cds/gc/impl/dhp_decl.h b/cds/gc/impl/dhp_decl.h index b0bde8f0..94ee0ad1 100644 --- a/cds/gc/impl/dhp_decl.h +++ b/cds/gc/impl/dhp_decl.h @@ -542,6 +542,14 @@ namespace cds { namespace gc { assert( m_guard.is_initialized() ); return m_guard; } + + void reset(guarded_type * p) CDS_NOEXCEPT + { + alloc_guard(); + assert( m_guard.is_initialized() ); + m_guard.set(p); + } + //@endcond private: diff --git a/cds/intrusive/details/multilevel_hashset_base.h b/cds/intrusive/details/multilevel_hashset_base.h index ba0f58c9..3988ac15 100644 --- a/cds/intrusive/details/multilevel_hashset_base.h +++ b/cds/intrusive/details/multilevel_hashset_base.h @@ -131,24 +131,24 @@ namespace cds { namespace intrusive { }; \endcode */ - typedef opt::none hash_accessor; + typedef cds::opt::none hash_accessor; /// Disposer for removing data nodes - typedef opt::v::empty_disposer disposer; + typedef cds::intrusive::opt::v::empty_disposer disposer; /// Hash comparing functor /** No default functor is provided. If the option is not specified, the \p less option is used. */ - typedef opt::none compare; + typedef cds::opt::none compare; /// Specifies binary predicate used for hash compare. /** If the option is not specified, \p memcmp() -like bit-wise hash comparator is used because the hash value is treated as fixed-sized bit-string. */ - typedef opt::none less; + typedef cds::opt::none less; /// Item counter /** @@ -172,7 +172,7 @@ namespace cds { namespace intrusive { Can be \p opt::v::relaxed_ordering (relaxed memory model, the default) or \p opt::v::sequential_consistent (sequentially consisnent memory model). */ - typedef opt::v::relaxed_ordering memory_model; + typedef cds::opt::v::relaxed_ordering memory_model; /// Back-off strategy typedef cds::backoff::Default back_off; @@ -188,7 +188,7 @@ namespace cds { namespace intrusive { /** List of available policy see \p opt::rcu_check_deadlock */ - typedef opt::v::rcu_throw_deadlock rcu_check_deadlock; + typedef cds::opt::v::rcu_throw_deadlock rcu_check_deadlock; }; /// Metafunction converting option list to \p multilevel_hashset::traits diff --git a/cds/intrusive/impl/multilevel_hashset.h b/cds/intrusive/impl/multilevel_hashset.h index 42ffefd6..4ecdda58 100644 --- a/cds/intrusive/impl/multilevel_hashset.h +++ b/cds/intrusive/impl/multilevel_hashset.h @@ -70,12 +70,15 @@ namespace cds { namespace intrusive { 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 + - \p Traits - type traits, the structure based on \p multilevel_hashset::traits or result of \p multilevel_hashset::make_traits metafunction. + \p Traits is the mandatory argument because it has one mandatory type - an @ref multilevel_hashset::traits::hash_accessor "accessor" + to hash value of \p T. The set algorithm does not calculate that hash value. 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_rcu "RCU type" + - for \ref cds_intrusive_MultiLevelHashSet_rcu "RCU type". RCU specialization + has a slightly different interface. */ template < class GC @@ -765,6 +768,37 @@ namespace cds { namespace intrusive { return false; } + /// Deletes the item pointed by iterator \p it + /** + Returns \p true if the operation is successful, \p false otherwise. + + The function does not invalidate the iterator, it remains valid and can be used for further traversing. + */ + bool erase_at( iterator const& it ) + { + if ( it.m_set != this ) + return false; + if ( it.m_pNode == m_Head && it.m_idx >= head_size()) + return false; + if ( it.m_idx >= array_node_size() ) + return false; + + for (;;) { + node_ptr slot = it.m_pNode->nodes[it.m_idx].load( memory_model::memory_order_acquire ); + if ( slot.bits() == 0 && slot.ptr() == it.pointer() ) { + if ( it.m_pNode->nodes[it.m_idx].compare_exchange_strong(slot, node_ptr(nullptr), memory_model::memory_order_acquire, atomics::memory_order_relaxed) ) { + // the item is guarded by iterator, so we may retire it safely + gc::template retire( slot.ptr() ); + --m_ItemCounter; + m_Stat.onEraseSuccess(); + return true; + } + } + else + return false; + } + } + /// Extracts the item with specified \p hash /** The function searches \p hash in the set, diff --git a/projects/Win/vc12/hdr-test-set.vcxproj b/projects/Win/vc12/hdr-test-set.vcxproj index afbd90e8..9615e062 100644 --- a/projects/Win/vc12/hdr-test-set.vcxproj +++ b/projects/Win/vc12/hdr-test-set.vcxproj @@ -566,6 +566,7 @@ + diff --git a/projects/Win/vc12/hdr-test-set.vcxproj.filters b/projects/Win/vc12/hdr-test-set.vcxproj.filters index 24772ff9..feb558e8 100644 --- a/projects/Win/vc12/hdr-test-set.vcxproj.filters +++ b/projects/Win/vc12/hdr-test-set.vcxproj.filters @@ -320,5 +320,8 @@ intrusive\multilevel_hashset + + intrusive\multilevel_hashset + \ No newline at end of file diff --git a/projects/Win/vc12/hdr-test-striped-set.vcxproj b/projects/Win/vc12/hdr-test-striped-set.vcxproj index b7ee1625..eb90bedf 100644 --- a/projects/Win/vc12/hdr-test-striped-set.vcxproj +++ b/projects/Win/vc12/hdr-test-striped-set.vcxproj @@ -92,6 +92,7 @@ + {A38E5597-6916-4480-A343-C9846EF544E4} diff --git a/projects/Win/vc12/hdr-test-striped-set.vcxproj.filters b/projects/Win/vc12/hdr-test-striped-set.vcxproj.filters index 80351d37..18d96345 100644 --- a/projects/Win/vc12/hdr-test-striped-set.vcxproj.filters +++ b/projects/Win/vc12/hdr-test-striped-set.vcxproj.filters @@ -164,5 +164,6 @@ container\striped + \ No newline at end of file diff --git a/projects/source.test-hdr.mk b/projects/source.test-hdr.mk index cb51fb9b..a552c28f 100644 --- a/projects/source.test-hdr.mk +++ b/projects/source.test-hdr.mk @@ -130,6 +130,7 @@ CDS_TESTHDR_QUEUE := \ CDS_TESTHDR_SET := \ tests/test-hdr/set/hdr_intrusive_multilevel_hashset_hp.cpp \ + tests/test-hdr/set/hdr_intrusive_multilevel_hashset_dhp.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/src/dhp_gc.cpp b/src/dhp_gc.cpp index 4b8ec0d5..629ab1f8 100644 --- a/src/dhp_gc.cpp +++ b/src/dhp_gc.cpp @@ -175,12 +175,14 @@ namespace cds { namespace gc { namespace dhp { details::liberate_set set( beans::ceil2( retiredList.second > nLiberateThreshold ? retiredList.second : nLiberateThreshold ) ); // Get list of retired pointers + size_t nRetiredCount = 0; details::retired_ptr_node * pHead = retiredList.first; while ( pHead ) { details::retired_ptr_node * pNext = pHead->m_pNext.load( atomics::memory_order_relaxed ); pHead->m_pNextFree.store( nullptr, atomics::memory_order_relaxed ); set.insert( *pHead ); pHead = pNext; + ++nRetiredCount; } // Liberate cycle @@ -230,7 +232,7 @@ namespace cds { namespace gc { namespace dhp { assert( range.second != nullptr ); m_RetiredAllocator.free_range( range.first, range.second ); } - else { + else if ( nRetiredCount >= nLiberateThreshold ) { // scan() cycle did not free any retired pointer - double scan() threshold m_nLiberateThreshold.compare_exchange_strong( nLiberateThreshold, nLiberateThreshold * 2, atomics::memory_order_release, atomics::memory_order_relaxed ); } diff --git a/tests/test-hdr/CMakeLists.txt b/tests/test-hdr/CMakeLists.txt index 16eb8f92..d66292df 100644 --- a/tests/test-hdr/CMakeLists.txt +++ b/tests/test-hdr/CMakeLists.txt @@ -131,6 +131,8 @@ set(CDS_TESTHDR_QUEUE queue/hdr_vyukov_mpmc_cyclic.cpp) set(CDS_TESTHDR_SET + set/hdr_intrusive_multilevel_hashset_hp.cpp + set/hdr_intrusive_multilevel_hashset_dhp.cpp set/hdr_intrusive_refinable_hashset_avlset.cpp set/hdr_intrusive_refinable_hashset_list.cpp set/hdr_intrusive_refinable_hashset_set.cpp @@ -270,6 +272,7 @@ set(CDS_TESTHDR_MISC misc/michael_allocator.cpp misc/hash_tuple.cpp misc/bitop_st.cpp + misc/split_bitstring.cpp misc/permutation_generator.cpp misc/thread_init_fini.cpp) diff --git a/tests/test-hdr/set/hdr_intrusive_multilevel_hashset.h b/tests/test-hdr/set/hdr_intrusive_multilevel_hashset.h index 3e417486..2b58b0bc 100644 --- a/tests/test-hdr/set/hdr_intrusive_multilevel_hashset.h +++ b/tests/test-hdr/set/hdr_intrusive_multilevel_hashset.h @@ -53,6 +53,45 @@ namespace set { } }; + struct hash128 + { + size_t lo; + size_t hi; + + hash128() {} + hash128(size_t l, size_t h) : lo(l), hi(h) {} + + struct make { + hash128 operator()( size_t n ) const + { + return hash128( std::hash()( n ), std::hash()( ~n )); + } + hash128 operator()( hash128 const& n ) const + { + return hash128( std::hash()( n.lo ), std::hash()( ~n.hi )); + } + }; + + struct less { + bool operator()( hash128 const& lhs, hash128 const& rhs ) const + { + if ( lhs.hi != rhs.hi ) + return lhs.hi < rhs.hi; + return lhs.lo < rhs.lo; + } + }; + + struct cmp { + int operator()( hash128 const& lhs, hash128 const& rhs ) const + { + if ( lhs.hi != rhs.hi ) + return lhs.hi < rhs.hi ? -1 : 1; + return lhs.lo < rhs.lo ? -1 : lhs.lo == rhs.lo ? 0 : 1; + } + }; + }; + + template void test_hp( size_t nHeadBits, size_t nArrayBits ) { @@ -268,6 +307,24 @@ namespace set { CPPUNIT_ASSERT(s.size() == 0 ); CPPUNIT_ASSERT(s.empty() ); + // erase with iterator + for ( auto& el : arrValue ) { + el.nDisposeCount = 0; + el.nIteratorCall = 0; + CPPUNIT_ASSERT(s.insert( el )); + } + for ( typename Set::iterator it = s.begin(), itEnd = s.end(); it != itEnd; ++it ) { + s.erase_at( it ); + it->nIteratorCall = 1; + } + CPPUNIT_ASSERT(s.size() == 0 ); + Set::gc::force_dispose(); + for ( auto& el : arrValue ) { + CPPUNIT_ASSERT( el.nDisposeCount == 1 ); + CPPUNIT_ASSERT( el.nIteratorCall == 1 ); + } + CPPUNIT_ASSERT(s.empty() ); + CPPUNIT_MSG( s.statistics() ); } @@ -275,12 +332,38 @@ namespace set { void hp_stdhash_stat(); void hp_stdhash_5_3(); void hp_stdhash_5_3_stat(); + void hp_hash128(); + void hp_hash128_stat(); + void hp_hash128_4_3(); + void hp_hash128_4_3_stat(); + + void dhp_stdhash(); + void dhp_stdhash_stat(); + void dhp_stdhash_5_3(); + void dhp_stdhash_5_3_stat(); + void dhp_hash128(); + void dhp_hash128_stat(); + void dhp_hash128_4_3(); + void dhp_hash128_4_3_stat(); CPPUNIT_TEST_SUITE(IntrusiveMultiLevelHashSetHdrTest) CPPUNIT_TEST(hp_stdhash) CPPUNIT_TEST(hp_stdhash_stat) CPPUNIT_TEST(hp_stdhash_5_3) CPPUNIT_TEST(hp_stdhash_5_3_stat) + CPPUNIT_TEST(hp_hash128) + CPPUNIT_TEST(hp_hash128_stat) + CPPUNIT_TEST(hp_hash128_4_3) + CPPUNIT_TEST(hp_hash128_4_3_stat) + + CPPUNIT_TEST(dhp_stdhash) + CPPUNIT_TEST(dhp_stdhash_stat) + CPPUNIT_TEST(dhp_stdhash_5_3) + CPPUNIT_TEST(dhp_stdhash_5_3_stat) + CPPUNIT_TEST(dhp_hash128) + CPPUNIT_TEST(dhp_hash128_stat) + CPPUNIT_TEST(dhp_hash128_4_3) + CPPUNIT_TEST(dhp_hash128_4_3_stat) CPPUNIT_TEST_SUITE_END() }; } // namespace set diff --git a/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_dhp.cpp b/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_dhp.cpp new file mode 100644 index 00000000..9e71de03 --- /dev/null +++ b/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_dhp.cpp @@ -0,0 +1,224 @@ +//$$CDS-header$$ + +#include "set/hdr_intrusive_multilevel_hashset.h" +#include +#include "unit/print_multilevel_hashset_stat.h" + +namespace set { + namespace { + typedef cds::gc::DHP gc_type; + } // namespace + + void IntrusiveMultiLevelHashSetHdrTest::dhp_stdhash() + { + typedef size_t hash_type; + + struct traits: public ci::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::MultiLevelHashSet< gc_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" ); + test_hp>(4, 2); + + typedef ci::MultiLevelHashSet< + gc_type, + Item, + typename ci::multilevel_hashset::make_traits< + ci::multilevel_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_hp>(4, 2); + } + + void IntrusiveMultiLevelHashSetHdrTest::dhp_hash128() + { + typedef hash128 hash_type; + + struct traits: public ci::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef hash128::less less; + }; + typedef ci::MultiLevelHashSet< gc_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" ); + test_hp(4, 2); + + typedef ci::MultiLevelHashSet< + gc_type, + Item, + typename ci::multilevel_hashset::make_traits< + ci::multilevel_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + , ci::opt::less< hash_type::less > + >::type + > set_type2; + test_hp(4, 2); + } + + void IntrusiveMultiLevelHashSetHdrTest::dhp_stdhash_stat() + { + typedef size_t hash_type; + + struct traits: public ci::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef ci::multilevel_hashset::stat<> stat; + }; + typedef ci::MultiLevelHashSet< gc_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" ); + test_hp>(4, 2); + + typedef ci::MultiLevelHashSet< + gc_type, + Item, + typename ci::multilevel_hashset::make_traits< + ci::multilevel_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::multilevel_hashset::stat<>> + >::type + > set_type2; + test_hp>(4, 2); + } + + void IntrusiveMultiLevelHashSetHdrTest::dhp_hash128_stat() + { + typedef hash128 hash_type; + + struct traits: public ci::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef hash128::cmp compare; + typedef ci::multilevel_hashset::stat<> stat; + }; + typedef ci::MultiLevelHashSet< gc_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" ); + test_hp(4, 2); + + typedef ci::MultiLevelHashSet< + gc_type, + Item, + typename ci::multilevel_hashset::make_traits< + ci::multilevel_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::multilevel_hashset::stat<>> + ,co::compare< hash128::cmp > + >::type + > set_type2; + test_hp(4, 2); + } + + void IntrusiveMultiLevelHashSetHdrTest::dhp_stdhash_5_3() + { + typedef size_t hash_type; + + struct traits: public ci::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::MultiLevelHashSet< gc_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" ); + test_hp>(5, 3); + + typedef ci::MultiLevelHashSet< + gc_type, + Item, + typename ci::multilevel_hashset::make_traits< + ci::multilevel_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_hp>(5, 3); + } + + void IntrusiveMultiLevelHashSetHdrTest::dhp_hash128_4_3() + { + typedef hash128 hash_type; + + struct traits: public ci::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef co::v::sequential_consistent memory_model; + }; + typedef ci::MultiLevelHashSet< gc_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" ); + test_hp(4, 3); + + typedef ci::MultiLevelHashSet< + gc_type, + Item, + typename ci::multilevel_hashset::make_traits< + ci::multilevel_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::memory_model< co::v::sequential_consistent > + >::type + > set_type2; + test_hp(4, 3); + } + + void IntrusiveMultiLevelHashSetHdrTest::dhp_stdhash_5_3_stat() + { + typedef size_t hash_type; + + struct traits: public ci::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef ci::multilevel_hashset::stat<> stat; + }; + typedef ci::MultiLevelHashSet< gc_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" ); + test_hp>(5, 3); + + typedef ci::MultiLevelHashSet< + gc_type, + Item, + typename ci::multilevel_hashset::make_traits< + ci::multilevel_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::multilevel_hashset::stat<>> + >::type + > set_type2; + test_hp>(5, 3); + } + + void IntrusiveMultiLevelHashSetHdrTest::dhp_hash128_4_3_stat() + { + typedef hash128 hash_type; + + struct traits: public ci::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef ci::multilevel_hashset::stat<> stat; + typedef hash128::less less; + typedef hash128::cmp compare; + }; + typedef ci::MultiLevelHashSet< gc_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" ); + test_hp(4, 3); + + typedef ci::MultiLevelHashSet< + gc_type, + Item, + typename ci::multilevel_hashset::make_traits< + ci::multilevel_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + , co::stat< ci::multilevel_hashset::stat<>> + , co::less< hash_type::less > + , co::compare< hash128::cmp > + >::type + > set_type2; + test_hp(4, 3); + } + +} // namespace set + +CPPUNIT_TEST_SUITE_REGISTRATION(set::IntrusiveMultiLevelHashSetHdrTest); diff --git a/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_hp.cpp b/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_hp.cpp index 43822e29..d46bdc0f 100644 --- a/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_hp.cpp +++ b/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_hp.cpp @@ -33,6 +33,32 @@ namespace set { test_hp>(4, 2); } + void IntrusiveMultiLevelHashSetHdrTest::hp_hash128() + { + typedef hash128 hash_type; + + struct traits: public ci::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef hash128::less less; + }; + typedef ci::MultiLevelHashSet< gc_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" ); + test_hp(4, 2); + + typedef ci::MultiLevelHashSet< + gc_type, + Item, + typename ci::multilevel_hashset::make_traits< + ci::multilevel_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + , ci::opt::less< hash_type::less > + >::type + > set_type2; + test_hp(4, 2); + } + void IntrusiveMultiLevelHashSetHdrTest::hp_stdhash_stat() { typedef size_t hash_type; @@ -59,6 +85,34 @@ namespace set { test_hp>(4, 2); } + void IntrusiveMultiLevelHashSetHdrTest::hp_hash128_stat() + { + typedef hash128 hash_type; + + struct traits: public ci::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef hash128::cmp compare; + typedef ci::multilevel_hashset::stat<> stat; + }; + typedef ci::MultiLevelHashSet< gc_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" ); + test_hp(4, 2); + + typedef ci::MultiLevelHashSet< + gc_type, + Item, + typename ci::multilevel_hashset::make_traits< + ci::multilevel_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::multilevel_hashset::stat<>> + ,co::compare< hash128::cmp > + >::type + > set_type2; + test_hp(4, 2); + } + void IntrusiveMultiLevelHashSetHdrTest::hp_stdhash_5_3() { typedef size_t hash_type; @@ -83,6 +137,32 @@ namespace set { test_hp>(5, 3); } + void IntrusiveMultiLevelHashSetHdrTest::hp_hash128_4_3() + { + typedef hash128 hash_type; + + struct traits: public ci::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef co::v::sequential_consistent memory_model; + }; + typedef ci::MultiLevelHashSet< gc_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" ); + test_hp(4, 3); + + typedef ci::MultiLevelHashSet< + gc_type, + Item, + typename ci::multilevel_hashset::make_traits< + ci::multilevel_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::memory_model< co::v::sequential_consistent > + >::type + > set_type2; + test_hp(4, 3); + } + void IntrusiveMultiLevelHashSetHdrTest::hp_stdhash_5_3_stat() { typedef size_t hash_type; @@ -109,6 +189,36 @@ namespace set { test_hp>(5, 3); } + void IntrusiveMultiLevelHashSetHdrTest::hp_hash128_4_3_stat() + { + typedef hash128 hash_type; + + struct traits: public ci::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef ci::multilevel_hashset::stat<> stat; + typedef hash128::less less; + typedef hash128::cmp compare; + }; + typedef ci::MultiLevelHashSet< gc_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" ); + test_hp(4, 3); + + typedef ci::MultiLevelHashSet< + gc_type, + Item, + typename ci::multilevel_hashset::make_traits< + ci::multilevel_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + , co::stat< ci::multilevel_hashset::stat<>> + , co::less< hash_type::less > + , co::compare< hash128::cmp > + >::type + > set_type2; + test_hp(4, 3); + } + } // namespace set CPPUNIT_TEST_SUITE_REGISTRATION(set::IntrusiveMultiLevelHashSetHdrTest); -- 2.34.1