From: khizmax Date: Sun, 4 Oct 2015 09:34:51 +0000 (+0300) Subject: Added container::MultiLevelHashSet specialization X-Git-Tag: v2.1.0~94 X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=e804c778ec01243f7f364974333be0238df904da;p=libcds.git Added container::MultiLevelHashSet specialization --- diff --git a/cds/container/impl/multilevel_hashset.h b/cds/container/impl/multilevel_hashset.h index 8a353e59..9d3341ba 100644 --- a/cds/container/impl/multilevel_hashset.h +++ b/cds/container/impl/multilevel_hashset.h @@ -204,7 +204,8 @@ namespace cds { namespace container { If the \p val key not found in the set, then the new item created from \p val will be inserted into the set iff \p bInsert is \p true. - Otherwise, if \p val is found, it is replaced with new item created from \p val. + Otherwise, if \p val is found, it is replaced with new item created from \p val + and previous item is disposed. In both cases \p func functor is called. The functor \p Func signature: @@ -225,11 +226,9 @@ namespace cds { namespace container { i.e. the item has been inserted or updated, \p second is \p true if the new item has been added or \p false if the item with key equal to \p val already exists. - - @warning See \ref cds_intrusive_item_creating "insert item troubleshooting" */ template - std::pair update( const Q& val, Func func, bool bInsert = true ) + std::pair update( Q const& val, Func func, bool bInsert = true ) { scoped_node_ptr sp( cxx_node_allocator().New( val )); std::pair bRes = base_class::do_update( *sp, func, bInsert ); @@ -304,7 +303,7 @@ namespace cds { namespace container { /// Extracts the item with specified \p hash /** The function searches \p hash in the set, - unlinks it from the set, and returns an guarded pointer to the item extracted. + unlinks it from the set, and returns a guarded pointer to the item extracted. If \p hash is not found the function returns an empty guarded pointer. The item returned is reclaimed by garbage collector \p GC diff --git a/cds/container/multilevel_hashset_rcu.h b/cds/container/multilevel_hashset_rcu.h new file mode 100644 index 00000000..b84e344a --- /dev/null +++ b/cds/container/multilevel_hashset_rcu.h @@ -0,0 +1,546 @@ +//$$CDS-header$$ + +#ifndef CDSLIB_CONTAINER_MULTILEVEL_HASHSET_RCU_H +#define CDSLIB_CONTAINER_MULTILEVEL_HASHSET_RCU_H + +#include +#include + +namespace cds { namespace container { + + /// Hash set based on multi-level array, \ref cds_urcu_desc "RCU" specialization + /** @ingroup cds_nonintrusive_set + @anchor cds_container_MultilevelHashSet_rcu + + Source: + - [2013] Steven Feldman, Pierre LaBorde, Damian Dechev "Concurrent Multi-level Arrays: + Wait-free Extensible Hash Maps" + + See algorithm short description @ref cds_intrusive_MultilevelHashSet_RCU "here" + + @note Two important things you should keep in mind when you're using \p %MultiLevelHashSet: + - all keys must be fixed-size. It means that you cannot use \p std::string as a key for \p %MultiLevelHashSet. + Instead, for the strings you should use well-known hashing algorithms like SHA1, SHA2, + MurmurHash, CityHash + or its successor FarmHash and so on, which + converts variable-length strings to fixed-length bit-strings, and use that hash as a key in \p %MultiLevelHashSet. + - \p %MultiLevelHashSet uses a perfect hashing. It means that if two different keys, for example, of type \p std::string, + 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. + + The set supports @ref cds_container_MultilevelHashSet_iterators "bidirectional thread-safe iterators". + + Template parameters: + - \p RCU - one of \ref cds_urcu_gc "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 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. + + @note Before including you should include appropriate RCU header file, + see \ref cds_urcu_gc "RCU type" for list of existing RCU class and corresponding header files. + + The set supports @ref cds_container_MultilevelHashSet_rcu_iterators "bidirectional thread-safe iterators" + with some restrictions. + */ + template < + class RCU + , typename T +#ifdef CDS_DOXYGEN_INVOKED + , class Traits = multilevel_hashset::traits +#else + , class Traits +#endif + > + class MultiLevelHashSet< cds::urcu::gc< RCU >, T, Traits > +#ifdef CDS_DOXYGEN_INVOKED + : protected cds::intrusive::MultiLevelHashSet< cds::urcu::gc< RCU >, T, Traits > +#else + : protected cds::container::details::make_multilevel_hashset< cds::urcu::gc< RCU >, T, Traits >::type +#endif + { + //@cond + typedef cds::container::details::make_multilevel_hashset< cds::urcu::gc< RCU >, T, Traits > maker; + typedef typename maker::type base_class; + //@endcond + + public: + typedef cds::urcu::gc< RCU > gc; ///< RCU garbage collector + typedef T value_type; ///< type of value stored in the set + typedef Traits traits; ///< Traits template parameter, see \p multilevel_hashset::traits + + typedef typename base_class::hash_accessor hash_accessor; ///< Hash accessor functor + typedef typename base_class::hash_type hash_type; ///< Hash type deduced from \p hash_accessor return type + typedef typename base_class::hash_comparator hash_comparator; ///< hash compare functor based on \p opt::compare and \p opt::less option setter + + typedef typename traits::item_counter item_counter; ///< Item counter type + typedef typename traits::allocator allocator; ///< Element allocator + typedef typename traits::node_allocator node_allocator; ///< Array node allocator + typedef typename traits::memory_model memory_model; ///< Memory model + typedef typename traits::back_off back_off; ///< Backoff strategy + typedef typename traits::stat stat; ///< Internal statistics type + typedef typename traits::rcu_check_deadlock rcu_check_deadlock; ///< Deadlock checking policy + typedef typename gc::scoped_lock rcu_lock; ///< RCU scoped lock + static CDS_CONSTEXPR const bool c_bExtractLockExternal = false; ///< Group of \p extract_xxx functions does not require external locking + typedef typename base_class::exempt_ptr exempt_ptr; ///< pointer to extracted node + + typedef typename base_class::iterator iterator; ///< @ref cds_container_MultilevelHashSet_rcu_iterators "bidirectional iterator" type + typedef typename base_class::const_iterator const_iterator; ///< @ref cds_container_MultilevelHashSet_rcu_iterators "bidirectional const iterator" type + typedef typename base_class::reverse_iterator reverse_iterator; ///< @ref cds_container_MultilevelHashSet_rcu_iterators "bidirectional reverse iterator" type + typedef typename base_class::const_reverse_iterator const_reverse_iterator; ///< @ref cds_container_MultilevelHashSet_rcu_iterators "bidirectional reverse const iterator" type + + protected: + //@cond + typedef typename maker::cxx_node_allocator cxx_node_allocator; + typedef std::unique_ptr< value_type, typename maker::node_disposer > scoped_node_ptr; + //@endcond + + public: + /// Creates empty set + /** + @param head_bits: 2head_bits specifies the size of head array, minimum is 4. + @param array_bits: 2array_bits specifies the size of array node, minimum is 2. + + Equation for \p head_bits and \p array_bits: + \code + sizeof(hash_type) * 8 == head_bits + N * array_bits + \endcode + where \p N is multi-level array depth. + */ + MultiLevelHashSet( size_t head_bits = 8, size_t array_bits = 4 ) + : base_class( head_bits, array_bits ) + {} + + /// Destructs the set and frees all data + ~MultiLevelHashSet() + {} + + /// Inserts new element + /** + The function creates an element with copy of \p val value and then inserts it into the set. + + The type \p Q should contain as minimum the complete hash for the element. + The object of \ref value_type should be constructible from a value of type \p Q. + In trivial case, \p Q is equal to \ref value_type. + + Returns \p true if \p val is inserted into the set, \p false otherwise. + + The function locks RCU internally. + */ + template + bool insert( Q const& val ) + { + scoped_node_ptr sp( cxx_node_allocator().New( val )); + if ( base_class::insert( *sp )) { + sp.release(); + return true; + } + return false; + } + + /// Inserts new element + /** + The function allows to split creating of new item into two part: + - create item with key only + - insert new item into the set + - if inserting is success, calls \p f functor to initialize value-fields of \p val. + + The functor signature is: + \code + void func( value_type& val ); + \endcode + where \p val is the item inserted. User-defined functor \p f should guarantee that during changing + \p val no any other changes could be made on this set's item by concurrent threads. + The user-defined functor is called only if the inserting is success. + + The function locks RCU internally. + */ + template + bool insert( Q const& val, Func f ) + { + scoped_node_ptr sp( cxx_node_allocator().New( val )); + if ( base_class::insert( *sp, f )) { + sp.release(); + return true; + } + return false; + } + + /// Updates the element + /** + The operation performs inserting or replacing with lock-free manner. + + If the \p val key not found in the set, then the new item created from \p val + will be inserted into the set iff \p bInsert is \p true. + Otherwise, if \p val is found, it is replaced with new item created from \p val + and previous item is disposed. + In both cases \p func functor is called. + + The functor \p Func signature: + \code + struct my_functor { + void operator()( value_type& cur, value_type * prev ); + }; + \endcode + where: + - \p cur - current element + - \p prev - pointer to previous element with such hash. \p prev is \p nullptr + if \p cur was just inserted. + + The functor may change non-key fields of the \p item; however, \p func must guarantee + that during changing no any other modifications could be made on this item by concurrent threads. + + Returns std::pair where \p first is \p true if operation is successfull, + i.e. the item has been inserted or updated, + \p second is \p true if the new item has been added or \p false if the item with key equal to \p val + already exists. + */ + template + std::pair update( Q const& val, Func func, bool bInsert = true ) + { + scoped_node_ptr sp( cxx_node_allocator().New( val )); + std::pair bRes = base_class::do_update( *sp, func, bInsert ); + if ( bRes.first ) + sp.release(); + return bRes; + } + + /// Inserts data of type \p value_type created in-place from std::forward(args)... + /** + Returns \p true if inserting successful, \p false otherwise. + */ + template + bool emplace( Args&&... args ) + { + scoped_node_ptr sp( cxx_node_allocator().New( std::forward(args)... )); + if ( base_class::insert( *sp )) { + sp.release(); + return true; + } + return false; + } + + /// Deletes the item from the set + /** + The function searches \p hash in the set, + deletes the item found, and returns \p true. + If that item is not found the function returns \p false. + */ + bool erase( hash_type const& hash ) + { + return base_class::erase( hash ); + } + + /// Deletes the item from the set + /** + The function searches \p hash in the set, + call \p f functor with item found, and deltes the element from the set. + + The \p Func interface is + \code + struct functor { + void operator()( value_type& item ); + }; + \endcode + + If \p hash is not found the function returns \p false. + */ + template + bool erase( hash_type const& hash, Func f ) + { + return base_class::erase( hash, f ); + } + + /// Extracts the item with specified \p hash + /** + The function searches \p hash in the set, + unlinks it from the set, and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the item found. + If the item with key equal to \p key is not found the function returns an empty \p exempt_ptr. + + RCU \p synchronize method can be called. RCU should NOT be locked. + The function does not call the disposer for the item found. + The disposer will be implicitly invoked when the returned object is destroyed or when + its \p release() member function is called. + Example: + \code + typedef cds::container::MultiLevelHashSet< cds::urcu::gc< cds::urcu::general_buffered<> >, foo, my_traits > set_type; + set_type theSet; + // ... + + typename set_type::exempt_ptr ep( theSet.extract( 5 )); + if ( ep ) { + // Deal with ep + //... + + // Dispose returned item. + ep.release(); + } + \endcode + */ + exempt_ptr extract( hash_type const& hash ) + { + return base_class::extract( hash ); + } + + /// Finds an item by it's \p hash + /** + The function searches the item by \p hash and calls the functor \p f for item found. + The interface of \p Func functor is: + \code + struct functor { + void operator()( value_type& item ); + }; + \endcode + where \p item is the item found. + + The functor may change non-key fields of \p item. Note that the functor is only guarantee + that \p item cannot be disposed during the functor is executing. + The functor does not serialize simultaneous access to the set's \p item. If such access is + possible you must provide your own synchronization schema on item level to prevent unsafe item modifications. + + The function returns \p true if \p hash is found, \p false otherwise. + */ + template + bool find( hash_type const& hash, Func f ) + { + return base_class::find( hash, f ); + } + + /// Checks whether the set contains \p hash + /** + The function searches the item by its \p hash + and returns \p true if it is found, or \p false otherwise. + */ + bool contains( hash_type const& hash ) + { + return base_class::contains( hash ); + } + + /// Finds an item by it's \p hash and returns the item found + /** + The function searches the item by its \p hash + and returns the pointer to the item found. + If \p hash is not found the function returns \p nullptr. + + RCU should be locked before the function invocation. + Returned pointer is valid only while RCU is locked. + + Usage: + \code + typedef cds::container::MultiLevelHashSet< your_template_params > my_set; + my_set theSet; + // ... + { + // lock RCU + my_set::rcu_lock; + + foo * p = theSet.get( 5 ); + if ( p ) { + // Deal with p + //... + } + } + \endcode + */ + value_type * get( hash_type const& hash ) + { + return base_class::get( hash ); + } + + /// Clears the set (non-atomic) + /** + The function unlink all data node from the set. + The function is not atomic but is thread-safe. + After \p %clear() the set may not be empty because another threads may insert items. + */ + void clear() + { + base_class::clear(); + } + + /// Checks if the set is empty + /** + Emptiness is checked by item counting: if item count is zero then the set is empty. + Thus, the correct item counting feature is an important part of the set implementation. + */ + bool empty() const + { + return base_class::empty(); + } + + /// Returns item count in the set + size_t size() const + { + return base_class::size(); + } + + /// Returns const reference to internal statistics + stat const& statistics() const + { + return base_class::statistics(); + } + + /// Returns the size of head node + size_t head_size() const + { + return base_class::head_size(); + } + + /// Returns the size of the array node + size_t array_node_size() const + { + return base_class::array_node_size(); + } + + public: + ///@name Thread-safe iterators + /** @anchor cds_container_MultilevelHashSet_rcu_iterators + The set supports thread-safe iterators: you may iterate over the set in multi-threaded environment + under explicit RCU lock. + RCU lock requirement means that inserting or searching is allowed but you must not erase the items from the set + since erasing under RCU lock can lead to a deadlock. However, another thread can call \p erase() safely + while your thread is iterating. + + A typical example is: + \code + struct foo { + uint32_t hash; + // ... other fields + uint32_t payload; // only for example + }; + struct set_traits: cds::container::multilevel_hashset::traits + { + struct hash_accessor { + uint32_t operator()( foo const& src ) const + { + retur src.hash; + } + }; + }; + + typedef cds::urcu::gc< cds::urcu::general_buffered<>> rcu; + typedef cds::container::MultiLevelHashSet< rcu, foo, set_traits > set_type; + + set_type s; + + // ... + + // iterate over the set + { + // lock the RCU. + typename set_type::rcu_lock l; // scoped RCU lock + + // traverse the set + for ( auto i = s.begin(); i != s.end(); ++i ) { + // deal with i. Remember, erasing is prohibited here! + i->payload++; + } + } // at this point RCU lock is released + /endcode + + Each iterator object supports the common interface: + - dereference operators: + @code + value_type [const] * operator ->() noexcept + value_type [const] & operator *() noexcept + @endcode + - pre-increment and pre-decrement. Post-operators is not supported + - equality operators == and !=. + Iterators are equal iff they point to the same cell of the same array node. + Note that for two iterators \p it1 and \p it2 the condition it1 == it2 + does not entail &(*it1) == &(*it2) : welcome to concurrent containers + + @note It is possible the item can be iterated more that once, for example, if an iterator points to the item + in an array node that is being splitted. + */ + ///@{ + + /// Returns an iterator to the beginning of the set + iterator begin() + { + return base_class::begin(); + } + + /// Returns an const iterator to the beginning of the set + const_iterator begin() const + { + return base_class::begin(); + } + + /// Returns an const iterator to the beginning of the set + const_iterator cbegin() + { + return base_class::cbegin(); + } + + /// Returns an iterator to the element following the last element of the set. This element acts as a placeholder; attempting to access it results in undefined behavior. + iterator end() + { + return base_class::end(); + } + + /// Returns a const iterator to the element following the last element of the set. This element acts as a placeholder; attempting to access it results in undefined behavior. + const_iterator end() const + { + return base_class::end(); + } + + /// Returns a const iterator to the element following the last element of the set. This element acts as a placeholder; attempting to access it results in undefined behavior. + const_iterator cend() + { + return base_class::cend(); + } + + /// Returns a reverse iterator to the first element of the reversed set + reverse_iterator rbegin() + { + return base_class::rbegin(); + } + + /// Returns a const reverse iterator to the first element of the reversed set + const_reverse_iterator rbegin() const + { + return base_class::rbegin(); + } + + /// Returns a const reverse iterator to the first element of the reversed set + const_reverse_iterator crbegin() + { + return base_class::crbegin(); + } + + /// Returns a reverse iterator to the element following the last element of the reversed set + /** + It corresponds to the element preceding the first element of the non-reversed container. + This element acts as a placeholder, attempting to access it results in undefined behavior. + */ + reverse_iterator rend() + { + return base_class::rend(); + } + + /// Returns a const reverse iterator to the element following the last element of the reversed set + /** + It corresponds to the element preceding the first element of the non-reversed container. + This element acts as a placeholder, attempting to access it results in undefined behavior. + */ + const_reverse_iterator rend() const + { + return base_class::rend(); + } + + /// Returns a const reverse iterator to the element following the last element of the reversed set + /** + It corresponds to the element preceding the first element of the non-reversed container. + This element acts as a placeholder, attempting to access it results in undefined behavior. + */ + const_reverse_iterator crend() + { + return base_class::crend(); + } + ///@} + }; + +}} // namespace cds::container + +#endif // #ifndef CDSLIB_CONTAINER_MULTILEVEL_HASHSET_RCU_H diff --git a/cds/intrusive/multilevel_hashset_rcu.h b/cds/intrusive/multilevel_hashset_rcu.h index 3146a6ad..1c088612 100644 --- a/cds/intrusive/multilevel_hashset_rcu.h +++ b/cds/intrusive/multilevel_hashset_rcu.h @@ -24,6 +24,16 @@ namespace cds { namespace intrusive { See algorithm short description @ref cds_intrusive_MultilevelHashSet_hp "here" + @note Two important things you should keep in mind when you're using \p %MultiLevelHashSet: + - all keys must be fixed-size. It means that you cannot use \p std::string as a key for \p %MultiLevelHashSet. + Instead, for the strings you should use well-known hashing algorithms like SHA1, SHA2, + MurmurHash, CityHash + or its successor FarmHash and so on, which + converts variable-length strings to fixed-length bit-strings, and use that hash as a key in \p %MultiLevelHashSet. + - \p %MultiLevelHashSet uses a perfect hashing. It means that if two different keys, for example, of type \p std::string, + 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 RCU - one of \ref cds_urcu_gc "RCU type" - \p T - a value type to be stored in the set @@ -458,7 +468,7 @@ namespace cds { namespace intrusive { // ... { // lock RCU - my_set::rcu_lock + my_set::rcu_lock; foo * p = theSet.get( 5 ); if ( p ) { diff --git a/projects/Win/vc12/cds.vcxproj b/projects/Win/vc12/cds.vcxproj index d4769161..f83e634d 100644 --- a/projects/Win/vc12/cds.vcxproj +++ b/projects/Win/vc12/cds.vcxproj @@ -706,6 +706,7 @@ + diff --git a/projects/Win/vc12/cds.vcxproj.filters b/projects/Win/vc12/cds.vcxproj.filters index c228d180..dff39dfa 100644 --- a/projects/Win/vc12/cds.vcxproj.filters +++ b/projects/Win/vc12/cds.vcxproj.filters @@ -1220,5 +1220,8 @@ Header Files\cds\intrusive + + Header Files\cds\container + \ No newline at end of file diff --git a/projects/Win/vc12/hdr-test-set.vcxproj b/projects/Win/vc12/hdr-test-set.vcxproj index 3d30e7a3..098bcba1 100644 --- a/projects/Win/vc12/hdr-test-set.vcxproj +++ b/projects/Win/vc12/hdr-test-set.vcxproj @@ -624,6 +624,11 @@ + + + + + diff --git a/projects/Win/vc12/hdr-test-set.vcxproj.filters b/projects/Win/vc12/hdr-test-set.vcxproj.filters index f9c2520e..0f5788e0 100644 --- a/projects/Win/vc12/hdr-test-set.vcxproj.filters +++ b/projects/Win/vc12/hdr-test-set.vcxproj.filters @@ -350,5 +350,20 @@ intrusive\multilevel_hashset + + container\multilevel_hashset + + + container\multilevel_hashset + + + container\multilevel_hashset + + + container\multilevel_hashset + + + container\multilevel_hashset + \ No newline at end of file diff --git a/projects/Win/vc14/cds.vcxproj b/projects/Win/vc14/cds.vcxproj index 7be0c3f3..b194cbc4 100644 --- a/projects/Win/vc14/cds.vcxproj +++ b/projects/Win/vc14/cds.vcxproj @@ -811,6 +811,7 @@ + diff --git a/projects/Win/vc14/cds.vcxproj.filters b/projects/Win/vc14/cds.vcxproj.filters index c228d180..dff39dfa 100644 --- a/projects/Win/vc14/cds.vcxproj.filters +++ b/projects/Win/vc14/cds.vcxproj.filters @@ -1220,5 +1220,8 @@ Header Files\cds\intrusive + + Header Files\cds\container + \ No newline at end of file diff --git a/projects/Win/vc14/hdr-test-set.vcxproj b/projects/Win/vc14/hdr-test-set.vcxproj index a18d6719..afce40f9 100644 --- a/projects/Win/vc14/hdr-test-set.vcxproj +++ b/projects/Win/vc14/hdr-test-set.vcxproj @@ -723,6 +723,11 @@ + + + + + diff --git a/projects/Win/vc14/hdr-test-set.vcxproj.filters b/projects/Win/vc14/hdr-test-set.vcxproj.filters index 08d97627..d9522f15 100644 --- a/projects/Win/vc14/hdr-test-set.vcxproj.filters +++ b/projects/Win/vc14/hdr-test-set.vcxproj.filters @@ -350,5 +350,20 @@ intrusive\multilevel_hashset + + container\multilevel_hashset + + + container\multilevel_hashset + + + container\multilevel_hashset + + + container\multilevel_hashset + + + container\multilevel_hashset + \ No newline at end of file diff --git a/projects/source.test-hdr.mk b/projects/source.test-hdr.mk index 3517c56f..696dfadc 100644 --- a/projects/source.test-hdr.mk +++ b/projects/source.test-hdr.mk @@ -181,6 +181,11 @@ CDS_TESTHDR_SET := \ tests/test-hdr/set/hdr_michael_set_lazy_nogc.cpp \ tests/test-hdr/set/hdr_multilevel_hashset_hp.cpp \ tests/test-hdr/set/hdr_multilevel_hashset_dhp.cpp \ + tests/test-hdr/set/hdr_multilevel_hashset_rcu_gpb.cpp \ + tests/test-hdr/set/hdr_multilevel_hashset_rcu_gpi.cpp \ + tests/test-hdr/set/hdr_multilevel_hashset_rcu_gpt.cpp \ + tests/test-hdr/set/hdr_multilevel_hashset_rcu_shb.cpp \ + tests/test-hdr/set/hdr_multilevel_hashset_rcu_sht.cpp \ tests/test-hdr/set/hdr_refinable_hashset_hashset_std.cpp \ tests/test-hdr/set/hdr_refinable_hashset_boost_flat_set.cpp \ tests/test-hdr/set/hdr_refinable_hashset_boost_list.cpp \ diff --git a/tests/test-hdr/CMakeLists.txt b/tests/test-hdr/CMakeLists.txt index 55590de9..f6a4ccd1 100644 --- a/tests/test-hdr/CMakeLists.txt +++ b/tests/test-hdr/CMakeLists.txt @@ -183,6 +183,11 @@ set(CDS_TESTHDR_SET set/hdr_michael_set_lazy_nogc.cpp set/hdr_multilevel_hashset_hp.cpp set/hdr_multilevel_hashset_dhp.cpp + set/hdr_multilevel_hashset_rcu_gpb.cpp + set/hdr_multilevel_hashset_rcu_gpi.cpp + set/hdr_multilevel_hashset_rcu_gpt.cpp + set/hdr_multilevel_hashset_rcu_shb.cpp + set/hdr_multilevel_hashset_rcu_sht.cpp set/hdr_refinable_hashset_hashset_std.cpp set/hdr_refinable_hashset_boost_flat_set.cpp set/hdr_refinable_hashset_boost_list.cpp diff --git a/tests/test-hdr/set/hdr_multilevel_hashset.h b/tests/test-hdr/set/hdr_multilevel_hashset.h index 24a5989c..2c5f3955 100644 --- a/tests/test-hdr/set/hdr_multilevel_hashset.h +++ b/tests/test-hdr/set/hdr_multilevel_hashset.h @@ -387,6 +387,255 @@ namespace set { CPPUNIT_MSG( s.statistics() ); } + template + void test_rcu(size_t nHeadBits, size_t nArrayBits) + { + typedef typename Set::hash_type hash_type; + typedef typename Set::value_type value_type; + typedef Arg arg_type; + typedef typename Set::exempt_ptr exempt_ptr; + typedef typename Set::rcu_lock rcu_lock; + + Hasher hasher; + + size_t const capacity = 1000; + + Set s(nHeadBits, nArrayBits); + CPPUNIT_MSG("Array size: head=" << s.head_size() << ", array_node=" << s.array_node_size()); + CPPUNIT_ASSERT(s.head_size() >= (size_t(1) << nHeadBits)); + CPPUNIT_ASSERT(s.array_node_size() == (size_t(1) << nArrayBits)); + + CPPUNIT_ASSERT(s.empty()); + CPPUNIT_ASSERT(s.size() == 0); + + // insert test + for (size_t i = 0; i < capacity; ++i) { + hash_type h = hasher(i); + CPPUNIT_ASSERT(!s.contains(h)); + CPPUNIT_ASSERT(s.insert(value_type(i, h))); + CPPUNIT_ASSERT(s.contains(h)); + + CPPUNIT_ASSERT(!s.empty()); + CPPUNIT_ASSERT(s.size() == i + 1); + + CPPUNIT_ASSERT(!s.insert(arg_type(i, h))); + CPPUNIT_ASSERT(s.size() == i + 1); + } + + // update existing test + for (size_t i = 0; i < capacity; ++i) { + hash_type h = hasher(i); + CPPUNIT_ASSERT(s.contains(h)); + std::pair ret = s.update(arg_type(i, h), + [](value_type& i, value_type * prev) { + CPPUNIT_ASSERT_CURRENT(prev != nullptr); + CPPUNIT_ASSERT_CURRENT(i.key == prev->key); + CPPUNIT_ASSERT_CURRENT(i.hash == prev->hash); + i.nInsertCall += 1; + }, false); + CPPUNIT_ASSERT(ret.first); + CPPUNIT_ASSERT(!ret.second); + CPPUNIT_ASSERT(s.contains(h)); + CPPUNIT_ASSERT(s.size() == capacity); + + { + rcu_lock l; + value_type * p = s.get(h); + CPPUNIT_ASSERT(p); + CPPUNIT_ASSERT(p->nInsertCall == 1); + CPPUNIT_ASSERT(p->key == i); + CPPUNIT_ASSERT(p->hash == h); + } + } + + // erase test + for (size_t i = 0; i < capacity; ++i) { + CPPUNIT_ASSERT(!s.empty()); + CPPUNIT_ASSERT(s.size() == capacity - i); + CPPUNIT_ASSERT(s.find(hasher(i), [](value_type &) {})); + CPPUNIT_ASSERT(s.erase(hasher(i))); + CPPUNIT_ASSERT(!s.find(hasher(i), [](value_type &) {})); + CPPUNIT_ASSERT(s.size() == capacity - i - 1); + } + CPPUNIT_ASSERT(s.empty()); + + // Iterators on empty set + { + rcu_lock l; + CPPUNIT_ASSERT(s.begin() == s.end()); + CPPUNIT_ASSERT(s.cbegin() == s.cend()); + CPPUNIT_ASSERT(s.rbegin() == s.rend()); + CPPUNIT_ASSERT(s.crbegin() == s.crend()); + } + + // insert with functor + for (size_t i = capacity; i > 0; --i) { + CPPUNIT_ASSERT(s.size() == capacity - i); + CPPUNIT_ASSERT(s.insert(arg_type(i, hasher(i)), [](value_type& val) { val.nInsertCall += 1; })); + CPPUNIT_ASSERT(s.size() == capacity - i + 1); + CPPUNIT_ASSERT(!s.empty()); + + CPPUNIT_ASSERT(s.find(hasher(i), [](value_type& val) { + CPPUNIT_ASSERT_CURRENT(val.nInsertCall == 1); + val.nFindCall += 1; + })); + } + CPPUNIT_ASSERT(s.size() == capacity); + + // for-each iterator test + { + rcu_lock l; + for (auto& el : s) { + CPPUNIT_ASSERT(el.nInsertCall == 1); + CPPUNIT_ASSERT(el.nFindCall == 1); + el.nFindCall += 1; + } + } + + // iterator test + { + rcu_lock l; + for (auto it = s.begin(), itEnd = s.end(); it != itEnd; ++it) { + CPPUNIT_ASSERT(it->nInsertCall == 1); + CPPUNIT_ASSERT(it->nFindCall == 2); + it->nFindCall += 1; + } + } + + // reverse iterator test + { + rcu_lock l; + for (auto it = s.rbegin(), itEnd = s.rend(); it != itEnd; ++it) { + CPPUNIT_ASSERT(it->nInsertCall == 1); + CPPUNIT_ASSERT(it->nFindCall == 3); + it->nFindCall += 1; + } + } + + // const iterator test + { + rcu_lock l; + for (auto it = s.cbegin(), itEnd = s.cend(); it != itEnd; ++it) { + CPPUNIT_ASSERT(it->nInsertCall == 1); + CPPUNIT_ASSERT(it->nFindCall == 4); + it->nIteratorCall += 1; + } + } + + // const reverse iterator test + { + rcu_lock l; + for (auto it = s.rbegin(), itEnd = s.rend(); it != itEnd; ++it) { + CPPUNIT_ASSERT(it->nInsertCall == 1); + CPPUNIT_ASSERT(it->nFindCall == 4); + CPPUNIT_ASSERT(it->nIteratorCall == 1); + it->nIteratorCall += 1; + } + } + + // check completeness + for (size_t i = 1; i <= capacity; ++i) { + CPPUNIT_ASSERT(s.find(hasher(i), [](value_type const& el) { + CPPUNIT_ASSERT_CURRENT(el.nInsertCall == 1); + CPPUNIT_ASSERT_CURRENT(el.nFindCall == 4); + CPPUNIT_ASSERT_CURRENT(el.nIteratorCall == 2); + })); + } + + // erase with functor test + { + size_t nSum = 0; + for (size_t i = 1; i <= capacity; ++i) { + CPPUNIT_ASSERT(s.size() == capacity - i + 1); + CPPUNIT_ASSERT(s.erase(hasher(i), [&nSum](value_type const& val) { + CPPUNIT_ASSERT_CURRENT(val.nInsertCall == 1); + CPPUNIT_ASSERT_CURRENT(val.nFindCall == 4); + CPPUNIT_ASSERT_CURRENT(val.nIteratorCall == 2); + nSum += val.key; + })); + CPPUNIT_ASSERT(s.size() == capacity - i); + CPPUNIT_ASSERT(!s.erase(hasher(i), [&nSum](value_type const& val) { nSum += val.key; })) + } + CPPUNIT_ASSERT(s.empty()); + CPPUNIT_ASSERT(nSum == (1 + capacity) * capacity / 2); + } + + // update test with insert allowing + for (size_t i = 0; i < capacity; ++i) { + hash_type h = hasher(i); + CPPUNIT_ASSERT(!s.contains(h)); + + { + rcu_lock l; + value_type * p = s.get(h); + CPPUNIT_ASSERT(!p); + } + std::pair ret = s.update(arg_type(i, h), + [](value_type& i, value_type * prev) { + CPPUNIT_ASSERT_CURRENT(prev == nullptr); + i.nInsertCall += 1; + }); + CPPUNIT_ASSERT(ret.first); + CPPUNIT_ASSERT(ret.second); + CPPUNIT_ASSERT(s.contains(h)); + CPPUNIT_ASSERT(s.size() == i + 1); + + { + rcu_lock l; + value_type * p = s.get(h); + CPPUNIT_ASSERT(p); + CPPUNIT_ASSERT(p->nInsertCall == 1); + CPPUNIT_ASSERT(p->key == i); + CPPUNIT_ASSERT(p->hash == h); + } + } + CPPUNIT_ASSERT(!s.empty()); + CPPUNIT_ASSERT(s.size() == capacity); + + s.clear(); + CPPUNIT_ASSERT(s.empty()); + CPPUNIT_ASSERT(s.size() == 0); + + // emplace test + for (size_t i = 0; i < capacity; ++i) { + hash_type h = hasher(i); + CPPUNIT_ASSERT(!s.contains(h)); + CPPUNIT_ASSERT(s.emplace(i, hasher(i))); + CPPUNIT_ASSERT(s.contains(h)); + + CPPUNIT_ASSERT(!s.empty()); + CPPUNIT_ASSERT(s.size() == i + 1); + + CPPUNIT_ASSERT(!s.emplace(arg_type(i, h))); + CPPUNIT_ASSERT(s.size() == i + 1); + } + CPPUNIT_ASSERT(!s.empty()); + CPPUNIT_ASSERT(s.size() == capacity); + + // extract test + for (size_t i = capacity; i != 0; --i) { + CPPUNIT_ASSERT(!s.empty()); + CPPUNIT_ASSERT(s.size() == i); + + exempt_ptr gp{ s.extract(hasher(i - 1)) }; + CPPUNIT_ASSERT(gp); + CPPUNIT_ASSERT(gp->key == i - 1); + CPPUNIT_ASSERT(gp->hash == hasher(i - 1)); + CPPUNIT_ASSERT(!s.contains(hasher(i - 1))); + + { + rcu_lock l; + value_type * p = s.get(hasher(i - 1)); + CPPUNIT_ASSERT( p == nullptr ); + } + CPPUNIT_ASSERT(s.size() == i - 1); + } + CPPUNIT_ASSERT(s.empty()); + CPPUNIT_ASSERT(s.size() == 0); + + CPPUNIT_MSG(s.statistics()); + } + void hp_stdhash(); void hp_stdhash_stat(); void hp_stdhash_5_3(); @@ -405,6 +654,51 @@ namespace set { void dhp_hash128_4_3(); void dhp_hash128_4_3_stat(); + void rcu_gpi_stdhash(); + void rcu_gpi_stdhash_stat(); + void rcu_gpi_stdhash_5_3(); + void rcu_gpi_stdhash_5_3_stat(); + void rcu_gpi_hash128(); + void rcu_gpi_hash128_stat(); + void rcu_gpi_hash128_4_3(); + void rcu_gpi_hash128_4_3_stat(); + + void rcu_gpb_stdhash(); + void rcu_gpb_stdhash_stat(); + void rcu_gpb_stdhash_5_3(); + void rcu_gpb_stdhash_5_3_stat(); + void rcu_gpb_hash128(); + void rcu_gpb_hash128_stat(); + void rcu_gpb_hash128_4_3(); + void rcu_gpb_hash128_4_3_stat(); + + void rcu_gpt_stdhash(); + void rcu_gpt_stdhash_stat(); + void rcu_gpt_stdhash_5_3(); + void rcu_gpt_stdhash_5_3_stat(); + void rcu_gpt_hash128(); + void rcu_gpt_hash128_stat(); + void rcu_gpt_hash128_4_3(); + void rcu_gpt_hash128_4_3_stat(); + + void rcu_shb_stdhash(); + void rcu_shb_stdhash_stat(); + void rcu_shb_stdhash_5_3(); + void rcu_shb_stdhash_5_3_stat(); + void rcu_shb_hash128(); + void rcu_shb_hash128_stat(); + void rcu_shb_hash128_4_3(); + void rcu_shb_hash128_4_3_stat(); + + void rcu_sht_stdhash(); + void rcu_sht_stdhash_stat(); + void rcu_sht_stdhash_5_3(); + void rcu_sht_stdhash_5_3_stat(); + void rcu_sht_hash128(); + void rcu_sht_hash128_stat(); + void rcu_sht_hash128_4_3(); + void rcu_sht_hash128_4_3_stat(); + CPPUNIT_TEST_SUITE(MultiLevelHashSetHdrTest) CPPUNIT_TEST(hp_stdhash) CPPUNIT_TEST(hp_stdhash_stat) @@ -423,6 +717,51 @@ namespace set { CPPUNIT_TEST(dhp_hash128_stat) CPPUNIT_TEST(dhp_hash128_4_3) CPPUNIT_TEST(dhp_hash128_4_3_stat) + + CPPUNIT_TEST(rcu_gpi_stdhash) + CPPUNIT_TEST(rcu_gpi_stdhash_stat) + CPPUNIT_TEST(rcu_gpi_stdhash_5_3) + CPPUNIT_TEST(rcu_gpi_stdhash_5_3_stat) + CPPUNIT_TEST(rcu_gpi_hash128) + CPPUNIT_TEST(rcu_gpi_hash128_stat) + CPPUNIT_TEST(rcu_gpi_hash128_4_3) + CPPUNIT_TEST(rcu_gpi_hash128_4_3_stat) + + CPPUNIT_TEST(rcu_gpb_stdhash) + CPPUNIT_TEST(rcu_gpb_stdhash_stat) + CPPUNIT_TEST(rcu_gpb_stdhash_5_3) + CPPUNIT_TEST(rcu_gpb_stdhash_5_3_stat) + CPPUNIT_TEST(rcu_gpb_hash128) + CPPUNIT_TEST(rcu_gpb_hash128_stat) + CPPUNIT_TEST(rcu_gpb_hash128_4_3) + CPPUNIT_TEST(rcu_gpb_hash128_4_3_stat) + + CPPUNIT_TEST(rcu_gpt_stdhash) + CPPUNIT_TEST(rcu_gpt_stdhash_stat) + CPPUNIT_TEST(rcu_gpt_stdhash_5_3) + CPPUNIT_TEST(rcu_gpt_stdhash_5_3_stat) + CPPUNIT_TEST(rcu_gpt_hash128) + CPPUNIT_TEST(rcu_gpt_hash128_stat) + CPPUNIT_TEST(rcu_gpt_hash128_4_3) + CPPUNIT_TEST(rcu_gpt_hash128_4_3_stat) + + CPPUNIT_TEST(rcu_shb_stdhash) + CPPUNIT_TEST(rcu_shb_stdhash_stat) + CPPUNIT_TEST(rcu_shb_stdhash_5_3) + CPPUNIT_TEST(rcu_shb_stdhash_5_3_stat) + CPPUNIT_TEST(rcu_shb_hash128) + CPPUNIT_TEST(rcu_shb_hash128_stat) + CPPUNIT_TEST(rcu_shb_hash128_4_3) + CPPUNIT_TEST(rcu_shb_hash128_4_3_stat) + + CPPUNIT_TEST(rcu_sht_stdhash) + CPPUNIT_TEST(rcu_sht_stdhash_stat) + CPPUNIT_TEST(rcu_sht_stdhash_5_3) + CPPUNIT_TEST(rcu_sht_stdhash_5_3_stat) + CPPUNIT_TEST(rcu_sht_hash128) + CPPUNIT_TEST(rcu_sht_hash128_stat) + CPPUNIT_TEST(rcu_sht_hash128_4_3) + CPPUNIT_TEST(rcu_sht_hash128_4_3_stat) CPPUNIT_TEST_SUITE_END() }; diff --git a/tests/test-hdr/set/hdr_multilevel_hashset_rcu_gpb.cpp b/tests/test-hdr/set/hdr_multilevel_hashset_rcu_gpb.cpp new file mode 100644 index 00000000..57fe6464 --- /dev/null +++ b/tests/test-hdr/set/hdr_multilevel_hashset_rcu_gpb.cpp @@ -0,0 +1,206 @@ +//$$CDS-header$$ + +#include "set/hdr_multilevel_hashset.h" +#include +#include +#include "unit/print_multilevel_hashset_stat.h" + +namespace set { + namespace { + typedef cds::urcu::gc> rcu_type; + } // namespace + + void MultiLevelHashSetHdrTest::rcu_gpb_stdhash() + { + typedef size_t hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" ); + test_rcu>(4, 2); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + >::type + > set_type2; + test_rcu>(4, 2); + } + + void MultiLevelHashSetHdrTest::rcu_gpb_hash128() + { + typedef hash128 hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef hash128::less less; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" ); + test_rcu(4, 2); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + , co::less< hash_type::less > + >::type + > set_type2; + test_rcu(4, 2); + } + + void MultiLevelHashSetHdrTest::rcu_gpb_stdhash_stat() + { + typedef size_t hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::multilevel_hashset::stat<> stat; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" ); + test_rcu>(4, 2); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + ,co::stat< cc::multilevel_hashset::stat<>> + >::type + > set_type2; + test_rcu>(4, 2); + } + + void MultiLevelHashSetHdrTest::rcu_gpb_hash128_stat() + { + typedef hash128 hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef hash128::cmp compare; + typedef cc::multilevel_hashset::stat<> stat; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" ); + test_rcu(4, 2); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + ,co::stat< cc::multilevel_hashset::stat<>> + ,co::compare< hash128::cmp > + >::type + > set_type2; + test_rcu(4, 2); + } + + void MultiLevelHashSetHdrTest::rcu_gpb_stdhash_5_3() + { + typedef size_t hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" ); + test_rcu>(5, 3); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + >::type + > set_type2; + test_rcu>(5, 3); + } + + void MultiLevelHashSetHdrTest::rcu_gpb_hash128_4_3() + { + typedef hash128 hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef co::v::sequential_consistent memory_model; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" ); + test_rcu(4, 3); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + ,co::memory_model< co::v::sequential_consistent > + >::type + > set_type2; + test_rcu(4, 3); + } + + void MultiLevelHashSetHdrTest::rcu_gpb_stdhash_5_3_stat() + { + typedef size_t hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::multilevel_hashset::stat<> stat; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" ); + test_rcu>(5, 3); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + ,co::stat< cc::multilevel_hashset::stat<>> + >::type + > set_type2; + test_rcu>(5, 3); + } + + void MultiLevelHashSetHdrTest::rcu_gpb_hash128_4_3_stat() + { + typedef hash128 hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::multilevel_hashset::stat<> stat; + typedef hash128::less less; + typedef hash128::cmp compare; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" ); + test_rcu(4, 3); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + , co::stat< cc::multilevel_hashset::stat<>> + , co::less< hash_type::less > + , co::compare< hash128::cmp > + >::type + > set_type2; + test_rcu(4, 3); + } +} // namespace set diff --git a/tests/test-hdr/set/hdr_multilevel_hashset_rcu_gpi.cpp b/tests/test-hdr/set/hdr_multilevel_hashset_rcu_gpi.cpp new file mode 100644 index 00000000..8f49d77a --- /dev/null +++ b/tests/test-hdr/set/hdr_multilevel_hashset_rcu_gpi.cpp @@ -0,0 +1,206 @@ +//$$CDS-header$$ + +#include "set/hdr_multilevel_hashset.h" +#include +#include +#include "unit/print_multilevel_hashset_stat.h" + +namespace set { + namespace { + typedef cds::urcu::gc> rcu_type; + } // namespace + + void MultiLevelHashSetHdrTest::rcu_gpi_stdhash() + { + typedef size_t hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" ); + test_rcu>(4, 2); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + >::type + > set_type2; + test_rcu>(4, 2); + } + + void MultiLevelHashSetHdrTest::rcu_gpi_hash128() + { + typedef hash128 hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef hash128::less less; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" ); + test_rcu(4, 2); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + , co::less< hash_type::less > + >::type + > set_type2; + test_rcu(4, 2); + } + + void MultiLevelHashSetHdrTest::rcu_gpi_stdhash_stat() + { + typedef size_t hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::multilevel_hashset::stat<> stat; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" ); + test_rcu>(4, 2); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + ,co::stat< cc::multilevel_hashset::stat<>> + >::type + > set_type2; + test_rcu>(4, 2); + } + + void MultiLevelHashSetHdrTest::rcu_gpi_hash128_stat() + { + typedef hash128 hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef hash128::cmp compare; + typedef cc::multilevel_hashset::stat<> stat; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" ); + test_rcu(4, 2); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + ,co::stat< cc::multilevel_hashset::stat<>> + ,co::compare< hash128::cmp > + >::type + > set_type2; + test_rcu(4, 2); + } + + void MultiLevelHashSetHdrTest::rcu_gpi_stdhash_5_3() + { + typedef size_t hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" ); + test_rcu>(5, 3); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + >::type + > set_type2; + test_rcu>(5, 3); + } + + void MultiLevelHashSetHdrTest::rcu_gpi_hash128_4_3() + { + typedef hash128 hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef co::v::sequential_consistent memory_model; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" ); + test_rcu(4, 3); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + ,co::memory_model< co::v::sequential_consistent > + >::type + > set_type2; + test_rcu(4, 3); + } + + void MultiLevelHashSetHdrTest::rcu_gpi_stdhash_5_3_stat() + { + typedef size_t hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::multilevel_hashset::stat<> stat; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" ); + test_rcu>(5, 3); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + ,co::stat< cc::multilevel_hashset::stat<>> + >::type + > set_type2; + test_rcu>(5, 3); + } + + void MultiLevelHashSetHdrTest::rcu_gpi_hash128_4_3_stat() + { + typedef hash128 hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::multilevel_hashset::stat<> stat; + typedef hash128::less less; + typedef hash128::cmp compare; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" ); + test_rcu(4, 3); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + , co::stat< cc::multilevel_hashset::stat<>> + , co::less< hash_type::less > + , co::compare< hash128::cmp > + >::type + > set_type2; + test_rcu(4, 3); + } +} // namespace set diff --git a/tests/test-hdr/set/hdr_multilevel_hashset_rcu_gpt.cpp b/tests/test-hdr/set/hdr_multilevel_hashset_rcu_gpt.cpp new file mode 100644 index 00000000..400ff185 --- /dev/null +++ b/tests/test-hdr/set/hdr_multilevel_hashset_rcu_gpt.cpp @@ -0,0 +1,206 @@ +//$$CDS-header$$ + +#include "set/hdr_multilevel_hashset.h" +#include +#include +#include "unit/print_multilevel_hashset_stat.h" + +namespace set { + namespace { + typedef cds::urcu::gc> rcu_type; + } // namespace + + void MultiLevelHashSetHdrTest::rcu_gpt_stdhash() + { + typedef size_t hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" ); + test_rcu>(4, 2); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + >::type + > set_type2; + test_rcu>(4, 2); + } + + void MultiLevelHashSetHdrTest::rcu_gpt_hash128() + { + typedef hash128 hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef hash128::less less; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" ); + test_rcu(4, 2); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + , co::less< hash_type::less > + >::type + > set_type2; + test_rcu(4, 2); + } + + void MultiLevelHashSetHdrTest::rcu_gpt_stdhash_stat() + { + typedef size_t hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::multilevel_hashset::stat<> stat; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" ); + test_rcu>(4, 2); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + ,co::stat< cc::multilevel_hashset::stat<>> + >::type + > set_type2; + test_rcu>(4, 2); + } + + void MultiLevelHashSetHdrTest::rcu_gpt_hash128_stat() + { + typedef hash128 hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef hash128::cmp compare; + typedef cc::multilevel_hashset::stat<> stat; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" ); + test_rcu(4, 2); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + ,co::stat< cc::multilevel_hashset::stat<>> + ,co::compare< hash128::cmp > + >::type + > set_type2; + test_rcu(4, 2); + } + + void MultiLevelHashSetHdrTest::rcu_gpt_stdhash_5_3() + { + typedef size_t hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" ); + test_rcu>(5, 3); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + >::type + > set_type2; + test_rcu>(5, 3); + } + + void MultiLevelHashSetHdrTest::rcu_gpt_hash128_4_3() + { + typedef hash128 hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef co::v::sequential_consistent memory_model; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" ); + test_rcu(4, 3); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + ,co::memory_model< co::v::sequential_consistent > + >::type + > set_type2; + test_rcu(4, 3); + } + + void MultiLevelHashSetHdrTest::rcu_gpt_stdhash_5_3_stat() + { + typedef size_t hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::multilevel_hashset::stat<> stat; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" ); + test_rcu>(5, 3); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + ,co::stat< cc::multilevel_hashset::stat<>> + >::type + > set_type2; + test_rcu>(5, 3); + } + + void MultiLevelHashSetHdrTest::rcu_gpt_hash128_4_3_stat() + { + typedef hash128 hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::multilevel_hashset::stat<> stat; + typedef hash128::less less; + typedef hash128::cmp compare; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" ); + test_rcu(4, 3); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + , co::stat< cc::multilevel_hashset::stat<>> + , co::less< hash_type::less > + , co::compare< hash128::cmp > + >::type + > set_type2; + test_rcu(4, 3); + } +} // namespace set diff --git a/tests/test-hdr/set/hdr_multilevel_hashset_rcu_shb.cpp b/tests/test-hdr/set/hdr_multilevel_hashset_rcu_shb.cpp new file mode 100644 index 00000000..319d9235 --- /dev/null +++ b/tests/test-hdr/set/hdr_multilevel_hashset_rcu_shb.cpp @@ -0,0 +1,224 @@ +//$$CDS-header$$ + +#include "set/hdr_multilevel_hashset.h" +#include +#include +#include "unit/print_multilevel_hashset_stat.h" + +namespace set { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + namespace { + typedef cds::urcu::gc> rcu_type; + } // namespace +#endif + + void MultiLevelHashSetHdrTest::rcu_shb_stdhash() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" ); + test_rcu>(4, 2); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + >::type + > set_type2; + test_rcu>(4, 2); +#endif + } + + void MultiLevelHashSetHdrTest::rcu_shb_hash128() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef hash128 hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef hash128::less less; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" ); + test_rcu(4, 2); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + , co::less< hash_type::less > + >::type + > set_type2; + test_rcu(4, 2); +#endif + } + + void MultiLevelHashSetHdrTest::rcu_shb_stdhash_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::multilevel_hashset::stat<> stat; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" ); + test_rcu>(4, 2); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + ,co::stat< cc::multilevel_hashset::stat<>> + >::type + > set_type2; + test_rcu>(4, 2); +#endif + } + + void MultiLevelHashSetHdrTest::rcu_shb_hash128_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef hash128 hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef hash128::cmp compare; + typedef cc::multilevel_hashset::stat<> stat; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" ); + test_rcu(4, 2); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + ,co::stat< cc::multilevel_hashset::stat<>> + ,co::compare< hash128::cmp > + >::type + > set_type2; + test_rcu(4, 2); +#endif + } + + void MultiLevelHashSetHdrTest::rcu_shb_stdhash_5_3() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" ); + test_rcu>(5, 3); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + >::type + > set_type2; + test_rcu>(5, 3); +#endif + } + + void MultiLevelHashSetHdrTest::rcu_shb_hash128_4_3() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef hash128 hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef co::v::sequential_consistent memory_model; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" ); + test_rcu(4, 3); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + ,co::memory_model< co::v::sequential_consistent > + >::type + > set_type2; + test_rcu(4, 3); +#endif + } + + void MultiLevelHashSetHdrTest::rcu_shb_stdhash_5_3_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::multilevel_hashset::stat<> stat; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" ); + test_rcu>(5, 3); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + ,co::stat< cc::multilevel_hashset::stat<>> + >::type + > set_type2; + test_rcu>(5, 3); +#endif + } + + void MultiLevelHashSetHdrTest::rcu_shb_hash128_4_3_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef hash128 hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::multilevel_hashset::stat<> stat; + typedef hash128::less less; + typedef hash128::cmp compare; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" ); + test_rcu(4, 3); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + , co::stat< cc::multilevel_hashset::stat<>> + , co::less< hash_type::less > + , co::compare< hash128::cmp > + >::type + > set_type2; + test_rcu(4, 3); +#endif + } +} // namespace set diff --git a/tests/test-hdr/set/hdr_multilevel_hashset_rcu_sht.cpp b/tests/test-hdr/set/hdr_multilevel_hashset_rcu_sht.cpp new file mode 100644 index 00000000..34415de5 --- /dev/null +++ b/tests/test-hdr/set/hdr_multilevel_hashset_rcu_sht.cpp @@ -0,0 +1,224 @@ +//$$CDS-header$$ + +#include "set/hdr_multilevel_hashset.h" +#include +#include +#include "unit/print_multilevel_hashset_stat.h" + +namespace set { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + namespace { + typedef cds::urcu::gc> rcu_type; + } // namespace +#endif + + void MultiLevelHashSetHdrTest::rcu_sht_stdhash() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" ); + test_rcu>(4, 2); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + >::type + > set_type2; + test_rcu>(4, 2); +#endif + } + + void MultiLevelHashSetHdrTest::rcu_sht_hash128() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef hash128 hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef hash128::less less; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" ); + test_rcu(4, 2); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + , co::less< hash_type::less > + >::type + > set_type2; + test_rcu(4, 2); +#endif + } + + void MultiLevelHashSetHdrTest::rcu_sht_stdhash_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::multilevel_hashset::stat<> stat; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" ); + test_rcu>(4, 2); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + ,co::stat< cc::multilevel_hashset::stat<>> + >::type + > set_type2; + test_rcu>(4, 2); +#endif + } + + void MultiLevelHashSetHdrTest::rcu_sht_hash128_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef hash128 hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef hash128::cmp compare; + typedef cc::multilevel_hashset::stat<> stat; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" ); + test_rcu(4, 2); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + ,co::stat< cc::multilevel_hashset::stat<>> + ,co::compare< hash128::cmp > + >::type + > set_type2; + test_rcu(4, 2); +#endif + } + + void MultiLevelHashSetHdrTest::rcu_sht_stdhash_5_3() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" ); + test_rcu>(5, 3); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + >::type + > set_type2; + test_rcu>(5, 3); +#endif + } + + void MultiLevelHashSetHdrTest::rcu_sht_hash128_4_3() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef hash128 hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef co::v::sequential_consistent memory_model; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" ); + test_rcu(4, 3); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + ,co::memory_model< co::v::sequential_consistent > + >::type + > set_type2; + test_rcu(4, 3); +#endif + } + + void MultiLevelHashSetHdrTest::rcu_sht_stdhash_5_3_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::multilevel_hashset::stat<> stat; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" ); + test_rcu>(5, 3); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + ,co::stat< cc::multilevel_hashset::stat<>> + >::type + > set_type2; + test_rcu>(5, 3); +#endif + } + + void MultiLevelHashSetHdrTest::rcu_sht_hash128_4_3_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef hash128 hash_type; + + struct traits: public cc::multilevel_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::multilevel_hashset::stat<> stat; + typedef hash128::less less; + typedef hash128::cmp compare; + }; + typedef cc::MultiLevelHashSet< rcu_type, Item, traits > set_type; + static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" ); + test_rcu(4, 3); + + typedef cc::MultiLevelHashSet< + rcu_type, + Item, + typename cc::multilevel_hashset::make_traits< + cc::multilevel_hashset::hash_accessor< get_hash> + , co::stat< cc::multilevel_hashset::stat<>> + , co::less< hash_type::less > + , co::compare< hash128::cmp > + >::type + > set_type2; + test_rcu(4, 3); +#endif + } +} // namespace set