From: khizmax Date: Tue, 20 Oct 2015 03:57:57 +0000 (+0300) Subject: Renamed MultiLevelHashSet/Map to FeldmanHashSet/Map X-Git-Tag: v2.1.0~88 X-Git-Url: http://plrg.eecs.uci.edu/git/?p=libcds.git;a=commitdiff_plain;h=87974cb23acebee8e4f679d922e264cc08a9a4eb Renamed MultiLevelHashSet/Map to FeldmanHashSet/Map --- diff --git a/cds/container/details/feldman_hashmap_base.h b/cds/container/details/feldman_hashmap_base.h new file mode 100644 index 00000000..20eab6b3 --- /dev/null +++ b/cds/container/details/feldman_hashmap_base.h @@ -0,0 +1,325 @@ +//$$CDS-header$$ + +#ifndef CDSLIB_CONTAINER_DETAILS_FELDMAN_HASHMAP_BASE_H +#define CDSLIB_CONTAINER_DETAILS_FELDMAN_HASHMAP_BASE_H + +#include +#include +#include + +namespace cds { namespace container { + /// \p FeldmanHashMap related definitions + /** @ingroup cds_nonintrusive_helper + */ + namespace feldman_hashmap { + /// \p FeldmanHashMap internal statistics, see cds::intrusive::feldman_hashset::stat + template + using stat = cds::intrusive::feldman_hashset::stat< EventCounter >; + + /// \p FeldmanHashMap empty internal statistics + typedef cds::intrusive::feldman_hashset::empty_stat empty_stat; + + /// Bit-wise memcmp-based comparator for hash value \p T + template + using bitwise_compare = cds::intrusive::feldman_hashset::bitwise_compare< T >; + + /// \p FeldmanHashMap traits + struct traits + { + /// Hash functor, default is \p opt::none + /** + \p FeldmanHashMap may use any hash functor converting a key to + fixed-sized bit-string, for example, SHA1, SHA2, + MurmurHash, + CityHash + or its successor FarmHash. + + If you use a fixed-sized key you may use it directly instead of a hash. + In such case \p %traits::hash should be specified as \p opt::none. + However, if you want to use the hash values or if your key type is not fixed-sized + you must specify a proper hash functor in your traits. + For example: + fixed-sized key - IP4 address map + @code + // Key - IP address + struct ip4_address { + uint8_t ip[4]; + }; + + // IP compare + struct ip4_cmp { + int operator()( ip4_address const& lhs, ip4_address const& rhs ) const + { + return memcmp( &lhs, &rhs, sizeof(lhs)); + } + }; + + // Value - statistics for the IP address + struct statistics { + // ... + }; + + // Traits + // Key type (ip4_addr) is fixed-sized so we may use the map without any hash functor + struct ip4_map_traits: public cds::container::multilevl_hashmap::traits + { + typedef ip4_cmp compare; + }; + + // IP4 address - statistics map + typedef cds::container::FeldmanHashMap< cds::gc::HP, ip4_address, statistics, ip4_map_traits > ip4_map; + @endcode + + variable-size key requires a hash functor: URL map + @code + // Value - statistics for the URL + struct statistics { + // ... + }; + + // Traits + // Key type (std::string) is variable-sized so we must provide a hash functor in our traits + // We do not specify any comparing predicate (less or compare) so std::less will be used by default + struct url_map_traits: public cds::container::multilevl_hashmap::traits + { + typedef std::hash hash; + }; + + // URL statistics map + typedef cds::container::FeldmanHashMap< cds::gc::HP, std::string, statistics, url_map_traits > url_map; + @endcode + */ + typedef opt::none hash; + + /// Hash comparing functor + /** + @copydetails cds::intrusive::feldman_hashset::traits::compare + */ + typedef cds::opt::none compare; + + /// Specifies binary predicate used for hash compare. + /** + @copydetails cds::intrusive::feldman_hashset::traits::less + */ + typedef cds::opt::none less; + + /// Item counter + /** + @copydetails cds::intrusive::feldman_hashset::traits::item_counter + */ + typedef cds::atomicity::item_counter item_counter; + + /// Item allocator + /** + Default is \ref CDS_DEFAULT_ALLOCATOR + */ + typedef CDS_DEFAULT_ALLOCATOR allocator; + + /// Array node allocator + /** + @copydetails cds::intrusive::feldman_hashset::traits::node_allocator + */ + typedef CDS_DEFAULT_ALLOCATOR node_allocator; + + /// C++ memory ordering model + /** + @copydetails cds::intrusive::feldman_hashset::traits::memory_model + */ + typedef cds::opt::v::relaxed_ordering memory_model; + + /// Back-off strategy + typedef cds::backoff::Default back_off; + + /// Internal statistics + /** + @copydetails cds::intrusive::feldman_hashset::traits::stat + */ + typedef empty_stat stat; + + /// RCU deadlock checking policy (only for \ref cds_container_FeldmanHashMap_rcu "RCU-based FeldmanHashMap") + /** + @copydetails cds::intrusive::feldman_hashset::traits::rcu_check_deadlock + */ + typedef cds::opt::v::rcu_throw_deadlock rcu_check_deadlock; + }; + + /// Metafunction converting option list to \p feldman_hashmap::traits + /** + Supported \p Options are: + - \p opt::hash - a hash functor, default is \p std::hash + @copydetails traits::hash + - \p opt::allocator - item allocator + @copydetails traits::allocator + - \p opt::node_allocator - array node allocator. + @copydetails traits::node_allocator + - \p opt::compare - hash comparison functor. No default functor is provided. + If the option is not specified, the \p opt::less is used. + - \p opt::less - specifies binary predicate used for hash comparison. + @copydetails cds::container::feldman_hashmap::traits::less + - \p opt::back_off - back-off strategy used. If the option is not specified, the \p cds::backoff::Default is used. + - \p opt::item_counter - the type of item counting feature. + @copydetails cds::container::feldman_hashmap::traits::item_counter + - \p opt::memory_model - C++ memory ordering model. Can be \p opt::v::relaxed_ordering (relaxed memory model, the default) + or \p opt::v::sequential_consistent (sequentially consisnent memory model). + - \p opt::stat - internal statistics. By default, it is disabled (\p feldman_hashmap::empty_stat). + To enable it use \p feldman_hashmap::stat + - \p opt::rcu_check_deadlock - a deadlock checking policy for \ref cds_intrusive_FeldmanHashSet_rcu "RCU-based FeldmanHashSet" + Default is \p opt::v::rcu_throw_deadlock + */ + template + struct make_traits + { +# ifdef CDS_DOXYGEN_INVOKED + typedef implementation_defined type ; ///< Metafunction result +# else + typedef typename cds::opt::make_options< + typename cds::opt::find_type_traits< traits, Options... >::type + ,Options... + >::type type; +# endif + }; + } // namespace feldman_hashmap + + //@cond + // Forward declaration + template < class GC, typename Key, typename T, class Traits = feldman_hashmap::traits > + class FeldmanHashMap; + //@endcond + + //@cond + namespace details { + + template + struct hash_selector + { + typedef Key key_type; + typedef Value mapped_type; + typedef Hash hasher; + + typedef typename std::decay< + typename std::remove_reference< + decltype(hasher()(std::declval())) + >::type + >::type hash_type; + + struct node_type + { + std::pair< key_type const, mapped_type> m_Value; + hash_type const m_hash; + + node_type() = delete; + node_type(node_type const&) = delete; + + template + node_type(hasher& h, Q const& key) + : m_Value(std::move(std::make_pair(key, mapped_type()))) + , m_hash(h(m_Value.first)) + {} + + template + node_type(hasher& h, Q const& key, U const& val) + : m_Value(std::move(std::make_pair(key, mapped_type(val)))) + , m_hash(h(m_Value.first)) + {} + + template + node_type(hasher& h, Q&& key, Args&&... args) + : m_Value(std::move(std::make_pair(std::forward(key), std::move(mapped_type(std::forward(args)...))))) + , m_hash(h(m_Value.first)) + {} + }; + + struct hash_accessor + { + hash_type const& operator()(node_type const& node) const + { + return node.m_hash; + } + }; + }; + + template + struct hash_selector + { + typedef Key key_type; + typedef Value mapped_type; + + struct hasher { + key_type const& operator()(key_type const& k) const + { + return k; + } + }; + typedef key_type hash_type; + + struct node_type + { + std::pair< key_type const, mapped_type> m_Value; + + node_type() = delete; + node_type(node_type const&) = delete; + + template + node_type(hasher /*h*/, Q const& key) + : m_Value(std::move(std::make_pair(key, mapped_type()))) + {} + + template + node_type(hasher /*h*/, Q const& key, U const& val) + : m_Value(std::move(std::make_pair(key, mapped_type(val)))) + {} + + template + node_type(hasher /*h*/, Q&& key, Args&&... args) + : m_Value(std::move(std::make_pair(std::forward(key), std::move(mapped_type(std::forward(args)...))))) + {} + }; + + struct hash_accessor + { + hash_type const& operator()(node_type const& node) const + { + return node.m_Value.first; + } + }; + }; + + template + struct make_feldman_hashmap + { + typedef GC gc; + typedef Key key_type; + typedef T mapped_type; + typedef Traits original_traits; + + + typedef hash_selector< key_type, mapped_type, typename original_traits::hash > select; + typedef typename select::hasher hasher; + typedef typename select::hash_type hash_type; + typedef typename select::node_type node_type; + + typedef cds::details::Allocator< node_type, typename original_traits::allocator > cxx_node_allocator; + + struct node_disposer + { + void operator()( node_type * p ) const + { + cxx_node_allocator().Delete( p ); + } + }; + + struct intrusive_traits: public original_traits + { + typedef typename select::hash_accessor hash_accessor; + typedef node_disposer disposer; + }; + + // Metafunction result + typedef cds::intrusive::FeldmanHashSet< GC, node_type, intrusive_traits > type; + }; + } // namespace details + //@endcond + +}} // namespace cds::container + +#endif // #ifndef CDSLIB_CONTAINER_DETAILS_FELDMAN_HASHMAP_BASE_H diff --git a/cds/container/details/feldman_hashset_base.h b/cds/container/details/feldman_hashset_base.h new file mode 100644 index 00000000..2f319627 --- /dev/null +++ b/cds/container/details/feldman_hashset_base.h @@ -0,0 +1,169 @@ +//$$CDS-header$$ + +#ifndef CDSLIB_CONTAINER_DETAILS_FELDMAN_HASHSET_BASE_H +#define CDSLIB_CONTAINER_DETAILS_FELDMAN_HASHSET_BASE_H + +#include +#include + +namespace cds { namespace container { + /// \p FeldmanHashSet related definitions + /** @ingroup cds_nonintrusive_helper + */ + namespace feldman_hashset { + /// Hash accessor option + /** + @copydetails cds::intrusive::feldman_hashset::traits::hash_accessor + */ + template + using hash_accessor = cds::intrusive::feldman_hashset::hash_accessor< Accessor >; + + /// \p FeldmanHashSet internal statistics, see cds::intrusive::feldman_hashset::stat + template + using stat = cds::intrusive::feldman_hashset::stat< EventCounter >; + + /// \p FeldmanHashSet empty internal statistics + typedef cds::intrusive::feldman_hashset::empty_stat empty_stat; + + /// Bit-wise memcmp-based comparator for hash value \p T + template + using bitwise_compare = cds::intrusive::feldman_hashset::bitwise_compare< T >; + + /// \p FeldmanHashSet traits + struct traits + { + /// Mandatory functor to get hash value from data node + /** + @copydetails cds::intrusive::feldman_hashset::traits::hash_accessor + */ + typedef cds::opt::none hash_accessor; + + /// Hash comparing functor + /** + @copydetails cds::intrusive::feldman_hashset::traits::compare + */ + typedef cds::opt::none compare; + + /// Specifies binary predicate used for hash compare. + /** + @copydetails cds::intrusive::feldman_hashset::traits::less + */ + typedef cds::opt::none less; + + /// Item counter + /** + @copydetails cds::intrusive::feldman_hashset::traits::item_counter + */ + typedef cds::atomicity::item_counter item_counter; + + /// Item allocator + /** + Default is \ref CDS_DEFAULT_ALLOCATOR + */ + typedef CDS_DEFAULT_ALLOCATOR allocator; + + /// Array node allocator + /** + @copydetails cds::intrusive::feldman_hashset::traits::node_allocator + */ + typedef CDS_DEFAULT_ALLOCATOR node_allocator; + + /// C++ memory ordering model + /** + @copydetails cds::intrusive::feldman_hashset::traits::memory_model + */ + typedef cds::opt::v::relaxed_ordering memory_model; + + /// Back-off strategy + typedef cds::backoff::Default back_off; + + /// Internal statistics + /** + @copydetails cds::intrusive::feldman_hashset::traits::stat + */ + typedef empty_stat stat; + + /// RCU deadlock checking policy (only for \ref cds_container_FeldmanHashSet_rcu "RCU-based FeldmanHashSet") + /** + @copydetails cds::intrusive::feldman_hashset::traits::rcu_check_deadlock + */ + typedef cds::opt::v::rcu_throw_deadlock rcu_check_deadlock; + }; + + /// Metafunction converting option list to \p feldman_hashset::traits + /** + Supported \p Options are: + - \p feldman_hashset::hash_accessor - mandatory option, hash accessor functor. + @copydetails traits::hash_accessor + - \p opt::allocator - item allocator + @copydetails traits::allocator + - \p opt::node_allocator - array node allocator. + @copydetails traits::node_allocator + - \p opt::compare - hash comparison functor. No default functor is provided. + If the option is not specified, the \p opt::less is used. + - \p opt::less - specifies binary predicate used for hash comparison. + @copydetails cds::container::feldman_hashset::traits::less + - \p opt::back_off - back-off strategy used. If the option is not specified, the \p cds::backoff::Default is used. + - \p opt::item_counter - the type of item counting feature. + @copydetails cds::intrusive::feldman_hashset::traits::item_counter + - \p opt::memory_model - C++ memory ordering model. Can be \p opt::v::relaxed_ordering (relaxed memory model, the default) + or \p opt::v::sequential_consistent (sequentially consisnent memory model). + - \p opt::stat - internal statistics. By default, it is disabled (\p feldman_hashset::empty_stat). + To enable it use \p feldman_hashset::stat + - \p opt::rcu_check_deadlock - a deadlock checking policy for \ref cds_intrusive_FeldmanHashSet_rcu "RCU-based FeldmanHashSet" + Default is \p opt::v::rcu_throw_deadlock + */ + template + struct make_traits + { +# ifdef CDS_DOXYGEN_INVOKED + typedef implementation_defined type ; ///< Metafunction result +# else + typedef typename cds::opt::make_options< + typename cds::opt::find_type_traits< traits, Options... >::type + ,Options... + >::type type; +# endif + }; + } // namespace feldman_hashset + + //@cond + // Forward declaration + template < class GC, typename T, class Traits = cds::container::feldman_hashset::traits > + class FeldmanHashSet; + //@endcond + + //@cond + namespace details { + + template + struct make_feldman_hashset + { + typedef GC gc; + typedef T value_type; + typedef Traits original_traits; + + typedef cds::details::Allocator< value_type, typename original_traits::allocator > cxx_node_allocator; + + struct node_disposer + { + void operator()( value_type * p ) const + { + cxx_node_allocator().Delete( p ); + } + }; + + struct intrusive_traits: public original_traits + { + typedef node_disposer disposer; + }; + + // Metafunction result + typedef cds::intrusive::FeldmanHashSet< GC, T, intrusive_traits > type; + }; + } // namespace details + //@endcond + +}} // namespace cds::container + +#endif // #ifndef CDSLIB_CONTAINER_DETAILS_FELDMAN_HASHSET_BASE_H diff --git a/cds/container/details/multilevel_hashmap_base.h b/cds/container/details/multilevel_hashmap_base.h deleted file mode 100644 index b06b5cb7..00000000 --- a/cds/container/details/multilevel_hashmap_base.h +++ /dev/null @@ -1,325 +0,0 @@ -//$$CDS-header$$ - -#ifndef CDSLIB_CONTAINER_DETAILS_MULTILEVEL_HASHMAP_BASE_H -#define CDSLIB_CONTAINER_DETAILS_MULTILEVEL_HASHMAP_BASE_H - -#include -#include -#include - -namespace cds { namespace container { - /// \p MultiLevelHashMap related definitions - /** @ingroup cds_nonintrusive_helper - */ - namespace multilevel_hashmap { - /// \p MultiLevelHashMap internal statistics, see cds::intrusive::multilevel_hashset::stat - template - using stat = cds::intrusive::multilevel_hashset::stat< EventCounter >; - - /// \p MultiLevelHashMap empty internal statistics - typedef cds::intrusive::multilevel_hashset::empty_stat empty_stat; - - /// Bit-wise memcmp-based comparator for hash value \p T - template - using bitwise_compare = cds::intrusive::multilevel_hashset::bitwise_compare< T >; - - /// \p MultiLevelHashMap traits - struct traits - { - /// Hash functor, default is \p opt::none - /** - \p MultiLevelHashMap may use any hash functor converting a key to - fixed-sized bit-string, for example, SHA1, SHA2, - MurmurHash, - CityHash - or its successor FarmHash. - - If you use a fixed-sized key you may use it directly instead of a hash. - In such case \p %traits::hash should be specified as \p opt::none. - However, if you want to use the hash values or if your key type is not fixed-sized - you must specify a proper hash functor in your traits. - For example: - fixed-sized key - IP4 address map - @code - // Key - IP address - struct ip4_address { - uint8_t ip[4]; - }; - - // IP compare - struct ip4_cmp { - int operator()( ip4_address const& lhs, ip4_address const& rhs ) const - { - return memcmp( &lhs, &rhs, sizeof(lhs)); - } - }; - - // Value - statistics for the IP address - struct statistics { - // ... - }; - - // Traits - // Key type (ip4_addr) is fixed-sized so we may use the map without any hash functor - struct ip4_map_traits: public cds::container::multilevl_hashmap::traits - { - typedef ip4_cmp compare; - }; - - // IP4 address - statistics map - typedef cds::container::MultiLevelHashMap< cds::gc::HP, ip4_address, statistics, ip4_map_traits > ip4_map; - @endcode - - variable-size key requires a hash functor: URL map - @code - // Value - statistics for the URL - struct statistics { - // ... - }; - - // Traits - // Key type (std::string) is variable-sized so we must provide a hash functor in our traits - // We do not specify any comparing predicate (less or compare) so std::less will be used by default - struct url_map_traits: public cds::container::multilevl_hashmap::traits - { - typedef std::hash hash; - }; - - // URL statistics map - typedef cds::container::MultiLevelHashMap< cds::gc::HP, std::string, statistics, url_map_traits > url_map; - @endcode - */ - typedef opt::none hash; - - /// Hash comparing functor - /** - @copydetails cds::intrusive::multilevel_hashset::traits::compare - */ - typedef cds::opt::none compare; - - /// Specifies binary predicate used for hash compare. - /** - @copydetails cds::intrusive::multilevel_hashset::traits::less - */ - typedef cds::opt::none less; - - /// Item counter - /** - @copydetails cds::intrusive::multilevel_hashset::traits::item_counter - */ - typedef cds::atomicity::item_counter item_counter; - - /// Item allocator - /** - Default is \ref CDS_DEFAULT_ALLOCATOR - */ - typedef CDS_DEFAULT_ALLOCATOR allocator; - - /// Array node allocator - /** - @copydetails cds::intrusive::multilevel_hashset::traits::node_allocator - */ - typedef CDS_DEFAULT_ALLOCATOR node_allocator; - - /// C++ memory ordering model - /** - @copydetails cds::intrusive::multilevel_hashset::traits::memory_model - */ - typedef cds::opt::v::relaxed_ordering memory_model; - - /// Back-off strategy - typedef cds::backoff::Default back_off; - - /// Internal statistics - /** - @copydetails cds::intrusive::multilevel_hashset::traits::stat - */ - typedef empty_stat stat; - - /// RCU deadlock checking policy (only for \ref cds_container_MultilevelHashMap_rcu "RCU-based MultilevelHashMap") - /** - @copydetails cds::intrusive::multilevel_hashset::traits::rcu_check_deadlock - */ - typedef cds::opt::v::rcu_throw_deadlock rcu_check_deadlock; - }; - - /// Metafunction converting option list to \p multilevel_hashmap::traits - /** - Supported \p Options are: - - \p opt::hash - a hash functor, default is \p std::hash - @copydetails traits::hash - - \p opt::allocator - item allocator - @copydetails traits::allocator - - \p opt::node_allocator - array node allocator. - @copydetails traits::node_allocator - - \p opt::compare - hash comparison functor. No default functor is provided. - If the option is not specified, the \p opt::less is used. - - \p opt::less - specifies binary predicate used for hash comparison. - @copydetails cds::container::multilevel_hashmap::traits::less - - \p opt::back_off - back-off strategy used. If the option is not specified, the \p cds::backoff::Default is used. - - \p opt::item_counter - the type of item counting feature. - @copydetails cds::container::multilevel_hashmap::traits::item_counter - - \p opt::memory_model - C++ memory ordering model. Can be \p opt::v::relaxed_ordering (relaxed memory model, the default) - or \p opt::v::sequential_consistent (sequentially consisnent memory model). - - \p opt::stat - internal statistics. By default, it is disabled (\p multilevel_hashmap::empty_stat). - To enable it use \p multilevel_hashmap::stat - - \p opt::rcu_check_deadlock - a deadlock checking policy for \ref cds_intrusive_MultilevelHashSet_rcu "RCU-based MultilevelHashSet" - Default is \p opt::v::rcu_throw_deadlock - */ - template - struct make_traits - { -# ifdef CDS_DOXYGEN_INVOKED - typedef implementation_defined type ; ///< Metafunction result -# else - typedef typename cds::opt::make_options< - typename cds::opt::find_type_traits< traits, Options... >::type - ,Options... - >::type type; -# endif - }; - } // namespace multilevel_hashmap - - //@cond - // Forward declaration - template < class GC, typename Key, typename T, class Traits = multilevel_hashmap::traits > - class MultiLevelHashMap; - //@endcond - - //@cond - namespace details { - - template - struct hash_selector - { - typedef Key key_type; - typedef Value mapped_type; - typedef Hash hasher; - - typedef typename std::decay< - typename std::remove_reference< - decltype(hasher()(std::declval())) - >::type - >::type hash_type; - - struct node_type - { - std::pair< key_type const, mapped_type> m_Value; - hash_type const m_hash; - - node_type() = delete; - node_type(node_type const&) = delete; - - template - node_type(hasher& h, Q const& key) - : m_Value(std::move(std::make_pair(key, mapped_type()))) - , m_hash(h(m_Value.first)) - {} - - template - node_type(hasher& h, Q const& key, U const& val) - : m_Value(std::move(std::make_pair(key, mapped_type(val)))) - , m_hash(h(m_Value.first)) - {} - - template - node_type(hasher& h, Q&& key, Args&&... args) - : m_Value(std::move(std::make_pair(std::forward(key), std::move(mapped_type(std::forward(args)...))))) - , m_hash(h(m_Value.first)) - {} - }; - - struct hash_accessor - { - hash_type const& operator()(node_type const& node) const - { - return node.m_hash; - } - }; - }; - - template - struct hash_selector - { - typedef Key key_type; - typedef Value mapped_type; - - struct hasher { - key_type const& operator()(key_type const& k) const - { - return k; - } - }; - typedef key_type hash_type; - - struct node_type - { - std::pair< key_type const, mapped_type> m_Value; - - node_type() = delete; - node_type(node_type const&) = delete; - - template - node_type(hasher /*h*/, Q const& key) - : m_Value(std::move(std::make_pair(key, mapped_type()))) - {} - - template - node_type(hasher /*h*/, Q const& key, U const& val) - : m_Value(std::move(std::make_pair(key, mapped_type(val)))) - {} - - template - node_type(hasher /*h*/, Q&& key, Args&&... args) - : m_Value(std::move(std::make_pair(std::forward(key), std::move(mapped_type(std::forward(args)...))))) - {} - }; - - struct hash_accessor - { - hash_type const& operator()(node_type const& node) const - { - return node.m_Value.first; - } - }; - }; - - template - struct make_multilevel_hashmap - { - typedef GC gc; - typedef Key key_type; - typedef T mapped_type; - typedef Traits original_traits; - - - typedef hash_selector< key_type, mapped_type, typename original_traits::hash > select; - typedef typename select::hasher hasher; - typedef typename select::hash_type hash_type; - typedef typename select::node_type node_type; - - typedef cds::details::Allocator< node_type, typename original_traits::allocator > cxx_node_allocator; - - struct node_disposer - { - void operator()( node_type * p ) const - { - cxx_node_allocator().Delete( p ); - } - }; - - struct intrusive_traits: public original_traits - { - typedef typename select::hash_accessor hash_accessor; - typedef node_disposer disposer; - }; - - // Metafunction result - typedef cds::intrusive::MultiLevelHashSet< GC, node_type, intrusive_traits > type; - }; - } // namespace details - //@endcond - -}} // namespace cds::container - -#endif // #ifndef CDSLIB_CONTAINER_DETAILS_MULTILEVEL_HASHMAP_BASE_H diff --git a/cds/container/details/multilevel_hashset_base.h b/cds/container/details/multilevel_hashset_base.h deleted file mode 100644 index f0c7fca0..00000000 --- a/cds/container/details/multilevel_hashset_base.h +++ /dev/null @@ -1,169 +0,0 @@ -//$$CDS-header$$ - -#ifndef CDSLIB_CONTAINER_DETAILS_MULTILEVEL_HASHSET_BASE_H -#define CDSLIB_CONTAINER_DETAILS_MULTILEVEL_HASHSET_BASE_H - -#include -#include - -namespace cds { namespace container { - /// \p MultiLevelHashSet related definitions - /** @ingroup cds_nonintrusive_helper - */ - namespace multilevel_hashset { - /// Hash accessor option - /** - @copydetails cds::intrusive::multilevel_hashset::traits::hash_accessor - */ - template - using hash_accessor = cds::intrusive::multilevel_hashset::hash_accessor< Accessor >; - - /// \p MultiLevelHashSet internal statistics, see cds::intrusive::multilevel_hashset::stat - template - using stat = cds::intrusive::multilevel_hashset::stat< EventCounter >; - - /// \p MultiLevelHashSet empty internal statistics - typedef cds::intrusive::multilevel_hashset::empty_stat empty_stat; - - /// Bit-wise memcmp-based comparator for hash value \p T - template - using bitwise_compare = cds::intrusive::multilevel_hashset::bitwise_compare< T >; - - /// \p MultiLevelHashSet traits - struct traits - { - /// Mandatory functor to get hash value from data node - /** - @copydetails cds::intrusive::multilevel_hashset::traits::hash_accessor - */ - typedef cds::opt::none hash_accessor; - - /// Hash comparing functor - /** - @copydetails cds::intrusive::multilevel_hashset::traits::compare - */ - typedef cds::opt::none compare; - - /// Specifies binary predicate used for hash compare. - /** - @copydetails cds::intrusive::multilevel_hashset::traits::less - */ - typedef cds::opt::none less; - - /// Item counter - /** - @copydetails cds::intrusive::multilevel_hashset::traits::item_counter - */ - typedef cds::atomicity::item_counter item_counter; - - /// Item allocator - /** - Default is \ref CDS_DEFAULT_ALLOCATOR - */ - typedef CDS_DEFAULT_ALLOCATOR allocator; - - /// Array node allocator - /** - @copydetails cds::intrusive::multilevel_hashset::traits::node_allocator - */ - typedef CDS_DEFAULT_ALLOCATOR node_allocator; - - /// C++ memory ordering model - /** - @copydetails cds::intrusive::multilevel_hashset::traits::memory_model - */ - typedef cds::opt::v::relaxed_ordering memory_model; - - /// Back-off strategy - typedef cds::backoff::Default back_off; - - /// Internal statistics - /** - @copydetails cds::intrusive::multilevel_hashset::traits::stat - */ - typedef empty_stat stat; - - /// RCU deadlock checking policy (only for \ref cds_container_MultilevelHashSet_rcu "RCU-based MultilevelHashSet") - /** - @copydetails cds::intrusive::multilevel_hashset::traits::rcu_check_deadlock - */ - typedef cds::opt::v::rcu_throw_deadlock rcu_check_deadlock; - }; - - /// Metafunction converting option list to \p multilevel_hashset::traits - /** - Supported \p Options are: - - \p multilevel_hashset::hash_accessor - mandatory option, hash accessor functor. - @copydetails traits::hash_accessor - - \p opt::allocator - item allocator - @copydetails traits::allocator - - \p opt::node_allocator - array node allocator. - @copydetails traits::node_allocator - - \p opt::compare - hash comparison functor. No default functor is provided. - If the option is not specified, the \p opt::less is used. - - \p opt::less - specifies binary predicate used for hash comparison. - @copydetails cds::container::multilevel_hashset::traits::less - - \p opt::back_off - back-off strategy used. If the option is not specified, the \p cds::backoff::Default is used. - - \p opt::item_counter - the type of item counting feature. - @copydetails cds::intrusive::multilevel_hashset::traits::item_counter - - \p opt::memory_model - C++ memory ordering model. Can be \p opt::v::relaxed_ordering (relaxed memory model, the default) - or \p opt::v::sequential_consistent (sequentially consisnent memory model). - - \p opt::stat - internal statistics. By default, it is disabled (\p multilevel_hashset::empty_stat). - To enable it use \p multilevel_hashset::stat - - \p opt::rcu_check_deadlock - a deadlock checking policy for \ref cds_intrusive_MultilevelHashSet_rcu "RCU-based MultilevelHashSet" - Default is \p opt::v::rcu_throw_deadlock - */ - template - struct make_traits - { -# ifdef CDS_DOXYGEN_INVOKED - typedef implementation_defined type ; ///< Metafunction result -# else - typedef typename cds::opt::make_options< - typename cds::opt::find_type_traits< traits, Options... >::type - ,Options... - >::type type; -# endif - }; - } // namespace multilevel_hashset - - //@cond - // Forward declaration - template < class GC, typename T, class Traits = cds::container::multilevel_hashset::traits > - class MultiLevelHashSet; - //@endcond - - //@cond - namespace details { - - template - struct make_multilevel_hashset - { - typedef GC gc; - typedef T value_type; - typedef Traits original_traits; - - typedef cds::details::Allocator< value_type, typename original_traits::allocator > cxx_node_allocator; - - struct node_disposer - { - void operator()( value_type * p ) const - { - cxx_node_allocator().Delete( p ); - } - }; - - struct intrusive_traits: public original_traits - { - typedef node_disposer disposer; - }; - - // Metafunction result - typedef cds::intrusive::MultiLevelHashSet< GC, T, intrusive_traits > type; - }; - } // namespace details - //@endcond - -}} // namespace cds::container - -#endif // #ifndef CDSLIB_CONTAINER_DETAILS_MULTILEVEL_HASHSET_BASE_H diff --git a/cds/container/feldman_hashmap_dhp.h b/cds/container/feldman_hashmap_dhp.h new file mode 100644 index 00000000..85ea7af2 --- /dev/null +++ b/cds/container/feldman_hashmap_dhp.h @@ -0,0 +1,9 @@ +//$$CDS-header$$ + +#ifndef CDSLIB_CONTAINER_FELDMAN_HASHMAP_DHP_H +#define CDSLIB_CONTAINER_FELDMAN_HASHMAP_DHP_H + +#include +#include + +#endif // #ifndef CDSLIB_CONTAINER_FELDMAN_HASHMAP_DHP_H diff --git a/cds/container/feldman_hashmap_hp.h b/cds/container/feldman_hashmap_hp.h new file mode 100644 index 00000000..50c66a87 --- /dev/null +++ b/cds/container/feldman_hashmap_hp.h @@ -0,0 +1,9 @@ +//$$CDS-header$$ + +#ifndef CDSLIB_CONTAINER_FELDMAN_HASHMAP_HP_H +#define CDSLIB_CONTAINER_FELDMAN_HASHMAP_HP_H + +#include +#include + +#endif // #ifndef CDSLIB_CONTAINER_FELDMAN_HASHMAP_HP_H diff --git a/cds/container/feldman_hashmap_rcu.h b/cds/container/feldman_hashmap_rcu.h new file mode 100644 index 00000000..501766a3 --- /dev/null +++ b/cds/container/feldman_hashmap_rcu.h @@ -0,0 +1,780 @@ +//$$CDS-header$$ + +#ifndef CDSLIB_CONTAINER_FELDMAN_HASHMAP_RCU_H +#define CDSLIB_CONTAINER_FELDMAN_HASHMAP_RCU_H + +#include +#include + +namespace cds { namespace container { + + /// Hash map based on multi-level array + /** @ingroup cds_nonintrusive_map + @anchor cds_container_FeldmanHashMap_rcu + + Source: + - [2013] Steven Feldman, Pierre LaBorde, Damian Dechev "Concurrent Multi-level Arrays: + Wait-free Extensible Hash Maps" + + See algorithm short description @ref cds_container_FeldmanHashMap_hp "here" + + @note Two important things you should keep in mind when you're using \p %FeldmanHashMap: + - all keys is converted to fixed-size bit-string by hash functor provided. + You can use variable-length keys, for example, \p std::string as a key for \p %FeldmanHashMap, + but real key in the map will be fixed-size hash values of your keys. + For the strings you may 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 such hash values will be the keys in \p %FeldmanHashMap. + If your key is fixed-sized the hash functor is optional, see \p feldman_hashmap::traits::hash for explanation and examples. + - \p %FeldmanHashMap 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 map. \p %FeldmanHashMap does not maintain the key, + it maintains its fixed-size hash value. + + The map supports @ref cds_container_FeldmanHashMap_rcu_iterators "bidirectional thread-safe iterators". + + Template parameters: + - \p RCU - one of \ref cds_urcu_gc "RCU type" + - \p Key - a key type to be stored in the map + - \p T - a value type to be stored in the map + - \p Traits - type traits, the structure based on \p feldman_hashmap::traits or result of \p feldman_hashmap::make_traits metafunction. + + @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. + */ + template < + class RCU + ,typename Key + ,typename T +#ifdef CDS_DOXYGEN_INVOKED + ,class Traits = feldman_hashmap::traits +#else + ,class Traits +#endif + > + class FeldmanHashMap< cds::urcu::gc< RCU >, Key, T, Traits > +#ifdef CDS_DOXYGEN_INVOKED + : protected cds::intrusive::FeldmanHashSet< cds::urcu::gc< RCU >, std::pair, Traits > +#else + : protected cds::container::details::make_feldman_hashmap< cds::urcu::gc< RCU >, Key, T, Traits >::type +#endif + { + //@cond + typedef cds::container::details::make_feldman_hashmap< cds::urcu::gc< RCU >, Key, T, Traits > maker; + typedef typename maker::type base_class; + //@endcond + public: + typedef cds::urcu::gc< RCU > gc; ///< RCU garbage collector + typedef Key key_type; ///< Key type + typedef T mapped_type; ///< Mapped type + typedef std::pair< key_type const, mapped_type> value_type; ///< Key-value pair to be stored in the map + typedef Traits traits; ///< Map traits +#ifdef CDS_DOXYGEN_INVOKED + typedef typename traits::hash hasher; ///< Hash functor, see \p feldman_hashmap::traits::hash +#else + typedef typename maker::hasher hasher; +#endif + + typedef typename maker::hash_type hash_type; ///< Hash type deduced from \p hasher return type + typedef typename base_class::hash_comparator hash_comparator; ///< hash compare functor based on \p Traits::compare and \p Traits::less + 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 + + protected: + //@cond + typedef typename maker::node_type node_type; + typedef typename maker::cxx_node_allocator cxx_node_allocator; + typedef std::unique_ptr< node_type, typename maker::node_disposer > scoped_node_ptr; + typedef typename base_class::check_deadlock_policy check_deadlock_policy; + + struct node_cast + { + value_type * operator()(node_type * p) const + { + return p ? &p->m_Value : nullptr; + } + }; + + public: + /// pointer to extracted node + using exempt_ptr = cds::urcu::exempt_ptr< gc, node_type, value_type, typename base_class::disposer, node_cast >; + + protected: + template + class bidirectional_iterator: public base_class::iterator_base + { + friend class FeldmanHashMap; + typedef typename base_class::iterator_base iterator_base; + + protected: + static CDS_CONSTEXPR bool const c_bConstantIterator = IsConst; + + public: + typedef typename std::conditional< IsConst, value_type const*, value_type*>::type value_ptr; ///< Value pointer + typedef typename std::conditional< IsConst, value_type const&, value_type&>::type value_ref; ///< Value reference + + public: + bidirectional_iterator() CDS_NOEXCEPT + {} + + bidirectional_iterator( bidirectional_iterator const& rhs ) CDS_NOEXCEPT + : iterator_base( rhs ) + {} + + bidirectional_iterator& operator=(bidirectional_iterator const& rhs) CDS_NOEXCEPT + { + iterator_base::operator=( rhs ); + return *this; + } + + bidirectional_iterator& operator++() + { + iterator_base::operator++(); + return *this; + } + + bidirectional_iterator& operator--() + { + iterator_base::operator--(); + return *this; + } + + value_ptr operator ->() const CDS_NOEXCEPT + { + node_type * p = iterator_base::pointer(); + return p ? &p->m_Value : nullptr; + } + + value_ref operator *() const CDS_NOEXCEPT + { + node_type * p = iterator_base::pointer(); + assert( p ); + return p->m_Value; + } + + void release() + { + iterator_base::release(); + } + + template + bool operator ==(bidirectional_iterator const& rhs) const CDS_NOEXCEPT + { + return iterator_base::operator==( rhs ); + } + + template + bool operator !=(bidirectional_iterator const& rhs) const CDS_NOEXCEPT + { + return !( *this == rhs ); + } + + public: // for internal use only! + bidirectional_iterator( base_class const& set, typename base_class::array_node * pNode, size_t idx, bool ) + : iterator_base( set, pNode, idx, false ) + {} + + bidirectional_iterator( base_class const& set, typename base_class::array_node * pNode, size_t idx ) + : iterator_base( set, pNode, idx ) + {} + }; + + /// Reverse bidirectional iterator + template + class reverse_bidirectional_iterator : public base_class::iterator_base + { + friend class FeldmanHashMap; + typedef typename base_class::iterator_base iterator_base; + + public: + typedef typename std::conditional< IsConst, value_type const*, value_type*>::type value_ptr; ///< Value pointer + typedef typename std::conditional< IsConst, value_type const&, value_type&>::type value_ref; ///< Value reference + + public: + reverse_bidirectional_iterator() CDS_NOEXCEPT + : iterator_base() + {} + + reverse_bidirectional_iterator( reverse_bidirectional_iterator const& rhs ) CDS_NOEXCEPT + : iterator_base( rhs ) + {} + + reverse_bidirectional_iterator& operator=( reverse_bidirectional_iterator const& rhs) CDS_NOEXCEPT + { + iterator_base::operator=( rhs ); + return *this; + } + + reverse_bidirectional_iterator& operator++() + { + iterator_base::operator--(); + return *this; + } + + reverse_bidirectional_iterator& operator--() + { + iterator_base::operator++(); + return *this; + } + + value_ptr operator ->() const CDS_NOEXCEPT + { + node_type * p = iterator_base::pointer(); + return p ? &p->m_Value : nullptr; + } + + value_ref operator *() const CDS_NOEXCEPT + { + node_type * p = iterator_base::pointer(); + assert( p ); + return p->m_Value; + } + + void release() + { + iterator_base::release(); + } + + template + bool operator ==(reverse_bidirectional_iterator const& rhs) const + { + return iterator_base::operator==( rhs ); + } + + template + bool operator !=(reverse_bidirectional_iterator const& rhs) + { + return !( *this == rhs ); + } + + public: // for internal use only! + reverse_bidirectional_iterator( base_class const& set, typename base_class::array_node * pNode, size_t idx, bool ) + : iterator_base( set, pNode, idx, false ) + {} + + reverse_bidirectional_iterator( base_class const& set, typename base_class::array_node * pNode, size_t idx ) + : iterator_base( set, pNode, idx, false ) + { + iterator_base::backward(); + } + }; + //@endcond + + public: +#ifdef CDS_DOXYGEN_INVOKED + typedef implementation_defined iterator; ///< @ref cds_container_FeldmanHashMap_rcu_iterators "bidirectional iterator" type + typedef implementation_defined const_iterator; ///< @ref cds_container_FeldmanHashMap_rcu_iterators "bidirectional const iterator" type + typedef implementation_defined reverse_iterator; ///< @ref cds_container_FeldmanHashMap_rcu_iterators "bidirectional reverse iterator" type + typedef implementation_defined const_reverse_iterator; ///< @ref cds_container_FeldmanHashMap_rcu_iterators "bidirectional reverse const iterator" type +#else + typedef bidirectional_iterator iterator; + typedef bidirectional_iterator const_iterator; + typedef reverse_bidirectional_iterator reverse_iterator; + typedef reverse_bidirectional_iterator const_reverse_iterator; +#endif + + protected: + //@cond + hasher m_Hasher; + //@endcond + + public: + /// Creates empty map + /** + @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. + */ + FeldmanHashMap( size_t head_bits = 8, size_t array_bits = 4 ) + : base_class( head_bits, array_bits ) + {} + + /// Destructs the map and frees all data + ~FeldmanHashMap() + {} + + /// Inserts new element with key and default value + /** + The function creates an element with \p key and default value, and then inserts the node created into the map. + + Preconditions: + - The \p key_type should be constructible from a value of type \p K. + In trivial case, \p K is equal to \p key_type. + - The \p mapped_type should be default-constructible. + + Returns \p true if inserting successful, \p false otherwise. + + The function locks RCU internally. + */ + template + bool insert( K&& key ) + { + scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward(key) )); + if ( base_class::insert( *sp )) { + sp.release(); + return true; + } + return false; + } + + /// Inserts new element + /** + The function creates a node with copy of \p val value + and then inserts the node created into the map. + + Preconditions: + - The \p key_type should be constructible from \p key of type \p K. + - The \p value_type should be constructible from \p val of type \p V. + + Returns \p true if \p val is inserted into the map, \p false otherwise. + + The function locks RCU internally. + */ + template + bool insert( K&& key, V&& val ) + { + scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward(key), std::forward(val))); + if ( base_class::insert( *sp )) { + sp.release(); + return true; + } + return false; + } + + /// Inserts new element and initialize it by a functor + /** + This function inserts new element with key \p key and if inserting is successful then it calls + \p func functor with signature + \code + struct functor { + void operator()( value_type& item ); + }; + \endcode + + The argument \p item of user-defined functor \p func is the reference + to the map's item inserted: + - item.first is a const reference to item's key that cannot be changed. + - item.second is a reference to item's value that may be changed. + + \p key_type should be constructible from value of type \p K. + + The function allows to split creating of new item into two part: + - create item from \p key; + - insert new item into the map; + - if inserting is successful, initialize the value of item by calling \p func functor + + This can be useful if complete initialization of object of \p value_type is heavyweight and + it is preferable that the initialization should be completed only if inserting is successful. + + The function locks RCU internally. + */ + template + bool insert_with( K&& key, Func func ) + { + scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward(key))); + if ( base_class::insert( *sp, [&func]( node_type& item ) { func( item.m_Value ); } )) { + sp.release(); + return true; + } + return false; + } + + /// For key \p key inserts data of type \p value_type created in-place from std::forward(args)... + /** + Returns \p true if inserting successful, \p false otherwise. + + The function locks RCU internally. + */ + template + bool emplace( K&& key, Args&&... args ) + { + scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward(key), std::forward(args)... )); + if ( base_class::insert( *sp )) { + sp.release(); + return true; + } + return false; + } + + /// Updates data by \p key + /** + The operation performs inserting or replacing the element with lock-free manner. + + If the \p key not found in the map, then the new item created from \p key + will be inserted into the map iff \p bInsert is \p true + (note that in this case the \ref key_type should be constructible from type \p K). + Otherwise, if \p key is found, it is replaced with a new item created from + \p key. + The functor \p Func signature: + \code + struct my_functor { + void operator()( value_type& item, value_type * old ); + }; + \endcode + where: + - \p item - item of the map + - \p old - old item of the map, if \p nullptr - the new item was inserted + + The functor may change any fields of the \p item.second. + + Returns std::pair where \p first is \p true if operation is successfull, + \p second is \p true if new item has been added or \p false if \p key already exists. + + The function locks RCU internally. + + @warning See \ref cds_intrusive_item_creating "insert item troubleshooting" + */ + template + std::pair update( K&& key, Func func, bool bInsert = true ) + { + scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward(key))); + std::pair result = base_class::do_update( *sp, + [&func]( node_type& node, node_type * old ) { func( node.m_Value, old ? &old->m_Value : nullptr );}, + bInsert ); + if ( result.first ) + sp.release(); + return result; + } + + /// Delete \p key from the map + /** + \p key_type must be constructible from value of type \p K. + The function deeltes the element with hash value equal to hash( key_type( key )) + + Return \p true if \p key is found and deleted, \p false otherwise. + + RCU should not be locked. The function locks RCU internally. + */ + template + bool erase( K const& key ) + { + return base_class::erase(m_Hasher(key_type(key))); + } + + /// Delete \p key from the map + /** + The function searches an item with hash value equal to hash( key_type( key )), + calls \p f functor and deletes the item. If \p key is not found, the functor is not called. + + The functor \p Func interface: + \code + struct extractor { + void operator()(value_type& item) { ... } + }; + \endcode + where \p item is the element found. + + \p key_type must be constructible from value of type \p K. + + Return \p true if key is found and deleted, \p false otherwise + + RCU should not be locked. The function locks RCU internally. + */ + template + bool erase( K const& key, Func f ) + { + return base_class::erase(m_Hasher(key_type(key)), [&f]( node_type& node) { f( node.m_Value ); }); + } + + /// Extracts the item from the map with specified \p key + /** + The function searches an item with key equal to hash( key_type( key )) in the map, + unlinks it from the map, and returns a guarded pointer to the item found. + If \p key is not found the function returns an empty guarded pointer. + + 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::FeldmanHashMap< cds::urcu::gc< cds::urcu::general_buffered<>>, int, foo, my_traits > map_type; + map_type theMap; + // ... + + typename map_type::exempt_ptr ep( theMap.extract( 5 )); + if ( ep ) { + // Deal with ep + //... + + // Dispose returned item. + ep.release(); + } + \endcode + */ + template + exempt_ptr extract( K const& key ) + { + check_deadlock_policy::check(); + + node_type * p; + { + rcu_lock rcuLock; + p = base_class::do_erase( m_Hasher( key_type(key)), [](node_type const&) -> bool {return true;}); + } + return exempt_ptr(p); + } + + /// Checks whether the map contains \p key + /** + The function searches the item by its hash that is equal to hash( key_type( key )) + and returns \p true if it is found, or \p false otherwise. + */ + template + bool contains( K const& key ) + { + return base_class::contains( m_Hasher( key_type( key )) ); + } + + /// Find the key \p key + /** + + The function searches the item by its hash that is equal to hash( key_type( key )) + 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 \p item.second. + + The function returns \p true if \p key is found, \p false otherwise. + */ + template + bool find( K const& key, Func f ) + { + return base_class::find( m_Hasher( key_type( key )), [&f](node_type& node) { f( node.m_Value );}); + } + + /// Finds the key \p key and return 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::FeldmanHashMap< your_template_params > my_map; + my_map theMap; + // ... + { + // lock RCU + my_map::rcu_lock; + + foo * p = theMap.get( 5 ); + if ( p ) { + // Deal with p + //... + } + } + \endcode + */ + template + value_type * get( K const& key ) + { + node_type * p = base_class::get( m_Hasher( key_type( key ))); + return p ? &p->m_Value : nullptr; + } + + /// Clears the map (non-atomic) + /** + The function unlink all data node from the map. + The function is not atomic but is thread-safe. + After \p %clear() the map may not be empty because another threads may insert items. + */ + void clear() + { + base_class::clear(); + } + + /// Checks if the map is empty + /** + Emptiness is checked by item counting: if item count is zero then the map is empty. + Thus, the correct item counting feature is an important part of the map implementation. + */ + bool empty() const + { + return base_class::empty(); + } + + /// Returns item count in the map + 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_FeldmanHashMap_rcu_iterators + The map supports thread-safe iterators: you may iterate over the map 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 map + 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 { + // ... other fields + uint32_t payload; // only for example + }; + typedef cds::urcu::gc< cds::urcu::general_buffered<>> rcu; + typedef cds::container::FeldmanHashMap< rcu, std::string, foo> map_type; + + map_type m; + + // ... + + // iterate over the map + { + // lock the RCU. + typename set_type::rcu_lock l; // scoped RCU lock + + // traverse the map + for ( auto i = m.begin(); i != s.end(); ++i ) { + // deal with i. Remember, erasing is prohibited here! + i->second.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 map + iterator begin() + { + return base_class::template init_begin(); + } + + /// Returns an const iterator to the beginning of the map + const_iterator begin() const + { + return base_class::template init_begin(); + } + + /// Returns an const iterator to the beginning of the map + const_iterator cbegin() + { + return base_class::template init_begin(); + } + + /// Returns an iterator to the element following the last element of the map. This element acts as a placeholder; attempting to access it results in undefined behavior. + iterator end() + { + return base_class::template init_end(); + } + + /// Returns a const iterator to the element following the last element of the map. This element acts as a placeholder; attempting to access it results in undefined behavior. + const_iterator end() const + { + return base_class::template init_end(); + } + + /// Returns a const iterator to the element following the last element of the map. This element acts as a placeholder; attempting to access it results in undefined behavior. + const_iterator cend() + { + return base_class::template init_end(); + } + + /// Returns a reverse iterator to the first element of the reversed map + reverse_iterator rbegin() + { + return base_class::template init_rbegin(); + } + + /// Returns a const reverse iterator to the first element of the reversed map + const_reverse_iterator rbegin() const + { + return base_class::template init_rbegin(); + } + + /// Returns a const reverse iterator to the first element of the reversed map + const_reverse_iterator crbegin() + { + return base_class::template init_rbegin(); + } + + /// Returns a reverse iterator to the element following the last element of the reversed map + /** + 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::template init_rend(); + } + + /// Returns a const reverse iterator to the element following the last element of the reversed map + /** + 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::template init_rend(); + } + + /// Returns a const reverse iterator to the element following the last element of the reversed map + /** + 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::template init_rend(); + } + ///@} + }; +}} // namespace cds::container + +#endif // #ifndef CDSLIB_CONTAINER_FELDMAN_HASHMAP_RCU_H diff --git a/cds/container/feldman_hashset_dhp.h b/cds/container/feldman_hashset_dhp.h new file mode 100644 index 00000000..ce87b590 --- /dev/null +++ b/cds/container/feldman_hashset_dhp.h @@ -0,0 +1,9 @@ +//$$CDS-header$$ + +#ifndef CDSLIB_CONTAINER_FELDMAN_HASHSET_DHP_H +#define CDSLIB_CONTAINER_FELDMAN_HASHSET_DHP_H + +#include +#include + +#endif // #ifndef CDSLIB_CONTAINER_FELDMAN_HASHSET_DHP_H diff --git a/cds/container/feldman_hashset_hp.h b/cds/container/feldman_hashset_hp.h new file mode 100644 index 00000000..00ac7049 --- /dev/null +++ b/cds/container/feldman_hashset_hp.h @@ -0,0 +1,9 @@ +//$$CDS-header$$ + +#ifndef CDSLIB_CONTAINER_FELDMAN_HASHSET_HP_H +#define CDSLIB_CONTAINER_FELDMAN_HASHSET_HP_H + +#include +#include + +#endif // #ifndef CDSLIB_CONTAINER_FELDMAN_HASHSET_HP_H diff --git a/cds/container/feldman_hashset_rcu.h b/cds/container/feldman_hashset_rcu.h new file mode 100644 index 00000000..b8bbccff --- /dev/null +++ b/cds/container/feldman_hashset_rcu.h @@ -0,0 +1,550 @@ +//$$CDS-header$$ + +#ifndef CDSLIB_CONTAINER_FELDMAN_HASHSET_RCU_H +#define CDSLIB_CONTAINER_FELDMAN_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_FeldmanHashSet_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_FeldmanHashSet_hp "here" + + @note Two important things you should keep in mind when you're using \p %FeldmanHashSet: + - all keys must be fixed-size. It means that you cannot use \p std::string as a key for \p %FeldmanHashSet. + 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 %FeldmanHashSet. + - \p %FeldmanHashSet 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 %FeldmanHashSet does not maintain the key, + it maintains its fixed-size hash value. + + The set supports @ref cds_container_FeldmanHashSet_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 feldman_hashset::traits or result of \p feldman_hashset::make_traits metafunction. + \p Traits is the mandatory argument because it has one mandatory type - an @ref feldman_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_FeldmanHashSet_rcu_iterators "bidirectional thread-safe iterators" + with some restrictions. + */ + template < + class RCU + , typename T +#ifdef CDS_DOXYGEN_INVOKED + , class Traits = feldman_hashset::traits +#else + , class Traits +#endif + > + class FeldmanHashSet< cds::urcu::gc< RCU >, T, Traits > +#ifdef CDS_DOXYGEN_INVOKED + : protected cds::intrusive::FeldmanHashSet< cds::urcu::gc< RCU >, T, Traits > +#else + : protected cds::container::details::make_feldman_hashset< cds::urcu::gc< RCU >, T, Traits >::type +#endif + { + //@cond + typedef cds::container::details::make_feldman_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 feldman_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_FeldmanHashSet_rcu_iterators "bidirectional iterator" type + typedef typename base_class::const_iterator const_iterator; ///< @ref cds_container_FeldmanHashSet_rcu_iterators "bidirectional const iterator" type + typedef typename base_class::reverse_iterator reverse_iterator; ///< @ref cds_container_FeldmanHashSet_rcu_iterators "bidirectional reverse iterator" type + typedef typename base_class::const_reverse_iterator const_reverse_iterator; ///< @ref cds_container_FeldmanHashSet_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. + */ + FeldmanHashSet( size_t head_bits = 8, size_t array_bits = 4 ) + : base_class( head_bits, array_bits ) + {} + + /// Destructs the set and frees all data + ~FeldmanHashSet() + {} + + /// 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. + + RCU should not be locked. The function locks RCU internally. + */ + 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. + + RCU should not be locked. The function locks RCU internally. + */ + 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::FeldmanHashSet< 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::FeldmanHashSet< 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_FeldmanHashSet_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::feldman_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::FeldmanHashSet< 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_FELDMAN_HASHSET_RCU_H diff --git a/cds/container/impl/feldman_hashmap.h b/cds/container/impl/feldman_hashmap.h new file mode 100644 index 00000000..7fd1c141 --- /dev/null +++ b/cds/container/impl/feldman_hashmap.h @@ -0,0 +1,803 @@ +//$$CDS-header$$ + +#ifndef CDSLIB_CONTAINER_IMPL_FELDMAN_HASHMAP_H +#define CDSLIB_CONTAINER_IMPL_FELDMAN_HASHMAP_H + +#include +#include +#include + +namespace cds { namespace container { + + /// Hash map based on multi-level array + /** @ingroup cds_nonintrusive_map + @anchor cds_container_FeldmanHashMap_hp + + Source: + - [2013] Steven Feldman, Pierre LaBorde, Damian Dechev "Concurrent Multi-level Arrays: + Wait-free Extensible Hash Maps" + + [From the paper] The hardest problem encountered while developing a parallel hash map is how to perform + a global resize, the process of redistributing the elements in a hash map that occurs when adding new + buckets. The negative impact of blocking synchronization is multiplied during a global resize, because all + threads will be forced to wait on the thread that is performing the involved process of resizing the hash map + and redistributing the elements. \p %FeldmanHashSet implementation avoids global resizes through new array + allocation. By allowing concurrent expansion this structure is free from the overhead of an explicit resize, + which facilitates concurrent operations. + + The presented design includes dynamic hashing, the use of sub-arrays within the hash map data structure; + which, in combination with perfect hashing, means that each element has a unique final, as well as current, position. + It is important to note that the perfect hash function required by our hash map is trivial to realize as + any hash function that permutes the bits of the key is suitable. This is possible because of our approach + to the hash function; we require that it produces hash values that are equal in size to that of the key. + We know that if we expand the hash map a fixed number of times there can be no collision as duplicate keys + are not provided for in the standard semantics of a hash map. + + \p %FeldmanHashMap is a multi-level array which has an internal structure similar to a tree: + @image html feldman_hashset.png + The multi-level array differs from a tree in that each position on the tree could hold an array of nodes or a single node. + A position that holds a single node is a \p dataNode which holds the hash value of a key and the value that is associated + with that key; it is a simple struct holding two variables. A \p dataNode in the multi-level array could be marked. + A \p markedDataNode refers to a pointer to a \p dataNode that has been bitmarked at the least significant bit (LSB) + of the pointer to the node. This signifies that this \p dataNode is contended. An expansion must occur at this node; + any thread that sees this \p markedDataNode will try to replace it with an \p arrayNode; which is a position that holds + an array of nodes. The pointer to an \p arrayNode is differentiated from that of a pointer to a \p dataNode by a bitmark + on the second-least significant bit. + + \p %FeldmanHashMap multi-level array is similar to a tree in that we keep a pointer to the root, which is a memory array + called \p head. The length of the \p head memory array is unique, whereas every other \p arrayNode has a uniform length; + a normal \p arrayNode has a fixed power-of-two length equal to the binary logarithm of a variable called \p arrayLength. + The maximum depth of the tree, \p maxDepth, is the maximum number of pointers that must be followed to reach any node. + We define \p currentDepth as the number of memory arrays that we need to traverse to reach the \p arrayNode on which + we need to operate; this is initially one, because of \p head. + + That approach to the structure of the hash map uses an extensible hashing scheme; the hash value is treated as a bit + string and rehash incrementally. + + @note Two important things you should keep in mind when you're using \p %FeldmanHashMap: + - all keys is converted to fixed-size bit-string by hash functor provided. + You can use variable-length keys, for example, \p std::string as a key for \p %FeldmanHashMap, + but real key in the map will be fixed-size hash values of your keys. + For the strings you may 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 such hash values will be the keys in \p %FeldmanHashMap. + If your key is fixed-sized the hash functor is optional, see \p feldman_hashmap::traits::hash for explanation and examples. + - \p %FeldmanHashMap 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 map. \p %FeldmanHashMap does not maintain the key, + it maintains its fixed-size hash value. + + The map supports @ref cds_container_FeldmanHashMap_iterators "bidirectional thread-safe iterators". + + 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 Key - a key type to be stored in the map + - \p T - a value type to be stored in the map + - \p Traits - type traits, the structure based on \p feldman_hashmap::traits or result of \p feldman_hashmap::make_traits metafunction. + + There are several specializations of \p %FeldmanHashMap for each \p GC. You should include: + - for \p gc::HP garbage collector + - for \p gc::DHP garbage collector + - for \ref cds_intrusive_FeldmanHashMap_rcu "RCU type". RCU specialization + has a slightly different interface. + */ + template < + class GC + ,typename Key + ,typename T +#ifdef CDS_DOXYGEN_INVOKED + ,class Traits = feldman_hashmap::traits +#else + ,class Traits +#endif + > + class FeldmanHashMap +#ifdef CDS_DOXYGEN_INVOKED + : protected cds::intrusive::FeldmanHashSet< GC, std::pair, Traits > +#else + : protected cds::container::details::make_feldman_hashmap< GC, Key, T, Traits >::type +#endif + { + //@cond + typedef cds::container::details::make_feldman_hashmap< GC, Key, T, Traits > maker; + typedef typename maker::type base_class; + //@endcond + public: + typedef GC gc; ///< Garbage collector + typedef Key key_type; ///< Key type + typedef T mapped_type; ///< Mapped type + typedef std::pair< key_type const, mapped_type> value_type; ///< Key-value pair to be stored in the map + typedef Traits traits; ///< Map traits +#ifdef CDS_DOXYGEN_INVOKED + typedef typename traits::hash hasher; ///< Hash functor, see \p feldman_hashmap::traits::hash +#else + typedef typename maker::hasher hasher; +#endif + + typedef typename maker::hash_type hash_type; ///< Hash type deduced from \p hasher return type + typedef typename base_class::hash_comparator hash_comparator; ///< hash compare functor based on \p Traits::compare and \p Traits::less + + 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 + + /// Count of hazard pointers required + static CDS_CONSTEXPR size_t const c_nHazardPtrCount = base_class::c_nHazardPtrCount; + + protected: + //@cond + typedef typename maker::node_type node_type; + typedef typename maker::cxx_node_allocator cxx_node_allocator; + typedef std::unique_ptr< node_type, typename maker::node_disposer > scoped_node_ptr; + + template + class bidirectional_iterator: public base_class::iterator_base + { + friend class FeldmanHashMap; + typedef typename base_class::iterator_base iterator_base; + + protected: + static CDS_CONSTEXPR bool const c_bConstantIterator = IsConst; + + public: + typedef typename std::conditional< IsConst, value_type const*, value_type*>::type value_ptr; ///< Value pointer + typedef typename std::conditional< IsConst, value_type const&, value_type&>::type value_ref; ///< Value reference + + public: + bidirectional_iterator() CDS_NOEXCEPT + {} + + bidirectional_iterator( bidirectional_iterator const& rhs ) CDS_NOEXCEPT + : iterator_base( rhs ) + {} + + bidirectional_iterator& operator=(bidirectional_iterator const& rhs) CDS_NOEXCEPT + { + iterator_base::operator=( rhs ); + return *this; + } + + bidirectional_iterator& operator++() + { + iterator_base::operator++(); + return *this; + } + + bidirectional_iterator& operator--() + { + iterator_base::operator--(); + return *this; + } + + value_ptr operator ->() const CDS_NOEXCEPT + { + node_type * p = iterator_base::pointer(); + return p ? &p->m_Value : nullptr; + } + + value_ref operator *() const CDS_NOEXCEPT + { + node_type * p = iterator_base::pointer(); + assert( p ); + return p->m_Value; + } + + void release() + { + iterator_base::release(); + } + + template + bool operator ==(bidirectional_iterator const& rhs) const CDS_NOEXCEPT + { + return iterator_base::operator==( rhs ); + } + + template + bool operator !=(bidirectional_iterator const& rhs) const CDS_NOEXCEPT + { + return !( *this == rhs ); + } + + public: // for internal use only! + bidirectional_iterator( base_class const& set, typename base_class::array_node * pNode, size_t idx, bool ) + : iterator_base( set, pNode, idx, false ) + {} + + bidirectional_iterator( base_class const& set, typename base_class::array_node * pNode, size_t idx ) + : iterator_base( set, pNode, idx ) + {} + }; + + /// Reverse bidirectional iterator + template + class reverse_bidirectional_iterator : public base_class::iterator_base + { + friend class FeldmanHashMap; + typedef typename base_class::iterator_base iterator_base; + + public: + typedef typename std::conditional< IsConst, value_type const*, value_type*>::type value_ptr; ///< Value pointer + typedef typename std::conditional< IsConst, value_type const&, value_type&>::type value_ref; ///< Value reference + + public: + reverse_bidirectional_iterator() CDS_NOEXCEPT + : iterator_base() + {} + + reverse_bidirectional_iterator( reverse_bidirectional_iterator const& rhs ) CDS_NOEXCEPT + : iterator_base( rhs ) + {} + + reverse_bidirectional_iterator& operator=( reverse_bidirectional_iterator const& rhs) CDS_NOEXCEPT + { + iterator_base::operator=( rhs ); + return *this; + } + + reverse_bidirectional_iterator& operator++() + { + iterator_base::operator--(); + return *this; + } + + reverse_bidirectional_iterator& operator--() + { + iterator_base::operator++(); + return *this; + } + + value_ptr operator ->() const CDS_NOEXCEPT + { + node_type * p = iterator_base::pointer(); + return p ? &p->m_Value : nullptr; + } + + value_ref operator *() const CDS_NOEXCEPT + { + node_type * p = iterator_base::pointer(); + assert( p ); + return p->m_Value; + } + + void release() + { + iterator_base::release(); + } + + template + bool operator ==(reverse_bidirectional_iterator const& rhs) const + { + return iterator_base::operator==( rhs ); + } + + template + bool operator !=(reverse_bidirectional_iterator const& rhs) + { + return !( *this == rhs ); + } + + public: // for internal use only! + reverse_bidirectional_iterator( base_class const& set, typename base_class::array_node * pNode, size_t idx, bool ) + : iterator_base( set, pNode, idx, false ) + {} + + reverse_bidirectional_iterator( base_class const& set, typename base_class::array_node * pNode, size_t idx ) + : iterator_base( set, pNode, idx, false ) + { + iterator_base::backward(); + } + }; + + //@endcond + + public: +#ifdef CDS_DOXYGEN_INVOKED + /// Guarded pointer + typedef typename gc::template guarded_ptr< value_type > guarded_ptr; +#else + typedef typename gc::template guarded_ptr< node_type, value_type, cds::container::details::guarded_ptr_cast_set > guarded_ptr; +#endif + +#ifdef CDS_DOXYGEN_INVOKED + typedef implementation_defined iterator; ///< @ref cds_container_FeldmanHashMap_iterators "bidirectional iterator" type + typedef implementation_defined const_iterator; ///< @ref cds_container_FeldmanHashMap_iterators "bidirectional const iterator" type + typedef implementation_defined reverse_iterator; ///< @ref cds_container_FeldmanHashMap_iterators "bidirectional reverse iterator" type + typedef implementation_defined const_reverse_iterator; ///< @ref cds_container_FeldmanHashMap_iterators "bidirectional reverse const iterator" type +#else + typedef bidirectional_iterator iterator; + typedef bidirectional_iterator const_iterator; + typedef reverse_bidirectional_iterator reverse_iterator; + typedef reverse_bidirectional_iterator const_reverse_iterator; +#endif + + protected: + //@cond + hasher m_Hasher; + //@endcond + + public: + /// Creates empty map + /** + @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. + */ + FeldmanHashMap( size_t head_bits = 8, size_t array_bits = 4 ) + : base_class( head_bits, array_bits ) + {} + + /// Destructs the map and frees all data + ~FeldmanHashMap() + {} + + /// Inserts new element with key and default value + /** + The function creates an element with \p key and default value, and then inserts the node created into the map. + + Preconditions: + - The \p key_type should be constructible from a value of type \p K. + In trivial case, \p K is equal to \p key_type. + - The \p mapped_type should be default-constructible. + + Returns \p true if inserting successful, \p false otherwise. + */ + template + bool insert( K&& key ) + { + scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward(key) )); + if ( base_class::insert( *sp )) { + sp.release(); + return true; + } + return false; + } + + /// Inserts new element + /** + The function creates a node with copy of \p val value + and then inserts the node created into the map. + + Preconditions: + - The \p key_type should be constructible from \p key of type \p K. + - The \p value_type should be constructible from \p val of type \p V. + + Returns \p true if \p val is inserted into the map, \p false otherwise. + */ + template + bool insert( K&& key, V&& val ) + { + scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward(key), std::forward(val))); + if ( base_class::insert( *sp )) { + sp.release(); + return true; + } + return false; + } + + /// Inserts new element and initialize it by a functor + /** + This function inserts new element with key \p key and if inserting is successful then it calls + \p func functor with signature + \code + struct functor { + void operator()( value_type& item ); + }; + \endcode + + The argument \p item of user-defined functor \p func is the reference + to the map's item inserted: + - item.first is a const reference to item's key that cannot be changed. + - item.second is a reference to item's value that may be changed. + + \p key_type should be constructible from value of type \p K. + + The function allows to split creating of new item into two part: + - create item from \p key; + - insert new item into the map; + - if inserting is successful, initialize the value of item by calling \p func functor + + This can be useful if complete initialization of object of \p value_type is heavyweight and + it is preferable that the initialization should be completed only if inserting is successful. + */ + template + bool insert_with( K&& key, Func func ) + { + scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward(key))); + if ( base_class::insert( *sp, [&func]( node_type& item ) { func( item.m_Value ); } )) { + sp.release(); + return true; + } + return false; + } + + /// For key \p key 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( K&& key, Args&&... args ) + { + scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward(key), std::forward(args)... )); + if ( base_class::insert( *sp )) { + sp.release(); + return true; + } + return false; + } + + /// Updates data by \p key + /** + The operation performs inserting or replacing the element with lock-free manner. + + If the \p key not found in the map, then the new item created from \p key + will be inserted into the map iff \p bInsert is \p true + (note that in this case the \ref key_type should be constructible from type \p K). + Otherwise, if \p key is found, it is replaced with a new item created from + \p key. + The functor \p Func signature: + \code + struct my_functor { + void operator()( value_type& item, value_type * old ); + }; + \endcode + where: + - \p item - item of the map + - \p old - old item of the map, if \p nullptr - the new item was inserted + + The functor may change any fields of the \p item.second. + + Returns std::pair where \p first is \p true if operation is successfull, + \p second is \p true if new item has been added or \p false if \p key already exists. + + @warning See \ref cds_intrusive_item_creating "insert item troubleshooting" + */ + template + std::pair update( K&& key, Func func, bool bInsert = true ) + { + scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward(key))); + std::pair result = base_class::do_update( *sp, + [&func]( node_type& node, node_type * old ) { func( node.m_Value, old ? &old->m_Value : nullptr );}, + bInsert ); + if ( result.first ) + sp.release(); + return result; + } + + /// Delete \p key from the map + /** + \p key_type must be constructible from value of type \p K. + The function deeltes the element with hash value equal to hash( key_type( key )) + + Return \p true if \p key is found and deleted, \p false otherwise. + */ + template + bool erase( K const& key ) + { + return base_class::erase( m_Hasher( key_type( key ))); + } + + /// Delete \p key from the map + /** + The function searches an item with hash value equal to hash( key_type( key )), + calls \p f functor and deletes the item. If \p key is not found, the functor is not called. + + The functor \p Func interface: + \code + struct extractor { + void operator()(value_type& item) { ... } + }; + \endcode + where \p item is the element found. + + \p key_type must be constructible from value of type \p K. + + Return \p true if key is found and deleted, \p false otherwise + */ + template + bool erase( K const& key, Func f ) + { + return base_class::erase( m_Hasher(key_type(key)), [&f]( node_type& node) { f( node.m_Value ); } ); + } + + /// Deletes the element pointed by iterator \p iter + /** + 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& iter ) + { + return base_class::do_erase_at( iter ); + } + //@cond + bool erase_at( reverse_iterator const& iter ) + { + return base_class::do_erase_at( iter ); + } + //@endcond + + /// Extracts the item from the map with specified \p key + /** + The function searches an item with key equal to hash( key_type( key )) in the map, + unlinks it from the map, and returns a guarded pointer to the item found. + If \p key is not found the function returns an empty guarded pointer. + + The item extracted is freed automatically by garbage collector \p GC + when returned \p guarded_ptr object will be destroyed or released. + @note Each \p guarded_ptr object uses the GC's guard that can be limited resource. + + Usage: + \code + typedef cds::container::FeldmanHashMap< cds::gc::HP, int, foo, my_traits > map_type; + map_type theMap; + // ... + { + map_type::guarded_ptr gp( theMap.extract( 5 )); + if ( gp ) { + // Deal with gp + // ... + } + // Destructor of gp releases internal HP guard and frees the pointer + } + \endcode + */ + template + guarded_ptr extract( K const& key ) + { + guarded_ptr gp; + typename gc::Guard guard; + node_type * p = base_class::do_erase( m_Hasher( key_type( key )), guard, []( node_type const&) -> bool {return true;} ); + + // p is guarded by HP + if ( p ) + gp.reset( p ); + return gp; + } + + /// Checks whether the map contains \p key + /** + The function searches the item by its hash that is equal to hash( key_type( key )) + and returns \p true if it is found, or \p false otherwise. + */ + template + bool contains( K const& key ) + { + return base_class::contains( m_Hasher( key_type( key )) ); + } + + /// Find the key \p key + /** + + The function searches the item by its hash that is equal to hash( key_type( key )) + 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 \p item.second. + + The function returns \p true if \p key is found, \p false otherwise. + */ + template + bool find( K const& key, Func f ) + { + return base_class::find( m_Hasher( key_type( key )), [&f](node_type& node) { f( node.m_Value );}); + } + + /// Finds the key \p key and return the item found + /** + The function searches the item with a hash equal to hash( key_type( key )) + and returns a guarded pointer to the item found. + If \p key is not found the function returns an empty guarded pointer. + + It is safe when a concurrent thread erases the item returned as \p guarded_ptr. + In this case the item will be freed later by garbage collector \p GC automatically + when \p guarded_ptr object will be destroyed or released. + @note Each \p guarded_ptr object uses one GC's guard which can be limited resource. + + Usage: + \code + typedef cds::container::FeldmanHashMap< cds::gc::HP, int, foo, my_traits > map_type; + map_type theMap; + // ... + { + map_type::guarded_ptr gp( theMap.get( 5 )); + if ( gp ) { + // Deal with gp + //... + } + // Destructor of guarded_ptr releases internal HP guard + } + \endcode + */ + template + guarded_ptr get( K const& key ) + { + guarded_ptr gp; + { + typename gc::Guard guard; + gp.reset( base_class::search( m_Hasher( key_type( key )), guard )); + } + return gp; + } + + /// Clears the map (non-atomic) + /** + The function unlink all data node from the map. + The function is not atomic but is thread-safe. + After \p %clear() the map may not be empty because another threads may insert items. + */ + void clear() + { + base_class::clear(); + } + + /// Checks if the map is empty + /** + Emptiness is checked by item counting: if item count is zero then the map is empty. + Thus, the correct item counting feature is an important part of the map implementation. + */ + bool empty() const + { + return base_class::empty(); + } + + /// Returns item count in the map + 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_FeldmanHashMap_iterators + The map supports thread-safe iterators: you may iterate over the map in multi-threaded environment. + It is guaranteed that the iterators will remain valid even if another thread deletes the node the iterator points to: + Hazard Pointer embedded into the iterator object protects the node from physical reclamation. + + @note Since the iterator object contains hazard pointer that is a thread-local resource, + the iterator should not be passed to another thread. + + 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 conditon it1 == it2 + does not entail &(*it1) == &(*it2) + - helper member function \p release() that clears internal hazard pointer. + After \p release() the iterator points to \p nullptr but it still remain valid: further iterating is possible. + + During iteration you may safely erase any item from the set; + @ref erase_at() function call doesn't invalidate any iterator. + If some iterator points to the item to be erased, that item is not deleted immediately + but only after that iterator will be advanced forward or backward. + + @note It is possible the item can be iterated more that once, for example, if an iterator points to the item + in array node that is being splitted. + */ + ///@{ + /// Returns an iterator to the beginning of the map + iterator begin() + { + return base_class::template init_begin(); + } + + /// Returns an const iterator to the beginning of the map + const_iterator begin() const + { + return base_class::template init_begin(); + } + + /// Returns an const iterator to the beginning of the map + const_iterator cbegin() + { + return base_class::template init_begin(); + } + + /// Returns an iterator to the element following the last element of the map. This element acts as a placeholder; attempting to access it results in undefined behavior. + iterator end() + { + return base_class::template init_end(); + } + + /// Returns a const iterator to the element following the last element of the map. This element acts as a placeholder; attempting to access it results in undefined behavior. + const_iterator end() const + { + return base_class::template init_end(); + } + + /// Returns a const iterator to the element following the last element of the map. This element acts as a placeholder; attempting to access it results in undefined behavior. + const_iterator cend() + { + return base_class::template init_end(); + } + + /// Returns a reverse iterator to the first element of the reversed map + reverse_iterator rbegin() + { + return base_class::template init_rbegin(); + } + + /// Returns a const reverse iterator to the first element of the reversed map + const_reverse_iterator rbegin() const + { + return base_class::template init_rbegin(); + } + + /// Returns a const reverse iterator to the first element of the reversed map + const_reverse_iterator crbegin() + { + return base_class::template init_rbegin(); + } + + /// Returns a reverse iterator to the element following the last element of the reversed map + /** + 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::template init_rend(); + } + + /// Returns a const reverse iterator to the element following the last element of the reversed map + /** + 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::template init_rend(); + } + + /// Returns a const reverse iterator to the element following the last element of the reversed map + /** + 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::template init_rend(); + } + ///@} + }; + +}} // namespace cds::container + +#endif // #ifndef CDSLIB_CONTAINER_IMPL_FELDMAN_HASHMAP_H diff --git a/cds/container/impl/feldman_hashset.h b/cds/container/impl/feldman_hashset.h new file mode 100644 index 00000000..4e05f39c --- /dev/null +++ b/cds/container/impl/feldman_hashset.h @@ -0,0 +1,562 @@ +//$$CDS-header$$ + +#ifndef CDSLIB_CONTAINER_IMPL_FELDMAN_HASHSET_H +#define CDSLIB_CONTAINER_IMPL_FELDMAN_HASHSET_H + +#include +#include + +namespace cds { namespace container { + + /// Hash set based on multi-level array + /** @ingroup cds_nonintrusive_set + @anchor cds_container_FeldmanHashSet_hp + + Source: + - [2013] Steven Feldman, Pierre LaBorde, Damian Dechev "Concurrent Multi-level Arrays: + Wait-free Extensible Hash Maps" + + [From the paper] The hardest problem encountered while developing a parallel hash map is how to perform + a global resize, the process of redistributing the elements in a hash map that occurs when adding new + buckets. The negative impact of blocking synchronization is multiplied during a global resize, because all + threads will be forced to wait on the thread that is performing the involved process of resizing the hash map + and redistributing the elements. \p %FeldmanHashSet implementation avoids global resizes through new array + allocation. By allowing concurrent expansion this structure is free from the overhead of an explicit resize, + which facilitates concurrent operations. + + The presented design includes dynamic hashing, the use of sub-arrays within the hash map data structure; + which, in combination with perfect hashing, means that each element has a unique final, as well as current, position. + It is important to note that the perfect hash function required by our hash map is trivial to realize as + any hash function that permutes the bits of the key is suitable. This is possible because of our approach + to the hash function; we require that it produces hash values that are equal in size to that of the key. + We know that if we expand the hash map a fixed number of times there can be no collision as duplicate keys + are not provided for in the standard semantics of a hash map. + + \p %FeldmanHashSet is a multi-level array which has an internal structure similar to a tree: + @image html feldman_hashset.png + The multi-level array differs from a tree in that each position on the tree could hold an array of nodes or a single node. + A position that holds a single node is a \p dataNode which holds the hash value of a key and the value that is associated + with that key; it is a simple struct holding two variables. A \p dataNode in the multi-level array could be marked. + A \p markedDataNode refers to a pointer to a \p dataNode that has been bitmarked at the least significant bit (LSB) + of the pointer to the node. This signifies that this \p dataNode is contended. An expansion must occur at this node; + any thread that sees this \p markedDataNode will try to replace it with an \p arrayNode; which is a position that holds + an array of nodes. The pointer to an \p arrayNode is differentiated from that of a pointer to a \p dataNode by a bitmark + on the second-least significant bit. + + \p %FeldmanHashSet multi-level array is similar to a tree in that we keep a pointer to the root, which is a memory array + called \p head. The length of the \p head memory array is unique, whereas every other \p arrayNode has a uniform length; + a normal \p arrayNode has a fixed power-of-two length equal to the binary logarithm of a variable called \p arrayLength. + The maximum depth of the tree, \p maxDepth, is the maximum number of pointers that must be followed to reach any node. + We define \p currentDepth as the number of memory arrays that we need to traverse to reach the \p arrayNode on which + we need to operate; this is initially one, because of \p head. + + That approach to the structure of the hash set uses an extensible hashing scheme; the hash value is treated as a bit + string and rehash incrementally. + + @note Two important things you should keep in mind when you're using \p %FeldmanHashSet: + - all keys must be fixed-size. It means that you cannot use \p std::string as a key for \p %FeldmanHashSet. + 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 %FeldmanHashSet. + - \p %FeldmanHashSet 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 %FeldmanHashSet does not maintain the key, + it maintains its fixed-size hash value. + + The set supports @ref cds_container_FeldmanHashSet_iterators "bidirectional thread-safe iterators". + + 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 feldman_hashset::traits or result of \p feldman_hashset::make_traits metafunction. + \p Traits is the mandatory argument because it has one mandatory type - an @ref feldman_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 %FeldmanHashSet for each \p GC. You should include: + - for \p gc::HP garbage collector + - for \p gc::DHP garbage collector + - for \ref cds_intrusive_FeldmanHashSet_rcu "RCU type". RCU specialization + has a slightly different interface. + */ + template < + class GC + , typename T +#ifdef CDS_DOXYGEN_INVOKED + , class Traits = feldman_hashset::traits +#else + , class Traits +#endif + > + class FeldmanHashSet +#ifdef CDS_DOXYGEN_INVOKED + : protected cds::intrusive::FeldmanHashSet< GC, T, Traits > +#else + : protected cds::container::details::make_feldman_hashset< GC, T, Traits >::type +#endif + { + //@cond + typedef cds::container::details::make_feldman_hashset< GC, T, Traits > maker; + typedef typename maker::type base_class; + //@endcond + + public: + typedef GC gc; ///< Garbage collector + typedef T value_type; ///< type of value stored in the set + typedef Traits traits; ///< Traits template parameter, see \p feldman_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 gc::template guarded_ptr< value_type > guarded_ptr; ///< Guarded pointer + + /// Count of hazard pointers required + static CDS_CONSTEXPR size_t const c_nHazardPtrCount = base_class::c_nHazardPtrCount; + + typedef typename base_class::iterator iterator; ///< @ref cds_container_FeldmanHashSet_iterators "bidirectional iterator" type + typedef typename base_class::const_iterator const_iterator; ///< @ref cds_container_FeldmanHashSet_iterators "bidirectional const iterator" type + typedef typename base_class::reverse_iterator reverse_iterator; ///< @ref cds_container_FeldmanHashSet_iterators "bidirectional reverse iterator" type + typedef typename base_class::const_reverse_iterator const_reverse_iterator; ///< @ref cds_container_FeldmanHashSet_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. + */ + FeldmanHashSet( size_t head_bits = 8, size_t array_bits = 4 ) + : base_class( head_bits, array_bits ) + {} + + /// Destructs the set and frees all data + ~FeldmanHashSet() + {} + + /// 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. + */ + 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. + */ + 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 ); + } + + /// Deletes the item pointed by iterator \p iter + /** + 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& iter ) + { + return base_class::erase_at( iter ); + } + //@cond + bool erase_at( reverse_iterator const& iter ) + { + return base_class::erase_at( iter ); + } + //@endcond + + /// Extracts the item with specified \p hash + /** + The function searches \p hash in the set, + 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 + when returned \ref guarded_ptr object to be destroyed or released. + @note Each \p guarded_ptr object uses the GC's guard that can be limited resource. + + Usage: + \code + typedef cds::container::FeldmanHashSet< your_template_args > my_set; + my_set theSet; + // ... + { + my_set::guarded_ptr gp( theSet.extract( 5 )); + if ( gp ) { + // Deal with gp + // ... + } + // Destructor of gp releases internal HP guard + } + \endcode + */ + guarded_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 guarded pointer to the item found. + If \p hash is not found the function returns an empty \p guarded_ptr. + + @note Each \p guarded_ptr object uses one GC's guard which can be limited resource. + + Usage: + \code + typedef cds::container::FeldmanHashSet< your_template_params > my_set; + my_set theSet; + // ... + { + my_set::guarded_ptr gp( theSet.get( 5 )); + if ( theSet.get( 5 )) { + // Deal with gp + //... + } + // Destructor of guarded_ptr releases internal HP guard + } + \endcode + */ + guarded_ptr 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_FeldmanHashSet_iterators + The set supports thread-safe iterators: you may iterate over the set in multi-threaded environment. + It is guaranteed that the iterators will remain valid even if another thread deletes the node the iterator points to: + Hazard Pointer embedded into the iterator object protects the node from physical reclamation. + + @note Since the iterator object contains hazard pointer that is a thread-local resource, + the iterator should not be passed to another thread. + + 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 conditon it1 == it2 + does not entail &(*it1) == &(*it2) + - helper member function \p release() that clears internal hazard pointer. + After \p release() the iterator points to \p nullptr but it still remain valid: further iterating is possible. + + During iteration you may safely erase any item from the set; + @ref erase_at() function call doesn't invalidate any iterator. + If some iterator points to the item to be erased, that item is not deleted immediately + but only after that iterator will be advanced forward or backward. + + @note It is possible the item can be iterated more that once, for example, if an iterator points to the item + in 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_IMPL_FELDMAN_HASHSET_H diff --git a/cds/container/impl/multilevel_hashmap.h b/cds/container/impl/multilevel_hashmap.h deleted file mode 100644 index 50a9d66f..00000000 --- a/cds/container/impl/multilevel_hashmap.h +++ /dev/null @@ -1,803 +0,0 @@ -//$$CDS-header$$ - -#ifndef CDSLIB_CONTAINER_IMPL_MULTILEVEL_HASHMAP_H -#define CDSLIB_CONTAINER_IMPL_MULTILEVEL_HASHMAP_H - -#include -#include -#include - -namespace cds { namespace container { - - /// Hash map based on multi-level array - /** @ingroup cds_nonintrusive_map - @anchor cds_container_MultilevelHashMap_hp - - Source: - - [2013] Steven Feldman, Pierre LaBorde, Damian Dechev "Concurrent Multi-level Arrays: - Wait-free Extensible Hash Maps" - - [From the paper] The hardest problem encountered while developing a parallel hash map is how to perform - a global resize, the process of redistributing the elements in a hash map that occurs when adding new - buckets. The negative impact of blocking synchronization is multiplied during a global resize, because all - threads will be forced to wait on the thread that is performing the involved process of resizing the hash map - and redistributing the elements. \p %MultilevelHashSet implementation avoids global resizes through new array - allocation. By allowing concurrent expansion this structure is free from the overhead of an explicit resize, - which facilitates concurrent operations. - - The presented design includes dynamic hashing, the use of sub-arrays within the hash map data structure; - which, in combination with perfect hashing, means that each element has a unique final, as well as current, position. - It is important to note that the perfect hash function required by our hash map is trivial to realize as - any hash function that permutes the bits of the key is suitable. This is possible because of our approach - to the hash function; we require that it produces hash values that are equal in size to that of the key. - We know that if we expand the hash map a fixed number of times there can be no collision as duplicate keys - are not provided for in the standard semantics of a hash map. - - \p %MultiLevelHashMap is a multi-level array which has an internal structure similar to a tree: - @image html multilevel_hashset.png - The multi-level array differs from a tree in that each position on the tree could hold an array of nodes or a single node. - A position that holds a single node is a \p dataNode which holds the hash value of a key and the value that is associated - with that key; it is a simple struct holding two variables. A \p dataNode in the multi-level array could be marked. - A \p markedDataNode refers to a pointer to a \p dataNode that has been bitmarked at the least significant bit (LSB) - of the pointer to the node. This signifies that this \p dataNode is contended. An expansion must occur at this node; - any thread that sees this \p markedDataNode will try to replace it with an \p arrayNode; which is a position that holds - an array of nodes. The pointer to an \p arrayNode is differentiated from that of a pointer to a \p dataNode by a bitmark - on the second-least significant bit. - - \p %MultiLevelHashMap multi-level array is similar to a tree in that we keep a pointer to the root, which is a memory array - called \p head. The length of the \p head memory array is unique, whereas every other \p arrayNode has a uniform length; - a normal \p arrayNode has a fixed power-of-two length equal to the binary logarithm of a variable called \p arrayLength. - The maximum depth of the tree, \p maxDepth, is the maximum number of pointers that must be followed to reach any node. - We define \p currentDepth as the number of memory arrays that we need to traverse to reach the \p arrayNode on which - we need to operate; this is initially one, because of \p head. - - That approach to the structure of the hash map uses an extensible hashing scheme; the hash value is treated as a bit - string and rehash incrementally. - - @note Two important things you should keep in mind when you're using \p %MultiLevelHashMap: - - all keys is converted to fixed-size bit-string by hash functor provided. - You can use variable-length keys, for example, \p std::string as a key for \p %MultiLevelHashMap, - but real key in the map will be fixed-size hash values of your keys. - For the strings you may 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 such hash values will be the keys in \p %MultiLevelHashMap. - If your key is fixed-sized the hash functor is optional, see \p multilevel_hashmap::traits::hash for explanation and examples. - - \p %MultiLevelHashMap 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 map. \p %MultiLevelHashMap does not maintain the key, - it maintains its fixed-size hash value. - - The map supports @ref cds_container_MultilevelHashMap_iterators "bidirectional thread-safe iterators". - - 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 Key - a key type to be stored in the map - - \p T - a value type to be stored in the map - - \p Traits - type traits, the structure based on \p multilevel_hashmap::traits or result of \p multilevel_hashmap::make_traits metafunction. - - There are several specializations of \p %MultiLevelHashMap for each \p GC. You should include: - - for \p gc::HP garbage collector - - for \p gc::DHP garbage collector - - for \ref cds_intrusive_MultiLevelHashMap_rcu "RCU type". RCU specialization - has a slightly different interface. - */ - template < - class GC - ,typename Key - ,typename T -#ifdef CDS_DOXYGEN_INVOKED - ,class Traits = multilevel_hashmap::traits -#else - ,class Traits -#endif - > - class MultiLevelHashMap -#ifdef CDS_DOXYGEN_INVOKED - : protected cds::intrusive::MultiLevelHashSet< GC, std::pair, Traits > -#else - : protected cds::container::details::make_multilevel_hashmap< GC, Key, T, Traits >::type -#endif - { - //@cond - typedef cds::container::details::make_multilevel_hashmap< GC, Key, T, Traits > maker; - typedef typename maker::type base_class; - //@endcond - public: - typedef GC gc; ///< Garbage collector - typedef Key key_type; ///< Key type - typedef T mapped_type; ///< Mapped type - typedef std::pair< key_type const, mapped_type> value_type; ///< Key-value pair to be stored in the map - typedef Traits traits; ///< Map traits -#ifdef CDS_DOXYGEN_INVOKED - typedef typename traits::hash hasher; ///< Hash functor, see \p multilevel_hashmap::traits::hash -#else - typedef typename maker::hasher hasher; -#endif - - typedef typename maker::hash_type hash_type; ///< Hash type deduced from \p hasher return type - typedef typename base_class::hash_comparator hash_comparator; ///< hash compare functor based on \p Traits::compare and \p Traits::less - - 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 - - /// Count of hazard pointers required - static CDS_CONSTEXPR size_t const c_nHazardPtrCount = base_class::c_nHazardPtrCount; - - protected: - //@cond - typedef typename maker::node_type node_type; - typedef typename maker::cxx_node_allocator cxx_node_allocator; - typedef std::unique_ptr< node_type, typename maker::node_disposer > scoped_node_ptr; - - template - class bidirectional_iterator: public base_class::iterator_base - { - friend class MultiLevelHashMap; - typedef typename base_class::iterator_base iterator_base; - - protected: - static CDS_CONSTEXPR bool const c_bConstantIterator = IsConst; - - public: - typedef typename std::conditional< IsConst, value_type const*, value_type*>::type value_ptr; ///< Value pointer - typedef typename std::conditional< IsConst, value_type const&, value_type&>::type value_ref; ///< Value reference - - public: - bidirectional_iterator() CDS_NOEXCEPT - {} - - bidirectional_iterator( bidirectional_iterator const& rhs ) CDS_NOEXCEPT - : iterator_base( rhs ) - {} - - bidirectional_iterator& operator=(bidirectional_iterator const& rhs) CDS_NOEXCEPT - { - iterator_base::operator=( rhs ); - return *this; - } - - bidirectional_iterator& operator++() - { - iterator_base::operator++(); - return *this; - } - - bidirectional_iterator& operator--() - { - iterator_base::operator--(); - return *this; - } - - value_ptr operator ->() const CDS_NOEXCEPT - { - node_type * p = iterator_base::pointer(); - return p ? &p->m_Value : nullptr; - } - - value_ref operator *() const CDS_NOEXCEPT - { - node_type * p = iterator_base::pointer(); - assert( p ); - return p->m_Value; - } - - void release() - { - iterator_base::release(); - } - - template - bool operator ==(bidirectional_iterator const& rhs) const CDS_NOEXCEPT - { - return iterator_base::operator==( rhs ); - } - - template - bool operator !=(bidirectional_iterator const& rhs) const CDS_NOEXCEPT - { - return !( *this == rhs ); - } - - public: // for internal use only! - bidirectional_iterator( base_class const& set, typename base_class::array_node * pNode, size_t idx, bool ) - : iterator_base( set, pNode, idx, false ) - {} - - bidirectional_iterator( base_class const& set, typename base_class::array_node * pNode, size_t idx ) - : iterator_base( set, pNode, idx ) - {} - }; - - /// Reverse bidirectional iterator - template - class reverse_bidirectional_iterator : public base_class::iterator_base - { - friend class MultiLevelHashMap; - typedef typename base_class::iterator_base iterator_base; - - public: - typedef typename std::conditional< IsConst, value_type const*, value_type*>::type value_ptr; ///< Value pointer - typedef typename std::conditional< IsConst, value_type const&, value_type&>::type value_ref; ///< Value reference - - public: - reverse_bidirectional_iterator() CDS_NOEXCEPT - : iterator_base() - {} - - reverse_bidirectional_iterator( reverse_bidirectional_iterator const& rhs ) CDS_NOEXCEPT - : iterator_base( rhs ) - {} - - reverse_bidirectional_iterator& operator=( reverse_bidirectional_iterator const& rhs) CDS_NOEXCEPT - { - iterator_base::operator=( rhs ); - return *this; - } - - reverse_bidirectional_iterator& operator++() - { - iterator_base::operator--(); - return *this; - } - - reverse_bidirectional_iterator& operator--() - { - iterator_base::operator++(); - return *this; - } - - value_ptr operator ->() const CDS_NOEXCEPT - { - node_type * p = iterator_base::pointer(); - return p ? &p->m_Value : nullptr; - } - - value_ref operator *() const CDS_NOEXCEPT - { - node_type * p = iterator_base::pointer(); - assert( p ); - return p->m_Value; - } - - void release() - { - iterator_base::release(); - } - - template - bool operator ==(reverse_bidirectional_iterator const& rhs) const - { - return iterator_base::operator==( rhs ); - } - - template - bool operator !=(reverse_bidirectional_iterator const& rhs) - { - return !( *this == rhs ); - } - - public: // for internal use only! - reverse_bidirectional_iterator( base_class const& set, typename base_class::array_node * pNode, size_t idx, bool ) - : iterator_base( set, pNode, idx, false ) - {} - - reverse_bidirectional_iterator( base_class const& set, typename base_class::array_node * pNode, size_t idx ) - : iterator_base( set, pNode, idx, false ) - { - iterator_base::backward(); - } - }; - - //@endcond - - public: -#ifdef CDS_DOXYGEN_INVOKED - /// Guarded pointer - typedef typename gc::template guarded_ptr< value_type > guarded_ptr; -#else - typedef typename gc::template guarded_ptr< node_type, value_type, cds::container::details::guarded_ptr_cast_set > guarded_ptr; -#endif - -#ifdef CDS_DOXYGEN_INVOKED - typedef implementation_defined iterator; ///< @ref cds_container_MultilevelHashMap_iterators "bidirectional iterator" type - typedef implementation_defined const_iterator; ///< @ref cds_container_MultilevelHashMap_iterators "bidirectional const iterator" type - typedef implementation_defined reverse_iterator; ///< @ref cds_container_MultilevelHashMap_iterators "bidirectional reverse iterator" type - typedef implementation_defined const_reverse_iterator; ///< @ref cds_container_MultilevelHashMap_iterators "bidirectional reverse const iterator" type -#else - typedef bidirectional_iterator iterator; - typedef bidirectional_iterator const_iterator; - typedef reverse_bidirectional_iterator reverse_iterator; - typedef reverse_bidirectional_iterator const_reverse_iterator; -#endif - - protected: - //@cond - hasher m_Hasher; - //@endcond - - public: - /// Creates empty map - /** - @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. - */ - MultiLevelHashMap( size_t head_bits = 8, size_t array_bits = 4 ) - : base_class( head_bits, array_bits ) - {} - - /// Destructs the map and frees all data - ~MultiLevelHashMap() - {} - - /// Inserts new element with key and default value - /** - The function creates an element with \p key and default value, and then inserts the node created into the map. - - Preconditions: - - The \p key_type should be constructible from a value of type \p K. - In trivial case, \p K is equal to \p key_type. - - The \p mapped_type should be default-constructible. - - Returns \p true if inserting successful, \p false otherwise. - */ - template - bool insert( K&& key ) - { - scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward(key) )); - if ( base_class::insert( *sp )) { - sp.release(); - return true; - } - return false; - } - - /// Inserts new element - /** - The function creates a node with copy of \p val value - and then inserts the node created into the map. - - Preconditions: - - The \p key_type should be constructible from \p key of type \p K. - - The \p value_type should be constructible from \p val of type \p V. - - Returns \p true if \p val is inserted into the map, \p false otherwise. - */ - template - bool insert( K&& key, V&& val ) - { - scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward(key), std::forward(val))); - if ( base_class::insert( *sp )) { - sp.release(); - return true; - } - return false; - } - - /// Inserts new element and initialize it by a functor - /** - This function inserts new element with key \p key and if inserting is successful then it calls - \p func functor with signature - \code - struct functor { - void operator()( value_type& item ); - }; - \endcode - - The argument \p item of user-defined functor \p func is the reference - to the map's item inserted: - - item.first is a const reference to item's key that cannot be changed. - - item.second is a reference to item's value that may be changed. - - \p key_type should be constructible from value of type \p K. - - The function allows to split creating of new item into two part: - - create item from \p key; - - insert new item into the map; - - if inserting is successful, initialize the value of item by calling \p func functor - - This can be useful if complete initialization of object of \p value_type is heavyweight and - it is preferable that the initialization should be completed only if inserting is successful. - */ - template - bool insert_with( K&& key, Func func ) - { - scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward(key))); - if ( base_class::insert( *sp, [&func]( node_type& item ) { func( item.m_Value ); } )) { - sp.release(); - return true; - } - return false; - } - - /// For key \p key 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( K&& key, Args&&... args ) - { - scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward(key), std::forward(args)... )); - if ( base_class::insert( *sp )) { - sp.release(); - return true; - } - return false; - } - - /// Updates data by \p key - /** - The operation performs inserting or replacing the element with lock-free manner. - - If the \p key not found in the map, then the new item created from \p key - will be inserted into the map iff \p bInsert is \p true - (note that in this case the \ref key_type should be constructible from type \p K). - Otherwise, if \p key is found, it is replaced with a new item created from - \p key. - The functor \p Func signature: - \code - struct my_functor { - void operator()( value_type& item, value_type * old ); - }; - \endcode - where: - - \p item - item of the map - - \p old - old item of the map, if \p nullptr - the new item was inserted - - The functor may change any fields of the \p item.second. - - Returns std::pair where \p first is \p true if operation is successfull, - \p second is \p true if new item has been added or \p false if \p key already exists. - - @warning See \ref cds_intrusive_item_creating "insert item troubleshooting" - */ - template - std::pair update( K&& key, Func func, bool bInsert = true ) - { - scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward(key))); - std::pair result = base_class::do_update( *sp, - [&func]( node_type& node, node_type * old ) { func( node.m_Value, old ? &old->m_Value : nullptr );}, - bInsert ); - if ( result.first ) - sp.release(); - return result; - } - - /// Delete \p key from the map - /** - \p key_type must be constructible from value of type \p K. - The function deeltes the element with hash value equal to hash( key_type( key )) - - Return \p true if \p key is found and deleted, \p false otherwise. - */ - template - bool erase( K const& key ) - { - return base_class::erase( m_Hasher( key_type( key ))); - } - - /// Delete \p key from the map - /** - The function searches an item with hash value equal to hash( key_type( key )), - calls \p f functor and deletes the item. If \p key is not found, the functor is not called. - - The functor \p Func interface: - \code - struct extractor { - void operator()(value_type& item) { ... } - }; - \endcode - where \p item is the element found. - - \p key_type must be constructible from value of type \p K. - - Return \p true if key is found and deleted, \p false otherwise - */ - template - bool erase( K const& key, Func f ) - { - return base_class::erase( m_Hasher(key_type(key)), [&f]( node_type& node) { f( node.m_Value ); } ); - } - - /// Deletes the element pointed by iterator \p iter - /** - 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& iter ) - { - return base_class::do_erase_at( iter ); - } - //@cond - bool erase_at( reverse_iterator const& iter ) - { - return base_class::do_erase_at( iter ); - } - //@endcond - - /// Extracts the item from the map with specified \p key - /** - The function searches an item with key equal to hash( key_type( key )) in the map, - unlinks it from the map, and returns a guarded pointer to the item found. - If \p key is not found the function returns an empty guarded pointer. - - The item extracted is freed automatically by garbage collector \p GC - when returned \p guarded_ptr object will be destroyed or released. - @note Each \p guarded_ptr object uses the GC's guard that can be limited resource. - - Usage: - \code - typedef cds::container::MultiLevelHashMap< cds::gc::HP, int, foo, my_traits > map_type; - map_type theMap; - // ... - { - map_type::guarded_ptr gp( theMap.extract( 5 )); - if ( gp ) { - // Deal with gp - // ... - } - // Destructor of gp releases internal HP guard and frees the pointer - } - \endcode - */ - template - guarded_ptr extract( K const& key ) - { - guarded_ptr gp; - typename gc::Guard guard; - node_type * p = base_class::do_erase( m_Hasher( key_type( key )), guard, []( node_type const&) -> bool {return true;} ); - - // p is guarded by HP - if ( p ) - gp.reset( p ); - return gp; - } - - /// Checks whether the map contains \p key - /** - The function searches the item by its hash that is equal to hash( key_type( key )) - and returns \p true if it is found, or \p false otherwise. - */ - template - bool contains( K const& key ) - { - return base_class::contains( m_Hasher( key_type( key )) ); - } - - /// Find the key \p key - /** - - The function searches the item by its hash that is equal to hash( key_type( key )) - 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 \p item.second. - - The function returns \p true if \p key is found, \p false otherwise. - */ - template - bool find( K const& key, Func f ) - { - return base_class::find( m_Hasher( key_type( key )), [&f](node_type& node) { f( node.m_Value );}); - } - - /// Finds the key \p key and return the item found - /** - The function searches the item with a hash equal to hash( key_type( key )) - and returns a guarded pointer to the item found. - If \p key is not found the function returns an empty guarded pointer. - - It is safe when a concurrent thread erases the item returned as \p guarded_ptr. - In this case the item will be freed later by garbage collector \p GC automatically - when \p guarded_ptr object will be destroyed or released. - @note Each \p guarded_ptr object uses one GC's guard which can be limited resource. - - Usage: - \code - typedef cds::container::MultiLevelHashMap< cds::gc::HP, int, foo, my_traits > map_type; - map_type theMap; - // ... - { - map_type::guarded_ptr gp( theMap.get( 5 )); - if ( gp ) { - // Deal with gp - //... - } - // Destructor of guarded_ptr releases internal HP guard - } - \endcode - */ - template - guarded_ptr get( K const& key ) - { - guarded_ptr gp; - { - typename gc::Guard guard; - gp.reset( base_class::search( m_Hasher( key_type( key )), guard )); - } - return gp; - } - - /// Clears the map (non-atomic) - /** - The function unlink all data node from the map. - The function is not atomic but is thread-safe. - After \p %clear() the map may not be empty because another threads may insert items. - */ - void clear() - { - base_class::clear(); - } - - /// Checks if the map is empty - /** - Emptiness is checked by item counting: if item count is zero then the map is empty. - Thus, the correct item counting feature is an important part of the map implementation. - */ - bool empty() const - { - return base_class::empty(); - } - - /// Returns item count in the map - 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_MultilevelHashMap_iterators - The map supports thread-safe iterators: you may iterate over the map in multi-threaded environment. - It is guaranteed that the iterators will remain valid even if another thread deletes the node the iterator points to: - Hazard Pointer embedded into the iterator object protects the node from physical reclamation. - - @note Since the iterator object contains hazard pointer that is a thread-local resource, - the iterator should not be passed to another thread. - - 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 conditon it1 == it2 - does not entail &(*it1) == &(*it2) - - helper member function \p release() that clears internal hazard pointer. - After \p release() the iterator points to \p nullptr but it still remain valid: further iterating is possible. - - During iteration you may safely erase any item from the set; - @ref erase_at() function call doesn't invalidate any iterator. - If some iterator points to the item to be erased, that item is not deleted immediately - but only after that iterator will be advanced forward or backward. - - @note It is possible the item can be iterated more that once, for example, if an iterator points to the item - in array node that is being splitted. - */ - ///@{ - /// Returns an iterator to the beginning of the map - iterator begin() - { - return base_class::template init_begin(); - } - - /// Returns an const iterator to the beginning of the map - const_iterator begin() const - { - return base_class::template init_begin(); - } - - /// Returns an const iterator to the beginning of the map - const_iterator cbegin() - { - return base_class::template init_begin(); - } - - /// Returns an iterator to the element following the last element of the map. This element acts as a placeholder; attempting to access it results in undefined behavior. - iterator end() - { - return base_class::template init_end(); - } - - /// Returns a const iterator to the element following the last element of the map. This element acts as a placeholder; attempting to access it results in undefined behavior. - const_iterator end() const - { - return base_class::template init_end(); - } - - /// Returns a const iterator to the element following the last element of the map. This element acts as a placeholder; attempting to access it results in undefined behavior. - const_iterator cend() - { - return base_class::template init_end(); - } - - /// Returns a reverse iterator to the first element of the reversed map - reverse_iterator rbegin() - { - return base_class::template init_rbegin(); - } - - /// Returns a const reverse iterator to the first element of the reversed map - const_reverse_iterator rbegin() const - { - return base_class::template init_rbegin(); - } - - /// Returns a const reverse iterator to the first element of the reversed map - const_reverse_iterator crbegin() - { - return base_class::template init_rbegin(); - } - - /// Returns a reverse iterator to the element following the last element of the reversed map - /** - 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::template init_rend(); - } - - /// Returns a const reverse iterator to the element following the last element of the reversed map - /** - 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::template init_rend(); - } - - /// Returns a const reverse iterator to the element following the last element of the reversed map - /** - 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::template init_rend(); - } - ///@} - }; - -}} // namespace cds::container - -#endif // #ifndef CDSLIB_CONTAINER_IMPL_MULTILEVEL_HASHMAP_H diff --git a/cds/container/impl/multilevel_hashset.h b/cds/container/impl/multilevel_hashset.h deleted file mode 100644 index 9d3341ba..00000000 --- a/cds/container/impl/multilevel_hashset.h +++ /dev/null @@ -1,562 +0,0 @@ -//$$CDS-header$$ - -#ifndef CDSLIB_CONTAINER_IMPL_MULTILEVEL_HASHSET_H -#define CDSLIB_CONTAINER_IMPL_MULTILEVEL_HASHSET_H - -#include -#include - -namespace cds { namespace container { - - /// Hash set based on multi-level array - /** @ingroup cds_nonintrusive_set - @anchor cds_container_MultilevelHashSet_hp - - Source: - - [2013] Steven Feldman, Pierre LaBorde, Damian Dechev "Concurrent Multi-level Arrays: - Wait-free Extensible Hash Maps" - - [From the paper] The hardest problem encountered while developing a parallel hash map is how to perform - a global resize, the process of redistributing the elements in a hash map that occurs when adding new - buckets. The negative impact of blocking synchronization is multiplied during a global resize, because all - threads will be forced to wait on the thread that is performing the involved process of resizing the hash map - and redistributing the elements. \p %MultilevelHashSet implementation avoids global resizes through new array - allocation. By allowing concurrent expansion this structure is free from the overhead of an explicit resize, - which facilitates concurrent operations. - - The presented design includes dynamic hashing, the use of sub-arrays within the hash map data structure; - which, in combination with perfect hashing, means that each element has a unique final, as well as current, position. - It is important to note that the perfect hash function required by our hash map is trivial to realize as - any hash function that permutes the bits of the key is suitable. This is possible because of our approach - to the hash function; we require that it produces hash values that are equal in size to that of the key. - We know that if we expand the hash map a fixed number of times there can be no collision as duplicate keys - are not provided for in the standard semantics of a hash map. - - \p %MultiLevelHashSet is a multi-level array which has an internal structure similar to a tree: - @image html multilevel_hashset.png - The multi-level array differs from a tree in that each position on the tree could hold an array of nodes or a single node. - A position that holds a single node is a \p dataNode which holds the hash value of a key and the value that is associated - with that key; it is a simple struct holding two variables. A \p dataNode in the multi-level array could be marked. - A \p markedDataNode refers to a pointer to a \p dataNode that has been bitmarked at the least significant bit (LSB) - of the pointer to the node. This signifies that this \p dataNode is contended. An expansion must occur at this node; - any thread that sees this \p markedDataNode will try to replace it with an \p arrayNode; which is a position that holds - an array of nodes. The pointer to an \p arrayNode is differentiated from that of a pointer to a \p dataNode by a bitmark - on the second-least significant bit. - - \p %MultiLevelHashSet multi-level array is similar to a tree in that we keep a pointer to the root, which is a memory array - called \p head. The length of the \p head memory array is unique, whereas every other \p arrayNode has a uniform length; - a normal \p arrayNode has a fixed power-of-two length equal to the binary logarithm of a variable called \p arrayLength. - The maximum depth of the tree, \p maxDepth, is the maximum number of pointers that must be followed to reach any node. - We define \p currentDepth as the number of memory arrays that we need to traverse to reach the \p arrayNode on which - we need to operate; this is initially one, because of \p head. - - That approach to the structure of the hash set uses an extensible hashing scheme; the hash value is treated as a bit - string and rehash incrementally. - - @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 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 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". RCU specialization - has a slightly different interface. - */ - template < - class GC - , typename T -#ifdef CDS_DOXYGEN_INVOKED - , class Traits = multilevel_hashset::traits -#else - , class Traits -#endif - > - class MultiLevelHashSet -#ifdef CDS_DOXYGEN_INVOKED - : protected cds::intrusive::MultiLevelHashSet< GC, T, Traits > -#else - : protected cds::container::details::make_multilevel_hashset< GC, T, Traits >::type -#endif - { - //@cond - typedef cds::container::details::make_multilevel_hashset< GC, T, Traits > maker; - typedef typename maker::type base_class; - //@endcond - - public: - typedef GC gc; ///< 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 gc::template guarded_ptr< value_type > guarded_ptr; ///< Guarded pointer - - /// Count of hazard pointers required - static CDS_CONSTEXPR size_t const c_nHazardPtrCount = base_class::c_nHazardPtrCount; - - typedef typename base_class::iterator iterator; ///< @ref cds_container_MultilevelHashSet_iterators "bidirectional iterator" type - typedef typename base_class::const_iterator const_iterator; ///< @ref cds_container_MultilevelHashSet_iterators "bidirectional const iterator" type - typedef typename base_class::reverse_iterator reverse_iterator; ///< @ref cds_container_MultilevelHashSet_iterators "bidirectional reverse iterator" type - typedef typename base_class::const_reverse_iterator const_reverse_iterator; ///< @ref cds_container_MultilevelHashSet_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. - */ - 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. - */ - 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 ); - } - - /// Deletes the item pointed by iterator \p iter - /** - 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& iter ) - { - return base_class::erase_at( iter ); - } - //@cond - bool erase_at( reverse_iterator const& iter ) - { - return base_class::erase_at( iter ); - } - //@endcond - - /// Extracts the item with specified \p hash - /** - The function searches \p hash in the set, - 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 - when returned \ref guarded_ptr object to be destroyed or released. - @note Each \p guarded_ptr object uses the GC's guard that can be limited resource. - - Usage: - \code - typedef cds::container::MultiLevelHashSet< your_template_args > my_set; - my_set theSet; - // ... - { - my_set::guarded_ptr gp( theSet.extract( 5 )); - if ( gp ) { - // Deal with gp - // ... - } - // Destructor of gp releases internal HP guard - } - \endcode - */ - guarded_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 guarded pointer to the item found. - If \p hash is not found the function returns an empty \p guarded_ptr. - - @note Each \p guarded_ptr object uses one GC's guard which can be limited resource. - - Usage: - \code - typedef cds::container::MultiLevelHashSet< your_template_params > my_set; - my_set theSet; - // ... - { - my_set::guarded_ptr gp( theSet.get( 5 )); - if ( theSet.get( 5 )) { - // Deal with gp - //... - } - // Destructor of guarded_ptr releases internal HP guard - } - \endcode - */ - guarded_ptr 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_iterators - The set supports thread-safe iterators: you may iterate over the set in multi-threaded environment. - It is guaranteed that the iterators will remain valid even if another thread deletes the node the iterator points to: - Hazard Pointer embedded into the iterator object protects the node from physical reclamation. - - @note Since the iterator object contains hazard pointer that is a thread-local resource, - the iterator should not be passed to another thread. - - 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 conditon it1 == it2 - does not entail &(*it1) == &(*it2) - - helper member function \p release() that clears internal hazard pointer. - After \p release() the iterator points to \p nullptr but it still remain valid: further iterating is possible. - - During iteration you may safely erase any item from the set; - @ref erase_at() function call doesn't invalidate any iterator. - If some iterator points to the item to be erased, that item is not deleted immediately - but only after that iterator will be advanced forward or backward. - - @note It is possible the item can be iterated more that once, for example, if an iterator points to the item - in 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_IMPL_MULTILEVEL_HASHSET_H diff --git a/cds/container/multilevel_hashmap_dhp.h b/cds/container/multilevel_hashmap_dhp.h deleted file mode 100644 index 1f898b59..00000000 --- a/cds/container/multilevel_hashmap_dhp.h +++ /dev/null @@ -1,9 +0,0 @@ -//$$CDS-header$$ - -#ifndef CDSLIB_CONTAINER_MULTILEVEL_HASHMAP_DHP_H -#define CDSLIB_CONTAINER_MULTILEVEL_HASHMAP_DHP_H - -#include -#include - -#endif // #ifndef CDSLIB_CONTAINER_MULTILEVEL_HASHMAP_DHP_H diff --git a/cds/container/multilevel_hashmap_hp.h b/cds/container/multilevel_hashmap_hp.h deleted file mode 100644 index f38c6267..00000000 --- a/cds/container/multilevel_hashmap_hp.h +++ /dev/null @@ -1,9 +0,0 @@ -//$$CDS-header$$ - -#ifndef CDSLIB_CONTAINER_MULTILEVEL_HASHMAP_HP_H -#define CDSLIB_CONTAINER_MULTILEVEL_HASHMAP_HP_H - -#include -#include - -#endif // #ifndef CDSLIB_CONTAINER_MULTILEVEL_HASHMAP_HP_H diff --git a/cds/container/multilevel_hashmap_rcu.h b/cds/container/multilevel_hashmap_rcu.h deleted file mode 100644 index c049b436..00000000 --- a/cds/container/multilevel_hashmap_rcu.h +++ /dev/null @@ -1,780 +0,0 @@ -//$$CDS-header$$ - -#ifndef CDSLIB_CONTAINER_MULTILEVEL_HASHMAP_RCU_H -#define CDSLIB_CONTAINER_MULTILEVEL_HASHMAP_RCU_H - -#include -#include - -namespace cds { namespace container { - - /// Hash map based on multi-level array - /** @ingroup cds_nonintrusive_map - @anchor cds_container_MultilevelHashMap_rcu - - Source: - - [2013] Steven Feldman, Pierre LaBorde, Damian Dechev "Concurrent Multi-level Arrays: - Wait-free Extensible Hash Maps" - - See algorithm short description @ref cds_container_MultilevelHashMap_hp "here" - - @note Two important things you should keep in mind when you're using \p %MultiLevelHashMap: - - all keys is converted to fixed-size bit-string by hash functor provided. - You can use variable-length keys, for example, \p std::string as a key for \p %MultiLevelHashMap, - but real key in the map will be fixed-size hash values of your keys. - For the strings you may 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 such hash values will be the keys in \p %MultiLevelHashMap. - If your key is fixed-sized the hash functor is optional, see \p multilevel_hashmap::traits::hash for explanation and examples. - - \p %MultiLevelHashMap 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 map. \p %MultiLevelHashMap does not maintain the key, - it maintains its fixed-size hash value. - - The map supports @ref cds_container_MultilevelHashMap_rcu_iterators "bidirectional thread-safe iterators". - - Template parameters: - - \p RCU - one of \ref cds_urcu_gc "RCU type" - - \p Key - a key type to be stored in the map - - \p T - a value type to be stored in the map - - \p Traits - type traits, the structure based on \p multilevel_hashmap::traits or result of \p multilevel_hashmap::make_traits metafunction. - - @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. - */ - template < - class RCU - ,typename Key - ,typename T -#ifdef CDS_DOXYGEN_INVOKED - ,class Traits = multilevel_hashmap::traits -#else - ,class Traits -#endif - > - class MultiLevelHashMap< cds::urcu::gc< RCU >, Key, T, Traits > -#ifdef CDS_DOXYGEN_INVOKED - : protected cds::intrusive::MultiLevelHashSet< cds::urcu::gc< RCU >, std::pair, Traits > -#else - : protected cds::container::details::make_multilevel_hashmap< cds::urcu::gc< RCU >, Key, T, Traits >::type -#endif - { - //@cond - typedef cds::container::details::make_multilevel_hashmap< cds::urcu::gc< RCU >, Key, T, Traits > maker; - typedef typename maker::type base_class; - //@endcond - public: - typedef cds::urcu::gc< RCU > gc; ///< RCU garbage collector - typedef Key key_type; ///< Key type - typedef T mapped_type; ///< Mapped type - typedef std::pair< key_type const, mapped_type> value_type; ///< Key-value pair to be stored in the map - typedef Traits traits; ///< Map traits -#ifdef CDS_DOXYGEN_INVOKED - typedef typename traits::hash hasher; ///< Hash functor, see \p multilevel_hashmap::traits::hash -#else - typedef typename maker::hasher hasher; -#endif - - typedef typename maker::hash_type hash_type; ///< Hash type deduced from \p hasher return type - typedef typename base_class::hash_comparator hash_comparator; ///< hash compare functor based on \p Traits::compare and \p Traits::less - 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 - - protected: - //@cond - typedef typename maker::node_type node_type; - typedef typename maker::cxx_node_allocator cxx_node_allocator; - typedef std::unique_ptr< node_type, typename maker::node_disposer > scoped_node_ptr; - typedef typename base_class::check_deadlock_policy check_deadlock_policy; - - struct node_cast - { - value_type * operator()(node_type * p) const - { - return p ? &p->m_Value : nullptr; - } - }; - - public: - /// pointer to extracted node - using exempt_ptr = cds::urcu::exempt_ptr< gc, node_type, value_type, typename base_class::disposer, node_cast >; - - protected: - template - class bidirectional_iterator: public base_class::iterator_base - { - friend class MultiLevelHashMap; - typedef typename base_class::iterator_base iterator_base; - - protected: - static CDS_CONSTEXPR bool const c_bConstantIterator = IsConst; - - public: - typedef typename std::conditional< IsConst, value_type const*, value_type*>::type value_ptr; ///< Value pointer - typedef typename std::conditional< IsConst, value_type const&, value_type&>::type value_ref; ///< Value reference - - public: - bidirectional_iterator() CDS_NOEXCEPT - {} - - bidirectional_iterator( bidirectional_iterator const& rhs ) CDS_NOEXCEPT - : iterator_base( rhs ) - {} - - bidirectional_iterator& operator=(bidirectional_iterator const& rhs) CDS_NOEXCEPT - { - iterator_base::operator=( rhs ); - return *this; - } - - bidirectional_iterator& operator++() - { - iterator_base::operator++(); - return *this; - } - - bidirectional_iterator& operator--() - { - iterator_base::operator--(); - return *this; - } - - value_ptr operator ->() const CDS_NOEXCEPT - { - node_type * p = iterator_base::pointer(); - return p ? &p->m_Value : nullptr; - } - - value_ref operator *() const CDS_NOEXCEPT - { - node_type * p = iterator_base::pointer(); - assert( p ); - return p->m_Value; - } - - void release() - { - iterator_base::release(); - } - - template - bool operator ==(bidirectional_iterator const& rhs) const CDS_NOEXCEPT - { - return iterator_base::operator==( rhs ); - } - - template - bool operator !=(bidirectional_iterator const& rhs) const CDS_NOEXCEPT - { - return !( *this == rhs ); - } - - public: // for internal use only! - bidirectional_iterator( base_class const& set, typename base_class::array_node * pNode, size_t idx, bool ) - : iterator_base( set, pNode, idx, false ) - {} - - bidirectional_iterator( base_class const& set, typename base_class::array_node * pNode, size_t idx ) - : iterator_base( set, pNode, idx ) - {} - }; - - /// Reverse bidirectional iterator - template - class reverse_bidirectional_iterator : public base_class::iterator_base - { - friend class MultiLevelHashMap; - typedef typename base_class::iterator_base iterator_base; - - public: - typedef typename std::conditional< IsConst, value_type const*, value_type*>::type value_ptr; ///< Value pointer - typedef typename std::conditional< IsConst, value_type const&, value_type&>::type value_ref; ///< Value reference - - public: - reverse_bidirectional_iterator() CDS_NOEXCEPT - : iterator_base() - {} - - reverse_bidirectional_iterator( reverse_bidirectional_iterator const& rhs ) CDS_NOEXCEPT - : iterator_base( rhs ) - {} - - reverse_bidirectional_iterator& operator=( reverse_bidirectional_iterator const& rhs) CDS_NOEXCEPT - { - iterator_base::operator=( rhs ); - return *this; - } - - reverse_bidirectional_iterator& operator++() - { - iterator_base::operator--(); - return *this; - } - - reverse_bidirectional_iterator& operator--() - { - iterator_base::operator++(); - return *this; - } - - value_ptr operator ->() const CDS_NOEXCEPT - { - node_type * p = iterator_base::pointer(); - return p ? &p->m_Value : nullptr; - } - - value_ref operator *() const CDS_NOEXCEPT - { - node_type * p = iterator_base::pointer(); - assert( p ); - return p->m_Value; - } - - void release() - { - iterator_base::release(); - } - - template - bool operator ==(reverse_bidirectional_iterator const& rhs) const - { - return iterator_base::operator==( rhs ); - } - - template - bool operator !=(reverse_bidirectional_iterator const& rhs) - { - return !( *this == rhs ); - } - - public: // for internal use only! - reverse_bidirectional_iterator( base_class const& set, typename base_class::array_node * pNode, size_t idx, bool ) - : iterator_base( set, pNode, idx, false ) - {} - - reverse_bidirectional_iterator( base_class const& set, typename base_class::array_node * pNode, size_t idx ) - : iterator_base( set, pNode, idx, false ) - { - iterator_base::backward(); - } - }; - //@endcond - - public: -#ifdef CDS_DOXYGEN_INVOKED - typedef implementation_defined iterator; ///< @ref cds_container_MultilevelHashMap_rcu_iterators "bidirectional iterator" type - typedef implementation_defined const_iterator; ///< @ref cds_container_MultilevelHashMap_rcu_iterators "bidirectional const iterator" type - typedef implementation_defined reverse_iterator; ///< @ref cds_container_MultilevelHashMap_rcu_iterators "bidirectional reverse iterator" type - typedef implementation_defined const_reverse_iterator; ///< @ref cds_container_MultilevelHashMap_rcu_iterators "bidirectional reverse const iterator" type -#else - typedef bidirectional_iterator iterator; - typedef bidirectional_iterator const_iterator; - typedef reverse_bidirectional_iterator reverse_iterator; - typedef reverse_bidirectional_iterator const_reverse_iterator; -#endif - - protected: - //@cond - hasher m_Hasher; - //@endcond - - public: - /// Creates empty map - /** - @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. - */ - MultiLevelHashMap( size_t head_bits = 8, size_t array_bits = 4 ) - : base_class( head_bits, array_bits ) - {} - - /// Destructs the map and frees all data - ~MultiLevelHashMap() - {} - - /// Inserts new element with key and default value - /** - The function creates an element with \p key and default value, and then inserts the node created into the map. - - Preconditions: - - The \p key_type should be constructible from a value of type \p K. - In trivial case, \p K is equal to \p key_type. - - The \p mapped_type should be default-constructible. - - Returns \p true if inserting successful, \p false otherwise. - - The function locks RCU internally. - */ - template - bool insert( K&& key ) - { - scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward(key) )); - if ( base_class::insert( *sp )) { - sp.release(); - return true; - } - return false; - } - - /// Inserts new element - /** - The function creates a node with copy of \p val value - and then inserts the node created into the map. - - Preconditions: - - The \p key_type should be constructible from \p key of type \p K. - - The \p value_type should be constructible from \p val of type \p V. - - Returns \p true if \p val is inserted into the map, \p false otherwise. - - The function locks RCU internally. - */ - template - bool insert( K&& key, V&& val ) - { - scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward(key), std::forward(val))); - if ( base_class::insert( *sp )) { - sp.release(); - return true; - } - return false; - } - - /// Inserts new element and initialize it by a functor - /** - This function inserts new element with key \p key and if inserting is successful then it calls - \p func functor with signature - \code - struct functor { - void operator()( value_type& item ); - }; - \endcode - - The argument \p item of user-defined functor \p func is the reference - to the map's item inserted: - - item.first is a const reference to item's key that cannot be changed. - - item.second is a reference to item's value that may be changed. - - \p key_type should be constructible from value of type \p K. - - The function allows to split creating of new item into two part: - - create item from \p key; - - insert new item into the map; - - if inserting is successful, initialize the value of item by calling \p func functor - - This can be useful if complete initialization of object of \p value_type is heavyweight and - it is preferable that the initialization should be completed only if inserting is successful. - - The function locks RCU internally. - */ - template - bool insert_with( K&& key, Func func ) - { - scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward(key))); - if ( base_class::insert( *sp, [&func]( node_type& item ) { func( item.m_Value ); } )) { - sp.release(); - return true; - } - return false; - } - - /// For key \p key inserts data of type \p value_type created in-place from std::forward(args)... - /** - Returns \p true if inserting successful, \p false otherwise. - - The function locks RCU internally. - */ - template - bool emplace( K&& key, Args&&... args ) - { - scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward(key), std::forward(args)... )); - if ( base_class::insert( *sp )) { - sp.release(); - return true; - } - return false; - } - - /// Updates data by \p key - /** - The operation performs inserting or replacing the element with lock-free manner. - - If the \p key not found in the map, then the new item created from \p key - will be inserted into the map iff \p bInsert is \p true - (note that in this case the \ref key_type should be constructible from type \p K). - Otherwise, if \p key is found, it is replaced with a new item created from - \p key. - The functor \p Func signature: - \code - struct my_functor { - void operator()( value_type& item, value_type * old ); - }; - \endcode - where: - - \p item - item of the map - - \p old - old item of the map, if \p nullptr - the new item was inserted - - The functor may change any fields of the \p item.second. - - Returns std::pair where \p first is \p true if operation is successfull, - \p second is \p true if new item has been added or \p false if \p key already exists. - - The function locks RCU internally. - - @warning See \ref cds_intrusive_item_creating "insert item troubleshooting" - */ - template - std::pair update( K&& key, Func func, bool bInsert = true ) - { - scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward(key))); - std::pair result = base_class::do_update( *sp, - [&func]( node_type& node, node_type * old ) { func( node.m_Value, old ? &old->m_Value : nullptr );}, - bInsert ); - if ( result.first ) - sp.release(); - return result; - } - - /// Delete \p key from the map - /** - \p key_type must be constructible from value of type \p K. - The function deeltes the element with hash value equal to hash( key_type( key )) - - Return \p true if \p key is found and deleted, \p false otherwise. - - RCU should not be locked. The function locks RCU internally. - */ - template - bool erase( K const& key ) - { - return base_class::erase(m_Hasher(key_type(key))); - } - - /// Delete \p key from the map - /** - The function searches an item with hash value equal to hash( key_type( key )), - calls \p f functor and deletes the item. If \p key is not found, the functor is not called. - - The functor \p Func interface: - \code - struct extractor { - void operator()(value_type& item) { ... } - }; - \endcode - where \p item is the element found. - - \p key_type must be constructible from value of type \p K. - - Return \p true if key is found and deleted, \p false otherwise - - RCU should not be locked. The function locks RCU internally. - */ - template - bool erase( K const& key, Func f ) - { - return base_class::erase(m_Hasher(key_type(key)), [&f]( node_type& node) { f( node.m_Value ); }); - } - - /// Extracts the item from the map with specified \p key - /** - The function searches an item with key equal to hash( key_type( key )) in the map, - unlinks it from the map, and returns a guarded pointer to the item found. - If \p key is not found the function returns an empty guarded pointer. - - 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::MultiLevelHashMap< cds::urcu::gc< cds::urcu::general_buffered<>>, int, foo, my_traits > map_type; - map_type theMap; - // ... - - typename map_type::exempt_ptr ep( theMap.extract( 5 )); - if ( ep ) { - // Deal with ep - //... - - // Dispose returned item. - ep.release(); - } - \endcode - */ - template - exempt_ptr extract( K const& key ) - { - check_deadlock_policy::check(); - - node_type * p; - { - rcu_lock rcuLock; - p = base_class::do_erase( m_Hasher( key_type(key)), [](node_type const&) -> bool {return true;}); - } - return exempt_ptr(p); - } - - /// Checks whether the map contains \p key - /** - The function searches the item by its hash that is equal to hash( key_type( key )) - and returns \p true if it is found, or \p false otherwise. - */ - template - bool contains( K const& key ) - { - return base_class::contains( m_Hasher( key_type( key )) ); - } - - /// Find the key \p key - /** - - The function searches the item by its hash that is equal to hash( key_type( key )) - 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 \p item.second. - - The function returns \p true if \p key is found, \p false otherwise. - */ - template - bool find( K const& key, Func f ) - { - return base_class::find( m_Hasher( key_type( key )), [&f](node_type& node) { f( node.m_Value );}); - } - - /// Finds the key \p key and return 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::MultiLevelHashMap< your_template_params > my_map; - my_map theMap; - // ... - { - // lock RCU - my_map::rcu_lock; - - foo * p = theMap.get( 5 ); - if ( p ) { - // Deal with p - //... - } - } - \endcode - */ - template - value_type * get( K const& key ) - { - node_type * p = base_class::get( m_Hasher( key_type( key ))); - return p ? &p->m_Value : nullptr; - } - - /// Clears the map (non-atomic) - /** - The function unlink all data node from the map. - The function is not atomic but is thread-safe. - After \p %clear() the map may not be empty because another threads may insert items. - */ - void clear() - { - base_class::clear(); - } - - /// Checks if the map is empty - /** - Emptiness is checked by item counting: if item count is zero then the map is empty. - Thus, the correct item counting feature is an important part of the map implementation. - */ - bool empty() const - { - return base_class::empty(); - } - - /// Returns item count in the map - 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_MultilevelHashMap_rcu_iterators - The map supports thread-safe iterators: you may iterate over the map 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 map - 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 { - // ... other fields - uint32_t payload; // only for example - }; - typedef cds::urcu::gc< cds::urcu::general_buffered<>> rcu; - typedef cds::container::MultiLevelHashMap< rcu, std::string, foo> map_type; - - map_type m; - - // ... - - // iterate over the map - { - // lock the RCU. - typename set_type::rcu_lock l; // scoped RCU lock - - // traverse the map - for ( auto i = m.begin(); i != s.end(); ++i ) { - // deal with i. Remember, erasing is prohibited here! - i->second.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 map - iterator begin() - { - return base_class::template init_begin(); - } - - /// Returns an const iterator to the beginning of the map - const_iterator begin() const - { - return base_class::template init_begin(); - } - - /// Returns an const iterator to the beginning of the map - const_iterator cbegin() - { - return base_class::template init_begin(); - } - - /// Returns an iterator to the element following the last element of the map. This element acts as a placeholder; attempting to access it results in undefined behavior. - iterator end() - { - return base_class::template init_end(); - } - - /// Returns a const iterator to the element following the last element of the map. This element acts as a placeholder; attempting to access it results in undefined behavior. - const_iterator end() const - { - return base_class::template init_end(); - } - - /// Returns a const iterator to the element following the last element of the map. This element acts as a placeholder; attempting to access it results in undefined behavior. - const_iterator cend() - { - return base_class::template init_end(); - } - - /// Returns a reverse iterator to the first element of the reversed map - reverse_iterator rbegin() - { - return base_class::template init_rbegin(); - } - - /// Returns a const reverse iterator to the first element of the reversed map - const_reverse_iterator rbegin() const - { - return base_class::template init_rbegin(); - } - - /// Returns a const reverse iterator to the first element of the reversed map - const_reverse_iterator crbegin() - { - return base_class::template init_rbegin(); - } - - /// Returns a reverse iterator to the element following the last element of the reversed map - /** - 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::template init_rend(); - } - - /// Returns a const reverse iterator to the element following the last element of the reversed map - /** - 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::template init_rend(); - } - - /// Returns a const reverse iterator to the element following the last element of the reversed map - /** - 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::template init_rend(); - } - ///@} - }; -}} // namespace cds::container - -#endif // #ifndef CDSLIB_CONTAINER_MULTILEVEL_HASHMAP_RCU_H diff --git a/cds/container/multilevel_hashset_dhp.h b/cds/container/multilevel_hashset_dhp.h deleted file mode 100644 index 66b62b85..00000000 --- a/cds/container/multilevel_hashset_dhp.h +++ /dev/null @@ -1,9 +0,0 @@ -//$$CDS-header$$ - -#ifndef CDSLIB_CONTAINER_MULTILEVEL_HASHSET_DHP_H -#define CDSLIB_CONTAINER_MULTILEVEL_HASHSET_DHP_H - -#include -#include - -#endif // #ifndef CDSLIB_CONTAINER_MULTILEVEL_HASHSET_DHP_H diff --git a/cds/container/multilevel_hashset_hp.h b/cds/container/multilevel_hashset_hp.h deleted file mode 100644 index 34dd032c..00000000 --- a/cds/container/multilevel_hashset_hp.h +++ /dev/null @@ -1,9 +0,0 @@ -//$$CDS-header$$ - -#ifndef CDSLIB_CONTAINER_MULTILEVEL_HASHSET_HP_H -#define CDSLIB_CONTAINER_MULTILEVEL_HASHSET_HP_H - -#include -#include - -#endif // #ifndef CDSLIB_CONTAINER_MULTILEVEL_HASHSET_HP_H diff --git a/cds/container/multilevel_hashset_rcu.h b/cds/container/multilevel_hashset_rcu.h deleted file mode 100644 index fdd1f5ed..00000000 --- a/cds/container/multilevel_hashset_rcu.h +++ /dev/null @@ -1,550 +0,0 @@ -//$$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_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. - - 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. - - RCU should not be locked. The function locks RCU internally. - */ - 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. - - RCU should not be locked. The function locks RCU internally. - */ - 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/details/feldman_hashset_base.h b/cds/intrusive/details/feldman_hashset_base.h new file mode 100644 index 00000000..cb37cc29 --- /dev/null +++ b/cds/intrusive/details/feldman_hashset_base.h @@ -0,0 +1,300 @@ +//$$CDS-header$$ + +#ifndef CDSLIB_INTRUSIVE_DETAILS_FELDMAN_HASHSET_BASE_H +#define CDSLIB_INTRUSIVE_DETAILS_FELDMAN_HASHSET_BASE_H + +#include // memcmp, memcpy +#include + +#include +#include +#include +#include +#include +#include + +namespace cds { namespace intrusive { + + /// FeldmanHashSet related definitions + /** @ingroup cds_intrusive_helper + */ + namespace feldman_hashset { + /// Hash accessor option + /** + @copydetails traits::hash_accessor + */ + template + struct hash_accessor { + //@cond + template struct pack: public Base + { + typedef Accessor hash_accessor; + }; + //@endcond + }; + + /// \p FeldmanHashSet internal statistics + template + struct stat { + typedef EventCounter event_counter ; ///< Event counter type + + event_counter m_nInsertSuccess; ///< Number of success \p insert() operations + event_counter m_nInsertFailed; ///< Number of failed \p insert() operations + event_counter m_nInsertRetry; ///< Number of attempts to insert new item + event_counter m_nUpdateNew; ///< Number of new item inserted for \p update() + event_counter m_nUpdateExisting; ///< Number of existing item updates + event_counter m_nUpdateFailed; ///< Number of failed \p update() call + event_counter m_nUpdateRetry; ///< Number of attempts to update the item + event_counter m_nEraseSuccess; ///< Number of successful \p erase(), \p unlink(), \p extract() operations + event_counter m_nEraseFailed; ///< Number of failed \p erase(), \p unlink(), \p extract() operations + event_counter m_nEraseRetry; ///< Number of attempts to \p erase() an item + event_counter m_nFindSuccess; ///< Number of successful \p find() and \p get() operations + event_counter m_nFindFailed; ///< Number of failed \p find() and \p get() operations + + event_counter m_nExpandNodeSuccess; ///< Number of succeeded attempts converting data node to array node + event_counter m_nExpandNodeFailed; ///< Number of failed attempts converting data node to array node + 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 + + event_counter m_nArrayNodeCount; ///< Number of array nodes + event_counter m_nHeight; ///< Current height of the tree + + //@cond + void onInsertSuccess() { ++m_nInsertSuccess; } + void onInsertFailed() { ++m_nInsertFailed; } + void onInsertRetry() { ++m_nInsertRetry; } + void onUpdateNew() { ++m_nUpdateNew; } + void onUpdateExisting() { ++m_nUpdateExisting; } + void onUpdateFailed() { ++m_nUpdateFailed; } + void onUpdateRetry() { ++m_nUpdateRetry; } + void onEraseSuccess() { ++m_nEraseSuccess; } + void onEraseFailed() { ++m_nEraseFailed; } + void onEraseRetry() { ++m_nEraseRetry; } + void onFindSuccess() { ++m_nFindSuccess; } + void onFindFailed() { ++m_nFindFailed; } + + void onExpandNodeSuccess() { ++m_nExpandNodeSuccess; } + void onExpandNodeFailed() { ++m_nExpandNodeFailed; } + void onSlotChanged() { ++m_nSlotChanged; } + void onSlotConverting() { ++m_nSlotConverting; } + void onArrayNodeCreated() { ++m_nArrayNodeCount; } + void height( size_t h ) { if (m_nHeight < h ) m_nHeight = h; } + //@endcond + }; + + /// \p FeldmanHashSet empty internal statistics + struct empty_stat { + //@cond + void onInsertSuccess() const {} + void onInsertFailed() const {} + void onInsertRetry() const {} + void onUpdateNew() const {} + void onUpdateExisting() const {} + void onUpdateFailed() const {} + void onUpdateRetry() const {} + void onEraseSuccess() const {} + void onEraseFailed() const {} + void onEraseRetry() const {} + void onFindSuccess() const {} + void onFindFailed() const {} + + void onExpandNodeSuccess() const {} + void onExpandNodeFailed() const {} + void onSlotChanged() const {} + void onSlotConverting() const {} + void onArrayNodeCreated() const {} + void height(size_t) const {} + //@endcond + }; + + /// \p FeldmanHashSet traits + struct traits + { + /// Mandatory functor to get hash value from data node + /** + It is most-important feature of \p FeldmanHashSet. + That functor must return a reference to fixed-sized hash value of data node. + The return value of that functor specifies the type of hash value. + + Example: + \code + typedef uint8_t hash_type[32]; // 256-bit hash type + struct foo { + hash_type hash; // 256-bit hash value + // ... other fields + }; + + // Hash accessor + struct foo_hash_accessor { + hash_type const& operator()( foo const& d ) const + { + return d.hash; + } + }; + \endcode + */ + typedef cds::opt::none hash_accessor; + + /// Disposer for removing data nodes + 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 cds::opt::none compare; + + /// Specifies binary predicate used for hash compare. + /** + If \p %less and \p %compare are not specified, \p memcmp() -like @ref bitwise_compare "bit-wise hash comparator" is used + because the hash value is treated as fixed-sized bit-string. + */ + typedef cds::opt::none less; + + /// Item counter + /** + The item counting is an important part of \p FeldmanHashSet algorithm: + the \p empty() member function depends on correct item counting. + Therefore, \p atomicity::empty_item_counter is not allowed as a type of the option. + + Default is \p atomicity::item_counter. + */ + typedef cds::atomicity::item_counter item_counter; + + /// Array node allocator + /** + Allocator for array nodes. That allocator is used for creating \p headNode and \p arrayNode when the set grows. + Default is \ref CDS_DEFAULT_ALLOCATOR + */ + typedef CDS_DEFAULT_ALLOCATOR node_allocator; + + /// C++ memory ordering model + /** + Can be \p opt::v::relaxed_ordering (relaxed memory model, the default) + or \p opt::v::sequential_consistent (sequentially consisnent memory model). + */ + typedef cds::opt::v::relaxed_ordering memory_model; + + /// Back-off strategy + typedef cds::backoff::Default back_off; + + /// Internal statistics + /** + By default, internal statistics is disabled (\p feldman_hashset::empty_stat). + Use \p feldman_hashset::stat to enable it. + */ + typedef empty_stat stat; + + /// RCU deadlock checking policy (only for \ref cds_intrusive_FeldmanHashSet_rcu "RCU-based FeldmanHashSet") + /** + List of available policy see \p opt::rcu_check_deadlock + */ + typedef cds::opt::v::rcu_throw_deadlock rcu_check_deadlock; + }; + + /// Metafunction converting option list to \p feldman_hashset::traits + /** + Supported \p Options are: + - \p feldman_hashset::hash_accessor - mandatory option, hash accessor functor. + @copydetails traits::hash_accessor + - \p opt::node_allocator - array node allocator. + @copydetails traits::node_allocator + - \p opt::compare - hash comparison functor. No default functor is provided. + If the option is not specified, the \p opt::less is used. + - \p opt::less - specifies binary predicate used for hash comparison. + 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. + - \p opt::back_off - back-off strategy used. If the option is not specified, the \p cds::backoff::Default is used. + - \p opt::disposer - the functor used for disposing removed data node. Default is \p opt::v::empty_disposer. Due the nature + of GC schema the disposer may be called asynchronously. + - \p opt::item_counter - the type of item counting feature. + The item counting is an important part of \p FeldmanHashSet algorithm: + the \p empty() member function depends on correct item counting. + Therefore, \p atomicity::empty_item_counter is not allowed as a type of the option. + Default is \p atomicity::item_counter. + - \p opt::memory_model - C++ memory ordering model. Can be \p opt::v::relaxed_ordering (relaxed memory model, the default) + or \p opt::v::sequential_consistent (sequentially consisnent memory model). + - \p opt::stat - internal statistics. By default, it is disabled (\p feldman_hashset::empty_stat). + To enable it use \p feldman_hashset::stat + - \p opt::rcu_check_deadlock - a deadlock checking policy for \ref cds_intrusive_FeldmanHashSet_rcu "RCU-based FeldmanHashSet" + Default is \p opt::v::rcu_throw_deadlock + */ + template + struct make_traits + { +# ifdef CDS_DOXYGEN_INVOKED + typedef implementation_defined type ; ///< Metafunction result +# else + typedef typename cds::opt::make_options< + typename cds::opt::find_type_traits< traits, Options... >::type + ,Options... + >::type type; +# endif + }; + + /// Bit-wise memcmp-based comparator for hash value \p T + 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)); + } + }; + + //@cond + namespace details { + template + using hash_splitter = cds::algo::split_bitstring< HashType, UInt >; + + struct metrics { + size_t head_node_size; // power-of-two + size_t head_node_size_log; // log2( head_node_size ) + size_t array_node_size; // power-of-two + size_t array_node_size_log;// log2( array_node_size ) + + static metrics make(size_t head_bits, size_t array_bits, size_t hash_size ) + { + size_t const hash_bits = hash_size * 8; + + if (array_bits < 2) + array_bits = 2; + if (head_bits < 4) + head_bits = 4; + if (head_bits > hash_bits) + head_bits = hash_bits; + if ((hash_bits - head_bits) % array_bits != 0) + head_bits += (hash_bits - head_bits) % array_bits; + + assert((hash_bits - head_bits) % array_bits == 0); + + metrics m; + m.head_node_size_log = head_bits; + m.head_node_size = size_t(1) << head_bits; + m.array_node_size_log = array_bits; + m.array_node_size = size_t(1) << array_bits; + return m; + } + }; + + } // namespace details + //@endcond + } // namespace feldman_hashset + + //@cond + // Forward declaration + template < class GC, typename T, class Traits = feldman_hashset::traits > + class FeldmanHashSet; + //@endcond + +}} // namespace cds::intrusive + +#endif // #ifndef CDSLIB_INTRUSIVE_DETAILS_FELDMAN_HASHSET_BASE_H diff --git a/cds/intrusive/details/multilevel_hashset_base.h b/cds/intrusive/details/multilevel_hashset_base.h deleted file mode 100644 index 1327a0a2..00000000 --- a/cds/intrusive/details/multilevel_hashset_base.h +++ /dev/null @@ -1,300 +0,0 @@ -//$$CDS-header$$ - -#ifndef CDSLIB_INTRUSIVE_DETAILS_MULTILEVEL_HASHSET_BASE_H -#define CDSLIB_INTRUSIVE_DETAILS_MULTILEVEL_HASHSET_BASE_H - -#include // memcmp, memcpy -#include - -#include -#include -#include -#include -#include -#include - -namespace cds { namespace intrusive { - - /// MultiLevelHashSet related definitions - /** @ingroup cds_intrusive_helper - */ - namespace multilevel_hashset { - /// Hash accessor option - /** - @copydetails traits::hash_accessor - */ - template - struct hash_accessor { - //@cond - template struct pack: public Base - { - typedef Accessor hash_accessor; - }; - //@endcond - }; - - /// \p MultiLevelHashSet internal statistics - template - struct stat { - typedef EventCounter event_counter ; ///< Event counter type - - event_counter m_nInsertSuccess; ///< Number of success \p insert() operations - event_counter m_nInsertFailed; ///< Number of failed \p insert() operations - event_counter m_nInsertRetry; ///< Number of attempts to insert new item - event_counter m_nUpdateNew; ///< Number of new item inserted for \p update() - event_counter m_nUpdateExisting; ///< Number of existing item updates - event_counter m_nUpdateFailed; ///< Number of failed \p update() call - event_counter m_nUpdateRetry; ///< Number of attempts to update the item - event_counter m_nEraseSuccess; ///< Number of successful \p erase(), \p unlink(), \p extract() operations - event_counter m_nEraseFailed; ///< Number of failed \p erase(), \p unlink(), \p extract() operations - event_counter m_nEraseRetry; ///< Number of attempts to \p erase() an item - event_counter m_nFindSuccess; ///< Number of successful \p find() and \p get() operations - event_counter m_nFindFailed; ///< Number of failed \p find() and \p get() operations - - event_counter m_nExpandNodeSuccess; ///< Number of succeeded attempts converting data node to array node - event_counter m_nExpandNodeFailed; ///< Number of failed attempts converting data node to array node - 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 - - event_counter m_nArrayNodeCount; ///< Number of array nodes - event_counter m_nHeight; ///< Current height of the tree - - //@cond - void onInsertSuccess() { ++m_nInsertSuccess; } - void onInsertFailed() { ++m_nInsertFailed; } - void onInsertRetry() { ++m_nInsertRetry; } - void onUpdateNew() { ++m_nUpdateNew; } - void onUpdateExisting() { ++m_nUpdateExisting; } - void onUpdateFailed() { ++m_nUpdateFailed; } - void onUpdateRetry() { ++m_nUpdateRetry; } - void onEraseSuccess() { ++m_nEraseSuccess; } - void onEraseFailed() { ++m_nEraseFailed; } - void onEraseRetry() { ++m_nEraseRetry; } - void onFindSuccess() { ++m_nFindSuccess; } - void onFindFailed() { ++m_nFindFailed; } - - void onExpandNodeSuccess() { ++m_nExpandNodeSuccess; } - void onExpandNodeFailed() { ++m_nExpandNodeFailed; } - void onSlotChanged() { ++m_nSlotChanged; } - void onSlotConverting() { ++m_nSlotConverting; } - void onArrayNodeCreated() { ++m_nArrayNodeCount; } - void height( size_t h ) { if (m_nHeight < h ) m_nHeight = h; } - //@endcond - }; - - /// \p MultiLevelHashSet empty internal statistics - struct empty_stat { - //@cond - void onInsertSuccess() const {} - void onInsertFailed() const {} - void onInsertRetry() const {} - void onUpdateNew() const {} - void onUpdateExisting() const {} - void onUpdateFailed() const {} - void onUpdateRetry() const {} - void onEraseSuccess() const {} - void onEraseFailed() const {} - void onEraseRetry() const {} - void onFindSuccess() const {} - void onFindFailed() const {} - - void onExpandNodeSuccess() const {} - void onExpandNodeFailed() const {} - void onSlotChanged() const {} - void onSlotConverting() const {} - void onArrayNodeCreated() const {} - void height(size_t) const {} - //@endcond - }; - - /// \p MultiLevelHashSet traits - struct traits - { - /// Mandatory functor to get hash value from data node - /** - It is most-important feature of \p MultiLevelHashSet. - That functor must return a reference to fixed-sized hash value of data node. - The return value of that functor specifies the type of hash value. - - Example: - \code - typedef uint8_t hash_type[32]; // 256-bit hash type - struct foo { - hash_type hash; // 256-bit hash value - // ... other fields - }; - - // Hash accessor - struct foo_hash_accessor { - hash_type const& operator()( foo const& d ) const - { - return d.hash; - } - }; - \endcode - */ - typedef cds::opt::none hash_accessor; - - /// Disposer for removing data nodes - 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 cds::opt::none compare; - - /// Specifies binary predicate used for hash compare. - /** - If \p %less and \p %compare are not specified, \p memcmp() -like @ref bitwise_compare "bit-wise hash comparator" is used - because the hash value is treated as fixed-sized bit-string. - */ - typedef cds::opt::none less; - - /// Item counter - /** - The item counting is an important part of \p MultiLevelHashSet algorithm: - the \p empty() member function depends on correct item counting. - Therefore, \p atomicity::empty_item_counter is not allowed as a type of the option. - - Default is \p atomicity::item_counter. - */ - typedef cds::atomicity::item_counter item_counter; - - /// Array node allocator - /** - Allocator for array nodes. That allocator is used for creating \p headNode and \p arrayNode when the set grows. - Default is \ref CDS_DEFAULT_ALLOCATOR - */ - typedef CDS_DEFAULT_ALLOCATOR node_allocator; - - /// C++ memory ordering model - /** - Can be \p opt::v::relaxed_ordering (relaxed memory model, the default) - or \p opt::v::sequential_consistent (sequentially consisnent memory model). - */ - typedef cds::opt::v::relaxed_ordering memory_model; - - /// Back-off strategy - typedef cds::backoff::Default back_off; - - /// Internal statistics - /** - By default, internal statistics is disabled (\p multilevel_hashset::empty_stat). - Use \p multilevel_hashset::stat to enable it. - */ - typedef empty_stat stat; - - /// RCU deadlock checking policy (only for \ref cds_intrusive_MultilevelHashSet_rcu "RCU-based MultilevelHashSet") - /** - List of available policy see \p opt::rcu_check_deadlock - */ - typedef cds::opt::v::rcu_throw_deadlock rcu_check_deadlock; - }; - - /// Metafunction converting option list to \p multilevel_hashset::traits - /** - Supported \p Options are: - - \p multilevel_hashset::hash_accessor - mandatory option, hash accessor functor. - @copydetails traits::hash_accessor - - \p opt::node_allocator - array node allocator. - @copydetails traits::node_allocator - - \p opt::compare - hash comparison functor. No default functor is provided. - If the option is not specified, the \p opt::less is used. - - \p opt::less - specifies binary predicate used for hash comparison. - 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. - - \p opt::back_off - back-off strategy used. If the option is not specified, the \p cds::backoff::Default is used. - - \p opt::disposer - the functor used for disposing removed data node. Default is \p opt::v::empty_disposer. Due the nature - of GC schema the disposer may be called asynchronously. - - \p opt::item_counter - the type of item counting feature. - The item counting is an important part of \p MultiLevelHashSet algorithm: - the \p empty() member function depends on correct item counting. - Therefore, \p atomicity::empty_item_counter is not allowed as a type of the option. - Default is \p atomicity::item_counter. - - \p opt::memory_model - C++ memory ordering model. Can be \p opt::v::relaxed_ordering (relaxed memory model, the default) - or \p opt::v::sequential_consistent (sequentially consisnent memory model). - - \p opt::stat - internal statistics. By default, it is disabled (\p multilevel_hashset::empty_stat). - To enable it use \p multilevel_hashset::stat - - \p opt::rcu_check_deadlock - a deadlock checking policy for \ref cds_intrusive_MultilevelHashSet_rcu "RCU-based MultilevelHashSet" - Default is \p opt::v::rcu_throw_deadlock - */ - template - struct make_traits - { -# ifdef CDS_DOXYGEN_INVOKED - typedef implementation_defined type ; ///< Metafunction result -# else - typedef typename cds::opt::make_options< - typename cds::opt::find_type_traits< traits, Options... >::type - ,Options... - >::type type; -# endif - }; - - /// Bit-wise memcmp-based comparator for hash value \p T - 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)); - } - }; - - //@cond - namespace details { - template - using hash_splitter = cds::algo::split_bitstring< HashType, UInt >; - - struct metrics { - size_t head_node_size; // power-of-two - size_t head_node_size_log; // log2( head_node_size ) - size_t array_node_size; // power-of-two - size_t array_node_size_log;// log2( array_node_size ) - - static metrics make(size_t head_bits, size_t array_bits, size_t hash_size ) - { - size_t const hash_bits = hash_size * 8; - - if (array_bits < 2) - array_bits = 2; - if (head_bits < 4) - head_bits = 4; - if (head_bits > hash_bits) - head_bits = hash_bits; - if ((hash_bits - head_bits) % array_bits != 0) - head_bits += (hash_bits - head_bits) % array_bits; - - assert((hash_bits - head_bits) % array_bits == 0); - - metrics m; - m.head_node_size_log = head_bits; - m.head_node_size = size_t(1) << head_bits; - m.array_node_size_log = array_bits; - m.array_node_size = size_t(1) << array_bits; - return m; - } - }; - - } // namespace details - //@endcond - } // namespace multilevel_hashset - - //@cond - // Forward declaration - template < class GC, typename T, class Traits = multilevel_hashset::traits > - class MultiLevelHashSet; - //@endcond - -}} // namespace cds::intrusive - -#endif // #ifndef CDSLIB_INTRUSIVE_DETAILS_MULTILEVEL_HASHSET_BASE_H diff --git a/cds/intrusive/feldman_hashset_dhp.h b/cds/intrusive/feldman_hashset_dhp.h new file mode 100644 index 00000000..2564eb07 --- /dev/null +++ b/cds/intrusive/feldman_hashset_dhp.h @@ -0,0 +1,9 @@ +//$$CDS-header$$ + +#ifndef CDSLIB_INTRUSIVE_FELDMAN_HASHSET_DHP_H +#define CDSLIB_INTRUSIVE_FELDMAN_HASHSET_DHP_H + +#include +#include + +#endif // #ifndef CDSLIB_INTRUSIVE_FELDMAN_HASHSET_DHP_H diff --git a/cds/intrusive/feldman_hashset_hp.h b/cds/intrusive/feldman_hashset_hp.h new file mode 100644 index 00000000..9ec8c9b1 --- /dev/null +++ b/cds/intrusive/feldman_hashset_hp.h @@ -0,0 +1,9 @@ +//$$CDS-header$$ + +#ifndef CDSLIB_INTRUSIVE_FELDMAN_HASHSET_HP_H +#define CDSLIB_INTRUSIVE_FELDMAN_HASHSET_HP_H + +#include +#include + +#endif // #ifndef CDSLIB_INTRUSIVE_FELDMAN_HASHSET_HP_H diff --git a/cds/intrusive/feldman_hashset_rcu.h b/cds/intrusive/feldman_hashset_rcu.h new file mode 100644 index 00000000..52e79b2d --- /dev/null +++ b/cds/intrusive/feldman_hashset_rcu.h @@ -0,0 +1,1416 @@ +//$$CDS-header$$ + +#ifndef CDSLIB_INTRUSIVE_FELDMAN_HASHSET_RCU_H +#define CDSLIB_INTRUSIVE_FELDMAN_HASHSET_RCU_H + +#include // std::ref +#include // std::iterator_traits + +#include +#include +#include +#include +#include + + +namespace cds { namespace intrusive { + /// Intrusive hash set based on multi-level array, \ref cds_urcu_desc "RCU" specialization + /** @ingroup cds_intrusive_map + @anchor cds_intrusive_FeldmanHashSet_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_FeldmanHashSet_hp "here" + + @note Two important things you should keep in mind when you're using \p %FeldmanHashSet: + - all keys must be fixed-size. It means that you cannot use \p std::string as a key for \p %FeldmanHashSet. + 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 %FeldmanHashSet. + - \p %FeldmanHashSet 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 %FeldmanHashSet 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 + - \p Traits - type traits, the structure based on \p feldman_hashset::traits or result of \p feldman_hashset::make_traits metafunction. + \p Traits is the mandatory argument because it has one mandatory type - an @ref feldman_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_intrusive_FeldmanHashSet_rcu_iterators "bidirectional thread-safe iterators" + with some restrictions. + */ + template < + class RCU, + class T, +#ifdef CDS_DOXYGEN_INVOKED + class Traits = feldman_hashset::traits +#else + class Traits +#endif + > + class FeldmanHashSet< cds::urcu::gc< RCU >, T, Traits > + { + 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 + + typedef typename traits::hash_accessor hash_accessor; ///< Hash accessor functor + static_assert(!std::is_same< hash_accessor, cds::opt::none >::value, "hash_accessor functor must be specified in Traits"); + + /// Hash type deduced from \p hash_accessor return type + typedef typename std::decay< + typename std::remove_reference< + decltype(hash_accessor()(std::declval())) + >::type + >::type hash_type; + //typedef typename std::result_of< hash_accessor( std::declval()) >::type hash_type; + static_assert(!std::is_pointer::value, "hash_accessor should return a reference to hash value"); + + typedef typename traits::disposer disposer; ///< data node disposer + +# ifdef CDS_DOXYGEN_INVOKED + typedef implementation_defined hash_comparator; ///< hash compare functor based on opt::compare and opt::less option setter +# else + typedef typename cds::opt::details::make_comparator_from< + hash_type, + traits, + feldman_hashset::bitwise_compare< hash_type > + >::type hash_comparator; +# endif + + typedef typename traits::item_counter item_counter; ///< Item counter type + 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 + + using exempt_ptr = cds::urcu::exempt_ptr< gc, value_type, value_type, disposer, void >; ///< pointer to extracted node + + /// Node marked poiter + typedef cds::details::marked_ptr< value_type, 3 > node_ptr; + /// Array node element + typedef atomics::atomic< node_ptr > atomic_node_ptr; + + protected: + //@cond + enum node_flags { + flag_array_converting = 1, ///< the cell is converting from data node to an array node + flag_array_node = 2 ///< the cell is a pointer to an array node + }; + + struct array_node { + array_node * const pParent; ///< parent array node + size_t const idxParent; ///< index in parent array node + atomic_node_ptr nodes[1]; ///< node array + + array_node(array_node * parent, size_t idx) + : pParent(parent) + , idxParent(idx) + {} + + array_node() = delete; + array_node(array_node const&) = delete; + array_node(array_node&&) = delete; + }; + + typedef cds::details::Allocator< array_node, node_allocator > cxx_array_node_allocator; + typedef feldman_hashset::details::hash_splitter< hash_type > hash_splitter; + typedef cds::urcu::details::check_deadlock_policy< gc, rcu_check_deadlock> check_deadlock_policy; + + //@endcond + + private: + //@cond + feldman_hashset::details::metrics const m_Metrics; ///< Metrics + array_node * m_Head; ///< Head array + item_counter m_ItemCounter; ///< Item counter + stat m_Stat; ///< Internal statistics + //@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. + */ + FeldmanHashSet(size_t head_bits = 8, size_t array_bits = 4) + : m_Metrics(feldman_hashset::details::metrics::make(head_bits, array_bits, sizeof(hash_type))) + , m_Head(alloc_head_node()) + {} + + /// Destructs the set and frees all data + ~FeldmanHashSet() + { + destroy_tree(); + free_array_node(m_Head); + } + + /// Inserts new node + /** + The function inserts \p val in the set if it does not contain + an item with that hash. + + Returns \p true if \p val is placed into the set, \p false otherwise. + + The function locks RCU internally. + */ + bool insert( value_type& val ) + { + return insert( val, [](value_type&) {} ); + } + + /// Inserts new node + /** + This function is intended for derived non-intrusive containers. + + 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 \p val. + + The functor signature is: + \code + void func( value_type& val ); + \endcode + where \p val is the item inserted. + + The user-defined functor is called only if the inserting is success. + + The function locks RCU internally. + @warning See \ref cds_intrusive_item_creating "insert item troubleshooting". + */ + template + bool insert( value_type& val, Func f ) + { + hash_type const& hash = hash_accessor()( val ); + hash_splitter splitter( hash ); + hash_comparator cmp; + back_off bkoff; + + size_t nOffset = m_Metrics.head_node_size_log; + array_node * pArr = m_Head; + size_t nSlot = splitter.cut( m_Metrics.head_node_size_log ); + assert( nSlot < m_Metrics.head_node_size ); + size_t nHeight = 1; + + while ( true ) { + node_ptr slot = pArr->nodes[nSlot].load( memory_model::memory_order_acquire ); + if ( slot.bits() == flag_array_node ) { + // array node, go down the tree + assert( slot.ptr() != nullptr ); + nSlot = splitter.cut( m_Metrics.array_node_size_log ); + assert( nSlot < m_Metrics.array_node_size ); + pArr = to_array( slot.ptr() ); + nOffset += m_Metrics.array_node_size_log; + ++nHeight; + } + else if ( slot.bits() == flag_array_converting ) { + // the slot is converting to array node right now + bkoff(); + m_Stat.onSlotConverting(); + } + else { + // data node + assert(slot.bits() == 0 ); + + rcu_lock rcuLock; + if ( pArr->nodes[nSlot].load(memory_model::memory_order_acquire) == slot ) { + if ( slot.ptr() ) { + if ( cmp( hash, hash_accessor()( *slot.ptr() )) == 0 ) { + // the item with that hash value already exists + m_Stat.onInsertFailed(); + return false; + } + + // the slot must be expanded + expand_slot( pArr, nSlot, slot, nOffset ); + } + else { + // the slot is empty, try to insert data node + node_ptr pNull; + if ( pArr->nodes[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 ); + ++m_ItemCounter; + m_Stat.onInsertSuccess(); + m_Stat.height( nHeight ); + return true; + } + + // insert failed - slot has been changed by another thread + // retry inserting + m_Stat.onInsertRetry(); + } + } + else + m_Stat.onSlotChanged(); + } + } // while + } + + /// Updates the node + /** + Performs inserting or updating the item with hash value equal to \p val. + - If hash value is found then existing item is replaced with \p val, old item is disposed + with \p Traits::disposer. Note that the disposer is called by \p GC asynchronously. + The function returns std::pair + - If hash value is not found and \p bInsert is \p true then \p val is inserted, + the function returns std::pair + - If hash value is not found and \p bInsert is \p false then the set is unchanged, + the function returns std::pair + + 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 new item has been added or \p false if the set contains that hash. + + The function locks RCU internally. + */ + std::pair update( value_type& val, bool bInsert = true ) + { + return do_update(val, [](value_type&, value_type *) {}, bInsert ); + } + + /// Unlinks the item \p val from the set + /** + The function searches the item \p val in the set and unlink it + if it is found and its address is equal to &val. + + The function returns \p true if success and \p false otherwise. + + RCU should not be locked. The function locks RCU internally. + */ + bool unlink( value_type const& val ) + { + check_deadlock_policy::check(); + + auto pred = [&val](value_type const& item) -> bool { return &item == &val; }; + value_type * p; + { + rcu_lock rcuLock; + p = do_erase( hash_accessor()( val ), std::ref( pred )); + } + if ( p ) { + gc::template retire_ptr( p ); + return true; + } + return false; + } + + /// Deletes the item from the set + /** + The function searches \p hash in the set, + unlinks the item found, and returns \p true. + If that item is not found the function returns \p false. + + The \ref disposer specified in \p Traits is called by garbage collector \p GC asynchronously. + + RCU should not be locked. The function locks RCU internally. + */ + bool erase( hash_type const& hash ) + { + return erase(hash, [](value_type const&) {} ); + } + + /// Deletes the item from the set + /** + The function searches \p hash in the set, + call \p f functor with item found, and unlinks it from the set. + The \ref disposer specified in \p Traits is called + by garbage collector \p GC asynchronously. + + 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. + + RCU should not be locked. The function locks RCU internally. + */ + template + bool erase( hash_type const& hash, Func f ) + { + check_deadlock_policy::check(); + + value_type * p; + + { + rcu_lock rcuLock; + p = do_erase( hash, []( value_type const&) -> bool { return true; } ); + } + + // p is guarded by HP + if ( p ) { + f( *p ); + gc::template retire_ptr(p); + return true; + } + return false; + } + + /// 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::intrusive::FeldmanHashSet< 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 ) + { + check_deadlock_policy::check(); + + value_type * p; + { + rcu_lock rcuLock; + p = do_erase( hash, []( value_type const&) -> bool {return true;} ); + } + return exempt_ptr( p ); + } + + /// 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. + + The function applies RCU lock internally. + */ + template + bool find( hash_type const& hash, Func f ) + { + rcu_lock rcuLock; + + value_type * p = search( hash ); + if ( p ) { + f( *p ); + return true; + } + return false; + } + + /// 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. + + The function applies RCU lock internally. + */ + bool contains( hash_type const& hash ) + { + return find( hash, [](value_type&) {} ); + } + + /// 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::intrusive::FeldmanHashSet< 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 ) + { + assert( gc::is_locked()); + return search( 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. + + For each item the \p disposer is called after unlinking. + */ + void clear() + { + clear_array( m_Head, head_size() ); + } + + /// 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 size() == 0; + } + + /// Returns item count in the set + size_t size() const + { + return m_ItemCounter; + } + + /// Returns const reference to internal statistics + stat const& statistics() const + { + return m_Stat; + } + + /// Returns the size of head node + size_t head_size() const + { + return m_Metrics.head_node_size; + } + + /// Returns the size of the array node + size_t array_node_size() const + { + return m_Metrics.array_node_size; + } + + protected: + //@cond + class iterator_base + { + friend class FeldmanHashSet; + + protected: + array_node * m_pNode; ///< current array node + size_t m_idx; ///< current position in m_pNode + value_type * m_pValue; ///< current value + FeldmanHashSet const* m_set; ///< Hash set + + public: + iterator_base() CDS_NOEXCEPT + : m_pNode(nullptr) + , m_idx(0) + , m_pValue(nullptr) + , m_set(nullptr) + {} + + iterator_base(iterator_base const& rhs) CDS_NOEXCEPT + : m_pNode(rhs.m_pNode) + , m_idx(rhs.m_idx) + , m_pValue(rhs.m_pValue) + , m_set(rhs.m_set) + {} + + iterator_base& operator=(iterator_base const& rhs) CDS_NOEXCEPT + { + m_pNode = rhs.m_pNode; + m_idx = rhs.m_idx; + m_pValue = rhs.m_pValue; + m_set = rhs.m_set; + return *this; + } + + iterator_base& operator++() + { + forward(); + return *this; + } + + iterator_base& operator--() + { + backward(); + return *this; + } + + bool operator ==(iterator_base const& rhs) const CDS_NOEXCEPT + { + return m_pNode == rhs.m_pNode && m_idx == rhs.m_idx && m_set == rhs.m_set; + } + + bool operator !=(iterator_base const& rhs) const CDS_NOEXCEPT + { + return !(*this == rhs); + } + + protected: + iterator_base(FeldmanHashSet const& set, array_node * pNode, size_t idx, bool) + : m_pNode(pNode) + , m_idx(idx) + , m_pValue(nullptr) + , m_set(&set) + {} + + iterator_base(FeldmanHashSet const& set, array_node * pNode, size_t idx) + : m_pNode(pNode) + , m_idx(idx) + , m_pValue(nullptr) + , m_set(&set) + { + forward(); + } + + value_type * pointer() const CDS_NOEXCEPT + { + assert(gc::is_locked()); + return m_pValue; + } + + void forward() + { + assert( gc::is_locked()); + assert(m_set != nullptr); + assert(m_pNode != nullptr); + + size_t const arrayNodeSize = m_set->array_node_size(); + size_t const headSize = m_set->head_size(); + array_node * pNode = m_pNode; + size_t idx = m_idx + 1; + size_t nodeSize = m_pNode->pParent ? arrayNodeSize : headSize; + + for (;;) { + if (idx < nodeSize) { + node_ptr slot = pNode->nodes[idx].load(memory_model::memory_order_acquire); + if (slot.bits() == flag_array_node) { + // array node, go down the tree + assert(slot.ptr() != nullptr); + pNode = to_array(slot.ptr()); + idx = 0; + nodeSize = arrayNodeSize; + } + else if (slot.bits() == flag_array_converting) { + // the slot is converting to array node right now - skip the node + ++idx; + } + else { + if (slot.ptr()) { + // data node + m_pNode = pNode; + m_idx = idx; + m_pValue = slot.ptr(); + return; + } + ++idx; + } + } + else { + // up to parent node + if (pNode->pParent) { + idx = pNode->idxParent + 1; + pNode = pNode->pParent; + nodeSize = pNode->pParent ? arrayNodeSize : headSize; + } + else { + // end() + assert(pNode == m_set->m_Head); + assert(idx == headSize); + m_pNode = pNode; + m_idx = idx; + m_pValue = nullptr; + return; + } + } + } + } + + void backward() + { + assert(gc::is_locked()); + assert(m_set != nullptr); + assert(m_pNode != nullptr); + + size_t const arrayNodeSize = m_set->array_node_size(); + size_t const headSize = m_set->head_size(); + size_t const endIdx = size_t(0) - 1; + + array_node * pNode = m_pNode; + size_t idx = m_idx - 1; + size_t nodeSize = m_pNode->pParent ? arrayNodeSize : headSize; + + for (;;) { + if (idx != endIdx) { + node_ptr slot = pNode->nodes[idx].load(memory_model::memory_order_acquire); + if (slot.bits() == flag_array_node) { + // array node, go down the tree + assert(slot.ptr() != nullptr); + pNode = to_array(slot.ptr()); + nodeSize = arrayNodeSize; + idx = nodeSize - 1; + } + else if (slot.bits() == flag_array_converting) { + // the slot is converting to array node right now - skip the node + --idx; + } + else { + if (slot.ptr()) { + // data node + m_pNode = pNode; + m_idx = idx; + m_pValue = slot.ptr(); + return; + } + --idx; + } + } + else { + // up to parent node + if (pNode->pParent) { + idx = pNode->idxParent - 1; + pNode = pNode->pParent; + nodeSize = pNode->pParent ? arrayNodeSize : headSize; + } + else { + // rend() + assert(pNode == m_set->m_Head); + assert(idx == endIdx); + m_pNode = pNode; + m_idx = idx; + m_pValue = nullptr; + return; + } + } + } + } + }; + + template + Iterator init_begin() const + { + return Iterator(*this, m_Head, size_t(0) - 1); + } + + template + Iterator init_end() const + { + return Iterator(*this, m_Head, head_size(), false); + } + + template + Iterator init_rbegin() const + { + return Iterator(*this, m_Head, head_size()); + } + + template + Iterator init_rend() const + { + return Iterator(*this, m_Head, size_t(0) - 1, false); + } + + /// Bidirectional iterator class + template + class bidirectional_iterator : protected iterator_base + { + friend class FeldmanHashSet; + + protected: + static CDS_CONSTEXPR bool const c_bConstantIterator = IsConst; + + public: + typedef typename std::conditional< IsConst, value_type const*, value_type*>::type value_ptr; ///< Value pointer + typedef typename std::conditional< IsConst, value_type const&, value_type&>::type value_ref; ///< Value reference + + public: + bidirectional_iterator() CDS_NOEXCEPT + {} + + bidirectional_iterator(bidirectional_iterator const& rhs) CDS_NOEXCEPT + : iterator_base(rhs) + {} + + bidirectional_iterator& operator=(bidirectional_iterator const& rhs) CDS_NOEXCEPT + { + iterator_base::operator=(rhs); + return *this; + } + + bidirectional_iterator& operator++() + { + iterator_base::operator++(); + return *this; + } + + bidirectional_iterator& operator--() + { + iterator_base::operator--(); + return *this; + } + + value_ptr operator ->() const CDS_NOEXCEPT + { + return iterator_base::pointer(); + } + + value_ref operator *() const CDS_NOEXCEPT + { + value_ptr p = iterator_base::pointer(); + assert(p); + return *p; + } + + template + bool operator ==(bidirectional_iterator const& rhs) const CDS_NOEXCEPT + { + return iterator_base::operator==(rhs); + } + + template + bool operator !=(bidirectional_iterator const& rhs) const CDS_NOEXCEPT + { + return !(*this == rhs); + } + + protected: + bidirectional_iterator(FeldmanHashSet& set, array_node * pNode, size_t idx, bool) + : iterator_base(set, pNode, idx, false) + {} + + bidirectional_iterator(FeldmanHashSet& set, array_node * pNode, size_t idx) + : iterator_base(set, pNode, idx) + {} + }; + + /// Reverse bidirectional iterator + template + class reverse_bidirectional_iterator : public iterator_base + { + friend class FeldmanHashSet; + + public: + typedef typename std::conditional< IsConst, value_type const*, value_type*>::type value_ptr; ///< Value pointer + typedef typename std::conditional< IsConst, value_type const&, value_type&>::type value_ref; ///< Value reference + + public: + reverse_bidirectional_iterator() CDS_NOEXCEPT + : iterator_base() + {} + + reverse_bidirectional_iterator(reverse_bidirectional_iterator const& rhs) CDS_NOEXCEPT + : iterator_base(rhs) + {} + + reverse_bidirectional_iterator& operator=(reverse_bidirectional_iterator const& rhs) CDS_NOEXCEPT + { + iterator_base::operator=(rhs); + return *this; + } + + reverse_bidirectional_iterator& operator++() + { + iterator_base::operator--(); + return *this; + } + + reverse_bidirectional_iterator& operator--() + { + iterator_base::operator++(); + return *this; + } + + value_ptr operator ->() const CDS_NOEXCEPT + { + return iterator_base::pointer(); + } + + value_ref operator *() const CDS_NOEXCEPT + { + value_ptr p = iterator_base::pointer(); + assert(p); + return *p; + } + + template + bool operator ==(reverse_bidirectional_iterator const& rhs) const + { + return iterator_base::operator==(rhs); + } + + template + bool operator !=(reverse_bidirectional_iterator const& rhs) + { + return !(*this == rhs); + } + + private: + reverse_bidirectional_iterator(FeldmanHashSet& set, array_node * pNode, size_t idx, bool) + : iterator_base(set, pNode, idx, false) + {} + + reverse_bidirectional_iterator(FeldmanHashSet& set, array_node * pNode, size_t idx) + : iterator_base(set, pNode, idx, false) + { + iterator_base::backward(); + } + }; + //@endcond + + public: +#ifdef CDS_DOXYGEN_INVOKED + typedef implementation_defined iterator; ///< @ref cds_intrusive_FeldmanHashSet_rcu_iterators "bidirectional iterator" type + typedef implementation_defined const_iterator; ///< @ref cds_intrusive_FeldmanHashSet_rcu_iterators "bidirectional const iterator" type + typedef implementation_defined reverse_iterator; ///< @ref cds_intrusive_FeldmanHashSet_rcu_iterators "bidirectional reverse iterator" type + typedef implementation_defined const_reverse_iterator; ///< @ref cds_intrusive_FeldmanHashSet_rcu_iterators "bidirectional reverse const iterator" type +#else + typedef bidirectional_iterator iterator; + typedef bidirectional_iterator const_iterator; + typedef reverse_bidirectional_iterator reverse_iterator; + typedef reverse_bidirectional_iterator const_reverse_iterator; +#endif + + ///@name Thread-safe iterators + /** @anchor cds_intrusive_FeldmanHashSet_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::intrusive::feldman_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::intrusive::FeldmanHashSet< 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 iterator(*this, m_Head, size_t(0) - 1); + } + + /// Returns an const iterator to the beginning of the set + const_iterator begin() const + { + return const_iterator(*this, m_Head, size_t(0) - 1); + } + + /// Returns an const iterator to the beginning of the set + const_iterator cbegin() + { + return const_iterator(*this, m_Head, size_t(0) - 1); + } + + /// 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 iterator(*this, m_Head, head_size(), false); + } + + /// 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 const_iterator(*this, m_Head, head_size(), false); + } + + /// 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 const_iterator(*this, m_Head, head_size(), false); + } + + /// Returns a reverse iterator to the first element of the reversed set + reverse_iterator rbegin() + { + return reverse_iterator(*this, m_Head, head_size()); + } + + /// Returns a const reverse iterator to the first element of the reversed set + const_reverse_iterator rbegin() const + { + return const_reverse_iterator(*this, m_Head, head_size()); + } + + /// Returns a const reverse iterator to the first element of the reversed set + const_reverse_iterator crbegin() + { + return const_reverse_iterator(*this, m_Head, head_size()); + } + + /// 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 reverse_iterator(*this, m_Head, size_t(0) - 1, false); + } + + /// 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 const_reverse_iterator(*this, m_Head, size_t(0) - 1, false); + } + + /// 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 const_reverse_iterator(*this, m_Head, size_t(0) - 1, false); + } + ///@} + + protected: + //@cond + template + std::pair do_update(value_type& val, Func f, bool bInsert = true) + { + hash_type const& hash = hash_accessor()(val); + hash_splitter splitter(hash); + hash_comparator cmp; + back_off bkoff; + + array_node * pArr = m_Head; + size_t nSlot = splitter.cut(m_Metrics.head_node_size_log); + assert(nSlot < m_Metrics.head_node_size); + size_t nOffset = m_Metrics.head_node_size_log; + size_t nHeight = 1; + + while (true) { + node_ptr slot = pArr->nodes[nSlot].load(memory_model::memory_order_acquire); + if (slot.bits() == flag_array_node) { + // array node, go down the tree + assert(slot.ptr() != nullptr); + nSlot = splitter.cut(m_Metrics.array_node_size_log); + assert(nSlot < m_Metrics.array_node_size); + pArr = to_array(slot.ptr()); + nOffset += m_Metrics.array_node_size_log; + ++nHeight; + } + else if (slot.bits() == flag_array_converting) { + // the slot is converting to array node right now + bkoff(); + m_Stat.onSlotConverting(); + } + else { + // data node + assert(slot.bits() == 0); + + value_type * pOld = nullptr; + { + rcu_lock rcuLock; + + if ( pArr->nodes[nSlot].load(memory_model::memory_order_acquire) == slot ) { + if ( slot.ptr()) { + if (cmp(hash, hash_accessor()(*slot.ptr())) == 0) { + // the item with that hash value already exists + // Replace it with val + if (slot.ptr() == &val) { + m_Stat.onUpdateExisting(); + return std::make_pair(true, false); + } + + if (pArr->nodes[nSlot].compare_exchange_strong(slot, node_ptr(&val), memory_model::memory_order_release, atomics::memory_order_relaxed)) { + // slot can be disposed + f(val, slot.ptr()); + pOld = slot.ptr(); + m_Stat.onUpdateExisting(); + goto update_existing_done; + } + + m_Stat.onUpdateRetry(); + continue; + } + + // the slot must be expanded + expand_slot(pArr, nSlot, slot, nOffset); + } + else { + // the slot is empty, try to insert data node + if (bInsert) { + node_ptr pNull; + if (pArr->nodes[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, nullptr); + ++m_ItemCounter; + m_Stat.onUpdateNew(); + m_Stat.height(nHeight); + return std::make_pair(true, true); + } + } + else { + m_Stat.onUpdateFailed(); + return std::make_pair(false, false); + } + + // insert failed - slot has been changed by another thread + // retry updating + m_Stat.onUpdateRetry(); + } + } + else + m_Stat.onSlotChanged(); + continue; + } // rcu_lock + + // update success + update_existing_done: + if ( pOld ) + gc::template retire_ptr( pOld ); + return std::make_pair(true, false); + } + } // while + } + + template + value_type * do_erase( hash_type const& hash, Predicate pred) + { + assert(gc::is_locked()); + + hash_splitter splitter(hash); + hash_comparator cmp; + back_off bkoff; + + array_node * pArr = m_Head; + size_t nSlot = splitter.cut(m_Metrics.head_node_size_log); + assert(nSlot < m_Metrics.head_node_size); + + while (true) { + node_ptr slot = pArr->nodes[nSlot].load(memory_model::memory_order_acquire); + if (slot.bits() == flag_array_node) { + // array node, go down the tree + assert(slot.ptr() != nullptr); + nSlot = splitter.cut(m_Metrics.array_node_size_log); + assert(nSlot < m_Metrics.array_node_size); + pArr = to_array(slot.ptr()); + } + else if (slot.bits() == flag_array_converting) { + // the slot is converting to array node right now + bkoff(); + m_Stat.onSlotConverting(); + } + else { + // data node + assert(slot.bits() == 0); + + if ( pArr->nodes[nSlot].load(memory_model::memory_order_acquire) == slot ) { + if (slot.ptr()) { + if (cmp(hash, hash_accessor()(*slot.ptr())) == 0 && pred(*slot.ptr())) { + // item found - replace it with nullptr + if (pArr->nodes[nSlot].compare_exchange_strong(slot, node_ptr(nullptr), memory_model::memory_order_acquire, atomics::memory_order_relaxed)) { + --m_ItemCounter; + m_Stat.onEraseSuccess(); + + return slot.ptr(); + } + m_Stat.onEraseRetry(); + continue; + } + m_Stat.onEraseFailed(); + return nullptr; + } + else { + // the slot is empty + m_Stat.onEraseFailed(); + return nullptr; + } + } + else + m_Stat.onSlotChanged(); + } + } // while + } + + value_type * search(hash_type const& hash ) + { + assert( gc::is_locked() ); + + hash_splitter splitter(hash); + hash_comparator cmp; + back_off bkoff; + + array_node * pArr = m_Head; + size_t nSlot = splitter.cut(m_Metrics.head_node_size_log); + assert(nSlot < m_Metrics.head_node_size); + + while (true) { + node_ptr slot = pArr->nodes[nSlot].load(memory_model::memory_order_acquire); + if (slot.bits() == flag_array_node) { + // array node, go down the tree + assert(slot.ptr() != nullptr); + nSlot = splitter.cut(m_Metrics.array_node_size_log); + assert(nSlot < m_Metrics.array_node_size); + pArr = to_array(slot.ptr()); + } + else if (slot.bits() == flag_array_converting) { + // the slot is converting to array node right now + bkoff(); + m_Stat.onSlotConverting(); + } + else { + // data node + assert(slot.bits() == 0); + + // protect data node by hazard pointer + if ( pArr->nodes[nSlot].load(memory_model::memory_order_acquire) != slot) { + // slot value has been changed - retry + m_Stat.onSlotChanged(); + } + else if (slot.ptr() && cmp(hash, hash_accessor()(*slot.ptr())) == 0) { + // item found + m_Stat.onFindSuccess(); + return slot.ptr(); + } + m_Stat.onFindFailed(); + return nullptr; + } + } // while + } + + //@endcond + + private: + //@cond + array_node * alloc_head_node() const + { + return alloc_array_node(head_size(), nullptr, 0); + } + + array_node * alloc_array_node(array_node * pParent, size_t idxParent) const + { + return alloc_array_node(array_node_size(), pParent, idxParent); + } + + static array_node * alloc_array_node(size_t nSize, array_node * pParent, size_t idxParent) + { + array_node * pNode = cxx_array_node_allocator().NewBlock(sizeof(array_node) + sizeof(atomic_node_ptr) * (nSize - 1), pParent, idxParent); + new (pNode->nodes) atomic_node_ptr[nSize]; + return pNode; + } + + static void free_array_node(array_node * parr) + { + cxx_array_node_allocator().Delete(parr); + } + + void destroy_tree() + { + // The function is not thread-safe. For use in dtor only + // Remove data node + clear(); + + // Destroy all array nodes + destroy_array_nodes(m_Head, head_size()); + } + + void destroy_array_nodes(array_node * pArr, size_t nSize) + { + for (atomic_node_ptr * p = pArr->nodes, *pLast = pArr->nodes + nSize; p != pLast; ++p) { + node_ptr slot = p->load(memory_model::memory_order_acquire); + if (slot.bits() == flag_array_node) { + destroy_array_nodes(to_array(slot.ptr()), array_node_size()); + free_array_node(to_array(slot.ptr())); + p->store(node_ptr(), memory_model::memory_order_relaxed); + } + } + } + + void clear_array(array_node * pArrNode, size_t nSize) + { + back_off bkoff; + + + for (atomic_node_ptr * pArr = pArrNode->nodes, *pLast = pArr + nSize; pArr != pLast; ++pArr) { + while (true) { + node_ptr slot = pArr->load(memory_model::memory_order_acquire); + if (slot.bits() == flag_array_node) { + // array node, go down the tree + assert(slot.ptr() != nullptr); + clear_array(to_array(slot.ptr()), array_node_size()); + break; + } + else if (slot.bits() == flag_array_converting) { + // the slot is converting to array node right now + while ((slot = pArr->load(memory_model::memory_order_acquire)).bits() == flag_array_converting) { + bkoff(); + m_Stat.onSlotConverting(); + } + bkoff.reset(); + + assert(slot.ptr() != nullptr); + assert(slot.bits() == flag_array_node); + clear_array(to_array(slot.ptr()), array_node_size()); + break; + } + else { + // data node + if (pArr->compare_exchange_strong(slot, node_ptr(), memory_model::memory_order_acquire, atomics::memory_order_relaxed)) { + if (slot.ptr()) { + gc::template retire_ptr(slot.ptr()); + --m_ItemCounter; + m_Stat.onEraseSuccess(); + } + break; + } + } + } + } + } + + bool expand_slot(array_node * pParent, size_t idxParent, node_ptr current, size_t nOffset) + { + assert(current.bits() == 0); + assert(current.ptr()); + + size_t idx = hash_splitter(hash_accessor()(*current.ptr()), nOffset).cut(m_Metrics.array_node_size_log); + array_node * pArr = alloc_array_node(pParent, idxParent); + + node_ptr cur(current.ptr()); + atomic_node_ptr& slot = pParent->nodes[idxParent]; + if (!slot.compare_exchange_strong(cur, cur | flag_array_converting, memory_model::memory_order_release, atomics::memory_order_relaxed)) + { + m_Stat.onExpandNodeFailed(); + free_array_node(pArr); + return false; + } + + pArr->nodes[idx].store(current, memory_model::memory_order_release); + + cur = cur | flag_array_converting; + CDS_VERIFY( + slot.compare_exchange_strong(cur, node_ptr(to_node(pArr), flag_array_node), memory_model::memory_order_release, atomics::memory_order_relaxed) + ); + + m_Stat.onExpandNodeSuccess(); + m_Stat.onArrayNodeCreated(); + return true; + } + + union converter { + value_type * pData; + array_node * pArr; + + converter(value_type * p) + : pData(p) + {} + + converter(array_node * p) + : pArr(p) + {} + }; + + static array_node * to_array(value_type * p) + { + return converter(p).pArr; + } + static value_type * to_node(array_node * p) + { + return converter(p).pData; + } + //@endcond + }; + +}} // namespace cds::intrusive + +#endif // #ifndef CDSLIB_INTRUSIVE_FELDMAN_HASHSET_RCU_H diff --git a/cds/intrusive/impl/feldman_hashset.h b/cds/intrusive/impl/feldman_hashset.h new file mode 100644 index 00000000..fb713bbd --- /dev/null +++ b/cds/intrusive/impl/feldman_hashset.h @@ -0,0 +1,1467 @@ +//$$CDS-header$$ + +#ifndef CDSLIB_INTRUSIVE_IMPL_FELDMAN_HASHSET_H +#define CDSLIB_INTRUSIVE_IMPL_FELDMAN_HASHSET_H + +#include // std::ref +#include // std::iterator_traits + +#include +#include + +namespace cds { namespace intrusive { + /// Intrusive hash set based on multi-level array + /** @ingroup cds_intrusive_map + @anchor cds_intrusive_FeldmanHashSet_hp + + Source: + - [2013] Steven Feldman, Pierre LaBorde, Damian Dechev "Concurrent Multi-level Arrays: + Wait-free Extensible Hash Maps" + + [From the paper] The hardest problem encountered while developing a parallel hash map is how to perform + a global resize, the process of redistributing the elements in a hash map that occurs when adding new + buckets. The negative impact of blocking synchronization is multiplied during a global resize, because all + threads will be forced to wait on the thread that is performing the involved process of resizing the hash map + and redistributing the elements. \p %FeldmanHashSet implementation avoids global resizes through new array + allocation. By allowing concurrent expansion this structure is free from the overhead of an explicit resize, + which facilitates concurrent operations. + + The presented design includes dynamic hashing, the use of sub-arrays within the hash map data structure; + which, in combination with perfect hashing, means that each element has a unique final, as well as current, position. + It is important to note that the perfect hash function required by our hash map is trivial to realize as + any hash function that permutes the bits of the key is suitable. This is possible because of our approach + to the hash function; we require that it produces hash values that are equal in size to that of the key. + We know that if we expand the hash map a fixed number of times there can be no collision as duplicate keys + are not provided for in the standard semantics of a hash map. + + \p %FeldmanHashSet is a multi-level array which has a structure similar to a tree: + @image html feldman_hashset.png + The multi-level array differs from a tree in that each position on the tree could hold an array of nodes or a single node. + A position that holds a single node is a \p dataNode which holds the hash value of a key and the value that is associated + with that key; it is a simple struct holding two variables. A \p dataNode in the multi-level array could be marked. + A \p markedDataNode refers to a pointer to a \p dataNode that has been bitmarked at the least significant bit (LSB) + of the pointer to the node. This signifies that this \p dataNode is contended. An expansion must occur at this node; + any thread that sees this \p markedDataNode will try to replace it with an \p arrayNode; which is a position that holds + an array of nodes. The pointer to an \p arrayNode is differentiated from that of a pointer to a \p dataNode by a bitmark + on the second-least significant bit. + + \p %FeldmanHashSet multi-level array is similar to a tree in that we keep a pointer to the root, which is a memory array + called \p head. The length of the \p head memory array is unique, whereas every other \p arrayNode has a uniform length; + a normal \p arrayNode has a fixed power-of-two length equal to the binary logarithm of a variable called \p arrayLength. + The maximum depth of the tree, \p maxDepth, is the maximum number of pointers that must be followed to reach any node. + We define \p currentDepth as the number of memory arrays that we need to traverse to reach the \p arrayNode on which + we need to operate; this is initially one, because of \p head. + + That approach to the structure of the hash set uses an extensible hashing scheme; the hash value is treated as a bit + string and rehash incrementally. + + @note Two important things you should keep in mind when you're using \p %FeldmanHashSet: + - all keys must be fixed-size. It means that you cannot use \p std::string as a key for \p %FeldmanHashSet. + 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 %FeldmanHashSet. + - \p %FeldmanHashSet 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 %FeldmanHashSet does not maintain the key, + it maintains its fixed-size hash value. + + The set supports @ref cds_intrusive_FeldmanHashSet_iterators "bidirectional thread-safe iterators". + + 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 feldman_hashset::traits or result of \p feldman_hashset::make_traits metafunction. + \p Traits is the mandatory argument because it has one mandatory type - an @ref feldman_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 %FeldmanHashSet for each \p GC. You should include: + - for \p gc::HP garbage collector + - for \p gc::DHP garbage collector + - for \ref cds_intrusive_FeldmanHashSet_rcu "RCU type". RCU specialization + has a slightly different interface. + */ + template < + class GC + ,typename T +#ifdef CDS_DOXYGEN_INVOKED + ,typename Traits = feldman_hashset::traits +#else + ,typename Traits +#endif + > + class FeldmanHashSet + { + public: + typedef GC gc; ///< Garbage collector + typedef T value_type; ///< type of value stored in the set + typedef Traits traits; ///< Traits template parameter, see \p feldman_hashset::traits + + typedef typename traits::hash_accessor hash_accessor; ///< Hash accessor functor + static_assert(!std::is_same< hash_accessor, cds::opt::none >::value, "hash_accessor functor must be specified" ); + + /// Hash type deduced from \p hash_accessor return type + typedef typename std::decay< + typename std::remove_reference< + decltype( hash_accessor()( std::declval()) ) + >::type + >::type hash_type; + //typedef typename std::result_of< hash_accessor( std::declval()) >::type hash_type; + static_assert( !std::is_pointer::value, "hash_accessor should return a reference to hash value" ); + + typedef typename traits::disposer disposer; ///< data node disposer + +# ifdef CDS_DOXYGEN_INVOKED + typedef implementation_defined hash_comparator ; ///< hash compare functor based on opt::compare and opt::less option setter +# else + typedef typename cds::opt::details::make_comparator_from< + hash_type, + traits, + feldman_hashset::bitwise_compare< hash_type > + >::type hash_comparator; +# endif + + typedef typename traits::item_counter item_counter; ///< Item counter type + 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 gc::template guarded_ptr< value_type > guarded_ptr; ///< Guarded pointer + + /// Count of hazard pointers required + static CDS_CONSTEXPR size_t const c_nHazardPtrCount = 2; + + /// Node marked poiter + typedef cds::details::marked_ptr< value_type, 3 > node_ptr; + /// Array node element + typedef atomics::atomic< node_ptr > atomic_node_ptr; + + protected: + //@cond + enum node_flags { + flag_array_converting = 1, ///< the cell is converting from data node to an array node + flag_array_node = 2 ///< the cell is a pointer to an array node + }; + + struct array_node { + array_node * const pParent; ///< parent array node + size_t const idxParent; ///< index in parent array node + atomic_node_ptr nodes[1]; ///< node array + + array_node( array_node * parent, size_t idx ) + : pParent( parent ) + , idxParent( idx ) + {} + + array_node() = delete; + array_node( array_node const&) = delete; + array_node( array_node&& ) = delete; + }; + + typedef cds::details::Allocator< array_node, node_allocator > cxx_array_node_allocator; + + typedef feldman_hashset::details::hash_splitter< hash_type > hash_splitter; + //@endcond + + protected: + //@cond + class iterator_base + { + friend class FeldmanHashSet; + + protected: + array_node * m_pNode; ///< current array node + size_t m_idx; ///< current position in m_pNode + typename gc::Guard m_guard; ///< HP guard + FeldmanHashSet const* m_set; ///< Hash set + + public: + iterator_base() CDS_NOEXCEPT + : m_pNode( nullptr ) + , m_idx( 0 ) + , m_set( nullptr ) + {} + + iterator_base( iterator_base const& rhs ) CDS_NOEXCEPT + : m_pNode( rhs.m_pNode ) + , m_idx( rhs.m_idx ) + , m_set( rhs.m_set ) + { + m_guard.copy( rhs.m_guard ); + } + + iterator_base& operator=(iterator_base const& rhs) CDS_NOEXCEPT + { + m_pNode = rhs.m_pNode; + m_idx = rhs.m_idx; + m_set = rhs.m_set; + m_guard.copy( rhs.m_guard ); + return *this; + } + + iterator_base& operator++() + { + forward(); + return *this; + } + + iterator_base& operator--() + { + backward(); + return *this; + } + + void release() + { + m_guard.clear(); + } + + bool operator ==(iterator_base const& rhs) const CDS_NOEXCEPT + { + return m_pNode == rhs.m_pNode && m_idx == rhs.m_idx && m_set == rhs.m_set; + } + + bool operator !=(iterator_base const& rhs) const CDS_NOEXCEPT + { + return !( *this == rhs ); + } + + protected: + iterator_base( FeldmanHashSet const& set, array_node * pNode, size_t idx, bool ) + : m_pNode( pNode ) + , m_idx( idx ) + , m_set( &set ) + {} + + iterator_base( FeldmanHashSet const& set, array_node * pNode, size_t idx ) + : m_pNode( pNode ) + , m_idx( idx ) + , m_set( &set ) + { + forward(); + } + + value_type * pointer() const CDS_NOEXCEPT + { + return m_guard.template get(); + } + + void forward() + { + assert( m_set != nullptr ); + assert( m_pNode != nullptr ); + + size_t const arrayNodeSize = m_set->array_node_size(); + size_t const headSize = m_set->head_size(); + array_node * pNode = m_pNode; + size_t idx = m_idx + 1; + size_t nodeSize = m_pNode->pParent? arrayNodeSize : headSize; + + for ( ;; ) { + if ( idx < nodeSize ) { + node_ptr slot = pNode->nodes[idx].load( memory_model::memory_order_acquire ); + if ( slot.bits() == flag_array_node ) { + // array node, go down the tree + assert( slot.ptr() != nullptr ); + pNode = to_array( slot.ptr() ); + idx = 0; + nodeSize = arrayNodeSize; + } + else if ( slot.bits() == flag_array_converting ) { + // the slot is converting to array node right now - skip the node + ++idx; + } + else { + if ( slot.ptr()) { + // data node + if ( m_guard.protect( pNode->nodes[idx], [](node_ptr p) -> value_type * { return p.ptr(); }) == slot ) { + m_pNode = pNode; + m_idx = idx; + return; + } + } + ++idx; + } + } + else { + // up to parent node + if ( pNode->pParent ) { + idx = pNode->idxParent + 1; + pNode = pNode->pParent; + nodeSize = pNode->pParent ? arrayNodeSize : headSize; + } + else { + // end() + assert( pNode == m_set->m_Head ); + assert( idx == headSize ); + m_pNode = pNode; + m_idx = idx; + return; + } + } + } + } + + void backward() + { + assert( m_set != nullptr ); + assert( m_pNode != nullptr ); + + size_t const arrayNodeSize = m_set->array_node_size(); + size_t const headSize = m_set->head_size(); + size_t const endIdx = size_t(0) - 1; + + array_node * pNode = m_pNode; + size_t idx = m_idx - 1; + size_t nodeSize = m_pNode->pParent? arrayNodeSize : headSize; + + for ( ;; ) { + if ( idx != endIdx ) { + node_ptr slot = pNode->nodes[idx].load( memory_model::memory_order_acquire ); + if ( slot.bits() == flag_array_node ) { + // array node, go down the tree + assert( slot.ptr() != nullptr ); + pNode = to_array( slot.ptr() ); + nodeSize = arrayNodeSize; + idx = nodeSize - 1; + } + else if ( slot.bits() == flag_array_converting ) { + // the slot is converting to array node right now - skip the node + --idx; + } + else { + if ( slot.ptr()) { + // data node + if ( m_guard.protect( pNode->nodes[idx], [](node_ptr p) -> value_type * { return p.ptr(); }) == slot ) { + m_pNode = pNode; + m_idx = idx; + return; + } + } + --idx; + } + } + else { + // up to parent node + if ( pNode->pParent ) { + idx = pNode->idxParent - 1; + pNode = pNode->pParent; + nodeSize = pNode->pParent ? arrayNodeSize : headSize; + } + else { + // rend() + assert( pNode == m_set->m_Head ); + assert( idx == endIdx ); + m_pNode = pNode; + m_idx = idx; + return; + } + } + } + } + }; + + template + Iterator init_begin() const + { + return Iterator( *this, m_Head, size_t(0) - 1 ); + } + + template + Iterator init_end() const + { + return Iterator( *this, m_Head, head_size(), false ); + } + + template + Iterator init_rbegin() const + { + return Iterator( *this, m_Head, head_size() ); + } + + template + Iterator init_rend() const + { + return Iterator( *this, m_Head, size_t(0) - 1, false ); + } + + /// Bidirectional iterator class + template + class bidirectional_iterator: protected iterator_base + { + friend class FeldmanHashSet; + + protected: + static CDS_CONSTEXPR bool const c_bConstantIterator = IsConst; + + public: + typedef typename std::conditional< IsConst, value_type const*, value_type*>::type value_ptr; ///< Value pointer + typedef typename std::conditional< IsConst, value_type const&, value_type&>::type value_ref; ///< Value reference + + public: + bidirectional_iterator() CDS_NOEXCEPT + {} + + bidirectional_iterator( bidirectional_iterator const& rhs ) CDS_NOEXCEPT + : iterator_base( rhs ) + {} + + bidirectional_iterator& operator=(bidirectional_iterator const& rhs) CDS_NOEXCEPT + { + iterator_base::operator=( rhs ); + return *this; + } + + bidirectional_iterator& operator++() + { + iterator_base::operator++(); + return *this; + } + + bidirectional_iterator& operator--() + { + iterator_base::operator--(); + return *this; + } + + value_ptr operator ->() const CDS_NOEXCEPT + { + return iterator_base::pointer(); + } + + value_ref operator *() const CDS_NOEXCEPT + { + value_ptr p = iterator_base::pointer(); + assert( p ); + return *p; + } + + void release() + { + iterator_base::release(); + } + + template + bool operator ==(bidirectional_iterator const& rhs) const CDS_NOEXCEPT + { + return iterator_base::operator==( rhs ); + } + + template + bool operator !=(bidirectional_iterator const& rhs) const CDS_NOEXCEPT + { + return !( *this == rhs ); + } + + protected: + bidirectional_iterator( FeldmanHashSet& set, array_node * pNode, size_t idx, bool ) + : iterator_base( set, pNode, idx, false ) + {} + + bidirectional_iterator( FeldmanHashSet& set, array_node * pNode, size_t idx ) + : iterator_base( set, pNode, idx ) + {} + }; + + /// Reverse bidirectional iterator + template + class reverse_bidirectional_iterator : public iterator_base + { + friend class FeldmanHashSet; + + public: + typedef typename std::conditional< IsConst, value_type const*, value_type*>::type value_ptr; ///< Value pointer + typedef typename std::conditional< IsConst, value_type const&, value_type&>::type value_ref; ///< Value reference + + public: + reverse_bidirectional_iterator() CDS_NOEXCEPT + : iterator_base() + {} + + reverse_bidirectional_iterator( reverse_bidirectional_iterator const& rhs ) CDS_NOEXCEPT + : iterator_base( rhs ) + {} + + reverse_bidirectional_iterator& operator=( reverse_bidirectional_iterator const& rhs) CDS_NOEXCEPT + { + iterator_base::operator=( rhs ); + return *this; + } + + reverse_bidirectional_iterator& operator++() + { + iterator_base::operator--(); + return *this; + } + + reverse_bidirectional_iterator& operator--() + { + iterator_base::operator++(); + return *this; + } + + value_ptr operator ->() const CDS_NOEXCEPT + { + return iterator_base::pointer(); + } + + value_ref operator *() const CDS_NOEXCEPT + { + value_ptr p = iterator_base::pointer(); + assert( p ); + return *p; + } + + void release() + { + iterator_base::release(); + } + + template + bool operator ==(reverse_bidirectional_iterator const& rhs) const + { + return iterator_base::operator==( rhs ); + } + + template + bool operator !=(reverse_bidirectional_iterator const& rhs) + { + return !( *this == rhs ); + } + + private: + reverse_bidirectional_iterator( FeldmanHashSet& set, array_node * pNode, size_t idx, bool ) + : iterator_base( set, pNode, idx, false ) + {} + + reverse_bidirectional_iterator( FeldmanHashSet& set, array_node * pNode, size_t idx ) + : iterator_base( set, pNode, idx, false ) + { + iterator_base::backward(); + } + }; + //@endcond + + public: +#ifdef CDS_DOXYGEN_INVOKED + typedef implementation_defined iterator; ///< @ref cds_intrusive_FeldmanHashSet_iterators "bidirectional iterator" type + typedef implementation_defined const_iterator; ///< @ref cds_intrusive_FeldmanHashSet_iterators "bidirectional const iterator" type + typedef implementation_defined reverse_iterator; ///< @ref cds_intrusive_FeldmanHashSet_iterators "bidirectional reverse iterator" type + typedef implementation_defined const_reverse_iterator; ///< @ref cds_intrusive_FeldmanHashSet_iterators "bidirectional reverse const iterator" type +#else + typedef bidirectional_iterator iterator; + typedef bidirectional_iterator const_iterator; + typedef reverse_bidirectional_iterator reverse_iterator; + typedef reverse_bidirectional_iterator const_reverse_iterator; +#endif + + private: + //@cond + feldman_hashset::details::metrics const m_Metrics; ///< Metrics + array_node * m_Head; ///< Head array + item_counter m_ItemCounter; ///< Item counter + stat m_Stat; ///< Internal statistics + //@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. + */ + FeldmanHashSet( size_t head_bits = 8, size_t array_bits = 4 ) + : m_Metrics( feldman_hashset::details::metrics::make( head_bits, array_bits, sizeof(hash_type))) + , m_Head( alloc_head_node()) + {} + + /// Destructs the set and frees all data + ~FeldmanHashSet() + { + destroy_tree(); + free_array_node( m_Head ); + } + + /// Inserts new node + /** + The function inserts \p val in the set if it does not contain + an item with that hash. + + Returns \p true if \p val is placed into the set, \p false otherwise. + */ + bool insert( value_type& val ) + { + return insert( val, [](value_type&) {} ); + } + + /// Inserts new node + /** + This function is intended for derived non-intrusive containers. + + 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 \p val. + + The functor signature is: + \code + void func( value_type& val ); + \endcode + where \p val is the item inserted. + + The user-defined functor is called only if the inserting is success. + + @warning See \ref cds_intrusive_item_creating "insert item troubleshooting". + */ + template + bool insert( value_type& val, Func f ) + { + hash_type const& hash = hash_accessor()( val ); + hash_splitter splitter( hash ); + hash_comparator cmp; + typename gc::Guard guard; + back_off bkoff; + + size_t nOffset = m_Metrics.head_node_size_log; + array_node * pArr = m_Head; + size_t nSlot = splitter.cut( m_Metrics.head_node_size_log ); + assert( nSlot < m_Metrics.head_node_size ); + size_t nHeight = 1; + + while ( true ) { + node_ptr slot = pArr->nodes[nSlot].load( memory_model::memory_order_acquire ); + if ( slot.bits() == flag_array_node ) { + // array node, go down the tree + assert( slot.ptr() != nullptr ); + nSlot = splitter.cut( m_Metrics.array_node_size_log ); + assert( nSlot < m_Metrics.array_node_size ); + pArr = to_array( slot.ptr() ); + nOffset += m_Metrics.array_node_size_log; + ++nHeight; + } + else if ( slot.bits() == flag_array_converting ) { + // the slot is converting to array node right now + bkoff(); + m_Stat.onSlotConverting(); + } + else { + // data node + assert(slot.bits() == 0 ); + + // protect data node by hazard pointer + if ( guard.protect( pArr->nodes[nSlot], [](node_ptr p) -> value_type * { return p.ptr(); }) != slot ) { + // slot value has been changed - retry + m_Stat.onSlotChanged(); + } + else if ( slot.ptr() ) { + if ( cmp( hash, hash_accessor()( *slot.ptr() )) == 0 ) { + // the item with that hash value already exists + m_Stat.onInsertFailed(); + return false; + } + + // the slot must be expanded + expand_slot( pArr, nSlot, slot, nOffset ); + } + else { + // the slot is empty, try to insert data node + node_ptr pNull; + if ( pArr->nodes[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 ); + ++m_ItemCounter; + m_Stat.onInsertSuccess(); + m_Stat.height( nHeight ); + return true; + } + + // insert failed - slot has been changed by another thread + // retry inserting + m_Stat.onInsertRetry(); + } + } + } // while + } + + /// Updates the node + /** + Performs inserting or updating the item with hash value equal to \p val. + - If hash value is found then existing item is replaced with \p val, old item is disposed + with \p Traits::disposer. Note that the disposer is called by \p GC asynchronously. + The function returns std::pair + - If hash value is not found and \p bInsert is \p true then \p val is inserted, + the function returns std::pair + - If hash value is not found and \p bInsert is \p false then the set is unchanged, + the function returns std::pair + + 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 new item has been added or \p false if the set contains that hash. + */ + std::pair update( value_type& val, bool bInsert = true ) + { + return do_update(val, [](value_type&, value_type *) {}, bInsert ); + } + + /// Unlinks the item \p val from the set + /** + The function searches the item \p val in the set and unlink it + if it is found and its address is equal to &val. + + The function returns \p true if success and \p false otherwise. + */ + bool unlink( value_type const& val ) + { + typename gc::Guard guard; + auto pred = [&val](value_type const& item) -> bool { return &item == &val; }; + value_type * p = do_erase( hash_accessor()( val ), guard, std::ref( pred )); + return p != nullptr; + } + + /// Deletes the item from the set + /** + The function searches \p hash in the set, + unlinks the item found, and returns \p true. + If that item is not found the function returns \p false. + + The \ref disposer specified in \p Traits is called by garbage collector \p GC asynchronously. + */ + bool erase( hash_type const& hash ) + { + return erase(hash, [](value_type const&) {} ); + } + + /// Deletes the item from the set + /** + The function searches \p hash in the set, + call \p f functor with item found, and unlinks it from the set. + The \ref disposer specified in \p Traits is called + by garbage collector \p GC asynchronously. + + 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 ) + { + typename gc::Guard guard; + value_type * p = do_erase( hash, guard, []( value_type const&) -> bool {return true; } ); + + // p is guarded by HP + if ( p ) { + f( *p ); + return true; + } + return false; + } + + /// Deletes the item pointed by iterator \p iter + /** + 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& iter ) + { + return do_erase_at( iter ); + } + //@cond + bool erase_at( reverse_iterator const& iter ) + { + return do_erase_at( iter ); + } + //@endcond + + /// 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. + If \p hash is not found the function returns an empty guarded pointer. + + The \p disposer specified in \p Traits class' template parameter is called automatically + by garbage collector \p GC when returned \ref guarded_ptr object to be destroyed or released. + @note Each \p guarded_ptr object uses the GC's guard that can be limited resource. + + Usage: + \code + typedef cds::intrusive::FeldmanHashSet< your_template_args > my_set; + my_set theSet; + // ... + { + my_set::guarded_ptr gp( theSet.extract( 5 )); + if ( gp ) { + // Deal with gp + // ... + } + // Destructor of gp releases internal HP guard + } + \endcode + */ + guarded_ptr extract( hash_type const& hash ) + { + guarded_ptr gp; + { + typename gc::Guard guard; + value_type * p = do_erase( hash, guard, []( value_type const&) -> bool {return true;} ); + + // p is guarded by HP + if ( p ) + gp.reset( p ); + } + return gp; + } + + /// 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 ) + { + typename gc::Guard guard; + value_type * p = search( hash, guard ); + + // p is guarded by HP + if ( p ) { + f( *p ); + return true; + } + return false; + } + + /// 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 find( hash, [](value_type&) {} ); + } + + /// 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 guarded pointer to the item found. + If \p hash is not found the function returns an empty \p guarded_ptr. + + @note Each \p guarded_ptr object uses one GC's guard which can be limited resource. + + Usage: + \code + typedef cds::intrusive::FeldmanHashSet< your_template_params > my_set; + my_set theSet; + // ... + { + my_set::guarded_ptr gp( theSet.get( 5 )); + if ( theSet.get( 5 )) { + // Deal with gp + //... + } + // Destructor of guarded_ptr releases internal HP guard + } + \endcode + */ + guarded_ptr get( hash_type const& hash ) + { + guarded_ptr gp; + { + typename gc::Guard guard; + gp.reset( search( hash, guard )); + } + return gp; + } + + /// 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. + + For each item the \p disposer is called after unlinking. + */ + void clear() + { + clear_array( m_Head, head_size() ); + } + + /// 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 size() == 0; + } + + /// Returns item count in the set + size_t size() const + { + return m_ItemCounter; + } + + /// Returns const reference to internal statistics + stat const& statistics() const + { + return m_Stat; + } + + /// Returns the size of head node + size_t head_size() const + { + return m_Metrics.head_node_size; + } + + /// Returns the size of the array node + size_t array_node_size() const + { + return m_Metrics.array_node_size; + } + + public: + ///@name Thread-safe iterators + /** @anchor cds_intrusive_FeldmanHashSet_iterators + The set supports thread-safe iterators: you may iterate over the set in multi-threaded environment. + It is guaranteed that the iterators will remain valid even if another thread deletes the node the iterator points to: + Hazard Pointer embedded into the iterator object protects the node from physical reclamation. + + @note Since the iterator object contains hazard pointer that is a thread-local resource, + the iterator should not be passed to another thread. + + 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 conditon it1 == it2 + does not entail &(*it1) == &(*it2) : welcome to concurrent containers + - helper member function \p release() that clears internal hazard pointer. + After \p release() the iterator points to \p nullptr but it still remain valid: further iterating is possible. + + During iteration you may safely erase any item from the set; + @ref erase_at() function call doesn't invalidate any iterator. + If some iterator points to the item to be erased, that item is not deleted immediately + but only after that iterator will be advanced forward or backward. + + @note It is possible the item can be iterated more that once, for example, if an iterator points to the item + in array node that is being splitted. + */ + ///@{ + + /// Returns an iterator to the beginning of the set + iterator begin() + { + return iterator( *this, m_Head, size_t(0) - 1 ); + } + + /// Returns an const iterator to the beginning of the set + const_iterator begin() const + { + return const_iterator( *this, m_Head, size_t(0) - 1 ); + } + + /// Returns an const iterator to the beginning of the set + const_iterator cbegin() + { + return const_iterator( *this, m_Head, size_t(0) - 1 ); + } + + /// 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 iterator( *this, m_Head, head_size(), false ); + } + + /// 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 const_iterator( *this, m_Head, head_size(), false ); + } + + /// 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 const_iterator( *this, m_Head, head_size(), false ); + } + + /// Returns a reverse iterator to the first element of the reversed set + reverse_iterator rbegin() + { + return reverse_iterator( *this, m_Head, head_size() ); + } + + /// Returns a const reverse iterator to the first element of the reversed set + const_reverse_iterator rbegin() const + { + return const_reverse_iterator( *this, m_Head, head_size() ); + } + + /// Returns a const reverse iterator to the first element of the reversed set + const_reverse_iterator crbegin() + { + return const_reverse_iterator( *this, m_Head, head_size() ); + } + + /// 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 reverse_iterator( *this, m_Head, size_t(0) - 1, false ); + } + + /// 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 const_reverse_iterator( *this, m_Head, size_t(0) - 1, false ); + } + + /// 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 const_reverse_iterator( *this, m_Head, size_t(0) - 1, false ); + } + ///@} + + private: + //@cond + + array_node * alloc_head_node() const + { + return alloc_array_node( head_size(), nullptr, 0 ); + } + + array_node * alloc_array_node( array_node * pParent, size_t idxParent ) const + { + return alloc_array_node( array_node_size(), pParent, idxParent ); + } + + static array_node * alloc_array_node( size_t nSize, array_node * pParent, size_t idxParent ) + { + array_node * pNode = cxx_array_node_allocator().NewBlock( sizeof(array_node) + sizeof(atomic_node_ptr) * (nSize - 1), pParent, idxParent ); + new ( pNode->nodes ) atomic_node_ptr[ nSize ]; + return pNode; + } + + static void free_array_node( array_node * parr ) + { + cxx_array_node_allocator().Delete( parr ); + } + + void destroy_tree() + { + // The function is not thread-safe. For use in dtor only + // Remove data node + clear(); + + // Destroy all array nodes + destroy_array_nodes( m_Head, head_size()); + } + + void destroy_array_nodes( array_node * pArr, size_t nSize ) + { + for ( atomic_node_ptr * p = pArr->nodes, *pLast = pArr->nodes + nSize; p != pLast; ++p ) { + node_ptr slot = p->load( memory_model::memory_order_acquire ); + if ( slot.bits() == flag_array_node ) { + destroy_array_nodes(to_array(slot.ptr()), array_node_size()); + free_array_node( to_array(slot.ptr())); + p->store(node_ptr(), memory_model::memory_order_relaxed ); + } + } + } + + void clear_array( array_node * pArrNode, size_t nSize ) + { + back_off bkoff; + + + for ( atomic_node_ptr * pArr = pArrNode->nodes, *pLast = pArr + nSize; pArr != pLast; ++pArr ) { + while ( true ) { + node_ptr slot = pArr->load( memory_model::memory_order_acquire ); + if ( slot.bits() == flag_array_node ) { + // array node, go down the tree + assert( slot.ptr() != nullptr ); + clear_array( to_array( slot.ptr()), array_node_size() ); + break; + } + else if ( slot.bits() == flag_array_converting ) { + // the slot is converting to array node right now + while ( (slot = pArr->load(memory_model::memory_order_acquire)).bits() == flag_array_converting ) { + bkoff(); + m_Stat.onSlotConverting(); + } + bkoff.reset(); + + assert( slot.ptr() != nullptr ); + assert(slot.bits() == flag_array_node ); + clear_array( to_array( slot.ptr()), array_node_size() ); + break; + } + else { + // data node + if ( pArr->compare_exchange_strong( slot, node_ptr(), memory_model::memory_order_acquire, atomics::memory_order_relaxed )) { + if ( slot.ptr() ) { + gc::template retire( slot.ptr() ); + --m_ItemCounter; + m_Stat.onEraseSuccess(); + } + break; + } + } + } + } + } + + union converter { + value_type * pData; + array_node * pArr; + + converter( value_type * p ) + : pData( p ) + {} + + converter( array_node * p ) + : pArr( p ) + {} + }; + + static array_node * to_array( value_type * p ) + { + return converter( p ).pArr; + } + static value_type * to_node( array_node * p ) + { + return converter( p ).pData; + } + + bool expand_slot( array_node * pParent, size_t idxParent, node_ptr current, size_t nOffset ) + { + assert( current.bits() == 0 ); + assert( current.ptr() ); + + size_t idx = hash_splitter(hash_accessor()(*current.ptr()), nOffset).cut( m_Metrics.array_node_size_log ); + array_node * pArr = alloc_array_node( pParent, idxParent ); + + node_ptr cur(current.ptr()); + atomic_node_ptr& slot = pParent->nodes[idxParent]; + if ( !slot.compare_exchange_strong( cur, cur | flag_array_converting, memory_model::memory_order_release, atomics::memory_order_relaxed )) + { + m_Stat.onExpandNodeFailed(); + free_array_node( pArr ); + return false; + } + + pArr->nodes[idx].store( current, memory_model::memory_order_release ); + + cur = cur | flag_array_converting; + CDS_VERIFY( + slot.compare_exchange_strong( cur, node_ptr( to_node( pArr ), flag_array_node ), memory_model::memory_order_release, atomics::memory_order_relaxed ) + ); + + m_Stat.onExpandNodeSuccess(); + m_Stat.onArrayNodeCreated(); + return true; + } + //@endcond + + protected: + //@cond + value_type * search( hash_type const& hash, typename gc::Guard& guard ) + { + hash_splitter splitter( hash ); + hash_comparator cmp; + back_off bkoff; + + array_node * pArr = m_Head; + size_t nSlot = splitter.cut( m_Metrics.head_node_size_log ); + assert( nSlot < m_Metrics.head_node_size ); + + while ( true ) { + node_ptr slot = pArr->nodes[nSlot].load( memory_model::memory_order_acquire ); + if ( slot.bits() == flag_array_node ) { + // array node, go down the tree + assert( slot.ptr() != nullptr ); + nSlot = splitter.cut( m_Metrics.array_node_size_log ); + assert( nSlot < m_Metrics.array_node_size ); + pArr = to_array( slot.ptr() ); + } + else if ( slot.bits() == flag_array_converting ) { + // the slot is converting to array node right now + bkoff(); + m_Stat.onSlotConverting(); + } + else { + // data node + assert(slot.bits() == 0 ); + + // protect data node by hazard pointer + if ( guard.protect( pArr->nodes[nSlot], [](node_ptr p) -> value_type * { return p.ptr(); }) != slot ) { + // slot value has been changed - retry + m_Stat.onSlotChanged(); + } + else if ( slot.ptr() && cmp( hash, hash_accessor()( *slot.ptr() )) == 0 ) { + // item found + m_Stat.onFindSuccess(); + return slot.ptr(); + } + m_Stat.onFindFailed(); + return nullptr; + } + } // while + } + + template + value_type * do_erase( hash_type const& hash, typename gc::Guard& guard, Predicate pred ) + { + hash_splitter splitter( hash ); + hash_comparator cmp; + back_off bkoff; + + array_node * pArr = m_Head; + size_t nSlot = splitter.cut( m_Metrics.head_node_size_log ); + assert( nSlot < m_Metrics.head_node_size ); + + while ( true ) { + node_ptr slot = pArr->nodes[nSlot].load( memory_model::memory_order_acquire ); + if ( slot.bits() == flag_array_node ) { + // array node, go down the tree + assert( slot.ptr() != nullptr ); + nSlot = splitter.cut( m_Metrics.array_node_size_log ); + assert( nSlot < m_Metrics.array_node_size ); + pArr = to_array( slot.ptr() ); + } + else if ( slot.bits() == flag_array_converting ) { + // the slot is converting to array node right now + bkoff(); + m_Stat.onSlotConverting(); + } + else { + // data node + assert(slot.bits() == 0 ); + + // protect data node by hazard pointer + if ( guard.protect( pArr->nodes[nSlot], [](node_ptr p) -> value_type * { return p.ptr(); }) != slot ) { + // slot value has been changed - retry + m_Stat.onSlotChanged(); + } + else if ( slot.ptr() ) { + if ( cmp( hash, hash_accessor()( *slot.ptr() )) == 0 && pred( *slot.ptr() )) { + // item found - replace it with nullptr + if ( pArr->nodes[nSlot].compare_exchange_strong(slot, node_ptr(nullptr), memory_model::memory_order_acquire, atomics::memory_order_relaxed) ) { + // slot is guarded by HP + gc::template retire( slot.ptr() ); + --m_ItemCounter; + m_Stat.onEraseSuccess(); + + return slot.ptr(); + } + m_Stat.onEraseRetry(); + continue; + } + m_Stat.onEraseFailed(); + return nullptr; + } + else { + // the slot is empty + m_Stat.onEraseFailed(); + return nullptr; + } + } + } // while + } + + bool do_erase_at( iterator_base const& iter ) + { + if ( iter.m_set != this ) + return false; + if ( iter.m_pNode == m_Head && iter.m_idx >= head_size()) + return false; + if ( iter.m_idx >= array_node_size() ) + return false; + + for (;;) { + node_ptr slot = iter.m_pNode->nodes[iter.m_idx].load( memory_model::memory_order_acquire ); + if ( slot.bits() == 0 && slot.ptr() == iter.pointer() ) { + if ( iter.m_pNode->nodes[iter.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; + } + } + + template + std::pair do_update( value_type& val, Func f, bool bInsert = true ) + { + hash_type const& hash = hash_accessor()( val ); + hash_splitter splitter( hash ); + hash_comparator cmp; + typename gc::template GuardArray<2> guards; + back_off bkoff; + + array_node * pArr = m_Head; + size_t nSlot = splitter.cut( m_Metrics.head_node_size_log ); + assert( nSlot < m_Metrics.head_node_size ); + size_t nOffset = m_Metrics.head_node_size_log; + size_t nHeight = 1; + + guards.assign( 1, &val ); + + while ( true ) { + node_ptr slot = pArr->nodes[nSlot].load( memory_model::memory_order_acquire ); + if ( slot.bits() == flag_array_node ) { + // array node, go down the tree + assert( slot.ptr() != nullptr ); + nSlot = splitter.cut( m_Metrics.array_node_size_log ); + assert( nSlot < m_Metrics.array_node_size ); + pArr = to_array( slot.ptr() ); + nOffset += m_Metrics.array_node_size_log; + ++nHeight; + } + else if ( slot.bits() == flag_array_converting ) { + // the slot is converting to array node right now + bkoff(); + m_Stat.onSlotConverting(); + } + else { + // data node + assert(slot.bits() == 0 ); + + // protect data node by hazard pointer + if ( guards.protect( 0, pArr->nodes[nSlot], [](node_ptr p) -> value_type * { return p.ptr(); }) != slot ) { + // slot value has been changed - retry + m_Stat.onSlotChanged(); + } + else if ( slot.ptr() ) { + if ( cmp( hash, hash_accessor()( *slot.ptr() )) == 0 ) { + // the item with that hash value already exists + // Replace it with val + if ( slot.ptr() == &val ) { + m_Stat.onUpdateExisting(); + return std::make_pair( true, false ); + } + + if ( pArr->nodes[nSlot].compare_exchange_strong( slot, node_ptr( &val ), memory_model::memory_order_release, atomics::memory_order_relaxed )) { + // slot can be disposed + f( val, slot.ptr() ); + gc::template retire( slot.ptr() ); + m_Stat.onUpdateExisting(); + return std::make_pair( true, false ); + } + + m_Stat.onUpdateRetry(); + continue; + } + + // the slot must be expanded + expand_slot( pArr, nSlot, slot, nOffset ); + } + else { + // the slot is empty, try to insert data node + if ( bInsert ) { + node_ptr pNull; + if ( pArr->nodes[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, nullptr ); + ++m_ItemCounter; + m_Stat.onUpdateNew(); + m_Stat.height( nHeight ); + return std::make_pair( true, true ); + } + } + else { + m_Stat.onUpdateFailed(); + return std::make_pair( false, false ); + } + + // insert failed - slot has been changed by another thread + // retry updating + m_Stat.onUpdateRetry(); + } + } + } // while + } + //@endcond + }; +}} // namespace cds::intrusive + +/* +namespace std { + + template + struct iterator_traits< typename cds::intrusive::FeldmanHashSet< GC, T, Traits >::iterator > + { + typedef typename cds::intrusive::FeldmanHashSet< GC, T, Traits >::iterator iterator_class; + + // difference_type is not applicable for that iterator + // typedef ??? difference_type + typedef T value_type; + typedef typename iterator_class::value_ptr pointer; + typedef typename iterator_class::value_ref reference; + typedef bidirectional_iterator_tag iterator_category; + }; + + template + struct iterator_traits< typename cds::intrusive::FeldmanHashSet< GC, T, Traits >::const_iterator > + { + typedef typename cds::intrusive::FeldmanHashSet< GC, T, Traits >::const_iterator iterator_class; + + // difference_type is not applicable for that iterator + // typedef ??? difference_type + typedef T value_type; + typedef typename iterator_class::value_ptr pointer; + typedef typename iterator_class::value_ref reference; + typedef bidirectional_iterator_tag iterator_category; + }; + +} // namespace std +*/ + +#endif // #ifndef CDSLIB_INTRUSIVE_IMPL_FELDMAN_HASHSET_H diff --git a/cds/intrusive/impl/multilevel_hashset.h b/cds/intrusive/impl/multilevel_hashset.h deleted file mode 100644 index edb7941f..00000000 --- a/cds/intrusive/impl/multilevel_hashset.h +++ /dev/null @@ -1,1467 +0,0 @@ -//$$CDS-header$$ - -#ifndef CDSLIB_INTRUSIVE_IMPL_MULTILEVEL_HASHSET_H -#define CDSLIB_INTRUSIVE_IMPL_MULTILEVEL_HASHSET_H - -#include // std::ref -#include // std::iterator_traits - -#include -#include - -namespace cds { namespace intrusive { - /// Intrusive hash set based on multi-level array - /** @ingroup cds_intrusive_map - @anchor cds_intrusive_MultilevelHashSet_hp - - Source: - - [2013] Steven Feldman, Pierre LaBorde, Damian Dechev "Concurrent Multi-level Arrays: - Wait-free Extensible Hash Maps" - - [From the paper] The hardest problem encountered while developing a parallel hash map is how to perform - a global resize, the process of redistributing the elements in a hash map that occurs when adding new - buckets. The negative impact of blocking synchronization is multiplied during a global resize, because all - threads will be forced to wait on the thread that is performing the involved process of resizing the hash map - and redistributing the elements. \p %MultilevelHashSet implementation avoids global resizes through new array - allocation. By allowing concurrent expansion this structure is free from the overhead of an explicit resize, - which facilitates concurrent operations. - - The presented design includes dynamic hashing, the use of sub-arrays within the hash map data structure; - which, in combination with perfect hashing, means that each element has a unique final, as well as current, position. - It is important to note that the perfect hash function required by our hash map is trivial to realize as - any hash function that permutes the bits of the key is suitable. This is possible because of our approach - to the hash function; we require that it produces hash values that are equal in size to that of the key. - We know that if we expand the hash map a fixed number of times there can be no collision as duplicate keys - are not provided for in the standard semantics of a hash map. - - \p %MultiLevelHashSet is a multi-level array which has a structure similar to a tree: - @image html multilevel_hashset.png - The multi-level array differs from a tree in that each position on the tree could hold an array of nodes or a single node. - A position that holds a single node is a \p dataNode which holds the hash value of a key and the value that is associated - with that key; it is a simple struct holding two variables. A \p dataNode in the multi-level array could be marked. - A \p markedDataNode refers to a pointer to a \p dataNode that has been bitmarked at the least significant bit (LSB) - of the pointer to the node. This signifies that this \p dataNode is contended. An expansion must occur at this node; - any thread that sees this \p markedDataNode will try to replace it with an \p arrayNode; which is a position that holds - an array of nodes. The pointer to an \p arrayNode is differentiated from that of a pointer to a \p dataNode by a bitmark - on the second-least significant bit. - - \p %MultiLevelHashSet multi-level array is similar to a tree in that we keep a pointer to the root, which is a memory array - called \p head. The length of the \p head memory array is unique, whereas every other \p arrayNode has a uniform length; - a normal \p arrayNode has a fixed power-of-two length equal to the binary logarithm of a variable called \p arrayLength. - The maximum depth of the tree, \p maxDepth, is the maximum number of pointers that must be followed to reach any node. - We define \p currentDepth as the number of memory arrays that we need to traverse to reach the \p arrayNode on which - we need to operate; this is initially one, because of \p head. - - That approach to the structure of the hash set uses an extensible hashing scheme; the hash value is treated as a bit - string and rehash incrementally. - - @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_intrusive_MultilevelHashSet_iterators "bidirectional thread-safe iterators". - - 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 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". RCU specialization - has a slightly different interface. - */ - template < - class GC - ,typename T -#ifdef CDS_DOXYGEN_INVOKED - ,typename Traits = multilevel_hashset::traits -#else - ,typename Traits -#endif - > - class MultiLevelHashSet - { - public: - typedef GC gc; ///< 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 traits::hash_accessor hash_accessor; ///< Hash accessor functor - static_assert(!std::is_same< hash_accessor, cds::opt::none >::value, "hash_accessor functor must be specified" ); - - /// Hash type deduced from \p hash_accessor return type - typedef typename std::decay< - typename std::remove_reference< - decltype( hash_accessor()( std::declval()) ) - >::type - >::type hash_type; - //typedef typename std::result_of< hash_accessor( std::declval()) >::type hash_type; - static_assert( !std::is_pointer::value, "hash_accessor should return a reference to hash value" ); - - typedef typename traits::disposer disposer; ///< data node disposer - -# ifdef CDS_DOXYGEN_INVOKED - typedef implementation_defined hash_comparator ; ///< hash compare functor based on opt::compare and opt::less option setter -# else - typedef typename cds::opt::details::make_comparator_from< - hash_type, - traits, - multilevel_hashset::bitwise_compare< hash_type > - >::type hash_comparator; -# endif - - typedef typename traits::item_counter item_counter; ///< Item counter type - 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 gc::template guarded_ptr< value_type > guarded_ptr; ///< Guarded pointer - - /// Count of hazard pointers required - static CDS_CONSTEXPR size_t const c_nHazardPtrCount = 2; - - /// Node marked poiter - typedef cds::details::marked_ptr< value_type, 3 > node_ptr; - /// Array node element - typedef atomics::atomic< node_ptr > atomic_node_ptr; - - protected: - //@cond - enum node_flags { - flag_array_converting = 1, ///< the cell is converting from data node to an array node - flag_array_node = 2 ///< the cell is a pointer to an array node - }; - - struct array_node { - array_node * const pParent; ///< parent array node - size_t const idxParent; ///< index in parent array node - atomic_node_ptr nodes[1]; ///< node array - - array_node( array_node * parent, size_t idx ) - : pParent( parent ) - , idxParent( idx ) - {} - - array_node() = delete; - array_node( array_node const&) = delete; - array_node( array_node&& ) = delete; - }; - - typedef cds::details::Allocator< array_node, node_allocator > cxx_array_node_allocator; - - typedef multilevel_hashset::details::hash_splitter< hash_type > hash_splitter; - //@endcond - - protected: - //@cond - class iterator_base - { - friend class MultiLevelHashSet; - - protected: - array_node * m_pNode; ///< current array node - size_t m_idx; ///< current position in m_pNode - typename gc::Guard m_guard; ///< HP guard - MultiLevelHashSet const* m_set; ///< Hash set - - public: - iterator_base() CDS_NOEXCEPT - : m_pNode( nullptr ) - , m_idx( 0 ) - , m_set( nullptr ) - {} - - iterator_base( iterator_base const& rhs ) CDS_NOEXCEPT - : m_pNode( rhs.m_pNode ) - , m_idx( rhs.m_idx ) - , m_set( rhs.m_set ) - { - m_guard.copy( rhs.m_guard ); - } - - iterator_base& operator=(iterator_base const& rhs) CDS_NOEXCEPT - { - m_pNode = rhs.m_pNode; - m_idx = rhs.m_idx; - m_set = rhs.m_set; - m_guard.copy( rhs.m_guard ); - return *this; - } - - iterator_base& operator++() - { - forward(); - return *this; - } - - iterator_base& operator--() - { - backward(); - return *this; - } - - void release() - { - m_guard.clear(); - } - - bool operator ==(iterator_base const& rhs) const CDS_NOEXCEPT - { - return m_pNode == rhs.m_pNode && m_idx == rhs.m_idx && m_set == rhs.m_set; - } - - bool operator !=(iterator_base const& rhs) const CDS_NOEXCEPT - { - return !( *this == rhs ); - } - - protected: - iterator_base( MultiLevelHashSet const& set, array_node * pNode, size_t idx, bool ) - : m_pNode( pNode ) - , m_idx( idx ) - , m_set( &set ) - {} - - iterator_base( MultiLevelHashSet const& set, array_node * pNode, size_t idx ) - : m_pNode( pNode ) - , m_idx( idx ) - , m_set( &set ) - { - forward(); - } - - value_type * pointer() const CDS_NOEXCEPT - { - return m_guard.template get(); - } - - void forward() - { - assert( m_set != nullptr ); - assert( m_pNode != nullptr ); - - size_t const arrayNodeSize = m_set->array_node_size(); - size_t const headSize = m_set->head_size(); - array_node * pNode = m_pNode; - size_t idx = m_idx + 1; - size_t nodeSize = m_pNode->pParent? arrayNodeSize : headSize; - - for ( ;; ) { - if ( idx < nodeSize ) { - node_ptr slot = pNode->nodes[idx].load( memory_model::memory_order_acquire ); - if ( slot.bits() == flag_array_node ) { - // array node, go down the tree - assert( slot.ptr() != nullptr ); - pNode = to_array( slot.ptr() ); - idx = 0; - nodeSize = arrayNodeSize; - } - else if ( slot.bits() == flag_array_converting ) { - // the slot is converting to array node right now - skip the node - ++idx; - } - else { - if ( slot.ptr()) { - // data node - if ( m_guard.protect( pNode->nodes[idx], [](node_ptr p) -> value_type * { return p.ptr(); }) == slot ) { - m_pNode = pNode; - m_idx = idx; - return; - } - } - ++idx; - } - } - else { - // up to parent node - if ( pNode->pParent ) { - idx = pNode->idxParent + 1; - pNode = pNode->pParent; - nodeSize = pNode->pParent ? arrayNodeSize : headSize; - } - else { - // end() - assert( pNode == m_set->m_Head ); - assert( idx == headSize ); - m_pNode = pNode; - m_idx = idx; - return; - } - } - } - } - - void backward() - { - assert( m_set != nullptr ); - assert( m_pNode != nullptr ); - - size_t const arrayNodeSize = m_set->array_node_size(); - size_t const headSize = m_set->head_size(); - size_t const endIdx = size_t(0) - 1; - - array_node * pNode = m_pNode; - size_t idx = m_idx - 1; - size_t nodeSize = m_pNode->pParent? arrayNodeSize : headSize; - - for ( ;; ) { - if ( idx != endIdx ) { - node_ptr slot = pNode->nodes[idx].load( memory_model::memory_order_acquire ); - if ( slot.bits() == flag_array_node ) { - // array node, go down the tree - assert( slot.ptr() != nullptr ); - pNode = to_array( slot.ptr() ); - nodeSize = arrayNodeSize; - idx = nodeSize - 1; - } - else if ( slot.bits() == flag_array_converting ) { - // the slot is converting to array node right now - skip the node - --idx; - } - else { - if ( slot.ptr()) { - // data node - if ( m_guard.protect( pNode->nodes[idx], [](node_ptr p) -> value_type * { return p.ptr(); }) == slot ) { - m_pNode = pNode; - m_idx = idx; - return; - } - } - --idx; - } - } - else { - // up to parent node - if ( pNode->pParent ) { - idx = pNode->idxParent - 1; - pNode = pNode->pParent; - nodeSize = pNode->pParent ? arrayNodeSize : headSize; - } - else { - // rend() - assert( pNode == m_set->m_Head ); - assert( idx == endIdx ); - m_pNode = pNode; - m_idx = idx; - return; - } - } - } - } - }; - - template - Iterator init_begin() const - { - return Iterator( *this, m_Head, size_t(0) - 1 ); - } - - template - Iterator init_end() const - { - return Iterator( *this, m_Head, head_size(), false ); - } - - template - Iterator init_rbegin() const - { - return Iterator( *this, m_Head, head_size() ); - } - - template - Iterator init_rend() const - { - return Iterator( *this, m_Head, size_t(0) - 1, false ); - } - - /// Bidirectional iterator class - template - class bidirectional_iterator: protected iterator_base - { - friend class MultiLevelHashSet; - - protected: - static CDS_CONSTEXPR bool const c_bConstantIterator = IsConst; - - public: - typedef typename std::conditional< IsConst, value_type const*, value_type*>::type value_ptr; ///< Value pointer - typedef typename std::conditional< IsConst, value_type const&, value_type&>::type value_ref; ///< Value reference - - public: - bidirectional_iterator() CDS_NOEXCEPT - {} - - bidirectional_iterator( bidirectional_iterator const& rhs ) CDS_NOEXCEPT - : iterator_base( rhs ) - {} - - bidirectional_iterator& operator=(bidirectional_iterator const& rhs) CDS_NOEXCEPT - { - iterator_base::operator=( rhs ); - return *this; - } - - bidirectional_iterator& operator++() - { - iterator_base::operator++(); - return *this; - } - - bidirectional_iterator& operator--() - { - iterator_base::operator--(); - return *this; - } - - value_ptr operator ->() const CDS_NOEXCEPT - { - return iterator_base::pointer(); - } - - value_ref operator *() const CDS_NOEXCEPT - { - value_ptr p = iterator_base::pointer(); - assert( p ); - return *p; - } - - void release() - { - iterator_base::release(); - } - - template - bool operator ==(bidirectional_iterator const& rhs) const CDS_NOEXCEPT - { - return iterator_base::operator==( rhs ); - } - - template - bool operator !=(bidirectional_iterator const& rhs) const CDS_NOEXCEPT - { - return !( *this == rhs ); - } - - protected: - bidirectional_iterator( MultiLevelHashSet& set, array_node * pNode, size_t idx, bool ) - : iterator_base( set, pNode, idx, false ) - {} - - bidirectional_iterator( MultiLevelHashSet& set, array_node * pNode, size_t idx ) - : iterator_base( set, pNode, idx ) - {} - }; - - /// Reverse bidirectional iterator - template - class reverse_bidirectional_iterator : public iterator_base - { - friend class MultiLevelHashSet; - - public: - typedef typename std::conditional< IsConst, value_type const*, value_type*>::type value_ptr; ///< Value pointer - typedef typename std::conditional< IsConst, value_type const&, value_type&>::type value_ref; ///< Value reference - - public: - reverse_bidirectional_iterator() CDS_NOEXCEPT - : iterator_base() - {} - - reverse_bidirectional_iterator( reverse_bidirectional_iterator const& rhs ) CDS_NOEXCEPT - : iterator_base( rhs ) - {} - - reverse_bidirectional_iterator& operator=( reverse_bidirectional_iterator const& rhs) CDS_NOEXCEPT - { - iterator_base::operator=( rhs ); - return *this; - } - - reverse_bidirectional_iterator& operator++() - { - iterator_base::operator--(); - return *this; - } - - reverse_bidirectional_iterator& operator--() - { - iterator_base::operator++(); - return *this; - } - - value_ptr operator ->() const CDS_NOEXCEPT - { - return iterator_base::pointer(); - } - - value_ref operator *() const CDS_NOEXCEPT - { - value_ptr p = iterator_base::pointer(); - assert( p ); - return *p; - } - - void release() - { - iterator_base::release(); - } - - template - bool operator ==(reverse_bidirectional_iterator const& rhs) const - { - return iterator_base::operator==( rhs ); - } - - template - bool operator !=(reverse_bidirectional_iterator const& rhs) - { - return !( *this == rhs ); - } - - private: - reverse_bidirectional_iterator( MultiLevelHashSet& set, array_node * pNode, size_t idx, bool ) - : iterator_base( set, pNode, idx, false ) - {} - - reverse_bidirectional_iterator( MultiLevelHashSet& set, array_node * pNode, size_t idx ) - : iterator_base( set, pNode, idx, false ) - { - iterator_base::backward(); - } - }; - //@endcond - - public: -#ifdef CDS_DOXYGEN_INVOKED - typedef implementation_defined iterator; ///< @ref cds_intrusive_MultilevelHashSet_iterators "bidirectional iterator" type - typedef implementation_defined const_iterator; ///< @ref cds_intrusive_MultilevelHashSet_iterators "bidirectional const iterator" type - typedef implementation_defined reverse_iterator; ///< @ref cds_intrusive_MultilevelHashSet_iterators "bidirectional reverse iterator" type - typedef implementation_defined const_reverse_iterator; ///< @ref cds_intrusive_MultilevelHashSet_iterators "bidirectional reverse const iterator" type -#else - typedef bidirectional_iterator iterator; - typedef bidirectional_iterator const_iterator; - typedef reverse_bidirectional_iterator reverse_iterator; - typedef reverse_bidirectional_iterator const_reverse_iterator; -#endif - - private: - //@cond - multilevel_hashset::details::metrics const m_Metrics; ///< Metrics - array_node * m_Head; ///< Head array - item_counter m_ItemCounter; ///< Item counter - stat m_Stat; ///< Internal statistics - //@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 ) - : m_Metrics( multilevel_hashset::details::metrics::make( head_bits, array_bits, sizeof(hash_type))) - , m_Head( alloc_head_node()) - {} - - /// Destructs the set and frees all data - ~MultiLevelHashSet() - { - destroy_tree(); - free_array_node( m_Head ); - } - - /// Inserts new node - /** - The function inserts \p val in the set if it does not contain - an item with that hash. - - Returns \p true if \p val is placed into the set, \p false otherwise. - */ - bool insert( value_type& val ) - { - return insert( val, [](value_type&) {} ); - } - - /// Inserts new node - /** - This function is intended for derived non-intrusive containers. - - 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 \p val. - - The functor signature is: - \code - void func( value_type& val ); - \endcode - where \p val is the item inserted. - - The user-defined functor is called only if the inserting is success. - - @warning See \ref cds_intrusive_item_creating "insert item troubleshooting". - */ - template - bool insert( value_type& val, Func f ) - { - hash_type const& hash = hash_accessor()( val ); - hash_splitter splitter( hash ); - hash_comparator cmp; - typename gc::Guard guard; - back_off bkoff; - - size_t nOffset = m_Metrics.head_node_size_log; - array_node * pArr = m_Head; - size_t nSlot = splitter.cut( m_Metrics.head_node_size_log ); - assert( nSlot < m_Metrics.head_node_size ); - size_t nHeight = 1; - - while ( true ) { - node_ptr slot = pArr->nodes[nSlot].load( memory_model::memory_order_acquire ); - if ( slot.bits() == flag_array_node ) { - // array node, go down the tree - assert( slot.ptr() != nullptr ); - nSlot = splitter.cut( m_Metrics.array_node_size_log ); - assert( nSlot < m_Metrics.array_node_size ); - pArr = to_array( slot.ptr() ); - nOffset += m_Metrics.array_node_size_log; - ++nHeight; - } - else if ( slot.bits() == flag_array_converting ) { - // the slot is converting to array node right now - bkoff(); - m_Stat.onSlotConverting(); - } - else { - // data node - assert(slot.bits() == 0 ); - - // protect data node by hazard pointer - if ( guard.protect( pArr->nodes[nSlot], [](node_ptr p) -> value_type * { return p.ptr(); }) != slot ) { - // slot value has been changed - retry - m_Stat.onSlotChanged(); - } - else if ( slot.ptr() ) { - if ( cmp( hash, hash_accessor()( *slot.ptr() )) == 0 ) { - // the item with that hash value already exists - m_Stat.onInsertFailed(); - return false; - } - - // the slot must be expanded - expand_slot( pArr, nSlot, slot, nOffset ); - } - else { - // the slot is empty, try to insert data node - node_ptr pNull; - if ( pArr->nodes[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 ); - ++m_ItemCounter; - m_Stat.onInsertSuccess(); - m_Stat.height( nHeight ); - return true; - } - - // insert failed - slot has been changed by another thread - // retry inserting - m_Stat.onInsertRetry(); - } - } - } // while - } - - /// Updates the node - /** - Performs inserting or updating the item with hash value equal to \p val. - - If hash value is found then existing item is replaced with \p val, old item is disposed - with \p Traits::disposer. Note that the disposer is called by \p GC asynchronously. - The function returns std::pair - - If hash value is not found and \p bInsert is \p true then \p val is inserted, - the function returns std::pair - - If hash value is not found and \p bInsert is \p false then the set is unchanged, - the function returns std::pair - - 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 new item has been added or \p false if the set contains that hash. - */ - std::pair update( value_type& val, bool bInsert = true ) - { - return do_update(val, [](value_type&, value_type *) {}, bInsert ); - } - - /// Unlinks the item \p val from the set - /** - The function searches the item \p val in the set and unlink it - if it is found and its address is equal to &val. - - The function returns \p true if success and \p false otherwise. - */ - bool unlink( value_type const& val ) - { - typename gc::Guard guard; - auto pred = [&val](value_type const& item) -> bool { return &item == &val; }; - value_type * p = do_erase( hash_accessor()( val ), guard, std::ref( pred )); - return p != nullptr; - } - - /// Deletes the item from the set - /** - The function searches \p hash in the set, - unlinks the item found, and returns \p true. - If that item is not found the function returns \p false. - - The \ref disposer specified in \p Traits is called by garbage collector \p GC asynchronously. - */ - bool erase( hash_type const& hash ) - { - return erase(hash, [](value_type const&) {} ); - } - - /// Deletes the item from the set - /** - The function searches \p hash in the set, - call \p f functor with item found, and unlinks it from the set. - The \ref disposer specified in \p Traits is called - by garbage collector \p GC asynchronously. - - 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 ) - { - typename gc::Guard guard; - value_type * p = do_erase( hash, guard, []( value_type const&) -> bool {return true; } ); - - // p is guarded by HP - if ( p ) { - f( *p ); - return true; - } - return false; - } - - /// Deletes the item pointed by iterator \p iter - /** - 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& iter ) - { - return do_erase_at( iter ); - } - //@cond - bool erase_at( reverse_iterator const& iter ) - { - return do_erase_at( iter ); - } - //@endcond - - /// 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. - If \p hash is not found the function returns an empty guarded pointer. - - The \p disposer specified in \p Traits class' template parameter is called automatically - by garbage collector \p GC when returned \ref guarded_ptr object to be destroyed or released. - @note Each \p guarded_ptr object uses the GC's guard that can be limited resource. - - Usage: - \code - typedef cds::intrusive::MultiLevelHashSet< your_template_args > my_set; - my_set theSet; - // ... - { - my_set::guarded_ptr gp( theSet.extract( 5 )); - if ( gp ) { - // Deal with gp - // ... - } - // Destructor of gp releases internal HP guard - } - \endcode - */ - guarded_ptr extract( hash_type const& hash ) - { - guarded_ptr gp; - { - typename gc::Guard guard; - value_type * p = do_erase( hash, guard, []( value_type const&) -> bool {return true;} ); - - // p is guarded by HP - if ( p ) - gp.reset( p ); - } - return gp; - } - - /// 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 ) - { - typename gc::Guard guard; - value_type * p = search( hash, guard ); - - // p is guarded by HP - if ( p ) { - f( *p ); - return true; - } - return false; - } - - /// 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 find( hash, [](value_type&) {} ); - } - - /// 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 guarded pointer to the item found. - If \p hash is not found the function returns an empty \p guarded_ptr. - - @note Each \p guarded_ptr object uses one GC's guard which can be limited resource. - - Usage: - \code - typedef cds::intrusive::MultiLevelHashSet< your_template_params > my_set; - my_set theSet; - // ... - { - my_set::guarded_ptr gp( theSet.get( 5 )); - if ( theSet.get( 5 )) { - // Deal with gp - //... - } - // Destructor of guarded_ptr releases internal HP guard - } - \endcode - */ - guarded_ptr get( hash_type const& hash ) - { - guarded_ptr gp; - { - typename gc::Guard guard; - gp.reset( search( hash, guard )); - } - return gp; - } - - /// 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. - - For each item the \p disposer is called after unlinking. - */ - void clear() - { - clear_array( m_Head, head_size() ); - } - - /// 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 size() == 0; - } - - /// Returns item count in the set - size_t size() const - { - return m_ItemCounter; - } - - /// Returns const reference to internal statistics - stat const& statistics() const - { - return m_Stat; - } - - /// Returns the size of head node - size_t head_size() const - { - return m_Metrics.head_node_size; - } - - /// Returns the size of the array node - size_t array_node_size() const - { - return m_Metrics.array_node_size; - } - - public: - ///@name Thread-safe iterators - /** @anchor cds_intrusive_MultilevelHashSet_iterators - The set supports thread-safe iterators: you may iterate over the set in multi-threaded environment. - It is guaranteed that the iterators will remain valid even if another thread deletes the node the iterator points to: - Hazard Pointer embedded into the iterator object protects the node from physical reclamation. - - @note Since the iterator object contains hazard pointer that is a thread-local resource, - the iterator should not be passed to another thread. - - 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 conditon it1 == it2 - does not entail &(*it1) == &(*it2) : welcome to concurrent containers - - helper member function \p release() that clears internal hazard pointer. - After \p release() the iterator points to \p nullptr but it still remain valid: further iterating is possible. - - During iteration you may safely erase any item from the set; - @ref erase_at() function call doesn't invalidate any iterator. - If some iterator points to the item to be erased, that item is not deleted immediately - but only after that iterator will be advanced forward or backward. - - @note It is possible the item can be iterated more that once, for example, if an iterator points to the item - in array node that is being splitted. - */ - ///@{ - - /// Returns an iterator to the beginning of the set - iterator begin() - { - return iterator( *this, m_Head, size_t(0) - 1 ); - } - - /// Returns an const iterator to the beginning of the set - const_iterator begin() const - { - return const_iterator( *this, m_Head, size_t(0) - 1 ); - } - - /// Returns an const iterator to the beginning of the set - const_iterator cbegin() - { - return const_iterator( *this, m_Head, size_t(0) - 1 ); - } - - /// 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 iterator( *this, m_Head, head_size(), false ); - } - - /// 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 const_iterator( *this, m_Head, head_size(), false ); - } - - /// 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 const_iterator( *this, m_Head, head_size(), false ); - } - - /// Returns a reverse iterator to the first element of the reversed set - reverse_iterator rbegin() - { - return reverse_iterator( *this, m_Head, head_size() ); - } - - /// Returns a const reverse iterator to the first element of the reversed set - const_reverse_iterator rbegin() const - { - return const_reverse_iterator( *this, m_Head, head_size() ); - } - - /// Returns a const reverse iterator to the first element of the reversed set - const_reverse_iterator crbegin() - { - return const_reverse_iterator( *this, m_Head, head_size() ); - } - - /// 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 reverse_iterator( *this, m_Head, size_t(0) - 1, false ); - } - - /// 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 const_reverse_iterator( *this, m_Head, size_t(0) - 1, false ); - } - - /// 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 const_reverse_iterator( *this, m_Head, size_t(0) - 1, false ); - } - ///@} - - private: - //@cond - - array_node * alloc_head_node() const - { - return alloc_array_node( head_size(), nullptr, 0 ); - } - - array_node * alloc_array_node( array_node * pParent, size_t idxParent ) const - { - return alloc_array_node( array_node_size(), pParent, idxParent ); - } - - static array_node * alloc_array_node( size_t nSize, array_node * pParent, size_t idxParent ) - { - array_node * pNode = cxx_array_node_allocator().NewBlock( sizeof(array_node) + sizeof(atomic_node_ptr) * (nSize - 1), pParent, idxParent ); - new ( pNode->nodes ) atomic_node_ptr[ nSize ]; - return pNode; - } - - static void free_array_node( array_node * parr ) - { - cxx_array_node_allocator().Delete( parr ); - } - - void destroy_tree() - { - // The function is not thread-safe. For use in dtor only - // Remove data node - clear(); - - // Destroy all array nodes - destroy_array_nodes( m_Head, head_size()); - } - - void destroy_array_nodes( array_node * pArr, size_t nSize ) - { - for ( atomic_node_ptr * p = pArr->nodes, *pLast = pArr->nodes + nSize; p != pLast; ++p ) { - node_ptr slot = p->load( memory_model::memory_order_acquire ); - if ( slot.bits() == flag_array_node ) { - destroy_array_nodes(to_array(slot.ptr()), array_node_size()); - free_array_node( to_array(slot.ptr())); - p->store(node_ptr(), memory_model::memory_order_relaxed ); - } - } - } - - void clear_array( array_node * pArrNode, size_t nSize ) - { - back_off bkoff; - - - for ( atomic_node_ptr * pArr = pArrNode->nodes, *pLast = pArr + nSize; pArr != pLast; ++pArr ) { - while ( true ) { - node_ptr slot = pArr->load( memory_model::memory_order_acquire ); - if ( slot.bits() == flag_array_node ) { - // array node, go down the tree - assert( slot.ptr() != nullptr ); - clear_array( to_array( slot.ptr()), array_node_size() ); - break; - } - else if ( slot.bits() == flag_array_converting ) { - // the slot is converting to array node right now - while ( (slot = pArr->load(memory_model::memory_order_acquire)).bits() == flag_array_converting ) { - bkoff(); - m_Stat.onSlotConverting(); - } - bkoff.reset(); - - assert( slot.ptr() != nullptr ); - assert(slot.bits() == flag_array_node ); - clear_array( to_array( slot.ptr()), array_node_size() ); - break; - } - else { - // data node - if ( pArr->compare_exchange_strong( slot, node_ptr(), memory_model::memory_order_acquire, atomics::memory_order_relaxed )) { - if ( slot.ptr() ) { - gc::template retire( slot.ptr() ); - --m_ItemCounter; - m_Stat.onEraseSuccess(); - } - break; - } - } - } - } - } - - union converter { - value_type * pData; - array_node * pArr; - - converter( value_type * p ) - : pData( p ) - {} - - converter( array_node * p ) - : pArr( p ) - {} - }; - - static array_node * to_array( value_type * p ) - { - return converter( p ).pArr; - } - static value_type * to_node( array_node * p ) - { - return converter( p ).pData; - } - - bool expand_slot( array_node * pParent, size_t idxParent, node_ptr current, size_t nOffset ) - { - assert( current.bits() == 0 ); - assert( current.ptr() ); - - size_t idx = hash_splitter(hash_accessor()(*current.ptr()), nOffset).cut( m_Metrics.array_node_size_log ); - array_node * pArr = alloc_array_node( pParent, idxParent ); - - node_ptr cur(current.ptr()); - atomic_node_ptr& slot = pParent->nodes[idxParent]; - if ( !slot.compare_exchange_strong( cur, cur | flag_array_converting, memory_model::memory_order_release, atomics::memory_order_relaxed )) - { - m_Stat.onExpandNodeFailed(); - free_array_node( pArr ); - return false; - } - - pArr->nodes[idx].store( current, memory_model::memory_order_release ); - - cur = cur | flag_array_converting; - CDS_VERIFY( - slot.compare_exchange_strong( cur, node_ptr( to_node( pArr ), flag_array_node ), memory_model::memory_order_release, atomics::memory_order_relaxed ) - ); - - m_Stat.onExpandNodeSuccess(); - m_Stat.onArrayNodeCreated(); - return true; - } - //@endcond - - protected: - //@cond - value_type * search( hash_type const& hash, typename gc::Guard& guard ) - { - hash_splitter splitter( hash ); - hash_comparator cmp; - back_off bkoff; - - array_node * pArr = m_Head; - size_t nSlot = splitter.cut( m_Metrics.head_node_size_log ); - assert( nSlot < m_Metrics.head_node_size ); - - while ( true ) { - node_ptr slot = pArr->nodes[nSlot].load( memory_model::memory_order_acquire ); - if ( slot.bits() == flag_array_node ) { - // array node, go down the tree - assert( slot.ptr() != nullptr ); - nSlot = splitter.cut( m_Metrics.array_node_size_log ); - assert( nSlot < m_Metrics.array_node_size ); - pArr = to_array( slot.ptr() ); - } - else if ( slot.bits() == flag_array_converting ) { - // the slot is converting to array node right now - bkoff(); - m_Stat.onSlotConverting(); - } - else { - // data node - assert(slot.bits() == 0 ); - - // protect data node by hazard pointer - if ( guard.protect( pArr->nodes[nSlot], [](node_ptr p) -> value_type * { return p.ptr(); }) != slot ) { - // slot value has been changed - retry - m_Stat.onSlotChanged(); - } - else if ( slot.ptr() && cmp( hash, hash_accessor()( *slot.ptr() )) == 0 ) { - // item found - m_Stat.onFindSuccess(); - return slot.ptr(); - } - m_Stat.onFindFailed(); - return nullptr; - } - } // while - } - - template - value_type * do_erase( hash_type const& hash, typename gc::Guard& guard, Predicate pred ) - { - hash_splitter splitter( hash ); - hash_comparator cmp; - back_off bkoff; - - array_node * pArr = m_Head; - size_t nSlot = splitter.cut( m_Metrics.head_node_size_log ); - assert( nSlot < m_Metrics.head_node_size ); - - while ( true ) { - node_ptr slot = pArr->nodes[nSlot].load( memory_model::memory_order_acquire ); - if ( slot.bits() == flag_array_node ) { - // array node, go down the tree - assert( slot.ptr() != nullptr ); - nSlot = splitter.cut( m_Metrics.array_node_size_log ); - assert( nSlot < m_Metrics.array_node_size ); - pArr = to_array( slot.ptr() ); - } - else if ( slot.bits() == flag_array_converting ) { - // the slot is converting to array node right now - bkoff(); - m_Stat.onSlotConverting(); - } - else { - // data node - assert(slot.bits() == 0 ); - - // protect data node by hazard pointer - if ( guard.protect( pArr->nodes[nSlot], [](node_ptr p) -> value_type * { return p.ptr(); }) != slot ) { - // slot value has been changed - retry - m_Stat.onSlotChanged(); - } - else if ( slot.ptr() ) { - if ( cmp( hash, hash_accessor()( *slot.ptr() )) == 0 && pred( *slot.ptr() )) { - // item found - replace it with nullptr - if ( pArr->nodes[nSlot].compare_exchange_strong(slot, node_ptr(nullptr), memory_model::memory_order_acquire, atomics::memory_order_relaxed) ) { - // slot is guarded by HP - gc::template retire( slot.ptr() ); - --m_ItemCounter; - m_Stat.onEraseSuccess(); - - return slot.ptr(); - } - m_Stat.onEraseRetry(); - continue; - } - m_Stat.onEraseFailed(); - return nullptr; - } - else { - // the slot is empty - m_Stat.onEraseFailed(); - return nullptr; - } - } - } // while - } - - bool do_erase_at( iterator_base const& iter ) - { - if ( iter.m_set != this ) - return false; - if ( iter.m_pNode == m_Head && iter.m_idx >= head_size()) - return false; - if ( iter.m_idx >= array_node_size() ) - return false; - - for (;;) { - node_ptr slot = iter.m_pNode->nodes[iter.m_idx].load( memory_model::memory_order_acquire ); - if ( slot.bits() == 0 && slot.ptr() == iter.pointer() ) { - if ( iter.m_pNode->nodes[iter.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; - } - } - - template - std::pair do_update( value_type& val, Func f, bool bInsert = true ) - { - hash_type const& hash = hash_accessor()( val ); - hash_splitter splitter( hash ); - hash_comparator cmp; - typename gc::template GuardArray<2> guards; - back_off bkoff; - - array_node * pArr = m_Head; - size_t nSlot = splitter.cut( m_Metrics.head_node_size_log ); - assert( nSlot < m_Metrics.head_node_size ); - size_t nOffset = m_Metrics.head_node_size_log; - size_t nHeight = 1; - - guards.assign( 1, &val ); - - while ( true ) { - node_ptr slot = pArr->nodes[nSlot].load( memory_model::memory_order_acquire ); - if ( slot.bits() == flag_array_node ) { - // array node, go down the tree - assert( slot.ptr() != nullptr ); - nSlot = splitter.cut( m_Metrics.array_node_size_log ); - assert( nSlot < m_Metrics.array_node_size ); - pArr = to_array( slot.ptr() ); - nOffset += m_Metrics.array_node_size_log; - ++nHeight; - } - else if ( slot.bits() == flag_array_converting ) { - // the slot is converting to array node right now - bkoff(); - m_Stat.onSlotConverting(); - } - else { - // data node - assert(slot.bits() == 0 ); - - // protect data node by hazard pointer - if ( guards.protect( 0, pArr->nodes[nSlot], [](node_ptr p) -> value_type * { return p.ptr(); }) != slot ) { - // slot value has been changed - retry - m_Stat.onSlotChanged(); - } - else if ( slot.ptr() ) { - if ( cmp( hash, hash_accessor()( *slot.ptr() )) == 0 ) { - // the item with that hash value already exists - // Replace it with val - if ( slot.ptr() == &val ) { - m_Stat.onUpdateExisting(); - return std::make_pair( true, false ); - } - - if ( pArr->nodes[nSlot].compare_exchange_strong( slot, node_ptr( &val ), memory_model::memory_order_release, atomics::memory_order_relaxed )) { - // slot can be disposed - f( val, slot.ptr() ); - gc::template retire( slot.ptr() ); - m_Stat.onUpdateExisting(); - return std::make_pair( true, false ); - } - - m_Stat.onUpdateRetry(); - continue; - } - - // the slot must be expanded - expand_slot( pArr, nSlot, slot, nOffset ); - } - else { - // the slot is empty, try to insert data node - if ( bInsert ) { - node_ptr pNull; - if ( pArr->nodes[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, nullptr ); - ++m_ItemCounter; - m_Stat.onUpdateNew(); - m_Stat.height( nHeight ); - return std::make_pair( true, true ); - } - } - else { - m_Stat.onUpdateFailed(); - return std::make_pair( false, false ); - } - - // insert failed - slot has been changed by another thread - // retry updating - m_Stat.onUpdateRetry(); - } - } - } // while - } - //@endcond - }; -}} // namespace cds::intrusive - -/* -namespace std { - - template - struct iterator_traits< typename cds::intrusive::MultiLevelHashSet< GC, T, Traits >::iterator > - { - typedef typename cds::intrusive::MultiLevelHashSet< GC, T, Traits >::iterator iterator_class; - - // difference_type is not applicable for that iterator - // typedef ??? difference_type - typedef T value_type; - typedef typename iterator_class::value_ptr pointer; - typedef typename iterator_class::value_ref reference; - typedef bidirectional_iterator_tag iterator_category; - }; - - template - struct iterator_traits< typename cds::intrusive::MultiLevelHashSet< GC, T, Traits >::const_iterator > - { - typedef typename cds::intrusive::MultiLevelHashSet< GC, T, Traits >::const_iterator iterator_class; - - // difference_type is not applicable for that iterator - // typedef ??? difference_type - typedef T value_type; - typedef typename iterator_class::value_ptr pointer; - typedef typename iterator_class::value_ref reference; - typedef bidirectional_iterator_tag iterator_category; - }; - -} // namespace std -*/ - -#endif // #ifndef CDSLIB_INTRUSIVE_IMPL_MULTILEVEL_HASHSET_H diff --git a/cds/intrusive/multilevel_hashset_dhp.h b/cds/intrusive/multilevel_hashset_dhp.h deleted file mode 100644 index e0c95112..00000000 --- a/cds/intrusive/multilevel_hashset_dhp.h +++ /dev/null @@ -1,9 +0,0 @@ -//$$CDS-header$$ - -#ifndef CDSLIB_INTRUSIVE_MULTILEVEL_HASHSET_DHP_H -#define CDSLIB_INTRUSIVE_MULTILEVEL_HASHSET_DHP_H - -#include -#include - -#endif // #ifndef CDSLIB_INTRUSIVE_MULTILEVEL_HASHSET_DHP_H diff --git a/cds/intrusive/multilevel_hashset_hp.h b/cds/intrusive/multilevel_hashset_hp.h deleted file mode 100644 index 97dc8a22..00000000 --- a/cds/intrusive/multilevel_hashset_hp.h +++ /dev/null @@ -1,9 +0,0 @@ -//$$CDS-header$$ - -#ifndef CDSLIB_INTRUSIVE_MULTILEVEL_HASHSET_HP_H -#define CDSLIB_INTRUSIVE_MULTILEVEL_HASHSET_HP_H - -#include -#include - -#endif // #ifndef CDSLIB_INTRUSIVE_MULTILEVEL_HASHSET_HP_H diff --git a/cds/intrusive/multilevel_hashset_rcu.h b/cds/intrusive/multilevel_hashset_rcu.h deleted file mode 100644 index accb6aa6..00000000 --- a/cds/intrusive/multilevel_hashset_rcu.h +++ /dev/null @@ -1,1416 +0,0 @@ -//$$CDS-header$$ - -#ifndef CDSLIB_INTRUSIVE_MULTILEVEL_HASHSET_RCU_H -#define CDSLIB_INTRUSIVE_MULTILEVEL_HASHSET_RCU_H - -#include // std::ref -#include // std::iterator_traits - -#include -#include -#include -#include -#include - - -namespace cds { namespace intrusive { - /// Intrusive hash set based on multi-level array, \ref cds_urcu_desc "RCU" specialization - /** @ingroup cds_intrusive_map - @anchor cds_intrusive_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_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 - - \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_intrusive_MultilevelHashSet_rcu_iterators "bidirectional thread-safe iterators" - with some restrictions. - */ - template < - class RCU, - class T, -#ifdef CDS_DOXYGEN_INVOKED - class Traits = multilevel_hashset::traits -#else - class Traits -#endif - > - class MultiLevelHashSet< cds::urcu::gc< RCU >, T, Traits > - { - 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 - - typedef typename traits::hash_accessor hash_accessor; ///< Hash accessor functor - static_assert(!std::is_same< hash_accessor, cds::opt::none >::value, "hash_accessor functor must be specified in Traits"); - - /// Hash type deduced from \p hash_accessor return type - typedef typename std::decay< - typename std::remove_reference< - decltype(hash_accessor()(std::declval())) - >::type - >::type hash_type; - //typedef typename std::result_of< hash_accessor( std::declval()) >::type hash_type; - static_assert(!std::is_pointer::value, "hash_accessor should return a reference to hash value"); - - typedef typename traits::disposer disposer; ///< data node disposer - -# ifdef CDS_DOXYGEN_INVOKED - typedef implementation_defined hash_comparator; ///< hash compare functor based on opt::compare and opt::less option setter -# else - typedef typename cds::opt::details::make_comparator_from< - hash_type, - traits, - multilevel_hashset::bitwise_compare< hash_type > - >::type hash_comparator; -# endif - - typedef typename traits::item_counter item_counter; ///< Item counter type - 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 - - using exempt_ptr = cds::urcu::exempt_ptr< gc, value_type, value_type, disposer, void >; ///< pointer to extracted node - - /// Node marked poiter - typedef cds::details::marked_ptr< value_type, 3 > node_ptr; - /// Array node element - typedef atomics::atomic< node_ptr > atomic_node_ptr; - - protected: - //@cond - enum node_flags { - flag_array_converting = 1, ///< the cell is converting from data node to an array node - flag_array_node = 2 ///< the cell is a pointer to an array node - }; - - struct array_node { - array_node * const pParent; ///< parent array node - size_t const idxParent; ///< index in parent array node - atomic_node_ptr nodes[1]; ///< node array - - array_node(array_node * parent, size_t idx) - : pParent(parent) - , idxParent(idx) - {} - - array_node() = delete; - array_node(array_node const&) = delete; - array_node(array_node&&) = delete; - }; - - typedef cds::details::Allocator< array_node, node_allocator > cxx_array_node_allocator; - typedef multilevel_hashset::details::hash_splitter< hash_type > hash_splitter; - typedef cds::urcu::details::check_deadlock_policy< gc, rcu_check_deadlock> check_deadlock_policy; - - //@endcond - - private: - //@cond - multilevel_hashset::details::metrics const m_Metrics; ///< Metrics - array_node * m_Head; ///< Head array - item_counter m_ItemCounter; ///< Item counter - stat m_Stat; ///< Internal statistics - //@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) - : m_Metrics(multilevel_hashset::details::metrics::make(head_bits, array_bits, sizeof(hash_type))) - , m_Head(alloc_head_node()) - {} - - /// Destructs the set and frees all data - ~MultiLevelHashSet() - { - destroy_tree(); - free_array_node(m_Head); - } - - /// Inserts new node - /** - The function inserts \p val in the set if it does not contain - an item with that hash. - - Returns \p true if \p val is placed into the set, \p false otherwise. - - The function locks RCU internally. - */ - bool insert( value_type& val ) - { - return insert( val, [](value_type&) {} ); - } - - /// Inserts new node - /** - This function is intended for derived non-intrusive containers. - - 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 \p val. - - The functor signature is: - \code - void func( value_type& val ); - \endcode - where \p val is the item inserted. - - The user-defined functor is called only if the inserting is success. - - The function locks RCU internally. - @warning See \ref cds_intrusive_item_creating "insert item troubleshooting". - */ - template - bool insert( value_type& val, Func f ) - { - hash_type const& hash = hash_accessor()( val ); - hash_splitter splitter( hash ); - hash_comparator cmp; - back_off bkoff; - - size_t nOffset = m_Metrics.head_node_size_log; - array_node * pArr = m_Head; - size_t nSlot = splitter.cut( m_Metrics.head_node_size_log ); - assert( nSlot < m_Metrics.head_node_size ); - size_t nHeight = 1; - - while ( true ) { - node_ptr slot = pArr->nodes[nSlot].load( memory_model::memory_order_acquire ); - if ( slot.bits() == flag_array_node ) { - // array node, go down the tree - assert( slot.ptr() != nullptr ); - nSlot = splitter.cut( m_Metrics.array_node_size_log ); - assert( nSlot < m_Metrics.array_node_size ); - pArr = to_array( slot.ptr() ); - nOffset += m_Metrics.array_node_size_log; - ++nHeight; - } - else if ( slot.bits() == flag_array_converting ) { - // the slot is converting to array node right now - bkoff(); - m_Stat.onSlotConverting(); - } - else { - // data node - assert(slot.bits() == 0 ); - - rcu_lock rcuLock; - if ( pArr->nodes[nSlot].load(memory_model::memory_order_acquire) == slot ) { - if ( slot.ptr() ) { - if ( cmp( hash, hash_accessor()( *slot.ptr() )) == 0 ) { - // the item with that hash value already exists - m_Stat.onInsertFailed(); - return false; - } - - // the slot must be expanded - expand_slot( pArr, nSlot, slot, nOffset ); - } - else { - // the slot is empty, try to insert data node - node_ptr pNull; - if ( pArr->nodes[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 ); - ++m_ItemCounter; - m_Stat.onInsertSuccess(); - m_Stat.height( nHeight ); - return true; - } - - // insert failed - slot has been changed by another thread - // retry inserting - m_Stat.onInsertRetry(); - } - } - else - m_Stat.onSlotChanged(); - } - } // while - } - - /// Updates the node - /** - Performs inserting or updating the item with hash value equal to \p val. - - If hash value is found then existing item is replaced with \p val, old item is disposed - with \p Traits::disposer. Note that the disposer is called by \p GC asynchronously. - The function returns std::pair - - If hash value is not found and \p bInsert is \p true then \p val is inserted, - the function returns std::pair - - If hash value is not found and \p bInsert is \p false then the set is unchanged, - the function returns std::pair - - 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 new item has been added or \p false if the set contains that hash. - - The function locks RCU internally. - */ - std::pair update( value_type& val, bool bInsert = true ) - { - return do_update(val, [](value_type&, value_type *) {}, bInsert ); - } - - /// Unlinks the item \p val from the set - /** - The function searches the item \p val in the set and unlink it - if it is found and its address is equal to &val. - - The function returns \p true if success and \p false otherwise. - - RCU should not be locked. The function locks RCU internally. - */ - bool unlink( value_type const& val ) - { - check_deadlock_policy::check(); - - auto pred = [&val](value_type const& item) -> bool { return &item == &val; }; - value_type * p; - { - rcu_lock rcuLock; - p = do_erase( hash_accessor()( val ), std::ref( pred )); - } - if ( p ) { - gc::template retire_ptr( p ); - return true; - } - return false; - } - - /// Deletes the item from the set - /** - The function searches \p hash in the set, - unlinks the item found, and returns \p true. - If that item is not found the function returns \p false. - - The \ref disposer specified in \p Traits is called by garbage collector \p GC asynchronously. - - RCU should not be locked. The function locks RCU internally. - */ - bool erase( hash_type const& hash ) - { - return erase(hash, [](value_type const&) {} ); - } - - /// Deletes the item from the set - /** - The function searches \p hash in the set, - call \p f functor with item found, and unlinks it from the set. - The \ref disposer specified in \p Traits is called - by garbage collector \p GC asynchronously. - - 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. - - RCU should not be locked. The function locks RCU internally. - */ - template - bool erase( hash_type const& hash, Func f ) - { - check_deadlock_policy::check(); - - value_type * p; - - { - rcu_lock rcuLock; - p = do_erase( hash, []( value_type const&) -> bool { return true; } ); - } - - // p is guarded by HP - if ( p ) { - f( *p ); - gc::template retire_ptr(p); - return true; - } - return false; - } - - /// 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::intrusive::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 ) - { - check_deadlock_policy::check(); - - value_type * p; - { - rcu_lock rcuLock; - p = do_erase( hash, []( value_type const&) -> bool {return true;} ); - } - return exempt_ptr( p ); - } - - /// 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. - - The function applies RCU lock internally. - */ - template - bool find( hash_type const& hash, Func f ) - { - rcu_lock rcuLock; - - value_type * p = search( hash ); - if ( p ) { - f( *p ); - return true; - } - return false; - } - - /// 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. - - The function applies RCU lock internally. - */ - bool contains( hash_type const& hash ) - { - return find( hash, [](value_type&) {} ); - } - - /// 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::intrusive::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 ) - { - assert( gc::is_locked()); - return search( 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. - - For each item the \p disposer is called after unlinking. - */ - void clear() - { - clear_array( m_Head, head_size() ); - } - - /// 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 size() == 0; - } - - /// Returns item count in the set - size_t size() const - { - return m_ItemCounter; - } - - /// Returns const reference to internal statistics - stat const& statistics() const - { - return m_Stat; - } - - /// Returns the size of head node - size_t head_size() const - { - return m_Metrics.head_node_size; - } - - /// Returns the size of the array node - size_t array_node_size() const - { - return m_Metrics.array_node_size; - } - - protected: - //@cond - class iterator_base - { - friend class MultiLevelHashSet; - - protected: - array_node * m_pNode; ///< current array node - size_t m_idx; ///< current position in m_pNode - value_type * m_pValue; ///< current value - MultiLevelHashSet const* m_set; ///< Hash set - - public: - iterator_base() CDS_NOEXCEPT - : m_pNode(nullptr) - , m_idx(0) - , m_pValue(nullptr) - , m_set(nullptr) - {} - - iterator_base(iterator_base const& rhs) CDS_NOEXCEPT - : m_pNode(rhs.m_pNode) - , m_idx(rhs.m_idx) - , m_pValue(rhs.m_pValue) - , m_set(rhs.m_set) - {} - - iterator_base& operator=(iterator_base const& rhs) CDS_NOEXCEPT - { - m_pNode = rhs.m_pNode; - m_idx = rhs.m_idx; - m_pValue = rhs.m_pValue; - m_set = rhs.m_set; - return *this; - } - - iterator_base& operator++() - { - forward(); - return *this; - } - - iterator_base& operator--() - { - backward(); - return *this; - } - - bool operator ==(iterator_base const& rhs) const CDS_NOEXCEPT - { - return m_pNode == rhs.m_pNode && m_idx == rhs.m_idx && m_set == rhs.m_set; - } - - bool operator !=(iterator_base const& rhs) const CDS_NOEXCEPT - { - return !(*this == rhs); - } - - protected: - iterator_base(MultiLevelHashSet const& set, array_node * pNode, size_t idx, bool) - : m_pNode(pNode) - , m_idx(idx) - , m_pValue(nullptr) - , m_set(&set) - {} - - iterator_base(MultiLevelHashSet const& set, array_node * pNode, size_t idx) - : m_pNode(pNode) - , m_idx(idx) - , m_pValue(nullptr) - , m_set(&set) - { - forward(); - } - - value_type * pointer() const CDS_NOEXCEPT - { - assert(gc::is_locked()); - return m_pValue; - } - - void forward() - { - assert( gc::is_locked()); - assert(m_set != nullptr); - assert(m_pNode != nullptr); - - size_t const arrayNodeSize = m_set->array_node_size(); - size_t const headSize = m_set->head_size(); - array_node * pNode = m_pNode; - size_t idx = m_idx + 1; - size_t nodeSize = m_pNode->pParent ? arrayNodeSize : headSize; - - for (;;) { - if (idx < nodeSize) { - node_ptr slot = pNode->nodes[idx].load(memory_model::memory_order_acquire); - if (slot.bits() == flag_array_node) { - // array node, go down the tree - assert(slot.ptr() != nullptr); - pNode = to_array(slot.ptr()); - idx = 0; - nodeSize = arrayNodeSize; - } - else if (slot.bits() == flag_array_converting) { - // the slot is converting to array node right now - skip the node - ++idx; - } - else { - if (slot.ptr()) { - // data node - m_pNode = pNode; - m_idx = idx; - m_pValue = slot.ptr(); - return; - } - ++idx; - } - } - else { - // up to parent node - if (pNode->pParent) { - idx = pNode->idxParent + 1; - pNode = pNode->pParent; - nodeSize = pNode->pParent ? arrayNodeSize : headSize; - } - else { - // end() - assert(pNode == m_set->m_Head); - assert(idx == headSize); - m_pNode = pNode; - m_idx = idx; - m_pValue = nullptr; - return; - } - } - } - } - - void backward() - { - assert(gc::is_locked()); - assert(m_set != nullptr); - assert(m_pNode != nullptr); - - size_t const arrayNodeSize = m_set->array_node_size(); - size_t const headSize = m_set->head_size(); - size_t const endIdx = size_t(0) - 1; - - array_node * pNode = m_pNode; - size_t idx = m_idx - 1; - size_t nodeSize = m_pNode->pParent ? arrayNodeSize : headSize; - - for (;;) { - if (idx != endIdx) { - node_ptr slot = pNode->nodes[idx].load(memory_model::memory_order_acquire); - if (slot.bits() == flag_array_node) { - // array node, go down the tree - assert(slot.ptr() != nullptr); - pNode = to_array(slot.ptr()); - nodeSize = arrayNodeSize; - idx = nodeSize - 1; - } - else if (slot.bits() == flag_array_converting) { - // the slot is converting to array node right now - skip the node - --idx; - } - else { - if (slot.ptr()) { - // data node - m_pNode = pNode; - m_idx = idx; - m_pValue = slot.ptr(); - return; - } - --idx; - } - } - else { - // up to parent node - if (pNode->pParent) { - idx = pNode->idxParent - 1; - pNode = pNode->pParent; - nodeSize = pNode->pParent ? arrayNodeSize : headSize; - } - else { - // rend() - assert(pNode == m_set->m_Head); - assert(idx == endIdx); - m_pNode = pNode; - m_idx = idx; - m_pValue = nullptr; - return; - } - } - } - } - }; - - template - Iterator init_begin() const - { - return Iterator(*this, m_Head, size_t(0) - 1); - } - - template - Iterator init_end() const - { - return Iterator(*this, m_Head, head_size(), false); - } - - template - Iterator init_rbegin() const - { - return Iterator(*this, m_Head, head_size()); - } - - template - Iterator init_rend() const - { - return Iterator(*this, m_Head, size_t(0) - 1, false); - } - - /// Bidirectional iterator class - template - class bidirectional_iterator : protected iterator_base - { - friend class MultiLevelHashSet; - - protected: - static CDS_CONSTEXPR bool const c_bConstantIterator = IsConst; - - public: - typedef typename std::conditional< IsConst, value_type const*, value_type*>::type value_ptr; ///< Value pointer - typedef typename std::conditional< IsConst, value_type const&, value_type&>::type value_ref; ///< Value reference - - public: - bidirectional_iterator() CDS_NOEXCEPT - {} - - bidirectional_iterator(bidirectional_iterator const& rhs) CDS_NOEXCEPT - : iterator_base(rhs) - {} - - bidirectional_iterator& operator=(bidirectional_iterator const& rhs) CDS_NOEXCEPT - { - iterator_base::operator=(rhs); - return *this; - } - - bidirectional_iterator& operator++() - { - iterator_base::operator++(); - return *this; - } - - bidirectional_iterator& operator--() - { - iterator_base::operator--(); - return *this; - } - - value_ptr operator ->() const CDS_NOEXCEPT - { - return iterator_base::pointer(); - } - - value_ref operator *() const CDS_NOEXCEPT - { - value_ptr p = iterator_base::pointer(); - assert(p); - return *p; - } - - template - bool operator ==(bidirectional_iterator const& rhs) const CDS_NOEXCEPT - { - return iterator_base::operator==(rhs); - } - - template - bool operator !=(bidirectional_iterator const& rhs) const CDS_NOEXCEPT - { - return !(*this == rhs); - } - - protected: - bidirectional_iterator(MultiLevelHashSet& set, array_node * pNode, size_t idx, bool) - : iterator_base(set, pNode, idx, false) - {} - - bidirectional_iterator(MultiLevelHashSet& set, array_node * pNode, size_t idx) - : iterator_base(set, pNode, idx) - {} - }; - - /// Reverse bidirectional iterator - template - class reverse_bidirectional_iterator : public iterator_base - { - friend class MultiLevelHashSet; - - public: - typedef typename std::conditional< IsConst, value_type const*, value_type*>::type value_ptr; ///< Value pointer - typedef typename std::conditional< IsConst, value_type const&, value_type&>::type value_ref; ///< Value reference - - public: - reverse_bidirectional_iterator() CDS_NOEXCEPT - : iterator_base() - {} - - reverse_bidirectional_iterator(reverse_bidirectional_iterator const& rhs) CDS_NOEXCEPT - : iterator_base(rhs) - {} - - reverse_bidirectional_iterator& operator=(reverse_bidirectional_iterator const& rhs) CDS_NOEXCEPT - { - iterator_base::operator=(rhs); - return *this; - } - - reverse_bidirectional_iterator& operator++() - { - iterator_base::operator--(); - return *this; - } - - reverse_bidirectional_iterator& operator--() - { - iterator_base::operator++(); - return *this; - } - - value_ptr operator ->() const CDS_NOEXCEPT - { - return iterator_base::pointer(); - } - - value_ref operator *() const CDS_NOEXCEPT - { - value_ptr p = iterator_base::pointer(); - assert(p); - return *p; - } - - template - bool operator ==(reverse_bidirectional_iterator const& rhs) const - { - return iterator_base::operator==(rhs); - } - - template - bool operator !=(reverse_bidirectional_iterator const& rhs) - { - return !(*this == rhs); - } - - private: - reverse_bidirectional_iterator(MultiLevelHashSet& set, array_node * pNode, size_t idx, bool) - : iterator_base(set, pNode, idx, false) - {} - - reverse_bidirectional_iterator(MultiLevelHashSet& set, array_node * pNode, size_t idx) - : iterator_base(set, pNode, idx, false) - { - iterator_base::backward(); - } - }; - //@endcond - - public: -#ifdef CDS_DOXYGEN_INVOKED - typedef implementation_defined iterator; ///< @ref cds_intrusive_MultilevelHashSet_rcu_iterators "bidirectional iterator" type - typedef implementation_defined const_iterator; ///< @ref cds_intrusive_MultilevelHashSet_rcu_iterators "bidirectional const iterator" type - typedef implementation_defined reverse_iterator; ///< @ref cds_intrusive_MultilevelHashSet_rcu_iterators "bidirectional reverse iterator" type - typedef implementation_defined const_reverse_iterator; ///< @ref cds_intrusive_MultilevelHashSet_rcu_iterators "bidirectional reverse const iterator" type -#else - typedef bidirectional_iterator iterator; - typedef bidirectional_iterator const_iterator; - typedef reverse_bidirectional_iterator reverse_iterator; - typedef reverse_bidirectional_iterator const_reverse_iterator; -#endif - - ///@name Thread-safe iterators - /** @anchor cds_intrusive_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::intrusive::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::intrusive::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 iterator(*this, m_Head, size_t(0) - 1); - } - - /// Returns an const iterator to the beginning of the set - const_iterator begin() const - { - return const_iterator(*this, m_Head, size_t(0) - 1); - } - - /// Returns an const iterator to the beginning of the set - const_iterator cbegin() - { - return const_iterator(*this, m_Head, size_t(0) - 1); - } - - /// 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 iterator(*this, m_Head, head_size(), false); - } - - /// 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 const_iterator(*this, m_Head, head_size(), false); - } - - /// 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 const_iterator(*this, m_Head, head_size(), false); - } - - /// Returns a reverse iterator to the first element of the reversed set - reverse_iterator rbegin() - { - return reverse_iterator(*this, m_Head, head_size()); - } - - /// Returns a const reverse iterator to the first element of the reversed set - const_reverse_iterator rbegin() const - { - return const_reverse_iterator(*this, m_Head, head_size()); - } - - /// Returns a const reverse iterator to the first element of the reversed set - const_reverse_iterator crbegin() - { - return const_reverse_iterator(*this, m_Head, head_size()); - } - - /// 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 reverse_iterator(*this, m_Head, size_t(0) - 1, false); - } - - /// 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 const_reverse_iterator(*this, m_Head, size_t(0) - 1, false); - } - - /// 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 const_reverse_iterator(*this, m_Head, size_t(0) - 1, false); - } - ///@} - - protected: - //@cond - template - std::pair do_update(value_type& val, Func f, bool bInsert = true) - { - hash_type const& hash = hash_accessor()(val); - hash_splitter splitter(hash); - hash_comparator cmp; - back_off bkoff; - - array_node * pArr = m_Head; - size_t nSlot = splitter.cut(m_Metrics.head_node_size_log); - assert(nSlot < m_Metrics.head_node_size); - size_t nOffset = m_Metrics.head_node_size_log; - size_t nHeight = 1; - - while (true) { - node_ptr slot = pArr->nodes[nSlot].load(memory_model::memory_order_acquire); - if (slot.bits() == flag_array_node) { - // array node, go down the tree - assert(slot.ptr() != nullptr); - nSlot = splitter.cut(m_Metrics.array_node_size_log); - assert(nSlot < m_Metrics.array_node_size); - pArr = to_array(slot.ptr()); - nOffset += m_Metrics.array_node_size_log; - ++nHeight; - } - else if (slot.bits() == flag_array_converting) { - // the slot is converting to array node right now - bkoff(); - m_Stat.onSlotConverting(); - } - else { - // data node - assert(slot.bits() == 0); - - value_type * pOld = nullptr; - { - rcu_lock rcuLock; - - if ( pArr->nodes[nSlot].load(memory_model::memory_order_acquire) == slot ) { - if ( slot.ptr()) { - if (cmp(hash, hash_accessor()(*slot.ptr())) == 0) { - // the item with that hash value already exists - // Replace it with val - if (slot.ptr() == &val) { - m_Stat.onUpdateExisting(); - return std::make_pair(true, false); - } - - if (pArr->nodes[nSlot].compare_exchange_strong(slot, node_ptr(&val), memory_model::memory_order_release, atomics::memory_order_relaxed)) { - // slot can be disposed - f(val, slot.ptr()); - pOld = slot.ptr(); - m_Stat.onUpdateExisting(); - goto update_existing_done; - } - - m_Stat.onUpdateRetry(); - continue; - } - - // the slot must be expanded - expand_slot(pArr, nSlot, slot, nOffset); - } - else { - // the slot is empty, try to insert data node - if (bInsert) { - node_ptr pNull; - if (pArr->nodes[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, nullptr); - ++m_ItemCounter; - m_Stat.onUpdateNew(); - m_Stat.height(nHeight); - return std::make_pair(true, true); - } - } - else { - m_Stat.onUpdateFailed(); - return std::make_pair(false, false); - } - - // insert failed - slot has been changed by another thread - // retry updating - m_Stat.onUpdateRetry(); - } - } - else - m_Stat.onSlotChanged(); - continue; - } // rcu_lock - - // update success - update_existing_done: - if ( pOld ) - gc::template retire_ptr( pOld ); - return std::make_pair(true, false); - } - } // while - } - - template - value_type * do_erase( hash_type const& hash, Predicate pred) - { - assert(gc::is_locked()); - - hash_splitter splitter(hash); - hash_comparator cmp; - back_off bkoff; - - array_node * pArr = m_Head; - size_t nSlot = splitter.cut(m_Metrics.head_node_size_log); - assert(nSlot < m_Metrics.head_node_size); - - while (true) { - node_ptr slot = pArr->nodes[nSlot].load(memory_model::memory_order_acquire); - if (slot.bits() == flag_array_node) { - // array node, go down the tree - assert(slot.ptr() != nullptr); - nSlot = splitter.cut(m_Metrics.array_node_size_log); - assert(nSlot < m_Metrics.array_node_size); - pArr = to_array(slot.ptr()); - } - else if (slot.bits() == flag_array_converting) { - // the slot is converting to array node right now - bkoff(); - m_Stat.onSlotConverting(); - } - else { - // data node - assert(slot.bits() == 0); - - if ( pArr->nodes[nSlot].load(memory_model::memory_order_acquire) == slot ) { - if (slot.ptr()) { - if (cmp(hash, hash_accessor()(*slot.ptr())) == 0 && pred(*slot.ptr())) { - // item found - replace it with nullptr - if (pArr->nodes[nSlot].compare_exchange_strong(slot, node_ptr(nullptr), memory_model::memory_order_acquire, atomics::memory_order_relaxed)) { - --m_ItemCounter; - m_Stat.onEraseSuccess(); - - return slot.ptr(); - } - m_Stat.onEraseRetry(); - continue; - } - m_Stat.onEraseFailed(); - return nullptr; - } - else { - // the slot is empty - m_Stat.onEraseFailed(); - return nullptr; - } - } - else - m_Stat.onSlotChanged(); - } - } // while - } - - value_type * search(hash_type const& hash ) - { - assert( gc::is_locked() ); - - hash_splitter splitter(hash); - hash_comparator cmp; - back_off bkoff; - - array_node * pArr = m_Head; - size_t nSlot = splitter.cut(m_Metrics.head_node_size_log); - assert(nSlot < m_Metrics.head_node_size); - - while (true) { - node_ptr slot = pArr->nodes[nSlot].load(memory_model::memory_order_acquire); - if (slot.bits() == flag_array_node) { - // array node, go down the tree - assert(slot.ptr() != nullptr); - nSlot = splitter.cut(m_Metrics.array_node_size_log); - assert(nSlot < m_Metrics.array_node_size); - pArr = to_array(slot.ptr()); - } - else if (slot.bits() == flag_array_converting) { - // the slot is converting to array node right now - bkoff(); - m_Stat.onSlotConverting(); - } - else { - // data node - assert(slot.bits() == 0); - - // protect data node by hazard pointer - if ( pArr->nodes[nSlot].load(memory_model::memory_order_acquire) != slot) { - // slot value has been changed - retry - m_Stat.onSlotChanged(); - } - else if (slot.ptr() && cmp(hash, hash_accessor()(*slot.ptr())) == 0) { - // item found - m_Stat.onFindSuccess(); - return slot.ptr(); - } - m_Stat.onFindFailed(); - return nullptr; - } - } // while - } - - //@endcond - - private: - //@cond - array_node * alloc_head_node() const - { - return alloc_array_node(head_size(), nullptr, 0); - } - - array_node * alloc_array_node(array_node * pParent, size_t idxParent) const - { - return alloc_array_node(array_node_size(), pParent, idxParent); - } - - static array_node * alloc_array_node(size_t nSize, array_node * pParent, size_t idxParent) - { - array_node * pNode = cxx_array_node_allocator().NewBlock(sizeof(array_node) + sizeof(atomic_node_ptr) * (nSize - 1), pParent, idxParent); - new (pNode->nodes) atomic_node_ptr[nSize]; - return pNode; - } - - static void free_array_node(array_node * parr) - { - cxx_array_node_allocator().Delete(parr); - } - - void destroy_tree() - { - // The function is not thread-safe. For use in dtor only - // Remove data node - clear(); - - // Destroy all array nodes - destroy_array_nodes(m_Head, head_size()); - } - - void destroy_array_nodes(array_node * pArr, size_t nSize) - { - for (atomic_node_ptr * p = pArr->nodes, *pLast = pArr->nodes + nSize; p != pLast; ++p) { - node_ptr slot = p->load(memory_model::memory_order_acquire); - if (slot.bits() == flag_array_node) { - destroy_array_nodes(to_array(slot.ptr()), array_node_size()); - free_array_node(to_array(slot.ptr())); - p->store(node_ptr(), memory_model::memory_order_relaxed); - } - } - } - - void clear_array(array_node * pArrNode, size_t nSize) - { - back_off bkoff; - - - for (atomic_node_ptr * pArr = pArrNode->nodes, *pLast = pArr + nSize; pArr != pLast; ++pArr) { - while (true) { - node_ptr slot = pArr->load(memory_model::memory_order_acquire); - if (slot.bits() == flag_array_node) { - // array node, go down the tree - assert(slot.ptr() != nullptr); - clear_array(to_array(slot.ptr()), array_node_size()); - break; - } - else if (slot.bits() == flag_array_converting) { - // the slot is converting to array node right now - while ((slot = pArr->load(memory_model::memory_order_acquire)).bits() == flag_array_converting) { - bkoff(); - m_Stat.onSlotConverting(); - } - bkoff.reset(); - - assert(slot.ptr() != nullptr); - assert(slot.bits() == flag_array_node); - clear_array(to_array(slot.ptr()), array_node_size()); - break; - } - else { - // data node - if (pArr->compare_exchange_strong(slot, node_ptr(), memory_model::memory_order_acquire, atomics::memory_order_relaxed)) { - if (slot.ptr()) { - gc::template retire_ptr(slot.ptr()); - --m_ItemCounter; - m_Stat.onEraseSuccess(); - } - break; - } - } - } - } - } - - bool expand_slot(array_node * pParent, size_t idxParent, node_ptr current, size_t nOffset) - { - assert(current.bits() == 0); - assert(current.ptr()); - - size_t idx = hash_splitter(hash_accessor()(*current.ptr()), nOffset).cut(m_Metrics.array_node_size_log); - array_node * pArr = alloc_array_node(pParent, idxParent); - - node_ptr cur(current.ptr()); - atomic_node_ptr& slot = pParent->nodes[idxParent]; - if (!slot.compare_exchange_strong(cur, cur | flag_array_converting, memory_model::memory_order_release, atomics::memory_order_relaxed)) - { - m_Stat.onExpandNodeFailed(); - free_array_node(pArr); - return false; - } - - pArr->nodes[idx].store(current, memory_model::memory_order_release); - - cur = cur | flag_array_converting; - CDS_VERIFY( - slot.compare_exchange_strong(cur, node_ptr(to_node(pArr), flag_array_node), memory_model::memory_order_release, atomics::memory_order_relaxed) - ); - - m_Stat.onExpandNodeSuccess(); - m_Stat.onArrayNodeCreated(); - return true; - } - - union converter { - value_type * pData; - array_node * pArr; - - converter(value_type * p) - : pData(p) - {} - - converter(array_node * p) - : pArr(p) - {} - }; - - static array_node * to_array(value_type * p) - { - return converter(p).pArr; - } - static value_type * to_node(array_node * p) - { - return converter(p).pData; - } - //@endcond - }; - -}} // namespace cds::intrusive - -#endif // #ifndef CDSLIB_INTRUSIVE_MULTILEVEL_HASHSET_RCU_H diff --git a/projects/Win/vc12/cds.sln b/projects/Win/vc12/cds.sln index 9e737608..ea2f9466 100644 --- a/projects/Win/vc12/cds.sln +++ b/projects/Win/vc12/cds.sln @@ -10,7 +10,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "multi-threaded test", "mult ..\..\..\tests\unit\print_cuckoo_stat.h = ..\..\..\tests\unit\print_cuckoo_stat.h ..\..\..\tests\unit\print_ellenbintree_stat.h = ..\..\..\tests\unit\print_ellenbintree_stat.h ..\..\..\tests\unit\print_mspriorityqueue_stat.h = ..\..\..\tests\unit\print_mspriorityqueue_stat.h - ..\..\..\tests\unit\print_multilevel_hashset_stat.h = ..\..\..\tests\unit\print_multilevel_hashset_stat.h + ..\..\..\tests\unit\print_feldman_hashset_stat.h = ..\..\..\tests\unit\print_feldman_hashset_stat.h ..\..\..\tests\unit\print_segmentedqueue_stat.h = ..\..\..\tests\unit\print_segmentedqueue_stat.h ..\..\..\tests\unit\print_skip_list_stat.h = ..\..\..\tests\unit\print_skip_list_stat.h ..\..\..\tests\unit\print_split_list_stat.h = ..\..\..\tests\unit\print_split_list_stat.h @@ -80,7 +80,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "map", "map", "{6BB7A27F-FC5 ..\..\..\tests\unit\map2\map_type_lazy_list.h = ..\..\..\tests\unit\map2\map_type_lazy_list.h ..\..\..\tests\unit\map2\map_type_michael.h = ..\..\..\tests\unit\map2\map_type_michael.h ..\..\..\tests\unit\map2\map_type_michael_list.h = ..\..\..\tests\unit\map2\map_type_michael_list.h - ..\..\..\tests\unit\map2\map_type_multilevel_hashmap.h = ..\..\..\tests\unit\map2\map_type_multilevel_hashmap.h + ..\..\..\tests\unit\map2\map_type_feldman_hashmap.h = ..\..\..\tests\unit\map2\map_type_feldman_hashmap.h ..\..\..\tests\unit\map2\map_type_skip_list.h = ..\..\..\tests\unit\map2\map_type_skip_list.h ..\..\..\tests\unit\map2\map_type_split_list.h = ..\..\..\tests\unit\map2\map_type_split_list.h ..\..\..\tests\unit\map2\map_type_std.h = ..\..\..\tests\unit\map2\map_type_std.h @@ -98,7 +98,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "set", "set", "{A64449B7-90F ..\..\..\tests\unit\set2\set_type_lazy_list.h = ..\..\..\tests\unit\set2\set_type_lazy_list.h ..\..\..\tests\unit\set2\set_type_michael.h = ..\..\..\tests\unit\set2\set_type_michael.h ..\..\..\tests\unit\set2\set_type_michael_list.h = ..\..\..\tests\unit\set2\set_type_michael_list.h - ..\..\..\tests\unit\set2\set_type_multilevel_hashset.h = ..\..\..\tests\unit\set2\set_type_multilevel_hashset.h + ..\..\..\tests\unit\set2\set_type_feldman_hashset.h = ..\..\..\tests\unit\set2\set_type_feldman_hashset.h ..\..\..\tests\unit\set2\set_type_skip_list.h = ..\..\..\tests\unit\set2\set_type_skip_list.h ..\..\..\tests\unit\set2\set_type_split_list.h = ..\..\..\tests\unit\set2\set_type_split_list.h ..\..\..\tests\unit\set2\set_type_std.h = ..\..\..\tests\unit\set2\set_type_std.h diff --git a/projects/Win/vc12/cds.vcxproj b/projects/Win/vc12/cds.vcxproj index 0ec0c295..f9a9bcdf 100644 --- a/projects/Win/vc12/cds.vcxproj +++ b/projects/Win/vc12/cds.vcxproj @@ -670,8 +670,8 @@ - - + + @@ -687,8 +687,8 @@ - - + + @@ -702,12 +702,12 @@ - - - - - - + + + + + + @@ -761,7 +761,7 @@ - + @@ -773,7 +773,7 @@ - + @@ -781,9 +781,9 @@ - - - + + + diff --git a/projects/Win/vc12/cds.vcxproj.filters b/projects/Win/vc12/cds.vcxproj.filters index 7ecba805..f1b37296 100644 --- a/projects/Win/vc12/cds.vcxproj.filters +++ b/projects/Win/vc12/cds.vcxproj.filters @@ -1178,52 +1178,52 @@ Header Files\cds\intrusive\details - + Header Files\cds\intrusive\impl - + Header Files\cds\intrusive\details - + Header Files\cds\intrusive - + Header Files\cds\intrusive Header Files\cds\algo - + Header Files\cds\container\details - + Header Files\cds\container\impl - + Header Files\cds\container - + Header Files\cds\container - + Header Files\cds\container\details - + Header Files\cds\container\impl - + Header Files\cds\container - + Header Files\cds\container - + Header Files\cds\intrusive - + Header Files\cds\container - + Header Files\cds\container diff --git a/projects/Win/vc12/hdr-test-map.vcxproj b/projects/Win/vc12/hdr-test-map.vcxproj index 674216bc..b8dfdf53 100644 --- a/projects/Win/vc12/hdr-test-map.vcxproj +++ b/projects/Win/vc12/hdr-test-map.vcxproj @@ -546,7 +546,7 @@ - + @@ -567,13 +567,13 @@ - - - - - - - + + + + + + + diff --git a/projects/Win/vc12/hdr-test-map.vcxproj.filters b/projects/Win/vc12/hdr-test-map.vcxproj.filters index a8e47dce..2fe1b481 100644 --- a/projects/Win/vc12/hdr-test-map.vcxproj.filters +++ b/projects/Win/vc12/hdr-test-map.vcxproj.filters @@ -175,25 +175,25 @@ skip_list - + multilvel_hashmap - + multilvel_hashmap - + multilvel_hashmap - + multilvel_hashmap - + multilvel_hashmap - + multilvel_hashmap - + multilvel_hashmap @@ -212,7 +212,7 @@ cuckoo - + multilvel_hashmap diff --git a/projects/Win/vc12/hdr-test-set.vcxproj b/projects/Win/vc12/hdr-test-set.vcxproj index 098bcba1..bc73c2c5 100644 --- a/projects/Win/vc12/hdr-test-set.vcxproj +++ b/projects/Win/vc12/hdr-test-set.vcxproj @@ -541,11 +541,11 @@ - + - + @@ -567,13 +567,13 @@ - - - - - - - + + + + + + + @@ -622,13 +622,13 @@ - - - - - - - + + + + + + + diff --git a/projects/Win/vc12/hdr-test-set.vcxproj.filters b/projects/Win/vc12/hdr-test-set.vcxproj.filters index 0f5788e0..c44ec9d3 100644 --- a/projects/Win/vc12/hdr-test-set.vcxproj.filters +++ b/projects/Win/vc12/hdr-test-set.vcxproj.filters @@ -19,11 +19,11 @@ container\skip_list - - intrusive\multilevel_hashset + + intrusive\feldman_hashset - - container\multilevel_hashset + + container\feldman_hashset @@ -51,10 +51,10 @@ {61f94a40-c964-4233-af67-66a1be1e0aab} - + {a878aed0-83c9-4ca7-95bb-74f10aad8bde} - + {5268f225-1474-413e-a1cb-5f00b8df5e1e} @@ -323,47 +323,47 @@ container\skip_list - - intrusive\multilevel_hashset + + intrusive\feldman_hashset - - intrusive\multilevel_hashset + + intrusive\feldman_hashset - - container\multilevel_hashset + + container\feldman_hashset - - container\multilevel_hashset + + container\feldman_hashset - - intrusive\multilevel_hashset + + intrusive\feldman_hashset - - intrusive\multilevel_hashset + + intrusive\feldman_hashset - - intrusive\multilevel_hashset + + intrusive\feldman_hashset - - intrusive\multilevel_hashset + + intrusive\feldman_hashset - - intrusive\multilevel_hashset + + intrusive\feldman_hashset - - container\multilevel_hashset + + container\feldman_hashset - - container\multilevel_hashset + + container\feldman_hashset - - container\multilevel_hashset + + container\feldman_hashset - - container\multilevel_hashset + + container\feldman_hashset - - container\multilevel_hashset + + container\feldman_hashset \ No newline at end of file diff --git a/projects/Win/vc12/unit-map-delodd.vcxproj b/projects/Win/vc12/unit-map-delodd.vcxproj index abce74e3..ae311eee 100644 --- a/projects/Win/vc12/unit-map-delodd.vcxproj +++ b/projects/Win/vc12/unit-map-delodd.vcxproj @@ -56,7 +56,7 @@ false - + false diff --git a/projects/Win/vc12/unit-map-find.vcxproj b/projects/Win/vc12/unit-map-find.vcxproj index e8db6c1d..b70d27f0 100644 --- a/projects/Win/vc12/unit-map-find.vcxproj +++ b/projects/Win/vc12/unit-map-find.vcxproj @@ -48,7 +48,7 @@ - + @@ -58,7 +58,7 @@ - + @@ -68,7 +68,7 @@ - + diff --git a/projects/Win/vc12/unit-map-find.vcxproj.filters b/projects/Win/vc12/unit-map-find.vcxproj.filters index 3a6880b2..bb9c849a 100644 --- a/projects/Win/vc12/unit-map-find.vcxproj.filters +++ b/projects/Win/vc12/unit-map-find.vcxproj.filters @@ -82,13 +82,13 @@ map_insfind_int - + map_find_int - + map_find_string - + map_insfind_int diff --git a/projects/Win/vc12/unit-map-insdel-item.vcxproj b/projects/Win/vc12/unit-map-insdel-item.vcxproj index cdcd25db..764bca0a 100644 --- a/projects/Win/vc12/unit-map-insdel-item.vcxproj +++ b/projects/Win/vc12/unit-map-insdel-item.vcxproj @@ -48,7 +48,7 @@ - + @@ -57,7 +57,7 @@ - + diff --git a/projects/Win/vc12/unit-map-insdel-item.vcxproj.filters b/projects/Win/vc12/unit-map-insdel-item.vcxproj.filters index 5aa2b21b..8c0b268a 100644 --- a/projects/Win/vc12/unit-map-insdel-item.vcxproj.filters +++ b/projects/Win/vc12/unit-map-insdel-item.vcxproj.filters @@ -57,10 +57,10 @@ map_insdel_item_string - + map_insdel_item_int - + map_insdel_item_string diff --git a/projects/Win/vc12/unit-map-insdel.vcxproj b/projects/Win/vc12/unit-map-insdel.vcxproj index 11d74752..d3f17705 100644 --- a/projects/Win/vc12/unit-map-insdel.vcxproj +++ b/projects/Win/vc12/unit-map-insdel.vcxproj @@ -48,7 +48,7 @@ - + @@ -57,7 +57,7 @@ - + @@ -67,7 +67,7 @@ - + diff --git a/projects/Win/vc12/unit-map-insdel.vcxproj.filters b/projects/Win/vc12/unit-map-insdel.vcxproj.filters index 0818ac7a..ef09d099 100644 --- a/projects/Win/vc12/unit-map-insdel.vcxproj.filters +++ b/projects/Win/vc12/unit-map-insdel.vcxproj.filters @@ -76,16 +76,16 @@ map_insdel_string - + map_insdel_int map_insdel_int - + map_insdel_func - + map_insdel_string diff --git a/projects/Win/vc12/unit-map-insdelfind.vcxproj b/projects/Win/vc12/unit-map-insdelfind.vcxproj index 37503239..aa969fd1 100644 --- a/projects/Win/vc12/unit-map-insdelfind.vcxproj +++ b/projects/Win/vc12/unit-map-insdelfind.vcxproj @@ -48,7 +48,7 @@ - + diff --git a/projects/Win/vc12/unit-set-delodd.vcxproj b/projects/Win/vc12/unit-set-delodd.vcxproj index 50f87cdd..f412302e 100644 --- a/projects/Win/vc12/unit-set-delodd.vcxproj +++ b/projects/Win/vc12/unit-set-delodd.vcxproj @@ -47,7 +47,7 @@ - + diff --git a/projects/Win/vc12/unit-set-insdel.vcxproj b/projects/Win/vc12/unit-set-insdel.vcxproj index 8e0830af..b40874b9 100644 --- a/projects/Win/vc12/unit-set-insdel.vcxproj +++ b/projects/Win/vc12/unit-set-insdel.vcxproj @@ -47,7 +47,7 @@ - + @@ -55,7 +55,7 @@ - + diff --git a/projects/Win/vc12/unit-set-insdel.vcxproj.filters b/projects/Win/vc12/unit-set-insdel.vcxproj.filters index 74851368..643f5857 100644 --- a/projects/Win/vc12/unit-set-insdel.vcxproj.filters +++ b/projects/Win/vc12/unit-set-insdel.vcxproj.filters @@ -46,10 +46,10 @@ set_insdel_func - + set_insdel_func - + set_insdel_string diff --git a/projects/Win/vc12/unit-set-insdelfind.vcxproj b/projects/Win/vc12/unit-set-insdelfind.vcxproj index 1bcaba07..b6a50a1e 100644 --- a/projects/Win/vc12/unit-set-insdelfind.vcxproj +++ b/projects/Win/vc12/unit-set-insdelfind.vcxproj @@ -47,7 +47,7 @@ - + diff --git a/projects/Win/vc14/cds.sln b/projects/Win/vc14/cds.sln index 4654ba12..7300001d 100644 --- a/projects/Win/vc14/cds.sln +++ b/projects/Win/vc14/cds.sln @@ -10,7 +10,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "multi-threaded test", "mult ..\..\..\tests\unit\print_cuckoo_stat.h = ..\..\..\tests\unit\print_cuckoo_stat.h ..\..\..\tests\unit\print_ellenbintree_stat.h = ..\..\..\tests\unit\print_ellenbintree_stat.h ..\..\..\tests\unit\print_mspriorityqueue_stat.h = ..\..\..\tests\unit\print_mspriorityqueue_stat.h - ..\..\..\tests\unit\print_multilevel_hashset_stat.h = ..\..\..\tests\unit\print_multilevel_hashset_stat.h + ..\..\..\tests\unit\print_feldman_hashset_stat.h = ..\..\..\tests\unit\print_feldman_hashset_stat.h ..\..\..\tests\unit\print_segmentedqueue_stat.h = ..\..\..\tests\unit\print_segmentedqueue_stat.h ..\..\..\tests\unit\print_skip_list_stat.h = ..\..\..\tests\unit\print_skip_list_stat.h ..\..\..\tests\unit\print_split_list_stat.h = ..\..\..\tests\unit\print_split_list_stat.h @@ -80,7 +80,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "map", "map", "{6BB7A27F-FC5 ..\..\..\tests\unit\map2\map_type_lazy_list.h = ..\..\..\tests\unit\map2\map_type_lazy_list.h ..\..\..\tests\unit\map2\map_type_michael.h = ..\..\..\tests\unit\map2\map_type_michael.h ..\..\..\tests\unit\map2\map_type_michael_list.h = ..\..\..\tests\unit\map2\map_type_michael_list.h - ..\..\..\tests\unit\map2\map_type_multilevel_hashmap.h = ..\..\..\tests\unit\map2\map_type_multilevel_hashmap.h + ..\..\..\tests\unit\map2\map_type_feldman_hashmap.h = ..\..\..\tests\unit\map2\map_type_feldman_hashmap.h ..\..\..\tests\unit\map2\map_type_skip_list.h = ..\..\..\tests\unit\map2\map_type_skip_list.h ..\..\..\tests\unit\map2\map_type_split_list.h = ..\..\..\tests\unit\map2\map_type_split_list.h ..\..\..\tests\unit\map2\map_type_std.h = ..\..\..\tests\unit\map2\map_type_std.h @@ -98,7 +98,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "set", "set", "{A64449B7-90F ..\..\..\tests\unit\set2\set_type_lazy_list.h = ..\..\..\tests\unit\set2\set_type_lazy_list.h ..\..\..\tests\unit\set2\set_type_michael.h = ..\..\..\tests\unit\set2\set_type_michael.h ..\..\..\tests\unit\set2\set_type_michael_list.h = ..\..\..\tests\unit\set2\set_type_michael_list.h - ..\..\..\tests\unit\set2\set_type_multilevel_hashset.h = ..\..\..\tests\unit\set2\set_type_multilevel_hashset.h + ..\..\..\tests\unit\set2\set_type_feldman_hashset.h = ..\..\..\tests\unit\set2\set_type_feldman_hashset.h ..\..\..\tests\unit\set2\set_type_skip_list.h = ..\..\..\tests\unit\set2\set_type_skip_list.h ..\..\..\tests\unit\set2\set_type_split_list.h = ..\..\..\tests\unit\set2\set_type_split_list.h ..\..\..\tests\unit\set2\set_type_std.h = ..\..\..\tests\unit\set2\set_type_std.h diff --git a/projects/Win/vc14/cds.vcxproj b/projects/Win/vc14/cds.vcxproj index 997771d8..e706ec52 100644 --- a/projects/Win/vc14/cds.vcxproj +++ b/projects/Win/vc14/cds.vcxproj @@ -775,8 +775,8 @@ - - + + @@ -792,8 +792,8 @@ - - + + @@ -807,12 +807,12 @@ - - - - - - + + + + + + @@ -866,7 +866,7 @@ - + @@ -878,7 +878,7 @@ - + @@ -886,9 +886,9 @@ - - - + + + diff --git a/projects/Win/vc14/cds.vcxproj.filters b/projects/Win/vc14/cds.vcxproj.filters index 7ecba805..f1b37296 100644 --- a/projects/Win/vc14/cds.vcxproj.filters +++ b/projects/Win/vc14/cds.vcxproj.filters @@ -1178,52 +1178,52 @@ Header Files\cds\intrusive\details - + Header Files\cds\intrusive\impl - + Header Files\cds\intrusive\details - + Header Files\cds\intrusive - + Header Files\cds\intrusive Header Files\cds\algo - + Header Files\cds\container\details - + Header Files\cds\container\impl - + Header Files\cds\container - + Header Files\cds\container - + Header Files\cds\container\details - + Header Files\cds\container\impl - + Header Files\cds\container - + Header Files\cds\container - + Header Files\cds\intrusive - + Header Files\cds\container - + Header Files\cds\container diff --git a/projects/Win/vc14/hdr-test-map.vcxproj b/projects/Win/vc14/hdr-test-map.vcxproj index fc21891d..79b3505c 100644 --- a/projects/Win/vc14/hdr-test-map.vcxproj +++ b/projects/Win/vc14/hdr-test-map.vcxproj @@ -645,7 +645,7 @@ - + @@ -666,13 +666,13 @@ - - - - - - - + + + + + + + diff --git a/projects/Win/vc14/hdr-test-map.vcxproj.filters b/projects/Win/vc14/hdr-test-map.vcxproj.filters index a8e47dce..2fe1b481 100644 --- a/projects/Win/vc14/hdr-test-map.vcxproj.filters +++ b/projects/Win/vc14/hdr-test-map.vcxproj.filters @@ -175,25 +175,25 @@ skip_list - + multilvel_hashmap - + multilvel_hashmap - + multilvel_hashmap - + multilvel_hashmap - + multilvel_hashmap - + multilvel_hashmap - + multilvel_hashmap @@ -212,7 +212,7 @@ cuckoo - + multilvel_hashmap diff --git a/projects/Win/vc14/hdr-test-set.vcxproj b/projects/Win/vc14/hdr-test-set.vcxproj index afce40f9..eb9711cc 100644 --- a/projects/Win/vc14/hdr-test-set.vcxproj +++ b/projects/Win/vc14/hdr-test-set.vcxproj @@ -640,11 +640,11 @@ - + - + @@ -666,13 +666,13 @@ - - - - - - - + + + + + + + @@ -721,13 +721,13 @@ - - - - - - - + + + + + + + diff --git a/projects/Win/vc14/hdr-test-set.vcxproj.filters b/projects/Win/vc14/hdr-test-set.vcxproj.filters index d9522f15..4b6cd72a 100644 --- a/projects/Win/vc14/hdr-test-set.vcxproj.filters +++ b/projects/Win/vc14/hdr-test-set.vcxproj.filters @@ -19,11 +19,11 @@ container\skip_list - - intrusive\multilevel_hashset + + intrusive\feldman_hashset - - container\multilevel_hashset + + container\feldman_hashset @@ -51,10 +51,10 @@ {61f94a40-c964-4233-af67-66a1be1e0aab} - + {a878aed0-83c9-4ca7-95bb-74f10aad8bde} - + {5268f225-1474-413e-a1cb-5f00b8df5e1e} @@ -323,47 +323,47 @@ container\skip_list - - intrusive\multilevel_hashset + + intrusive\feldman_hashset - - intrusive\multilevel_hashset + + intrusive\feldman_hashset - - container\multilevel_hashset + + container\feldman_hashset - - container\multilevel_hashset + + container\feldman_hashset - - intrusive\multilevel_hashset + + intrusive\feldman_hashset - - intrusive\multilevel_hashset + + intrusive\feldman_hashset - - intrusive\multilevel_hashset + + intrusive\feldman_hashset - - intrusive\multilevel_hashset + + intrusive\feldman_hashset - - intrusive\multilevel_hashset + + intrusive\feldman_hashset - - container\multilevel_hashset + + container\feldman_hashset - - container\multilevel_hashset + + container\feldman_hashset - - container\multilevel_hashset + + container\feldman_hashset - - container\multilevel_hashset + + container\feldman_hashset - - container\multilevel_hashset + + container\feldman_hashset \ No newline at end of file diff --git a/projects/Win/vc14/unit-map-delodd.vcxproj b/projects/Win/vc14/unit-map-delodd.vcxproj index 0f2ebc7b..b62b1ec1 100644 --- a/projects/Win/vc14/unit-map-delodd.vcxproj +++ b/projects/Win/vc14/unit-map-delodd.vcxproj @@ -64,7 +64,7 @@ false - + false diff --git a/projects/Win/vc14/unit-map-find.vcxproj b/projects/Win/vc14/unit-map-find.vcxproj index a2353126..ee8b9183 100644 --- a/projects/Win/vc14/unit-map-find.vcxproj +++ b/projects/Win/vc14/unit-map-find.vcxproj @@ -56,7 +56,7 @@ - + @@ -66,7 +66,7 @@ - + @@ -76,7 +76,7 @@ - + diff --git a/projects/Win/vc14/unit-map-find.vcxproj.filters b/projects/Win/vc14/unit-map-find.vcxproj.filters index 3a6880b2..bb9c849a 100644 --- a/projects/Win/vc14/unit-map-find.vcxproj.filters +++ b/projects/Win/vc14/unit-map-find.vcxproj.filters @@ -82,13 +82,13 @@ map_insfind_int - + map_find_int - + map_find_string - + map_insfind_int diff --git a/projects/Win/vc14/unit-map-insdel-item.vcxproj b/projects/Win/vc14/unit-map-insdel-item.vcxproj index c86e7c44..7bab5385 100644 --- a/projects/Win/vc14/unit-map-insdel-item.vcxproj +++ b/projects/Win/vc14/unit-map-insdel-item.vcxproj @@ -56,7 +56,7 @@ - + @@ -65,7 +65,7 @@ - + diff --git a/projects/Win/vc14/unit-map-insdel-item.vcxproj.filters b/projects/Win/vc14/unit-map-insdel-item.vcxproj.filters index 5aa2b21b..8c0b268a 100644 --- a/projects/Win/vc14/unit-map-insdel-item.vcxproj.filters +++ b/projects/Win/vc14/unit-map-insdel-item.vcxproj.filters @@ -57,10 +57,10 @@ map_insdel_item_string - + map_insdel_item_int - + map_insdel_item_string diff --git a/projects/Win/vc14/unit-map-insdel.vcxproj b/projects/Win/vc14/unit-map-insdel.vcxproj index 514c248f..b2ac6a90 100644 --- a/projects/Win/vc14/unit-map-insdel.vcxproj +++ b/projects/Win/vc14/unit-map-insdel.vcxproj @@ -56,7 +56,7 @@ - + @@ -65,7 +65,7 @@ - + @@ -75,7 +75,7 @@ - + diff --git a/projects/Win/vc14/unit-map-insdel.vcxproj.filters b/projects/Win/vc14/unit-map-insdel.vcxproj.filters index 0818ac7a..ef09d099 100644 --- a/projects/Win/vc14/unit-map-insdel.vcxproj.filters +++ b/projects/Win/vc14/unit-map-insdel.vcxproj.filters @@ -76,16 +76,16 @@ map_insdel_string - + map_insdel_int map_insdel_int - + map_insdel_func - + map_insdel_string diff --git a/projects/Win/vc14/unit-map-insdelfind.vcxproj b/projects/Win/vc14/unit-map-insdelfind.vcxproj index aef3bdad..a62d2f13 100644 --- a/projects/Win/vc14/unit-map-insdelfind.vcxproj +++ b/projects/Win/vc14/unit-map-insdelfind.vcxproj @@ -56,7 +56,7 @@ - + diff --git a/projects/Win/vc14/unit-set-delodd.vcxproj b/projects/Win/vc14/unit-set-delodd.vcxproj index 8981a8eb..f5fed26b 100644 --- a/projects/Win/vc14/unit-set-delodd.vcxproj +++ b/projects/Win/vc14/unit-set-delodd.vcxproj @@ -55,7 +55,7 @@ - + diff --git a/projects/Win/vc14/unit-set-insdel.vcxproj b/projects/Win/vc14/unit-set-insdel.vcxproj index 1cc826c3..9a8ad1dc 100644 --- a/projects/Win/vc14/unit-set-insdel.vcxproj +++ b/projects/Win/vc14/unit-set-insdel.vcxproj @@ -55,7 +55,7 @@ - + @@ -63,7 +63,7 @@ - + diff --git a/projects/Win/vc14/unit-set-insdel.vcxproj.filters b/projects/Win/vc14/unit-set-insdel.vcxproj.filters index 74851368..643f5857 100644 --- a/projects/Win/vc14/unit-set-insdel.vcxproj.filters +++ b/projects/Win/vc14/unit-set-insdel.vcxproj.filters @@ -46,10 +46,10 @@ set_insdel_func - + set_insdel_func - + set_insdel_string diff --git a/projects/Win/vc14/unit-set-insdelfind.vcxproj b/projects/Win/vc14/unit-set-insdelfind.vcxproj index 9d1009a4..614d6046 100644 --- a/projects/Win/vc14/unit-set-insdelfind.vcxproj +++ b/projects/Win/vc14/unit-set-insdelfind.vcxproj @@ -55,7 +55,7 @@ - + diff --git a/projects/source.test-hdr.mk b/projects/source.test-hdr.mk index 3e202ed4..7ae0cf05 100644 --- a/projects/source.test-hdr.mk +++ b/projects/source.test-hdr.mk @@ -15,13 +15,13 @@ CDS_TESTHDR_MAP := \ tests/test-hdr/map/hdr_michael_map_lazy_rcu_shb.cpp \ tests/test-hdr/map/hdr_michael_map_lazy_rcu_sht.cpp \ tests/test-hdr/map/hdr_michael_map_lazy_nogc.cpp \ - tests/test-hdr/map/hdr_multilevel_hashmap_hp.cpp \ - tests/test-hdr/map/hdr_multilevel_hashmap_dhp.cpp \ - tests/test-hdr/map/hdr_multilevel_hashmap_rcu_gpb.cpp \ - tests/test-hdr/map/hdr_multilevel_hashmap_rcu_gpi.cpp \ - tests/test-hdr/map/hdr_multilevel_hashmap_rcu_gpt.cpp \ - tests/test-hdr/map/hdr_multilevel_hashmap_rcu_shb.cpp \ - tests/test-hdr/map/hdr_multilevel_hashmap_rcu_sht.cpp \ + tests/test-hdr/map/hdr_feldman_hashmap_hp.cpp \ + tests/test-hdr/map/hdr_feldman_hashmap_dhp.cpp \ + tests/test-hdr/map/hdr_feldman_hashmap_rcu_gpb.cpp \ + tests/test-hdr/map/hdr_feldman_hashmap_rcu_gpi.cpp \ + tests/test-hdr/map/hdr_feldman_hashmap_rcu_gpt.cpp \ + tests/test-hdr/map/hdr_feldman_hashmap_rcu_shb.cpp \ + tests/test-hdr/map/hdr_feldman_hashmap_rcu_sht.cpp \ tests/test-hdr/map/hdr_refinable_hashmap_hashmap_std.cpp \ tests/test-hdr/map/hdr_refinable_hashmap_boost_list.cpp \ tests/test-hdr/map/hdr_refinable_hashmap_list.cpp \ @@ -136,13 +136,13 @@ 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_multilevel_hashset_dhp.cpp \ - tests/test-hdr/set/hdr_intrusive_multilevel_hashset_rcu_gpi.cpp \ - tests/test-hdr/set/hdr_intrusive_multilevel_hashset_rcu_gpb.cpp \ - tests/test-hdr/set/hdr_intrusive_multilevel_hashset_rcu_gpt.cpp \ - tests/test-hdr/set/hdr_intrusive_multilevel_hashset_rcu_shb.cpp \ - tests/test-hdr/set/hdr_intrusive_multilevel_hashset_rcu_sht.cpp \ + tests/test-hdr/set/hdr_intrusive_feldman_hashset_hp.cpp \ + tests/test-hdr/set/hdr_intrusive_feldman_hashset_dhp.cpp \ + tests/test-hdr/set/hdr_intrusive_feldman_hashset_rcu_gpi.cpp \ + tests/test-hdr/set/hdr_intrusive_feldman_hashset_rcu_gpb.cpp \ + tests/test-hdr/set/hdr_intrusive_feldman_hashset_rcu_gpt.cpp \ + tests/test-hdr/set/hdr_intrusive_feldman_hashset_rcu_shb.cpp \ + tests/test-hdr/set/hdr_intrusive_feldman_hashset_rcu_sht.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 \ @@ -184,13 +184,13 @@ CDS_TESTHDR_SET := \ tests/test-hdr/set/hdr_michael_set_lazy_rcu_shb.cpp \ tests/test-hdr/set/hdr_michael_set_lazy_rcu_sht.cpp \ 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_feldman_hashset_hp.cpp \ + tests/test-hdr/set/hdr_feldman_hashset_dhp.cpp \ + tests/test-hdr/set/hdr_feldman_hashset_rcu_gpb.cpp \ + tests/test-hdr/set/hdr_feldman_hashset_rcu_gpi.cpp \ + tests/test-hdr/set/hdr_feldman_hashset_rcu_gpt.cpp \ + tests/test-hdr/set/hdr_feldman_hashset_rcu_shb.cpp \ + tests/test-hdr/set/hdr_feldman_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/projects/source.unit.map.mk b/projects/source.unit.map.mk index 8367de57..1db4e0e2 100644 --- a/projects/source.unit.map.mk +++ b/projects/source.unit.map.mk @@ -5,7 +5,7 @@ CDSUNIT_MAP_SOURCES := \ tests/unit/map2/map_find_int_cuckoo.cpp \ tests/unit/map2/map_find_int_ellentree.cpp \ tests/unit/map2/map_find_int_michael.cpp \ - tests/unit/map2/map_find_int_multilevelhashmap.cpp \ + tests/unit/map2/map_find_int_feldmanhashmap.cpp \ tests/unit/map2/map_find_int_skip.cpp \ tests/unit/map2/map_find_int_split.cpp \ tests/unit/map2/map_find_int_striped.cpp \ @@ -15,7 +15,7 @@ CDSUNIT_MAP_SOURCES := \ tests/unit/map2/map_find_string_cuckoo.cpp \ tests/unit/map2/map_find_string_ellentree.cpp \ tests/unit/map2/map_find_string_michael.cpp \ - tests/unit/map2/map_find_string_multilevelhashmap.cpp \ + tests/unit/map2/map_find_string_feldmanhashmap.cpp \ tests/unit/map2/map_find_string_skip.cpp \ tests/unit/map2/map_find_string_split.cpp \ tests/unit/map2/map_find_string_striped.cpp \ @@ -25,7 +25,7 @@ CDSUNIT_MAP_SOURCES := \ tests/unit/map2/map_insfind_int_cuckoo.cpp \ tests/unit/map2/map_insfind_int_ellentree.cpp \ tests/unit/map2/map_insfind_int_michael.cpp \ - tests/unit/map2/map_insfind_int_multilevelhashmap.cpp \ + tests/unit/map2/map_insfind_int_feldmanhashmap.cpp \ tests/unit/map2/map_insfind_int_skip.cpp \ tests/unit/map2/map_insfind_int_split.cpp \ tests/unit/map2/map_insfind_int_striped.cpp \ @@ -35,7 +35,7 @@ CDSUNIT_MAP_SOURCES := \ tests/unit/map2/map_insdel_func_cuckoo.cpp \ tests/unit/map2/map_insdel_func_ellentree.cpp \ tests/unit/map2/map_insdel_func_michael.cpp \ - tests/unit/map2/map_insdel_func_multilevelhashmap.cpp \ + tests/unit/map2/map_insdel_func_feldmanhashmap.cpp \ tests/unit/map2/map_insdel_func_skip.cpp \ tests/unit/map2/map_insdel_func_split.cpp \ tests/unit/map2/map_insdel_func_striped.cpp \ @@ -44,7 +44,7 @@ CDSUNIT_MAP_SOURCES := \ tests/unit/map2/map_insdel_int_cuckoo.cpp \ tests/unit/map2/map_insdel_int_ellentree.cpp \ tests/unit/map2/map_insdel_int_michael.cpp \ - tests/unit/map2/map_insdel_int_multilevelhashmap.cpp \ + tests/unit/map2/map_insdel_int_feldmanhashmap.cpp \ tests/unit/map2/map_insdel_int_skip.cpp \ tests/unit/map2/map_insdel_int_split.cpp \ tests/unit/map2/map_insdel_int_striped.cpp \ @@ -54,7 +54,7 @@ CDSUNIT_MAP_SOURCES := \ tests/unit/map2/map_insdel_item_int_cuckoo.cpp \ tests/unit/map2/map_insdel_item_int_ellentree.cpp \ tests/unit/map2/map_insdel_item_int_michael.cpp \ - tests/unit/map2/map_insdel_item_int_multilevelhashmap.cpp \ + tests/unit/map2/map_insdel_item_int_feldmanhashmap.cpp \ tests/unit/map2/map_insdel_item_int_skip.cpp \ tests/unit/map2/map_insdel_item_int_split.cpp \ tests/unit/map2/map_insdel_item_int_striped.cpp \ @@ -63,7 +63,7 @@ CDSUNIT_MAP_SOURCES := \ tests/unit/map2/map_insdel_item_string_cuckoo.cpp \ tests/unit/map2/map_insdel_item_string_ellentree.cpp \ tests/unit/map2/map_insdel_item_string_michael.cpp \ - tests/unit/map2/map_insdel_item_string_multilevelhashmap.cpp \ + tests/unit/map2/map_insdel_item_string_feldmanhashmap.cpp \ tests/unit/map2/map_insdel_item_string_skip.cpp \ tests/unit/map2/map_insdel_item_string_split.cpp \ tests/unit/map2/map_insdel_item_string_striped.cpp \ @@ -72,7 +72,7 @@ CDSUNIT_MAP_SOURCES := \ tests/unit/map2/map_insdel_string_cuckoo.cpp \ tests/unit/map2/map_insdel_string_ellentree.cpp \ tests/unit/map2/map_insdel_string_michael.cpp \ - tests/unit/map2/map_insdel_string_multilevelhashmap.cpp \ + tests/unit/map2/map_insdel_string_feldmanhashmap.cpp \ tests/unit/map2/map_insdel_string_skip.cpp \ tests/unit/map2/map_insdel_string_split.cpp \ tests/unit/map2/map_insdel_string_striped.cpp \ @@ -82,7 +82,7 @@ CDSUNIT_MAP_SOURCES := \ tests/unit/map2/map_insdelfind_cuckoo.cpp \ tests/unit/map2/map_insdelfind_ellentree.cpp \ tests/unit/map2/map_insdelfind_michael.cpp \ - tests/unit/map2/map_insdelfind_multilevelhashmap.cpp \ + tests/unit/map2/map_insdelfind_feldmanhashmap.cpp \ tests/unit/map2/map_insdelfind_skip.cpp \ tests/unit/map2/map_insdelfind_split.cpp \ tests/unit/map2/map_insdelfind_striped.cpp \ @@ -92,6 +92,6 @@ CDSUNIT_MAP_SOURCES := \ tests/unit/map2/map_delodd_cuckoo.cpp \ tests/unit/map2/map_delodd_ellentree.cpp \ tests/unit/map2/map_delodd_michael.cpp \ - tests/unit/map2/map_delodd_multilevelhashmap.cpp \ + tests/unit/map2/map_delodd_feldmanhashmap.cpp \ tests/unit/map2/map_delodd_skip.cpp \ tests/unit/map2/map_delodd_split.cpp \ diff --git a/projects/source.unit.set.mk b/projects/source.unit.set.mk index 49688bad..46178fdd 100644 --- a/projects/source.unit.set.mk +++ b/projects/source.unit.set.mk @@ -4,7 +4,7 @@ CDSUNIT_SET_SOURCES := \ tests/unit/set2/set_insdel_func_cuckoo.cpp \ tests/unit/set2/set_insdel_func_ellentree.cpp \ tests/unit/set2/set_insdel_func_michael.cpp \ - tests/unit/set2/set_insdel_func_multilevelhashset.cpp \ + tests/unit/set2/set_insdel_func_feldmanhashset.cpp \ tests/unit/set2/set_insdel_func_skip.cpp \ tests/unit/set2/set_insdel_func_split.cpp \ tests/unit/set2/set_insdel_func_striped.cpp \ @@ -12,7 +12,7 @@ CDSUNIT_SET_SOURCES := \ tests/unit/set2/set_insdel_string_cuckoo.cpp \ tests/unit/set2/set_insdel_string_ellentree.cpp \ tests/unit/set2/set_insdel_string_michael.cpp \ - tests/unit/set2/set_insdel_string_multilevelhashset.cpp \ + tests/unit/set2/set_insdel_string_feldmanhashset.cpp \ tests/unit/set2/set_insdel_string_skip.cpp \ tests/unit/set2/set_insdel_string_split.cpp \ tests/unit/set2/set_insdel_string_striped.cpp \ @@ -21,7 +21,7 @@ CDSUNIT_SET_SOURCES := \ tests/unit/set2/set_insdelfind_cuckoo.cpp \ tests/unit/set2/set_insdelfind_ellentree.cpp \ tests/unit/set2/set_insdelfind_michael.cpp \ - tests/unit/set2/set_insdelfind_multilevelhashset.cpp \ + tests/unit/set2/set_insdelfind_feldmanhashset.cpp \ tests/unit/set2/set_insdelfind_skip.cpp \ tests/unit/set2/set_insdelfind_split.cpp \ tests/unit/set2/set_insdelfind_striped.cpp \ @@ -30,6 +30,6 @@ CDSUNIT_SET_SOURCES := \ tests/unit/set2/set_delodd_cuckoo.cpp \ tests/unit/set2/set_delodd_ellentree.cpp \ tests/unit/set2/set_delodd_michael.cpp \ - tests/unit/set2/set_delodd_multilevelhashset.cpp \ + tests/unit/set2/set_delodd_feldmanhashset.cpp \ tests/unit/set2/set_delodd_skip.cpp \ tests/unit/set2/set_delodd_split.cpp \ diff --git a/tests/data/test-debug.conf b/tests/data/test-debug.conf index f7b05d65..ce46294d 100644 --- a/tests/data/test-debug.conf +++ b/tests/data/test-debug.conf @@ -127,9 +127,9 @@ CuckooInitialSize=256 CuckooProbesetSize=8 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=8 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=8 +FeldmanMapArrayBits=4 [Map_find_string] ThreadCount=2 @@ -143,9 +143,9 @@ CuckooInitialSize=256 CuckooProbesetSize=8 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=8 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=8 +FeldmanMapArrayBits=4 [Map_InsDel_int] InsertThreadCount=4 @@ -159,9 +159,9 @@ CuckooInitialSize=256 CuckooProbesetSize=8 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=8 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=8 +FeldmanMapArrayBits=4 [Map_InsDel_func] InsertThreadCount=4 @@ -176,9 +176,9 @@ CuckooInitialSize=256 CuckooProbesetSize=8 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=8 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=8 +FeldmanMapArrayBits=4 [Map_InsDel_Item_int] ThreadCount=4 @@ -192,9 +192,9 @@ CuckooInitialSize=256 CuckooProbesetSize=8 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=8 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=8 +FeldmanMapArrayBits=4 [Map_InsDel_string] InsertThreadCount=4 @@ -208,9 +208,9 @@ CuckooInitialSize=256 CuckooProbesetSize=8 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=8 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=8 +FeldmanMapArrayBits=4 [Map_InsDel_Item_string] ThreadCount=4 @@ -224,9 +224,9 @@ CuckooInitialSize=256 CuckooProbesetSize=8 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=8 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=8 +FeldmanMapArrayBits=4 [Map_InsFind_int] ThreadCount=0 @@ -238,9 +238,9 @@ CuckooInitialSize=256 CuckooProbesetSize=8 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=8 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=8 +FeldmanMapArrayBits=4 [Map_InsDelFind] InitialMapSize=50000 @@ -255,9 +255,9 @@ CuckooInitialSize=256 CuckooProbesetSize=8 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=8 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=8 +FeldmanMapArrayBits=4 [Map_DelOdd] MapSize=50000 @@ -271,6 +271,6 @@ CuckooInitialSize=256 CuckooProbesetSize=8 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=8 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=8 +FeldmanMapArrayBits=4 diff --git a/tests/data/test-express.conf b/tests/data/test-express.conf index 3fd1f3cd..c58393c8 100644 --- a/tests/data/test-express.conf +++ b/tests/data/test-express.conf @@ -125,9 +125,9 @@ CuckooInitialSize=1024 CuckooProbesetSize=16 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=8 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=8 +FeldmanMapArrayBits=4 [Map_find_string] ThreadCount=8 @@ -141,9 +141,9 @@ CuckooInitialSize=1024 CuckooProbesetSize=16 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=8 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=8 +FeldmanMapArrayBits=4 [Map_InsDel_int] InsertThreadCount=4 @@ -157,9 +157,9 @@ CuckooInitialSize=1024 CuckooProbesetSize=16 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=8 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=8 +FeldmanMapArrayBits=4 [Map_InsDel_func] InsertThreadCount=4 @@ -174,9 +174,9 @@ CuckooInitialSize=1024 CuckooProbesetSize=16 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=8 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=8 +FeldmanMapArrayBits=4 [Map_InsDel_Item_int] ThreadCount=8 @@ -190,9 +190,9 @@ CuckooInitialSize=1024 CuckooProbesetSize=16 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=8 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=8 +FeldmanMapArrayBits=4 [Map_InsDel_string] InsertThreadCount=4 @@ -206,9 +206,9 @@ CuckooInitialSize=1024 CuckooProbesetSize=16 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=8 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=8 +FeldmanMapArrayBits=4 [Map_InsDel_Item_string] ThreadCount=8 @@ -222,9 +222,9 @@ CuckooInitialSize=1024 CuckooProbesetSize=16 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=8 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=8 +FeldmanMapArrayBits=4 [Map_InsFind_int] ThreadCount=0 @@ -236,9 +236,9 @@ CuckooInitialSize=1024 CuckooProbesetSize=16 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=8 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=8 +FeldmanMapArrayBits=4 [Map_InsDelFind] InitialMapSize=500000 @@ -253,9 +253,9 @@ CuckooInitialSize=1024 CuckooProbesetSize=16 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=8 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=8 +FeldmanMapArrayBits=4 [Map_DelOdd] MapSize=500000 @@ -269,6 +269,6 @@ CuckooInitialSize=1024 CuckooProbesetSize=16 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=8 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=8 +FeldmanMapArrayBits=4 diff --git a/tests/data/test.conf b/tests/data/test.conf index 257a7def..f5284ecd 100644 --- a/tests/data/test.conf +++ b/tests/data/test.conf @@ -120,9 +120,9 @@ CuckooInitialSize=1024 CuckooProbesetSize=16 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=10 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=10 +FeldmanMapArrayBits=4 [Map_find_string] ThreadCount=8 @@ -136,9 +136,9 @@ CuckooInitialSize=1024 CuckooProbesetSize=16 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=10 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=10 +FeldmanMapArrayBits=4 [Map_InsDel_int] InsertThreadCount=4 @@ -152,9 +152,9 @@ CuckooInitialSize=1024 CuckooProbesetSize=16 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=10 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=10 +FeldmanMapArrayBits=4 [Map_InsDel_func] InsertThreadCount=4 @@ -169,9 +169,9 @@ CuckooInitialSize=1024 CuckooProbesetSize=16 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=10 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=10 +FeldmanMapArrayBits=4 [Map_InsDel_Item_int] ThreadCount=8 @@ -185,9 +185,9 @@ CuckooInitialSize=1024 CuckooProbesetSize=16 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=10 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=10 +FeldmanMapArrayBits=4 [Map_InsDel_string] InsertThreadCount=4 @@ -201,9 +201,9 @@ CuckooInitialSize=1024 CuckooProbesetSize=16 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=10 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=10 +FeldmanMapArrayBits=4 [Map_InsDel_Item_string] ThreadCount=8 @@ -217,9 +217,9 @@ CuckooInitialSize=1024 CuckooProbesetSize=16 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=10 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=10 +FeldmanMapArrayBits=4 [Map_InsFind_int] ThreadCount=0 @@ -231,9 +231,9 @@ CuckooInitialSize=1024 CuckooProbesetSize=16 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=10 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=10 +FeldmanMapArrayBits=4 [Map_InsDelFind] InitialMapSize=500000 @@ -248,9 +248,9 @@ CuckooInitialSize=1024 CuckooProbesetSize=16 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=10 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=10 +FeldmanMapArrayBits=4 [Map_DelOdd] @@ -265,6 +265,6 @@ CuckooInitialSize=1024 CuckooProbesetSize=16 # 0 - use default CuckooProbesetThreshold=0 -# *** MultiLevelHashMap properties -MultiLevelMapHeadBits=10 -MultiLevelMapArrayBits=4 +# *** FeldmanHashMap properties +FeldmanMapHeadBits=10 +FeldmanMapArrayBits=4 diff --git a/tests/test-hdr/CMakeLists.txt b/tests/test-hdr/CMakeLists.txt index e90e9462..c93157a1 100644 --- a/tests/test-hdr/CMakeLists.txt +++ b/tests/test-hdr/CMakeLists.txt @@ -17,13 +17,13 @@ set(CDS_TESTHDR_MAP map/hdr_michael_map_lazy_rcu_shb.cpp map/hdr_michael_map_lazy_rcu_sht.cpp map/hdr_michael_map_lazy_nogc.cpp - map/hdr_multilevel_hashmap_hp.cpp - map/hdr_multilevel_hashmap_dhp.cpp - map/hdr_multilevel_hashmap_rcu_gpb.cpp - map/hdr_multilevel_hashmap_rcu_gpi.cpp - map/hdr_multilevel_hashmap_rcu_gpt.cpp - map/hdr_multilevel_hashmap_rcu_shb.cpp - map/hdr_multilevel_hashmap_rcu_sht.cpp + map/hdr_feldman_hashmap_hp.cpp + map/hdr_feldman_hashmap_dhp.cpp + map/hdr_feldman_hashmap_rcu_gpb.cpp + map/hdr_feldman_hashmap_rcu_gpi.cpp + map/hdr_feldman_hashmap_rcu_gpt.cpp + map/hdr_feldman_hashmap_rcu_shb.cpp + map/hdr_feldman_hashmap_rcu_sht.cpp map/hdr_refinable_hashmap_hashmap_std.cpp map/hdr_refinable_hashmap_boost_list.cpp map/hdr_refinable_hashmap_list.cpp @@ -138,13 +138,13 @@ 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_multilevel_hashset_rcu_gpi.cpp - set/hdr_intrusive_multilevel_hashset_rcu_gpb.cpp - set/hdr_intrusive_multilevel_hashset_rcu_gpt.cpp - set/hdr_intrusive_multilevel_hashset_rcu_shb.cpp - set/hdr_intrusive_multilevel_hashset_rcu_sht.cpp + set/hdr_intrusive_feldman_hashset_hp.cpp + set/hdr_intrusive_feldman_hashset_dhp.cpp + set/hdr_intrusive_feldman_hashset_rcu_gpi.cpp + set/hdr_intrusive_feldman_hashset_rcu_gpb.cpp + set/hdr_intrusive_feldman_hashset_rcu_gpt.cpp + set/hdr_intrusive_feldman_hashset_rcu_shb.cpp + set/hdr_intrusive_feldman_hashset_rcu_sht.cpp set/hdr_intrusive_refinable_hashset_avlset.cpp set/hdr_intrusive_refinable_hashset_list.cpp set/hdr_intrusive_refinable_hashset_set.cpp @@ -186,13 +186,13 @@ set(CDS_TESTHDR_SET set/hdr_michael_set_lazy_rcu_shb.cpp set/hdr_michael_set_lazy_rcu_sht.cpp 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_feldman_hashset_hp.cpp + set/hdr_feldman_hashset_dhp.cpp + set/hdr_feldman_hashset_rcu_gpb.cpp + set/hdr_feldman_hashset_rcu_gpi.cpp + set/hdr_feldman_hashset_rcu_gpt.cpp + set/hdr_feldman_hashset_rcu_shb.cpp + set/hdr_feldman_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/map/hdr_feldman_hashmap.h b/tests/test-hdr/map/hdr_feldman_hashmap.h new file mode 100644 index 00000000..b8fc5a7a --- /dev/null +++ b/tests/test-hdr/map/hdr_feldman_hashmap.h @@ -0,0 +1,799 @@ +//$$CDS-header$$ + +#ifndef CDSTEST_HDR_FELDMAN_HASHMAP_H +#define CDSTEST_HDR_FELDMAN_HASHMAP_H + +#include "cppunit/cppunit_proxy.h" + +// forward declaration +namespace cds { + namespace container {} + namespace opt {} +} + +namespace map { + namespace cc = cds::container; + namespace co = cds::opt; + + class FeldmanHashMapHdrTest : public CppUnitMini::TestCase + { + struct Item + { + unsigned int nInsertCall; + unsigned int nFindCall; + unsigned int nEraseCall; + mutable unsigned int nIteratorCall; + + Item() + : nInsertCall(0) + , nFindCall(0) + , nEraseCall(0) + , nIteratorCall(0) + {} + + explicit Item( unsigned int n ) + : nInsertCall(n) + , nFindCall(0) + , nEraseCall(0) + , nIteratorCall(0) + {} + }; + + struct hash128 + { + size_t lo; + size_t hi; + + hash128() {} + hash128(size_t l, size_t h) : lo(l), hi(h) {} + hash128( hash128 const& h) : lo(h.lo), hi(h.hi) {} + + 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; + } + }; + + friend bool operator==( hash128 const& lhs, hash128 const& rhs ) + { + return cmp()( lhs, rhs ) == 0; + } + friend bool operator!=(hash128 const& lhs, hash128 const& rhs) + { + return !( lhs == rhs ); + } + }; + + template + void test_hp( size_t nHeadBits, size_t nArrayBits ) + { + typedef typename Map::hash_type hash_type; + typedef typename Map::key_type key_type; + typedef typename Map::mapped_type mapped_type; + typedef typename Map::value_type value_type; + typedef typename Map::guarded_ptr guarded_ptr; + + size_t const capacity = 1000; + + Map m( nHeadBits, nArrayBits ); + CPPUNIT_MSG("Array size: head=" << m.head_size() << ", array_node=" << m.array_node_size()); + //CPPUNIT_ASSERT(m.head_size() >= (size_t(1) << nHeadBits)); + //CPPUNIT_ASSERT(m.array_node_size() == (size_t(1) << nArrayBits)); + + CPPUNIT_ASSERT(m.empty()); + CPPUNIT_ASSERT(m.size() == 0); + + // insert( key )/update()/get()/find() + for ( size_t i = 0; i < capacity; ++i ) { + size_t key = i * 57; + CPPUNIT_ASSERT(!m.contains( key )) + CPPUNIT_ASSERT(m.insert( key )); + CPPUNIT_ASSERT(m.contains( key )); + CPPUNIT_ASSERT(m.size() == i + 1); + + auto ret = m.update(key, [] ( value_type& v, value_type * old ) { + CPPUNIT_ASSERT_CURRENT( old != nullptr ); + ++v.second.nInsertCall; + }, false ); + CPPUNIT_ASSERT( ret.first ); + CPPUNIT_ASSERT( !ret.second ); + + CPPUNIT_ASSERT(m.find(key, [](value_type& v) { ++v.second.nFindCall;} )); + + guarded_ptr gp{ m.get( key ) }; + CPPUNIT_ASSERT( gp ); + CPPUNIT_ASSERT( gp->first == key ); + CPPUNIT_ASSERT( gp->second.nInsertCall == 1 ); + CPPUNIT_ASSERT( gp->second.nFindCall == 1 ); + } + CPPUNIT_ASSERT(!m.empty()); + CPPUNIT_ASSERT(m.size() == capacity); + + // iterator test + size_t nCount = 0; + for ( auto it = m.begin(), itEnd = m.end(); it != itEnd; ++it ) { + CPPUNIT_ASSERT( it->second.nIteratorCall == 0 ); + CPPUNIT_ASSERT( it->second.nInsertCall == 1 ); + CPPUNIT_ASSERT( (*it).second.nFindCall == 1 ); + it->second.nIteratorCall += 1; + ++nCount; + } + CPPUNIT_ASSERT( nCount == capacity ); + + nCount = 0; + for ( auto it = m.rbegin(), itEnd = m.rend(); it != itEnd; ++it ) { + CPPUNIT_ASSERT( it->second.nInsertCall == 1 ); + CPPUNIT_ASSERT( (*it).second.nFindCall == 1 ); + CPPUNIT_ASSERT( it->second.nIteratorCall == 1 ); + (*it).second.nIteratorCall += 1; + ++nCount; + } + CPPUNIT_ASSERT( nCount == capacity ); + + nCount = 0; + for ( auto it = m.cbegin(), itEnd = m.cend(); it != itEnd; ++it ) { + CPPUNIT_ASSERT( it->second.nInsertCall == 1 ); + CPPUNIT_ASSERT( (*it).second.nFindCall == 1 ); + CPPUNIT_ASSERT( it->second.nIteratorCall == 2 ); + (*it).second.nIteratorCall += 1; + ++nCount; + } + CPPUNIT_ASSERT( nCount == capacity ); + + nCount = 0; + for ( auto it = m.crbegin(), itEnd = m.crend(); it != itEnd; ++it ) { + CPPUNIT_ASSERT( it->second.nInsertCall == 1 ); + CPPUNIT_ASSERT( (*it).second.nFindCall == 1 ); + CPPUNIT_ASSERT( it->second.nIteratorCall == 3 ); + (*it).second.nIteratorCall += 1; + ++nCount; + } + CPPUNIT_ASSERT( nCount == capacity ); + + // find + for ( size_t i = 0; i < capacity; i++ ) { + size_t key = i * 57; + CPPUNIT_ASSERT( m.find( key, [key]( value_type& v ) { + CPPUNIT_ASSERT_CURRENT( v.first == key ); + CPPUNIT_ASSERT_CURRENT( v.second.nInsertCall == 1 ); + CPPUNIT_ASSERT_CURRENT( v.second.nFindCall == 1 ); + CPPUNIT_ASSERT_CURRENT( v.second.nIteratorCall == 4 ); + })); + } + + // erase + for ( size_t i = capacity; i > 0; --i ) { + size_t key = (i -1) * 57; + guarded_ptr gp = m.get( key ); + CPPUNIT_ASSERT( gp ); + CPPUNIT_ASSERT( gp->first == key ); + CPPUNIT_ASSERT( gp->second.nInsertCall == 1 ); + CPPUNIT_ASSERT( gp->second.nFindCall == 1 ); + CPPUNIT_ASSERT( (*gp).second.nIteratorCall == 4 ); + + CPPUNIT_ASSERT(m.erase( key )); + + gp = m.get( key ); + CPPUNIT_ASSERT( !gp ); + CPPUNIT_ASSERT(!m.contains( key )); + } + CPPUNIT_ASSERT( m.empty()); + CPPUNIT_ASSERT(m.size() == 0); + + // Iterators on empty map + CPPUNIT_ASSERT(m.begin() == m.end()); + CPPUNIT_ASSERT(m.cbegin() == m.cend()); + CPPUNIT_ASSERT(m.rbegin() == m.rend()); + CPPUNIT_ASSERT(m.crbegin() == m.crend()); + + // insert( key, val ) + for ( size_t i = 0; i < capacity; ++i ) { + CPPUNIT_ASSERT(!m.contains(i)); + CPPUNIT_ASSERT(m.insert( i, (unsigned int) i * 100)); + CPPUNIT_ASSERT( m.contains(i)); + CPPUNIT_ASSERT( m.find( i, [i]( value_type& v ) { + CPPUNIT_ASSERT_CURRENT( v.first == i ); + CPPUNIT_ASSERT_CURRENT( v.second.nInsertCall == i * 100 ); + })); + } + CPPUNIT_ASSERT( !m.empty()); + CPPUNIT_ASSERT(m.size() == capacity); + + // erase( key, func ) + for ( size_t i = 0; i < capacity; ++i ) { + CPPUNIT_ASSERT( m.contains(i)); + CPPUNIT_ASSERT( m.erase( i, [i]( value_type& v ) { + CPPUNIT_ASSERT_CURRENT( v.first == i ); + CPPUNIT_ASSERT_CURRENT( v.second.nInsertCall == i * 100 ); + v.second.nInsertCall = 0; + })); + } + CPPUNIT_ASSERT( m.empty()); + CPPUNIT_ASSERT(m.size() == 0 ); + + // insert_with + for ( size_t i = 0; i < capacity; ++i ) { + size_t key = i * 121; + CPPUNIT_ASSERT(!m.contains(key)); + CPPUNIT_ASSERT( m.insert_with( key, [key]( value_type& v ) { + CPPUNIT_ASSERT_CURRENT( v.first == key ); + CPPUNIT_ASSERT_CURRENT( v.second.nInsertCall == 0 ); + v.second.nInsertCall = decltype(v.second.nInsertCall)( key ); + })); + CPPUNIT_ASSERT(m.find(key, [key] (value_type& v ) { + CPPUNIT_ASSERT_CURRENT( v.first == key ); + CPPUNIT_ASSERT_CURRENT( v.second.nInsertCall == key ); + })); + CPPUNIT_ASSERT(m.size() == i + 1); + } + CPPUNIT_ASSERT( !m.empty()); + CPPUNIT_ASSERT(m.size() == capacity); + + nCount = 0; + for ( auto it = m.begin(), itEnd = m.end(); it != itEnd; ++it ) { + CPPUNIT_ASSERT( it->first == it->second.nInsertCall ); + CPPUNIT_ASSERT( it->second.nIteratorCall == 0 ); + it->second.nIteratorCall += 1; + ++nCount; + } + CPPUNIT_ASSERT( nCount == capacity ); + + nCount = 0; + for ( auto it = m.rbegin(), itEnd = m.rend(); it != itEnd; ++it ) { + CPPUNIT_ASSERT( it->first == it->second.nInsertCall ); + CPPUNIT_ASSERT( it->second.nIteratorCall == 1 ); + it->second.nIteratorCall += 1; + ++nCount; + } + CPPUNIT_ASSERT( nCount == capacity ); + + // erase_at( iterator ) + nCount = 0; + for ( auto it = m.begin(), itEnd = m.end(); it != itEnd; ++it ) { + CPPUNIT_ASSERT( it->first == it->second.nInsertCall ); + CPPUNIT_ASSERT( it->second.nIteratorCall == 2 ); + CPPUNIT_ASSERT(m.erase_at( it )); + ++nCount; + CPPUNIT_ASSERT(!m.contains( it->first )); + } + CPPUNIT_ASSERT( nCount == capacity ); + CPPUNIT_ASSERT( m.empty()); + CPPUNIT_ASSERT(m.size() == 0 ); + + // emplace + for ( size_t i = 0; i < capacity; ++i ) { + size_t key = i * 1023; + CPPUNIT_ASSERT(!m.contains(key)); + CPPUNIT_ASSERT( m.emplace( key, (unsigned int) i )); + CPPUNIT_ASSERT(m.find(key, [key] (value_type& v ) { + CPPUNIT_ASSERT_CURRENT( v.first == key ); + CPPUNIT_ASSERT_CURRENT( v.second.nInsertCall * 1023 == key ); + })); + CPPUNIT_ASSERT(m.size() == i + 1); + } + CPPUNIT_ASSERT( !m.empty()); + CPPUNIT_ASSERT(m.size() == capacity); + + // erase_at( reverse_iterator ) + nCount = 0; + for ( auto it = m.rbegin(), itEnd = m.rend(); it != itEnd; ++it ) { + CPPUNIT_ASSERT( it->first == it->second.nInsertCall * 1023 ); + CPPUNIT_ASSERT(m.erase_at( it )); + ++nCount; + CPPUNIT_ASSERT(!m.contains( it->first )); + } + CPPUNIT_ASSERT( nCount == capacity ); + CPPUNIT_ASSERT( m.empty()); + CPPUNIT_ASSERT(m.size() == 0 ); + + + // extract + for ( size_t i = 0; i < capacity; ++i ) { + size_t key = i * 711; + CPPUNIT_ASSERT(!m.contains(key)); + auto ret = m.update( key, [i]( value_type& v, value_type * old ) { + CPPUNIT_ASSERT_CURRENT( old == nullptr ); + v.second.nInsertCall = (unsigned int) i; + }); + CPPUNIT_ASSERT( ret.first ); + CPPUNIT_ASSERT( ret.second ); + CPPUNIT_ASSERT(m.find(key, [i, key] (value_type& v ) { + CPPUNIT_ASSERT_CURRENT( v.first == key ); + CPPUNIT_ASSERT_CURRENT( v.second.nInsertCall == i ); + })); + CPPUNIT_ASSERT(m.size() == i + 1); + } + CPPUNIT_ASSERT( !m.empty()); + CPPUNIT_ASSERT(m.size() == capacity); + + for ( size_t i = capacity; i > 0; --i ) { + size_t key = (i-1) * 711; + guarded_ptr gp{ m.extract(key) }; + CPPUNIT_ASSERT( gp ); + CPPUNIT_ASSERT( gp->first == key ); + CPPUNIT_ASSERT((*gp).second.nInsertCall == i - 1 ); + gp = m.extract(key); + CPPUNIT_ASSERT( !gp ); + } + CPPUNIT_ASSERT( m.empty()); + CPPUNIT_ASSERT(m.size() == 0 ); + + // clear + for ( size_t i = 0; i < capacity; ++i ) { + CPPUNIT_ASSERT(!m.contains( i )) + CPPUNIT_ASSERT(m.insert( i )); + CPPUNIT_ASSERT(m.contains( i )); + CPPUNIT_ASSERT(m.size() == i + 1); + } + CPPUNIT_ASSERT( !m.empty()); + CPPUNIT_ASSERT(m.size() == capacity ); + + m.clear(); + CPPUNIT_ASSERT( m.empty()); + CPPUNIT_ASSERT(m.size() == 0 ); + + + CPPUNIT_MSG( m.statistics() ); + } + + template + void test_rcu(size_t nHeadBits, size_t nArrayBits) + { + typedef typename Map::hash_type hash_type; + typedef typename Map::key_type key_type; + typedef typename Map::mapped_type mapped_type; + typedef typename Map::value_type value_type; + typedef typename Map::exempt_ptr exempt_ptr; + typedef typename Map::rcu_lock rcu_lock; + + size_t const capacity = 1000; + + Map m(nHeadBits, nArrayBits); + CPPUNIT_MSG("Array size: head=" << m.head_size() << ", array_node=" << m.array_node_size()); + CPPUNIT_ASSERT(m.head_size() >= (size_t(1) << nHeadBits)); + CPPUNIT_ASSERT(m.array_node_size() == (size_t(1) << nArrayBits)); + + CPPUNIT_ASSERT(m.empty()); + CPPUNIT_ASSERT(m.size() == 0); + + // insert( key )/update()/get()/find() + for (size_t i = 0; i < capacity; ++i) { + size_t key = i * 57; + CPPUNIT_ASSERT(!m.contains(key)) + CPPUNIT_ASSERT(m.insert(key)); + CPPUNIT_ASSERT(m.contains(key)); + CPPUNIT_ASSERT(m.size() == i + 1); + + auto ret = m.update(key, [](value_type& v, value_type * old) { + CPPUNIT_ASSERT_CURRENT(old != nullptr); + ++v.second.nInsertCall; + }, false); + CPPUNIT_ASSERT(ret.first); + CPPUNIT_ASSERT(!ret.second); + + CPPUNIT_ASSERT(m.find(key, [](value_type& v) { ++v.second.nFindCall;})); + + { + rcu_lock l; + value_type* p{ m.get(key) }; + CPPUNIT_ASSERT(p); + CPPUNIT_ASSERT(p->first == key); + CPPUNIT_ASSERT(p->second.nInsertCall == 1); + CPPUNIT_ASSERT(p->second.nFindCall == 1); + } + } + CPPUNIT_ASSERT(!m.empty()); + CPPUNIT_ASSERT(m.size() == capacity); + + // iterator test + size_t nCount = 0; + { + rcu_lock l; + for (auto it = m.begin(), itEnd = m.end(); it != itEnd; ++it) { + CPPUNIT_ASSERT(it->second.nIteratorCall == 0); + CPPUNIT_ASSERT(it->second.nInsertCall == 1); + CPPUNIT_ASSERT((*it).second.nFindCall == 1); + it->second.nIteratorCall += 1; + ++nCount; + } + } + CPPUNIT_ASSERT(nCount == capacity); + + nCount = 0; + { + rcu_lock l; + for (auto it = m.rbegin(), itEnd = m.rend(); it != itEnd; ++it) { + CPPUNIT_ASSERT(it->second.nInsertCall == 1); + CPPUNIT_ASSERT((*it).second.nFindCall == 1); + CPPUNIT_ASSERT(it->second.nIteratorCall == 1); + (*it).second.nIteratorCall += 1; + ++nCount; + } + } + CPPUNIT_ASSERT(nCount == capacity); + + nCount = 0; + { + rcu_lock l; + for (auto it = m.cbegin(), itEnd = m.cend(); it != itEnd; ++it) { + CPPUNIT_ASSERT(it->second.nInsertCall == 1); + CPPUNIT_ASSERT((*it).second.nFindCall == 1); + CPPUNIT_ASSERT(it->second.nIteratorCall == 2); + (*it).second.nIteratorCall += 1; + ++nCount; + } + } + CPPUNIT_ASSERT(nCount == capacity); + + nCount = 0; + { + rcu_lock l; + for (auto it = m.crbegin(), itEnd = m.crend(); it != itEnd; ++it) { + CPPUNIT_ASSERT(it->second.nInsertCall == 1); + CPPUNIT_ASSERT((*it).second.nFindCall == 1); + CPPUNIT_ASSERT(it->second.nIteratorCall == 3); + (*it).second.nIteratorCall += 1; + ++nCount; + } + } + CPPUNIT_ASSERT(nCount == capacity); + + // find + for (size_t i = 0; i < capacity; i++) { + size_t key = i * 57; + CPPUNIT_ASSERT(m.find(key, [key](value_type& v) { + CPPUNIT_ASSERT_CURRENT(v.first == key); + CPPUNIT_ASSERT_CURRENT(v.second.nInsertCall == 1); + CPPUNIT_ASSERT_CURRENT(v.second.nFindCall == 1); + CPPUNIT_ASSERT_CURRENT(v.second.nIteratorCall == 4); + })); + } + + // erase + for (size_t i = capacity; i > 0; --i) { + size_t key = (i - 1) * 57; + { + rcu_lock l; + value_type* p = m.get(key); + CPPUNIT_ASSERT(p); + CPPUNIT_ASSERT(p->first == key); + CPPUNIT_ASSERT(p->second.nInsertCall == 1); + CPPUNIT_ASSERT(p->second.nFindCall == 1); + CPPUNIT_ASSERT(p->second.nIteratorCall == 4); + } + + CPPUNIT_ASSERT(m.erase(key)); + + { + rcu_lock l; + value_type* p = m.get(key); + CPPUNIT_ASSERT(!p); + } + CPPUNIT_ASSERT(!m.contains(key)); + } + CPPUNIT_ASSERT(m.empty()); + CPPUNIT_ASSERT(m.size() == 0); + + // Iterators on empty map + { + rcu_lock l; + CPPUNIT_ASSERT(m.begin() == m.end()); + CPPUNIT_ASSERT(m.cbegin() == m.cend()); + CPPUNIT_ASSERT(m.rbegin() == m.rend()); + CPPUNIT_ASSERT(m.crbegin() == m.crend()); + } + + // insert( key, val ) + for (size_t i = 0; i < capacity; ++i) { + CPPUNIT_ASSERT(!m.contains(i)); + CPPUNIT_ASSERT(m.insert(i, (unsigned int)i * 100)); + CPPUNIT_ASSERT(m.contains(i)); + CPPUNIT_ASSERT(m.find(i, [i](value_type& v) { + CPPUNIT_ASSERT_CURRENT(v.first == i); + CPPUNIT_ASSERT_CURRENT(v.second.nInsertCall == i * 100); + })); + } + CPPUNIT_ASSERT(!m.empty()); + CPPUNIT_ASSERT(m.size() == capacity); + + // erase( key, func ) + for (size_t i = 0; i < capacity; ++i) { + CPPUNIT_ASSERT(m.contains(i)); + CPPUNIT_ASSERT(m.erase(i, [i](value_type& v) { + CPPUNIT_ASSERT_CURRENT(v.first == i); + CPPUNIT_ASSERT_CURRENT(v.second.nInsertCall == i * 100); + v.second.nInsertCall = 0; + })); + } + CPPUNIT_ASSERT(m.empty()); + CPPUNIT_ASSERT(m.size() == 0); + + // insert_with + for (size_t i = 0; i < capacity; ++i) { + size_t key = i * 121; + CPPUNIT_ASSERT(!m.contains(key)); + CPPUNIT_ASSERT(m.insert_with(key, [key](value_type& v) { + CPPUNIT_ASSERT_CURRENT(v.first == key); + CPPUNIT_ASSERT_CURRENT(v.second.nInsertCall == 0); + v.second.nInsertCall = decltype(v.second.nInsertCall)(key); + })); + CPPUNIT_ASSERT(m.find(key, [key](value_type& v) { + CPPUNIT_ASSERT_CURRENT(v.first == key); + CPPUNIT_ASSERT_CURRENT(v.second.nInsertCall == key); + })); + CPPUNIT_ASSERT(m.size() == i + 1); + } + CPPUNIT_ASSERT(!m.empty()); + CPPUNIT_ASSERT(m.size() == capacity); + + nCount = 0; + { + rcu_lock l; + for (auto it = m.begin(), itEnd = m.end(); it != itEnd; ++it) { + CPPUNIT_ASSERT(it->first == it->second.nInsertCall); + CPPUNIT_ASSERT(it->second.nIteratorCall == 0); + it->second.nIteratorCall += 1; + ++nCount; + } + } + CPPUNIT_ASSERT(nCount == capacity); + + nCount = 0; + { + rcu_lock l; + for (auto it = m.rbegin(), itEnd = m.rend(); it != itEnd; ++it) { + CPPUNIT_ASSERT(it->first == it->second.nInsertCall); + CPPUNIT_ASSERT(it->second.nIteratorCall == 1); + it->second.nIteratorCall += 1; + ++nCount; + } + } + CPPUNIT_ASSERT(nCount == capacity); + + // clear() + m.clear(); + CPPUNIT_ASSERT(m.empty()); + CPPUNIT_ASSERT(m.size() == 0); + + // emplace + for (size_t i = 0; i < capacity; ++i) { + size_t key = i * 1023; + CPPUNIT_ASSERT(!m.contains(key)); + CPPUNIT_ASSERT(m.emplace(key, static_cast(i))); + CPPUNIT_ASSERT(m.find(key, [key](value_type& v) { + CPPUNIT_ASSERT_CURRENT(v.first == key); + CPPUNIT_ASSERT_CURRENT(v.second.nInsertCall * 1023 == key); + })); + CPPUNIT_ASSERT(m.size() == i + 1); + } + CPPUNIT_ASSERT(!m.empty()); + CPPUNIT_ASSERT(m.size() == capacity); + + // extract + for (size_t i = capacity; i > 0; --i) { + size_t key = (i - 1) * 1023; + exempt_ptr xp{ m.extract(key) }; + CPPUNIT_ASSERT(xp); + CPPUNIT_ASSERT(xp->first == key); + CPPUNIT_ASSERT((*xp).second.nInsertCall == static_cast(i - 1)); + xp = m.extract(key); + CPPUNIT_ASSERT(!xp); + } + CPPUNIT_ASSERT(m.empty()); + CPPUNIT_ASSERT(m.size() == 0); + + CPPUNIT_MSG(m.statistics()); + } + + void hp_nohash(); + void hp_nohash_stat(); + void hp_nohash_5_3(); + void hp_nohash_5_3_stat(); + void hp_stdhash(); + 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_nohash(); + void dhp_nohash_stat(); + void dhp_nohash_5_3(); + void dhp_nohash_5_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(); + + void rcu_gpb_nohash(); + void rcu_gpb_nohash_stat(); + void rcu_gpb_nohash_5_3(); + void rcu_gpb_nohash_5_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_gpi_nohash(); + void rcu_gpi_nohash_stat(); + void rcu_gpi_nohash_5_3(); + void rcu_gpi_nohash_5_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_gpt_nohash(); + void rcu_gpt_nohash_stat(); + void rcu_gpt_nohash_5_3(); + void rcu_gpt_nohash_5_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_nohash(); + void rcu_shb_nohash_stat(); + void rcu_shb_nohash_5_3(); + void rcu_shb_nohash_5_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_nohash(); + void rcu_sht_nohash_stat(); + void rcu_sht_nohash_5_3(); + void rcu_sht_nohash_5_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(FeldmanHashMapHdrTest) + CPPUNIT_TEST(hp_nohash) + CPPUNIT_TEST(hp_nohash_stat) + CPPUNIT_TEST(hp_nohash_5_3) + CPPUNIT_TEST(hp_nohash_5_3_stat) + 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_nohash) + CPPUNIT_TEST(dhp_nohash_stat) + CPPUNIT_TEST(dhp_nohash_5_3) + CPPUNIT_TEST(dhp_nohash_5_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(rcu_gpb_nohash) + CPPUNIT_TEST(rcu_gpb_nohash_stat) + CPPUNIT_TEST(rcu_gpb_nohash_5_3) + CPPUNIT_TEST(rcu_gpb_nohash_5_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_gpi_nohash) + CPPUNIT_TEST(rcu_gpi_nohash_stat) + CPPUNIT_TEST(rcu_gpi_nohash_5_3) + CPPUNIT_TEST(rcu_gpi_nohash_5_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_gpt_nohash) + CPPUNIT_TEST(rcu_gpt_nohash_stat) + CPPUNIT_TEST(rcu_gpt_nohash_5_3) + CPPUNIT_TEST(rcu_gpt_nohash_5_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_nohash) + CPPUNIT_TEST(rcu_shb_nohash_stat) + CPPUNIT_TEST(rcu_shb_nohash_5_3) + CPPUNIT_TEST(rcu_shb_nohash_5_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_nohash) + CPPUNIT_TEST(rcu_sht_nohash_stat) + CPPUNIT_TEST(rcu_sht_nohash_5_3) + CPPUNIT_TEST(rcu_sht_nohash_5_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() + + }; + +} // namespace map + +#endif //#ifndef CDSTEST_HDR_FELDMAN_HASHMAP_H diff --git a/tests/test-hdr/map/hdr_feldman_hashmap_dhp.cpp b/tests/test-hdr/map/hdr_feldman_hashmap_dhp.cpp new file mode 100644 index 00000000..de6aef85 --- /dev/null +++ b/tests/test-hdr/map/hdr_feldman_hashmap_dhp.cpp @@ -0,0 +1,198 @@ +//$$CDS-header$$ + +#include "map/hdr_feldman_hashmap.h" +#include +#include "unit/print_feldman_hashset_stat.h" + +namespace map { + namespace { + typedef cds::gc::DHP gc_type; + } // namespace + + void FeldmanHashMapHdrTest::dhp_nohash() + { + typedef cc::FeldmanHashMap< gc_type, size_t, Item > map_type; + + test_hp(4, 2); + } + + void FeldmanHashMapHdrTest::dhp_stdhash() + { + struct traits : public cc::feldman_hashmap::traits { + typedef std::hash hash; + }; + typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type; + + test_hp(4, 2); + } + + void FeldmanHashMapHdrTest::dhp_hash128() + { + struct traits : public cc::feldman_hashmap::traits { + typedef hash128::make hash; + typedef hash128::less less; + }; + typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type; + test_hp(4, 2); + + typedef cc::FeldmanHashMap< gc_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::hash< hash128::make > + , co::less< hash128::less > + >::type + > map_type2; + test_hp(4, 2); + } + + void FeldmanHashMapHdrTest::dhp_nohash_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + }; + typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type; + test_hp(4, 2); + + typedef cc::FeldmanHashMap< gc_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + >::type + > map_type2; + test_hp(4, 2); + } + + void FeldmanHashMapHdrTest::dhp_stdhash_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef std::hash hash; + typedef cc::feldman_hashmap::stat<> stat; + }; + typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type; + test_hp(4, 2); + + typedef cc::FeldmanHashMap< gc_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + ,co::hash< std::hash> + >::type + > map_type2; + test_hp(4, 2); + } + + void FeldmanHashMapHdrTest::dhp_hash128_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + typedef hash128::make hash; + typedef hash128::cmp compare; + }; + typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type; + test_hp(4, 2); + + typedef cc::FeldmanHashMap< gc_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + , co::hash< hash128::make > + , co::compare< hash128::cmp > + >::type + > map_type2; + test_hp(4, 2); + } + + void FeldmanHashMapHdrTest::dhp_nohash_5_3() + { + typedef cc::FeldmanHashMap< gc_type, size_t, Item > map_type; + + test_hp(5, 3); + } + + + void FeldmanHashMapHdrTest::dhp_stdhash_5_3() + { + struct traits : public cc::feldman_hashmap::traits { + typedef std::hash hash; + }; + typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type; + + test_hp(5, 3); + } + + void FeldmanHashMapHdrTest::dhp_nohash_5_3_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + typedef cds::backoff::empty back_off; + }; + typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type; + test_hp(5, 3); + + typedef cc::FeldmanHashMap< gc_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + , co::back_off< cds::backoff::empty > + >::type + > map_type2; + test_hp(5, 3); + } + + void FeldmanHashMapHdrTest::dhp_stdhash_5_3_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + typedef cds::backoff::empty back_off; + typedef std::hash hash; + }; + typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type; + test_hp(5, 3); + + typedef cc::FeldmanHashMap< gc_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + ,co::back_off< cds::backoff::empty > + ,co::hash< std::hash> + >::type + > map_type2; + test_hp(5, 3); + } + + void FeldmanHashMapHdrTest::dhp_hash128_4_3() + { + struct traits : public cc::feldman_hashmap::traits { + typedef hash128::make hash; + typedef hash128::less less; + }; + typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type; + test_hp(4, 3); + + typedef cc::FeldmanHashMap< gc_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::hash< hash128::make > + , co::less< hash128::less > + >::type + > map_type2; + test_hp(4, 3); + } + + void FeldmanHashMapHdrTest::dhp_hash128_4_3_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef hash128::make hash; + typedef hash128::less less; + typedef cc::feldman_hashmap::stat<> stat; + typedef co::v::sequential_consistent memory_model; + }; + typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type; + test_hp(4, 3); + + typedef cc::FeldmanHashMap< gc_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::hash< hash128::make > + , co::less< hash128::less > + , co::stat< cc::feldman_hashmap::stat<>> + , co::memory_model< co::v::sequential_consistent > + >::type + > map_type2; + test_hp(4, 3); + } +} // namespace map + +CPPUNIT_TEST_SUITE_REGISTRATION(map::FeldmanHashMapHdrTest); diff --git a/tests/test-hdr/map/hdr_feldman_hashmap_hp.cpp b/tests/test-hdr/map/hdr_feldman_hashmap_hp.cpp new file mode 100644 index 00000000..2c4df61f --- /dev/null +++ b/tests/test-hdr/map/hdr_feldman_hashmap_hp.cpp @@ -0,0 +1,198 @@ +//$$CDS-header$$ + +#include "map/hdr_feldman_hashmap.h" +#include +#include "unit/print_feldman_hashset_stat.h" + +namespace map { + namespace { + typedef cds::gc::HP gc_type; + } // namespace + + void FeldmanHashMapHdrTest::hp_nohash() + { + typedef cc::FeldmanHashMap< gc_type, size_t, Item > map_type; + + test_hp(4, 2); + } + + void FeldmanHashMapHdrTest::hp_stdhash() + { + struct traits : public cc::feldman_hashmap::traits { + typedef std::hash hash; + }; + typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type; + + test_hp(4, 2); + } + + void FeldmanHashMapHdrTest::hp_hash128() + { + struct traits : public cc::feldman_hashmap::traits { + typedef hash128::make hash; + typedef hash128::less less; + }; + typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type; + test_hp(4, 2); + + typedef cc::FeldmanHashMap< gc_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::hash< hash128::make > + , co::less< hash128::less > + >::type + > map_type2; + test_hp(4, 2); + } + + void FeldmanHashMapHdrTest::hp_nohash_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + }; + typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type; + test_hp(4, 2); + + typedef cc::FeldmanHashMap< gc_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + >::type + > map_type2; + test_hp(4, 2); + } + + void FeldmanHashMapHdrTest::hp_stdhash_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef std::hash hash; + typedef cc::feldman_hashmap::stat<> stat; + }; + typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type; + test_hp(4, 2); + + typedef cc::FeldmanHashMap< gc_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + ,co::hash< std::hash> + >::type + > map_type2; + test_hp(4, 2); + } + + void FeldmanHashMapHdrTest::hp_hash128_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + typedef hash128::make hash; + typedef hash128::cmp compare; + }; + typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type; + test_hp(4, 2); + + typedef cc::FeldmanHashMap< gc_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + , co::hash< hash128::make > + , co::compare< hash128::cmp > + >::type + > map_type2; + test_hp(4, 2); + } + + void FeldmanHashMapHdrTest::hp_nohash_5_3() + { + typedef cc::FeldmanHashMap< gc_type, size_t, Item > map_type; + + test_hp(5, 3); + } + + + void FeldmanHashMapHdrTest::hp_stdhash_5_3() + { + struct traits : public cc::feldman_hashmap::traits { + typedef std::hash hash; + }; + typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type; + + test_hp(5, 3); + } + + void FeldmanHashMapHdrTest::hp_nohash_5_3_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + typedef cds::backoff::empty back_off; + }; + typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type; + test_hp(5, 3); + + typedef cc::FeldmanHashMap< gc_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + , co::back_off< cds::backoff::empty > + >::type + > map_type2; + test_hp(5, 3); + } + + void FeldmanHashMapHdrTest::hp_stdhash_5_3_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + typedef cds::backoff::empty back_off; + typedef std::hash hash; + }; + typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type; + test_hp(5, 3); + + typedef cc::FeldmanHashMap< gc_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + ,co::back_off< cds::backoff::empty > + ,co::hash< std::hash> + >::type + > map_type2; + test_hp(5, 3); + } + + void FeldmanHashMapHdrTest::hp_hash128_4_3() + { + struct traits : public cc::feldman_hashmap::traits { + typedef hash128::make hash; + typedef hash128::less less; + }; + typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type; + test_hp(4, 3); + + typedef cc::FeldmanHashMap< gc_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::hash< hash128::make > + , co::less< hash128::less > + >::type + > map_type2; + test_hp(4, 3); + } + + void FeldmanHashMapHdrTest::hp_hash128_4_3_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef hash128::make hash; + typedef hash128::less less; + typedef cc::feldman_hashmap::stat<> stat; + typedef co::v::sequential_consistent memory_model; + }; + typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type; + test_hp(4, 3); + + typedef cc::FeldmanHashMap< gc_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::hash< hash128::make > + , co::less< hash128::less > + , co::stat< cc::feldman_hashmap::stat<>> + , co::memory_model< co::v::sequential_consistent > + >::type + > map_type2; + test_hp(4, 3); + } +} // namespace map + +CPPUNIT_TEST_SUITE_REGISTRATION(map::FeldmanHashMapHdrTest); diff --git a/tests/test-hdr/map/hdr_feldman_hashmap_rcu_gpb.cpp b/tests/test-hdr/map/hdr_feldman_hashmap_rcu_gpb.cpp new file mode 100644 index 00000000..87582cdb --- /dev/null +++ b/tests/test-hdr/map/hdr_feldman_hashmap_rcu_gpb.cpp @@ -0,0 +1,197 @@ +//$$CDS-header$$ + +#include "map/hdr_feldman_hashmap.h" +#include +#include +#include "unit/print_feldman_hashset_stat.h" + +namespace map { + namespace { + typedef cds::urcu::gc< cds::urcu::general_buffered<>> rcu_type; + } // namespace + + void FeldmanHashMapHdrTest::rcu_gpb_nohash() + { + typedef cc::FeldmanHashMap< rcu_type, size_t, Item > map_type; + + test_rcu(4, 2); + } + + void FeldmanHashMapHdrTest::rcu_gpb_stdhash() + { + struct traits : public cc::feldman_hashmap::traits { + typedef std::hash hash; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + + test_rcu(4, 2); + } + + void FeldmanHashMapHdrTest::rcu_gpb_hash128() + { + struct traits : public cc::feldman_hashmap::traits { + typedef hash128::make hash; + typedef hash128::less less; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 2); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::hash< hash128::make > + , co::less< hash128::less > + >::type + > map_type2; + test_rcu(4, 2); + } + + void FeldmanHashMapHdrTest::rcu_gpb_nohash_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 2); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + >::type + > map_type2; + test_rcu(4, 2); + } + + void FeldmanHashMapHdrTest::rcu_gpb_stdhash_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef std::hash hash; + typedef cc::feldman_hashmap::stat<> stat; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 2); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + ,co::hash> + >::type + > map_type2; + test_rcu(4, 2); + } + + void FeldmanHashMapHdrTest::rcu_gpb_hash128_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + typedef hash128::make hash; + typedef hash128::cmp compare; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 2); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + , co::hash< hash128::make > + , co::compare< hash128::cmp > + >::type + > map_type2; + test_rcu(4, 2); + } + + void FeldmanHashMapHdrTest::rcu_gpb_nohash_5_3() + { + typedef cc::FeldmanHashMap< rcu_type, size_t, Item > map_type; + + test_rcu(5, 3); + } + + void FeldmanHashMapHdrTest::rcu_gpb_stdhash_5_3() + { + struct traits : public cc::feldman_hashmap::traits { + typedef std::hash hash; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + + test_rcu(5, 3); + } + + void FeldmanHashMapHdrTest::rcu_gpb_nohash_5_3_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + typedef cds::backoff::empty back_off; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(5, 3); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + , co::back_off< cds::backoff::empty > + >::type + > map_type2; + test_rcu(5, 3); + } + + void FeldmanHashMapHdrTest::rcu_gpb_stdhash_5_3_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + typedef cds::backoff::empty back_off; + typedef std::hash hash; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(5, 3); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + ,co::back_off< cds::backoff::empty > + ,co::hash< std::hash> + >::type + > map_type2; + test_rcu(5, 3); + } + + void FeldmanHashMapHdrTest::rcu_gpb_hash128_4_3() + { + struct traits : public cc::feldman_hashmap::traits { + typedef hash128::make hash; + typedef hash128::less less; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 3); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::hash< hash128::make > + , co::less< hash128::less > + >::type + > map_type2; + test_rcu(4, 3); + } + + void FeldmanHashMapHdrTest::rcu_gpb_hash128_4_3_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef hash128::make hash; + typedef hash128::less less; + typedef cc::feldman_hashmap::stat<> stat; + typedef co::v::sequential_consistent memory_model; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 3); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::hash< hash128::make > + , co::less< hash128::less > + , co::stat< cc::feldman_hashmap::stat<>> + , co::memory_model< co::v::sequential_consistent > + >::type + > map_type2; + test_rcu(4, 3); + } + +} // namespace map diff --git a/tests/test-hdr/map/hdr_feldman_hashmap_rcu_gpi.cpp b/tests/test-hdr/map/hdr_feldman_hashmap_rcu_gpi.cpp new file mode 100644 index 00000000..145a47ae --- /dev/null +++ b/tests/test-hdr/map/hdr_feldman_hashmap_rcu_gpi.cpp @@ -0,0 +1,197 @@ +//$$CDS-header$$ + +#include "map/hdr_feldman_hashmap.h" +#include +#include +#include "unit/print_feldman_hashset_stat.h" + +namespace map { + namespace { + typedef cds::urcu::gc< cds::urcu::general_instant<>> rcu_type; + } // namespace + + void FeldmanHashMapHdrTest::rcu_gpi_nohash() + { + typedef cc::FeldmanHashMap< rcu_type, size_t, Item > map_type; + + test_rcu(4, 2); + } + + void FeldmanHashMapHdrTest::rcu_gpi_stdhash() + { + struct traits : public cc::feldman_hashmap::traits { + typedef std::hash hash; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + + test_rcu(4, 2); + } + + void FeldmanHashMapHdrTest::rcu_gpi_hash128() + { + struct traits : public cc::feldman_hashmap::traits { + typedef hash128::make hash; + typedef hash128::less less; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 2); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::hash< hash128::make > + , co::less< hash128::less > + >::type + > map_type2; + test_rcu(4, 2); + } + + void FeldmanHashMapHdrTest::rcu_gpi_nohash_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 2); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + >::type + > map_type2; + test_rcu(4, 2); + } + + void FeldmanHashMapHdrTest::rcu_gpi_stdhash_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef std::hash hash; + typedef cc::feldman_hashmap::stat<> stat; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 2); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + ,co::hash> + >::type + > map_type2; + test_rcu(4, 2); + } + + void FeldmanHashMapHdrTest::rcu_gpi_hash128_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + typedef hash128::make hash; + typedef hash128::cmp compare; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 2); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + , co::hash< hash128::make > + , co::compare< hash128::cmp > + >::type + > map_type2; + test_rcu(4, 2); + } + + void FeldmanHashMapHdrTest::rcu_gpi_nohash_5_3() + { + typedef cc::FeldmanHashMap< rcu_type, size_t, Item > map_type; + + test_rcu(5, 3); + } + + void FeldmanHashMapHdrTest::rcu_gpi_stdhash_5_3() + { + struct traits : public cc::feldman_hashmap::traits { + typedef std::hash hash; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + + test_rcu(5, 3); + } + + void FeldmanHashMapHdrTest::rcu_gpi_nohash_5_3_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + typedef cds::backoff::empty back_off; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(5, 3); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + , co::back_off< cds::backoff::empty > + >::type + > map_type2; + test_rcu(5, 3); + } + + void FeldmanHashMapHdrTest::rcu_gpi_stdhash_5_3_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + typedef cds::backoff::empty back_off; + typedef std::hash hash; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(5, 3); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + ,co::back_off< cds::backoff::empty > + ,co::hash< std::hash> + >::type + > map_type2; + test_rcu(5, 3); + } + + void FeldmanHashMapHdrTest::rcu_gpi_hash128_4_3() + { + struct traits : public cc::feldman_hashmap::traits { + typedef hash128::make hash; + typedef hash128::less less; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 3); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::hash< hash128::make > + , co::less< hash128::less > + >::type + > map_type2; + test_rcu(4, 3); + } + + void FeldmanHashMapHdrTest::rcu_gpi_hash128_4_3_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef hash128::make hash; + typedef hash128::less less; + typedef cc::feldman_hashmap::stat<> stat; + typedef co::v::sequential_consistent memory_model; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 3); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::hash< hash128::make > + , co::less< hash128::less > + , co::stat< cc::feldman_hashmap::stat<>> + , co::memory_model< co::v::sequential_consistent > + >::type + > map_type2; + test_rcu(4, 3); + } + +} // namespace map diff --git a/tests/test-hdr/map/hdr_feldman_hashmap_rcu_gpt.cpp b/tests/test-hdr/map/hdr_feldman_hashmap_rcu_gpt.cpp new file mode 100644 index 00000000..534ab886 --- /dev/null +++ b/tests/test-hdr/map/hdr_feldman_hashmap_rcu_gpt.cpp @@ -0,0 +1,197 @@ +//$$CDS-header$$ + +#include "map/hdr_feldman_hashmap.h" +#include +#include +#include "unit/print_feldman_hashset_stat.h" + +namespace map { + namespace { + typedef cds::urcu::gc< cds::urcu::general_threaded<>> rcu_type; + } // namespace + + void FeldmanHashMapHdrTest::rcu_gpt_nohash() + { + typedef cc::FeldmanHashMap< rcu_type, size_t, Item > map_type; + + test_rcu(4, 2); + } + + void FeldmanHashMapHdrTest::rcu_gpt_stdhash() + { + struct traits : public cc::feldman_hashmap::traits { + typedef std::hash hash; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + + test_rcu(4, 2); + } + + void FeldmanHashMapHdrTest::rcu_gpt_hash128() + { + struct traits : public cc::feldman_hashmap::traits { + typedef hash128::make hash; + typedef hash128::less less; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 2); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::hash< hash128::make > + , co::less< hash128::less > + >::type + > map_type2; + test_rcu(4, 2); + } + + void FeldmanHashMapHdrTest::rcu_gpt_nohash_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 2); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + >::type + > map_type2; + test_rcu(4, 2); + } + + void FeldmanHashMapHdrTest::rcu_gpt_stdhash_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef std::hash hash; + typedef cc::feldman_hashmap::stat<> stat; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 2); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + ,co::hash> + >::type + > map_type2; + test_rcu(4, 2); + } + + void FeldmanHashMapHdrTest::rcu_gpt_hash128_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + typedef hash128::make hash; + typedef hash128::cmp compare; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 2); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + , co::hash< hash128::make > + , co::compare< hash128::cmp > + >::type + > map_type2; + test_rcu(4, 2); + } + + void FeldmanHashMapHdrTest::rcu_gpt_nohash_5_3() + { + typedef cc::FeldmanHashMap< rcu_type, size_t, Item > map_type; + + test_rcu(5, 3); + } + + void FeldmanHashMapHdrTest::rcu_gpt_stdhash_5_3() + { + struct traits : public cc::feldman_hashmap::traits { + typedef std::hash hash; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + + test_rcu(5, 3); + } + + void FeldmanHashMapHdrTest::rcu_gpt_nohash_5_3_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + typedef cds::backoff::empty back_off; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(5, 3); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + , co::back_off< cds::backoff::empty > + >::type + > map_type2; + test_rcu(5, 3); + } + + void FeldmanHashMapHdrTest::rcu_gpt_stdhash_5_3_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + typedef cds::backoff::empty back_off; + typedef std::hash hash; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(5, 3); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + ,co::back_off< cds::backoff::empty > + ,co::hash< std::hash> + >::type + > map_type2; + test_rcu(5, 3); + } + + void FeldmanHashMapHdrTest::rcu_gpt_hash128_4_3() + { + struct traits : public cc::feldman_hashmap::traits { + typedef hash128::make hash; + typedef hash128::less less; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 3); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::hash< hash128::make > + , co::less< hash128::less > + >::type + > map_type2; + test_rcu(4, 3); + } + + void FeldmanHashMapHdrTest::rcu_gpt_hash128_4_3_stat() + { + struct traits : public cc::feldman_hashmap::traits { + typedef hash128::make hash; + typedef hash128::less less; + typedef cc::feldman_hashmap::stat<> stat; + typedef co::v::sequential_consistent memory_model; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 3); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::hash< hash128::make > + , co::less< hash128::less > + , co::stat< cc::feldman_hashmap::stat<>> + , co::memory_model< co::v::sequential_consistent > + >::type + > map_type2; + test_rcu(4, 3); + } + +} // namespace map diff --git a/tests/test-hdr/map/hdr_feldman_hashmap_rcu_shb.cpp b/tests/test-hdr/map/hdr_feldman_hashmap_rcu_shb.cpp new file mode 100644 index 00000000..b9b34ad4 --- /dev/null +++ b/tests/test-hdr/map/hdr_feldman_hashmap_rcu_shb.cpp @@ -0,0 +1,223 @@ +//$$CDS-header$$ + +#include "map/hdr_feldman_hashmap.h" +#include +#include +#include "unit/print_feldman_hashset_stat.h" + +namespace map { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + namespace { + typedef cds::urcu::gc< cds::urcu::signal_buffered<>> rcu_type; + } // namespace +#endif + + void FeldmanHashMapHdrTest::rcu_shb_nohash() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef cc::FeldmanHashMap< rcu_type, size_t, Item > map_type; + + test_rcu(4, 2); +#endif + } + + void FeldmanHashMapHdrTest::rcu_shb_stdhash() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + struct traits : public cc::feldman_hashmap::traits { + typedef std::hash hash; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + + test_rcu(4, 2); +#endif + } + + void FeldmanHashMapHdrTest::rcu_shb_hash128() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + struct traits : public cc::feldman_hashmap::traits { + typedef hash128::make hash; + typedef hash128::less less; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 2); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::hash< hash128::make > + , co::less< hash128::less > + >::type + > map_type2; + test_rcu(4, 2); +#endif + } + + void FeldmanHashMapHdrTest::rcu_shb_nohash_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 2); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + >::type + > map_type2; + test_rcu(4, 2); +#endif + } + + void FeldmanHashMapHdrTest::rcu_shb_stdhash_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + struct traits : public cc::feldman_hashmap::traits { + typedef std::hash hash; + typedef cc::feldman_hashmap::stat<> stat; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 2); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + ,co::hash> + >::type + > map_type2; + test_rcu(4, 2); +#endif + } + + void FeldmanHashMapHdrTest::rcu_shb_hash128_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + typedef hash128::make hash; + typedef hash128::cmp compare; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 2); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + , co::hash< hash128::make > + , co::compare< hash128::cmp > + >::type + > map_type2; + test_rcu(4, 2); +#endif + } + + void FeldmanHashMapHdrTest::rcu_shb_nohash_5_3() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef cc::FeldmanHashMap< rcu_type, size_t, Item > map_type; + + test_rcu(5, 3); +#endif + } + + void FeldmanHashMapHdrTest::rcu_shb_stdhash_5_3() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + struct traits : public cc::feldman_hashmap::traits { + typedef std::hash hash; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + + test_rcu(5, 3); +#endif + } + + void FeldmanHashMapHdrTest::rcu_shb_nohash_5_3_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + typedef cds::backoff::empty back_off; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(5, 3); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + , co::back_off< cds::backoff::empty > + >::type + > map_type2; + test_rcu(5, 3); +#endif + } + + void FeldmanHashMapHdrTest::rcu_shb_stdhash_5_3_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + typedef cds::backoff::empty back_off; + typedef std::hash hash; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(5, 3); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + ,co::back_off< cds::backoff::empty > + ,co::hash< std::hash> + >::type + > map_type2; + test_rcu(5, 3); +#endif + } + + void FeldmanHashMapHdrTest::rcu_shb_hash128_4_3() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + struct traits : public cc::feldman_hashmap::traits { + typedef hash128::make hash; + typedef hash128::less less; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 3); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::hash< hash128::make > + , co::less< hash128::less > + >::type + > map_type2; + test_rcu(4, 3); +#endif + } + + void FeldmanHashMapHdrTest::rcu_shb_hash128_4_3_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + struct traits : public cc::feldman_hashmap::traits { + typedef hash128::make hash; + typedef hash128::less less; + typedef cc::feldman_hashmap::stat<> stat; + typedef co::v::sequential_consistent memory_model; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 3); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::hash< hash128::make > + , co::less< hash128::less > + , co::stat< cc::feldman_hashmap::stat<>> + , co::memory_model< co::v::sequential_consistent > + >::type + > map_type2; + test_rcu(4, 3); +#endif + } + +} // namespace map diff --git a/tests/test-hdr/map/hdr_feldman_hashmap_rcu_sht.cpp b/tests/test-hdr/map/hdr_feldman_hashmap_rcu_sht.cpp new file mode 100644 index 00000000..ce040861 --- /dev/null +++ b/tests/test-hdr/map/hdr_feldman_hashmap_rcu_sht.cpp @@ -0,0 +1,223 @@ +//$$CDS-header$$ + +#include "map/hdr_feldman_hashmap.h" +#include +#include +#include "unit/print_feldman_hashset_stat.h" + +namespace map { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + namespace { + typedef cds::urcu::gc< cds::urcu::signal_threaded<>> rcu_type; + } // namespace +#endif + + void FeldmanHashMapHdrTest::rcu_sht_nohash() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef cc::FeldmanHashMap< rcu_type, size_t, Item > map_type; + + test_rcu(4, 2); +#endif + } + + void FeldmanHashMapHdrTest::rcu_sht_stdhash() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + struct traits : public cc::feldman_hashmap::traits { + typedef std::hash hash; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + + test_rcu(4, 2); +#endif + } + + void FeldmanHashMapHdrTest::rcu_sht_hash128() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + struct traits : public cc::feldman_hashmap::traits { + typedef hash128::make hash; + typedef hash128::less less; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 2); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::hash< hash128::make > + , co::less< hash128::less > + >::type + > map_type2; + test_rcu(4, 2); +#endif + } + + void FeldmanHashMapHdrTest::rcu_sht_nohash_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 2); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + >::type + > map_type2; + test_rcu(4, 2); +#endif + } + + void FeldmanHashMapHdrTest::rcu_sht_stdhash_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + struct traits : public cc::feldman_hashmap::traits { + typedef std::hash hash; + typedef cc::feldman_hashmap::stat<> stat; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 2); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + ,co::hash> + >::type + > map_type2; + test_rcu(4, 2); +#endif + } + + void FeldmanHashMapHdrTest::rcu_sht_hash128_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + typedef hash128::make hash; + typedef hash128::cmp compare; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 2); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + , co::hash< hash128::make > + , co::compare< hash128::cmp > + >::type + > map_type2; + test_rcu(4, 2); +#endif + } + + void FeldmanHashMapHdrTest::rcu_sht_nohash_5_3() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef cc::FeldmanHashMap< rcu_type, size_t, Item > map_type; + + test_rcu(5, 3); +#endif + } + + void FeldmanHashMapHdrTest::rcu_sht_stdhash_5_3() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + struct traits : public cc::feldman_hashmap::traits { + typedef std::hash hash; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + + test_rcu(5, 3); +#endif + } + + void FeldmanHashMapHdrTest::rcu_sht_nohash_5_3_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + typedef cds::backoff::empty back_off; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(5, 3); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + , co::back_off< cds::backoff::empty > + >::type + > map_type2; + test_rcu(5, 3); +#endif + } + + void FeldmanHashMapHdrTest::rcu_sht_stdhash_5_3_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + struct traits : public cc::feldman_hashmap::traits { + typedef cc::feldman_hashmap::stat<> stat; + typedef cds::backoff::empty back_off; + typedef std::hash hash; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(5, 3); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::stat< cc::feldman_hashmap::stat<>> + ,co::back_off< cds::backoff::empty > + ,co::hash< std::hash> + >::type + > map_type2; + test_rcu(5, 3); +#endif + } + + void FeldmanHashMapHdrTest::rcu_sht_hash128_4_3() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + struct traits : public cc::feldman_hashmap::traits { + typedef hash128::make hash; + typedef hash128::less less; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 3); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::hash< hash128::make > + , co::less< hash128::less > + >::type + > map_type2; + test_rcu(4, 3); +#endif + } + + void FeldmanHashMapHdrTest::rcu_sht_hash128_4_3_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + struct traits : public cc::feldman_hashmap::traits { + typedef hash128::make hash; + typedef hash128::less less; + typedef cc::feldman_hashmap::stat<> stat; + typedef co::v::sequential_consistent memory_model; + }; + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type; + test_rcu(4, 3); + + typedef cc::FeldmanHashMap< rcu_type, size_t, Item, + typename cc::feldman_hashmap::make_traits< + co::hash< hash128::make > + , co::less< hash128::less > + , co::stat< cc::feldman_hashmap::stat<>> + , co::memory_model< co::v::sequential_consistent > + >::type + > map_type2; + test_rcu(4, 3); +#endif + } + +} // namespace map diff --git a/tests/test-hdr/map/hdr_multilevel_hashmap.h b/tests/test-hdr/map/hdr_multilevel_hashmap.h deleted file mode 100644 index 8d0bf2c6..00000000 --- a/tests/test-hdr/map/hdr_multilevel_hashmap.h +++ /dev/null @@ -1,799 +0,0 @@ -//$$CDS-header$$ - -#ifndef CDSTEST_HDR_MULTILEVEL_HASHMAP_H -#define CDSTEST_HDR_MULTILEVEL_HASHMAP_H - -#include "cppunit/cppunit_proxy.h" - -// forward declaration -namespace cds { - namespace container {} - namespace opt {} -} - -namespace map { - namespace cc = cds::container; - namespace co = cds::opt; - - class MultiLevelHashMapHdrTest : public CppUnitMini::TestCase - { - struct Item - { - unsigned int nInsertCall; - unsigned int nFindCall; - unsigned int nEraseCall; - mutable unsigned int nIteratorCall; - - Item() - : nInsertCall(0) - , nFindCall(0) - , nEraseCall(0) - , nIteratorCall(0) - {} - - explicit Item( unsigned int n ) - : nInsertCall(n) - , nFindCall(0) - , nEraseCall(0) - , nIteratorCall(0) - {} - }; - - struct hash128 - { - size_t lo; - size_t hi; - - hash128() {} - hash128(size_t l, size_t h) : lo(l), hi(h) {} - hash128( hash128 const& h) : lo(h.lo), hi(h.hi) {} - - 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; - } - }; - - friend bool operator==( hash128 const& lhs, hash128 const& rhs ) - { - return cmp()( lhs, rhs ) == 0; - } - friend bool operator!=(hash128 const& lhs, hash128 const& rhs) - { - return !( lhs == rhs ); - } - }; - - template - void test_hp( size_t nHeadBits, size_t nArrayBits ) - { - typedef typename Map::hash_type hash_type; - typedef typename Map::key_type key_type; - typedef typename Map::mapped_type mapped_type; - typedef typename Map::value_type value_type; - typedef typename Map::guarded_ptr guarded_ptr; - - size_t const capacity = 1000; - - Map m( nHeadBits, nArrayBits ); - CPPUNIT_MSG("Array size: head=" << m.head_size() << ", array_node=" << m.array_node_size()); - //CPPUNIT_ASSERT(m.head_size() >= (size_t(1) << nHeadBits)); - //CPPUNIT_ASSERT(m.array_node_size() == (size_t(1) << nArrayBits)); - - CPPUNIT_ASSERT(m.empty()); - CPPUNIT_ASSERT(m.size() == 0); - - // insert( key )/update()/get()/find() - for ( size_t i = 0; i < capacity; ++i ) { - size_t key = i * 57; - CPPUNIT_ASSERT(!m.contains( key )) - CPPUNIT_ASSERT(m.insert( key )); - CPPUNIT_ASSERT(m.contains( key )); - CPPUNIT_ASSERT(m.size() == i + 1); - - auto ret = m.update(key, [] ( value_type& v, value_type * old ) { - CPPUNIT_ASSERT_CURRENT( old != nullptr ); - ++v.second.nInsertCall; - }, false ); - CPPUNIT_ASSERT( ret.first ); - CPPUNIT_ASSERT( !ret.second ); - - CPPUNIT_ASSERT(m.find(key, [](value_type& v) { ++v.second.nFindCall;} )); - - guarded_ptr gp{ m.get( key ) }; - CPPUNIT_ASSERT( gp ); - CPPUNIT_ASSERT( gp->first == key ); - CPPUNIT_ASSERT( gp->second.nInsertCall == 1 ); - CPPUNIT_ASSERT( gp->second.nFindCall == 1 ); - } - CPPUNIT_ASSERT(!m.empty()); - CPPUNIT_ASSERT(m.size() == capacity); - - // iterator test - size_t nCount = 0; - for ( auto it = m.begin(), itEnd = m.end(); it != itEnd; ++it ) { - CPPUNIT_ASSERT( it->second.nIteratorCall == 0 ); - CPPUNIT_ASSERT( it->second.nInsertCall == 1 ); - CPPUNIT_ASSERT( (*it).second.nFindCall == 1 ); - it->second.nIteratorCall += 1; - ++nCount; - } - CPPUNIT_ASSERT( nCount == capacity ); - - nCount = 0; - for ( auto it = m.rbegin(), itEnd = m.rend(); it != itEnd; ++it ) { - CPPUNIT_ASSERT( it->second.nInsertCall == 1 ); - CPPUNIT_ASSERT( (*it).second.nFindCall == 1 ); - CPPUNIT_ASSERT( it->second.nIteratorCall == 1 ); - (*it).second.nIteratorCall += 1; - ++nCount; - } - CPPUNIT_ASSERT( nCount == capacity ); - - nCount = 0; - for ( auto it = m.cbegin(), itEnd = m.cend(); it != itEnd; ++it ) { - CPPUNIT_ASSERT( it->second.nInsertCall == 1 ); - CPPUNIT_ASSERT( (*it).second.nFindCall == 1 ); - CPPUNIT_ASSERT( it->second.nIteratorCall == 2 ); - (*it).second.nIteratorCall += 1; - ++nCount; - } - CPPUNIT_ASSERT( nCount == capacity ); - - nCount = 0; - for ( auto it = m.crbegin(), itEnd = m.crend(); it != itEnd; ++it ) { - CPPUNIT_ASSERT( it->second.nInsertCall == 1 ); - CPPUNIT_ASSERT( (*it).second.nFindCall == 1 ); - CPPUNIT_ASSERT( it->second.nIteratorCall == 3 ); - (*it).second.nIteratorCall += 1; - ++nCount; - } - CPPUNIT_ASSERT( nCount == capacity ); - - // find - for ( size_t i = 0; i < capacity; i++ ) { - size_t key = i * 57; - CPPUNIT_ASSERT( m.find( key, [key]( value_type& v ) { - CPPUNIT_ASSERT_CURRENT( v.first == key ); - CPPUNIT_ASSERT_CURRENT( v.second.nInsertCall == 1 ); - CPPUNIT_ASSERT_CURRENT( v.second.nFindCall == 1 ); - CPPUNIT_ASSERT_CURRENT( v.second.nIteratorCall == 4 ); - })); - } - - // erase - for ( size_t i = capacity; i > 0; --i ) { - size_t key = (i -1) * 57; - guarded_ptr gp = m.get( key ); - CPPUNIT_ASSERT( gp ); - CPPUNIT_ASSERT( gp->first == key ); - CPPUNIT_ASSERT( gp->second.nInsertCall == 1 ); - CPPUNIT_ASSERT( gp->second.nFindCall == 1 ); - CPPUNIT_ASSERT( (*gp).second.nIteratorCall == 4 ); - - CPPUNIT_ASSERT(m.erase( key )); - - gp = m.get( key ); - CPPUNIT_ASSERT( !gp ); - CPPUNIT_ASSERT(!m.contains( key )); - } - CPPUNIT_ASSERT( m.empty()); - CPPUNIT_ASSERT(m.size() == 0); - - // Iterators on empty map - CPPUNIT_ASSERT(m.begin() == m.end()); - CPPUNIT_ASSERT(m.cbegin() == m.cend()); - CPPUNIT_ASSERT(m.rbegin() == m.rend()); - CPPUNIT_ASSERT(m.crbegin() == m.crend()); - - // insert( key, val ) - for ( size_t i = 0; i < capacity; ++i ) { - CPPUNIT_ASSERT(!m.contains(i)); - CPPUNIT_ASSERT(m.insert( i, (unsigned int) i * 100)); - CPPUNIT_ASSERT( m.contains(i)); - CPPUNIT_ASSERT( m.find( i, [i]( value_type& v ) { - CPPUNIT_ASSERT_CURRENT( v.first == i ); - CPPUNIT_ASSERT_CURRENT( v.second.nInsertCall == i * 100 ); - })); - } - CPPUNIT_ASSERT( !m.empty()); - CPPUNIT_ASSERT(m.size() == capacity); - - // erase( key, func ) - for ( size_t i = 0; i < capacity; ++i ) { - CPPUNIT_ASSERT( m.contains(i)); - CPPUNIT_ASSERT( m.erase( i, [i]( value_type& v ) { - CPPUNIT_ASSERT_CURRENT( v.first == i ); - CPPUNIT_ASSERT_CURRENT( v.second.nInsertCall == i * 100 ); - v.second.nInsertCall = 0; - })); - } - CPPUNIT_ASSERT( m.empty()); - CPPUNIT_ASSERT(m.size() == 0 ); - - // insert_with - for ( size_t i = 0; i < capacity; ++i ) { - size_t key = i * 121; - CPPUNIT_ASSERT(!m.contains(key)); - CPPUNIT_ASSERT( m.insert_with( key, [key]( value_type& v ) { - CPPUNIT_ASSERT_CURRENT( v.first == key ); - CPPUNIT_ASSERT_CURRENT( v.second.nInsertCall == 0 ); - v.second.nInsertCall = decltype(v.second.nInsertCall)( key ); - })); - CPPUNIT_ASSERT(m.find(key, [key] (value_type& v ) { - CPPUNIT_ASSERT_CURRENT( v.first == key ); - CPPUNIT_ASSERT_CURRENT( v.second.nInsertCall == key ); - })); - CPPUNIT_ASSERT(m.size() == i + 1); - } - CPPUNIT_ASSERT( !m.empty()); - CPPUNIT_ASSERT(m.size() == capacity); - - nCount = 0; - for ( auto it = m.begin(), itEnd = m.end(); it != itEnd; ++it ) { - CPPUNIT_ASSERT( it->first == it->second.nInsertCall ); - CPPUNIT_ASSERT( it->second.nIteratorCall == 0 ); - it->second.nIteratorCall += 1; - ++nCount; - } - CPPUNIT_ASSERT( nCount == capacity ); - - nCount = 0; - for ( auto it = m.rbegin(), itEnd = m.rend(); it != itEnd; ++it ) { - CPPUNIT_ASSERT( it->first == it->second.nInsertCall ); - CPPUNIT_ASSERT( it->second.nIteratorCall == 1 ); - it->second.nIteratorCall += 1; - ++nCount; - } - CPPUNIT_ASSERT( nCount == capacity ); - - // erase_at( iterator ) - nCount = 0; - for ( auto it = m.begin(), itEnd = m.end(); it != itEnd; ++it ) { - CPPUNIT_ASSERT( it->first == it->second.nInsertCall ); - CPPUNIT_ASSERT( it->second.nIteratorCall == 2 ); - CPPUNIT_ASSERT(m.erase_at( it )); - ++nCount; - CPPUNIT_ASSERT(!m.contains( it->first )); - } - CPPUNIT_ASSERT( nCount == capacity ); - CPPUNIT_ASSERT( m.empty()); - CPPUNIT_ASSERT(m.size() == 0 ); - - // emplace - for ( size_t i = 0; i < capacity; ++i ) { - size_t key = i * 1023; - CPPUNIT_ASSERT(!m.contains(key)); - CPPUNIT_ASSERT( m.emplace( key, (unsigned int) i )); - CPPUNIT_ASSERT(m.find(key, [key] (value_type& v ) { - CPPUNIT_ASSERT_CURRENT( v.first == key ); - CPPUNIT_ASSERT_CURRENT( v.second.nInsertCall * 1023 == key ); - })); - CPPUNIT_ASSERT(m.size() == i + 1); - } - CPPUNIT_ASSERT( !m.empty()); - CPPUNIT_ASSERT(m.size() == capacity); - - // erase_at( reverse_iterator ) - nCount = 0; - for ( auto it = m.rbegin(), itEnd = m.rend(); it != itEnd; ++it ) { - CPPUNIT_ASSERT( it->first == it->second.nInsertCall * 1023 ); - CPPUNIT_ASSERT(m.erase_at( it )); - ++nCount; - CPPUNIT_ASSERT(!m.contains( it->first )); - } - CPPUNIT_ASSERT( nCount == capacity ); - CPPUNIT_ASSERT( m.empty()); - CPPUNIT_ASSERT(m.size() == 0 ); - - - // extract - for ( size_t i = 0; i < capacity; ++i ) { - size_t key = i * 711; - CPPUNIT_ASSERT(!m.contains(key)); - auto ret = m.update( key, [i]( value_type& v, value_type * old ) { - CPPUNIT_ASSERT_CURRENT( old == nullptr ); - v.second.nInsertCall = (unsigned int) i; - }); - CPPUNIT_ASSERT( ret.first ); - CPPUNIT_ASSERT( ret.second ); - CPPUNIT_ASSERT(m.find(key, [i, key] (value_type& v ) { - CPPUNIT_ASSERT_CURRENT( v.first == key ); - CPPUNIT_ASSERT_CURRENT( v.second.nInsertCall == i ); - })); - CPPUNIT_ASSERT(m.size() == i + 1); - } - CPPUNIT_ASSERT( !m.empty()); - CPPUNIT_ASSERT(m.size() == capacity); - - for ( size_t i = capacity; i > 0; --i ) { - size_t key = (i-1) * 711; - guarded_ptr gp{ m.extract(key) }; - CPPUNIT_ASSERT( gp ); - CPPUNIT_ASSERT( gp->first == key ); - CPPUNIT_ASSERT((*gp).second.nInsertCall == i - 1 ); - gp = m.extract(key); - CPPUNIT_ASSERT( !gp ); - } - CPPUNIT_ASSERT( m.empty()); - CPPUNIT_ASSERT(m.size() == 0 ); - - // clear - for ( size_t i = 0; i < capacity; ++i ) { - CPPUNIT_ASSERT(!m.contains( i )) - CPPUNIT_ASSERT(m.insert( i )); - CPPUNIT_ASSERT(m.contains( i )); - CPPUNIT_ASSERT(m.size() == i + 1); - } - CPPUNIT_ASSERT( !m.empty()); - CPPUNIT_ASSERT(m.size() == capacity ); - - m.clear(); - CPPUNIT_ASSERT( m.empty()); - CPPUNIT_ASSERT(m.size() == 0 ); - - - CPPUNIT_MSG( m.statistics() ); - } - - template - void test_rcu(size_t nHeadBits, size_t nArrayBits) - { - typedef typename Map::hash_type hash_type; - typedef typename Map::key_type key_type; - typedef typename Map::mapped_type mapped_type; - typedef typename Map::value_type value_type; - typedef typename Map::exempt_ptr exempt_ptr; - typedef typename Map::rcu_lock rcu_lock; - - size_t const capacity = 1000; - - Map m(nHeadBits, nArrayBits); - CPPUNIT_MSG("Array size: head=" << m.head_size() << ", array_node=" << m.array_node_size()); - CPPUNIT_ASSERT(m.head_size() >= (size_t(1) << nHeadBits)); - CPPUNIT_ASSERT(m.array_node_size() == (size_t(1) << nArrayBits)); - - CPPUNIT_ASSERT(m.empty()); - CPPUNIT_ASSERT(m.size() == 0); - - // insert( key )/update()/get()/find() - for (size_t i = 0; i < capacity; ++i) { - size_t key = i * 57; - CPPUNIT_ASSERT(!m.contains(key)) - CPPUNIT_ASSERT(m.insert(key)); - CPPUNIT_ASSERT(m.contains(key)); - CPPUNIT_ASSERT(m.size() == i + 1); - - auto ret = m.update(key, [](value_type& v, value_type * old) { - CPPUNIT_ASSERT_CURRENT(old != nullptr); - ++v.second.nInsertCall; - }, false); - CPPUNIT_ASSERT(ret.first); - CPPUNIT_ASSERT(!ret.second); - - CPPUNIT_ASSERT(m.find(key, [](value_type& v) { ++v.second.nFindCall;})); - - { - rcu_lock l; - value_type* p{ m.get(key) }; - CPPUNIT_ASSERT(p); - CPPUNIT_ASSERT(p->first == key); - CPPUNIT_ASSERT(p->second.nInsertCall == 1); - CPPUNIT_ASSERT(p->second.nFindCall == 1); - } - } - CPPUNIT_ASSERT(!m.empty()); - CPPUNIT_ASSERT(m.size() == capacity); - - // iterator test - size_t nCount = 0; - { - rcu_lock l; - for (auto it = m.begin(), itEnd = m.end(); it != itEnd; ++it) { - CPPUNIT_ASSERT(it->second.nIteratorCall == 0); - CPPUNIT_ASSERT(it->second.nInsertCall == 1); - CPPUNIT_ASSERT((*it).second.nFindCall == 1); - it->second.nIteratorCall += 1; - ++nCount; - } - } - CPPUNIT_ASSERT(nCount == capacity); - - nCount = 0; - { - rcu_lock l; - for (auto it = m.rbegin(), itEnd = m.rend(); it != itEnd; ++it) { - CPPUNIT_ASSERT(it->second.nInsertCall == 1); - CPPUNIT_ASSERT((*it).second.nFindCall == 1); - CPPUNIT_ASSERT(it->second.nIteratorCall == 1); - (*it).second.nIteratorCall += 1; - ++nCount; - } - } - CPPUNIT_ASSERT(nCount == capacity); - - nCount = 0; - { - rcu_lock l; - for (auto it = m.cbegin(), itEnd = m.cend(); it != itEnd; ++it) { - CPPUNIT_ASSERT(it->second.nInsertCall == 1); - CPPUNIT_ASSERT((*it).second.nFindCall == 1); - CPPUNIT_ASSERT(it->second.nIteratorCall == 2); - (*it).second.nIteratorCall += 1; - ++nCount; - } - } - CPPUNIT_ASSERT(nCount == capacity); - - nCount = 0; - { - rcu_lock l; - for (auto it = m.crbegin(), itEnd = m.crend(); it != itEnd; ++it) { - CPPUNIT_ASSERT(it->second.nInsertCall == 1); - CPPUNIT_ASSERT((*it).second.nFindCall == 1); - CPPUNIT_ASSERT(it->second.nIteratorCall == 3); - (*it).second.nIteratorCall += 1; - ++nCount; - } - } - CPPUNIT_ASSERT(nCount == capacity); - - // find - for (size_t i = 0; i < capacity; i++) { - size_t key = i * 57; - CPPUNIT_ASSERT(m.find(key, [key](value_type& v) { - CPPUNIT_ASSERT_CURRENT(v.first == key); - CPPUNIT_ASSERT_CURRENT(v.second.nInsertCall == 1); - CPPUNIT_ASSERT_CURRENT(v.second.nFindCall == 1); - CPPUNIT_ASSERT_CURRENT(v.second.nIteratorCall == 4); - })); - } - - // erase - for (size_t i = capacity; i > 0; --i) { - size_t key = (i - 1) * 57; - { - rcu_lock l; - value_type* p = m.get(key); - CPPUNIT_ASSERT(p); - CPPUNIT_ASSERT(p->first == key); - CPPUNIT_ASSERT(p->second.nInsertCall == 1); - CPPUNIT_ASSERT(p->second.nFindCall == 1); - CPPUNIT_ASSERT(p->second.nIteratorCall == 4); - } - - CPPUNIT_ASSERT(m.erase(key)); - - { - rcu_lock l; - value_type* p = m.get(key); - CPPUNIT_ASSERT(!p); - } - CPPUNIT_ASSERT(!m.contains(key)); - } - CPPUNIT_ASSERT(m.empty()); - CPPUNIT_ASSERT(m.size() == 0); - - // Iterators on empty map - { - rcu_lock l; - CPPUNIT_ASSERT(m.begin() == m.end()); - CPPUNIT_ASSERT(m.cbegin() == m.cend()); - CPPUNIT_ASSERT(m.rbegin() == m.rend()); - CPPUNIT_ASSERT(m.crbegin() == m.crend()); - } - - // insert( key, val ) - for (size_t i = 0; i < capacity; ++i) { - CPPUNIT_ASSERT(!m.contains(i)); - CPPUNIT_ASSERT(m.insert(i, (unsigned int)i * 100)); - CPPUNIT_ASSERT(m.contains(i)); - CPPUNIT_ASSERT(m.find(i, [i](value_type& v) { - CPPUNIT_ASSERT_CURRENT(v.first == i); - CPPUNIT_ASSERT_CURRENT(v.second.nInsertCall == i * 100); - })); - } - CPPUNIT_ASSERT(!m.empty()); - CPPUNIT_ASSERT(m.size() == capacity); - - // erase( key, func ) - for (size_t i = 0; i < capacity; ++i) { - CPPUNIT_ASSERT(m.contains(i)); - CPPUNIT_ASSERT(m.erase(i, [i](value_type& v) { - CPPUNIT_ASSERT_CURRENT(v.first == i); - CPPUNIT_ASSERT_CURRENT(v.second.nInsertCall == i * 100); - v.second.nInsertCall = 0; - })); - } - CPPUNIT_ASSERT(m.empty()); - CPPUNIT_ASSERT(m.size() == 0); - - // insert_with - for (size_t i = 0; i < capacity; ++i) { - size_t key = i * 121; - CPPUNIT_ASSERT(!m.contains(key)); - CPPUNIT_ASSERT(m.insert_with(key, [key](value_type& v) { - CPPUNIT_ASSERT_CURRENT(v.first == key); - CPPUNIT_ASSERT_CURRENT(v.second.nInsertCall == 0); - v.second.nInsertCall = decltype(v.second.nInsertCall)(key); - })); - CPPUNIT_ASSERT(m.find(key, [key](value_type& v) { - CPPUNIT_ASSERT_CURRENT(v.first == key); - CPPUNIT_ASSERT_CURRENT(v.second.nInsertCall == key); - })); - CPPUNIT_ASSERT(m.size() == i + 1); - } - CPPUNIT_ASSERT(!m.empty()); - CPPUNIT_ASSERT(m.size() == capacity); - - nCount = 0; - { - rcu_lock l; - for (auto it = m.begin(), itEnd = m.end(); it != itEnd; ++it) { - CPPUNIT_ASSERT(it->first == it->second.nInsertCall); - CPPUNIT_ASSERT(it->second.nIteratorCall == 0); - it->second.nIteratorCall += 1; - ++nCount; - } - } - CPPUNIT_ASSERT(nCount == capacity); - - nCount = 0; - { - rcu_lock l; - for (auto it = m.rbegin(), itEnd = m.rend(); it != itEnd; ++it) { - CPPUNIT_ASSERT(it->first == it->second.nInsertCall); - CPPUNIT_ASSERT(it->second.nIteratorCall == 1); - it->second.nIteratorCall += 1; - ++nCount; - } - } - CPPUNIT_ASSERT(nCount == capacity); - - // clear() - m.clear(); - CPPUNIT_ASSERT(m.empty()); - CPPUNIT_ASSERT(m.size() == 0); - - // emplace - for (size_t i = 0; i < capacity; ++i) { - size_t key = i * 1023; - CPPUNIT_ASSERT(!m.contains(key)); - CPPUNIT_ASSERT(m.emplace(key, static_cast(i))); - CPPUNIT_ASSERT(m.find(key, [key](value_type& v) { - CPPUNIT_ASSERT_CURRENT(v.first == key); - CPPUNIT_ASSERT_CURRENT(v.second.nInsertCall * 1023 == key); - })); - CPPUNIT_ASSERT(m.size() == i + 1); - } - CPPUNIT_ASSERT(!m.empty()); - CPPUNIT_ASSERT(m.size() == capacity); - - // extract - for (size_t i = capacity; i > 0; --i) { - size_t key = (i - 1) * 1023; - exempt_ptr xp{ m.extract(key) }; - CPPUNIT_ASSERT(xp); - CPPUNIT_ASSERT(xp->first == key); - CPPUNIT_ASSERT((*xp).second.nInsertCall == static_cast(i - 1)); - xp = m.extract(key); - CPPUNIT_ASSERT(!xp); - } - CPPUNIT_ASSERT(m.empty()); - CPPUNIT_ASSERT(m.size() == 0); - - CPPUNIT_MSG(m.statistics()); - } - - void hp_nohash(); - void hp_nohash_stat(); - void hp_nohash_5_3(); - void hp_nohash_5_3_stat(); - void hp_stdhash(); - 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_nohash(); - void dhp_nohash_stat(); - void dhp_nohash_5_3(); - void dhp_nohash_5_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(); - - void rcu_gpb_nohash(); - void rcu_gpb_nohash_stat(); - void rcu_gpb_nohash_5_3(); - void rcu_gpb_nohash_5_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_gpi_nohash(); - void rcu_gpi_nohash_stat(); - void rcu_gpi_nohash_5_3(); - void rcu_gpi_nohash_5_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_gpt_nohash(); - void rcu_gpt_nohash_stat(); - void rcu_gpt_nohash_5_3(); - void rcu_gpt_nohash_5_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_nohash(); - void rcu_shb_nohash_stat(); - void rcu_shb_nohash_5_3(); - void rcu_shb_nohash_5_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_nohash(); - void rcu_sht_nohash_stat(); - void rcu_sht_nohash_5_3(); - void rcu_sht_nohash_5_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(MultiLevelHashMapHdrTest) - CPPUNIT_TEST(hp_nohash) - CPPUNIT_TEST(hp_nohash_stat) - CPPUNIT_TEST(hp_nohash_5_3) - CPPUNIT_TEST(hp_nohash_5_3_stat) - 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_nohash) - CPPUNIT_TEST(dhp_nohash_stat) - CPPUNIT_TEST(dhp_nohash_5_3) - CPPUNIT_TEST(dhp_nohash_5_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(rcu_gpb_nohash) - CPPUNIT_TEST(rcu_gpb_nohash_stat) - CPPUNIT_TEST(rcu_gpb_nohash_5_3) - CPPUNIT_TEST(rcu_gpb_nohash_5_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_gpi_nohash) - CPPUNIT_TEST(rcu_gpi_nohash_stat) - CPPUNIT_TEST(rcu_gpi_nohash_5_3) - CPPUNIT_TEST(rcu_gpi_nohash_5_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_gpt_nohash) - CPPUNIT_TEST(rcu_gpt_nohash_stat) - CPPUNIT_TEST(rcu_gpt_nohash_5_3) - CPPUNIT_TEST(rcu_gpt_nohash_5_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_nohash) - CPPUNIT_TEST(rcu_shb_nohash_stat) - CPPUNIT_TEST(rcu_shb_nohash_5_3) - CPPUNIT_TEST(rcu_shb_nohash_5_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_nohash) - CPPUNIT_TEST(rcu_sht_nohash_stat) - CPPUNIT_TEST(rcu_sht_nohash_5_3) - CPPUNIT_TEST(rcu_sht_nohash_5_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() - - }; - -} // namespace map - -#endif //#ifndef CDSTEST_HDR_MULTILEVEL_HASHMAP_H diff --git a/tests/test-hdr/map/hdr_multilevel_hashmap_dhp.cpp b/tests/test-hdr/map/hdr_multilevel_hashmap_dhp.cpp deleted file mode 100644 index 89e8e60f..00000000 --- a/tests/test-hdr/map/hdr_multilevel_hashmap_dhp.cpp +++ /dev/null @@ -1,198 +0,0 @@ -//$$CDS-header$$ - -#include "map/hdr_multilevel_hashmap.h" -#include -#include "unit/print_multilevel_hashset_stat.h" - -namespace map { - namespace { - typedef cds::gc::DHP gc_type; - } // namespace - - void MultiLevelHashMapHdrTest::dhp_nohash() - { - typedef cc::MultiLevelHashMap< gc_type, size_t, Item > map_type; - - test_hp(4, 2); - } - - void MultiLevelHashMapHdrTest::dhp_stdhash() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef std::hash hash; - }; - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type; - - test_hp(4, 2); - } - - void MultiLevelHashMapHdrTest::dhp_hash128() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef hash128::make hash; - typedef hash128::less less; - }; - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type; - test_hp(4, 2); - - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::hash< hash128::make > - , co::less< hash128::less > - >::type - > map_type2; - test_hp(4, 2); - } - - void MultiLevelHashMapHdrTest::dhp_nohash_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - }; - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type; - test_hp(4, 2); - - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - >::type - > map_type2; - test_hp(4, 2); - } - - void MultiLevelHashMapHdrTest::dhp_stdhash_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef std::hash hash; - typedef cc::multilevel_hashmap::stat<> stat; - }; - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type; - test_hp(4, 2); - - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - ,co::hash< std::hash> - >::type - > map_type2; - test_hp(4, 2); - } - - void MultiLevelHashMapHdrTest::dhp_hash128_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - typedef hash128::make hash; - typedef hash128::cmp compare; - }; - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type; - test_hp(4, 2); - - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - , co::hash< hash128::make > - , co::compare< hash128::cmp > - >::type - > map_type2; - test_hp(4, 2); - } - - void MultiLevelHashMapHdrTest::dhp_nohash_5_3() - { - typedef cc::MultiLevelHashMap< gc_type, size_t, Item > map_type; - - test_hp(5, 3); - } - - - void MultiLevelHashMapHdrTest::dhp_stdhash_5_3() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef std::hash hash; - }; - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type; - - test_hp(5, 3); - } - - void MultiLevelHashMapHdrTest::dhp_nohash_5_3_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - typedef cds::backoff::empty back_off; - }; - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type; - test_hp(5, 3); - - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - , co::back_off< cds::backoff::empty > - >::type - > map_type2; - test_hp(5, 3); - } - - void MultiLevelHashMapHdrTest::dhp_stdhash_5_3_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - typedef cds::backoff::empty back_off; - typedef std::hash hash; - }; - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type; - test_hp(5, 3); - - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - ,co::back_off< cds::backoff::empty > - ,co::hash< std::hash> - >::type - > map_type2; - test_hp(5, 3); - } - - void MultiLevelHashMapHdrTest::dhp_hash128_4_3() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef hash128::make hash; - typedef hash128::less less; - }; - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type; - test_hp(4, 3); - - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::hash< hash128::make > - , co::less< hash128::less > - >::type - > map_type2; - test_hp(4, 3); - } - - void MultiLevelHashMapHdrTest::dhp_hash128_4_3_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef hash128::make hash; - typedef hash128::less less; - typedef cc::multilevel_hashmap::stat<> stat; - typedef co::v::sequential_consistent memory_model; - }; - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type; - test_hp(4, 3); - - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::hash< hash128::make > - , co::less< hash128::less > - , co::stat< cc::multilevel_hashmap::stat<>> - , co::memory_model< co::v::sequential_consistent > - >::type - > map_type2; - test_hp(4, 3); - } -} // namespace map - -CPPUNIT_TEST_SUITE_REGISTRATION(map::MultiLevelHashMapHdrTest); diff --git a/tests/test-hdr/map/hdr_multilevel_hashmap_hp.cpp b/tests/test-hdr/map/hdr_multilevel_hashmap_hp.cpp deleted file mode 100644 index 8eca0d95..00000000 --- a/tests/test-hdr/map/hdr_multilevel_hashmap_hp.cpp +++ /dev/null @@ -1,198 +0,0 @@ -//$$CDS-header$$ - -#include "map/hdr_multilevel_hashmap.h" -#include -#include "unit/print_multilevel_hashset_stat.h" - -namespace map { - namespace { - typedef cds::gc::HP gc_type; - } // namespace - - void MultiLevelHashMapHdrTest::hp_nohash() - { - typedef cc::MultiLevelHashMap< gc_type, size_t, Item > map_type; - - test_hp(4, 2); - } - - void MultiLevelHashMapHdrTest::hp_stdhash() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef std::hash hash; - }; - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type; - - test_hp(4, 2); - } - - void MultiLevelHashMapHdrTest::hp_hash128() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef hash128::make hash; - typedef hash128::less less; - }; - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type; - test_hp(4, 2); - - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::hash< hash128::make > - , co::less< hash128::less > - >::type - > map_type2; - test_hp(4, 2); - } - - void MultiLevelHashMapHdrTest::hp_nohash_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - }; - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type; - test_hp(4, 2); - - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - >::type - > map_type2; - test_hp(4, 2); - } - - void MultiLevelHashMapHdrTest::hp_stdhash_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef std::hash hash; - typedef cc::multilevel_hashmap::stat<> stat; - }; - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type; - test_hp(4, 2); - - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - ,co::hash< std::hash> - >::type - > map_type2; - test_hp(4, 2); - } - - void MultiLevelHashMapHdrTest::hp_hash128_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - typedef hash128::make hash; - typedef hash128::cmp compare; - }; - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type; - test_hp(4, 2); - - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - , co::hash< hash128::make > - , co::compare< hash128::cmp > - >::type - > map_type2; - test_hp(4, 2); - } - - void MultiLevelHashMapHdrTest::hp_nohash_5_3() - { - typedef cc::MultiLevelHashMap< gc_type, size_t, Item > map_type; - - test_hp(5, 3); - } - - - void MultiLevelHashMapHdrTest::hp_stdhash_5_3() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef std::hash hash; - }; - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type; - - test_hp(5, 3); - } - - void MultiLevelHashMapHdrTest::hp_nohash_5_3_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - typedef cds::backoff::empty back_off; - }; - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type; - test_hp(5, 3); - - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - , co::back_off< cds::backoff::empty > - >::type - > map_type2; - test_hp(5, 3); - } - - void MultiLevelHashMapHdrTest::hp_stdhash_5_3_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - typedef cds::backoff::empty back_off; - typedef std::hash hash; - }; - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type; - test_hp(5, 3); - - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - ,co::back_off< cds::backoff::empty > - ,co::hash< std::hash> - >::type - > map_type2; - test_hp(5, 3); - } - - void MultiLevelHashMapHdrTest::hp_hash128_4_3() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef hash128::make hash; - typedef hash128::less less; - }; - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type; - test_hp(4, 3); - - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::hash< hash128::make > - , co::less< hash128::less > - >::type - > map_type2; - test_hp(4, 3); - } - - void MultiLevelHashMapHdrTest::hp_hash128_4_3_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef hash128::make hash; - typedef hash128::less less; - typedef cc::multilevel_hashmap::stat<> stat; - typedef co::v::sequential_consistent memory_model; - }; - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type; - test_hp(4, 3); - - typedef cc::MultiLevelHashMap< gc_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::hash< hash128::make > - , co::less< hash128::less > - , co::stat< cc::multilevel_hashmap::stat<>> - , co::memory_model< co::v::sequential_consistent > - >::type - > map_type2; - test_hp(4, 3); - } -} // namespace map - -CPPUNIT_TEST_SUITE_REGISTRATION(map::MultiLevelHashMapHdrTest); diff --git a/tests/test-hdr/map/hdr_multilevel_hashmap_rcu_gpb.cpp b/tests/test-hdr/map/hdr_multilevel_hashmap_rcu_gpb.cpp deleted file mode 100644 index 15d12185..00000000 --- a/tests/test-hdr/map/hdr_multilevel_hashmap_rcu_gpb.cpp +++ /dev/null @@ -1,197 +0,0 @@ -//$$CDS-header$$ - -#include "map/hdr_multilevel_hashmap.h" -#include -#include -#include "unit/print_multilevel_hashset_stat.h" - -namespace map { - namespace { - typedef cds::urcu::gc< cds::urcu::general_buffered<>> rcu_type; - } // namespace - - void MultiLevelHashMapHdrTest::rcu_gpb_nohash() - { - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item > map_type; - - test_rcu(4, 2); - } - - void MultiLevelHashMapHdrTest::rcu_gpb_stdhash() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef std::hash hash; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - - test_rcu(4, 2); - } - - void MultiLevelHashMapHdrTest::rcu_gpb_hash128() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef hash128::make hash; - typedef hash128::less less; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 2); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::hash< hash128::make > - , co::less< hash128::less > - >::type - > map_type2; - test_rcu(4, 2); - } - - void MultiLevelHashMapHdrTest::rcu_gpb_nohash_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 2); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - >::type - > map_type2; - test_rcu(4, 2); - } - - void MultiLevelHashMapHdrTest::rcu_gpb_stdhash_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef std::hash hash; - typedef cc::multilevel_hashmap::stat<> stat; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 2); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - ,co::hash> - >::type - > map_type2; - test_rcu(4, 2); - } - - void MultiLevelHashMapHdrTest::rcu_gpb_hash128_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - typedef hash128::make hash; - typedef hash128::cmp compare; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 2); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - , co::hash< hash128::make > - , co::compare< hash128::cmp > - >::type - > map_type2; - test_rcu(4, 2); - } - - void MultiLevelHashMapHdrTest::rcu_gpb_nohash_5_3() - { - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item > map_type; - - test_rcu(5, 3); - } - - void MultiLevelHashMapHdrTest::rcu_gpb_stdhash_5_3() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef std::hash hash; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - - test_rcu(5, 3); - } - - void MultiLevelHashMapHdrTest::rcu_gpb_nohash_5_3_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - typedef cds::backoff::empty back_off; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(5, 3); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - , co::back_off< cds::backoff::empty > - >::type - > map_type2; - test_rcu(5, 3); - } - - void MultiLevelHashMapHdrTest::rcu_gpb_stdhash_5_3_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - typedef cds::backoff::empty back_off; - typedef std::hash hash; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(5, 3); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - ,co::back_off< cds::backoff::empty > - ,co::hash< std::hash> - >::type - > map_type2; - test_rcu(5, 3); - } - - void MultiLevelHashMapHdrTest::rcu_gpb_hash128_4_3() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef hash128::make hash; - typedef hash128::less less; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 3); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::hash< hash128::make > - , co::less< hash128::less > - >::type - > map_type2; - test_rcu(4, 3); - } - - void MultiLevelHashMapHdrTest::rcu_gpb_hash128_4_3_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef hash128::make hash; - typedef hash128::less less; - typedef cc::multilevel_hashmap::stat<> stat; - typedef co::v::sequential_consistent memory_model; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 3); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::hash< hash128::make > - , co::less< hash128::less > - , co::stat< cc::multilevel_hashmap::stat<>> - , co::memory_model< co::v::sequential_consistent > - >::type - > map_type2; - test_rcu(4, 3); - } - -} // namespace map diff --git a/tests/test-hdr/map/hdr_multilevel_hashmap_rcu_gpi.cpp b/tests/test-hdr/map/hdr_multilevel_hashmap_rcu_gpi.cpp deleted file mode 100644 index 349c29de..00000000 --- a/tests/test-hdr/map/hdr_multilevel_hashmap_rcu_gpi.cpp +++ /dev/null @@ -1,197 +0,0 @@ -//$$CDS-header$$ - -#include "map/hdr_multilevel_hashmap.h" -#include -#include -#include "unit/print_multilevel_hashset_stat.h" - -namespace map { - namespace { - typedef cds::urcu::gc< cds::urcu::general_instant<>> rcu_type; - } // namespace - - void MultiLevelHashMapHdrTest::rcu_gpi_nohash() - { - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item > map_type; - - test_rcu(4, 2); - } - - void MultiLevelHashMapHdrTest::rcu_gpi_stdhash() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef std::hash hash; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - - test_rcu(4, 2); - } - - void MultiLevelHashMapHdrTest::rcu_gpi_hash128() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef hash128::make hash; - typedef hash128::less less; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 2); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::hash< hash128::make > - , co::less< hash128::less > - >::type - > map_type2; - test_rcu(4, 2); - } - - void MultiLevelHashMapHdrTest::rcu_gpi_nohash_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 2); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - >::type - > map_type2; - test_rcu(4, 2); - } - - void MultiLevelHashMapHdrTest::rcu_gpi_stdhash_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef std::hash hash; - typedef cc::multilevel_hashmap::stat<> stat; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 2); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - ,co::hash> - >::type - > map_type2; - test_rcu(4, 2); - } - - void MultiLevelHashMapHdrTest::rcu_gpi_hash128_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - typedef hash128::make hash; - typedef hash128::cmp compare; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 2); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - , co::hash< hash128::make > - , co::compare< hash128::cmp > - >::type - > map_type2; - test_rcu(4, 2); - } - - void MultiLevelHashMapHdrTest::rcu_gpi_nohash_5_3() - { - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item > map_type; - - test_rcu(5, 3); - } - - void MultiLevelHashMapHdrTest::rcu_gpi_stdhash_5_3() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef std::hash hash; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - - test_rcu(5, 3); - } - - void MultiLevelHashMapHdrTest::rcu_gpi_nohash_5_3_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - typedef cds::backoff::empty back_off; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(5, 3); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - , co::back_off< cds::backoff::empty > - >::type - > map_type2; - test_rcu(5, 3); - } - - void MultiLevelHashMapHdrTest::rcu_gpi_stdhash_5_3_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - typedef cds::backoff::empty back_off; - typedef std::hash hash; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(5, 3); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - ,co::back_off< cds::backoff::empty > - ,co::hash< std::hash> - >::type - > map_type2; - test_rcu(5, 3); - } - - void MultiLevelHashMapHdrTest::rcu_gpi_hash128_4_3() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef hash128::make hash; - typedef hash128::less less; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 3); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::hash< hash128::make > - , co::less< hash128::less > - >::type - > map_type2; - test_rcu(4, 3); - } - - void MultiLevelHashMapHdrTest::rcu_gpi_hash128_4_3_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef hash128::make hash; - typedef hash128::less less; - typedef cc::multilevel_hashmap::stat<> stat; - typedef co::v::sequential_consistent memory_model; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 3); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::hash< hash128::make > - , co::less< hash128::less > - , co::stat< cc::multilevel_hashmap::stat<>> - , co::memory_model< co::v::sequential_consistent > - >::type - > map_type2; - test_rcu(4, 3); - } - -} // namespace map diff --git a/tests/test-hdr/map/hdr_multilevel_hashmap_rcu_gpt.cpp b/tests/test-hdr/map/hdr_multilevel_hashmap_rcu_gpt.cpp deleted file mode 100644 index 155035c2..00000000 --- a/tests/test-hdr/map/hdr_multilevel_hashmap_rcu_gpt.cpp +++ /dev/null @@ -1,197 +0,0 @@ -//$$CDS-header$$ - -#include "map/hdr_multilevel_hashmap.h" -#include -#include -#include "unit/print_multilevel_hashset_stat.h" - -namespace map { - namespace { - typedef cds::urcu::gc< cds::urcu::general_threaded<>> rcu_type; - } // namespace - - void MultiLevelHashMapHdrTest::rcu_gpt_nohash() - { - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item > map_type; - - test_rcu(4, 2); - } - - void MultiLevelHashMapHdrTest::rcu_gpt_stdhash() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef std::hash hash; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - - test_rcu(4, 2); - } - - void MultiLevelHashMapHdrTest::rcu_gpt_hash128() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef hash128::make hash; - typedef hash128::less less; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 2); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::hash< hash128::make > - , co::less< hash128::less > - >::type - > map_type2; - test_rcu(4, 2); - } - - void MultiLevelHashMapHdrTest::rcu_gpt_nohash_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 2); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - >::type - > map_type2; - test_rcu(4, 2); - } - - void MultiLevelHashMapHdrTest::rcu_gpt_stdhash_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef std::hash hash; - typedef cc::multilevel_hashmap::stat<> stat; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 2); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - ,co::hash> - >::type - > map_type2; - test_rcu(4, 2); - } - - void MultiLevelHashMapHdrTest::rcu_gpt_hash128_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - typedef hash128::make hash; - typedef hash128::cmp compare; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 2); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - , co::hash< hash128::make > - , co::compare< hash128::cmp > - >::type - > map_type2; - test_rcu(4, 2); - } - - void MultiLevelHashMapHdrTest::rcu_gpt_nohash_5_3() - { - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item > map_type; - - test_rcu(5, 3); - } - - void MultiLevelHashMapHdrTest::rcu_gpt_stdhash_5_3() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef std::hash hash; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - - test_rcu(5, 3); - } - - void MultiLevelHashMapHdrTest::rcu_gpt_nohash_5_3_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - typedef cds::backoff::empty back_off; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(5, 3); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - , co::back_off< cds::backoff::empty > - >::type - > map_type2; - test_rcu(5, 3); - } - - void MultiLevelHashMapHdrTest::rcu_gpt_stdhash_5_3_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - typedef cds::backoff::empty back_off; - typedef std::hash hash; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(5, 3); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - ,co::back_off< cds::backoff::empty > - ,co::hash< std::hash> - >::type - > map_type2; - test_rcu(5, 3); - } - - void MultiLevelHashMapHdrTest::rcu_gpt_hash128_4_3() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef hash128::make hash; - typedef hash128::less less; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 3); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::hash< hash128::make > - , co::less< hash128::less > - >::type - > map_type2; - test_rcu(4, 3); - } - - void MultiLevelHashMapHdrTest::rcu_gpt_hash128_4_3_stat() - { - struct traits : public cc::multilevel_hashmap::traits { - typedef hash128::make hash; - typedef hash128::less less; - typedef cc::multilevel_hashmap::stat<> stat; - typedef co::v::sequential_consistent memory_model; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 3); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::hash< hash128::make > - , co::less< hash128::less > - , co::stat< cc::multilevel_hashmap::stat<>> - , co::memory_model< co::v::sequential_consistent > - >::type - > map_type2; - test_rcu(4, 3); - } - -} // namespace map diff --git a/tests/test-hdr/map/hdr_multilevel_hashmap_rcu_shb.cpp b/tests/test-hdr/map/hdr_multilevel_hashmap_rcu_shb.cpp deleted file mode 100644 index 5eb4de4a..00000000 --- a/tests/test-hdr/map/hdr_multilevel_hashmap_rcu_shb.cpp +++ /dev/null @@ -1,223 +0,0 @@ -//$$CDS-header$$ - -#include "map/hdr_multilevel_hashmap.h" -#include -#include -#include "unit/print_multilevel_hashset_stat.h" - -namespace map { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - namespace { - typedef cds::urcu::gc< cds::urcu::signal_buffered<>> rcu_type; - } // namespace -#endif - - void MultiLevelHashMapHdrTest::rcu_shb_nohash() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item > map_type; - - test_rcu(4, 2); -#endif - } - - void MultiLevelHashMapHdrTest::rcu_shb_stdhash() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - struct traits : public cc::multilevel_hashmap::traits { - typedef std::hash hash; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - - test_rcu(4, 2); -#endif - } - - void MultiLevelHashMapHdrTest::rcu_shb_hash128() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - struct traits : public cc::multilevel_hashmap::traits { - typedef hash128::make hash; - typedef hash128::less less; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 2); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::hash< hash128::make > - , co::less< hash128::less > - >::type - > map_type2; - test_rcu(4, 2); -#endif - } - - void MultiLevelHashMapHdrTest::rcu_shb_nohash_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 2); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - >::type - > map_type2; - test_rcu(4, 2); -#endif - } - - void MultiLevelHashMapHdrTest::rcu_shb_stdhash_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - struct traits : public cc::multilevel_hashmap::traits { - typedef std::hash hash; - typedef cc::multilevel_hashmap::stat<> stat; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 2); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - ,co::hash> - >::type - > map_type2; - test_rcu(4, 2); -#endif - } - - void MultiLevelHashMapHdrTest::rcu_shb_hash128_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - typedef hash128::make hash; - typedef hash128::cmp compare; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 2); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - , co::hash< hash128::make > - , co::compare< hash128::cmp > - >::type - > map_type2; - test_rcu(4, 2); -#endif - } - - void MultiLevelHashMapHdrTest::rcu_shb_nohash_5_3() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item > map_type; - - test_rcu(5, 3); -#endif - } - - void MultiLevelHashMapHdrTest::rcu_shb_stdhash_5_3() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - struct traits : public cc::multilevel_hashmap::traits { - typedef std::hash hash; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - - test_rcu(5, 3); -#endif - } - - void MultiLevelHashMapHdrTest::rcu_shb_nohash_5_3_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - typedef cds::backoff::empty back_off; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(5, 3); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - , co::back_off< cds::backoff::empty > - >::type - > map_type2; - test_rcu(5, 3); -#endif - } - - void MultiLevelHashMapHdrTest::rcu_shb_stdhash_5_3_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - typedef cds::backoff::empty back_off; - typedef std::hash hash; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(5, 3); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - ,co::back_off< cds::backoff::empty > - ,co::hash< std::hash> - >::type - > map_type2; - test_rcu(5, 3); -#endif - } - - void MultiLevelHashMapHdrTest::rcu_shb_hash128_4_3() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - struct traits : public cc::multilevel_hashmap::traits { - typedef hash128::make hash; - typedef hash128::less less; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 3); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::hash< hash128::make > - , co::less< hash128::less > - >::type - > map_type2; - test_rcu(4, 3); -#endif - } - - void MultiLevelHashMapHdrTest::rcu_shb_hash128_4_3_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - struct traits : public cc::multilevel_hashmap::traits { - typedef hash128::make hash; - typedef hash128::less less; - typedef cc::multilevel_hashmap::stat<> stat; - typedef co::v::sequential_consistent memory_model; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 3); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::hash< hash128::make > - , co::less< hash128::less > - , co::stat< cc::multilevel_hashmap::stat<>> - , co::memory_model< co::v::sequential_consistent > - >::type - > map_type2; - test_rcu(4, 3); -#endif - } - -} // namespace map diff --git a/tests/test-hdr/map/hdr_multilevel_hashmap_rcu_sht.cpp b/tests/test-hdr/map/hdr_multilevel_hashmap_rcu_sht.cpp deleted file mode 100644 index 91f3d555..00000000 --- a/tests/test-hdr/map/hdr_multilevel_hashmap_rcu_sht.cpp +++ /dev/null @@ -1,223 +0,0 @@ -//$$CDS-header$$ - -#include "map/hdr_multilevel_hashmap.h" -#include -#include -#include "unit/print_multilevel_hashset_stat.h" - -namespace map { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - namespace { - typedef cds::urcu::gc< cds::urcu::signal_threaded<>> rcu_type; - } // namespace -#endif - - void MultiLevelHashMapHdrTest::rcu_sht_nohash() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item > map_type; - - test_rcu(4, 2); -#endif - } - - void MultiLevelHashMapHdrTest::rcu_sht_stdhash() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - struct traits : public cc::multilevel_hashmap::traits { - typedef std::hash hash; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - - test_rcu(4, 2); -#endif - } - - void MultiLevelHashMapHdrTest::rcu_sht_hash128() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - struct traits : public cc::multilevel_hashmap::traits { - typedef hash128::make hash; - typedef hash128::less less; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 2); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::hash< hash128::make > - , co::less< hash128::less > - >::type - > map_type2; - test_rcu(4, 2); -#endif - } - - void MultiLevelHashMapHdrTest::rcu_sht_nohash_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 2); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - >::type - > map_type2; - test_rcu(4, 2); -#endif - } - - void MultiLevelHashMapHdrTest::rcu_sht_stdhash_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - struct traits : public cc::multilevel_hashmap::traits { - typedef std::hash hash; - typedef cc::multilevel_hashmap::stat<> stat; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 2); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - ,co::hash> - >::type - > map_type2; - test_rcu(4, 2); -#endif - } - - void MultiLevelHashMapHdrTest::rcu_sht_hash128_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - typedef hash128::make hash; - typedef hash128::cmp compare; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 2); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - , co::hash< hash128::make > - , co::compare< hash128::cmp > - >::type - > map_type2; - test_rcu(4, 2); -#endif - } - - void MultiLevelHashMapHdrTest::rcu_sht_nohash_5_3() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item > map_type; - - test_rcu(5, 3); -#endif - } - - void MultiLevelHashMapHdrTest::rcu_sht_stdhash_5_3() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - struct traits : public cc::multilevel_hashmap::traits { - typedef std::hash hash; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - - test_rcu(5, 3); -#endif - } - - void MultiLevelHashMapHdrTest::rcu_sht_nohash_5_3_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - typedef cds::backoff::empty back_off; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(5, 3); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - , co::back_off< cds::backoff::empty > - >::type - > map_type2; - test_rcu(5, 3); -#endif - } - - void MultiLevelHashMapHdrTest::rcu_sht_stdhash_5_3_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - struct traits : public cc::multilevel_hashmap::traits { - typedef cc::multilevel_hashmap::stat<> stat; - typedef cds::backoff::empty back_off; - typedef std::hash hash; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(5, 3); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::stat< cc::multilevel_hashmap::stat<>> - ,co::back_off< cds::backoff::empty > - ,co::hash< std::hash> - >::type - > map_type2; - test_rcu(5, 3); -#endif - } - - void MultiLevelHashMapHdrTest::rcu_sht_hash128_4_3() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - struct traits : public cc::multilevel_hashmap::traits { - typedef hash128::make hash; - typedef hash128::less less; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 3); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::hash< hash128::make > - , co::less< hash128::less > - >::type - > map_type2; - test_rcu(4, 3); -#endif - } - - void MultiLevelHashMapHdrTest::rcu_sht_hash128_4_3_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - struct traits : public cc::multilevel_hashmap::traits { - typedef hash128::make hash; - typedef hash128::less less; - typedef cc::multilevel_hashmap::stat<> stat; - typedef co::v::sequential_consistent memory_model; - }; - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type; - test_rcu(4, 3); - - typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, - typename cc::multilevel_hashmap::make_traits< - co::hash< hash128::make > - , co::less< hash128::less > - , co::stat< cc::multilevel_hashmap::stat<>> - , co::memory_model< co::v::sequential_consistent > - >::type - > map_type2; - test_rcu(4, 3); -#endif - } - -} // namespace map diff --git a/tests/test-hdr/set/hdr_feldman_hashset.h b/tests/test-hdr/set/hdr_feldman_hashset.h new file mode 100644 index 00000000..e2595706 --- /dev/null +++ b/tests/test-hdr/set/hdr_feldman_hashset.h @@ -0,0 +1,843 @@ +//$$CDS-header$$ + +#ifndef CDSTEST_HDR_FELDMAN_HASHSET_H +#define CDSTEST_HDR_FELDMAN_HASHSET_H + +#include "cppunit/cppunit_proxy.h" + +// forward declaration +namespace cds { + namespace container {} + namespace opt {} +} + +namespace set { + namespace cc = cds::container; + namespace co = cds::opt; + + class FeldmanHashSetHdrTest : public CppUnitMini::TestCase + { + template + struct Arg + { + size_t key; + Hash hash; + + Arg( size_t k, Hash const& h ) + : key( k ) + , hash( h ) + {} + }; + + template + struct Item + { + unsigned int nInsertCall; + unsigned int nFindCall; + unsigned int nEraseCall; + mutable unsigned int nIteratorCall; + Hash hash; + size_t key; + + Item( size_t k, Hash const& h ) + : nInsertCall(0) + , nFindCall(0) + , nEraseCall(0) + , nIteratorCall(0) + , hash( h ) + , key( k ) + {} + + explicit Item( Arg const& arg ) + : nInsertCall(0) + , nFindCall(0) + , nEraseCall(0) + , nIteratorCall(0) + , hash( arg.hash ) + , key( arg.key ) + {} + + Item( Item const& i ) + : nInsertCall(0) + , nFindCall(0) + , nEraseCall(0) + , nIteratorCall(0) + , hash( i.hash ) + , key( i.key ) + {} + }; + + template + struct get_hash + { + Hash const& operator()( Item const& i ) const + { + return i.hash; + } + }; + + template + struct get_key + { + Key operator()(Item const& i)const + { + return i.hash; + } + }; + + template + struct nohash { + Key operator()(Key k) const + { + return k; + } + }; + + struct hash128 + { + size_t lo; + size_t hi; + + hash128() {} + hash128(size_t l, size_t h) : lo(l), hi(h) {} + hash128( hash128 const& h) : lo(h.lo), hi(h.hi) {} + + 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; + } + }; + + friend bool operator==( hash128 const& lhs, hash128 const& rhs ) + { + return cmp()( lhs, rhs ) == 0; + } + friend bool operator!=(hash128 const& lhs, hash128 const& rhs) + { + return !( lhs == rhs ); + } + }; + + template + void test_hp( 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::guarded_ptr guarded_ptr; + + 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 ); + + guarded_ptr gp(s.get( h )); + CPPUNIT_ASSERT( gp ); + CPPUNIT_ASSERT( gp->nInsertCall == 1 ); + CPPUNIT_ASSERT( gp->key == i ); + CPPUNIT_ASSERT( gp->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 + 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 + for ( auto& el : s ) { + CPPUNIT_ASSERT( el.nInsertCall == 1 ); + CPPUNIT_ASSERT( el.nFindCall == 1 ); + el.nFindCall += 1; + } + + // iterator test + 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 + 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 + 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 + 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 )); + guarded_ptr gp(s.get( h )); + CPPUNIT_ASSERT( !gp ); + 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 ); + + gp = s.get( h ); + CPPUNIT_ASSERT( gp ); + CPPUNIT_ASSERT( gp->nInsertCall == 1 ); + CPPUNIT_ASSERT( gp->key == i ); + CPPUNIT_ASSERT( gp->hash == h ); + } + CPPUNIT_ASSERT( !s.empty() ); + CPPUNIT_ASSERT(s.size() == capacity ); + + // erase_at( iterator ) test + for ( auto it = s.begin(), itEnd = s.end(); it != itEnd; ++it ) { + CPPUNIT_ASSERT( s.erase_at( it )); + } + 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 ); + + // erase_at( reverse_iterator ) test + for ( auto it = s.rbegin(), itEnd = s.rend(); it != itEnd; ++it ) { + CPPUNIT_ASSERT( s.erase_at( it )); + } + CPPUNIT_ASSERT( s.empty() ); + CPPUNIT_ASSERT( s.size() == 0 ); + + // extract test + for ( size_t i = 0; i < capacity; ++i ) { + hash_type h = hasher(i); + CPPUNIT_ASSERT( !s.contains( h )); + CPPUNIT_ASSERT( s.emplace( arg_type( i, hasher(i) ))); + CPPUNIT_ASSERT(s.contains( h )); + + CPPUNIT_ASSERT( !s.empty() ); + CPPUNIT_ASSERT( s.size() == i + 1); + + CPPUNIT_ASSERT( !s.emplace( i, h )); + CPPUNIT_ASSERT( s.size() == i + 1); + } + CPPUNIT_ASSERT( !s.empty() ); + CPPUNIT_ASSERT(s.size() == capacity ); + + for ( size_t i = capacity; i != 0; --i ) { + CPPUNIT_ASSERT( !s.empty() ); + CPPUNIT_ASSERT( s.size() == i ); + + guarded_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))); + + gp = s.get(hasher(i-1)); + CPPUNIT_ASSERT( !gp ); + + CPPUNIT_ASSERT( s.size() == i - 1 ); + } + CPPUNIT_ASSERT( s.empty() ); + CPPUNIT_ASSERT(s.size() == 0 ); + + // clear test + for ( size_t i = 0; i < capacity; ++i ) { + hash_type h = hasher(i); + CPPUNIT_ASSERT( !s.contains( h )); + CPPUNIT_ASSERT( s.emplace( arg_type( i, hasher(i) ))); + CPPUNIT_ASSERT(s.contains( h )); + + CPPUNIT_ASSERT( !s.empty() ); + CPPUNIT_ASSERT( s.size() == i + 1); + + CPPUNIT_ASSERT( !s.emplace( i, h )); + CPPUNIT_ASSERT( s.size() == i + 1); + } + CPPUNIT_ASSERT( !s.empty() ); + CPPUNIT_ASSERT(s.size() == capacity ); + + s.clear(); + CPPUNIT_ASSERT( s.empty() ); + CPPUNIT_ASSERT(s.size() == 0 ); + + 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_nohash(); + void hp_nohash_stat(); + void hp_nohash_5_3(); + void hp_nohash_5_3_stat(); + void hp_stdhash(); + 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_nohash(); + void dhp_nohash_stat(); + void dhp_nohash_5_3(); + void dhp_nohash_5_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(); + + void rcu_gpi_nohash(); + void rcu_gpi_nohash_stat(); + void rcu_gpi_nohash_5_3(); + void rcu_gpi_nohash_5_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_nohash(); + void rcu_gpb_nohash_stat(); + void rcu_gpb_nohash_5_3(); + void rcu_gpb_nohash_5_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_nohash(); + void rcu_gpt_nohash_stat(); + void rcu_gpt_nohash_5_3(); + void rcu_gpt_nohash_5_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_nohash(); + void rcu_shb_nohash_stat(); + void rcu_shb_nohash_5_3(); + void rcu_shb_nohash_5_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_nohash(); + void rcu_sht_nohash_stat(); + void rcu_sht_nohash_5_3(); + void rcu_sht_nohash_5_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(FeldmanHashSetHdrTest) + CPPUNIT_TEST(hp_nohash) + CPPUNIT_TEST(hp_nohash_stat) + CPPUNIT_TEST(hp_nohash_5_3) + CPPUNIT_TEST(hp_nohash_5_3_stat) + 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_nohash) + CPPUNIT_TEST(dhp_nohash_stat) + CPPUNIT_TEST(dhp_nohash_5_3) + CPPUNIT_TEST(dhp_nohash_5_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(rcu_gpi_nohash) + CPPUNIT_TEST(rcu_gpi_nohash_stat) + CPPUNIT_TEST(rcu_gpi_nohash_5_3) + CPPUNIT_TEST(rcu_gpi_nohash_5_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_nohash) + CPPUNIT_TEST(rcu_gpb_nohash_stat) + CPPUNIT_TEST(rcu_gpb_nohash_5_3) + CPPUNIT_TEST(rcu_gpb_nohash_5_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_nohash) + CPPUNIT_TEST(rcu_gpt_nohash_stat) + CPPUNIT_TEST(rcu_gpt_nohash_5_3) + CPPUNIT_TEST(rcu_gpt_nohash_5_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_nohash) + CPPUNIT_TEST(rcu_shb_nohash_stat) + CPPUNIT_TEST(rcu_shb_nohash_5_3) + CPPUNIT_TEST(rcu_shb_nohash_5_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_nohash) + CPPUNIT_TEST(rcu_sht_nohash_stat) + CPPUNIT_TEST(rcu_sht_nohash_5_3) + CPPUNIT_TEST(rcu_sht_nohash_5_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() + }; + +} // namespace set + +#endif // #ifndef CDSTEST_HDR_FELDMAN_HASHSET_H diff --git a/tests/test-hdr/set/hdr_feldman_hashset_dhp.cpp b/tests/test-hdr/set/hdr_feldman_hashset_dhp.cpp new file mode 100644 index 00000000..ac1758d3 --- /dev/null +++ b/tests/test-hdr/set/hdr_feldman_hashset_dhp.cpp @@ -0,0 +1,299 @@ +//$$CDS-header$$ + +#include "set/hdr_feldman_hashset.h" +#include +#include "unit/print_feldman_hashset_stat.h" + +namespace set { + namespace { + typedef cds::gc::DHP gc_type; + } // namespace + + void FeldmanHashSetHdrTest::dhp_nohash() + { + typedef size_t key_type; + + struct traits : public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + }; + typedef cc::FeldmanHashSet< 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 cc::FeldmanHashSet< + gc_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + >::type + > set_type2; + test_hp>(4, 2); + } + + void FeldmanHashSetHdrTest::dhp_stdhash() + { + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + }; + typedef cc::FeldmanHashSet< 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 cc::FeldmanHashSet< + gc_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + >::type + > set_type2; + test_hp>(4, 2); + } + + void FeldmanHashSetHdrTest::dhp_hash128() + { + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef hash128::less less; + }; + typedef cc::FeldmanHashSet< 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 cc::FeldmanHashSet< + gc_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + , co::less< hash_type::less > + >::type + > set_type2; + test_hp(4, 2); + } + + void FeldmanHashSetHdrTest::dhp_nohash_stat() + { + typedef size_t key_type; + + struct traits : public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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 cc::FeldmanHashSet< + gc_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + , co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_hp>(4, 2); + } + + void FeldmanHashSetHdrTest::dhp_stdhash_stat() + { + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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 cc::FeldmanHashSet< + gc_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_hp>(4, 2); + } + + void FeldmanHashSetHdrTest::dhp_hash128_stat() + { + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef hash128::cmp compare; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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 cc::FeldmanHashSet< + gc_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::stat< cc::feldman_hashset::stat<>> + ,co::compare< hash128::cmp > + >::type + > set_type2; + test_hp(4, 2); + } + + void FeldmanHashSetHdrTest::dhp_nohash_5_3() + { + typedef size_t key_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + }; + typedef cc::FeldmanHashSet< 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 cc::FeldmanHashSet< + gc_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + >::type + > set_type2; + test_hp>(5, 3); + } + + void FeldmanHashSetHdrTest::dhp_stdhash_5_3() + { + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + }; + typedef cc::FeldmanHashSet< 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 cc::FeldmanHashSet< + gc_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + >::type + > set_type2; + test_hp>(5, 3); + } + + void FeldmanHashSetHdrTest::dhp_hash128_4_3() + { + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef co::v::sequential_consistent memory_model; + }; + typedef cc::FeldmanHashSet< 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 cc::FeldmanHashSet< + gc_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::memory_model< co::v::sequential_consistent > + >::type + > set_type2; + test_hp(4, 3); + } + + void FeldmanHashSetHdrTest::dhp_nohash_5_3_stat() + { + typedef size_t key_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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 cc::FeldmanHashSet< + gc_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + ,co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_hp>(5, 3); + } + + void FeldmanHashSetHdrTest::dhp_stdhash_5_3_stat() + { + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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 cc::FeldmanHashSet< + gc_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_hp>(5, 3); + } + + void FeldmanHashSetHdrTest::dhp_hash128_4_3_stat() + { + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + typedef hash128::less less; + typedef hash128::cmp compare; + }; + typedef cc::FeldmanHashSet< 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 cc::FeldmanHashSet< + gc_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + , co::stat< cc::feldman_hashset::stat<>> + , co::less< hash_type::less > + , co::compare< hash128::cmp > + >::type + > set_type2; + test_hp(4, 3); + } + + +} // namespace set diff --git a/tests/test-hdr/set/hdr_feldman_hashset_hp.cpp b/tests/test-hdr/set/hdr_feldman_hashset_hp.cpp new file mode 100644 index 00000000..724f9d8e --- /dev/null +++ b/tests/test-hdr/set/hdr_feldman_hashset_hp.cpp @@ -0,0 +1,301 @@ +//$$CDS-header$$ + +#include "set/hdr_feldman_hashset.h" +#include +#include "unit/print_feldman_hashset_stat.h" + +namespace set { + namespace { + typedef cds::gc::HP gc_type; + } // namespace + + void FeldmanHashSetHdrTest::hp_nohash() + { + typedef size_t key_type; + + struct traits : public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + }; + typedef cc::FeldmanHashSet< 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 cc::FeldmanHashSet< + gc_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + >::type + > set_type2; + test_hp>(4, 2); + } + + void FeldmanHashSetHdrTest::hp_stdhash() + { + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + }; + typedef cc::FeldmanHashSet< 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 cc::FeldmanHashSet< + gc_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + >::type + > set_type2; + test_hp>(4, 2); + } + + void FeldmanHashSetHdrTest::hp_hash128() + { + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef hash128::less less; + }; + typedef cc::FeldmanHashSet< 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 cc::FeldmanHashSet< + gc_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + , co::less< hash_type::less > + >::type + > set_type2; + test_hp(4, 2); + } + + void FeldmanHashSetHdrTest::hp_nohash_stat() + { + typedef size_t key_type; + + struct traits : public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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 cc::FeldmanHashSet< + gc_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + , co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_hp>(4, 2); + } + + void FeldmanHashSetHdrTest::hp_stdhash_stat() + { + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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 cc::FeldmanHashSet< + gc_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_hp>(4, 2); + } + + void FeldmanHashSetHdrTest::hp_hash128_stat() + { + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef hash128::cmp compare; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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 cc::FeldmanHashSet< + gc_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::stat< cc::feldman_hashset::stat<>> + ,co::compare< hash128::cmp > + >::type + > set_type2; + test_hp(4, 2); + } + + void FeldmanHashSetHdrTest::hp_nohash_5_3() + { + typedef size_t key_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + }; + typedef cc::FeldmanHashSet< 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 cc::FeldmanHashSet< + gc_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + >::type + > set_type2; + test_hp>(5, 3); + } + + void FeldmanHashSetHdrTest::hp_stdhash_5_3() + { + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + }; + typedef cc::FeldmanHashSet< 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 cc::FeldmanHashSet< + gc_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + >::type + > set_type2; + test_hp>(5, 3); + } + + void FeldmanHashSetHdrTest::hp_hash128_4_3() + { + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef co::v::sequential_consistent memory_model; + }; + typedef cc::FeldmanHashSet< 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 cc::FeldmanHashSet< + gc_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::memory_model< co::v::sequential_consistent > + >::type + > set_type2; + test_hp(4, 3); + } + + void FeldmanHashSetHdrTest::hp_nohash_5_3_stat() + { + typedef size_t key_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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 cc::FeldmanHashSet< + gc_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + ,co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_hp>(5, 3); + } + + void FeldmanHashSetHdrTest::hp_stdhash_5_3_stat() + { + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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 cc::FeldmanHashSet< + gc_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_hp>(5, 3); + } + + void FeldmanHashSetHdrTest::hp_hash128_4_3_stat() + { + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + typedef hash128::less less; + typedef hash128::cmp compare; + }; + typedef cc::FeldmanHashSet< 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 cc::FeldmanHashSet< + gc_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + , co::stat< cc::feldman_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::FeldmanHashSetHdrTest); diff --git a/tests/test-hdr/set/hdr_feldman_hashset_rcu_gpb.cpp b/tests/test-hdr/set/hdr_feldman_hashset_rcu_gpb.cpp new file mode 100644 index 00000000..0eacbc44 --- /dev/null +++ b/tests/test-hdr/set/hdr_feldman_hashset_rcu_gpb.cpp @@ -0,0 +1,300 @@ +//$$CDS-header$$ + +#include "set/hdr_feldman_hashset.h" +#include +#include +#include "unit/print_feldman_hashset_stat.h" + +namespace set { + namespace { + typedef cds::urcu::gc> rcu_type; + } // namespace + + void FeldmanHashSetHdrTest::rcu_gpb_nohash() + { + typedef size_t key_type; + + struct traits : public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + >::type + > set_type2; + test_rcu>(4, 2); + } + + void FeldmanHashSetHdrTest::rcu_gpb_stdhash() + { + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + >::type + > set_type2; + test_rcu>(4, 2); + } + + void FeldmanHashSetHdrTest::rcu_gpb_hash128() + { + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef hash128::less less; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + , co::less< hash_type::less > + >::type + > set_type2; + test_rcu(4, 2); + } + + void FeldmanHashSetHdrTest::rcu_gpb_nohash_stat() + { + typedef size_t key_type; + + struct traits : public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + , co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(4, 2); + } + + void FeldmanHashSetHdrTest::rcu_gpb_stdhash_stat() + { + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(4, 2); + } + + void FeldmanHashSetHdrTest::rcu_gpb_hash128_stat() + { + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef hash128::cmp compare; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::stat< cc::feldman_hashset::stat<>> + ,co::compare< hash128::cmp > + >::type + > set_type2; + test_rcu(4, 2); + } + + void FeldmanHashSetHdrTest::rcu_gpb_nohash_5_3() + { + typedef size_t key_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + >::type + > set_type2; + test_rcu>(5, 3); + } + + void FeldmanHashSetHdrTest::rcu_gpb_stdhash_5_3() + { + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + >::type + > set_type2; + test_rcu>(5, 3); + } + + void FeldmanHashSetHdrTest::rcu_gpb_hash128_4_3() + { + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef co::v::sequential_consistent memory_model; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::memory_model< co::v::sequential_consistent > + >::type + > set_type2; + test_rcu(4, 3); + } + + void FeldmanHashSetHdrTest::rcu_gpb_nohash_5_3_stat() + { + typedef size_t key_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + ,co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(5, 3); + } + + void FeldmanHashSetHdrTest::rcu_gpb_stdhash_5_3_stat() + { + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(5, 3); + } + + void FeldmanHashSetHdrTest::rcu_gpb_hash128_4_3_stat() + { + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + typedef hash128::less less; + typedef hash128::cmp compare; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + , co::stat< cc::feldman_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_feldman_hashset_rcu_gpi.cpp b/tests/test-hdr/set/hdr_feldman_hashset_rcu_gpi.cpp new file mode 100644 index 00000000..50b51b10 --- /dev/null +++ b/tests/test-hdr/set/hdr_feldman_hashset_rcu_gpi.cpp @@ -0,0 +1,300 @@ +//$$CDS-header$$ + +#include "set/hdr_feldman_hashset.h" +#include +#include +#include "unit/print_feldman_hashset_stat.h" + +namespace set { + namespace { + typedef cds::urcu::gc> rcu_type; + } // namespace + + void FeldmanHashSetHdrTest::rcu_gpi_nohash() + { + typedef size_t key_type; + + struct traits : public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + >::type + > set_type2; + test_rcu>(4, 2); + } + + void FeldmanHashSetHdrTest::rcu_gpi_stdhash() + { + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + >::type + > set_type2; + test_rcu>(4, 2); + } + + void FeldmanHashSetHdrTest::rcu_gpi_hash128() + { + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef hash128::less less; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + , co::less< hash_type::less > + >::type + > set_type2; + test_rcu(4, 2); + } + + void FeldmanHashSetHdrTest::rcu_gpi_nohash_stat() + { + typedef size_t key_type; + + struct traits : public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + , co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(4, 2); + } + + void FeldmanHashSetHdrTest::rcu_gpi_stdhash_stat() + { + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(4, 2); + } + + void FeldmanHashSetHdrTest::rcu_gpi_hash128_stat() + { + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef hash128::cmp compare; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::stat< cc::feldman_hashset::stat<>> + ,co::compare< hash128::cmp > + >::type + > set_type2; + test_rcu(4, 2); + } + + void FeldmanHashSetHdrTest::rcu_gpi_nohash_5_3() + { + typedef size_t key_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + >::type + > set_type2; + test_rcu>(5, 3); + } + + void FeldmanHashSetHdrTest::rcu_gpi_stdhash_5_3() + { + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + >::type + > set_type2; + test_rcu>(5, 3); + } + + void FeldmanHashSetHdrTest::rcu_gpi_hash128_4_3() + { + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef co::v::sequential_consistent memory_model; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::memory_model< co::v::sequential_consistent > + >::type + > set_type2; + test_rcu(4, 3); + } + + void FeldmanHashSetHdrTest::rcu_gpi_nohash_5_3_stat() + { + typedef size_t key_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + ,co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(5, 3); + } + + void FeldmanHashSetHdrTest::rcu_gpi_stdhash_5_3_stat() + { + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(5, 3); + } + + void FeldmanHashSetHdrTest::rcu_gpi_hash128_4_3_stat() + { + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + typedef hash128::less less; + typedef hash128::cmp compare; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + , co::stat< cc::feldman_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_feldman_hashset_rcu_gpt.cpp b/tests/test-hdr/set/hdr_feldman_hashset_rcu_gpt.cpp new file mode 100644 index 00000000..620a8ee7 --- /dev/null +++ b/tests/test-hdr/set/hdr_feldman_hashset_rcu_gpt.cpp @@ -0,0 +1,300 @@ +//$$CDS-header$$ + +#include "set/hdr_feldman_hashset.h" +#include +#include +#include "unit/print_feldman_hashset_stat.h" + +namespace set { + namespace { + typedef cds::urcu::gc> rcu_type; + } // namespace + + void FeldmanHashSetHdrTest::rcu_gpt_nohash() + { + typedef size_t key_type; + + struct traits : public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + >::type + > set_type2; + test_rcu>(4, 2); + } + + void FeldmanHashSetHdrTest::rcu_gpt_stdhash() + { + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + >::type + > set_type2; + test_rcu>(4, 2); + } + + void FeldmanHashSetHdrTest::rcu_gpt_hash128() + { + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef hash128::less less; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + , co::less< hash_type::less > + >::type + > set_type2; + test_rcu(4, 2); + } + + void FeldmanHashSetHdrTest::rcu_gpt_nohash_stat() + { + typedef size_t key_type; + + struct traits : public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + , co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(4, 2); + } + + void FeldmanHashSetHdrTest::rcu_gpt_stdhash_stat() + { + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(4, 2); + } + + void FeldmanHashSetHdrTest::rcu_gpt_hash128_stat() + { + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef hash128::cmp compare; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::stat< cc::feldman_hashset::stat<>> + ,co::compare< hash128::cmp > + >::type + > set_type2; + test_rcu(4, 2); + } + + void FeldmanHashSetHdrTest::rcu_gpt_nohash_5_3() + { + typedef size_t key_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + >::type + > set_type2; + test_rcu>(5, 3); + } + + void FeldmanHashSetHdrTest::rcu_gpt_stdhash_5_3() + { + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + >::type + > set_type2; + test_rcu>(5, 3); + } + + void FeldmanHashSetHdrTest::rcu_gpt_hash128_4_3() + { + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef co::v::sequential_consistent memory_model; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::memory_model< co::v::sequential_consistent > + >::type + > set_type2; + test_rcu(4, 3); + } + + void FeldmanHashSetHdrTest::rcu_gpt_nohash_5_3_stat() + { + typedef size_t key_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + ,co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(5, 3); + } + + void FeldmanHashSetHdrTest::rcu_gpt_stdhash_5_3_stat() + { + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(5, 3); + } + + void FeldmanHashSetHdrTest::rcu_gpt_hash128_4_3_stat() + { + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + typedef hash128::less less; + typedef hash128::cmp compare; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + , co::stat< cc::feldman_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_feldman_hashset_rcu_shb.cpp b/tests/test-hdr/set/hdr_feldman_hashset_rcu_shb.cpp new file mode 100644 index 00000000..67811de4 --- /dev/null +++ b/tests/test-hdr/set/hdr_feldman_hashset_rcu_shb.cpp @@ -0,0 +1,324 @@ +//$$CDS-header$$ + +#include "set/hdr_feldman_hashset.h" +#include +#include +#include "unit/print_feldman_hashset_stat.h" + +namespace set { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + namespace { + typedef cds::urcu::gc> rcu_type; + } // namespace +#endif + + void FeldmanHashSetHdrTest::rcu_shb_nohash() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t key_type; + + struct traits : public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + >::type + > set_type2; + test_rcu>(4, 2); +#endif + } + + void FeldmanHashSetHdrTest::rcu_shb_stdhash() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + >::type + > set_type2; + test_rcu>(4, 2); +#endif + } + + void FeldmanHashSetHdrTest::rcu_shb_hash128() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef hash128::less less; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + , co::less< hash_type::less > + >::type + > set_type2; + test_rcu(4, 2); +#endif + } + + void FeldmanHashSetHdrTest::rcu_shb_nohash_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t key_type; + + struct traits : public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + , co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(4, 2); +#endif + } + + void FeldmanHashSetHdrTest::rcu_shb_stdhash_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(4, 2); +#endif + } + + void FeldmanHashSetHdrTest::rcu_shb_hash128_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef hash128::cmp compare; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::stat< cc::feldman_hashset::stat<>> + ,co::compare< hash128::cmp > + >::type + > set_type2; + test_rcu(4, 2); +#endif + } + + void FeldmanHashSetHdrTest::rcu_shb_nohash_5_3() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t key_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + >::type + > set_type2; + test_rcu>(5, 3); +#endif + } + + void FeldmanHashSetHdrTest::rcu_shb_stdhash_5_3() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + >::type + > set_type2; + test_rcu>(5, 3); +#endif + } + + void FeldmanHashSetHdrTest::rcu_shb_hash128_4_3() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef co::v::sequential_consistent memory_model; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::memory_model< co::v::sequential_consistent > + >::type + > set_type2; + test_rcu(4, 3); +#endif + } + + void FeldmanHashSetHdrTest::rcu_shb_nohash_5_3_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t key_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + ,co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(5, 3); +#endif + } + + void FeldmanHashSetHdrTest::rcu_shb_stdhash_5_3_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(5, 3); +#endif + } + + void FeldmanHashSetHdrTest::rcu_shb_hash128_4_3_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + typedef hash128::less less; + typedef hash128::cmp compare; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + , co::stat< cc::feldman_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_feldman_hashset_rcu_sht.cpp b/tests/test-hdr/set/hdr_feldman_hashset_rcu_sht.cpp new file mode 100644 index 00000000..1a2100a1 --- /dev/null +++ b/tests/test-hdr/set/hdr_feldman_hashset_rcu_sht.cpp @@ -0,0 +1,324 @@ +//$$CDS-header$$ + +#include "set/hdr_feldman_hashset.h" +#include +#include +#include "unit/print_feldman_hashset_stat.h" + +namespace set { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + namespace { + typedef cds::urcu::gc> rcu_type; + } // namespace +#endif + + void FeldmanHashSetHdrTest::rcu_sht_nohash() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t key_type; + + struct traits : public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + >::type + > set_type2; + test_rcu>(4, 2); +#endif + } + + void FeldmanHashSetHdrTest::rcu_sht_stdhash() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + >::type + > set_type2; + test_rcu>(4, 2); +#endif + } + + void FeldmanHashSetHdrTest::rcu_sht_hash128() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef hash128::less less; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + , co::less< hash_type::less > + >::type + > set_type2; + test_rcu(4, 2); +#endif + } + + void FeldmanHashSetHdrTest::rcu_sht_nohash_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t key_type; + + struct traits : public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + , co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(4, 2); +#endif + } + + void FeldmanHashSetHdrTest::rcu_sht_stdhash_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(4, 2); +#endif + } + + void FeldmanHashSetHdrTest::rcu_sht_hash128_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef hash128::cmp compare; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::stat< cc::feldman_hashset::stat<>> + ,co::compare< hash128::cmp > + >::type + > set_type2; + test_rcu(4, 2); +#endif + } + + void FeldmanHashSetHdrTest::rcu_sht_nohash_5_3() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t key_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + >::type + > set_type2; + test_rcu>(5, 3); +#endif + } + + void FeldmanHashSetHdrTest::rcu_sht_stdhash_5_3() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + >::type + > set_type2; + test_rcu>(5, 3); +#endif + } + + void FeldmanHashSetHdrTest::rcu_sht_hash128_4_3() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef co::v::sequential_consistent memory_model; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::memory_model< co::v::sequential_consistent > + >::type + > set_type2; + test_rcu(4, 3); +#endif + } + + void FeldmanHashSetHdrTest::rcu_sht_nohash_5_3_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t key_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_key> + ,co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(5, 3); +#endif + } + + void FeldmanHashSetHdrTest::rcu_sht_stdhash_5_3_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + ,co::stat< cc::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(5, 3); +#endif + } + + void FeldmanHashSetHdrTest::rcu_sht_hash128_4_3_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef hash128 hash_type; + + struct traits: public cc::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef cc::feldman_hashset::stat<> stat; + typedef hash128::less less; + typedef hash128::cmp compare; + }; + typedef cc::FeldmanHashSet< 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::FeldmanHashSet< + rcu_type, + Item, + typename cc::feldman_hashset::make_traits< + cc::feldman_hashset::hash_accessor< get_hash> + , co::stat< cc::feldman_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_intrusive_feldman_hashset.h b/tests/test-hdr/set/hdr_intrusive_feldman_hashset.h new file mode 100644 index 00000000..dd7b9d31 --- /dev/null +++ b/tests/test-hdr/set/hdr_intrusive_feldman_hashset.h @@ -0,0 +1,789 @@ +//$$CDS-header$$ + +#ifndef CDSTEST_HDR_INTRUSIVE_FELDMAN_HASHSET_H +#define CDSTEST_HDR_INTRUSIVE_FELDMAN_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 IntrusiveFeldmanHashSetHdrTest: public CppUnitMini::TestCase + { + template + struct Item + { + unsigned int nDisposeCount ; // count of disposer calling + Hash hash; + unsigned int nInsertCall; + unsigned int nFindCall; + unsigned int nEraseCall; + mutable unsigned int nIteratorCall; + + Item() + : nDisposeCount(0) + , nInsertCall(0) + , nFindCall(0) + , nEraseCall(0) + , nIteratorCall(0) + {} + }; + + template + struct get_hash + { + Hash const& operator()( Item const& i ) const + { + return i.hash; + } + }; + + template + struct get_key + { + Key const& operator()(Item const& i) const + { + return i.hash; + } + }; + + struct item_disposer { + template + void operator()( Item * p ) + { + ++p->nDisposeCount; + } + }; + + template + struct nohash { + Key operator()(Key k) const + { + return k; + } + }; + + 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 ) + { + typedef typename Set::hash_type hash_type; + typedef typename Set::value_type value_type; + + Hash hasher; + + size_t const arrCapacity = 1000; + std::vector< value_type > arrValue; + arrValue.reserve( arrCapacity ); + for ( size_t i = 0; i < arrCapacity; ++i ) { + arrValue.emplace_back( value_type() ); + arrValue.back().hash = hasher( i ); + } + CPPUNIT_ASSERT( arrValue.size() == arrCapacity ); + + 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)); + + // insert() test + CPPUNIT_ASSERT(s.size() == 0 ); + CPPUNIT_ASSERT(s.empty() ); + for ( auto& el : arrValue ) { + CPPUNIT_ASSERT( s.insert( el )); + CPPUNIT_ASSERT(s.contains( el.hash )); + } + CPPUNIT_ASSERT(s.size() == arrCapacity ); + for ( auto& el : arrValue ) { + CPPUNIT_ASSERT(s.contains( el.hash )); + CPPUNIT_ASSERT( !s.insert( el ) ); + } + CPPUNIT_ASSERT(s.size() == arrCapacity ); + CPPUNIT_ASSERT( !s.empty() ); + + // Iterator test + { + typedef typename Set::iterator iterator; + for ( iterator it = s.begin(), itEnd = s.end(); it != itEnd; ++it ) + ++(it->nIteratorCall); + for ( auto& el : arrValue ) { + CPPUNIT_ASSERT( el.nIteratorCall == 1 ); + el.nIteratorCall = 0; + } + } + + { + // Const iterator test + for ( typename Set::const_iterator it = s.cbegin(), itEnd = s.cend(); it != itEnd; ++it ) + (*it).nIteratorCall += 1; + for ( auto& el : arrValue ) { + CPPUNIT_ASSERT( el.nIteratorCall == 1 ); + el.nIteratorCall = 0; + } + } + + { + // Reverse iterator test + for ( typename Set::reverse_iterator it = s.rbegin(), itEnd = s.rend(); it != itEnd; ++it ) + it->nIteratorCall += 1; + for ( auto& el : arrValue ) { + CPPUNIT_ASSERT( el.nIteratorCall == 1 ); + el.nIteratorCall = 0; + } + } + + { + // Reverse const iterator test + for ( typename Set::const_reverse_iterator it = s.crbegin(), itEnd = s.crend(); it != itEnd; ++it ) { + (*it).nIteratorCall += 1; + it.release(); + } + for ( auto& el : arrValue ) { + CPPUNIT_ASSERT( el.nIteratorCall == 1 ); + el.nIteratorCall = 0; + } + } + + // update() exists test + for ( auto& el : arrValue ) { + bool bOp, bInsert; + std::tie(bOp, bInsert) = s.update( el, false ); + CPPUNIT_ASSERT( bOp ); + CPPUNIT_ASSERT( !bInsert ); + CPPUNIT_ASSERT( el.nFindCall == 0 ); + CPPUNIT_ASSERT(s.find(el.hash, [](value_type& v) { v.nFindCall++; } )); + CPPUNIT_ASSERT( el.nFindCall == 1 ); + } + + // unlink test + CPPUNIT_ASSERT(s.size() == arrCapacity ); + for ( auto const& el : arrValue ) { + CPPUNIT_ASSERT(s.unlink( el )); + CPPUNIT_ASSERT(!s.contains( el.hash )); + } + CPPUNIT_ASSERT(s.size() == 0 ); + Set::gc::force_dispose(); + for ( auto const& el : arrValue ) { + CPPUNIT_ASSERT( el.nDisposeCount == 1 ); + } + + // new hash values + for ( auto& el : arrValue ) + el.hash = hasher( el.hash ); + + // insert( func ) + CPPUNIT_ASSERT(s.size() == 0 ); + for ( auto& el : arrValue ) { + CPPUNIT_ASSERT( s.insert( el, []( value_type& v ) { ++v.nInsertCall; } )); + CPPUNIT_ASSERT(s.contains( el.hash )); + CPPUNIT_ASSERT( el.nInsertCall == 1 ); + } + CPPUNIT_ASSERT(s.size() == arrCapacity ); + for ( auto& el : arrValue ) { + CPPUNIT_ASSERT(s.contains( el.hash )); + CPPUNIT_ASSERT( !s.insert( el ) ); + } + CPPUNIT_ASSERT(s.size() == arrCapacity ); + CPPUNIT_ASSERT( !s.empty() ); + + for ( auto& el : arrValue ) + el.nDisposeCount = 0; + + s.clear(); + CPPUNIT_ASSERT(s.size() == 0 ); + Set::gc::force_dispose(); + for ( auto const& el : arrValue ) { + CPPUNIT_ASSERT( el.nDisposeCount == 1 ); + } + + // new hash values + for ( auto& el : arrValue ) + el.hash = hasher( el.hash ); + + // update test + for ( auto& el : arrValue ) { + bool bOp, bInsert; + std::tie(bOp, bInsert) = s.update( el, false ); + CPPUNIT_ASSERT( !bOp ); + CPPUNIT_ASSERT( !bInsert ); + CPPUNIT_ASSERT( !s.contains( el.hash )); + + std::tie(bOp, bInsert) = s.update( el, true ); + CPPUNIT_ASSERT( bOp ); + CPPUNIT_ASSERT( bInsert ); + CPPUNIT_ASSERT( s.contains( el.hash )); + } + CPPUNIT_ASSERT(s.size() == arrCapacity ); + + // erase test + for ( auto& el : arrValue ) { + el.nDisposeCount = 0; + CPPUNIT_ASSERT( s.contains( el.hash )); + CPPUNIT_ASSERT(s.erase( el.hash )); + CPPUNIT_ASSERT( !s.contains( el.hash )); + CPPUNIT_ASSERT( !s.erase( el.hash )); + } + CPPUNIT_ASSERT(s.size() == 0 ); + Set::gc::force_dispose(); + for ( auto& el : arrValue ) { + CPPUNIT_ASSERT( el.nDisposeCount == 1 ); + CPPUNIT_ASSERT(s.insert( el )); + } + + // erase with functor, get() test + for ( auto& el : arrValue ) { + el.nDisposeCount = 0; + CPPUNIT_ASSERT( s.contains( el.hash ) ); + { + typename Set::guarded_ptr gp{ s.get( el.hash ) }; + CPPUNIT_ASSERT( gp ); + CPPUNIT_ASSERT( gp->nEraseCall == 0); + CPPUNIT_ASSERT(s.erase( gp->hash, []( value_type& i ) { ++i.nEraseCall; } )); + CPPUNIT_ASSERT( gp->nEraseCall == 1); + Set::gc::force_dispose(); + CPPUNIT_ASSERT( gp->nDisposeCount == 0 ); + } + CPPUNIT_ASSERT( !s.contains( el.hash )); + CPPUNIT_ASSERT( !s.erase( el.hash )); + CPPUNIT_ASSERT( el.nEraseCall == 1 ); + Set::gc::force_dispose(); + CPPUNIT_ASSERT( el.nDisposeCount == 1 ); + } + CPPUNIT_ASSERT(s.size() == 0 ); + + // new hash values + for ( auto& el : arrValue ) { + el.hash = hasher( el.hash ); + el.nDisposeCount = 0; + bool bOp, bInsert; + std::tie(bOp, bInsert) = s.update( el ); + CPPUNIT_ASSERT( bOp ); + CPPUNIT_ASSERT( bInsert ); + } + CPPUNIT_ASSERT(s.size() == arrCapacity ); + + // extract test + for ( auto& el : arrValue ) { + CPPUNIT_ASSERT( s.contains( el.hash ) ); + typename Set::guarded_ptr gp = s.extract( el.hash ); + CPPUNIT_ASSERT( gp ); + Set::gc::force_dispose(); + CPPUNIT_ASSERT( el.nDisposeCount == 0 ); + CPPUNIT_ASSERT( gp->nDisposeCount == 0 ); + gp = s.get( el.hash ); + CPPUNIT_ASSERT( !gp ); + Set::gc::force_dispose(); + CPPUNIT_ASSERT( el.nDisposeCount == 1 ); + CPPUNIT_ASSERT( !s.contains( el.hash ) ); + } + 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 ( auto 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() ); + + // erase with reverse_iterator + for ( auto& el : arrValue ) { + el.nDisposeCount = 0; + el.nIteratorCall = 0; + CPPUNIT_ASSERT(s.insert( el )); + } + for ( auto it = s.rbegin(), itEnd = s.rend(); 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() ); + } + + 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 typename Set::rcu_lock rcu_lock; + + Hash hasher; + + size_t const arrCapacity = 1000; + std::vector< value_type > arrValue; + arrValue.reserve(arrCapacity); + for (size_t i = 0; i < arrCapacity; ++i) { + arrValue.emplace_back(value_type()); + arrValue.back().hash = hasher(i); + } + CPPUNIT_ASSERT(arrValue.size() == arrCapacity); + + 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)); + + // insert() test + CPPUNIT_ASSERT(s.size() == 0); + CPPUNIT_ASSERT(s.empty()); + for (auto& el : arrValue) { + CPPUNIT_ASSERT(s.insert(el)); + CPPUNIT_ASSERT(s.contains(el.hash)); + } + CPPUNIT_ASSERT(s.size() == arrCapacity); + for (auto& el : arrValue) { + CPPUNIT_ASSERT(s.contains(el.hash)); + CPPUNIT_ASSERT(!s.insert(el)); + } + CPPUNIT_ASSERT(s.size() == arrCapacity); + CPPUNIT_ASSERT(!s.empty()); + + // Iterator test + { + rcu_lock l; + + typedef typename Set::iterator iterator; + for (iterator it = s.begin(), itEnd = s.end(); it != itEnd; ++it) + ++(it->nIteratorCall); + for (auto& el : arrValue) { + CPPUNIT_ASSERT(el.nIteratorCall == 1); + el.nIteratorCall = 0; + } + } + + { + // Const iterator test + rcu_lock l; + + for (typename Set::const_iterator it = s.cbegin(), itEnd = s.cend(); it != itEnd; ++it) + (*it).nIteratorCall += 1; + for (auto& el : arrValue) { + CPPUNIT_ASSERT(el.nIteratorCall == 1); + el.nIteratorCall = 0; + } + } + + { + // Reverse iterator test + rcu_lock l; + + for (typename Set::reverse_iterator it = s.rbegin(), itEnd = s.rend(); it != itEnd; ++it) + it->nIteratorCall += 1; + for (auto& el : arrValue) { + CPPUNIT_ASSERT(el.nIteratorCall == 1); + el.nIteratorCall = 0; + } + } + + { + // Reverse const iterator test + rcu_lock l; + + for (typename Set::const_reverse_iterator it = s.crbegin(), itEnd = s.crend(); it != itEnd; ++it) { + (*it).nIteratorCall += 1; + } + for (auto& el : arrValue) { + CPPUNIT_ASSERT(el.nIteratorCall == 1); + el.nIteratorCall = 0; + } + } + + // update() exists test + for (auto& el : arrValue) { + bool bOp, bInsert; + std::tie(bOp, bInsert) = s.update(el, false); + CPPUNIT_ASSERT(bOp); + CPPUNIT_ASSERT(!bInsert); + CPPUNIT_ASSERT(el.nFindCall == 0); + CPPUNIT_ASSERT(s.find(el.hash, [](value_type& v) { v.nFindCall++; })); + CPPUNIT_ASSERT(el.nFindCall == 1); + } + + // unlink test + CPPUNIT_ASSERT(s.size() == arrCapacity); + for (auto const& el : arrValue) { + CPPUNIT_ASSERT(s.unlink(el)); + CPPUNIT_ASSERT(!s.contains(el.hash)); + } + CPPUNIT_ASSERT(s.size() == 0); + Set::gc::force_dispose(); + for (auto const& el : arrValue) { + CPPUNIT_ASSERT(el.nDisposeCount == 1); + } + + // new hash values + for (auto& el : arrValue) + el.hash = hasher(el.hash); + + // insert( func ) + CPPUNIT_ASSERT(s.size() == 0); + for (auto& el : arrValue) { + CPPUNIT_ASSERT(s.insert(el, [](value_type& v) { ++v.nInsertCall; })); + CPPUNIT_ASSERT(s.contains(el.hash)); + CPPUNIT_ASSERT(el.nInsertCall == 1); + } + CPPUNIT_ASSERT(s.size() == arrCapacity); + for (auto& el : arrValue) { + CPPUNIT_ASSERT(s.contains(el.hash)); + CPPUNIT_ASSERT(!s.insert(el)); + } + CPPUNIT_ASSERT(s.size() == arrCapacity); + CPPUNIT_ASSERT(!s.empty()); + + for (auto& el : arrValue) + el.nDisposeCount = 0; + + s.clear(); + CPPUNIT_ASSERT(s.size() == 0); + Set::gc::force_dispose(); + for (auto const& el : arrValue) { + CPPUNIT_ASSERT(el.nDisposeCount == 1); + } + + // new hash values + for (auto& el : arrValue) + el.hash = hasher(el.hash); + + // update test + for (auto& el : arrValue) { + bool bOp, bInsert; + std::tie(bOp, bInsert) = s.update(el, false); + CPPUNIT_ASSERT(!bOp); + CPPUNIT_ASSERT(!bInsert); + CPPUNIT_ASSERT(!s.contains(el.hash)); + + std::tie(bOp, bInsert) = s.update(el, true); + CPPUNIT_ASSERT(bOp); + CPPUNIT_ASSERT(bInsert); + CPPUNIT_ASSERT(s.contains(el.hash)); + } + CPPUNIT_ASSERT(s.size() == arrCapacity); + + // erase test + for (auto& el : arrValue) { + el.nDisposeCount = 0; + CPPUNIT_ASSERT(s.contains(el.hash)); + CPPUNIT_ASSERT(s.erase(el.hash)); + CPPUNIT_ASSERT(!s.contains(el.hash)); + CPPUNIT_ASSERT(!s.erase(el.hash)); + } + CPPUNIT_ASSERT(s.size() == 0); + Set::gc::force_dispose(); + for (auto& el : arrValue) { + CPPUNIT_ASSERT(el.nDisposeCount == 1); + CPPUNIT_ASSERT(s.insert(el)); + } + + // erase with functor, get() test + for (auto& el : arrValue) { + el.nDisposeCount = 0; + CPPUNIT_ASSERT(s.contains(el.hash)); + value_type * p; + { + rcu_lock l; + p = s.get(el.hash); + CPPUNIT_ASSERT(p); + CPPUNIT_ASSERT(p->nEraseCall == 0); + } + // This is single-threaded test with faked disposer + // so we can dereference p outside RCU lock section + CPPUNIT_ASSERT(s.erase(p->hash, [](value_type& i) { ++i.nEraseCall; })); + CPPUNIT_ASSERT(p->nEraseCall == 1); + Set::gc::force_dispose(); + CPPUNIT_ASSERT(p->nDisposeCount == 1); + + CPPUNIT_ASSERT(!s.contains(el.hash)); + CPPUNIT_ASSERT(!s.erase(el.hash)); + CPPUNIT_ASSERT(el.nEraseCall == 1); + Set::gc::force_dispose(); + CPPUNIT_ASSERT(el.nDisposeCount == 1); + } + CPPUNIT_ASSERT(s.size() == 0); + + // new hash values + for (auto& el : arrValue) { + el.hash = hasher(el.hash); + el.nDisposeCount = 0; + bool bOp, bInsert; + std::tie(bOp, bInsert) = s.update(el); + CPPUNIT_ASSERT(bOp); + CPPUNIT_ASSERT(bInsert); + } + CPPUNIT_ASSERT(s.size() == arrCapacity); + + // extract test + for (auto& el : arrValue) { + CPPUNIT_ASSERT(s.contains(el.hash)); + typename Set::exempt_ptr xp = s.extract(el.hash); + CPPUNIT_ASSERT(xp); + Set::gc::force_dispose(); + CPPUNIT_ASSERT(el.nDisposeCount == 0); + CPPUNIT_ASSERT(xp->nDisposeCount == 0); + xp.release(); + { + rcu_lock l; + value_type * p = s.get(el.hash); + CPPUNIT_ASSERT(!p); + } + Set::gc::force_dispose(); + CPPUNIT_ASSERT(el.nDisposeCount == 1); + CPPUNIT_ASSERT(!s.contains(el.hash)); + } + CPPUNIT_ASSERT(s.size() == 0); + CPPUNIT_ASSERT(s.empty()); + + CPPUNIT_MSG(s.statistics()); + } + + void hp_nohash(); + void hp_nohash_stat(); + void hp_nohash_5_3(); + void hp_nohash_5_3_stat(); + void hp_stdhash(); + 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_nohash(); + void dhp_nohash_stat(); + void dhp_nohash_5_3(); + void dhp_nohash_5_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(); + + void rcu_gpi_nohash(); + void rcu_gpi_nohash_stat(); + void rcu_gpi_nohash_5_3(); + void rcu_gpi_nohash_5_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_nohash(); + void rcu_gpb_nohash_stat(); + void rcu_gpb_nohash_5_3(); + void rcu_gpb_nohash_5_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_nohash(); + void rcu_gpt_nohash_stat(); + void rcu_gpt_nohash_5_3(); + void rcu_gpt_nohash_5_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_nohash(); + void rcu_shb_nohash_stat(); + void rcu_shb_nohash_5_3(); + void rcu_shb_nohash_5_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_nohash(); + void rcu_sht_nohash_stat(); + void rcu_sht_nohash_5_3(); + void rcu_sht_nohash_5_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(IntrusiveFeldmanHashSetHdrTest) + CPPUNIT_TEST(hp_nohash) + CPPUNIT_TEST(hp_nohash_stat) + CPPUNIT_TEST(hp_nohash_5_3) + CPPUNIT_TEST(hp_nohash_5_3_stat) + 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_nohash) + CPPUNIT_TEST(dhp_nohash_stat) + CPPUNIT_TEST(dhp_nohash_5_3) + CPPUNIT_TEST(dhp_nohash_5_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(rcu_gpi_nohash) + CPPUNIT_TEST(rcu_gpi_nohash_stat) + CPPUNIT_TEST(rcu_gpi_nohash_5_3) + CPPUNIT_TEST(rcu_gpi_nohash_5_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_nohash) + CPPUNIT_TEST(rcu_gpb_nohash_stat) + CPPUNIT_TEST(rcu_gpb_nohash_5_3) + CPPUNIT_TEST(rcu_gpb_nohash_5_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_nohash) + CPPUNIT_TEST(rcu_gpt_nohash_stat) + CPPUNIT_TEST(rcu_gpt_nohash_5_3) + CPPUNIT_TEST(rcu_gpt_nohash_5_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_nohash) + CPPUNIT_TEST(rcu_shb_nohash_stat) + CPPUNIT_TEST(rcu_shb_nohash_5_3) + CPPUNIT_TEST(rcu_shb_nohash_5_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_nohash) + CPPUNIT_TEST(rcu_sht_nohash_stat) + CPPUNIT_TEST(rcu_sht_nohash_5_3) + CPPUNIT_TEST(rcu_sht_nohash_5_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() + + }; +} // namespace set + +#endif // #ifndef CDSTEST_HDR_INTRUSIVE_FELDMAN_HASHSET_H diff --git a/tests/test-hdr/set/hdr_intrusive_feldman_hashset_dhp.cpp b/tests/test-hdr/set/hdr_intrusive_feldman_hashset_dhp.cpp new file mode 100644 index 00000000..d1ddcc60 --- /dev/null +++ b/tests/test-hdr/set/hdr_intrusive_feldman_hashset_dhp.cpp @@ -0,0 +1,322 @@ +//$$CDS-header$$ + +#include "set/hdr_intrusive_feldman_hashset.h" +#include +#include "unit/print_feldman_hashset_stat.h" + +namespace set { + namespace { + typedef cds::gc::DHP gc_type; + } // namespace + + void IntrusiveFeldmanHashSetHdrTest::dhp_nohash() + { + typedef size_t key_type; + + struct traits : public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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::FeldmanHashSet< + gc_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_hp>(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::dhp_stdhash() + { + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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::FeldmanHashSet< + gc_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_hp>(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::dhp_hash128() + { + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef hash128::less less; + }; + typedef ci::FeldmanHashSet< 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::FeldmanHashSet< + gc_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + , ci::opt::less< hash_type::less > + >::type + > set_type2; + test_hp(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::dhp_nohash_stat() + { + typedef size_t key_type; + + struct traits : public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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::FeldmanHashSet< + gc_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + , co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_hp>(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::dhp_stdhash_stat() + { + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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::FeldmanHashSet< + gc_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_hp>(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::dhp_hash128_stat() + { + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef hash128::cmp compare; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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::FeldmanHashSet< + gc_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + ,co::compare< hash128::cmp > + >::type + > set_type2; + test_hp(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::dhp_nohash_5_3() + { + typedef size_t key_type; + + struct traits : public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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::FeldmanHashSet< + gc_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_hp>(5, 3); + } + + void IntrusiveFeldmanHashSetHdrTest::dhp_stdhash_5_3() + { + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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::FeldmanHashSet< + gc_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_hp>(5, 3); + } + + void IntrusiveFeldmanHashSetHdrTest::dhp_hash128_4_3() + { + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef co::v::sequential_consistent memory_model; + }; + typedef ci::FeldmanHashSet< 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::FeldmanHashSet< + gc_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_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 IntrusiveFeldmanHashSetHdrTest::dhp_nohash_5_3_stat() + { + typedef size_t key_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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::FeldmanHashSet< + gc_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_hp>(5, 3); + } + + void IntrusiveFeldmanHashSetHdrTest::dhp_stdhash_5_3_stat() + { + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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::FeldmanHashSet< + gc_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_hp>(5, 3); + } + + void IntrusiveFeldmanHashSetHdrTest::dhp_hash128_4_3_stat() + { + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + typedef hash128::less less; + typedef hash128::cmp compare; + }; + typedef ci::FeldmanHashSet< 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::FeldmanHashSet< + gc_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + , co::stat< ci::feldman_hashset::stat<>> + , co::less< hash_type::less > + , co::compare< hash128::cmp > + >::type + > set_type2; + test_hp(4, 3); + } + +} // namespace set diff --git a/tests/test-hdr/set/hdr_intrusive_feldman_hashset_hp.cpp b/tests/test-hdr/set/hdr_intrusive_feldman_hashset_hp.cpp new file mode 100644 index 00000000..8e5117e4 --- /dev/null +++ b/tests/test-hdr/set/hdr_intrusive_feldman_hashset_hp.cpp @@ -0,0 +1,324 @@ +//$$CDS-header$$ + +#include "set/hdr_intrusive_feldman_hashset.h" +#include +#include "unit/print_feldman_hashset_stat.h" + +namespace set { + namespace { + typedef cds::gc::HP gc_type; + } // namespace + + void IntrusiveFeldmanHashSetHdrTest::hp_nohash() + { + typedef size_t key_type; + + struct traits : public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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::FeldmanHashSet< + gc_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_hp>(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::hp_stdhash() + { + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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::FeldmanHashSet< + gc_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_hp>(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::hp_hash128() + { + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef hash128::less less; + }; + typedef ci::FeldmanHashSet< 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::FeldmanHashSet< + gc_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + , ci::opt::less< hash_type::less > + >::type + > set_type2; + test_hp(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::hp_nohash_stat() + { + typedef size_t key_type; + + struct traits : public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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::FeldmanHashSet< + gc_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + , co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_hp>(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::hp_stdhash_stat() + { + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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::FeldmanHashSet< + gc_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_hp>(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::hp_hash128_stat() + { + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef hash128::cmp compare; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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::FeldmanHashSet< + gc_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + ,co::compare< hash128::cmp > + >::type + > set_type2; + test_hp(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::hp_nohash_5_3() + { + typedef size_t key_type; + + struct traits : public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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::FeldmanHashSet< + gc_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_hp>(5, 3); + } + + void IntrusiveFeldmanHashSetHdrTest::hp_stdhash_5_3() + { + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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::FeldmanHashSet< + gc_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_hp>(5, 3); + } + + void IntrusiveFeldmanHashSetHdrTest::hp_hash128_4_3() + { + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef co::v::sequential_consistent memory_model; + }; + typedef ci::FeldmanHashSet< 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::FeldmanHashSet< + gc_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_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 IntrusiveFeldmanHashSetHdrTest::hp_nohash_5_3_stat() + { + typedef size_t key_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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::FeldmanHashSet< + gc_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_hp>(5, 3); + } + + void IntrusiveFeldmanHashSetHdrTest::hp_stdhash_5_3_stat() + { + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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::FeldmanHashSet< + gc_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_hp>(5, 3); + } + + void IntrusiveFeldmanHashSetHdrTest::hp_hash128_4_3_stat() + { + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + typedef hash128::less less; + typedef hash128::cmp compare; + }; + typedef ci::FeldmanHashSet< 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::FeldmanHashSet< + gc_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + , co::stat< ci::feldman_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::IntrusiveFeldmanHashSetHdrTest); diff --git a/tests/test-hdr/set/hdr_intrusive_feldman_hashset_rcu_gpb.cpp b/tests/test-hdr/set/hdr_intrusive_feldman_hashset_rcu_gpb.cpp new file mode 100644 index 00000000..c0aa5573 --- /dev/null +++ b/tests/test-hdr/set/hdr_intrusive_feldman_hashset_rcu_gpb.cpp @@ -0,0 +1,323 @@ +//$$CDS-header$$ + +#include "set/hdr_intrusive_feldman_hashset.h" +#include +#include +#include "unit/print_feldman_hashset_stat.h" + +namespace set { + namespace { + typedef cds::urcu::gc> rcu_type; + } // namespace + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpb_nohash() + { + typedef size_t key_type; + + struct traits : public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_rcu>(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpb_stdhash() + { + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_rcu>(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpb_hash128() + { + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef hash128::less less; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + , ci::opt::less< hash_type::less > + >::type + > set_type2; + test_rcu(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpb_nohash_stat() + { + typedef size_t key_type; + + struct traits : public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + , co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpb_stdhash_stat() + { + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpb_hash128_stat() + { + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef hash128::cmp compare; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + ,co::compare< hash128::cmp > + >::type + > set_type2; + test_rcu(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpb_nohash_5_3() + { + typedef size_t key_type; + + struct traits : public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_rcu>(5, 3); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpb_stdhash_5_3() + { + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_rcu>(5, 3); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpb_hash128_4_3() + { + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef co::v::sequential_consistent memory_model; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::memory_model< co::v::sequential_consistent > + >::type + > set_type2; + test_rcu(4, 3); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpb_nohash_5_3_stat() + { + typedef size_t key_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(5, 3); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpb_stdhash_5_3_stat() + { + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(5, 3); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpb_hash128_4_3_stat() + { + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + typedef hash128::less less; + typedef hash128::cmp compare; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + , co::stat< ci::feldman_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_intrusive_feldman_hashset_rcu_gpi.cpp b/tests/test-hdr/set/hdr_intrusive_feldman_hashset_rcu_gpi.cpp new file mode 100644 index 00000000..f1b0f430 --- /dev/null +++ b/tests/test-hdr/set/hdr_intrusive_feldman_hashset_rcu_gpi.cpp @@ -0,0 +1,323 @@ +//$$CDS-header$$ + +#include "set/hdr_intrusive_feldman_hashset.h" +#include +#include +#include "unit/print_feldman_hashset_stat.h" + +namespace set { + namespace { + typedef cds::urcu::gc> rcu_type; + } // namespace + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpi_nohash() + { + typedef size_t key_type; + + struct traits : public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_rcu>(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpi_stdhash() + { + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_rcu>(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpi_hash128() + { + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef hash128::less less; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + , ci::opt::less< hash_type::less > + >::type + > set_type2; + test_rcu(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpi_nohash_stat() + { + typedef size_t key_type; + + struct traits : public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + , co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpi_stdhash_stat() + { + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpi_hash128_stat() + { + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef hash128::cmp compare; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + ,co::compare< hash128::cmp > + >::type + > set_type2; + test_rcu(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpi_nohash_5_3() + { + typedef size_t key_type; + + struct traits : public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_rcu>(5, 3); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpi_stdhash_5_3() + { + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_rcu>(5, 3); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpi_hash128_4_3() + { + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef co::v::sequential_consistent memory_model; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::memory_model< co::v::sequential_consistent > + >::type + > set_type2; + test_rcu(4, 3); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpi_nohash_5_3_stat() + { + typedef size_t key_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(5, 3); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpi_stdhash_5_3_stat() + { + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(5, 3); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpi_hash128_4_3_stat() + { + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + typedef hash128::less less; + typedef hash128::cmp compare; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + , co::stat< ci::feldman_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_intrusive_feldman_hashset_rcu_gpt.cpp b/tests/test-hdr/set/hdr_intrusive_feldman_hashset_rcu_gpt.cpp new file mode 100644 index 00000000..222fe31d --- /dev/null +++ b/tests/test-hdr/set/hdr_intrusive_feldman_hashset_rcu_gpt.cpp @@ -0,0 +1,323 @@ +//$$CDS-header$$ + +#include "set/hdr_intrusive_feldman_hashset.h" +#include +#include +#include "unit/print_feldman_hashset_stat.h" + +namespace set { + namespace { + typedef cds::urcu::gc> rcu_type; + } // namespace + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpt_nohash() + { + typedef size_t key_type; + + struct traits : public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_rcu>(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpt_stdhash() + { + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_rcu>(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpt_hash128() + { + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef hash128::less less; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + , ci::opt::less< hash_type::less > + >::type + > set_type2; + test_rcu(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpt_nohash_stat() + { + typedef size_t key_type; + + struct traits : public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + , co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpt_stdhash_stat() + { + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpt_hash128_stat() + { + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef hash128::cmp compare; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + ,co::compare< hash128::cmp > + >::type + > set_type2; + test_rcu(4, 2); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpt_nohash_5_3() + { + typedef size_t key_type; + + struct traits : public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_rcu>(5, 3); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpt_stdhash_5_3() + { + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_rcu>(5, 3); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpt_hash128_4_3() + { + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef co::v::sequential_consistent memory_model; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::memory_model< co::v::sequential_consistent > + >::type + > set_type2; + test_rcu(4, 3); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpt_nohash_5_3_stat() + { + typedef size_t key_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(5, 3); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpt_stdhash_5_3_stat() + { + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(5, 3); + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_gpt_hash128_4_3_stat() + { + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + typedef hash128::less less; + typedef hash128::cmp compare; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + , co::stat< ci::feldman_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_intrusive_feldman_hashset_rcu_shb.cpp b/tests/test-hdr/set/hdr_intrusive_feldman_hashset_rcu_shb.cpp new file mode 100644 index 00000000..317b4390 --- /dev/null +++ b/tests/test-hdr/set/hdr_intrusive_feldman_hashset_rcu_shb.cpp @@ -0,0 +1,349 @@ +//$$CDS-header$$ + +#include "set/hdr_intrusive_feldman_hashset.h" +#include +#include +#include "unit/print_feldman_hashset_stat.h" + +namespace set { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + namespace { + typedef cds::urcu::gc> rcu_type; + } // namespace +#endif + + void IntrusiveFeldmanHashSetHdrTest::rcu_shb_nohash() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t key_type; + + struct traits : public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_rcu>(4, 2); +#endif + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_shb_stdhash() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_rcu>(4, 2); +#endif + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_shb_hash128() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef hash128::less less; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + , ci::opt::less< hash_type::less > + >::type + > set_type2; + test_rcu(4, 2); +#endif + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_shb_nohash_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t key_type; + + struct traits : public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + , co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(4, 2); +#endif + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_shb_stdhash_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(4, 2); +#endif + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_shb_hash128_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef hash128::cmp compare; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + ,co::compare< hash128::cmp > + >::type + > set_type2; + test_rcu(4, 2); +#endif + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_shb_nohash_5_3() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t key_type; + + struct traits : public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_rcu>(5, 3); +#endif + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_shb_stdhash_5_3() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_rcu>(5, 3); +#endif + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_shb_hash128_4_3() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef co::v::sequential_consistent memory_model; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::memory_model< co::v::sequential_consistent > + >::type + > set_type2; + test_rcu(4, 3); +#endif + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_shb_nohash_5_3_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t key_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(5, 3); +#endif + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_shb_stdhash_5_3_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(5, 3); +#endif + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_shb_hash128_4_3_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + typedef hash128::less less; + typedef hash128::cmp compare; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + , co::stat< ci::feldman_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_intrusive_feldman_hashset_rcu_sht.cpp b/tests/test-hdr/set/hdr_intrusive_feldman_hashset_rcu_sht.cpp new file mode 100644 index 00000000..67e181d5 --- /dev/null +++ b/tests/test-hdr/set/hdr_intrusive_feldman_hashset_rcu_sht.cpp @@ -0,0 +1,349 @@ +//$$CDS-header$$ + +#include "set/hdr_intrusive_feldman_hashset.h" +#include +#include +#include "unit/print_feldman_hashset_stat.h" + +namespace set { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + namespace { + typedef cds::urcu::gc> rcu_type; + } // namespace +#endif + + void IntrusiveFeldmanHashSetHdrTest::rcu_sht_nohash() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t key_type; + + struct traits : public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_rcu>(4, 2); +#endif + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_sht_stdhash() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_rcu>(4, 2); +#endif + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_sht_hash128() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef hash128::less less; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + , ci::opt::less< hash_type::less > + >::type + > set_type2; + test_rcu(4, 2); +#endif + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_sht_nohash_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t key_type; + + struct traits : public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + , co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(4, 2); +#endif + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_sht_stdhash_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(4, 2); +#endif + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_sht_hash128_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef hash128::cmp compare; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + ,co::compare< hash128::cmp > + >::type + > set_type2; + test_rcu(4, 2); +#endif + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_sht_nohash_5_3() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t key_type; + + struct traits : public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_rcu>(5, 3); +#endif + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_sht_stdhash_5_3() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + >::type + > set_type2; + test_rcu>(5, 3); +#endif + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_sht_hash128_4_3() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef co::v::sequential_consistent memory_model; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::memory_model< co::v::sequential_consistent > + >::type + > set_type2; + test_rcu(4, 3); +#endif + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_sht_nohash_5_3_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t key_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_key hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_key> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(5, 3); +#endif + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_sht_stdhash_5_3_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef size_t hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + ,co::stat< ci::feldman_hashset::stat<>> + >::type + > set_type2; + test_rcu>(5, 3); +#endif + } + + void IntrusiveFeldmanHashSetHdrTest::rcu_sht_hash128_4_3_stat() + { +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef hash128 hash_type; + + struct traits: public ci::feldman_hashset::traits + { + typedef get_hash hash_accessor; + typedef item_disposer disposer; + typedef ci::feldman_hashset::stat<> stat; + typedef hash128::less less; + typedef hash128::cmp compare; + }; + typedef ci::FeldmanHashSet< 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 ci::FeldmanHashSet< + rcu_type, + Item, + typename ci::feldman_hashset::make_traits< + ci::feldman_hashset::hash_accessor< get_hash> + , ci::opt::disposer< item_disposer > + , co::stat< ci::feldman_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_intrusive_multilevel_hashset.h b/tests/test-hdr/set/hdr_intrusive_multilevel_hashset.h deleted file mode 100644 index 551fd9b7..00000000 --- a/tests/test-hdr/set/hdr_intrusive_multilevel_hashset.h +++ /dev/null @@ -1,789 +0,0 @@ -//$$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; - unsigned int nInsertCall; - unsigned int nFindCall; - unsigned int nEraseCall; - mutable unsigned int nIteratorCall; - - Item() - : nDisposeCount(0) - , nInsertCall(0) - , nFindCall(0) - , nEraseCall(0) - , nIteratorCall(0) - {} - }; - - template - struct get_hash - { - Hash const& operator()( Item const& i ) const - { - return i.hash; - } - }; - - template - struct get_key - { - Key const& operator()(Item const& i) const - { - return i.hash; - } - }; - - struct item_disposer { - template - void operator()( Item * p ) - { - ++p->nDisposeCount; - } - }; - - template - struct nohash { - Key operator()(Key k) const - { - return k; - } - }; - - 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 ) - { - typedef typename Set::hash_type hash_type; - typedef typename Set::value_type value_type; - - Hash hasher; - - size_t const arrCapacity = 1000; - std::vector< value_type > arrValue; - arrValue.reserve( arrCapacity ); - for ( size_t i = 0; i < arrCapacity; ++i ) { - arrValue.emplace_back( value_type() ); - arrValue.back().hash = hasher( i ); - } - CPPUNIT_ASSERT( arrValue.size() == arrCapacity ); - - 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)); - - // insert() test - CPPUNIT_ASSERT(s.size() == 0 ); - CPPUNIT_ASSERT(s.empty() ); - for ( auto& el : arrValue ) { - CPPUNIT_ASSERT( s.insert( el )); - CPPUNIT_ASSERT(s.contains( el.hash )); - } - CPPUNIT_ASSERT(s.size() == arrCapacity ); - for ( auto& el : arrValue ) { - CPPUNIT_ASSERT(s.contains( el.hash )); - CPPUNIT_ASSERT( !s.insert( el ) ); - } - CPPUNIT_ASSERT(s.size() == arrCapacity ); - CPPUNIT_ASSERT( !s.empty() ); - - // Iterator test - { - typedef typename Set::iterator iterator; - for ( iterator it = s.begin(), itEnd = s.end(); it != itEnd; ++it ) - ++(it->nIteratorCall); - for ( auto& el : arrValue ) { - CPPUNIT_ASSERT( el.nIteratorCall == 1 ); - el.nIteratorCall = 0; - } - } - - { - // Const iterator test - for ( typename Set::const_iterator it = s.cbegin(), itEnd = s.cend(); it != itEnd; ++it ) - (*it).nIteratorCall += 1; - for ( auto& el : arrValue ) { - CPPUNIT_ASSERT( el.nIteratorCall == 1 ); - el.nIteratorCall = 0; - } - } - - { - // Reverse iterator test - for ( typename Set::reverse_iterator it = s.rbegin(), itEnd = s.rend(); it != itEnd; ++it ) - it->nIteratorCall += 1; - for ( auto& el : arrValue ) { - CPPUNIT_ASSERT( el.nIteratorCall == 1 ); - el.nIteratorCall = 0; - } - } - - { - // Reverse const iterator test - for ( typename Set::const_reverse_iterator it = s.crbegin(), itEnd = s.crend(); it != itEnd; ++it ) { - (*it).nIteratorCall += 1; - it.release(); - } - for ( auto& el : arrValue ) { - CPPUNIT_ASSERT( el.nIteratorCall == 1 ); - el.nIteratorCall = 0; - } - } - - // update() exists test - for ( auto& el : arrValue ) { - bool bOp, bInsert; - std::tie(bOp, bInsert) = s.update( el, false ); - CPPUNIT_ASSERT( bOp ); - CPPUNIT_ASSERT( !bInsert ); - CPPUNIT_ASSERT( el.nFindCall == 0 ); - CPPUNIT_ASSERT(s.find(el.hash, [](value_type& v) { v.nFindCall++; } )); - CPPUNIT_ASSERT( el.nFindCall == 1 ); - } - - // unlink test - CPPUNIT_ASSERT(s.size() == arrCapacity ); - for ( auto const& el : arrValue ) { - CPPUNIT_ASSERT(s.unlink( el )); - CPPUNIT_ASSERT(!s.contains( el.hash )); - } - CPPUNIT_ASSERT(s.size() == 0 ); - Set::gc::force_dispose(); - for ( auto const& el : arrValue ) { - CPPUNIT_ASSERT( el.nDisposeCount == 1 ); - } - - // new hash values - for ( auto& el : arrValue ) - el.hash = hasher( el.hash ); - - // insert( func ) - CPPUNIT_ASSERT(s.size() == 0 ); - for ( auto& el : arrValue ) { - CPPUNIT_ASSERT( s.insert( el, []( value_type& v ) { ++v.nInsertCall; } )); - CPPUNIT_ASSERT(s.contains( el.hash )); - CPPUNIT_ASSERT( el.nInsertCall == 1 ); - } - CPPUNIT_ASSERT(s.size() == arrCapacity ); - for ( auto& el : arrValue ) { - CPPUNIT_ASSERT(s.contains( el.hash )); - CPPUNIT_ASSERT( !s.insert( el ) ); - } - CPPUNIT_ASSERT(s.size() == arrCapacity ); - CPPUNIT_ASSERT( !s.empty() ); - - for ( auto& el : arrValue ) - el.nDisposeCount = 0; - - s.clear(); - CPPUNIT_ASSERT(s.size() == 0 ); - Set::gc::force_dispose(); - for ( auto const& el : arrValue ) { - CPPUNIT_ASSERT( el.nDisposeCount == 1 ); - } - - // new hash values - for ( auto& el : arrValue ) - el.hash = hasher( el.hash ); - - // update test - for ( auto& el : arrValue ) { - bool bOp, bInsert; - std::tie(bOp, bInsert) = s.update( el, false ); - CPPUNIT_ASSERT( !bOp ); - CPPUNIT_ASSERT( !bInsert ); - CPPUNIT_ASSERT( !s.contains( el.hash )); - - std::tie(bOp, bInsert) = s.update( el, true ); - CPPUNIT_ASSERT( bOp ); - CPPUNIT_ASSERT( bInsert ); - CPPUNIT_ASSERT( s.contains( el.hash )); - } - CPPUNIT_ASSERT(s.size() == arrCapacity ); - - // erase test - for ( auto& el : arrValue ) { - el.nDisposeCount = 0; - CPPUNIT_ASSERT( s.contains( el.hash )); - CPPUNIT_ASSERT(s.erase( el.hash )); - CPPUNIT_ASSERT( !s.contains( el.hash )); - CPPUNIT_ASSERT( !s.erase( el.hash )); - } - CPPUNIT_ASSERT(s.size() == 0 ); - Set::gc::force_dispose(); - for ( auto& el : arrValue ) { - CPPUNIT_ASSERT( el.nDisposeCount == 1 ); - CPPUNIT_ASSERT(s.insert( el )); - } - - // erase with functor, get() test - for ( auto& el : arrValue ) { - el.nDisposeCount = 0; - CPPUNIT_ASSERT( s.contains( el.hash ) ); - { - typename Set::guarded_ptr gp{ s.get( el.hash ) }; - CPPUNIT_ASSERT( gp ); - CPPUNIT_ASSERT( gp->nEraseCall == 0); - CPPUNIT_ASSERT(s.erase( gp->hash, []( value_type& i ) { ++i.nEraseCall; } )); - CPPUNIT_ASSERT( gp->nEraseCall == 1); - Set::gc::force_dispose(); - CPPUNIT_ASSERT( gp->nDisposeCount == 0 ); - } - CPPUNIT_ASSERT( !s.contains( el.hash )); - CPPUNIT_ASSERT( !s.erase( el.hash )); - CPPUNIT_ASSERT( el.nEraseCall == 1 ); - Set::gc::force_dispose(); - CPPUNIT_ASSERT( el.nDisposeCount == 1 ); - } - CPPUNIT_ASSERT(s.size() == 0 ); - - // new hash values - for ( auto& el : arrValue ) { - el.hash = hasher( el.hash ); - el.nDisposeCount = 0; - bool bOp, bInsert; - std::tie(bOp, bInsert) = s.update( el ); - CPPUNIT_ASSERT( bOp ); - CPPUNIT_ASSERT( bInsert ); - } - CPPUNIT_ASSERT(s.size() == arrCapacity ); - - // extract test - for ( auto& el : arrValue ) { - CPPUNIT_ASSERT( s.contains( el.hash ) ); - typename Set::guarded_ptr gp = s.extract( el.hash ); - CPPUNIT_ASSERT( gp ); - Set::gc::force_dispose(); - CPPUNIT_ASSERT( el.nDisposeCount == 0 ); - CPPUNIT_ASSERT( gp->nDisposeCount == 0 ); - gp = s.get( el.hash ); - CPPUNIT_ASSERT( !gp ); - Set::gc::force_dispose(); - CPPUNIT_ASSERT( el.nDisposeCount == 1 ); - CPPUNIT_ASSERT( !s.contains( el.hash ) ); - } - 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 ( auto 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() ); - - // erase with reverse_iterator - for ( auto& el : arrValue ) { - el.nDisposeCount = 0; - el.nIteratorCall = 0; - CPPUNIT_ASSERT(s.insert( el )); - } - for ( auto it = s.rbegin(), itEnd = s.rend(); 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() ); - } - - 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 typename Set::rcu_lock rcu_lock; - - Hash hasher; - - size_t const arrCapacity = 1000; - std::vector< value_type > arrValue; - arrValue.reserve(arrCapacity); - for (size_t i = 0; i < arrCapacity; ++i) { - arrValue.emplace_back(value_type()); - arrValue.back().hash = hasher(i); - } - CPPUNIT_ASSERT(arrValue.size() == arrCapacity); - - 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)); - - // insert() test - CPPUNIT_ASSERT(s.size() == 0); - CPPUNIT_ASSERT(s.empty()); - for (auto& el : arrValue) { - CPPUNIT_ASSERT(s.insert(el)); - CPPUNIT_ASSERT(s.contains(el.hash)); - } - CPPUNIT_ASSERT(s.size() == arrCapacity); - for (auto& el : arrValue) { - CPPUNIT_ASSERT(s.contains(el.hash)); - CPPUNIT_ASSERT(!s.insert(el)); - } - CPPUNIT_ASSERT(s.size() == arrCapacity); - CPPUNIT_ASSERT(!s.empty()); - - // Iterator test - { - rcu_lock l; - - typedef typename Set::iterator iterator; - for (iterator it = s.begin(), itEnd = s.end(); it != itEnd; ++it) - ++(it->nIteratorCall); - for (auto& el : arrValue) { - CPPUNIT_ASSERT(el.nIteratorCall == 1); - el.nIteratorCall = 0; - } - } - - { - // Const iterator test - rcu_lock l; - - for (typename Set::const_iterator it = s.cbegin(), itEnd = s.cend(); it != itEnd; ++it) - (*it).nIteratorCall += 1; - for (auto& el : arrValue) { - CPPUNIT_ASSERT(el.nIteratorCall == 1); - el.nIteratorCall = 0; - } - } - - { - // Reverse iterator test - rcu_lock l; - - for (typename Set::reverse_iterator it = s.rbegin(), itEnd = s.rend(); it != itEnd; ++it) - it->nIteratorCall += 1; - for (auto& el : arrValue) { - CPPUNIT_ASSERT(el.nIteratorCall == 1); - el.nIteratorCall = 0; - } - } - - { - // Reverse const iterator test - rcu_lock l; - - for (typename Set::const_reverse_iterator it = s.crbegin(), itEnd = s.crend(); it != itEnd; ++it) { - (*it).nIteratorCall += 1; - } - for (auto& el : arrValue) { - CPPUNIT_ASSERT(el.nIteratorCall == 1); - el.nIteratorCall = 0; - } - } - - // update() exists test - for (auto& el : arrValue) { - bool bOp, bInsert; - std::tie(bOp, bInsert) = s.update(el, false); - CPPUNIT_ASSERT(bOp); - CPPUNIT_ASSERT(!bInsert); - CPPUNIT_ASSERT(el.nFindCall == 0); - CPPUNIT_ASSERT(s.find(el.hash, [](value_type& v) { v.nFindCall++; })); - CPPUNIT_ASSERT(el.nFindCall == 1); - } - - // unlink test - CPPUNIT_ASSERT(s.size() == arrCapacity); - for (auto const& el : arrValue) { - CPPUNIT_ASSERT(s.unlink(el)); - CPPUNIT_ASSERT(!s.contains(el.hash)); - } - CPPUNIT_ASSERT(s.size() == 0); - Set::gc::force_dispose(); - for (auto const& el : arrValue) { - CPPUNIT_ASSERT(el.nDisposeCount == 1); - } - - // new hash values - for (auto& el : arrValue) - el.hash = hasher(el.hash); - - // insert( func ) - CPPUNIT_ASSERT(s.size() == 0); - for (auto& el : arrValue) { - CPPUNIT_ASSERT(s.insert(el, [](value_type& v) { ++v.nInsertCall; })); - CPPUNIT_ASSERT(s.contains(el.hash)); - CPPUNIT_ASSERT(el.nInsertCall == 1); - } - CPPUNIT_ASSERT(s.size() == arrCapacity); - for (auto& el : arrValue) { - CPPUNIT_ASSERT(s.contains(el.hash)); - CPPUNIT_ASSERT(!s.insert(el)); - } - CPPUNIT_ASSERT(s.size() == arrCapacity); - CPPUNIT_ASSERT(!s.empty()); - - for (auto& el : arrValue) - el.nDisposeCount = 0; - - s.clear(); - CPPUNIT_ASSERT(s.size() == 0); - Set::gc::force_dispose(); - for (auto const& el : arrValue) { - CPPUNIT_ASSERT(el.nDisposeCount == 1); - } - - // new hash values - for (auto& el : arrValue) - el.hash = hasher(el.hash); - - // update test - for (auto& el : arrValue) { - bool bOp, bInsert; - std::tie(bOp, bInsert) = s.update(el, false); - CPPUNIT_ASSERT(!bOp); - CPPUNIT_ASSERT(!bInsert); - CPPUNIT_ASSERT(!s.contains(el.hash)); - - std::tie(bOp, bInsert) = s.update(el, true); - CPPUNIT_ASSERT(bOp); - CPPUNIT_ASSERT(bInsert); - CPPUNIT_ASSERT(s.contains(el.hash)); - } - CPPUNIT_ASSERT(s.size() == arrCapacity); - - // erase test - for (auto& el : arrValue) { - el.nDisposeCount = 0; - CPPUNIT_ASSERT(s.contains(el.hash)); - CPPUNIT_ASSERT(s.erase(el.hash)); - CPPUNIT_ASSERT(!s.contains(el.hash)); - CPPUNIT_ASSERT(!s.erase(el.hash)); - } - CPPUNIT_ASSERT(s.size() == 0); - Set::gc::force_dispose(); - for (auto& el : arrValue) { - CPPUNIT_ASSERT(el.nDisposeCount == 1); - CPPUNIT_ASSERT(s.insert(el)); - } - - // erase with functor, get() test - for (auto& el : arrValue) { - el.nDisposeCount = 0; - CPPUNIT_ASSERT(s.contains(el.hash)); - value_type * p; - { - rcu_lock l; - p = s.get(el.hash); - CPPUNIT_ASSERT(p); - CPPUNIT_ASSERT(p->nEraseCall == 0); - } - // This is single-threaded test with faked disposer - // so we can dereference p outside RCU lock section - CPPUNIT_ASSERT(s.erase(p->hash, [](value_type& i) { ++i.nEraseCall; })); - CPPUNIT_ASSERT(p->nEraseCall == 1); - Set::gc::force_dispose(); - CPPUNIT_ASSERT(p->nDisposeCount == 1); - - CPPUNIT_ASSERT(!s.contains(el.hash)); - CPPUNIT_ASSERT(!s.erase(el.hash)); - CPPUNIT_ASSERT(el.nEraseCall == 1); - Set::gc::force_dispose(); - CPPUNIT_ASSERT(el.nDisposeCount == 1); - } - CPPUNIT_ASSERT(s.size() == 0); - - // new hash values - for (auto& el : arrValue) { - el.hash = hasher(el.hash); - el.nDisposeCount = 0; - bool bOp, bInsert; - std::tie(bOp, bInsert) = s.update(el); - CPPUNIT_ASSERT(bOp); - CPPUNIT_ASSERT(bInsert); - } - CPPUNIT_ASSERT(s.size() == arrCapacity); - - // extract test - for (auto& el : arrValue) { - CPPUNIT_ASSERT(s.contains(el.hash)); - typename Set::exempt_ptr xp = s.extract(el.hash); - CPPUNIT_ASSERT(xp); - Set::gc::force_dispose(); - CPPUNIT_ASSERT(el.nDisposeCount == 0); - CPPUNIT_ASSERT(xp->nDisposeCount == 0); - xp.release(); - { - rcu_lock l; - value_type * p = s.get(el.hash); - CPPUNIT_ASSERT(!p); - } - Set::gc::force_dispose(); - CPPUNIT_ASSERT(el.nDisposeCount == 1); - CPPUNIT_ASSERT(!s.contains(el.hash)); - } - CPPUNIT_ASSERT(s.size() == 0); - CPPUNIT_ASSERT(s.empty()); - - CPPUNIT_MSG(s.statistics()); - } - - void hp_nohash(); - void hp_nohash_stat(); - void hp_nohash_5_3(); - void hp_nohash_5_3_stat(); - void hp_stdhash(); - 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_nohash(); - void dhp_nohash_stat(); - void dhp_nohash_5_3(); - void dhp_nohash_5_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(); - - void rcu_gpi_nohash(); - void rcu_gpi_nohash_stat(); - void rcu_gpi_nohash_5_3(); - void rcu_gpi_nohash_5_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_nohash(); - void rcu_gpb_nohash_stat(); - void rcu_gpb_nohash_5_3(); - void rcu_gpb_nohash_5_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_nohash(); - void rcu_gpt_nohash_stat(); - void rcu_gpt_nohash_5_3(); - void rcu_gpt_nohash_5_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_nohash(); - void rcu_shb_nohash_stat(); - void rcu_shb_nohash_5_3(); - void rcu_shb_nohash_5_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_nohash(); - void rcu_sht_nohash_stat(); - void rcu_sht_nohash_5_3(); - void rcu_sht_nohash_5_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(IntrusiveMultiLevelHashSetHdrTest) - CPPUNIT_TEST(hp_nohash) - CPPUNIT_TEST(hp_nohash_stat) - CPPUNIT_TEST(hp_nohash_5_3) - CPPUNIT_TEST(hp_nohash_5_3_stat) - 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_nohash) - CPPUNIT_TEST(dhp_nohash_stat) - CPPUNIT_TEST(dhp_nohash_5_3) - CPPUNIT_TEST(dhp_nohash_5_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(rcu_gpi_nohash) - CPPUNIT_TEST(rcu_gpi_nohash_stat) - CPPUNIT_TEST(rcu_gpi_nohash_5_3) - CPPUNIT_TEST(rcu_gpi_nohash_5_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_nohash) - CPPUNIT_TEST(rcu_gpb_nohash_stat) - CPPUNIT_TEST(rcu_gpb_nohash_5_3) - CPPUNIT_TEST(rcu_gpb_nohash_5_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_nohash) - CPPUNIT_TEST(rcu_gpt_nohash_stat) - CPPUNIT_TEST(rcu_gpt_nohash_5_3) - CPPUNIT_TEST(rcu_gpt_nohash_5_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_nohash) - CPPUNIT_TEST(rcu_shb_nohash_stat) - CPPUNIT_TEST(rcu_shb_nohash_5_3) - CPPUNIT_TEST(rcu_shb_nohash_5_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_nohash) - CPPUNIT_TEST(rcu_sht_nohash_stat) - CPPUNIT_TEST(rcu_sht_nohash_5_3) - CPPUNIT_TEST(rcu_sht_nohash_5_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() - - }; -} // namespace set - -#endif // #ifndef CDSTEST_HDR_INTRUSIVE_MULTILEVEL_HASHSET_H diff --git a/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_dhp.cpp b/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_dhp.cpp deleted file mode 100644 index 5c0d5b5a..00000000 --- a/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_dhp.cpp +++ /dev/null @@ -1,322 +0,0 @@ -//$$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_nohash() - { - typedef size_t key_type; - - struct traits : public ci::multilevel_hashset::traits - { - typedef get_key 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_key> - , ci::opt::disposer< item_disposer > - >::type - > set_type2; - test_hp>(4, 2); - } - - 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_nohash_stat() - { - typedef size_t key_type; - - struct traits : public ci::multilevel_hashset::traits - { - typedef get_key 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_key> - , ci::opt::disposer< item_disposer > - , co::stat< ci::multilevel_hashset::stat<>> - >::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_nohash_5_3() - { - typedef size_t key_type; - - struct traits : public ci::multilevel_hashset::traits - { - typedef get_key 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_key> - , ci::opt::disposer< item_disposer > - >::type - > set_type2; - test_hp>(5, 3); - } - - 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_nohash_5_3_stat() - { - typedef size_t key_type; - - struct traits: public ci::multilevel_hashset::traits - { - typedef get_key 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_key> - , ci::opt::disposer< item_disposer > - ,co::stat< ci::multilevel_hashset::stat<>> - >::type - > set_type2; - test_hp>(5, 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 diff --git a/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_hp.cpp b/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_hp.cpp deleted file mode 100644 index 341204a2..00000000 --- a/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_hp.cpp +++ /dev/null @@ -1,324 +0,0 @@ -//$$CDS-header$$ - -#include "set/hdr_intrusive_multilevel_hashset.h" -#include -#include "unit/print_multilevel_hashset_stat.h" - -namespace set { - namespace { - typedef cds::gc::HP gc_type; - } // namespace - - void IntrusiveMultiLevelHashSetHdrTest::hp_nohash() - { - typedef size_t key_type; - - struct traits : public ci::multilevel_hashset::traits - { - typedef get_key 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_key> - , ci::opt::disposer< item_disposer > - >::type - > set_type2; - test_hp>(4, 2); - } - - void IntrusiveMultiLevelHashSetHdrTest::hp_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::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_nohash_stat() - { - typedef size_t key_type; - - struct traits : public ci::multilevel_hashset::traits - { - typedef get_key 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_key> - , ci::opt::disposer< item_disposer > - , co::stat< ci::multilevel_hashset::stat<>> - >::type - > set_type2; - test_hp>(4, 2); - } - - void IntrusiveMultiLevelHashSetHdrTest::hp_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::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_nohash_5_3() - { - typedef size_t key_type; - - struct traits : public ci::multilevel_hashset::traits - { - typedef get_key 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_key> - , ci::opt::disposer< item_disposer > - >::type - > set_type2; - test_hp>(5, 3); - } - - void IntrusiveMultiLevelHashSetHdrTest::hp_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::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_nohash_5_3_stat() - { - typedef size_t key_type; - - struct traits: public ci::multilevel_hashset::traits - { - typedef get_key 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_key> - , ci::opt::disposer< item_disposer > - ,co::stat< ci::multilevel_hashset::stat<>> - >::type - > set_type2; - test_hp>(5, 3); - } - - void IntrusiveMultiLevelHashSetHdrTest::hp_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::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); diff --git a/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_rcu_gpb.cpp b/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_rcu_gpb.cpp deleted file mode 100644 index 72f02b8f..00000000 --- a/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_rcu_gpb.cpp +++ /dev/null @@ -1,323 +0,0 @@ -//$$CDS-header$$ - -#include "set/hdr_intrusive_multilevel_hashset.h" -#include -#include -#include "unit/print_multilevel_hashset_stat.h" - -namespace set { - namespace { - typedef cds::urcu::gc> rcu_type; - } // namespace - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpb_nohash() - { - typedef size_t key_type; - - struct traits : public ci::multilevel_hashset::traits - { - typedef get_key hash_accessor; - typedef item_disposer disposer; - }; - typedef ci::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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_key> - , ci::opt::disposer< item_disposer > - >::type - > set_type2; - test_rcu>(4, 2); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpb_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< 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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_hash> - , ci::opt::disposer< item_disposer > - >::type - > set_type2; - test_rcu>(4, 2); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpb_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< 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 ci::MultiLevelHashSet< - rcu_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_rcu(4, 2); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpb_nohash_stat() - { - typedef size_t key_type; - - struct traits : public ci::multilevel_hashset::traits - { - typedef get_key hash_accessor; - typedef item_disposer disposer; - typedef ci::multilevel_hashset::stat<> stat; - }; - typedef ci::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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_key> - , ci::opt::disposer< item_disposer > - , co::stat< ci::multilevel_hashset::stat<>> - >::type - > set_type2; - test_rcu>(4, 2); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpb_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< 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 ci::MultiLevelHashSet< - rcu_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_rcu>(4, 2); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpb_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< 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 ci::MultiLevelHashSet< - rcu_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_rcu(4, 2); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpb_nohash_5_3() - { - typedef size_t key_type; - - struct traits : public ci::multilevel_hashset::traits - { - typedef get_key hash_accessor; - typedef item_disposer disposer; - }; - typedef ci::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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_key> - , ci::opt::disposer< item_disposer > - >::type - > set_type2; - test_rcu>(5, 3); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpb_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< 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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_hash> - , ci::opt::disposer< item_disposer > - >::type - > set_type2; - test_rcu>(5, 3); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpb_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< 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 ci::MultiLevelHashSet< - rcu_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_rcu(4, 3); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpb_nohash_5_3_stat() - { - typedef size_t key_type; - - struct traits: public ci::multilevel_hashset::traits - { - typedef get_key hash_accessor; - typedef item_disposer disposer; - typedef ci::multilevel_hashset::stat<> stat; - }; - typedef ci::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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_key> - , ci::opt::disposer< item_disposer > - ,co::stat< ci::multilevel_hashset::stat<>> - >::type - > set_type2; - test_rcu>(5, 3); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpb_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< 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 ci::MultiLevelHashSet< - rcu_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_rcu>(5, 3); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpb_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< 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 ci::MultiLevelHashSet< - rcu_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_rcu(4, 3); - } - -} // namespace set diff --git a/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_rcu_gpi.cpp b/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_rcu_gpi.cpp deleted file mode 100644 index f61730f6..00000000 --- a/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_rcu_gpi.cpp +++ /dev/null @@ -1,323 +0,0 @@ -//$$CDS-header$$ - -#include "set/hdr_intrusive_multilevel_hashset.h" -#include -#include -#include "unit/print_multilevel_hashset_stat.h" - -namespace set { - namespace { - typedef cds::urcu::gc> rcu_type; - } // namespace - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpi_nohash() - { - typedef size_t key_type; - - struct traits : public ci::multilevel_hashset::traits - { - typedef get_key hash_accessor; - typedef item_disposer disposer; - }; - typedef ci::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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_key> - , ci::opt::disposer< item_disposer > - >::type - > set_type2; - test_rcu>(4, 2); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpi_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< 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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_hash> - , ci::opt::disposer< item_disposer > - >::type - > set_type2; - test_rcu>(4, 2); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpi_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< 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 ci::MultiLevelHashSet< - rcu_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_rcu(4, 2); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpi_nohash_stat() - { - typedef size_t key_type; - - struct traits : public ci::multilevel_hashset::traits - { - typedef get_key hash_accessor; - typedef item_disposer disposer; - typedef ci::multilevel_hashset::stat<> stat; - }; - typedef ci::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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_key> - , ci::opt::disposer< item_disposer > - , co::stat< ci::multilevel_hashset::stat<>> - >::type - > set_type2; - test_rcu>(4, 2); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpi_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< 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 ci::MultiLevelHashSet< - rcu_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_rcu>(4, 2); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpi_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< 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 ci::MultiLevelHashSet< - rcu_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_rcu(4, 2); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpi_nohash_5_3() - { - typedef size_t key_type; - - struct traits : public ci::multilevel_hashset::traits - { - typedef get_key hash_accessor; - typedef item_disposer disposer; - }; - typedef ci::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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_key> - , ci::opt::disposer< item_disposer > - >::type - > set_type2; - test_rcu>(5, 3); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpi_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< 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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_hash> - , ci::opt::disposer< item_disposer > - >::type - > set_type2; - test_rcu>(5, 3); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpi_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< 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 ci::MultiLevelHashSet< - rcu_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_rcu(4, 3); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpi_nohash_5_3_stat() - { - typedef size_t key_type; - - struct traits: public ci::multilevel_hashset::traits - { - typedef get_key hash_accessor; - typedef item_disposer disposer; - typedef ci::multilevel_hashset::stat<> stat; - }; - typedef ci::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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_key> - , ci::opt::disposer< item_disposer > - ,co::stat< ci::multilevel_hashset::stat<>> - >::type - > set_type2; - test_rcu>(5, 3); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpi_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< 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 ci::MultiLevelHashSet< - rcu_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_rcu>(5, 3); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpi_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< 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 ci::MultiLevelHashSet< - rcu_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_rcu(4, 3); - } - -} // namespace set diff --git a/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_rcu_gpt.cpp b/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_rcu_gpt.cpp deleted file mode 100644 index da4e9d52..00000000 --- a/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_rcu_gpt.cpp +++ /dev/null @@ -1,323 +0,0 @@ -//$$CDS-header$$ - -#include "set/hdr_intrusive_multilevel_hashset.h" -#include -#include -#include "unit/print_multilevel_hashset_stat.h" - -namespace set { - namespace { - typedef cds::urcu::gc> rcu_type; - } // namespace - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpt_nohash() - { - typedef size_t key_type; - - struct traits : public ci::multilevel_hashset::traits - { - typedef get_key hash_accessor; - typedef item_disposer disposer; - }; - typedef ci::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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_key> - , ci::opt::disposer< item_disposer > - >::type - > set_type2; - test_rcu>(4, 2); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpt_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< 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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_hash> - , ci::opt::disposer< item_disposer > - >::type - > set_type2; - test_rcu>(4, 2); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpt_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< 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 ci::MultiLevelHashSet< - rcu_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_rcu(4, 2); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpt_nohash_stat() - { - typedef size_t key_type; - - struct traits : public ci::multilevel_hashset::traits - { - typedef get_key hash_accessor; - typedef item_disposer disposer; - typedef ci::multilevel_hashset::stat<> stat; - }; - typedef ci::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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_key> - , ci::opt::disposer< item_disposer > - , co::stat< ci::multilevel_hashset::stat<>> - >::type - > set_type2; - test_rcu>(4, 2); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpt_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< 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 ci::MultiLevelHashSet< - rcu_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_rcu>(4, 2); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpt_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< 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 ci::MultiLevelHashSet< - rcu_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_rcu(4, 2); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpt_nohash_5_3() - { - typedef size_t key_type; - - struct traits : public ci::multilevel_hashset::traits - { - typedef get_key hash_accessor; - typedef item_disposer disposer; - }; - typedef ci::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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_key> - , ci::opt::disposer< item_disposer > - >::type - > set_type2; - test_rcu>(5, 3); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpt_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< 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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_hash> - , ci::opt::disposer< item_disposer > - >::type - > set_type2; - test_rcu>(5, 3); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpt_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< 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 ci::MultiLevelHashSet< - rcu_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_rcu(4, 3); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpt_nohash_5_3_stat() - { - typedef size_t key_type; - - struct traits: public ci::multilevel_hashset::traits - { - typedef get_key hash_accessor; - typedef item_disposer disposer; - typedef ci::multilevel_hashset::stat<> stat; - }; - typedef ci::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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_key> - , ci::opt::disposer< item_disposer > - ,co::stat< ci::multilevel_hashset::stat<>> - >::type - > set_type2; - test_rcu>(5, 3); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpt_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< 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 ci::MultiLevelHashSet< - rcu_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_rcu>(5, 3); - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_gpt_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< 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 ci::MultiLevelHashSet< - rcu_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_rcu(4, 3); - } - -} // namespace set diff --git a/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_rcu_shb.cpp b/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_rcu_shb.cpp deleted file mode 100644 index b1236812..00000000 --- a/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_rcu_shb.cpp +++ /dev/null @@ -1,349 +0,0 @@ -//$$CDS-header$$ - -#include "set/hdr_intrusive_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 IntrusiveMultiLevelHashSetHdrTest::rcu_shb_nohash() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef size_t key_type; - - struct traits : public ci::multilevel_hashset::traits - { - typedef get_key hash_accessor; - typedef item_disposer disposer; - }; - typedef ci::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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_key> - , ci::opt::disposer< item_disposer > - >::type - > set_type2; - test_rcu>(4, 2); -#endif - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_shb_stdhash() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef size_t hash_type; - - struct traits: public ci::multilevel_hashset::traits - { - typedef get_hash hash_accessor; - typedef item_disposer disposer; - }; - typedef ci::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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_hash> - , ci::opt::disposer< item_disposer > - >::type - > set_type2; - test_rcu>(4, 2); -#endif - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_shb_hash128() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - 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< 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 ci::MultiLevelHashSet< - rcu_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_rcu(4, 2); -#endif - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_shb_nohash_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef size_t key_type; - - struct traits : public ci::multilevel_hashset::traits - { - typedef get_key hash_accessor; - typedef item_disposer disposer; - typedef ci::multilevel_hashset::stat<> stat; - }; - typedef ci::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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_key> - , ci::opt::disposer< item_disposer > - , co::stat< ci::multilevel_hashset::stat<>> - >::type - > set_type2; - test_rcu>(4, 2); -#endif - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_shb_stdhash_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - 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< 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 ci::MultiLevelHashSet< - rcu_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_rcu>(4, 2); -#endif - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_shb_hash128_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - 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< 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 ci::MultiLevelHashSet< - rcu_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_rcu(4, 2); -#endif - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_shb_nohash_5_3() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef size_t key_type; - - struct traits : public ci::multilevel_hashset::traits - { - typedef get_key hash_accessor; - typedef item_disposer disposer; - }; - typedef ci::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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_key> - , ci::opt::disposer< item_disposer > - >::type - > set_type2; - test_rcu>(5, 3); -#endif - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_shb_stdhash_5_3() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef size_t hash_type; - - struct traits: public ci::multilevel_hashset::traits - { - typedef get_hash hash_accessor; - typedef item_disposer disposer; - }; - typedef ci::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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_hash> - , ci::opt::disposer< item_disposer > - >::type - > set_type2; - test_rcu>(5, 3); -#endif - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_shb_hash128_4_3() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - 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< 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 ci::MultiLevelHashSet< - rcu_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_rcu(4, 3); -#endif - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_shb_nohash_5_3_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef size_t key_type; - - struct traits: public ci::multilevel_hashset::traits - { - typedef get_key hash_accessor; - typedef item_disposer disposer; - typedef ci::multilevel_hashset::stat<> stat; - }; - typedef ci::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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_key> - , ci::opt::disposer< item_disposer > - ,co::stat< ci::multilevel_hashset::stat<>> - >::type - > set_type2; - test_rcu>(5, 3); -#endif - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_shb_stdhash_5_3_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - 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< 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 ci::MultiLevelHashSet< - rcu_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_rcu>(5, 3); -#endif - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_shb_hash128_4_3_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - 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< 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 ci::MultiLevelHashSet< - rcu_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_rcu(4, 3); -#endif - } - -} // namespace set diff --git a/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_rcu_sht.cpp b/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_rcu_sht.cpp deleted file mode 100644 index 6ade6cf7..00000000 --- a/tests/test-hdr/set/hdr_intrusive_multilevel_hashset_rcu_sht.cpp +++ /dev/null @@ -1,349 +0,0 @@ -//$$CDS-header$$ - -#include "set/hdr_intrusive_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 IntrusiveMultiLevelHashSetHdrTest::rcu_sht_nohash() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef size_t key_type; - - struct traits : public ci::multilevel_hashset::traits - { - typedef get_key hash_accessor; - typedef item_disposer disposer; - }; - typedef ci::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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_key> - , ci::opt::disposer< item_disposer > - >::type - > set_type2; - test_rcu>(4, 2); -#endif - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_sht_stdhash() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef size_t hash_type; - - struct traits: public ci::multilevel_hashset::traits - { - typedef get_hash hash_accessor; - typedef item_disposer disposer; - }; - typedef ci::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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_hash> - , ci::opt::disposer< item_disposer > - >::type - > set_type2; - test_rcu>(4, 2); -#endif - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_sht_hash128() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - 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< 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 ci::MultiLevelHashSet< - rcu_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_rcu(4, 2); -#endif - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_sht_nohash_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef size_t key_type; - - struct traits : public ci::multilevel_hashset::traits - { - typedef get_key hash_accessor; - typedef item_disposer disposer; - typedef ci::multilevel_hashset::stat<> stat; - }; - typedef ci::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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_key> - , ci::opt::disposer< item_disposer > - , co::stat< ci::multilevel_hashset::stat<>> - >::type - > set_type2; - test_rcu>(4, 2); -#endif - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_sht_stdhash_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - 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< 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 ci::MultiLevelHashSet< - rcu_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_rcu>(4, 2); -#endif - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_sht_hash128_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - 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< 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 ci::MultiLevelHashSet< - rcu_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_rcu(4, 2); -#endif - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_sht_nohash_5_3() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef size_t key_type; - - struct traits : public ci::multilevel_hashset::traits - { - typedef get_key hash_accessor; - typedef item_disposer disposer; - }; - typedef ci::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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_key> - , ci::opt::disposer< item_disposer > - >::type - > set_type2; - test_rcu>(5, 3); -#endif - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_sht_stdhash_5_3() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef size_t hash_type; - - struct traits: public ci::multilevel_hashset::traits - { - typedef get_hash hash_accessor; - typedef item_disposer disposer; - }; - typedef ci::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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_hash> - , ci::opt::disposer< item_disposer > - >::type - > set_type2; - test_rcu>(5, 3); -#endif - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_sht_hash128_4_3() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - 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< 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 ci::MultiLevelHashSet< - rcu_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_rcu(4, 3); -#endif - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_sht_nohash_5_3_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef size_t key_type; - - struct traits: public ci::multilevel_hashset::traits - { - typedef get_key hash_accessor; - typedef item_disposer disposer; - typedef ci::multilevel_hashset::stat<> stat; - }; - typedef ci::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 ci::MultiLevelHashSet< - rcu_type, - Item, - typename ci::multilevel_hashset::make_traits< - ci::multilevel_hashset::hash_accessor< get_key> - , ci::opt::disposer< item_disposer > - ,co::stat< ci::multilevel_hashset::stat<>> - >::type - > set_type2; - test_rcu>(5, 3); -#endif - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_sht_stdhash_5_3_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - 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< 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 ci::MultiLevelHashSet< - rcu_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_rcu>(5, 3); -#endif - } - - void IntrusiveMultiLevelHashSetHdrTest::rcu_sht_hash128_4_3_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - 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< 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 ci::MultiLevelHashSet< - rcu_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_rcu(4, 3); -#endif - } - -} // namespace set diff --git a/tests/test-hdr/set/hdr_multilevel_hashset.h b/tests/test-hdr/set/hdr_multilevel_hashset.h deleted file mode 100644 index e61d3629..00000000 --- a/tests/test-hdr/set/hdr_multilevel_hashset.h +++ /dev/null @@ -1,843 +0,0 @@ -//$$CDS-header$$ - -#ifndef CDSTEST_HDR_MULTILEVEL_HASHSET_H -#define CDSTEST_HDR_MULTILEVEL_HASHSET_H - -#include "cppunit/cppunit_proxy.h" - -// forward declaration -namespace cds { - namespace container {} - namespace opt {} -} - -namespace set { - namespace cc = cds::container; - namespace co = cds::opt; - - class MultiLevelHashSetHdrTest : public CppUnitMini::TestCase - { - template - struct Arg - { - size_t key; - Hash hash; - - Arg( size_t k, Hash const& h ) - : key( k ) - , hash( h ) - {} - }; - - template - struct Item - { - unsigned int nInsertCall; - unsigned int nFindCall; - unsigned int nEraseCall; - mutable unsigned int nIteratorCall; - Hash hash; - size_t key; - - Item( size_t k, Hash const& h ) - : nInsertCall(0) - , nFindCall(0) - , nEraseCall(0) - , nIteratorCall(0) - , hash( h ) - , key( k ) - {} - - explicit Item( Arg const& arg ) - : nInsertCall(0) - , nFindCall(0) - , nEraseCall(0) - , nIteratorCall(0) - , hash( arg.hash ) - , key( arg.key ) - {} - - Item( Item const& i ) - : nInsertCall(0) - , nFindCall(0) - , nEraseCall(0) - , nIteratorCall(0) - , hash( i.hash ) - , key( i.key ) - {} - }; - - template - struct get_hash - { - Hash const& operator()( Item const& i ) const - { - return i.hash; - } - }; - - template - struct get_key - { - Key operator()(Item const& i)const - { - return i.hash; - } - }; - - template - struct nohash { - Key operator()(Key k) const - { - return k; - } - }; - - struct hash128 - { - size_t lo; - size_t hi; - - hash128() {} - hash128(size_t l, size_t h) : lo(l), hi(h) {} - hash128( hash128 const& h) : lo(h.lo), hi(h.hi) {} - - 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; - } - }; - - friend bool operator==( hash128 const& lhs, hash128 const& rhs ) - { - return cmp()( lhs, rhs ) == 0; - } - friend bool operator!=(hash128 const& lhs, hash128 const& rhs) - { - return !( lhs == rhs ); - } - }; - - template - void test_hp( 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::guarded_ptr guarded_ptr; - - 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 ); - - guarded_ptr gp(s.get( h )); - CPPUNIT_ASSERT( gp ); - CPPUNIT_ASSERT( gp->nInsertCall == 1 ); - CPPUNIT_ASSERT( gp->key == i ); - CPPUNIT_ASSERT( gp->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 - 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 - for ( auto& el : s ) { - CPPUNIT_ASSERT( el.nInsertCall == 1 ); - CPPUNIT_ASSERT( el.nFindCall == 1 ); - el.nFindCall += 1; - } - - // iterator test - 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 - 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 - 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 - 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 )); - guarded_ptr gp(s.get( h )); - CPPUNIT_ASSERT( !gp ); - 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 ); - - gp = s.get( h ); - CPPUNIT_ASSERT( gp ); - CPPUNIT_ASSERT( gp->nInsertCall == 1 ); - CPPUNIT_ASSERT( gp->key == i ); - CPPUNIT_ASSERT( gp->hash == h ); - } - CPPUNIT_ASSERT( !s.empty() ); - CPPUNIT_ASSERT(s.size() == capacity ); - - // erase_at( iterator ) test - for ( auto it = s.begin(), itEnd = s.end(); it != itEnd; ++it ) { - CPPUNIT_ASSERT( s.erase_at( it )); - } - 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 ); - - // erase_at( reverse_iterator ) test - for ( auto it = s.rbegin(), itEnd = s.rend(); it != itEnd; ++it ) { - CPPUNIT_ASSERT( s.erase_at( it )); - } - CPPUNIT_ASSERT( s.empty() ); - CPPUNIT_ASSERT( s.size() == 0 ); - - // extract test - for ( size_t i = 0; i < capacity; ++i ) { - hash_type h = hasher(i); - CPPUNIT_ASSERT( !s.contains( h )); - CPPUNIT_ASSERT( s.emplace( arg_type( i, hasher(i) ))); - CPPUNIT_ASSERT(s.contains( h )); - - CPPUNIT_ASSERT( !s.empty() ); - CPPUNIT_ASSERT( s.size() == i + 1); - - CPPUNIT_ASSERT( !s.emplace( i, h )); - CPPUNIT_ASSERT( s.size() == i + 1); - } - CPPUNIT_ASSERT( !s.empty() ); - CPPUNIT_ASSERT(s.size() == capacity ); - - for ( size_t i = capacity; i != 0; --i ) { - CPPUNIT_ASSERT( !s.empty() ); - CPPUNIT_ASSERT( s.size() == i ); - - guarded_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))); - - gp = s.get(hasher(i-1)); - CPPUNIT_ASSERT( !gp ); - - CPPUNIT_ASSERT( s.size() == i - 1 ); - } - CPPUNIT_ASSERT( s.empty() ); - CPPUNIT_ASSERT(s.size() == 0 ); - - // clear test - for ( size_t i = 0; i < capacity; ++i ) { - hash_type h = hasher(i); - CPPUNIT_ASSERT( !s.contains( h )); - CPPUNIT_ASSERT( s.emplace( arg_type( i, hasher(i) ))); - CPPUNIT_ASSERT(s.contains( h )); - - CPPUNIT_ASSERT( !s.empty() ); - CPPUNIT_ASSERT( s.size() == i + 1); - - CPPUNIT_ASSERT( !s.emplace( i, h )); - CPPUNIT_ASSERT( s.size() == i + 1); - } - CPPUNIT_ASSERT( !s.empty() ); - CPPUNIT_ASSERT(s.size() == capacity ); - - s.clear(); - CPPUNIT_ASSERT( s.empty() ); - CPPUNIT_ASSERT(s.size() == 0 ); - - 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_nohash(); - void hp_nohash_stat(); - void hp_nohash_5_3(); - void hp_nohash_5_3_stat(); - void hp_stdhash(); - 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_nohash(); - void dhp_nohash_stat(); - void dhp_nohash_5_3(); - void dhp_nohash_5_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(); - - void rcu_gpi_nohash(); - void rcu_gpi_nohash_stat(); - void rcu_gpi_nohash_5_3(); - void rcu_gpi_nohash_5_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_nohash(); - void rcu_gpb_nohash_stat(); - void rcu_gpb_nohash_5_3(); - void rcu_gpb_nohash_5_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_nohash(); - void rcu_gpt_nohash_stat(); - void rcu_gpt_nohash_5_3(); - void rcu_gpt_nohash_5_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_nohash(); - void rcu_shb_nohash_stat(); - void rcu_shb_nohash_5_3(); - void rcu_shb_nohash_5_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_nohash(); - void rcu_sht_nohash_stat(); - void rcu_sht_nohash_5_3(); - void rcu_sht_nohash_5_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_nohash) - CPPUNIT_TEST(hp_nohash_stat) - CPPUNIT_TEST(hp_nohash_5_3) - CPPUNIT_TEST(hp_nohash_5_3_stat) - 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_nohash) - CPPUNIT_TEST(dhp_nohash_stat) - CPPUNIT_TEST(dhp_nohash_5_3) - CPPUNIT_TEST(dhp_nohash_5_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(rcu_gpi_nohash) - CPPUNIT_TEST(rcu_gpi_nohash_stat) - CPPUNIT_TEST(rcu_gpi_nohash_5_3) - CPPUNIT_TEST(rcu_gpi_nohash_5_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_nohash) - CPPUNIT_TEST(rcu_gpb_nohash_stat) - CPPUNIT_TEST(rcu_gpb_nohash_5_3) - CPPUNIT_TEST(rcu_gpb_nohash_5_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_nohash) - CPPUNIT_TEST(rcu_gpt_nohash_stat) - CPPUNIT_TEST(rcu_gpt_nohash_5_3) - CPPUNIT_TEST(rcu_gpt_nohash_5_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_nohash) - CPPUNIT_TEST(rcu_shb_nohash_stat) - CPPUNIT_TEST(rcu_shb_nohash_5_3) - CPPUNIT_TEST(rcu_shb_nohash_5_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_nohash) - CPPUNIT_TEST(rcu_sht_nohash_stat) - CPPUNIT_TEST(rcu_sht_nohash_5_3) - CPPUNIT_TEST(rcu_sht_nohash_5_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() - }; - -} // namespace set - -#endif // #ifndef CDSTEST_HDR_MULTILEVEL_HASHSET_H diff --git a/tests/test-hdr/set/hdr_multilevel_hashset_dhp.cpp b/tests/test-hdr/set/hdr_multilevel_hashset_dhp.cpp deleted file mode 100644 index 02989fda..00000000 --- a/tests/test-hdr/set/hdr_multilevel_hashset_dhp.cpp +++ /dev/null @@ -1,299 +0,0 @@ -//$$CDS-header$$ - -#include "set/hdr_multilevel_hashset.h" -#include -#include "unit/print_multilevel_hashset_stat.h" - -namespace set { - namespace { - typedef cds::gc::DHP gc_type; - } // namespace - - void MultiLevelHashSetHdrTest::dhp_nohash() - { - typedef size_t key_type; - - struct traits : public cc::multilevel_hashset::traits - { - typedef get_key hash_accessor; - }; - typedef cc::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 cc::MultiLevelHashSet< - gc_type, - Item, - typename cc::multilevel_hashset::make_traits< - cc::multilevel_hashset::hash_accessor< get_key> - >::type - > set_type2; - test_hp>(4, 2); - } - - void MultiLevelHashSetHdrTest::dhp_stdhash() - { - typedef size_t hash_type; - - struct traits: public cc::multilevel_hashset::traits - { - typedef get_hash hash_accessor; - }; - typedef cc::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 cc::MultiLevelHashSet< - gc_type, - Item, - typename cc::multilevel_hashset::make_traits< - cc::multilevel_hashset::hash_accessor< get_hash> - >::type - > set_type2; - test_hp>(4, 2); - } - - void MultiLevelHashSetHdrTest::dhp_hash128() - { - typedef hash128 hash_type; - - struct traits: public cc::multilevel_hashset::traits - { - typedef get_hash hash_accessor; - typedef hash128::less less; - }; - typedef cc::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 cc::MultiLevelHashSet< - gc_type, - Item, - typename cc::multilevel_hashset::make_traits< - cc::multilevel_hashset::hash_accessor< get_hash> - , co::less< hash_type::less > - >::type - > set_type2; - test_hp(4, 2); - } - - void MultiLevelHashSetHdrTest::dhp_nohash_stat() - { - typedef size_t key_type; - - struct traits : public cc::multilevel_hashset::traits - { - typedef get_key hash_accessor; - typedef cc::multilevel_hashset::stat<> stat; - }; - typedef cc::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 cc::MultiLevelHashSet< - gc_type, - Item, - typename cc::multilevel_hashset::make_traits< - cc::multilevel_hashset::hash_accessor< get_key> - , co::stat< cc::multilevel_hashset::stat<>> - >::type - > set_type2; - test_hp>(4, 2); - } - - void MultiLevelHashSetHdrTest::dhp_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< 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 cc::MultiLevelHashSet< - gc_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_hp>(4, 2); - } - - void MultiLevelHashSetHdrTest::dhp_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< 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 cc::MultiLevelHashSet< - gc_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_hp(4, 2); - } - - void MultiLevelHashSetHdrTest::dhp_nohash_5_3() - { - typedef size_t key_type; - - struct traits: public cc::multilevel_hashset::traits - { - typedef get_key hash_accessor; - }; - typedef cc::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 cc::MultiLevelHashSet< - gc_type, - Item, - typename cc::multilevel_hashset::make_traits< - cc::multilevel_hashset::hash_accessor< get_key> - >::type - > set_type2; - test_hp>(5, 3); - } - - void MultiLevelHashSetHdrTest::dhp_stdhash_5_3() - { - typedef size_t hash_type; - - struct traits: public cc::multilevel_hashset::traits - { - typedef get_hash hash_accessor; - }; - typedef cc::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 cc::MultiLevelHashSet< - gc_type, - Item, - typename cc::multilevel_hashset::make_traits< - cc::multilevel_hashset::hash_accessor< get_hash> - >::type - > set_type2; - test_hp>(5, 3); - } - - void MultiLevelHashSetHdrTest::dhp_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< 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 cc::MultiLevelHashSet< - gc_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_hp(4, 3); - } - - void MultiLevelHashSetHdrTest::dhp_nohash_5_3_stat() - { - typedef size_t key_type; - - struct traits: public cc::multilevel_hashset::traits - { - typedef get_key hash_accessor; - typedef cc::multilevel_hashset::stat<> stat; - }; - typedef cc::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 cc::MultiLevelHashSet< - gc_type, - Item, - typename cc::multilevel_hashset::make_traits< - cc::multilevel_hashset::hash_accessor< get_key> - ,co::stat< cc::multilevel_hashset::stat<>> - >::type - > set_type2; - test_hp>(5, 3); - } - - void MultiLevelHashSetHdrTest::dhp_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< 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 cc::MultiLevelHashSet< - gc_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_hp>(5, 3); - } - - void MultiLevelHashSetHdrTest::dhp_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< 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 cc::MultiLevelHashSet< - gc_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_hp(4, 3); - } - - -} // namespace set diff --git a/tests/test-hdr/set/hdr_multilevel_hashset_hp.cpp b/tests/test-hdr/set/hdr_multilevel_hashset_hp.cpp deleted file mode 100644 index 11e6f160..00000000 --- a/tests/test-hdr/set/hdr_multilevel_hashset_hp.cpp +++ /dev/null @@ -1,301 +0,0 @@ -//$$CDS-header$$ - -#include "set/hdr_multilevel_hashset.h" -#include -#include "unit/print_multilevel_hashset_stat.h" - -namespace set { - namespace { - typedef cds::gc::HP gc_type; - } // namespace - - void MultiLevelHashSetHdrTest::hp_nohash() - { - typedef size_t key_type; - - struct traits : public cc::multilevel_hashset::traits - { - typedef get_key hash_accessor; - }; - typedef cc::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 cc::MultiLevelHashSet< - gc_type, - Item, - typename cc::multilevel_hashset::make_traits< - cc::multilevel_hashset::hash_accessor< get_key> - >::type - > set_type2; - test_hp>(4, 2); - } - - void MultiLevelHashSetHdrTest::hp_stdhash() - { - typedef size_t hash_type; - - struct traits: public cc::multilevel_hashset::traits - { - typedef get_hash hash_accessor; - }; - typedef cc::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 cc::MultiLevelHashSet< - gc_type, - Item, - typename cc::multilevel_hashset::make_traits< - cc::multilevel_hashset::hash_accessor< get_hash> - >::type - > set_type2; - test_hp>(4, 2); - } - - void MultiLevelHashSetHdrTest::hp_hash128() - { - typedef hash128 hash_type; - - struct traits: public cc::multilevel_hashset::traits - { - typedef get_hash hash_accessor; - typedef hash128::less less; - }; - typedef cc::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 cc::MultiLevelHashSet< - gc_type, - Item, - typename cc::multilevel_hashset::make_traits< - cc::multilevel_hashset::hash_accessor< get_hash> - , co::less< hash_type::less > - >::type - > set_type2; - test_hp(4, 2); - } - - void MultiLevelHashSetHdrTest::hp_nohash_stat() - { - typedef size_t key_type; - - struct traits : public cc::multilevel_hashset::traits - { - typedef get_key hash_accessor; - typedef cc::multilevel_hashset::stat<> stat; - }; - typedef cc::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 cc::MultiLevelHashSet< - gc_type, - Item, - typename cc::multilevel_hashset::make_traits< - cc::multilevel_hashset::hash_accessor< get_key> - , co::stat< cc::multilevel_hashset::stat<>> - >::type - > set_type2; - test_hp>(4, 2); - } - - void MultiLevelHashSetHdrTest::hp_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< 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 cc::MultiLevelHashSet< - gc_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_hp>(4, 2); - } - - void MultiLevelHashSetHdrTest::hp_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< 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 cc::MultiLevelHashSet< - gc_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_hp(4, 2); - } - - void MultiLevelHashSetHdrTest::hp_nohash_5_3() - { - typedef size_t key_type; - - struct traits: public cc::multilevel_hashset::traits - { - typedef get_key hash_accessor; - }; - typedef cc::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 cc::MultiLevelHashSet< - gc_type, - Item, - typename cc::multilevel_hashset::make_traits< - cc::multilevel_hashset::hash_accessor< get_key> - >::type - > set_type2; - test_hp>(5, 3); - } - - void MultiLevelHashSetHdrTest::hp_stdhash_5_3() - { - typedef size_t hash_type; - - struct traits: public cc::multilevel_hashset::traits - { - typedef get_hash hash_accessor; - }; - typedef cc::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 cc::MultiLevelHashSet< - gc_type, - Item, - typename cc::multilevel_hashset::make_traits< - cc::multilevel_hashset::hash_accessor< get_hash> - >::type - > set_type2; - test_hp>(5, 3); - } - - void MultiLevelHashSetHdrTest::hp_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< 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 cc::MultiLevelHashSet< - gc_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_hp(4, 3); - } - - void MultiLevelHashSetHdrTest::hp_nohash_5_3_stat() - { - typedef size_t key_type; - - struct traits: public cc::multilevel_hashset::traits - { - typedef get_key hash_accessor; - typedef cc::multilevel_hashset::stat<> stat; - }; - typedef cc::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 cc::MultiLevelHashSet< - gc_type, - Item, - typename cc::multilevel_hashset::make_traits< - cc::multilevel_hashset::hash_accessor< get_key> - ,co::stat< cc::multilevel_hashset::stat<>> - >::type - > set_type2; - test_hp>(5, 3); - } - - void MultiLevelHashSetHdrTest::hp_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< 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 cc::MultiLevelHashSet< - gc_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_hp>(5, 3); - } - - void MultiLevelHashSetHdrTest::hp_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< 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 cc::MultiLevelHashSet< - gc_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_hp(4, 3); - } - - -} // namespace set - -CPPUNIT_TEST_SUITE_REGISTRATION(set::MultiLevelHashSetHdrTest); diff --git a/tests/test-hdr/set/hdr_multilevel_hashset_rcu_gpb.cpp b/tests/test-hdr/set/hdr_multilevel_hashset_rcu_gpb.cpp deleted file mode 100644 index b44bb6ec..00000000 --- a/tests/test-hdr/set/hdr_multilevel_hashset_rcu_gpb.cpp +++ /dev/null @@ -1,300 +0,0 @@ -//$$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_nohash() - { - typedef size_t key_type; - - struct traits : public cc::multilevel_hashset::traits - { - typedef get_key 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_key> - >::type - > set_type2; - test_rcu>(4, 2); - } - - 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_nohash_stat() - { - typedef size_t key_type; - - struct traits : public cc::multilevel_hashset::traits - { - typedef get_key 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_key> - , co::stat< cc::multilevel_hashset::stat<>> - >::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_nohash_5_3() - { - typedef size_t key_type; - - struct traits: public cc::multilevel_hashset::traits - { - typedef get_key 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_key> - >::type - > set_type2; - test_rcu>(5, 3); - } - - 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_nohash_5_3_stat() - { - typedef size_t key_type; - - struct traits: public cc::multilevel_hashset::traits - { - typedef get_key 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_key> - ,co::stat< cc::multilevel_hashset::stat<>> - >::type - > set_type2; - test_rcu>(5, 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 deleted file mode 100644 index 946a5fe3..00000000 --- a/tests/test-hdr/set/hdr_multilevel_hashset_rcu_gpi.cpp +++ /dev/null @@ -1,300 +0,0 @@ -//$$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_nohash() - { - typedef size_t key_type; - - struct traits : public cc::multilevel_hashset::traits - { - typedef get_key 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_key> - >::type - > set_type2; - test_rcu>(4, 2); - } - - 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_nohash_stat() - { - typedef size_t key_type; - - struct traits : public cc::multilevel_hashset::traits - { - typedef get_key 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_key> - , co::stat< cc::multilevel_hashset::stat<>> - >::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_nohash_5_3() - { - typedef size_t key_type; - - struct traits: public cc::multilevel_hashset::traits - { - typedef get_key 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_key> - >::type - > set_type2; - test_rcu>(5, 3); - } - - 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_nohash_5_3_stat() - { - typedef size_t key_type; - - struct traits: public cc::multilevel_hashset::traits - { - typedef get_key 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_key> - ,co::stat< cc::multilevel_hashset::stat<>> - >::type - > set_type2; - test_rcu>(5, 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 deleted file mode 100644 index a209533b..00000000 --- a/tests/test-hdr/set/hdr_multilevel_hashset_rcu_gpt.cpp +++ /dev/null @@ -1,300 +0,0 @@ -//$$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_nohash() - { - typedef size_t key_type; - - struct traits : public cc::multilevel_hashset::traits - { - typedef get_key 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_key> - >::type - > set_type2; - test_rcu>(4, 2); - } - - 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_nohash_stat() - { - typedef size_t key_type; - - struct traits : public cc::multilevel_hashset::traits - { - typedef get_key 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_key> - , co::stat< cc::multilevel_hashset::stat<>> - >::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_nohash_5_3() - { - typedef size_t key_type; - - struct traits: public cc::multilevel_hashset::traits - { - typedef get_key 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_key> - >::type - > set_type2; - test_rcu>(5, 3); - } - - 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_nohash_5_3_stat() - { - typedef size_t key_type; - - struct traits: public cc::multilevel_hashset::traits - { - typedef get_key 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_key> - ,co::stat< cc::multilevel_hashset::stat<>> - >::type - > set_type2; - test_rcu>(5, 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 deleted file mode 100644 index eaf261c2..00000000 --- a/tests/test-hdr/set/hdr_multilevel_hashset_rcu_shb.cpp +++ /dev/null @@ -1,324 +0,0 @@ -//$$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_nohash() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef size_t key_type; - - struct traits : public cc::multilevel_hashset::traits - { - typedef get_key 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_key> - >::type - > set_type2; - test_rcu>(4, 2); -#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_nohash_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef size_t key_type; - - struct traits : public cc::multilevel_hashset::traits - { - typedef get_key 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_key> - , co::stat< cc::multilevel_hashset::stat<>> - >::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_nohash_5_3() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef size_t key_type; - - struct traits: public cc::multilevel_hashset::traits - { - typedef get_key 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_key> - >::type - > set_type2; - test_rcu>(5, 3); -#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_nohash_5_3_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef size_t key_type; - - struct traits: public cc::multilevel_hashset::traits - { - typedef get_key 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_key> - ,co::stat< cc::multilevel_hashset::stat<>> - >::type - > set_type2; - test_rcu>(5, 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 deleted file mode 100644 index 9147939c..00000000 --- a/tests/test-hdr/set/hdr_multilevel_hashset_rcu_sht.cpp +++ /dev/null @@ -1,324 +0,0 @@ -//$$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_nohash() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef size_t key_type; - - struct traits : public cc::multilevel_hashset::traits - { - typedef get_key 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_key> - >::type - > set_type2; - test_rcu>(4, 2); -#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_nohash_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef size_t key_type; - - struct traits : public cc::multilevel_hashset::traits - { - typedef get_key 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_key> - , co::stat< cc::multilevel_hashset::stat<>> - >::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_nohash_5_3() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef size_t key_type; - - struct traits: public cc::multilevel_hashset::traits - { - typedef get_key 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_key> - >::type - > set_type2; - test_rcu>(5, 3); -#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_nohash_5_3_stat() - { -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef size_t key_type; - - struct traits: public cc::multilevel_hashset::traits - { - typedef get_key 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_key> - ,co::stat< cc::multilevel_hashset::stat<>> - >::type - > set_type2; - test_rcu>(5, 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 diff --git a/tests/unit/map2/CMakeLists.txt b/tests/unit/map2/CMakeLists.txt index 454721ae..dc30aa0e 100644 --- a/tests/unit/map2/CMakeLists.txt +++ b/tests/unit/map2/CMakeLists.txt @@ -6,7 +6,7 @@ set(CDSUNIT_MAP_SOURCES map_find_int_cuckoo.cpp map_find_int_ellentree.cpp map_find_int_michael.cpp - map_find_int_multilevelhashmap.cpp + map_find_int_feldmanhashmap.cpp map_find_int_skip.cpp map_find_int_split.cpp map_find_int_striped.cpp @@ -16,7 +16,7 @@ set(CDSUNIT_MAP_SOURCES map_find_string_cuckoo.cpp map_find_string_ellentree.cpp map_find_string_michael.cpp - map_find_string_multilevelhashmap.cpp + map_find_string_feldmanhashmap.cpp map_find_string_skip.cpp map_find_string_split.cpp map_find_string_striped.cpp @@ -36,7 +36,7 @@ set(CDSUNIT_MAP_SOURCES map_insdel_func_cuckoo.cpp map_insdel_func_ellentree.cpp map_insdel_func_michael.cpp - map_insdel_func_multilevelhashmap.cpp + map_insdel_func_feldmanhashmap.cpp map_insdel_func_skip.cpp map_insdel_func_split.cpp map_insdel_func_striped.cpp @@ -45,7 +45,7 @@ set(CDSUNIT_MAP_SOURCES map_insdel_int_cuckoo.cpp map_insdel_int_ellentree.cpp map_insdel_int_michael.cpp - map_insdel_int_multilevelhashmap.cpp + map_insdel_int_feldmanhashmap.cpp map_insdel_int_skip.cpp map_insdel_int_split.cpp map_insdel_int_striped.cpp @@ -55,7 +55,7 @@ set(CDSUNIT_MAP_SOURCES map_insdel_item_int_cuckoo.cpp map_insdel_item_int_ellentree.cpp map_insdel_item_int_michael.cpp - map_insdel_item_int_multilevelhashmap.cpp + map_insdel_item_int_feldmanhashmap.cpp map_insdel_item_int_skip.cpp map_insdel_item_int_split.cpp map_insdel_item_int_striped.cpp @@ -64,7 +64,7 @@ set(CDSUNIT_MAP_SOURCES map_insdel_item_string_cuckoo.cpp map_insdel_item_string_ellentree.cpp map_insdel_item_string_michael.cpp - map_insdel_item_string_multilevelhashmap.cpp + map_insdel_item_string_feldmanhashmap.cpp map_insdel_item_string_skip.cpp map_insdel_item_string_split.cpp map_insdel_item_string_striped.cpp @@ -73,7 +73,7 @@ set(CDSUNIT_MAP_SOURCES map_insdel_string_cuckoo.cpp map_insdel_string_ellentree.cpp map_insdel_string_michael.cpp - map_insdel_string_multilevelhashmap.cpp + map_insdel_string_feldmanhashmap.cpp map_insdel_string_skip.cpp map_insdel_string_split.cpp map_insdel_string_striped.cpp @@ -83,7 +83,7 @@ set(CDSUNIT_MAP_SOURCES map_insdelfind_cuckoo.cpp map_insdelfind_ellentree.cpp map_insdelfind_michael.cpp - map_insdelfind_multilevelhashmap.cpp + map_insdelfind_feldmanhashmap.cpp map_insdelfind_skip.cpp map_insdelfind_split.cpp map_insdelfind_striped.cpp @@ -93,7 +93,7 @@ set(CDSUNIT_MAP_SOURCES map_delodd_cuckoo.cpp map_delodd_ellentree.cpp map_delodd_michael.cpp - map_delodd_multilevelhashmap.cpp + map_delodd_feldmanhashmap.cpp map_delodd_split.cpp map_delodd_skip.cpp ) diff --git a/tests/unit/map2/map_defs.h b/tests/unit/map2/map_defs.h index 8de1ba64..b44879de 100644 --- a/tests/unit/map2/map_defs.h +++ b/tests/unit/map2/map_defs.h @@ -727,351 +727,351 @@ // ************************************************************************************** -// MultiLevelHashMap +// FeldmanHashMap // fixed-sized key - no hash function is necessary -#undef CDSUNIT_DECLARE_MultiLevelHashMap_fixed -#undef CDSUNIT_DECLARE_MultiLevelHashMap_fixed_RCU_Signal -#undef CDSUNIT_TEST_MultiLevelHashMap_fixed -#undef CDSUNIT_TEST_MultiLevelHashMap_fixed_RCU_Signal +#undef CDSUNIT_DECLARE_FeldmanHashMap_fixed +#undef CDSUNIT_DECLARE_FeldmanHashMap_fixed_RCU_Signal +#undef CDSUNIT_TEST_FeldmanHashMap_fixed +#undef CDSUNIT_TEST_FeldmanHashMap_fixed_RCU_Signal #ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED -# define CDSUNIT_DECLARE_MultiLevelHashMap_fixed_RCU_Signal \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_shb_fixed) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_shb_fixed_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_sht_fixed) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_sht_fixed_stat) \ - -# define CDSUNIT_TEST_MultiLevelHashMap_fixed_RCU_Signal \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_shb_fixed) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_shb_fixed_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_sht_fixed) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_sht_fixed_stat) \ +# define CDSUNIT_DECLARE_FeldmanHashMap_fixed_RCU_Signal \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_shb_fixed) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_shb_fixed_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_sht_fixed) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_sht_fixed_stat) \ + +# define CDSUNIT_TEST_FeldmanHashMap_fixed_RCU_Signal \ + CPPUNIT_TEST(FeldmanHashMap_rcu_shb_fixed) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_shb_fixed_stat) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_sht_fixed) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_sht_fixed_stat) \ #else -# define CDSUNIT_DECLARE_MultiLevelHashMap_fixed_RCU_Signal -# define CDSUNIT_TEST_MultiLevelHashMap_fixed_RCU_Signal +# define CDSUNIT_DECLARE_FeldmanHashMap_fixed_RCU_Signal +# define CDSUNIT_TEST_FeldmanHashMap_fixed_RCU_Signal #endif -#define CDSUNIT_DECLARE_MultiLevelHashMap_fixed \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_hp_fixed) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_hp_fixed_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_dhp_fixed) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_dhp_fixed_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpi_fixed) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpi_fixed_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpb_fixed) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpb_fixed_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpt_fixed) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpt_fixed_stat) \ - CDSUNIT_DECLARE_MultiLevelHashMap_fixed_RCU_Signal - -#define CDSUNIT_TEST_MultiLevelHashMap_fixed \ - CPPUNIT_TEST(MultiLevelHashMap_hp_fixed) \ - CPPUNIT_TEST(MultiLevelHashMap_hp_fixed_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_dhp_fixed) \ - CPPUNIT_TEST(MultiLevelHashMap_dhp_fixed_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpi_fixed) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpi_fixed_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpb_fixed) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpb_fixed_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpt_fixed) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpt_fixed_stat) \ - CDSUNIT_TEST_MultiLevelHashMap_fixed_RCU_Signal +#define CDSUNIT_DECLARE_FeldmanHashMap_fixed \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_hp_fixed) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_hp_fixed_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_dhp_fixed) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_dhp_fixed_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpi_fixed) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpi_fixed_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpb_fixed) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpb_fixed_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpt_fixed) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpt_fixed_stat) \ + CDSUNIT_DECLARE_FeldmanHashMap_fixed_RCU_Signal + +#define CDSUNIT_TEST_FeldmanHashMap_fixed \ + CPPUNIT_TEST(FeldmanHashMap_hp_fixed) \ + CPPUNIT_TEST(FeldmanHashMap_hp_fixed_stat) \ + CPPUNIT_TEST(FeldmanHashMap_dhp_fixed) \ + CPPUNIT_TEST(FeldmanHashMap_dhp_fixed_stat) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpi_fixed) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpi_fixed_stat) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpb_fixed) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpb_fixed_stat) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpt_fixed) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpt_fixed_stat) \ + CDSUNIT_TEST_FeldmanHashMap_fixed_RCU_Signal // std::hash -#undef CDSUNIT_DECLARE_MultiLevelHashMap_stdhash -#undef CDSUNIT_DECLARE_MultiLevelHashMap_stdhash_RCU_Signal -#undef CDSUNIT_TEST_MultiLevelHashMap_stdhash -#undef CDSUNIT_TEST_MultiLevelHashMap_stdhash_RCU_Signal +#undef CDSUNIT_DECLARE_FeldmanHashMap_stdhash +#undef CDSUNIT_DECLARE_FeldmanHashMap_stdhash_RCU_Signal +#undef CDSUNIT_TEST_FeldmanHashMap_stdhash +#undef CDSUNIT_TEST_FeldmanHashMap_stdhash_RCU_Signal #ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED -# define CDSUNIT_DECLARE_MultiLevelHashMap_stdhash_RCU_Signal \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_shb_stdhash) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_shb_stdhash_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_sht_stdhash) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_sht_stdhash_stat) \ - -# define CDSUNIT_TEST_MultiLevelHashMap_stdhash_RCU_Signal \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_shb_stdhash) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_shb_stdhash_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_sht_stdhash) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_sht_stdhash_stat) \ +# define CDSUNIT_DECLARE_FeldmanHashMap_stdhash_RCU_Signal \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_shb_stdhash) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_shb_stdhash_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_sht_stdhash) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_sht_stdhash_stat) \ + +# define CDSUNIT_TEST_FeldmanHashMap_stdhash_RCU_Signal \ + CPPUNIT_TEST(FeldmanHashMap_rcu_shb_stdhash) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_shb_stdhash_stat) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_sht_stdhash) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_sht_stdhash_stat) \ #else -# define CDSUNIT_DECLARE_MultiLevelHashMap_stdhash_RCU_Signal -# define CDSUNIT_TEST_MultiLevelHashMap_stdhash_RCU_Signal +# define CDSUNIT_DECLARE_FeldmanHashMap_stdhash_RCU_Signal +# define CDSUNIT_TEST_FeldmanHashMap_stdhash_RCU_Signal #endif -#define CDSUNIT_DECLARE_MultiLevelHashMap_stdhash \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_hp_stdhash) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_hp_stdhash_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_dhp_stdhash) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_dhp_stdhash_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpi_stdhash) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpi_stdhash_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpb_stdhash) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpb_stdhash_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpt_stdhash) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpt_stdhash_stat) \ - CDSUNIT_DECLARE_MultiLevelHashMap_stdhash_RCU_Signal - -#define CDSUNIT_TEST_MultiLevelHashMap_stdhash \ - CPPUNIT_TEST(MultiLevelHashMap_hp_stdhash) \ - CPPUNIT_TEST(MultiLevelHashMap_hp_stdhash_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_dhp_stdhash) \ - CPPUNIT_TEST(MultiLevelHashMap_dhp_stdhash_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpi_stdhash) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpi_stdhash_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpb_stdhash) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpb_stdhash_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpt_stdhash) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpt_stdhash_stat) \ - CDSUNIT_TEST_MultiLevelHashMap_stdhash_RCU_Signal +#define CDSUNIT_DECLARE_FeldmanHashMap_stdhash \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_hp_stdhash) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_hp_stdhash_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_dhp_stdhash) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_dhp_stdhash_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpi_stdhash) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpi_stdhash_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpb_stdhash) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpb_stdhash_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpt_stdhash) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpt_stdhash_stat) \ + CDSUNIT_DECLARE_FeldmanHashMap_stdhash_RCU_Signal + +#define CDSUNIT_TEST_FeldmanHashMap_stdhash \ + CPPUNIT_TEST(FeldmanHashMap_hp_stdhash) \ + CPPUNIT_TEST(FeldmanHashMap_hp_stdhash_stat) \ + CPPUNIT_TEST(FeldmanHashMap_dhp_stdhash) \ + CPPUNIT_TEST(FeldmanHashMap_dhp_stdhash_stat) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpi_stdhash) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpi_stdhash_stat) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpb_stdhash) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpb_stdhash_stat) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpt_stdhash) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpt_stdhash_stat) \ + CDSUNIT_TEST_FeldmanHashMap_stdhash_RCU_Signal // MD5 -#undef CDSUNIT_DECLARE_MultiLevelHashMap_md5 -#undef CDSUNIT_DECLARE_MultiLevelHashMap_md5_RCU_Signal -#undef CDSUNIT_TEST_MultiLevelHashMap_md5 -#undef CDSUNIT_TEST_MultiLevelHashMap_md5_RCU_Signal +#undef CDSUNIT_DECLARE_FeldmanHashMap_md5 +#undef CDSUNIT_DECLARE_FeldmanHashMap_md5_RCU_Signal +#undef CDSUNIT_TEST_FeldmanHashMap_md5 +#undef CDSUNIT_TEST_FeldmanHashMap_md5_RCU_Signal #ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED -# define CDSUNIT_DECLARE_MultiLevelHashMap_md5_RCU_Signal \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_shb_md5) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_shb_md5_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_sht_md5) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_sht_md5_stat) \ - -# define CDSUNIT_TEST_MultiLevelHashMap_md5_RCU_Signal \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_shb_md5) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_shb_md5_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_sht_md5) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_sht_md5_stat) \ +# define CDSUNIT_DECLARE_FeldmanHashMap_md5_RCU_Signal \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_shb_md5) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_shb_md5_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_sht_md5) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_sht_md5_stat) \ + +# define CDSUNIT_TEST_FeldmanHashMap_md5_RCU_Signal \ + CPPUNIT_TEST(FeldmanHashMap_rcu_shb_md5) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_shb_md5_stat) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_sht_md5) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_sht_md5_stat) \ #else -# define CDSUNIT_DECLARE_MultiLevelHashMap_md5_RCU_Signal -# define CDSUNIT_TEST_MultiLevelHashMap_md5_RCU_Signal +# define CDSUNIT_DECLARE_FeldmanHashMap_md5_RCU_Signal +# define CDSUNIT_TEST_FeldmanHashMap_md5_RCU_Signal #endif -#define CDSUNIT_DECLARE_MultiLevelHashMap_md5 \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_hp_md5) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_hp_md5_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_dhp_md5) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_dhp_md5_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpi_md5) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpi_md5_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpb_md5) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpb_md5_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpt_md5) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpt_md5_stat) \ - CDSUNIT_DECLARE_MultiLevelHashMap_md5_RCU_Signal - -#define CDSUNIT_TEST_MultiLevelHashMap_md5 \ - CPPUNIT_TEST(MultiLevelHashMap_hp_md5) \ - CPPUNIT_TEST(MultiLevelHashMap_hp_md5_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_dhp_md5) \ - CPPUNIT_TEST(MultiLevelHashMap_dhp_md5_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpi_md5) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpi_md5_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpb_md5) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpb_md5_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpt_md5) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpt_md5_stat) \ - CDSUNIT_TEST_MultiLevelHashMap_md5_RCU_Signal +#define CDSUNIT_DECLARE_FeldmanHashMap_md5 \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_hp_md5) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_hp_md5_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_dhp_md5) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_dhp_md5_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpi_md5) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpi_md5_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpb_md5) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpb_md5_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpt_md5) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpt_md5_stat) \ + CDSUNIT_DECLARE_FeldmanHashMap_md5_RCU_Signal + +#define CDSUNIT_TEST_FeldmanHashMap_md5 \ + CPPUNIT_TEST(FeldmanHashMap_hp_md5) \ + CPPUNIT_TEST(FeldmanHashMap_hp_md5_stat) \ + CPPUNIT_TEST(FeldmanHashMap_dhp_md5) \ + CPPUNIT_TEST(FeldmanHashMap_dhp_md5_stat) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpi_md5) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpi_md5_stat) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpb_md5) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpb_md5_stat) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpt_md5) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpt_md5_stat) \ + CDSUNIT_TEST_FeldmanHashMap_md5_RCU_Signal // SHA256 -#undef CDSUNIT_DECLARE_MultiLevelHashMap_sha256 -#undef CDSUNIT_DECLARE_MultiLevelHashMap_sha256_RCU_Signal -#undef CDSUNIT_TEST_MultiLevelHashMap_sha256 -#undef CDSUNIT_TEST_MultiLevelHashMap_sha256_RCU_Signal +#undef CDSUNIT_DECLARE_FeldmanHashMap_sha256 +#undef CDSUNIT_DECLARE_FeldmanHashMap_sha256_RCU_Signal +#undef CDSUNIT_TEST_FeldmanHashMap_sha256 +#undef CDSUNIT_TEST_FeldmanHashMap_sha256_RCU_Signal #ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED -# define CDSUNIT_DECLARE_MultiLevelHashMap_sha256_RCU_Signal \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_shb_sha256) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_shb_sha256_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_sht_sha256) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_sht_sha256_stat) \ - -# define CDSUNIT_TEST_MultiLevelHashMap_sha256_RCU_Signal \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_shb_sha256) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_shb_sha256_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_sht_sha256) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_sht_sha256_stat) \ +# define CDSUNIT_DECLARE_FeldmanHashMap_sha256_RCU_Signal \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_shb_sha256) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_shb_sha256_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_sht_sha256) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_sht_sha256_stat) \ + +# define CDSUNIT_TEST_FeldmanHashMap_sha256_RCU_Signal \ + CPPUNIT_TEST(FeldmanHashMap_rcu_shb_sha256) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_shb_sha256_stat) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_sht_sha256) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_sht_sha256_stat) \ #else -# define CDSUNIT_DECLARE_MultiLevelHashMap_sha256_RCU_Signal -# define CDSUNIT_TEST_MultiLevelHashMap_sha256_RCU_Signal +# define CDSUNIT_DECLARE_FeldmanHashMap_sha256_RCU_Signal +# define CDSUNIT_TEST_FeldmanHashMap_sha256_RCU_Signal #endif -#define CDSUNIT_DECLARE_MultiLevelHashMap_sha256 \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_hp_sha256) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_hp_sha256_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_dhp_sha256) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_dhp_sha256_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpi_sha256) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpi_sha256_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpb_sha256) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpb_sha256_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpt_sha256) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpt_sha256_stat) \ - CDSUNIT_DECLARE_MultiLevelHashMap_sha256_RCU_Signal - -#define CDSUNIT_TEST_MultiLevelHashMap_sha256 \ - CPPUNIT_TEST(MultiLevelHashMap_hp_sha256) \ - CPPUNIT_TEST(MultiLevelHashMap_hp_sha256_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_dhp_sha256) \ - CPPUNIT_TEST(MultiLevelHashMap_dhp_sha256_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpi_sha256) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpi_sha256_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpb_sha256) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpb_sha256_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpt_sha256) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpt_sha256_stat) \ - CDSUNIT_TEST_MultiLevelHashMap_sha256_RCU_Signal +#define CDSUNIT_DECLARE_FeldmanHashMap_sha256 \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_hp_sha256) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_hp_sha256_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_dhp_sha256) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_dhp_sha256_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpi_sha256) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpi_sha256_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpb_sha256) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpb_sha256_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpt_sha256) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpt_sha256_stat) \ + CDSUNIT_DECLARE_FeldmanHashMap_sha256_RCU_Signal + +#define CDSUNIT_TEST_FeldmanHashMap_sha256 \ + CPPUNIT_TEST(FeldmanHashMap_hp_sha256) \ + CPPUNIT_TEST(FeldmanHashMap_hp_sha256_stat) \ + CPPUNIT_TEST(FeldmanHashMap_dhp_sha256) \ + CPPUNIT_TEST(FeldmanHashMap_dhp_sha256_stat) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpi_sha256) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpi_sha256_stat) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpb_sha256) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpb_sha256_stat) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpt_sha256) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpt_sha256_stat) \ + CDSUNIT_TEST_FeldmanHashMap_sha256_RCU_Signal // CityHash - only for 64bit -#undef CDSUNIT_DECLARE_MultiLevelHashMap_city128_RCU_Signal -#undef CDSUNIT_TEST_MultiLevelHashMap_city128_RCU_Signal +#undef CDSUNIT_DECLARE_FeldmanHashMap_city128_RCU_Signal +#undef CDSUNIT_TEST_FeldmanHashMap_city128_RCU_Signal #if CDS_BUILD_BITS == 64 -#undef CDSUNIT_DECLARE_MultiLevelHashMap_city64 -#undef CDSUNIT_DECLARE_MultiLevelHashMap_city64_RCU_Signal -#undef CDSUNIT_TEST_MultiLevelHashMap_city64 -#undef CDSUNIT_TEST_MultiLevelHashMap_city64_RCU_Signal +#undef CDSUNIT_DECLARE_FeldmanHashMap_city64 +#undef CDSUNIT_DECLARE_FeldmanHashMap_city64_RCU_Signal +#undef CDSUNIT_TEST_FeldmanHashMap_city64 +#undef CDSUNIT_TEST_FeldmanHashMap_city64_RCU_Signal #ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED -# define CDSUNIT_DECLARE_MultiLevelHashMap_city64_RCU_Signal \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_shb_city64) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_shb_city64_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_sht_city64) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_sht_city64_stat) \ - -# define CDSUNIT_TEST_MultiLevelHashMap_city64_RCU_Signal \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_shb_city64) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_shb_city64_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_sht_city64) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_sht_city64_stat) \ +# define CDSUNIT_DECLARE_FeldmanHashMap_city64_RCU_Signal \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_shb_city64) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_shb_city64_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_sht_city64) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_sht_city64_stat) \ + +# define CDSUNIT_TEST_FeldmanHashMap_city64_RCU_Signal \ + CPPUNIT_TEST(FeldmanHashMap_rcu_shb_city64) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_shb_city64_stat) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_sht_city64) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_sht_city64_stat) \ #else -# define CDSUNIT_DECLARE_MultiLevelHashMap_city64_RCU_Signal -# define CDSUNIT_TEST_MultiLevelHashMap_city64_RCU_Signal +# define CDSUNIT_DECLARE_FeldmanHashMap_city64_RCU_Signal +# define CDSUNIT_TEST_FeldmanHashMap_city64_RCU_Signal #endif -#define CDSUNIT_DECLARE_MultiLevelHashMap_city64 \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_hp_city64) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_hp_city64_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_dhp_city64) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_dhp_city64_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpi_city64) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpi_city64_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpb_city64) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpb_city64_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpt_city64) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpt_city64_stat) \ - CDSUNIT_DECLARE_MultiLevelHashMap_city64_RCU_Signal - -#define CDSUNIT_TEST_MultiLevelHashMap_city64 \ - CPPUNIT_TEST(MultiLevelHashMap_hp_city64) \ - CPPUNIT_TEST(MultiLevelHashMap_hp_city64_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_dhp_city64) \ - CPPUNIT_TEST(MultiLevelHashMap_dhp_city64_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpi_city64) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpi_city64_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpb_city64) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpb_city64_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpt_city64) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpt_city64_stat) \ - CDSUNIT_TEST_MultiLevelHashMap_city64_RCU_Signal - -#undef CDSUNIT_DECLARE_MultiLevelHashMap_city128 -#undef CDSUNIT_DECLARE_MultiLevelHashMap_city128_RCU_Signal -#undef CDSUNIT_TEST_MultiLevelHashMap_city128 -#undef CDSUNIT_TEST_MultiLevelHashMap_city128_RCU_Signal +#define CDSUNIT_DECLARE_FeldmanHashMap_city64 \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_hp_city64) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_hp_city64_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_dhp_city64) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_dhp_city64_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpi_city64) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpi_city64_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpb_city64) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpb_city64_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpt_city64) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpt_city64_stat) \ + CDSUNIT_DECLARE_FeldmanHashMap_city64_RCU_Signal + +#define CDSUNIT_TEST_FeldmanHashMap_city64 \ + CPPUNIT_TEST(FeldmanHashMap_hp_city64) \ + CPPUNIT_TEST(FeldmanHashMap_hp_city64_stat) \ + CPPUNIT_TEST(FeldmanHashMap_dhp_city64) \ + CPPUNIT_TEST(FeldmanHashMap_dhp_city64_stat) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpi_city64) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpi_city64_stat) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpb_city64) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpb_city64_stat) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpt_city64) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpt_city64_stat) \ + CDSUNIT_TEST_FeldmanHashMap_city64_RCU_Signal + +#undef CDSUNIT_DECLARE_FeldmanHashMap_city128 +#undef CDSUNIT_DECLARE_FeldmanHashMap_city128_RCU_Signal +#undef CDSUNIT_TEST_FeldmanHashMap_city128 +#undef CDSUNIT_TEST_FeldmanHashMap_city128_RCU_Signal #ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED -# define CDSUNIT_DECLARE_MultiLevelHashMap_city128_RCU_Signal \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_shb_city128) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_shb_city128_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_sht_city128) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_sht_city128_stat) \ - -# define CDSUNIT_TEST_MultiLevelHashMap_city128_RCU_Signal \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_shb_city128) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_shb_city128_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_sht_city128) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_sht_city128_stat) \ +# define CDSUNIT_DECLARE_FeldmanHashMap_city128_RCU_Signal \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_shb_city128) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_shb_city128_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_sht_city128) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_sht_city128_stat) \ + +# define CDSUNIT_TEST_FeldmanHashMap_city128_RCU_Signal \ + CPPUNIT_TEST(FeldmanHashMap_rcu_shb_city128) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_shb_city128_stat) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_sht_city128) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_sht_city128_stat) \ #else -# define CDSUNIT_DECLARE_MultiLevelHashMap_city128_RCU_Signal -# define CDSUNIT_TEST_MultiLevelHashMap_city128_RCU_Signal +# define CDSUNIT_DECLARE_FeldmanHashMap_city128_RCU_Signal +# define CDSUNIT_TEST_FeldmanHashMap_city128_RCU_Signal #endif -#define CDSUNIT_DECLARE_MultiLevelHashMap_city128 \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_hp_city128) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_hp_city128_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_dhp_city128) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_dhp_city128_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpi_city128) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpi_city128_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpb_city128) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpb_city128_stat) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpt_city128) \ - TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_rcu_gpt_city128_stat) \ - CDSUNIT_DECLARE_MultiLevelHashMap_city128_RCU_Signal - -#define CDSUNIT_TEST_MultiLevelHashMap_city128 \ - CPPUNIT_TEST(MultiLevelHashMap_hp_city128) \ - CPPUNIT_TEST(MultiLevelHashMap_hp_city128_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_dhp_city128) \ - CPPUNIT_TEST(MultiLevelHashMap_dhp_city128_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpi_city128) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpi_city128_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpb_city128) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpb_city128_stat) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpt_city128) \ - CPPUNIT_TEST(MultiLevelHashMap_rcu_gpt_city128_stat) \ - CDSUNIT_TEST_MultiLevelHashMap_city128_RCU_Signal - -#define CDSUNIT_DECLARE_MultiLevelHashMap_city \ - CDSUNIT_DECLARE_MultiLevelHashMap_city64 \ - CDSUNIT_DECLARE_MultiLevelHashMap_city128 - -#define CDSUNIT_TEST_MultiLevelHashMap_city \ - CDSUNIT_TEST_MultiLevelHashMap_city64 \ - CDSUNIT_TEST_MultiLevelHashMap_city128 +#define CDSUNIT_DECLARE_FeldmanHashMap_city128 \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_hp_city128) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_hp_city128_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_dhp_city128) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_dhp_city128_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpi_city128) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpi_city128_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpb_city128) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpb_city128_stat) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpt_city128) \ + TEST_CASE(tag_FeldmanHashMap, FeldmanHashMap_rcu_gpt_city128_stat) \ + CDSUNIT_DECLARE_FeldmanHashMap_city128_RCU_Signal + +#define CDSUNIT_TEST_FeldmanHashMap_city128 \ + CPPUNIT_TEST(FeldmanHashMap_hp_city128) \ + CPPUNIT_TEST(FeldmanHashMap_hp_city128_stat) \ + CPPUNIT_TEST(FeldmanHashMap_dhp_city128) \ + CPPUNIT_TEST(FeldmanHashMap_dhp_city128_stat) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpi_city128) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpi_city128_stat) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpb_city128) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpb_city128_stat) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpt_city128) \ + CPPUNIT_TEST(FeldmanHashMap_rcu_gpt_city128_stat) \ + CDSUNIT_TEST_FeldmanHashMap_city128_RCU_Signal + +#define CDSUNIT_DECLARE_FeldmanHashMap_city \ + CDSUNIT_DECLARE_FeldmanHashMap_city64 \ + CDSUNIT_DECLARE_FeldmanHashMap_city128 + +#define CDSUNIT_TEST_FeldmanHashMap_city \ + CDSUNIT_TEST_FeldmanHashMap_city64 \ + CDSUNIT_TEST_FeldmanHashMap_city128 #else // 32bit -# define CDSUNIT_DECLARE_MultiLevelHashMap_city -# define CDSUNIT_TEST_MultiLevelHashMap_city +# define CDSUNIT_DECLARE_FeldmanHashMap_city +# define CDSUNIT_TEST_FeldmanHashMap_city #endif // #if CDS_BUILD_BITS == 64 -#undef CDSUNIT_DECLARE_MultiLevelHashMap -#undef CDSUNIT_TEST_MultiLevelHashMap - -#define CDSUNIT_DECLARE_MultiLevelHashMap \ - CDSUNIT_DECLARE_MultiLevelHashMap_fixed \ - CDSUNIT_DECLARE_MultiLevelHashMap_stdhash \ - CDSUNIT_DECLARE_MultiLevelHashMap_md5 \ - CDSUNIT_DECLARE_MultiLevelHashMap_sha256 \ - CDSUNIT_DECLARE_MultiLevelHashMap_city \ - -#define CDSUNIT_TEST_MultiLevelHashMap \ - CDSUNIT_TEST_MultiLevelHashMap_fixed \ - CDSUNIT_TEST_MultiLevelHashMap_stdhash \ - CDSUNIT_TEST_MultiLevelHashMap_md5 \ - CDSUNIT_TEST_MultiLevelHashMap_sha256 \ - CDSUNIT_TEST_MultiLevelHashMap_city +#undef CDSUNIT_DECLARE_FeldmanHashMap +#undef CDSUNIT_TEST_FeldmanHashMap + +#define CDSUNIT_DECLARE_FeldmanHashMap \ + CDSUNIT_DECLARE_FeldmanHashMap_fixed \ + CDSUNIT_DECLARE_FeldmanHashMap_stdhash \ + CDSUNIT_DECLARE_FeldmanHashMap_md5 \ + CDSUNIT_DECLARE_FeldmanHashMap_sha256 \ + CDSUNIT_DECLARE_FeldmanHashMap_city \ + +#define CDSUNIT_TEST_FeldmanHashMap \ + CDSUNIT_TEST_FeldmanHashMap_fixed \ + CDSUNIT_TEST_FeldmanHashMap_stdhash \ + CDSUNIT_TEST_FeldmanHashMap_md5 \ + CDSUNIT_TEST_FeldmanHashMap_sha256 \ + CDSUNIT_TEST_FeldmanHashMap_city diff --git a/tests/unit/map2/map_delodd.cpp b/tests/unit/map2/map_delodd.cpp index 69b78ab5..8d933e7d 100644 --- a/tests/unit/map2/map_delodd.cpp +++ b/tests/unit/map2/map_delodd.cpp @@ -17,8 +17,8 @@ namespace map2 { c_nCuckooProbesetSize = cfg.getSizeT("CuckooProbesetSize", c_nCuckooProbesetSize ); c_nCuckooProbesetThreshold = cfg.getSizeT("CuckooProbesetThreshold", c_nCuckooProbesetThreshold ); - c_nMultiLevelMap_HeadBits = cfg.getSizeT("MultiLevelMapHeadBits", c_nMultiLevelMap_HeadBits); - c_nMultiLevelMap_ArrayBits = cfg.getSizeT("MultiLevelMapArrayBits", c_nMultiLevelMap_ArrayBits); + c_nFeldmanMap_HeadBits = cfg.getSizeT("FeldmanMapHeadBits", c_nFeldmanMap_HeadBits); + c_nFeldmanMap_ArrayBits = cfg.getSizeT("FeldmanMapArrayBits", c_nFeldmanMap_ArrayBits); if ( c_nInsThreadCount == 0 ) c_nInsThreadCount = cds::OS::topology::processor_count(); diff --git a/tests/unit/map2/map_delodd.h b/tests/unit/map2/map_delodd.h index 7c90e6b7..9b39b8d8 100644 --- a/tests/unit/map2/map_delodd.h +++ b/tests/unit/map2/map_delodd.h @@ -125,8 +125,8 @@ namespace map2 { size_t c_nCuckooProbesetSize = 16; // CuckooMap probeset size (only for list-based probeset) size_t c_nCuckooProbesetThreshold = 0; // CUckooMap probeset threshold (0 - use default) - size_t c_nMultiLevelMap_HeadBits = 10; - size_t c_nMultiLevelMap_ArrayBits = 4; + size_t c_nFeldmanMap_HeadBits = 10; + size_t c_nFeldmanMap_ArrayBits = 4; bool c_bPrintGCState = true; @@ -163,7 +163,7 @@ namespace map2 { void operator()( bool /*bNew*/, Q const&, V& ) {} - // MultiLevelHashMap + // FeldmanHashMap template void operator()( Q&, Q*) {} @@ -773,8 +773,8 @@ namespace map2 { CDSUNIT_DECLARE_SkipListMap CDSUNIT_DECLARE_EllenBinTreeMap CDSUNIT_DECLARE_BronsonAVLTreeMap - CDSUNIT_DECLARE_MultiLevelHashMap_fixed - CDSUNIT_DECLARE_MultiLevelHashMap_city + CDSUNIT_DECLARE_FeldmanHashMap_fixed + CDSUNIT_DECLARE_FeldmanHashMap_city CDSUNIT_DECLARE_CuckooMap CPPUNIT_TEST_SUITE(Map_DelOdd) @@ -783,8 +783,8 @@ namespace map2 { CDSUNIT_TEST_SkipListMap CDSUNIT_TEST_EllenBinTreeMap CDSUNIT_TEST_BronsonAVLTreeMap - CDSUNIT_TEST_MultiLevelHashMap_fixed - CDSUNIT_TEST_MultiLevelHashMap_city + CDSUNIT_TEST_FeldmanHashMap_fixed + CDSUNIT_TEST_FeldmanHashMap_city CDSUNIT_TEST_CuckooMap CPPUNIT_TEST_SUITE_END(); diff --git a/tests/unit/map2/map_delodd_feldmanhashmap.cpp b/tests/unit/map2/map_delodd_feldmanhashmap.cpp new file mode 100644 index 00000000..11c4d749 --- /dev/null +++ b/tests/unit/map2/map_delodd_feldmanhashmap.cpp @@ -0,0 +1,13 @@ +//$$CDS-header$$ + +#include "map2/map_delodd.h" +#include "map2/map_type_feldman_hashmap.h" + +#undef TEST_CASE +#define TEST_CASE(TAG, X) void Map_DelOdd::X() { run_test::X>(); } +#include "map2/map_defs.h" + +namespace map2 { + CDSUNIT_DECLARE_FeldmanHashMap_fixed + CDSUNIT_DECLARE_FeldmanHashMap_city +} // namespace map2 diff --git a/tests/unit/map2/map_delodd_multilevelhashmap.cpp b/tests/unit/map2/map_delodd_multilevelhashmap.cpp deleted file mode 100644 index b337daa3..00000000 --- a/tests/unit/map2/map_delodd_multilevelhashmap.cpp +++ /dev/null @@ -1,13 +0,0 @@ -//$$CDS-header$$ - -#include "map2/map_delodd.h" -#include "map2/map_type_multilevel_hashmap.h" - -#undef TEST_CASE -#define TEST_CASE(TAG, X) void Map_DelOdd::X() { run_test::X>(); } -#include "map2/map_defs.h" - -namespace map2 { - CDSUNIT_DECLARE_MultiLevelHashMap_fixed - CDSUNIT_DECLARE_MultiLevelHashMap_city -} // namespace map2 diff --git a/tests/unit/map2/map_find_int.cpp b/tests/unit/map2/map_find_int.cpp index 0cd09317..e763b55d 100644 --- a/tests/unit/map2/map_find_int.cpp +++ b/tests/unit/map2/map_find_int.cpp @@ -40,8 +40,8 @@ namespace map2 { c_nCuckooProbesetSize = cfg.getSizeT("CuckooProbesetSize", c_nCuckooProbesetSize); c_nCuckooProbesetThreshold = cfg.getSizeT("CuckooProbesetThreshold", c_nCuckooProbesetThreshold); - c_nMultiLevelMap_HeadBits = cfg.getSizeT("MultiLevelMapHeadBits", c_nMultiLevelMap_HeadBits); - c_nMultiLevelMap_ArrayBits = cfg.getSizeT("MultiLevelMapArrayBits", c_nMultiLevelMap_ArrayBits); + c_nFeldmanMap_HeadBits = cfg.getSizeT("FeldmanMapHeadBits", c_nFeldmanMap_HeadBits); + c_nFeldmanMap_ArrayBits = cfg.getSizeT("FeldmanMapArrayBits", c_nFeldmanMap_ArrayBits); if ( c_nThreadCount == 0 ) c_nThreadCount = std::thread::hardware_concurrency(); diff --git a/tests/unit/map2/map_find_int.h b/tests/unit/map2/map_find_int.h index 9e73d4c9..2250f924 100644 --- a/tests/unit/map2/map_find_int.h +++ b/tests/unit/map2/map_find_int.h @@ -26,8 +26,8 @@ namespace map2 { size_t c_nCuckooProbesetSize = 16; // CuckooMap probeset size (only for list-based probeset) size_t c_nCuckooProbesetThreshold = 0; // CUckooMap probeset threshold (o - use default) - size_t c_nMultiLevelMap_HeadBits = 10; - size_t c_nMultiLevelMap_ArrayBits = 4; + size_t c_nFeldmanMap_HeadBits = 10; + size_t c_nFeldmanMap_ArrayBits = 4; size_t c_nLoadFactor; // current load factor @@ -227,7 +227,7 @@ namespace map2 { CDSUNIT_DECLARE_SkipListMap_nogc CDSUNIT_DECLARE_EllenBinTreeMap CDSUNIT_DECLARE_BronsonAVLTreeMap - CDSUNIT_DECLARE_MultiLevelHashMap + CDSUNIT_DECLARE_FeldmanHashMap CDSUNIT_DECLARE_StripedMap CDSUNIT_DECLARE_RefinableMap CDSUNIT_DECLARE_CuckooMap @@ -243,7 +243,7 @@ namespace map2 { CDSUNIT_TEST_SkipListMap_nogc CDSUNIT_TEST_EllenBinTreeMap CDSUNIT_TEST_BronsonAVLTreeMap - CDSUNIT_TEST_MultiLevelHashMap + CDSUNIT_TEST_FeldmanHashMap CDSUNIT_TEST_CuckooMap CDSUNIT_TEST_StripedMap CDSUNIT_TEST_RefinableMap diff --git a/tests/unit/map2/map_find_int_feldmanhashmap.cpp b/tests/unit/map2/map_find_int_feldmanhashmap.cpp new file mode 100644 index 00000000..7049ce26 --- /dev/null +++ b/tests/unit/map2/map_find_int_feldmanhashmap.cpp @@ -0,0 +1,12 @@ +//$$CDS-header$$ + +#include "map2/map_find_int.h" +#include "map2/map_type_feldman_hashmap.h" + +#undef TEST_CASE +#define TEST_CASE(TAG, X) void Map_find_int::X() { run_test::X>(); } +#include "map2/map_defs.h" + +namespace map2 { + CDSUNIT_DECLARE_FeldmanHashMap +} // namespace map2 diff --git a/tests/unit/map2/map_find_int_multilevelhashmap.cpp b/tests/unit/map2/map_find_int_multilevelhashmap.cpp deleted file mode 100644 index e606fe01..00000000 --- a/tests/unit/map2/map_find_int_multilevelhashmap.cpp +++ /dev/null @@ -1,12 +0,0 @@ -//$$CDS-header$$ - -#include "map2/map_find_int.h" -#include "map2/map_type_multilevel_hashmap.h" - -#undef TEST_CASE -#define TEST_CASE(TAG, X) void Map_find_int::X() { run_test::X>(); } -#include "map2/map_defs.h" - -namespace map2 { - CDSUNIT_DECLARE_MultiLevelHashMap -} // namespace map2 diff --git a/tests/unit/map2/map_find_string.cpp b/tests/unit/map2/map_find_string.cpp index 6ccadef3..ec08b9bc 100644 --- a/tests/unit/map2/map_find_string.cpp +++ b/tests/unit/map2/map_find_string.cpp @@ -43,8 +43,8 @@ namespace map2 { c_nCuckooProbesetSize = cfg.getSizeT("CuckooProbesetSize", c_nCuckooProbesetSize); c_nCuckooProbesetThreshold = cfg.getSizeT("CuckooProbesetThreshold", c_nCuckooProbesetThreshold); - c_nMultiLevelMap_HeadBits = cfg.getSizeT("MultiLevelMapHeadBits", c_nMultiLevelMap_HeadBits); - c_nMultiLevelMap_ArrayBits = cfg.getSizeT("MultiLevelMapArrayBits", c_nMultiLevelMap_ArrayBits); + c_nFeldmanMap_HeadBits = cfg.getSizeT("FeldmanMapHeadBits", c_nFeldmanMap_HeadBits); + c_nFeldmanMap_ArrayBits = cfg.getSizeT("FeldmanMapArrayBits", c_nFeldmanMap_ArrayBits); if ( c_nThreadCount == 0 ) c_nThreadCount = std::thread::hardware_concurrency(); diff --git a/tests/unit/map2/map_find_string.h b/tests/unit/map2/map_find_string.h index 36e99089..cbba772c 100644 --- a/tests/unit/map2/map_find_string.h +++ b/tests/unit/map2/map_find_string.h @@ -23,8 +23,8 @@ namespace map2 { size_t c_nCuckooProbesetSize = 16; // CuckooMap probeset size (only for list-based probeset) size_t c_nCuckooProbesetThreshold = 0; // CUckooMap probeset threshold (o - use default) - size_t c_nMultiLevelMap_HeadBits = 10; - size_t c_nMultiLevelMap_ArrayBits = 4; + size_t c_nFeldmanMap_HeadBits = 10; + size_t c_nFeldmanMap_ArrayBits = 4; size_t c_nLoadFactor; // current load factor @@ -216,9 +216,9 @@ namespace map2 { CDSUNIT_DECLARE_SkipListMap_nogc CDSUNIT_DECLARE_EllenBinTreeMap CDSUNIT_DECLARE_BronsonAVLTreeMap - CDSUNIT_DECLARE_MultiLevelHashMap_md5 - CDSUNIT_DECLARE_MultiLevelHashMap_sha256 - CDSUNIT_DECLARE_MultiLevelHashMap_city + CDSUNIT_DECLARE_FeldmanHashMap_md5 + CDSUNIT_DECLARE_FeldmanHashMap_sha256 + CDSUNIT_DECLARE_FeldmanHashMap_city CDSUNIT_DECLARE_StripedMap CDSUNIT_DECLARE_RefinableMap CDSUNIT_DECLARE_CuckooMap @@ -234,9 +234,9 @@ namespace map2 { CDSUNIT_TEST_SkipListMap_nogc CDSUNIT_TEST_EllenBinTreeMap CDSUNIT_TEST_BronsonAVLTreeMap - CDSUNIT_TEST_MultiLevelHashMap_md5 - CDSUNIT_TEST_MultiLevelHashMap_sha256 - CDSUNIT_TEST_MultiLevelHashMap_city + CDSUNIT_TEST_FeldmanHashMap_md5 + CDSUNIT_TEST_FeldmanHashMap_sha256 + CDSUNIT_TEST_FeldmanHashMap_city CDSUNIT_TEST_CuckooMap CDSUNIT_TEST_StripedMap CDSUNIT_TEST_RefinableMap diff --git a/tests/unit/map2/map_find_string_feldmanhashmap.cpp b/tests/unit/map2/map_find_string_feldmanhashmap.cpp new file mode 100644 index 00000000..af6121ef --- /dev/null +++ b/tests/unit/map2/map_find_string_feldmanhashmap.cpp @@ -0,0 +1,14 @@ +//$$CDS-header$$ + +#include "map2/map_find_string.h" +#include "map2/map_type_feldman_hashmap.h" + +#undef TEST_CASE +#define TEST_CASE(TAG, X) void Map_find_string::X() { run_test::X>(); } +#include "map2/map_defs.h" + +namespace map2 { + CDSUNIT_DECLARE_FeldmanHashMap_md5 + CDSUNIT_DECLARE_FeldmanHashMap_sha256 + CDSUNIT_DECLARE_FeldmanHashMap_city +} // namespace map2 diff --git a/tests/unit/map2/map_find_string_multilevelhashmap.cpp b/tests/unit/map2/map_find_string_multilevelhashmap.cpp deleted file mode 100644 index 92d001c2..00000000 --- a/tests/unit/map2/map_find_string_multilevelhashmap.cpp +++ /dev/null @@ -1,14 +0,0 @@ -//$$CDS-header$$ - -#include "map2/map_find_string.h" -#include "map2/map_type_multilevel_hashmap.h" - -#undef TEST_CASE -#define TEST_CASE(TAG, X) void Map_find_string::X() { run_test::X>(); } -#include "map2/map_defs.h" - -namespace map2 { - CDSUNIT_DECLARE_MultiLevelHashMap_md5 - CDSUNIT_DECLARE_MultiLevelHashMap_sha256 - CDSUNIT_DECLARE_MultiLevelHashMap_city -} // namespace map2 diff --git a/tests/unit/map2/map_insdel_func.cpp b/tests/unit/map2/map_insdel_func.cpp index f96723e1..cebd7c5a 100644 --- a/tests/unit/map2/map_insdel_func.cpp +++ b/tests/unit/map2/map_insdel_func.cpp @@ -19,8 +19,8 @@ namespace map2 { c_nCuckooProbesetSize = cfg.getULong("CuckooProbesetSize", static_cast(c_nCuckooProbesetSize) ); c_nCuckooProbesetThreshold = cfg.getULong("CuckooProbesetThreshold", static_cast(c_nCuckooProbesetThreshold) ); - c_nMultiLevelMap_HeadBits = cfg.getULong("MultiLevelMapHeadBits", static_cast(c_nMultiLevelMap_HeadBits) ); - c_nMultiLevelMap_ArrayBits = cfg.getULong("MultiLevelMapArrayBits", static_cast(c_nMultiLevelMap_ArrayBits) ); + c_nFeldmanMap_HeadBits = cfg.getULong("FeldmanMapHeadBits", static_cast(c_nFeldmanMap_HeadBits) ); + c_nFeldmanMap_ArrayBits = cfg.getULong("FeldmanMapArrayBits", static_cast(c_nFeldmanMap_ArrayBits) ); } } // namespace map2 diff --git a/tests/unit/map2/map_insdel_func.h b/tests/unit/map2/map_insdel_func.h index 797c5e23..78fa6bb7 100644 --- a/tests/unit/map2/map_insdel_func.h +++ b/tests/unit/map2/map_insdel_func.h @@ -27,8 +27,8 @@ namespace map2 { size_t c_nCuckooProbesetSize = 16; // CuckooMap probeset size (only for list-based probeset) size_t c_nCuckooProbesetThreshold = 0; // CUckooMap probeset threshold (o - use default) - size_t c_nMultiLevelMap_HeadBits = 10; - size_t c_nMultiLevelMap_ArrayBits = 4; + size_t c_nFeldmanMap_HeadBits = 10; + size_t c_nFeldmanMap_ArrayBits = 4; size_t c_nLoadFactor; // current load factor @@ -214,7 +214,7 @@ namespace map2 { operator()( bNew, val.first, val.second ); } - // For MultiLevelHashMap + // For FeldmanHashMap template void operator()( Val& cur, Val * old ) { @@ -550,8 +550,8 @@ namespace map2 { CDSUNIT_DECLARE_SkipListMap CDSUNIT_DECLARE_EllenBinTreeMap CDSUNIT_DECLARE_BronsonAVLTreeMap - CDSUNIT_DECLARE_MultiLevelHashMap_fixed - CDSUNIT_DECLARE_MultiLevelHashMap_city + CDSUNIT_DECLARE_FeldmanHashMap_fixed + CDSUNIT_DECLARE_FeldmanHashMap_city CDSUNIT_DECLARE_StripedMap CDSUNIT_DECLARE_RefinableMap CDSUNIT_DECLARE_CuckooMap @@ -562,8 +562,8 @@ namespace map2 { CDSUNIT_TEST_SkipListMap CDSUNIT_TEST_EllenBinTreeMap CDSUNIT_TEST_BronsonAVLTreeMap - CDSUNIT_TEST_MultiLevelHashMap_fixed - CDSUNIT_TEST_MultiLevelHashMap_city + CDSUNIT_TEST_FeldmanHashMap_fixed + CDSUNIT_TEST_FeldmanHashMap_city CDSUNIT_TEST_CuckooMap CDSUNIT_TEST_StripedMap CDSUNIT_TEST_RefinableMap diff --git a/tests/unit/map2/map_insdel_func_feldmanhashmap.cpp b/tests/unit/map2/map_insdel_func_feldmanhashmap.cpp new file mode 100644 index 00000000..3e1bf3ad --- /dev/null +++ b/tests/unit/map2/map_insdel_func_feldmanhashmap.cpp @@ -0,0 +1,13 @@ +//$$CDS-header$$ + +#include "map2/map_insdel_func.h" +#include "map2/map_type_feldman_hashmap.h" + +#undef TEST_CASE +#define TEST_CASE(TAG, X) void Map_InsDel_func::X() { run_test::X>(); } +#include "map2/map_defs.h" + +namespace map2 { + CDSUNIT_DECLARE_FeldmanHashMap_fixed + CDSUNIT_DECLARE_FeldmanHashMap_city +} // namespace map2 diff --git a/tests/unit/map2/map_insdel_func_multilevelhashmap.cpp b/tests/unit/map2/map_insdel_func_multilevelhashmap.cpp deleted file mode 100644 index b79e71e8..00000000 --- a/tests/unit/map2/map_insdel_func_multilevelhashmap.cpp +++ /dev/null @@ -1,13 +0,0 @@ -//$$CDS-header$$ - -#include "map2/map_insdel_func.h" -#include "map2/map_type_multilevel_hashmap.h" - -#undef TEST_CASE -#define TEST_CASE(TAG, X) void Map_InsDel_func::X() { run_test::X>(); } -#include "map2/map_defs.h" - -namespace map2 { - CDSUNIT_DECLARE_MultiLevelHashMap_fixed - CDSUNIT_DECLARE_MultiLevelHashMap_city -} // namespace map2 diff --git a/tests/unit/map2/map_insdel_int.cpp b/tests/unit/map2/map_insdel_int.cpp index cd636039..4c051e9a 100644 --- a/tests/unit/map2/map_insdel_int.cpp +++ b/tests/unit/map2/map_insdel_int.cpp @@ -18,8 +18,8 @@ namespace map2 { c_nCuckooProbesetSize = cfg.getULong("CuckooProbesetSize", static_cast(c_nCuckooProbesetSize) ); c_nCuckooProbesetThreshold = cfg.getULong("CuckooProbesetThreshold", static_cast(c_nCuckooProbesetThreshold) ); - c_nMultiLevelMap_HeadBits = cfg.getULong("MultiLevelMapHeadBits", static_cast(c_nMultiLevelMap_HeadBits) ); - c_nMultiLevelMap_ArrayBits = cfg.getULong("MultiLevelMapArrayBits", static_cast(c_nMultiLevelMap_ArrayBits) ); + c_nFeldmanMap_HeadBits = cfg.getULong("FeldmanMapHeadBits", static_cast(c_nFeldmanMap_HeadBits) ); + c_nFeldmanMap_ArrayBits = cfg.getULong("FeldmanMapArrayBits", static_cast(c_nFeldmanMap_ArrayBits) ); c_bPrintGCState = cfg.getBool("PrintGCStateFlag", c_bPrintGCState ); diff --git a/tests/unit/map2/map_insdel_int.h b/tests/unit/map2/map_insdel_int.h index 2f7f8a93..20e3720f 100644 --- a/tests/unit/map2/map_insdel_int.h +++ b/tests/unit/map2/map_insdel_int.h @@ -22,8 +22,8 @@ namespace map2 { size_t c_nCuckooProbesetSize = 16; // CuckooMap probeset size (only for list-based probeset) size_t c_nCuckooProbesetThreshold = 0; // CUckooMap probeset threshold (o - use default) - size_t c_nMultiLevelMap_HeadBits = 10; - size_t c_nMultiLevelMap_ArrayBits = 4; + size_t c_nFeldmanMap_HeadBits = 10; + size_t c_nFeldmanMap_ArrayBits = 4; bool c_bPrintGCState = true; @@ -251,8 +251,8 @@ namespace map2 { CDSUNIT_DECLARE_SkipListMap CDSUNIT_DECLARE_EllenBinTreeMap CDSUNIT_DECLARE_BronsonAVLTreeMap - CDSUNIT_DECLARE_MultiLevelHashMap_fixed - CDSUNIT_DECLARE_MultiLevelHashMap_city + CDSUNIT_DECLARE_FeldmanHashMap_fixed + CDSUNIT_DECLARE_FeldmanHashMap_city CDSUNIT_DECLARE_StripedMap CDSUNIT_DECLARE_RefinableMap CDSUNIT_DECLARE_CuckooMap @@ -264,8 +264,8 @@ namespace map2 { CDSUNIT_TEST_SkipListMap CDSUNIT_TEST_EllenBinTreeMap CDSUNIT_TEST_BronsonAVLTreeMap - CDSUNIT_TEST_MultiLevelHashMap_fixed - CDSUNIT_TEST_MultiLevelHashMap_city + CDSUNIT_TEST_FeldmanHashMap_fixed + CDSUNIT_TEST_FeldmanHashMap_city CDSUNIT_TEST_CuckooMap CDSUNIT_TEST_StripedMap CDSUNIT_TEST_RefinableMap diff --git a/tests/unit/map2/map_insdel_int_feldmanhashmap.cpp b/tests/unit/map2/map_insdel_int_feldmanhashmap.cpp new file mode 100644 index 00000000..64868315 --- /dev/null +++ b/tests/unit/map2/map_insdel_int_feldmanhashmap.cpp @@ -0,0 +1,13 @@ +//$$CDS-header$$ + +#include "map2/map_insdel_int.h" +#include "map2/map_type_feldman_hashmap.h" + +#undef TEST_CASE +#define TEST_CASE(TAG, X) void Map_InsDel_int::X() { run_test::X>(); } +#include "map2/map_defs.h" + +namespace map2 { + CDSUNIT_DECLARE_FeldmanHashMap_fixed + CDSUNIT_DECLARE_FeldmanHashMap_city +} // namespace map2 diff --git a/tests/unit/map2/map_insdel_int_multilevelhashmap.cpp b/tests/unit/map2/map_insdel_int_multilevelhashmap.cpp deleted file mode 100644 index 1ac91ec9..00000000 --- a/tests/unit/map2/map_insdel_int_multilevelhashmap.cpp +++ /dev/null @@ -1,13 +0,0 @@ -//$$CDS-header$$ - -#include "map2/map_insdel_int.h" -#include "map2/map_type_multilevel_hashmap.h" - -#undef TEST_CASE -#define TEST_CASE(TAG, X) void Map_InsDel_int::X() { run_test::X>(); } -#include "map2/map_defs.h" - -namespace map2 { - CDSUNIT_DECLARE_MultiLevelHashMap_fixed - CDSUNIT_DECLARE_MultiLevelHashMap_city -} // namespace map2 diff --git a/tests/unit/map2/map_insdel_item_int.cpp b/tests/unit/map2/map_insdel_item_int.cpp index 12e93805..69d39908 100644 --- a/tests/unit/map2/map_insdel_item_int.cpp +++ b/tests/unit/map2/map_insdel_item_int.cpp @@ -18,8 +18,8 @@ namespace map2 { c_nCuckooProbesetSize = cfg.getSizeT("CuckooProbesetSize", c_nCuckooProbesetSize); c_nCuckooProbesetThreshold = cfg.getSizeT("CuckooProbesetThreshold", c_nCuckooProbesetThreshold); - c_nMultiLevelMap_HeadBits = cfg.getSizeT("MultiLevelMapHeadBits", c_nMultiLevelMap_HeadBits); - c_nMultiLevelMap_ArrayBits = cfg.getSizeT("MultiLevelMapArrayBits", c_nMultiLevelMap_ArrayBits); + c_nFeldmanMap_HeadBits = cfg.getSizeT("FeldmanMapHeadBits", c_nFeldmanMap_HeadBits); + c_nFeldmanMap_ArrayBits = cfg.getSizeT("FeldmanMapArrayBits", c_nFeldmanMap_ArrayBits); if ( c_nThreadCount == 0 ) c_nThreadCount = std::thread::hardware_concurrency() * 2; diff --git a/tests/unit/map2/map_insdel_item_int.h b/tests/unit/map2/map_insdel_item_int.h index fffbf8c4..a4f01add 100644 --- a/tests/unit/map2/map_insdel_item_int.h +++ b/tests/unit/map2/map_insdel_item_int.h @@ -22,8 +22,8 @@ namespace map2 { size_t c_nCuckooProbesetSize = 16; // CuckooMap probeset size (only for list-based probeset) size_t c_nCuckooProbesetThreshold = 0; // CUckooMap probeset threshold (o - use default) - size_t c_nMultiLevelMap_HeadBits = 10; - size_t c_nMultiLevelMap_ArrayBits = 4; + size_t c_nFeldmanMap_HeadBits = 10; + size_t c_nFeldmanMap_ArrayBits = 4; size_t c_nGoalItem; size_t c_nLoadFactor = 2; // current load factor @@ -63,7 +63,7 @@ namespace map2 { val = key; } - // for MultiLevelHashMap + // for FeldmanHashMap void operator()( std::pair& item, std::pair * pOld ) { if ( !pOld ) @@ -276,8 +276,8 @@ namespace map2 { CDSUNIT_DECLARE_SkipListMap CDSUNIT_DECLARE_EllenBinTreeMap CDSUNIT_DECLARE_BronsonAVLTreeMap - CDSUNIT_DECLARE_MultiLevelHashMap_fixed - CDSUNIT_DECLARE_MultiLevelHashMap_city + CDSUNIT_DECLARE_FeldmanHashMap_fixed + CDSUNIT_DECLARE_FeldmanHashMap_city CDSUNIT_DECLARE_StripedMap CDSUNIT_DECLARE_RefinableMap CDSUNIT_DECLARE_CuckooMap @@ -289,8 +289,8 @@ namespace map2 { CDSUNIT_TEST_SkipListMap CDSUNIT_TEST_EllenBinTreeMap CDSUNIT_TEST_BronsonAVLTreeMap - CDSUNIT_TEST_MultiLevelHashMap_fixed - CDSUNIT_TEST_MultiLevelHashMap_city + CDSUNIT_TEST_FeldmanHashMap_fixed + CDSUNIT_TEST_FeldmanHashMap_city CDSUNIT_TEST_CuckooMap CDSUNIT_TEST_StripedMap CDSUNIT_TEST_RefinableMap diff --git a/tests/unit/map2/map_insdel_item_int_feldmanhashmap.cpp b/tests/unit/map2/map_insdel_item_int_feldmanhashmap.cpp new file mode 100644 index 00000000..2a6e3ba5 --- /dev/null +++ b/tests/unit/map2/map_insdel_item_int_feldmanhashmap.cpp @@ -0,0 +1,13 @@ +//$$CDS-header$$ + +#include "map2/map_insdel_item_int.h" +#include "map2/map_type_feldman_hashmap.h" + +#undef TEST_CASE +#define TEST_CASE(TAG, X) void Map_InsDel_Item_int::X() { run_test::X>(); } +#include "map2/map_defs.h" + +namespace map2 { + CDSUNIT_DECLARE_FeldmanHashMap_fixed + CDSUNIT_DECLARE_FeldmanHashMap_city +} // namespace map2 diff --git a/tests/unit/map2/map_insdel_item_int_multilevelhashmap.cpp b/tests/unit/map2/map_insdel_item_int_multilevelhashmap.cpp deleted file mode 100644 index 4bd37b74..00000000 --- a/tests/unit/map2/map_insdel_item_int_multilevelhashmap.cpp +++ /dev/null @@ -1,13 +0,0 @@ -//$$CDS-header$$ - -#include "map2/map_insdel_item_int.h" -#include "map2/map_type_multilevel_hashmap.h" - -#undef TEST_CASE -#define TEST_CASE(TAG, X) void Map_InsDel_Item_int::X() { run_test::X>(); } -#include "map2/map_defs.h" - -namespace map2 { - CDSUNIT_DECLARE_MultiLevelHashMap_fixed - CDSUNIT_DECLARE_MultiLevelHashMap_city -} // namespace map2 diff --git a/tests/unit/map2/map_insdel_item_string.cpp b/tests/unit/map2/map_insdel_item_string.cpp index a8c125be..46679f27 100644 --- a/tests/unit/map2/map_insdel_item_string.cpp +++ b/tests/unit/map2/map_insdel_item_string.cpp @@ -18,8 +18,8 @@ namespace map2 { c_nCuckooProbesetSize = cfg.getSizeT("CuckooProbesetSize", c_nCuckooProbesetSize); c_nCuckooProbesetThreshold = cfg.getSizeT("CuckooProbesetThreshold", c_nCuckooProbesetThreshold); - c_nMultiLevelMap_HeadBits = cfg.getSizeT("MultiLevelMapHeadBits", c_nMultiLevelMap_HeadBits); - c_nMultiLevelMap_ArrayBits = cfg.getSizeT("MultiLevelMapArrayBits", c_nMultiLevelMap_ArrayBits); + c_nFeldmanMap_HeadBits = cfg.getSizeT("FeldmanMapHeadBits", c_nFeldmanMap_HeadBits); + c_nFeldmanMap_ArrayBits = cfg.getSizeT("FeldmanMapArrayBits", c_nFeldmanMap_ArrayBits); if ( c_nThreadCount == 0 ) c_nThreadCount = std::thread::hardware_concurrency() * 2; diff --git a/tests/unit/map2/map_insdel_item_string.h b/tests/unit/map2/map_insdel_item_string.h index f7e41dc1..56ef762e 100644 --- a/tests/unit/map2/map_insdel_item_string.h +++ b/tests/unit/map2/map_insdel_item_string.h @@ -22,8 +22,8 @@ namespace map2 { size_t c_nCuckooProbesetSize = 16; // CuckooMap probeset size (only for list-based probeset) size_t c_nCuckooProbesetThreshold = 0; // CUckooMap probeset threshold (o - use default) - size_t c_nMultiLevelMap_HeadBits = 10; - size_t c_nMultiLevelMap_ArrayBits = 4; + size_t c_nFeldmanMap_HeadBits = 10; + size_t c_nFeldmanMap_ArrayBits = 4; size_t c_nGoalItem; size_t c_nLoadFactor = 2; // current load factor @@ -257,9 +257,9 @@ namespace map2 { CDSUNIT_DECLARE_SkipListMap CDSUNIT_DECLARE_EllenBinTreeMap CDSUNIT_DECLARE_BronsonAVLTreeMap - CDSUNIT_DECLARE_MultiLevelHashMap_md5 - CDSUNIT_DECLARE_MultiLevelHashMap_sha256 - CDSUNIT_DECLARE_MultiLevelHashMap_city + CDSUNIT_DECLARE_FeldmanHashMap_md5 + CDSUNIT_DECLARE_FeldmanHashMap_sha256 + CDSUNIT_DECLARE_FeldmanHashMap_city CDSUNIT_DECLARE_StripedMap CDSUNIT_DECLARE_RefinableMap CDSUNIT_DECLARE_CuckooMap @@ -271,9 +271,9 @@ namespace map2 { CDSUNIT_TEST_SkipListMap CDSUNIT_TEST_EllenBinTreeMap CDSUNIT_TEST_BronsonAVLTreeMap - CDSUNIT_TEST_MultiLevelHashMap_md5 - CDSUNIT_TEST_MultiLevelHashMap_sha256 - CDSUNIT_TEST_MultiLevelHashMap_city + CDSUNIT_TEST_FeldmanHashMap_md5 + CDSUNIT_TEST_FeldmanHashMap_sha256 + CDSUNIT_TEST_FeldmanHashMap_city CDSUNIT_TEST_CuckooMap CDSUNIT_TEST_StripedMap CDSUNIT_TEST_RefinableMap diff --git a/tests/unit/map2/map_insdel_item_string_feldmanhashmap.cpp b/tests/unit/map2/map_insdel_item_string_feldmanhashmap.cpp new file mode 100644 index 00000000..659d0e65 --- /dev/null +++ b/tests/unit/map2/map_insdel_item_string_feldmanhashmap.cpp @@ -0,0 +1,14 @@ +//$$CDS-header$$ + +#include "map2/map_insdel_item_string.h" +#include "map2/map_type_feldman_hashmap.h" + +#undef TEST_CASE +#define TEST_CASE(TAG, X) void Map_InsDel_Item_string::X() { run_test::X>(); } +#include "map2/map_defs.h" + +namespace map2 { + CDSUNIT_DECLARE_FeldmanHashMap_md5 + CDSUNIT_DECLARE_FeldmanHashMap_sha256 + CDSUNIT_DECLARE_FeldmanHashMap_city +} // namespace map2 diff --git a/tests/unit/map2/map_insdel_item_string_multilevelhashmap.cpp b/tests/unit/map2/map_insdel_item_string_multilevelhashmap.cpp deleted file mode 100644 index 0d75f795..00000000 --- a/tests/unit/map2/map_insdel_item_string_multilevelhashmap.cpp +++ /dev/null @@ -1,14 +0,0 @@ -//$$CDS-header$$ - -#include "map2/map_insdel_item_string.h" -#include "map2/map_type_multilevel_hashmap.h" - -#undef TEST_CASE -#define TEST_CASE(TAG, X) void Map_InsDel_Item_string::X() { run_test::X>(); } -#include "map2/map_defs.h" - -namespace map2 { - CDSUNIT_DECLARE_MultiLevelHashMap_md5 - CDSUNIT_DECLARE_MultiLevelHashMap_sha256 - CDSUNIT_DECLARE_MultiLevelHashMap_city -} // namespace map2 diff --git a/tests/unit/map2/map_insdel_string.cpp b/tests/unit/map2/map_insdel_string.cpp index e52c8276..6354966d 100644 --- a/tests/unit/map2/map_insdel_string.cpp +++ b/tests/unit/map2/map_insdel_string.cpp @@ -18,8 +18,8 @@ namespace map2 { c_nCuckooProbesetSize = cfg.getSizeT("CuckooProbesetSize", c_nCuckooProbesetSize); c_nCuckooProbesetThreshold = cfg.getSizeT("CuckooProbesetThreshold", c_nCuckooProbesetThreshold); - c_nMultiLevelMap_HeadBits = cfg.getSizeT("MultiLevelMapHeadBits", c_nMultiLevelMap_HeadBits); - c_nMultiLevelMap_ArrayBits = cfg.getSizeT("MultiLevelMapArrayBits", c_nMultiLevelMap_ArrayBits); + c_nFeldmanMap_HeadBits = cfg.getSizeT("FeldmanMapHeadBits", c_nFeldmanMap_HeadBits); + c_nFeldmanMap_ArrayBits = cfg.getSizeT("FeldmanMapArrayBits", c_nFeldmanMap_ArrayBits); if ( c_nInsertThreadCount == 0 ) c_nInsertThreadCount = std::thread::hardware_concurrency(); diff --git a/tests/unit/map2/map_insdel_string.h b/tests/unit/map2/map_insdel_string.h index b1fe41be..8c71f081 100644 --- a/tests/unit/map2/map_insdel_string.h +++ b/tests/unit/map2/map_insdel_string.h @@ -22,8 +22,8 @@ namespace map2 { size_t c_nCuckooProbesetSize = 16; // CuckooMap probeset size (only for list-based probeset) size_t c_nCuckooProbesetThreshold = 0; // CUckooMap probeset threshold (o - use default) - size_t c_nMultiLevelMap_HeadBits = 10; - size_t c_nMultiLevelMap_ArrayBits = 4; + size_t c_nFeldmanMap_HeadBits = 10; + size_t c_nFeldmanMap_ArrayBits = 4; bool c_bPrintGCState = true; @@ -256,8 +256,8 @@ namespace map2 { CDSUNIT_DECLARE_SkipListMap CDSUNIT_DECLARE_EllenBinTreeMap CDSUNIT_DECLARE_BronsonAVLTreeMap - CDSUNIT_DECLARE_MultiLevelHashMap_sha256 - CDSUNIT_DECLARE_MultiLevelHashMap_city + CDSUNIT_DECLARE_FeldmanHashMap_sha256 + CDSUNIT_DECLARE_FeldmanHashMap_city CDSUNIT_DECLARE_StripedMap CDSUNIT_DECLARE_RefinableMap CDSUNIT_DECLARE_CuckooMap @@ -269,8 +269,8 @@ namespace map2 { CDSUNIT_TEST_SkipListMap CDSUNIT_TEST_EllenBinTreeMap CDSUNIT_TEST_BronsonAVLTreeMap - CDSUNIT_TEST_MultiLevelHashMap_sha256 - CDSUNIT_TEST_MultiLevelHashMap_city + CDSUNIT_TEST_FeldmanHashMap_sha256 + CDSUNIT_TEST_FeldmanHashMap_city CDSUNIT_TEST_CuckooMap CDSUNIT_TEST_StripedMap CDSUNIT_TEST_RefinableMap diff --git a/tests/unit/map2/map_insdel_string_feldmanhashmap.cpp b/tests/unit/map2/map_insdel_string_feldmanhashmap.cpp new file mode 100644 index 00000000..60cc3513 --- /dev/null +++ b/tests/unit/map2/map_insdel_string_feldmanhashmap.cpp @@ -0,0 +1,13 @@ +//$$CDS-header$$ + +#include "map2/map_insdel_string.h" +#include "map2/map_type_feldman_hashmap.h" + +#undef TEST_CASE +#define TEST_CASE(TAG, X) void Map_InsDel_string::X() { run_test::X>(); } +#include "map2/map_defs.h" + +namespace map2 { + CDSUNIT_DECLARE_FeldmanHashMap_sha256 + CDSUNIT_DECLARE_FeldmanHashMap_city +} // namespace map2 diff --git a/tests/unit/map2/map_insdel_string_multilevelhashmap.cpp b/tests/unit/map2/map_insdel_string_multilevelhashmap.cpp deleted file mode 100644 index 9651f0d8..00000000 --- a/tests/unit/map2/map_insdel_string_multilevelhashmap.cpp +++ /dev/null @@ -1,13 +0,0 @@ -//$$CDS-header$$ - -#include "map2/map_insdel_string.h" -#include "map2/map_type_multilevel_hashmap.h" - -#undef TEST_CASE -#define TEST_CASE(TAG, X) void Map_InsDel_string::X() { run_test::X>(); } -#include "map2/map_defs.h" - -namespace map2 { - CDSUNIT_DECLARE_MultiLevelHashMap_sha256 - CDSUNIT_DECLARE_MultiLevelHashMap_city -} // namespace map2 diff --git a/tests/unit/map2/map_insdelfind.cpp b/tests/unit/map2/map_insdelfind.cpp index 9f343de7..2f8cfeee 100644 --- a/tests/unit/map2/map_insdelfind.cpp +++ b/tests/unit/map2/map_insdelfind.cpp @@ -20,8 +20,8 @@ namespace map2 { c_nCuckooProbesetSize = cfg.getSizeT("CuckooProbesetSize", c_nCuckooProbesetSize); c_nCuckooProbesetThreshold = cfg.getSizeT("CuckooProbesetThreshold", c_nCuckooProbesetThreshold); - c_nMultiLevelMap_HeadBits = cfg.getSizeT("MultiLevelMapHeadBits", c_nMultiLevelMap_HeadBits); - c_nMultiLevelMap_ArrayBits = cfg.getSizeT("MultiLevelMapArrayBits", c_nMultiLevelMap_ArrayBits); + c_nFeldmanMap_HeadBits = cfg.getSizeT("FeldmanMapHeadBits", c_nFeldmanMap_HeadBits); + c_nFeldmanMap_ArrayBits = cfg.getSizeT("FeldmanMapArrayBits", c_nFeldmanMap_ArrayBits); if ( c_nThreadCount == 0 ) c_nThreadCount = std::thread::hardware_concurrency() * 2; diff --git a/tests/unit/map2/map_insdelfind.h b/tests/unit/map2/map_insdelfind.h index 102498e1..636b9ab6 100644 --- a/tests/unit/map2/map_insdelfind.h +++ b/tests/unit/map2/map_insdelfind.h @@ -23,8 +23,8 @@ namespace map2 { size_t c_nCuckooProbesetSize = 16; // CuckooMap probeset size (only for list-based probeset) size_t c_nCuckooProbesetThreshold = 0; // CUckooMap probeset threshold (o - use default) - size_t c_nMultiLevelMap_HeadBits = 10; - size_t c_nMultiLevelMap_ArrayBits = 4; + size_t c_nFeldmanMap_HeadBits = 10; + size_t c_nFeldmanMap_ArrayBits = 4; size_t c_nLoadFactor = 2; // current load factor @@ -84,7 +84,7 @@ namespace map2 { void operator()( bool /*bNew*/, map_value_type& /*cur*/, Q const& /*val*/ ) {} - // MultiLevelHashMap + // FeldmanHashMap void operator()( map_value_type& /*cur*/, map_value_type * /*old*/) {} @@ -255,8 +255,8 @@ namespace map2 { CDSUNIT_DECLARE_SkipListMap CDSUNIT_DECLARE_EllenBinTreeMap CDSUNIT_DECLARE_BronsonAVLTreeMap - CDSUNIT_DECLARE_MultiLevelHashMap_fixed - CDSUNIT_DECLARE_MultiLevelHashMap_city + CDSUNIT_DECLARE_FeldmanHashMap_fixed + CDSUNIT_DECLARE_FeldmanHashMap_city CDSUNIT_DECLARE_StripedMap CDSUNIT_DECLARE_RefinableMap CDSUNIT_DECLARE_CuckooMap @@ -268,8 +268,8 @@ namespace map2 { CDSUNIT_TEST_SkipListMap CDSUNIT_TEST_EllenBinTreeMap CDSUNIT_TEST_BronsonAVLTreeMap - CDSUNIT_TEST_MultiLevelHashMap_fixed - CDSUNIT_TEST_MultiLevelHashMap_city + CDSUNIT_TEST_FeldmanHashMap_fixed + CDSUNIT_TEST_FeldmanHashMap_city CDSUNIT_TEST_CuckooMap CDSUNIT_TEST_StripedMap CDSUNIT_TEST_RefinableMap diff --git a/tests/unit/map2/map_insdelfind_feldmanhashmap.cpp b/tests/unit/map2/map_insdelfind_feldmanhashmap.cpp new file mode 100644 index 00000000..1321f576 --- /dev/null +++ b/tests/unit/map2/map_insdelfind_feldmanhashmap.cpp @@ -0,0 +1,13 @@ +//$$CDS-header$$ + +#include "map2/map_insdelfind.h" +#include "map2/map_type_feldman_hashmap.h" + +#undef TEST_CASE +#define TEST_CASE(TAG, X) void Map_InsDelFind::X() { run_test::X>(); } +#include "map2/map_defs.h" + +namespace map2 { + CDSUNIT_DECLARE_FeldmanHashMap_fixed + CDSUNIT_DECLARE_FeldmanHashMap_city +} // namespace map2 diff --git a/tests/unit/map2/map_insdelfind_multilevelhashmap.cpp b/tests/unit/map2/map_insdelfind_multilevelhashmap.cpp deleted file mode 100644 index 2eadd2d0..00000000 --- a/tests/unit/map2/map_insdelfind_multilevelhashmap.cpp +++ /dev/null @@ -1,13 +0,0 @@ -//$$CDS-header$$ - -#include "map2/map_insdelfind.h" -#include "map2/map_type_multilevel_hashmap.h" - -#undef TEST_CASE -#define TEST_CASE(TAG, X) void Map_InsDelFind::X() { run_test::X>(); } -#include "map2/map_defs.h" - -namespace map2 { - CDSUNIT_DECLARE_MultiLevelHashMap_fixed - CDSUNIT_DECLARE_MultiLevelHashMap_city -} // namespace map2 diff --git a/tests/unit/map2/map_insfind_int.cpp b/tests/unit/map2/map_insfind_int.cpp index de3cf59e..31dee98d 100644 --- a/tests/unit/map2/map_insfind_int.cpp +++ b/tests/unit/map2/map_insfind_int.cpp @@ -16,8 +16,8 @@ namespace map2 { c_nCuckooProbesetSize = cfg.getSizeT("CuckooProbesetSize", c_nCuckooProbesetSize); c_nCuckooProbesetThreshold = cfg.getSizeT("CuckooProbesetThreshold", c_nCuckooProbesetThreshold); - c_nMultiLevelMap_HeadBits = cfg.getSizeT("MultiLevelMapHeadBits", c_nMultiLevelMap_HeadBits); - c_nMultiLevelMap_ArrayBits = cfg.getSizeT("MultiLevelMapArrayBits", c_nMultiLevelMap_ArrayBits); + c_nFeldmanMap_HeadBits = cfg.getSizeT("FeldmanMapHeadBits", c_nFeldmanMap_HeadBits); + c_nFeldmanMap_ArrayBits = cfg.getSizeT("FeldmanMapArrayBits", c_nFeldmanMap_ArrayBits); if ( c_nThreadCount == 0 ) c_nThreadCount = std::thread::hardware_concurrency(); diff --git a/tests/unit/map2/map_insfind_int.h b/tests/unit/map2/map_insfind_int.h index d98961de..57e59c7f 100644 --- a/tests/unit/map2/map_insfind_int.h +++ b/tests/unit/map2/map_insfind_int.h @@ -22,8 +22,8 @@ namespace map2 { size_t c_nCuckooProbesetSize = 16; // CuckooMap probeset size (only for list-based probeset) size_t c_nCuckooProbesetThreshold = 0; // CUckooMap probeset threshold (o - use default) - size_t c_nMultiLevelMap_HeadBits = 10; - size_t c_nMultiLevelMap_ArrayBits = 4; + size_t c_nFeldmanMap_HeadBits = 10; + size_t c_nFeldmanMap_ArrayBits = 4; size_t c_nLoadFactor = 2; // current load factor @@ -197,8 +197,8 @@ namespace map2 { CDSUNIT_DECLARE_SkipListMap_nogc CDSUNIT_DECLARE_EllenBinTreeMap CDSUNIT_DECLARE_BronsonAVLTreeMap - CDSUNIT_DECLARE_MultiLevelHashMap_fixed - CDSUNIT_DECLARE_MultiLevelHashMap_city + CDSUNIT_DECLARE_FeldmanHashMap_fixed + CDSUNIT_DECLARE_FeldmanHashMap_city CDSUNIT_DECLARE_StripedMap CDSUNIT_DECLARE_RefinableMap CDSUNIT_DECLARE_CuckooMap @@ -214,8 +214,8 @@ namespace map2 { CDSUNIT_TEST_SkipListMap_nogc CDSUNIT_TEST_EllenBinTreeMap CDSUNIT_TEST_BronsonAVLTreeMap - CDSUNIT_TEST_MultiLevelHashMap_fixed - CDSUNIT_TEST_MultiLevelHashMap_city + CDSUNIT_TEST_FeldmanHashMap_fixed + CDSUNIT_TEST_FeldmanHashMap_city CDSUNIT_TEST_CuckooMap CDSUNIT_TEST_StripedMap CDSUNIT_TEST_RefinableMap diff --git a/tests/unit/map2/map_insfind_int_feldmanhashmap.cpp b/tests/unit/map2/map_insfind_int_feldmanhashmap.cpp new file mode 100644 index 00000000..bf058fb9 --- /dev/null +++ b/tests/unit/map2/map_insfind_int_feldmanhashmap.cpp @@ -0,0 +1,13 @@ +//$$CDS-header$$ + +#include "map2/map_insfind_int.h" +#include "map2/map_type_feldman_hashmap.h" + +#undef TEST_CASE +#define TEST_CASE(TAG, X) void Map_InsFind_int::X() { run_test::X>(); } +#include "map2/map_defs.h" + +namespace map2 { + CDSUNIT_DECLARE_FeldmanHashMap_fixed + CDSUNIT_DECLARE_FeldmanHashMap_city +} // namespace map2 diff --git a/tests/unit/map2/map_insfind_int_multilevelhashmap.cpp b/tests/unit/map2/map_insfind_int_multilevelhashmap.cpp deleted file mode 100644 index 260b1e72..00000000 --- a/tests/unit/map2/map_insfind_int_multilevelhashmap.cpp +++ /dev/null @@ -1,13 +0,0 @@ -//$$CDS-header$$ - -#include "map2/map_insfind_int.h" -#include "map2/map_type_multilevel_hashmap.h" - -#undef TEST_CASE -#define TEST_CASE(TAG, X) void Map_InsFind_int::X() { run_test::X>(); } -#include "map2/map_defs.h" - -namespace map2 { - CDSUNIT_DECLARE_MultiLevelHashMap_fixed - CDSUNIT_DECLARE_MultiLevelHashMap_city -} // namespace map2 diff --git a/tests/unit/map2/map_type_feldman_hashmap.h b/tests/unit/map2/map_type_feldman_hashmap.h new file mode 100644 index 00000000..ec1bbc28 --- /dev/null +++ b/tests/unit/map2/map_type_feldman_hashmap.h @@ -0,0 +1,227 @@ +//$$CDS-header$$ + +#ifndef CDSUNIT_MAP_TYPE_FELDMAN_HASHMAP_H +#define CDSUNIT_MAP_TYPE_FELDMAN_HASHMAP_H + +#include "map2/map_type.h" + +#include +#include +#include + +#include "print_feldman_hashset_stat.h" +#include "hashing/hash_func.h" + +namespace map2 { + + template + class FeldmanHashMap : public cc::FeldmanHashMap< GC, Key, T, Traits > + { + typedef cc::FeldmanHashMap< GC, Key, T, Traits > base_class; + public: + template + FeldmanHashMap( Config const& cfg) + : base_class( cfg.c_nFeldmanMap_HeadBits, cfg.c_nFeldmanMap_ArrayBits ) + {} + + // for testing + static CDS_CONSTEXPR bool const c_bExtractSupported = true; + static CDS_CONSTEXPR bool const c_bLoadFactorDepended = false; + static CDS_CONSTEXPR bool const c_bEraseExactKey = true; + }; + + struct tag_FeldmanHashMap; + + template + struct map_type< tag_FeldmanHashMap, Key, Value >: public map_type_base< Key, Value > + { + typedef map_type_base< Key, Value > base_class; + typedef typename base_class::compare compare; + typedef typename base_class::less less; + + struct traits_FeldmanHashMap_stdhash : public cc::feldman_hashmap::traits + { + typedef std::hash< Key > hash; + }; + + typedef FeldmanHashMap< cds::gc::HP, Key, Value, traits_FeldmanHashMap_stdhash > FeldmanHashMap_hp_stdhash; + typedef FeldmanHashMap< cds::gc::DHP, Key, Value, traits_FeldmanHashMap_stdhash > FeldmanHashMap_dhp_stdhash; + typedef FeldmanHashMap< rcu_gpi, Key, Value, traits_FeldmanHashMap_stdhash > FeldmanHashMap_rcu_gpi_stdhash; + typedef FeldmanHashMap< rcu_gpb, Key, Value, traits_FeldmanHashMap_stdhash > FeldmanHashMap_rcu_gpb_stdhash; + typedef FeldmanHashMap< rcu_gpt, Key, Value, traits_FeldmanHashMap_stdhash > FeldmanHashMap_rcu_gpt_stdhash; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashMap< rcu_shb, Key, Value, traits_FeldmanHashMap_stdhash > FeldmanHashMap_rcu_shb_stdhash; + typedef FeldmanHashMap< rcu_sht, Key, Value, traits_FeldmanHashMap_stdhash > FeldmanHashMap_rcu_sht_stdhash; +#endif + + struct traits_FeldmanHashMap_stdhash_stat: traits_FeldmanHashMap_stdhash + { + typedef cc::feldman_hashmap::stat<> stat; + }; + + typedef FeldmanHashMap< cds::gc::HP, Key, Value, traits_FeldmanHashMap_stdhash_stat > FeldmanHashMap_hp_stdhash_stat; + typedef FeldmanHashMap< cds::gc::DHP, Key, Value, traits_FeldmanHashMap_stdhash_stat > FeldmanHashMap_dhp_stdhash_stat; + typedef FeldmanHashMap< rcu_gpi, Key, Value, traits_FeldmanHashMap_stdhash_stat > FeldmanHashMap_rcu_gpi_stdhash_stat; + typedef FeldmanHashMap< rcu_gpb, Key, Value, traits_FeldmanHashMap_stdhash_stat > FeldmanHashMap_rcu_gpb_stdhash_stat; + typedef FeldmanHashMap< rcu_gpt, Key, Value, traits_FeldmanHashMap_stdhash_stat > FeldmanHashMap_rcu_gpt_stdhash_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashMap< rcu_shb, Key, Value, traits_FeldmanHashMap_stdhash_stat > FeldmanHashMap_rcu_shb_stdhash_stat; + typedef FeldmanHashMap< rcu_sht, Key, Value, traits_FeldmanHashMap_stdhash_stat > FeldmanHashMap_rcu_sht_stdhash_stat; +#endif + + // SHA256 + struct traits_FeldmanHashMap_sha256 : public cc::feldman_hashmap::traits + { + typedef ::hashing::sha256 hash; + }; + typedef FeldmanHashMap< cds::gc::HP, Key, Value, traits_FeldmanHashMap_sha256 > FeldmanHashMap_hp_sha256; + typedef FeldmanHashMap< cds::gc::DHP, Key, Value, traits_FeldmanHashMap_sha256 > FeldmanHashMap_dhp_sha256; + typedef FeldmanHashMap< rcu_gpi, Key, Value, traits_FeldmanHashMap_sha256 > FeldmanHashMap_rcu_gpi_sha256; + typedef FeldmanHashMap< rcu_gpb, Key, Value, traits_FeldmanHashMap_sha256 > FeldmanHashMap_rcu_gpb_sha256; + typedef FeldmanHashMap< rcu_gpt, Key, Value, traits_FeldmanHashMap_sha256 > FeldmanHashMap_rcu_gpt_sha256; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashMap< rcu_shb, Key, Value, traits_FeldmanHashMap_sha256 > FeldmanHashMap_rcu_shb_sha256; + typedef FeldmanHashMap< rcu_sht, Key, Value, traits_FeldmanHashMap_sha256 > FeldmanHashMap_rcu_sht_sha256; +#endif + + struct traits_FeldmanHashMap_sha256_stat : public traits_FeldmanHashMap_sha256 + { + typedef cc::feldman_hashmap::stat<> stat; + }; + typedef FeldmanHashMap< cds::gc::HP, Key, Value, traits_FeldmanHashMap_sha256_stat > FeldmanHashMap_hp_sha256_stat; + typedef FeldmanHashMap< cds::gc::DHP, Key, Value, traits_FeldmanHashMap_sha256_stat > FeldmanHashMap_dhp_sha256_stat; + typedef FeldmanHashMap< rcu_gpi, Key, Value, traits_FeldmanHashMap_sha256_stat > FeldmanHashMap_rcu_gpi_sha256_stat; + typedef FeldmanHashMap< rcu_gpb, Key, Value, traits_FeldmanHashMap_sha256_stat > FeldmanHashMap_rcu_gpb_sha256_stat; + typedef FeldmanHashMap< rcu_gpt, Key, Value, traits_FeldmanHashMap_sha256_stat > FeldmanHashMap_rcu_gpt_sha256_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashMap< rcu_shb, Key, Value, traits_FeldmanHashMap_sha256_stat > FeldmanHashMap_rcu_shb_sha256_stat; + typedef FeldmanHashMap< rcu_sht, Key, Value, traits_FeldmanHashMap_sha256_stat > FeldmanHashMap_rcu_sht_sha256_stat; +#endif + + //MD5 + struct traits_FeldmanHashMap_md5 : public cc::feldman_hashmap::traits + { + typedef ::hashing::md5 hash; + }; + typedef FeldmanHashMap< cds::gc::HP, Key, Value, traits_FeldmanHashMap_md5 > FeldmanHashMap_hp_md5; + typedef FeldmanHashMap< cds::gc::DHP, Key, Value, traits_FeldmanHashMap_md5 > FeldmanHashMap_dhp_md5; + typedef FeldmanHashMap< rcu_gpi, Key, Value, traits_FeldmanHashMap_md5 > FeldmanHashMap_rcu_gpi_md5; + typedef FeldmanHashMap< rcu_gpb, Key, Value, traits_FeldmanHashMap_md5 > FeldmanHashMap_rcu_gpb_md5; + typedef FeldmanHashMap< rcu_gpt, Key, Value, traits_FeldmanHashMap_md5 > FeldmanHashMap_rcu_gpt_md5; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashMap< rcu_shb, Key, Value, traits_FeldmanHashMap_md5 > FeldmanHashMap_rcu_shb_md5; + typedef FeldmanHashMap< rcu_sht, Key, Value, traits_FeldmanHashMap_md5 > FeldmanHashMap_rcu_sht_md5; +#endif + + struct traits_FeldmanHashMap_md5_stat : public traits_FeldmanHashMap_md5 + { + typedef cc::feldman_hashmap::stat<> stat; + }; + typedef FeldmanHashMap< cds::gc::HP, Key, Value, traits_FeldmanHashMap_md5_stat > FeldmanHashMap_hp_md5_stat; + typedef FeldmanHashMap< cds::gc::DHP, Key, Value, traits_FeldmanHashMap_md5_stat > FeldmanHashMap_dhp_md5_stat; + typedef FeldmanHashMap< rcu_gpi, Key, Value, traits_FeldmanHashMap_md5_stat > FeldmanHashMap_rcu_gpi_md5_stat; + typedef FeldmanHashMap< rcu_gpb, Key, Value, traits_FeldmanHashMap_md5_stat > FeldmanHashMap_rcu_gpb_md5_stat; + typedef FeldmanHashMap< rcu_gpt, Key, Value, traits_FeldmanHashMap_md5_stat > FeldmanHashMap_rcu_gpt_md5_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashMap< rcu_shb, Key, Value, traits_FeldmanHashMap_md5_stat > FeldmanHashMap_rcu_shb_md5_stat; + typedef FeldmanHashMap< rcu_sht, Key, Value, traits_FeldmanHashMap_md5_stat > FeldmanHashMap_rcu_sht_md5_stat; +#endif + + // CityHash +#if CDS_BUILD_BITS == 64 + struct traits_FeldmanHashMap_city64 : public cc::feldman_hashmap::traits + { + typedef ::hashing::city64 hash; + typedef ::hashing::city64::less less; + }; + typedef FeldmanHashMap< cds::gc::HP, Key, Value, traits_FeldmanHashMap_city64 > FeldmanHashMap_hp_city64; + typedef FeldmanHashMap< cds::gc::DHP, Key, Value, traits_FeldmanHashMap_city64 > FeldmanHashMap_dhp_city64; + typedef FeldmanHashMap< rcu_gpi, Key, Value, traits_FeldmanHashMap_city64 > FeldmanHashMap_rcu_gpi_city64; + typedef FeldmanHashMap< rcu_gpb, Key, Value, traits_FeldmanHashMap_city64 > FeldmanHashMap_rcu_gpb_city64; + typedef FeldmanHashMap< rcu_gpt, Key, Value, traits_FeldmanHashMap_city64 > FeldmanHashMap_rcu_gpt_city64; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashMap< rcu_shb, Key, Value, traits_FeldmanHashMap_city64 > FeldmanHashMap_rcu_shb_city64; + typedef FeldmanHashMap< rcu_sht, Key, Value, traits_FeldmanHashMap_city64 > FeldmanHashMap_rcu_sht_city64; +#endif + + struct traits_FeldmanHashMap_city64_stat : public traits_FeldmanHashMap_city64 + { + typedef cc::feldman_hashmap::stat<> stat; + }; + typedef FeldmanHashMap< cds::gc::HP, Key, Value, traits_FeldmanHashMap_city64_stat > FeldmanHashMap_hp_city64_stat; + typedef FeldmanHashMap< cds::gc::DHP, Key, Value, traits_FeldmanHashMap_city64_stat > FeldmanHashMap_dhp_city64_stat; + typedef FeldmanHashMap< rcu_gpi, Key, Value, traits_FeldmanHashMap_city64_stat > FeldmanHashMap_rcu_gpi_city64_stat; + typedef FeldmanHashMap< rcu_gpb, Key, Value, traits_FeldmanHashMap_city64_stat > FeldmanHashMap_rcu_gpb_city64_stat; + typedef FeldmanHashMap< rcu_gpt, Key, Value, traits_FeldmanHashMap_city64_stat > FeldmanHashMap_rcu_gpt_city64_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashMap< rcu_shb, Key, Value, traits_FeldmanHashMap_city64_stat > FeldmanHashMap_rcu_shb_city64_stat; + typedef FeldmanHashMap< rcu_sht, Key, Value, traits_FeldmanHashMap_city64_stat > FeldmanHashMap_rcu_sht_city64_stat; +#endif + + struct traits_FeldmanHashMap_city128 : public cc::feldman_hashmap::traits + { + typedef ::hashing::city128 hash; + typedef ::hashing::city128::less less; + }; + typedef FeldmanHashMap< cds::gc::HP, Key, Value, traits_FeldmanHashMap_city128 > FeldmanHashMap_hp_city128; + typedef FeldmanHashMap< cds::gc::DHP, Key, Value, traits_FeldmanHashMap_city128 > FeldmanHashMap_dhp_city128; + typedef FeldmanHashMap< rcu_gpi, Key, Value, traits_FeldmanHashMap_city128 > FeldmanHashMap_rcu_gpi_city128; + typedef FeldmanHashMap< rcu_gpb, Key, Value, traits_FeldmanHashMap_city128 > FeldmanHashMap_rcu_gpb_city128; + typedef FeldmanHashMap< rcu_gpt, Key, Value, traits_FeldmanHashMap_city128 > FeldmanHashMap_rcu_gpt_city128; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashMap< rcu_shb, Key, Value, traits_FeldmanHashMap_city128 > FeldmanHashMap_rcu_shb_city128; + typedef FeldmanHashMap< rcu_sht, Key, Value, traits_FeldmanHashMap_city128 > FeldmanHashMap_rcu_sht_city128; +#endif + + struct traits_FeldmanHashMap_city128_stat : public traits_FeldmanHashMap_city128 + { + typedef cc::feldman_hashmap::stat<> stat; + }; + typedef FeldmanHashMap< cds::gc::HP, Key, Value, traits_FeldmanHashMap_city128_stat > FeldmanHashMap_hp_city128_stat; + typedef FeldmanHashMap< cds::gc::DHP, Key, Value, traits_FeldmanHashMap_city128_stat > FeldmanHashMap_dhp_city128_stat; + typedef FeldmanHashMap< rcu_gpi, Key, Value, traits_FeldmanHashMap_city128_stat > FeldmanHashMap_rcu_gpi_city128_stat; + typedef FeldmanHashMap< rcu_gpb, Key, Value, traits_FeldmanHashMap_city128_stat > FeldmanHashMap_rcu_gpb_city128_stat; + typedef FeldmanHashMap< rcu_gpt, Key, Value, traits_FeldmanHashMap_city128_stat > FeldmanHashMap_rcu_gpt_city128_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashMap< rcu_shb, Key, Value, traits_FeldmanHashMap_city128_stat > FeldmanHashMap_rcu_shb_city128_stat; + typedef FeldmanHashMap< rcu_sht, Key, Value, traits_FeldmanHashMap_city128_stat > FeldmanHashMap_rcu_sht_city128_stat; +#endif +#endif // CDS_BUILD_BITS == 64 + + + // for fixed-sized keys - no hash functor required + typedef FeldmanHashMap< cds::gc::HP, Key, Value > FeldmanHashMap_hp_fixed; + typedef FeldmanHashMap< cds::gc::DHP, Key, Value > FeldmanHashMap_dhp_fixed; + typedef FeldmanHashMap< rcu_gpi, Key, Value > FeldmanHashMap_rcu_gpi_fixed; + typedef FeldmanHashMap< rcu_gpb, Key, Value > FeldmanHashMap_rcu_gpb_fixed; + typedef FeldmanHashMap< rcu_gpt, Key, Value > FeldmanHashMap_rcu_gpt_fixed; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashMap< rcu_shb, Key, Value > FeldmanHashMap_rcu_shb_fixed; + typedef FeldmanHashMap< rcu_sht, Key, Value > FeldmanHashMap_rcu_sht_fixed; +#endif + + struct traits_FeldmanHashMap_stat : public cc::feldman_hashmap::traits + { + typedef cc::feldman_hashmap::stat<> stat; + }; + typedef FeldmanHashMap< cds::gc::HP, Key, Value, traits_FeldmanHashMap_stat > FeldmanHashMap_hp_fixed_stat; + typedef FeldmanHashMap< cds::gc::DHP, Key, Value, traits_FeldmanHashMap_stat > FeldmanHashMap_dhp_fixed_stat; + typedef FeldmanHashMap< rcu_gpi, Key, Value, traits_FeldmanHashMap_stat > FeldmanHashMap_rcu_gpi_fixed_stat; + typedef FeldmanHashMap< rcu_gpb, Key, Value, traits_FeldmanHashMap_stat > FeldmanHashMap_rcu_gpb_fixed_stat; + typedef FeldmanHashMap< rcu_gpt, Key, Value, traits_FeldmanHashMap_stat > FeldmanHashMap_rcu_gpt_fixed_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashMap< rcu_shb, Key, Value, traits_FeldmanHashMap_stat > FeldmanHashMap_rcu_shb_fixed_stat; + typedef FeldmanHashMap< rcu_sht, Key, Value, traits_FeldmanHashMap_stat > FeldmanHashMap_rcu_sht_fixed_stat; +#endif + + }; + + template + static inline void print_stat( FeldmanHashMap< GC, K, T, Traits > const& m ) + { + CPPUNIT_MSG( m.statistics() ); + } + +} // namespace map2 + +#endif // #ifndef CDSUNIT_MAP_TYPE_FELDMAN_HASHMAP_H diff --git a/tests/unit/map2/map_type_multilevel_hashmap.h b/tests/unit/map2/map_type_multilevel_hashmap.h deleted file mode 100644 index 1ac5a842..00000000 --- a/tests/unit/map2/map_type_multilevel_hashmap.h +++ /dev/null @@ -1,227 +0,0 @@ -//$$CDS-header$$ - -#ifndef CDSUNIT_MAP_TYPE_MULTILEVEL_HASHMAP_H -#define CDSUNIT_MAP_TYPE_MULTILEVEL_HASHMAP_H - -#include "map2/map_type.h" - -#include -#include -#include - -#include "print_multilevel_hashset_stat.h" -#include "hashing/hash_func.h" - -namespace map2 { - - template - class MultiLevelHashMap : public cc::MultiLevelHashMap< GC, Key, T, Traits > - { - typedef cc::MultiLevelHashMap< GC, Key, T, Traits > base_class; - public: - template - MultiLevelHashMap( Config const& cfg) - : base_class( cfg.c_nMultiLevelMap_HeadBits, cfg.c_nMultiLevelMap_ArrayBits ) - {} - - // for testing - static CDS_CONSTEXPR bool const c_bExtractSupported = true; - static CDS_CONSTEXPR bool const c_bLoadFactorDepended = false; - static CDS_CONSTEXPR bool const c_bEraseExactKey = true; - }; - - struct tag_MultiLevelHashMap; - - template - struct map_type< tag_MultiLevelHashMap, Key, Value >: public map_type_base< Key, Value > - { - typedef map_type_base< Key, Value > base_class; - typedef typename base_class::compare compare; - typedef typename base_class::less less; - - struct traits_MultiLevelHashMap_stdhash : public cc::multilevel_hashmap::traits - { - typedef std::hash< Key > hash; - }; - - typedef MultiLevelHashMap< cds::gc::HP, Key, Value, traits_MultiLevelHashMap_stdhash > MultiLevelHashMap_hp_stdhash; - typedef MultiLevelHashMap< cds::gc::DHP, Key, Value, traits_MultiLevelHashMap_stdhash > MultiLevelHashMap_dhp_stdhash; - typedef MultiLevelHashMap< rcu_gpi, Key, Value, traits_MultiLevelHashMap_stdhash > MultiLevelHashMap_rcu_gpi_stdhash; - typedef MultiLevelHashMap< rcu_gpb, Key, Value, traits_MultiLevelHashMap_stdhash > MultiLevelHashMap_rcu_gpb_stdhash; - typedef MultiLevelHashMap< rcu_gpt, Key, Value, traits_MultiLevelHashMap_stdhash > MultiLevelHashMap_rcu_gpt_stdhash; -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef MultiLevelHashMap< rcu_shb, Key, Value, traits_MultiLevelHashMap_stdhash > MultiLevelHashMap_rcu_shb_stdhash; - typedef MultiLevelHashMap< rcu_sht, Key, Value, traits_MultiLevelHashMap_stdhash > MultiLevelHashMap_rcu_sht_stdhash; -#endif - - struct traits_MultiLevelHashMap_stdhash_stat: traits_MultiLevelHashMap_stdhash - { - typedef cc::multilevel_hashmap::stat<> stat; - }; - - typedef MultiLevelHashMap< cds::gc::HP, Key, Value, traits_MultiLevelHashMap_stdhash_stat > MultiLevelHashMap_hp_stdhash_stat; - typedef MultiLevelHashMap< cds::gc::DHP, Key, Value, traits_MultiLevelHashMap_stdhash_stat > MultiLevelHashMap_dhp_stdhash_stat; - typedef MultiLevelHashMap< rcu_gpi, Key, Value, traits_MultiLevelHashMap_stdhash_stat > MultiLevelHashMap_rcu_gpi_stdhash_stat; - typedef MultiLevelHashMap< rcu_gpb, Key, Value, traits_MultiLevelHashMap_stdhash_stat > MultiLevelHashMap_rcu_gpb_stdhash_stat; - typedef MultiLevelHashMap< rcu_gpt, Key, Value, traits_MultiLevelHashMap_stdhash_stat > MultiLevelHashMap_rcu_gpt_stdhash_stat; -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef MultiLevelHashMap< rcu_shb, Key, Value, traits_MultiLevelHashMap_stdhash_stat > MultiLevelHashMap_rcu_shb_stdhash_stat; - typedef MultiLevelHashMap< rcu_sht, Key, Value, traits_MultiLevelHashMap_stdhash_stat > MultiLevelHashMap_rcu_sht_stdhash_stat; -#endif - - // SHA256 - struct traits_MultiLevelHashMap_sha256 : public cc::multilevel_hashmap::traits - { - typedef ::hashing::sha256 hash; - }; - typedef MultiLevelHashMap< cds::gc::HP, Key, Value, traits_MultiLevelHashMap_sha256 > MultiLevelHashMap_hp_sha256; - typedef MultiLevelHashMap< cds::gc::DHP, Key, Value, traits_MultiLevelHashMap_sha256 > MultiLevelHashMap_dhp_sha256; - typedef MultiLevelHashMap< rcu_gpi, Key, Value, traits_MultiLevelHashMap_sha256 > MultiLevelHashMap_rcu_gpi_sha256; - typedef MultiLevelHashMap< rcu_gpb, Key, Value, traits_MultiLevelHashMap_sha256 > MultiLevelHashMap_rcu_gpb_sha256; - typedef MultiLevelHashMap< rcu_gpt, Key, Value, traits_MultiLevelHashMap_sha256 > MultiLevelHashMap_rcu_gpt_sha256; -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef MultiLevelHashMap< rcu_shb, Key, Value, traits_MultiLevelHashMap_sha256 > MultiLevelHashMap_rcu_shb_sha256; - typedef MultiLevelHashMap< rcu_sht, Key, Value, traits_MultiLevelHashMap_sha256 > MultiLevelHashMap_rcu_sht_sha256; -#endif - - struct traits_MultiLevelHashMap_sha256_stat : public traits_MultiLevelHashMap_sha256 - { - typedef cc::multilevel_hashmap::stat<> stat; - }; - typedef MultiLevelHashMap< cds::gc::HP, Key, Value, traits_MultiLevelHashMap_sha256_stat > MultiLevelHashMap_hp_sha256_stat; - typedef MultiLevelHashMap< cds::gc::DHP, Key, Value, traits_MultiLevelHashMap_sha256_stat > MultiLevelHashMap_dhp_sha256_stat; - typedef MultiLevelHashMap< rcu_gpi, Key, Value, traits_MultiLevelHashMap_sha256_stat > MultiLevelHashMap_rcu_gpi_sha256_stat; - typedef MultiLevelHashMap< rcu_gpb, Key, Value, traits_MultiLevelHashMap_sha256_stat > MultiLevelHashMap_rcu_gpb_sha256_stat; - typedef MultiLevelHashMap< rcu_gpt, Key, Value, traits_MultiLevelHashMap_sha256_stat > MultiLevelHashMap_rcu_gpt_sha256_stat; -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef MultiLevelHashMap< rcu_shb, Key, Value, traits_MultiLevelHashMap_sha256_stat > MultiLevelHashMap_rcu_shb_sha256_stat; - typedef MultiLevelHashMap< rcu_sht, Key, Value, traits_MultiLevelHashMap_sha256_stat > MultiLevelHashMap_rcu_sht_sha256_stat; -#endif - - //MD5 - struct traits_MultiLevelHashMap_md5 : public cc::multilevel_hashmap::traits - { - typedef ::hashing::md5 hash; - }; - typedef MultiLevelHashMap< cds::gc::HP, Key, Value, traits_MultiLevelHashMap_md5 > MultiLevelHashMap_hp_md5; - typedef MultiLevelHashMap< cds::gc::DHP, Key, Value, traits_MultiLevelHashMap_md5 > MultiLevelHashMap_dhp_md5; - typedef MultiLevelHashMap< rcu_gpi, Key, Value, traits_MultiLevelHashMap_md5 > MultiLevelHashMap_rcu_gpi_md5; - typedef MultiLevelHashMap< rcu_gpb, Key, Value, traits_MultiLevelHashMap_md5 > MultiLevelHashMap_rcu_gpb_md5; - typedef MultiLevelHashMap< rcu_gpt, Key, Value, traits_MultiLevelHashMap_md5 > MultiLevelHashMap_rcu_gpt_md5; -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef MultiLevelHashMap< rcu_shb, Key, Value, traits_MultiLevelHashMap_md5 > MultiLevelHashMap_rcu_shb_md5; - typedef MultiLevelHashMap< rcu_sht, Key, Value, traits_MultiLevelHashMap_md5 > MultiLevelHashMap_rcu_sht_md5; -#endif - - struct traits_MultiLevelHashMap_md5_stat : public traits_MultiLevelHashMap_md5 - { - typedef cc::multilevel_hashmap::stat<> stat; - }; - typedef MultiLevelHashMap< cds::gc::HP, Key, Value, traits_MultiLevelHashMap_md5_stat > MultiLevelHashMap_hp_md5_stat; - typedef MultiLevelHashMap< cds::gc::DHP, Key, Value, traits_MultiLevelHashMap_md5_stat > MultiLevelHashMap_dhp_md5_stat; - typedef MultiLevelHashMap< rcu_gpi, Key, Value, traits_MultiLevelHashMap_md5_stat > MultiLevelHashMap_rcu_gpi_md5_stat; - typedef MultiLevelHashMap< rcu_gpb, Key, Value, traits_MultiLevelHashMap_md5_stat > MultiLevelHashMap_rcu_gpb_md5_stat; - typedef MultiLevelHashMap< rcu_gpt, Key, Value, traits_MultiLevelHashMap_md5_stat > MultiLevelHashMap_rcu_gpt_md5_stat; -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef MultiLevelHashMap< rcu_shb, Key, Value, traits_MultiLevelHashMap_md5_stat > MultiLevelHashMap_rcu_shb_md5_stat; - typedef MultiLevelHashMap< rcu_sht, Key, Value, traits_MultiLevelHashMap_md5_stat > MultiLevelHashMap_rcu_sht_md5_stat; -#endif - - // CityHash -#if CDS_BUILD_BITS == 64 - struct traits_MultiLevelHashMap_city64 : public cc::multilevel_hashmap::traits - { - typedef ::hashing::city64 hash; - typedef ::hashing::city64::less less; - }; - typedef MultiLevelHashMap< cds::gc::HP, Key, Value, traits_MultiLevelHashMap_city64 > MultiLevelHashMap_hp_city64; - typedef MultiLevelHashMap< cds::gc::DHP, Key, Value, traits_MultiLevelHashMap_city64 > MultiLevelHashMap_dhp_city64; - typedef MultiLevelHashMap< rcu_gpi, Key, Value, traits_MultiLevelHashMap_city64 > MultiLevelHashMap_rcu_gpi_city64; - typedef MultiLevelHashMap< rcu_gpb, Key, Value, traits_MultiLevelHashMap_city64 > MultiLevelHashMap_rcu_gpb_city64; - typedef MultiLevelHashMap< rcu_gpt, Key, Value, traits_MultiLevelHashMap_city64 > MultiLevelHashMap_rcu_gpt_city64; -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef MultiLevelHashMap< rcu_shb, Key, Value, traits_MultiLevelHashMap_city64 > MultiLevelHashMap_rcu_shb_city64; - typedef MultiLevelHashMap< rcu_sht, Key, Value, traits_MultiLevelHashMap_city64 > MultiLevelHashMap_rcu_sht_city64; -#endif - - struct traits_MultiLevelHashMap_city64_stat : public traits_MultiLevelHashMap_city64 - { - typedef cc::multilevel_hashmap::stat<> stat; - }; - typedef MultiLevelHashMap< cds::gc::HP, Key, Value, traits_MultiLevelHashMap_city64_stat > MultiLevelHashMap_hp_city64_stat; - typedef MultiLevelHashMap< cds::gc::DHP, Key, Value, traits_MultiLevelHashMap_city64_stat > MultiLevelHashMap_dhp_city64_stat; - typedef MultiLevelHashMap< rcu_gpi, Key, Value, traits_MultiLevelHashMap_city64_stat > MultiLevelHashMap_rcu_gpi_city64_stat; - typedef MultiLevelHashMap< rcu_gpb, Key, Value, traits_MultiLevelHashMap_city64_stat > MultiLevelHashMap_rcu_gpb_city64_stat; - typedef MultiLevelHashMap< rcu_gpt, Key, Value, traits_MultiLevelHashMap_city64_stat > MultiLevelHashMap_rcu_gpt_city64_stat; -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef MultiLevelHashMap< rcu_shb, Key, Value, traits_MultiLevelHashMap_city64_stat > MultiLevelHashMap_rcu_shb_city64_stat; - typedef MultiLevelHashMap< rcu_sht, Key, Value, traits_MultiLevelHashMap_city64_stat > MultiLevelHashMap_rcu_sht_city64_stat; -#endif - - struct traits_MultiLevelHashMap_city128 : public cc::multilevel_hashmap::traits - { - typedef ::hashing::city128 hash; - typedef ::hashing::city128::less less; - }; - typedef MultiLevelHashMap< cds::gc::HP, Key, Value, traits_MultiLevelHashMap_city128 > MultiLevelHashMap_hp_city128; - typedef MultiLevelHashMap< cds::gc::DHP, Key, Value, traits_MultiLevelHashMap_city128 > MultiLevelHashMap_dhp_city128; - typedef MultiLevelHashMap< rcu_gpi, Key, Value, traits_MultiLevelHashMap_city128 > MultiLevelHashMap_rcu_gpi_city128; - typedef MultiLevelHashMap< rcu_gpb, Key, Value, traits_MultiLevelHashMap_city128 > MultiLevelHashMap_rcu_gpb_city128; - typedef MultiLevelHashMap< rcu_gpt, Key, Value, traits_MultiLevelHashMap_city128 > MultiLevelHashMap_rcu_gpt_city128; -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef MultiLevelHashMap< rcu_shb, Key, Value, traits_MultiLevelHashMap_city128 > MultiLevelHashMap_rcu_shb_city128; - typedef MultiLevelHashMap< rcu_sht, Key, Value, traits_MultiLevelHashMap_city128 > MultiLevelHashMap_rcu_sht_city128; -#endif - - struct traits_MultiLevelHashMap_city128_stat : public traits_MultiLevelHashMap_city128 - { - typedef cc::multilevel_hashmap::stat<> stat; - }; - typedef MultiLevelHashMap< cds::gc::HP, Key, Value, traits_MultiLevelHashMap_city128_stat > MultiLevelHashMap_hp_city128_stat; - typedef MultiLevelHashMap< cds::gc::DHP, Key, Value, traits_MultiLevelHashMap_city128_stat > MultiLevelHashMap_dhp_city128_stat; - typedef MultiLevelHashMap< rcu_gpi, Key, Value, traits_MultiLevelHashMap_city128_stat > MultiLevelHashMap_rcu_gpi_city128_stat; - typedef MultiLevelHashMap< rcu_gpb, Key, Value, traits_MultiLevelHashMap_city128_stat > MultiLevelHashMap_rcu_gpb_city128_stat; - typedef MultiLevelHashMap< rcu_gpt, Key, Value, traits_MultiLevelHashMap_city128_stat > MultiLevelHashMap_rcu_gpt_city128_stat; -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef MultiLevelHashMap< rcu_shb, Key, Value, traits_MultiLevelHashMap_city128_stat > MultiLevelHashMap_rcu_shb_city128_stat; - typedef MultiLevelHashMap< rcu_sht, Key, Value, traits_MultiLevelHashMap_city128_stat > MultiLevelHashMap_rcu_sht_city128_stat; -#endif -#endif // CDS_BUILD_BITS == 64 - - - // for fixed-sized keys - no hash functor required - typedef MultiLevelHashMap< cds::gc::HP, Key, Value > MultiLevelHashMap_hp_fixed; - typedef MultiLevelHashMap< cds::gc::DHP, Key, Value > MultiLevelHashMap_dhp_fixed; - typedef MultiLevelHashMap< rcu_gpi, Key, Value > MultiLevelHashMap_rcu_gpi_fixed; - typedef MultiLevelHashMap< rcu_gpb, Key, Value > MultiLevelHashMap_rcu_gpb_fixed; - typedef MultiLevelHashMap< rcu_gpt, Key, Value > MultiLevelHashMap_rcu_gpt_fixed; -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef MultiLevelHashMap< rcu_shb, Key, Value > MultiLevelHashMap_rcu_shb_fixed; - typedef MultiLevelHashMap< rcu_sht, Key, Value > MultiLevelHashMap_rcu_sht_fixed; -#endif - - struct traits_MultiLevelHashMap_stat : public cc::multilevel_hashmap::traits - { - typedef cc::multilevel_hashmap::stat<> stat; - }; - typedef MultiLevelHashMap< cds::gc::HP, Key, Value, traits_MultiLevelHashMap_stat > MultiLevelHashMap_hp_fixed_stat; - typedef MultiLevelHashMap< cds::gc::DHP, Key, Value, traits_MultiLevelHashMap_stat > MultiLevelHashMap_dhp_fixed_stat; - typedef MultiLevelHashMap< rcu_gpi, Key, Value, traits_MultiLevelHashMap_stat > MultiLevelHashMap_rcu_gpi_fixed_stat; - typedef MultiLevelHashMap< rcu_gpb, Key, Value, traits_MultiLevelHashMap_stat > MultiLevelHashMap_rcu_gpb_fixed_stat; - typedef MultiLevelHashMap< rcu_gpt, Key, Value, traits_MultiLevelHashMap_stat > MultiLevelHashMap_rcu_gpt_fixed_stat; -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef MultiLevelHashMap< rcu_shb, Key, Value, traits_MultiLevelHashMap_stat > MultiLevelHashMap_rcu_shb_fixed_stat; - typedef MultiLevelHashMap< rcu_sht, Key, Value, traits_MultiLevelHashMap_stat > MultiLevelHashMap_rcu_sht_fixed_stat; -#endif - - }; - - template - static inline void print_stat( MultiLevelHashMap< GC, K, T, Traits > const& m ) - { - CPPUNIT_MSG( m.statistics() ); - } - -} // namespace map2 - -#endif // #ifndef CDSUNIT_MAP_TYPE_MULTILEVEL_HASHMAP_H diff --git a/tests/unit/print_feldman_hashset_stat.h b/tests/unit/print_feldman_hashset_stat.h new file mode 100644 index 00000000..73560dec --- /dev/null +++ b/tests/unit/print_feldman_hashset_stat.h @@ -0,0 +1,42 @@ +//$$CDS-header$$ + +#ifndef CDSUNIT_PRINT_FELDMAN_HASHSET_STAT_H +#define CDSUNIT_PRINT_FELDMAN_HASHSET_STAT_H + +#include +#include + +namespace std { + + static inline ostream& operator <<( ostream& o, cds::intrusive::feldman_hashset::stat<> const& s ) + { + return + o << "Stat [cds::intrusive::feldman_hashset::stat]\n" + << "\t\t m_nInsertSuccess: " << s.m_nInsertSuccess.get() << "\n" + << "\t\t m_nInsertFailed: " << s.m_nInsertFailed.get() << "\n" + << "\t\t m_nInsertRetry: " << s.m_nInsertRetry.get() << "\n" + << "\t\t m_nUpdateNew: " << s.m_nUpdateNew.get() << "\n" + << "\t\t m_nUpdateExisting: " << s.m_nUpdateExisting.get() << "\n" + << "\t\t m_nUpdateFailed: " << s.m_nUpdateFailed.get() << "\n" + << "\t\t m_nUpdateRetry: " << s.m_nUpdateRetry.get() << "\n" + << "\t\t m_nEraseSuccess: " << s.m_nEraseSuccess.get() << "\n" + << "\t\t m_nEraseFailed: " << s.m_nEraseFailed.get() << "\n" + << "\t\t m_nEraseRetry: " << s.m_nEraseRetry.get() << "\n" + << "\t\t m_nFindSuccess: " << s.m_nFindSuccess.get() << "\n" + << "\t\t m_nFindFailed: " << s.m_nFindFailed.get() << "\n" + << "\t\t m_nExpandNodeSuccess: " << s.m_nExpandNodeSuccess.get() << "\n" + << "\t\t m_nExpandNodeFailed: " << s.m_nExpandNodeFailed.get() << "\n" + << "\t\t m_nSlotChanged: " << s.m_nSlotChanged.get() << "\n" + << "\t\t m_nSlotConverting: " << s.m_nSlotConverting.get() << "\n" + << "\t\t m_nArrayNodeCount: " << s.m_nArrayNodeCount.get() << "\n" + << "\t\t m_nHeight: " << s.m_nHeight.get() << "\n"; + } + + static inline ostream& operator <<( ostream& o, cds::intrusive::feldman_hashset::empty_stat const& /*s*/ ) + { + return o; + } + +} // namespace std + +#endif // #ifndef CDSUNIT_PRINT_FELDMAN_HASHSET_STAT_H diff --git a/tests/unit/print_multilevel_hashset_stat.h b/tests/unit/print_multilevel_hashset_stat.h deleted file mode 100644 index 5fe06af3..00000000 --- a/tests/unit/print_multilevel_hashset_stat.h +++ /dev/null @@ -1,42 +0,0 @@ -//$$CDS-header$$ - -#ifndef CDSUNIT_PRINT_MULTILEVEL_HASHSET_STAT_H -#define CDSUNIT_PRINT_MULTILEVEL_HASHSET_STAT_H - -#include -#include - -namespace std { - - static inline ostream& operator <<( ostream& o, cds::intrusive::multilevel_hashset::stat<> const& s ) - { - return - o << "Stat [cds::intrusive::multilevel_hashset::stat]\n" - << "\t\t m_nInsertSuccess: " << s.m_nInsertSuccess.get() << "\n" - << "\t\t m_nInsertFailed: " << s.m_nInsertFailed.get() << "\n" - << "\t\t m_nInsertRetry: " << s.m_nInsertRetry.get() << "\n" - << "\t\t m_nUpdateNew: " << s.m_nUpdateNew.get() << "\n" - << "\t\t m_nUpdateExisting: " << s.m_nUpdateExisting.get() << "\n" - << "\t\t m_nUpdateFailed: " << s.m_nUpdateFailed.get() << "\n" - << "\t\t m_nUpdateRetry: " << s.m_nUpdateRetry.get() << "\n" - << "\t\t m_nEraseSuccess: " << s.m_nEraseSuccess.get() << "\n" - << "\t\t m_nEraseFailed: " << s.m_nEraseFailed.get() << "\n" - << "\t\t m_nEraseRetry: " << s.m_nEraseRetry.get() << "\n" - << "\t\t m_nFindSuccess: " << s.m_nFindSuccess.get() << "\n" - << "\t\t m_nFindFailed: " << s.m_nFindFailed.get() << "\n" - << "\t\t m_nExpandNodeSuccess: " << s.m_nExpandNodeSuccess.get() << "\n" - << "\t\t m_nExpandNodeFailed: " << s.m_nExpandNodeFailed.get() << "\n" - << "\t\t m_nSlotChanged: " << s.m_nSlotChanged.get() << "\n" - << "\t\t m_nSlotConverting: " << s.m_nSlotConverting.get() << "\n" - << "\t\t m_nArrayNodeCount: " << s.m_nArrayNodeCount.get() << "\n" - << "\t\t m_nHeight: " << s.m_nHeight.get() << "\n"; - } - - static inline ostream& operator <<( ostream& o, cds::intrusive::multilevel_hashset::empty_stat const& /*s*/ ) - { - return o; - } - -} // namespace std - -#endif // #ifndef CDSUNIT_PRINT_MULTILEVEL_HASHSET_STAT_H diff --git a/tests/unit/set2/CMakeLists.txt b/tests/unit/set2/CMakeLists.txt index e7b7ea06..89e71cf1 100644 --- a/tests/unit/set2/CMakeLists.txt +++ b/tests/unit/set2/CMakeLists.txt @@ -5,7 +5,7 @@ set(CDSUNIT_SET_SOURCES set_insdel_func_cuckoo.cpp set_insdel_func_ellentree.cpp set_insdel_func_michael.cpp - set_insdel_func_multilevelhashset.cpp + set_insdel_func_feldmanhashset.cpp set_insdel_func_skip.cpp set_insdel_func_split.cpp set_insdel_func_striped.cpp @@ -13,7 +13,7 @@ set(CDSUNIT_SET_SOURCES set_insdel_string_cuckoo.cpp set_insdel_string_ellentree.cpp set_insdel_string_michael.cpp - set_insdel_string_multilevelhashset.cpp + set_insdel_string_feldmanhashset.cpp set_insdel_string_skip.cpp set_insdel_string_split.cpp set_insdel_string_striped.cpp @@ -22,7 +22,7 @@ set(CDSUNIT_SET_SOURCES set_insdelfind_cuckoo.cpp set_insdelfind_ellentree.cpp set_insdelfind_michael.cpp - set_insdelfind_multilevelhashset.cpp + set_insdelfind_feldmanhashset.cpp set_insdelfind_skip.cpp set_insdelfind_split.cpp set_insdelfind_striped.cpp @@ -31,7 +31,7 @@ set(CDSUNIT_SET_SOURCES set_delodd_cuckoo.cpp set_delodd_ellentree.cpp set_delodd_michael.cpp - set_delodd_multilevelhashset.cpp + set_delodd_feldmanhashset.cpp set_delodd_skip.cpp set_delodd_split.cpp ) diff --git a/tests/unit/set2/set_defs.h b/tests/unit/set2/set_defs.h index 478ce052..ce1f9c1e 100644 --- a/tests/unit/set2/set_defs.h +++ b/tests/unit/set2/set_defs.h @@ -616,311 +616,311 @@ //*********************************************** -// MultiLevelHashSet +// FeldmanHashSet // For fixed-sized key - no hash function is needed -#undef CDSUNIT_DECLARE_MultiLevelHashSet_fixed -#undef CDSUNIT_DECLARE_MultiLevelHashSet_fixed_RCU_signal -#undef CDSUNIT_TEST_MultiLevelHashSet_fixed -#undef CDSUNIT_TEST_MultiLevelHashSet_fixed_RCU_signal +#undef CDSUNIT_DECLARE_FeldmanHashSet_fixed +#undef CDSUNIT_DECLARE_FeldmanHashSet_fixed_RCU_signal +#undef CDSUNIT_TEST_FeldmanHashSet_fixed +#undef CDSUNIT_TEST_FeldmanHashSet_fixed_RCU_signal #ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED -# define CDSUNIT_DECLARE_MultiLevelHashSet_fixed_RCU_signal \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_shb_fixed) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_shb_fixed_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_sht_fixed) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_sht_fixed_stat) \ - -# define CDSUNIT_TEST_MultiLevelHashSet_fixed_RCU_signal \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_shb_fixed) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_shb_fixed_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_sht_fixed) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_sht_fixed_stat) \ +# define CDSUNIT_DECLARE_FeldmanHashSet_fixed_RCU_signal \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_shb_fixed) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_shb_fixed_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_sht_fixed) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_sht_fixed_stat) \ + +# define CDSUNIT_TEST_FeldmanHashSet_fixed_RCU_signal \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_shb_fixed) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_shb_fixed_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_sht_fixed) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_sht_fixed_stat) \ #else -# define CDSUNIT_DECLARE_MultiLevelHashSet_fixed_RCU_signal -# define CDSUNIT_TEST_MultiLevelHashSet_fixed_RCU_signal +# define CDSUNIT_DECLARE_FeldmanHashSet_fixed_RCU_signal +# define CDSUNIT_TEST_FeldmanHashSet_fixed_RCU_signal #endif -#define CDSUNIT_DECLARE_MultiLevelHashSet_fixed \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_hp_fixed) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_hp_fixed_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_dhp_fixed) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_dhp_fixed_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpi_fixed) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpi_fixed_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpb_fixed) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpb_fixed_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpt_fixed) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpt_fixed_stat) \ - CDSUNIT_DECLARE_MultiLevelHashSet_fixed_RCU_signal - -#define CDSUNIT_TEST_MultiLevelHashSet_fixed \ - CPPUNIT_TEST(MultiLevelHashSet_hp_fixed) \ - CPPUNIT_TEST(MultiLevelHashSet_hp_fixed_stat) \ - CPPUNIT_TEST(MultiLevelHashSet_dhp_fixed) \ - CPPUNIT_TEST(MultiLevelHashSet_dhp_fixed_stat) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpi_fixed) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpi_fixed_stat) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpb_fixed) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpb_fixed_stat) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpt_fixed) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpt_fixed_stat) \ - CDSUNIT_TEST_MultiLevelHashSet_fixed_RCU_signal +#define CDSUNIT_DECLARE_FeldmanHashSet_fixed \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_hp_fixed) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_hp_fixed_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_dhp_fixed) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_dhp_fixed_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpi_fixed) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpi_fixed_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpb_fixed) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpb_fixed_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpt_fixed) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpt_fixed_stat) \ + CDSUNIT_DECLARE_FeldmanHashSet_fixed_RCU_signal + +#define CDSUNIT_TEST_FeldmanHashSet_fixed \ + CPPUNIT_TEST(FeldmanHashSet_hp_fixed) \ + CPPUNIT_TEST(FeldmanHashSet_hp_fixed_stat) \ + CPPUNIT_TEST(FeldmanHashSet_dhp_fixed) \ + CPPUNIT_TEST(FeldmanHashSet_dhp_fixed_stat) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpi_fixed) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpi_fixed_stat) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpb_fixed) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpb_fixed_stat) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpt_fixed) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpt_fixed_stat) \ + CDSUNIT_TEST_FeldmanHashSet_fixed_RCU_signal // std::hash -#undef CDSUNIT_DECLARE_MultiLevelHashSet_stdhash -#undef CDSUNIT_DECLARE_MultiLevelHashSet_stdhash_RCU_signal -#undef CDSUNIT_TEST_MultiLevelHashSet_stdhash -#undef CDSUNIT_TEST_MultiLevelHashSet_stdhash_RCU_signal +#undef CDSUNIT_DECLARE_FeldmanHashSet_stdhash +#undef CDSUNIT_DECLARE_FeldmanHashSet_stdhash_RCU_signal +#undef CDSUNIT_TEST_FeldmanHashSet_stdhash +#undef CDSUNIT_TEST_FeldmanHashSet_stdhash_RCU_signal #ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED -# define CDSUNIT_DECLARE_MultiLevelHashSet_stdhash_RCU_signal \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_shb_stdhash) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_shb_stdhash_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_sht_stdhash) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_sht_stdhash_stat) \ - -# define CDSUNIT_TEST_MultiLevelHashSet_stdhash_RCU_signal \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_shb_stdhash) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_shb_stdhash_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_sht_stdhash) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_sht_stdhash_stat) \ +# define CDSUNIT_DECLARE_FeldmanHashSet_stdhash_RCU_signal \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_shb_stdhash) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_shb_stdhash_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_sht_stdhash) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_sht_stdhash_stat) \ + +# define CDSUNIT_TEST_FeldmanHashSet_stdhash_RCU_signal \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_shb_stdhash) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_shb_stdhash_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_sht_stdhash) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_sht_stdhash_stat) \ #else -# define CDSUNIT_DECLARE_MultiLevelHashSet_stdhash_RCU_signal -# define CDSUNIT_TEST_MultiLevelHashSet_stdhash_RCU_signal +# define CDSUNIT_DECLARE_FeldmanHashSet_stdhash_RCU_signal +# define CDSUNIT_TEST_FeldmanHashSet_stdhash_RCU_signal #endif -#define CDSUNIT_DECLARE_MultiLevelHashSet_stdhash \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_hp_stdhash) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_hp_stdhash_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_dhp_stdhash) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_dhp_stdhash_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpi_stdhash) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpi_stdhash_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpb_stdhash) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpb_stdhash_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpt_stdhash) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpt_stdhash_stat) \ - CDSUNIT_DECLARE_MultiLevelHashSet_stdhash_RCU_signal - -#define CDSUNIT_TEST_MultiLevelHashSet_stdhash \ - CPPUNIT_TEST(MultiLevelHashSet_hp_stdhash) \ - CPPUNIT_TEST(MultiLevelHashSet_hp_stdhash_stat) \ - CPPUNIT_TEST(MultiLevelHashSet_dhp_stdhash) \ - CPPUNIT_TEST(MultiLevelHashSet_dhp_stdhash_stat) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpi_stdhash) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpi_stdhash_stat) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpb_stdhash) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpb_stdhash_stat) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpt_stdhash) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpt_stdhash_stat) \ - CDSUNIT_TEST_MultiLevelHashSet_stdhash_RCU_signal +#define CDSUNIT_DECLARE_FeldmanHashSet_stdhash \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_hp_stdhash) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_hp_stdhash_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_dhp_stdhash) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_dhp_stdhash_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpi_stdhash) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpi_stdhash_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpb_stdhash) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpb_stdhash_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpt_stdhash) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpt_stdhash_stat) \ + CDSUNIT_DECLARE_FeldmanHashSet_stdhash_RCU_signal + +#define CDSUNIT_TEST_FeldmanHashSet_stdhash \ + CPPUNIT_TEST(FeldmanHashSet_hp_stdhash) \ + CPPUNIT_TEST(FeldmanHashSet_hp_stdhash_stat) \ + CPPUNIT_TEST(FeldmanHashSet_dhp_stdhash) \ + CPPUNIT_TEST(FeldmanHashSet_dhp_stdhash_stat) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpi_stdhash) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpi_stdhash_stat) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpb_stdhash) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpb_stdhash_stat) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpt_stdhash) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpt_stdhash_stat) \ + CDSUNIT_TEST_FeldmanHashSet_stdhash_RCU_signal // MD5 -#undef CDSUNIT_DECLARE_MultiLevelHashSet_md5 -#undef CDSUNIT_DECLARE_MultiLevelHashSet_md5_RCU_signal -#undef CDSUNIT_TEST_MultiLevelHashSet_md5 -#undef CDSUNIT_TEST_MultiLevelHashSet_md5_RCU_signal +#undef CDSUNIT_DECLARE_FeldmanHashSet_md5 +#undef CDSUNIT_DECLARE_FeldmanHashSet_md5_RCU_signal +#undef CDSUNIT_TEST_FeldmanHashSet_md5 +#undef CDSUNIT_TEST_FeldmanHashSet_md5_RCU_signal #ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED -# define CDSUNIT_DECLARE_MultiLevelHashSet_md5_RCU_signal \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_shb_md5) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_shb_md5_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_sht_md5) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_sht_md5_stat) \ - -# define CDSUNIT_TEST_MultiLevelHashSet_md5_RCU_signal \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_shb_md5) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_shb_md5_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_sht_md5) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_sht_md5_stat) \ +# define CDSUNIT_DECLARE_FeldmanHashSet_md5_RCU_signal \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_shb_md5) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_shb_md5_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_sht_md5) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_sht_md5_stat) \ + +# define CDSUNIT_TEST_FeldmanHashSet_md5_RCU_signal \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_shb_md5) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_shb_md5_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_sht_md5) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_sht_md5_stat) \ #else -# define CDSUNIT_DECLARE_MultiLevelHashSet_md5_RCU_signal -# define CDSUNIT_TEST_MultiLevelHashSet_md5_RCU_signal +# define CDSUNIT_DECLARE_FeldmanHashSet_md5_RCU_signal +# define CDSUNIT_TEST_FeldmanHashSet_md5_RCU_signal #endif -#define CDSUNIT_DECLARE_MultiLevelHashSet_md5 \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_hp_md5) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_hp_md5_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_dhp_md5) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_dhp_md5_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpi_md5) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpi_md5_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpb_md5) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpb_md5_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpt_md5) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpt_md5_stat) \ - CDSUNIT_DECLARE_MultiLevelHashSet_md5_RCU_signal - -#define CDSUNIT_TEST_MultiLevelHashSet_md5 \ - CPPUNIT_TEST(MultiLevelHashSet_hp_md5) \ - CPPUNIT_TEST(MultiLevelHashSet_hp_md5_stat) \ - CPPUNIT_TEST(MultiLevelHashSet_dhp_md5) \ - CPPUNIT_TEST(MultiLevelHashSet_dhp_md5_stat) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpi_md5) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpi_md5_stat) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpb_md5) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpb_md5_stat) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpt_md5) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpt_md5_stat) \ - CDSUNIT_TEST_MultiLevelHashSet_md5_RCU_signal +#define CDSUNIT_DECLARE_FeldmanHashSet_md5 \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_hp_md5) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_hp_md5_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_dhp_md5) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_dhp_md5_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpi_md5) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpi_md5_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpb_md5) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpb_md5_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpt_md5) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpt_md5_stat) \ + CDSUNIT_DECLARE_FeldmanHashSet_md5_RCU_signal + +#define CDSUNIT_TEST_FeldmanHashSet_md5 \ + CPPUNIT_TEST(FeldmanHashSet_hp_md5) \ + CPPUNIT_TEST(FeldmanHashSet_hp_md5_stat) \ + CPPUNIT_TEST(FeldmanHashSet_dhp_md5) \ + CPPUNIT_TEST(FeldmanHashSet_dhp_md5_stat) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpi_md5) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpi_md5_stat) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpb_md5) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpb_md5_stat) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpt_md5) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpt_md5_stat) \ + CDSUNIT_TEST_FeldmanHashSet_md5_RCU_signal // SHA256 -#undef CDSUNIT_DECLARE_MultiLevelHashSet_sha256 -#undef CDSUNIT_DECLARE_MultiLevelHashSet_sha256_RCU_signal -#undef CDSUNIT_TEST_MultiLevelHashSet_sha256 -#undef CDSUNIT_TEST_MultiLevelHashSet_sha256_RCU_signal +#undef CDSUNIT_DECLARE_FeldmanHashSet_sha256 +#undef CDSUNIT_DECLARE_FeldmanHashSet_sha256_RCU_signal +#undef CDSUNIT_TEST_FeldmanHashSet_sha256 +#undef CDSUNIT_TEST_FeldmanHashSet_sha256_RCU_signal #ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED -# define CDSUNIT_DECLARE_MultiLevelHashSet_sha256_RCU_signal \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_shb_sha256) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_shb_sha256_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_sht_sha256) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_sht_sha256_stat) \ - -# define CDSUNIT_TEST_MultiLevelHashSet_sha256_RCU_signal \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_shb_sha256) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_shb_sha256_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_sht_sha256) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_sht_sha256_stat) \ +# define CDSUNIT_DECLARE_FeldmanHashSet_sha256_RCU_signal \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_shb_sha256) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_shb_sha256_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_sht_sha256) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_sht_sha256_stat) \ + +# define CDSUNIT_TEST_FeldmanHashSet_sha256_RCU_signal \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_shb_sha256) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_shb_sha256_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_sht_sha256) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_sht_sha256_stat) \ #else -# define CDSUNIT_DECLARE_MultiLevelHashSet_sha256_RCU_signal -# define CDSUNIT_TEST_MultiLevelHashSet_sha256_RCU_signal +# define CDSUNIT_DECLARE_FeldmanHashSet_sha256_RCU_signal +# define CDSUNIT_TEST_FeldmanHashSet_sha256_RCU_signal #endif -#define CDSUNIT_DECLARE_MultiLevelHashSet_sha256 \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_hp_sha256) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_hp_sha256_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_dhp_sha256) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_dhp_sha256_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpi_sha256) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpi_sha256_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpb_sha256) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpb_sha256_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpt_sha256) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpt_sha256_stat) \ - CDSUNIT_DECLARE_MultiLevelHashSet_sha256_RCU_signal - -#define CDSUNIT_TEST_MultiLevelHashSet_sha256 \ - CPPUNIT_TEST(MultiLevelHashSet_hp_sha256) \ - CPPUNIT_TEST(MultiLevelHashSet_hp_sha256_stat) \ - CPPUNIT_TEST(MultiLevelHashSet_dhp_sha256) \ - CPPUNIT_TEST(MultiLevelHashSet_dhp_sha256_stat) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpi_sha256) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpi_sha256_stat) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpb_sha256) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpb_sha256_stat) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpt_sha256) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpt_sha256_stat) \ - CDSUNIT_TEST_MultiLevelHashSet_sha256_RCU_signal +#define CDSUNIT_DECLARE_FeldmanHashSet_sha256 \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_hp_sha256) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_hp_sha256_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_dhp_sha256) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_dhp_sha256_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpi_sha256) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpi_sha256_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpb_sha256) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpb_sha256_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpt_sha256) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpt_sha256_stat) \ + CDSUNIT_DECLARE_FeldmanHashSet_sha256_RCU_signal + +#define CDSUNIT_TEST_FeldmanHashSet_sha256 \ + CPPUNIT_TEST(FeldmanHashSet_hp_sha256) \ + CPPUNIT_TEST(FeldmanHashSet_hp_sha256_stat) \ + CPPUNIT_TEST(FeldmanHashSet_dhp_sha256) \ + CPPUNIT_TEST(FeldmanHashSet_dhp_sha256_stat) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpi_sha256) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpi_sha256_stat) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpb_sha256) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpb_sha256_stat) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpt_sha256) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpt_sha256_stat) \ + CDSUNIT_TEST_FeldmanHashSet_sha256_RCU_signal // CityHash -only for 64bit -#undef CDSUNIT_DECLARE_MultiLevelHashSet_city -#undef CDSUNIT_DECLARE_MultiLevelHashSet_city_RCU_signal -#undef CDSUNIT_TEST_MultiLevelHashSet_city -#undef CDSUNIT_TEST_MultiLevelHashSet_city_RCU_signal +#undef CDSUNIT_DECLARE_FeldmanHashSet_city +#undef CDSUNIT_DECLARE_FeldmanHashSet_city_RCU_signal +#undef CDSUNIT_TEST_FeldmanHashSet_city +#undef CDSUNIT_TEST_FeldmanHashSet_city_RCU_signal #if CDS_BUILD_BITS == 64 #ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED -# define CDSUNIT_DECLARE_MultiLevelHashSet_city_RCU_signal \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_shb_city64) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_shb_city64_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_sht_city64) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_sht_city64_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_shb_city128) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_shb_city128_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_sht_city128) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_sht_city128_stat) \ - -# define CDSUNIT_TEST_MultiLevelHashSet_city_RCU_signal \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_shb_city64) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_shb_city64_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_sht_city64) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_sht_city64_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_shb_city128) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_shb_city128_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_sht_city128) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_sht_city128_stat) \ +# define CDSUNIT_DECLARE_FeldmanHashSet_city_RCU_signal \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_shb_city64) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_shb_city64_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_sht_city64) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_sht_city64_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_shb_city128) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_shb_city128_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_sht_city128) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_sht_city128_stat) \ + +# define CDSUNIT_TEST_FeldmanHashSet_city_RCU_signal \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_shb_city64) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_shb_city64_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_sht_city64) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_sht_city64_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_shb_city128) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_shb_city128_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_sht_city128) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_sht_city128_stat) \ #else -# define CDSUNIT_DECLARE_MultiLevelHashSet_city_RCU_signal -# define CDSUNIT_TEST_MultiLevelHashSet_city_RCU_signal +# define CDSUNIT_DECLARE_FeldmanHashSet_city_RCU_signal +# define CDSUNIT_TEST_FeldmanHashSet_city_RCU_signal #endif -#define CDSUNIT_DECLARE_MultiLevelHashSet_city \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_hp_city64) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_hp_city64_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_dhp_city64) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_dhp_city64_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpi_city64) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpi_city64_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpb_city64) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpb_city64_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpt_city64) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpt_city64_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_hp_city128) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_hp_city128_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_dhp_city128) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_dhp_city128_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpi_city128) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpi_city128_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpb_city128) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpb_city128_stat) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpt_city128) \ - TEST_CASE(tag_MultiLevelHashSet, MultiLevelHashSet_rcu_gpt_city128_stat) \ - CDSUNIT_DECLARE_MultiLevelHashSet_city_RCU_signal - -#define CDSUNIT_TEST_MultiLevelHashSet_city \ - CPPUNIT_TEST(MultiLevelHashSet_hp_city64) \ - CPPUNIT_TEST(MultiLevelHashSet_hp_city64_stat) \ - CPPUNIT_TEST(MultiLevelHashSet_dhp_city64) \ - CPPUNIT_TEST(MultiLevelHashSet_dhp_city64_stat) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpi_city64) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpi_city64_stat) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpb_city64) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpb_city64_stat) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpt_city64) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpt_city64_stat) \ - CPPUNIT_TEST(MultiLevelHashSet_hp_city128) \ - CPPUNIT_TEST(MultiLevelHashSet_hp_city128_stat) \ - CPPUNIT_TEST(MultiLevelHashSet_dhp_city128) \ - CPPUNIT_TEST(MultiLevelHashSet_dhp_city128_stat) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpi_city128) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpi_city128_stat) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpb_city128) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpb_city128_stat) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpt_city128) \ - CPPUNIT_TEST(MultiLevelHashSet_rcu_gpt_city128_stat) \ - CDSUNIT_TEST_MultiLevelHashSet_city_RCU_signal +#define CDSUNIT_DECLARE_FeldmanHashSet_city \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_hp_city64) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_hp_city64_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_dhp_city64) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_dhp_city64_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpi_city64) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpi_city64_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpb_city64) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpb_city64_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpt_city64) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpt_city64_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_hp_city128) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_hp_city128_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_dhp_city128) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_dhp_city128_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpi_city128) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpi_city128_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpb_city128) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpb_city128_stat) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpt_city128) \ + TEST_CASE(tag_FeldmanHashSet, FeldmanHashSet_rcu_gpt_city128_stat) \ + CDSUNIT_DECLARE_FeldmanHashSet_city_RCU_signal + +#define CDSUNIT_TEST_FeldmanHashSet_city \ + CPPUNIT_TEST(FeldmanHashSet_hp_city64) \ + CPPUNIT_TEST(FeldmanHashSet_hp_city64_stat) \ + CPPUNIT_TEST(FeldmanHashSet_dhp_city64) \ + CPPUNIT_TEST(FeldmanHashSet_dhp_city64_stat) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpi_city64) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpi_city64_stat) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpb_city64) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpb_city64_stat) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpt_city64) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpt_city64_stat) \ + CPPUNIT_TEST(FeldmanHashSet_hp_city128) \ + CPPUNIT_TEST(FeldmanHashSet_hp_city128_stat) \ + CPPUNIT_TEST(FeldmanHashSet_dhp_city128) \ + CPPUNIT_TEST(FeldmanHashSet_dhp_city128_stat) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpi_city128) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpi_city128_stat) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpb_city128) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpb_city128_stat) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpt_city128) \ + CPPUNIT_TEST(FeldmanHashSet_rcu_gpt_city128_stat) \ + CDSUNIT_TEST_FeldmanHashSet_city_RCU_signal #else -# define CDSUNIT_DECLARE_MultiLevelHashSet_city -# define CDSUNIT_DECLARE_MultiLevelHashSet_city_RCU_signal -# define CDSUNIT_TEST_MultiLevelHashSet_city -# define CDSUNIT_TEST_MultiLevelHashSet_city_RCU_signal +# define CDSUNIT_DECLARE_FeldmanHashSet_city +# define CDSUNIT_DECLARE_FeldmanHashSet_city_RCU_signal +# define CDSUNIT_TEST_FeldmanHashSet_city +# define CDSUNIT_TEST_FeldmanHashSet_city_RCU_signal #endif // CDS_BUILD_BITS == 64 // All -#define CDSUNIT_DECLARE_MultiLevelHashSet \ - CDSUNIT_DECLARE_MultiLevelHashSet_fixed \ - CDSUNIT_DECLARE_MultiLevelHashSet_stdhash \ - CDSUNIT_DECLARE_MultiLevelHashSet_md5 \ - CDSUNIT_DECLARE_MultiLevelHashSet_sha256 \ - CDSUNIT_DECLARE_MultiLevelHashSet_city - -#define CDSUNIT_TEST_MultiLevelHashSet \ - CDSUNIT_TEST_MultiLevelHashSet_fixed \ - CDSUNIT_TEST_MultiLevelHashSet_stdhash \ - CDSUNIT_TEST_MultiLevelHashSet_md5 \ - CDSUNIT_TEST_MultiLevelHashSet_sha256 \ - CDSUNIT_TEST_MultiLevelHashSet_city +#define CDSUNIT_DECLARE_FeldmanHashSet \ + CDSUNIT_DECLARE_FeldmanHashSet_fixed \ + CDSUNIT_DECLARE_FeldmanHashSet_stdhash \ + CDSUNIT_DECLARE_FeldmanHashSet_md5 \ + CDSUNIT_DECLARE_FeldmanHashSet_sha256 \ + CDSUNIT_DECLARE_FeldmanHashSet_city + +#define CDSUNIT_TEST_FeldmanHashSet \ + CDSUNIT_TEST_FeldmanHashSet_fixed \ + CDSUNIT_TEST_FeldmanHashSet_stdhash \ + CDSUNIT_TEST_FeldmanHashSet_md5 \ + CDSUNIT_TEST_FeldmanHashSet_sha256 \ + CDSUNIT_TEST_FeldmanHashSet_city diff --git a/tests/unit/set2/set_delodd.cpp b/tests/unit/set2/set_delodd.cpp index db240612..f2b89d86 100644 --- a/tests/unit/set2/set_delodd.cpp +++ b/tests/unit/set2/set_delodd.cpp @@ -18,8 +18,8 @@ namespace set2 { c_nCuckooProbesetSize = cfg.getSizeT("CuckooProbesetSize", c_nCuckooProbesetSize ); c_nCuckooProbesetThreshold = cfg.getSizeT("CuckooProbesetThreshold", c_nCuckooProbesetThreshold ); - c_nMultiLevelSet_HeadBits = cfg.getSizeT("MultiLevelMapHeadBits", c_nMultiLevelSet_HeadBits); - c_nMultiLevelSet_ArrayBits = cfg.getSizeT("MultiLevelMapArrayBits", c_nMultiLevelSet_ArrayBits); + c_nFeldmanSet_HeadBits = cfg.getSizeT("FeldmanMapHeadBits", c_nFeldmanSet_HeadBits); + c_nFeldmanSet_ArrayBits = cfg.getSizeT("FeldmanMapArrayBits", c_nFeldmanSet_ArrayBits); if ( c_nInsThreadCount == 0 ) c_nInsThreadCount = std::thread::hardware_concurrency(); diff --git a/tests/unit/set2/set_delodd.h b/tests/unit/set2/set_delodd.h index 2edf537a..b9d7a87a 100644 --- a/tests/unit/set2/set_delodd.h +++ b/tests/unit/set2/set_delodd.h @@ -128,8 +128,8 @@ namespace set2 { size_t c_nCuckooProbesetSize = 16; // CuckooSet probeset size (only for list-based probeset) size_t c_nCuckooProbesetThreshold = 0; // CUckooSet probeset threshold (0 - use default) - size_t c_nMultiLevelSet_HeadBits = 10; - size_t c_nMultiLevelSet_ArrayBits = 4; + size_t c_nFeldmanSet_HeadBits = 10; + size_t c_nFeldmanSet_ArrayBits = 4; size_t c_nLoadFactor = 2; std::vector m_arrData; @@ -795,16 +795,16 @@ namespace set2 { CDSUNIT_DECLARE_SkipListSet CDSUNIT_DECLARE_EllenBinTreeSet CDSUNIT_DECLARE_CuckooSet - CDSUNIT_DECLARE_MultiLevelHashSet_fixed - CDSUNIT_DECLARE_MultiLevelHashSet_city + CDSUNIT_DECLARE_FeldmanHashSet_fixed + CDSUNIT_DECLARE_FeldmanHashSet_city CPPUNIT_TEST_SUITE_(Set_DelOdd, "Map_DelOdd") CDSUNIT_TEST_MichaelSet CDSUNIT_TEST_SplitList CDSUNIT_TEST_SkipListSet CDSUNIT_TEST_EllenBinTreeSet - CDSUNIT_TEST_MultiLevelHashSet_fixed - CDSUNIT_TEST_MultiLevelHashSet_city + CDSUNIT_TEST_FeldmanHashSet_fixed + CDSUNIT_TEST_FeldmanHashSet_city CDSUNIT_TEST_CuckooSet CPPUNIT_TEST_SUITE_END(); }; diff --git a/tests/unit/set2/set_delodd_feldmanhashset.cpp b/tests/unit/set2/set_delodd_feldmanhashset.cpp new file mode 100644 index 00000000..36e21bd4 --- /dev/null +++ b/tests/unit/set2/set_delodd_feldmanhashset.cpp @@ -0,0 +1,13 @@ +//$$CDS-header$$ + +#include "set2/set_delodd.h" +#include "set2/set_type_feldman_hashset.h" + +#undef TEST_CASE +#define TEST_CASE(TAG, X) void Set_DelOdd::X() { run_test_extract::X>(); } +#include "set2/set_defs.h" + +namespace set2 { + CDSUNIT_DECLARE_FeldmanHashSet_fixed + CDSUNIT_DECLARE_FeldmanHashSet_city +} // namespace set2 diff --git a/tests/unit/set2/set_delodd_multilevelhashset.cpp b/tests/unit/set2/set_delodd_multilevelhashset.cpp deleted file mode 100644 index bef43b67..00000000 --- a/tests/unit/set2/set_delodd_multilevelhashset.cpp +++ /dev/null @@ -1,13 +0,0 @@ -//$$CDS-header$$ - -#include "set2/set_delodd.h" -#include "set2/set_type_multilevel_hashset.h" - -#undef TEST_CASE -#define TEST_CASE(TAG, X) void Set_DelOdd::X() { run_test_extract::X>(); } -#include "set2/set_defs.h" - -namespace set2 { - CDSUNIT_DECLARE_MultiLevelHashSet_fixed - CDSUNIT_DECLARE_MultiLevelHashSet_city -} // namespace set2 diff --git a/tests/unit/set2/set_insdel_func.cpp b/tests/unit/set2/set_insdel_func.cpp index 02773f1e..ee25b908 100644 --- a/tests/unit/set2/set_insdel_func.cpp +++ b/tests/unit/set2/set_insdel_func.cpp @@ -19,8 +19,8 @@ namespace set2 { c_nCuckooProbesetSize = cfg.getSizeT("CuckooProbesetSize", c_nCuckooProbesetSize ); c_nCuckooProbesetThreshold = cfg.getSizeT("CuckooProbesetThreshold", c_nCuckooProbesetThreshold ); - c_nMultiLevelSet_HeadBits = cfg.getSizeT("MultiLevelMapHeadBits", c_nMultiLevelSet_HeadBits); - c_nMultiLevelSet_ArrayBits = cfg.getSizeT("MultiLevelMapArrayBits", c_nMultiLevelSet_ArrayBits); + c_nFeldmanSet_HeadBits = cfg.getSizeT("FeldmanMapHeadBits", c_nFeldmanSet_HeadBits); + c_nFeldmanSet_ArrayBits = cfg.getSizeT("FeldmanMapArrayBits", c_nFeldmanSet_ArrayBits); if ( c_nInsertThreadCount == 0 ) c_nInsertThreadCount = std::thread::hardware_concurrency(); diff --git a/tests/unit/set2/set_insdel_func.h b/tests/unit/set2/set_insdel_func.h index 7aba9bbe..e0479788 100644 --- a/tests/unit/set2/set_insdel_func.h +++ b/tests/unit/set2/set_insdel_func.h @@ -27,8 +27,8 @@ namespace set2 { size_t c_nCuckooProbesetSize = 16; // CuckooSet probeset size (only for list-based probeset) size_t c_nCuckooProbesetThreshold = 0; // CUckooSet probeset threshold (0 - use default) - size_t c_nMultiLevelSet_HeadBits = 10; - size_t c_nMultiLevelSet_ArrayBits = 4; + size_t c_nFeldmanSet_HeadBits = 10; + size_t c_nFeldmanSet_ArrayBits = 4; size_t c_nLoadFactor = 2; @@ -549,15 +549,15 @@ namespace set2 { CDSUNIT_DECLARE_RefinableSet CDSUNIT_DECLARE_CuckooSet CDSUNIT_DECLARE_EllenBinTreeSet - CDSUNIT_DECLARE_MultiLevelHashSet_fixed - CDSUNIT_DECLARE_MultiLevelHashSet_city + CDSUNIT_DECLARE_FeldmanHashSet_fixed + CDSUNIT_DECLARE_FeldmanHashSet_city CPPUNIT_TEST_SUITE_(Set_InsDel_func, "Map_InsDel_func") CDSUNIT_TEST_MichaelSet CDSUNIT_TEST_SplitList CDSUNIT_TEST_SkipListSet - CDSUNIT_TEST_MultiLevelHashSet_fixed - CDSUNIT_TEST_MultiLevelHashSet_city + CDSUNIT_TEST_FeldmanHashSet_fixed + CDSUNIT_TEST_FeldmanHashSet_city CDSUNIT_TEST_EllenBinTreeSet CDSUNIT_TEST_StripedSet CDSUNIT_TEST_RefinableSet diff --git a/tests/unit/set2/set_insdel_func_feldmanhashset.cpp b/tests/unit/set2/set_insdel_func_feldmanhashset.cpp new file mode 100644 index 00000000..9610a4ce --- /dev/null +++ b/tests/unit/set2/set_insdel_func_feldmanhashset.cpp @@ -0,0 +1,13 @@ +//$$CDS-header$$ + +#include "set2/set_insdel_func.h" +#include "set2/set_type_feldman_hashset.h" + +#undef TEST_CASE +#define TEST_CASE(TAG, X) void Set_InsDel_func::X() { run_test::X>(); } +#include "set2/set_defs.h" + +namespace set2 { + CDSUNIT_DECLARE_FeldmanHashSet_fixed + CDSUNIT_DECLARE_FeldmanHashSet_city +} // namespace set2 diff --git a/tests/unit/set2/set_insdel_func_multilevelhashset.cpp b/tests/unit/set2/set_insdel_func_multilevelhashset.cpp deleted file mode 100644 index f7e818b3..00000000 --- a/tests/unit/set2/set_insdel_func_multilevelhashset.cpp +++ /dev/null @@ -1,13 +0,0 @@ -//$$CDS-header$$ - -#include "set2/set_insdel_func.h" -#include "set2/set_type_multilevel_hashset.h" - -#undef TEST_CASE -#define TEST_CASE(TAG, X) void Set_InsDel_func::X() { run_test::X>(); } -#include "set2/set_defs.h" - -namespace set2 { - CDSUNIT_DECLARE_MultiLevelHashSet_fixed - CDSUNIT_DECLARE_MultiLevelHashSet_city -} // namespace set2 diff --git a/tests/unit/set2/set_insdel_string.cpp b/tests/unit/set2/set_insdel_string.cpp index f20d5205..ac11081b 100644 --- a/tests/unit/set2/set_insdel_string.cpp +++ b/tests/unit/set2/set_insdel_string.cpp @@ -18,8 +18,8 @@ namespace set2 { c_nCuckooProbesetSize = cfg.getSizeT("CuckooProbesetSize", c_nCuckooProbesetSize ); c_nCuckooProbesetThreshold = cfg.getSizeT("CuckooProbesetThreshold", c_nCuckooProbesetThreshold ); - c_nMultiLevelSet_HeadBits = cfg.getSizeT("MultiLevelMapHeadBits", c_nMultiLevelSet_HeadBits); - c_nMultiLevelSet_ArrayBits = cfg.getSizeT("MultiLevelMapArrayBits", c_nMultiLevelSet_ArrayBits); + c_nFeldmanSet_HeadBits = cfg.getSizeT("FeldmanMapHeadBits", c_nFeldmanSet_HeadBits); + c_nFeldmanSet_ArrayBits = cfg.getSizeT("FeldmanMapArrayBits", c_nFeldmanSet_ArrayBits); if ( c_nInsertThreadCount == 0 ) c_nInsertThreadCount = std::thread::hardware_concurrency(); diff --git a/tests/unit/set2/set_insdel_string.h b/tests/unit/set2/set_insdel_string.h index b76d698f..6ab2f420 100644 --- a/tests/unit/set2/set_insdel_string.h +++ b/tests/unit/set2/set_insdel_string.h @@ -23,8 +23,8 @@ namespace set2 { size_t c_nCuckooProbesetSize = 16; // CuckooSet probeset size (only for list-based probeset) size_t c_nCuckooProbesetThreshold = 0; // CUckooSet probeset threshold (0 - use default) - size_t c_nMultiLevelSet_HeadBits = 10; - size_t c_nMultiLevelSet_ArrayBits = 4; + size_t c_nFeldmanSet_HeadBits = 10; + size_t c_nFeldmanSet_ArrayBits = 4; size_t c_nLoadFactor = 2; @@ -517,20 +517,20 @@ namespace set2 { CDSUNIT_DECLARE_CuckooSet CDSUNIT_DECLARE_SkipListSet CDSUNIT_DECLARE_EllenBinTreeSet - CDSUNIT_DECLARE_MultiLevelHashSet_stdhash - CDSUNIT_DECLARE_MultiLevelHashSet_md5 - CDSUNIT_DECLARE_MultiLevelHashSet_sha256 - CDSUNIT_DECLARE_MultiLevelHashSet_city + CDSUNIT_DECLARE_FeldmanHashSet_stdhash + CDSUNIT_DECLARE_FeldmanHashSet_md5 + CDSUNIT_DECLARE_FeldmanHashSet_sha256 + CDSUNIT_DECLARE_FeldmanHashSet_city CDSUNIT_DECLARE_StdSet CPPUNIT_TEST_SUITE_(Set_InsDel_string, "Map_InsDel_func") CDSUNIT_TEST_MichaelSet CDSUNIT_TEST_SplitList CDSUNIT_TEST_SkipListSet - CDSUNIT_TEST_MultiLevelHashSet_stdhash - CDSUNIT_TEST_MultiLevelHashSet_md5 - CDSUNIT_TEST_MultiLevelHashSet_sha256 - CDSUNIT_TEST_MultiLevelHashSet_city + CDSUNIT_TEST_FeldmanHashSet_stdhash + CDSUNIT_TEST_FeldmanHashSet_md5 + CDSUNIT_TEST_FeldmanHashSet_sha256 + CDSUNIT_TEST_FeldmanHashSet_city CDSUNIT_TEST_EllenBinTreeSet CDSUNIT_TEST_StripedSet CDSUNIT_TEST_RefinableSet diff --git a/tests/unit/set2/set_insdel_string_feldmanhashset.cpp b/tests/unit/set2/set_insdel_string_feldmanhashset.cpp new file mode 100644 index 00000000..e9becc45 --- /dev/null +++ b/tests/unit/set2/set_insdel_string_feldmanhashset.cpp @@ -0,0 +1,15 @@ +//$$CDS-header$$ + +#include "set2/set_insdel_string.h" +#include "set2/set_type_feldman_hashset.h" + +#undef TEST_CASE +#define TEST_CASE(TAG, X) void Set_InsDel_string::X() { run_test_extract::X>(); } +#include "set2/set_defs.h" + +namespace set2 { + CDSUNIT_DECLARE_FeldmanHashSet_stdhash + CDSUNIT_DECLARE_FeldmanHashSet_md5 + CDSUNIT_DECLARE_FeldmanHashSet_sha256 + CDSUNIT_DECLARE_FeldmanHashSet_city +} // namespace set2 diff --git a/tests/unit/set2/set_insdel_string_multilevelhashset.cpp b/tests/unit/set2/set_insdel_string_multilevelhashset.cpp deleted file mode 100644 index 5050b872..00000000 --- a/tests/unit/set2/set_insdel_string_multilevelhashset.cpp +++ /dev/null @@ -1,15 +0,0 @@ -//$$CDS-header$$ - -#include "set2/set_insdel_string.h" -#include "set2/set_type_multilevel_hashset.h" - -#undef TEST_CASE -#define TEST_CASE(TAG, X) void Set_InsDel_string::X() { run_test_extract::X>(); } -#include "set2/set_defs.h" - -namespace set2 { - CDSUNIT_DECLARE_MultiLevelHashSet_stdhash - CDSUNIT_DECLARE_MultiLevelHashSet_md5 - CDSUNIT_DECLARE_MultiLevelHashSet_sha256 - CDSUNIT_DECLARE_MultiLevelHashSet_city -} // namespace set2 diff --git a/tests/unit/set2/set_insdelfind.cpp b/tests/unit/set2/set_insdelfind.cpp index df6a559a..ed71911b 100644 --- a/tests/unit/set2/set_insdelfind.cpp +++ b/tests/unit/set2/set_insdelfind.cpp @@ -19,8 +19,8 @@ namespace set2 { c_nCuckooProbesetSize = cfg.getSizeT("CuckooProbesetSize", c_nCuckooProbesetSize ); c_nCuckooProbesetThreshold = cfg.getSizeT("CuckooProbesetThreshold", c_nCuckooProbesetThreshold ); - c_nMultiLevelSet_HeadBits = cfg.getSizeT("MultiLevelMapHeadBits", c_nMultiLevelSet_HeadBits); - c_nMultiLevelSet_ArrayBits = cfg.getSizeT("MultiLevelMapArrayBits", c_nMultiLevelSet_ArrayBits); + c_nFeldmanSet_HeadBits = cfg.getSizeT("FeldmanMapHeadBits", c_nFeldmanSet_HeadBits); + c_nFeldmanSet_ArrayBits = cfg.getSizeT("FeldmanMapArrayBits", c_nFeldmanSet_ArrayBits); if ( c_nThreadCount == 0 ) c_nThreadCount = std::thread::hardware_concurrency(); diff --git a/tests/unit/set2/set_insdelfind.h b/tests/unit/set2/set_insdelfind.h index 89be492f..6f0b276b 100644 --- a/tests/unit/set2/set_insdelfind.h +++ b/tests/unit/set2/set_insdelfind.h @@ -22,8 +22,8 @@ namespace set2 { size_t c_nCuckooProbesetSize = 16; // CuckooSet probeset size (only for list-based probeset) size_t c_nCuckooProbesetThreshold = 0; // CUckooSet probeset threshold (0 - use default) - size_t c_nMultiLevelSet_HeadBits = 10; - size_t c_nMultiLevelSet_ArrayBits = 4; + size_t c_nFeldmanSet_HeadBits = 10; + size_t c_nFeldmanSet_ArrayBits = 4; size_t c_nLoadFactor = 2; @@ -226,14 +226,14 @@ namespace set2 { CDSUNIT_DECLARE_CuckooSet CDSUNIT_DECLARE_SkipListSet CDSUNIT_DECLARE_EllenBinTreeSet - CDSUNIT_DECLARE_MultiLevelHashSet + CDSUNIT_DECLARE_FeldmanHashSet CDSUNIT_DECLARE_StdSet CPPUNIT_TEST_SUITE_(Set_InsDelFind, "Map_InsDelFind") CDSUNIT_TEST_MichaelSet CDSUNIT_TEST_SplitList CDSUNIT_TEST_SkipListSet - CDSUNIT_TEST_MultiLevelHashSet + CDSUNIT_TEST_FeldmanHashSet CDSUNIT_TEST_EllenBinTreeSet CDSUNIT_TEST_StripedSet CDSUNIT_TEST_RefinableSet diff --git a/tests/unit/set2/set_insdelfind_feldmanhashset.cpp b/tests/unit/set2/set_insdelfind_feldmanhashset.cpp new file mode 100644 index 00000000..b1befc0a --- /dev/null +++ b/tests/unit/set2/set_insdelfind_feldmanhashset.cpp @@ -0,0 +1,12 @@ +//$$CDS-header$$ + +#include "set2/set_insdelfind.h" +#include "set2/set_type_feldman_hashset.h" + +#undef TEST_CASE +#define TEST_CASE(TAG, X) void Set_InsDelFind::X() { run_test::X>(); } +#include "set2/set_defs.h" + +namespace set2 { + CDSUNIT_DECLARE_FeldmanHashSet +} // namespace set2 diff --git a/tests/unit/set2/set_insdelfind_multilevelhashset.cpp b/tests/unit/set2/set_insdelfind_multilevelhashset.cpp deleted file mode 100644 index 0a374821..00000000 --- a/tests/unit/set2/set_insdelfind_multilevelhashset.cpp +++ /dev/null @@ -1,12 +0,0 @@ -//$$CDS-header$$ - -#include "set2/set_insdelfind.h" -#include "set2/set_type_multilevel_hashset.h" - -#undef TEST_CASE -#define TEST_CASE(TAG, X) void Set_InsDelFind::X() { run_test::X>(); } -#include "set2/set_defs.h" - -namespace set2 { - CDSUNIT_DECLARE_MultiLevelHashSet -} // namespace set2 diff --git a/tests/unit/set2/set_type_feldman_hashset.h b/tests/unit/set2/set_type_feldman_hashset.h new file mode 100644 index 00000000..68066db0 --- /dev/null +++ b/tests/unit/set2/set_type_feldman_hashset.h @@ -0,0 +1,341 @@ +//$$CDS-header$$ + +#ifndef CDSUNIT_SET_TYPE_MICHAEL_H +#define CDSUNIT_SET_TYPE_MICHAEL_H + +#include "set2/set_type.h" + +#include +#include +#include + +#include "print_feldman_hashset_stat.h" +#include "hashing/hash_func.h" + +namespace set2 { + + template + class FeldmanHashSet : public cc::FeldmanHashSet< GC, T, Traits > + { + typedef cc::FeldmanHashSet< GC, T, Traits > base_class; + + template + struct get_extracted_ptr + { + typedef typename base_class::guarded_ptr extracted_ptr; + }; + + template + struct get_extracted_ptr> + { + typedef typename base_class::exempt_ptr extracted_ptr; + }; + + public: + typedef typename T::hasher hasher ; + typedef typename get_extracted_ptr::extracted_ptr extracted_ptr; + + template + FeldmanHashSet( Config const& cfg ) + : base_class( cfg.c_nFeldmanSet_HeadBits, cfg.c_nFeldmanSet_ArrayBits ) + {} + + template + bool erase( Q const& key ) + { + return base_class::erase( hasher()( key )); + } + + template + bool erase( Q const& key, Func f ) + { + return base_class::erase( hasher()( key ), f ); + } + + template + extracted_ptr extract(Q const& key) + { + return base_class::extract( hasher()(key) ); + } + + template + bool contains( Q const& key ) + { + return base_class::contains( hasher()(key) ); + } + + // for testing + static CDS_CONSTEXPR bool const c_bExtractSupported = true; + static CDS_CONSTEXPR bool const c_bLoadFactorDepended = false; + static CDS_CONSTEXPR bool const c_bEraseExactKey = true; + }; + + struct tag_FeldmanHashSet; + + template + struct set_type< tag_FeldmanHashSet, Key, Val >: public set_type_base< Key, Val > + { + typedef set_type_base< Key, Val > base_class; + typedef typename base_class::compare compare; + typedef typename base_class::less less; + typedef typename base_class::hash hash; + typedef typename base_class::key_type key_type; + typedef typename base_class::value_type value_type; + + template + struct hash_type + { + typedef Hasher hasher; + typedef typename hasher::hash_type type; + }; + + template + struct hash_type> + { + typedef std::hash hasher; + typedef size_t type; + }; + + template + struct key_val: base_class::key_val + { + typedef typename base_class::key_val base; + typedef Hasher hasher; + typedef typename hash_type::type hash_type; + + hash_type hash; + + /*explicit*/ key_val( key_type const& k ): base(k), hash( hasher()( k )) {} + key_val( key_type const& k, value_type const& v ): base(k, v), hash( hasher()( k )) {} + + template + /*explicit*/ key_val( K const& k ): base(k), hash( hasher()( k )) {} + + template + key_val( K const& k, T const& v ): base(k, v), hash( hasher()( k )) {} + }; + + struct default_traits : public cc::feldman_hashset::traits + { + struct hash_accessor { + template + typename key_val::hash_type const& operator()( key_val const& kv ) + { + return kv.hash; + } + }; + }; + + typedef FeldmanHashSet< cds::gc::HP, key_val>, default_traits > FeldmanHashSet_hp_stdhash; + typedef FeldmanHashSet< cds::gc::DHP, key_val>, default_traits > FeldmanHashSet_dhp_stdhash; + typedef FeldmanHashSet< rcu_gpi, key_val>, default_traits > FeldmanHashSet_rcu_gpi_stdhash; + typedef FeldmanHashSet< rcu_gpb, key_val>, default_traits > FeldmanHashSet_rcu_gpb_stdhash; + typedef FeldmanHashSet< rcu_gpt, key_val>, default_traits > FeldmanHashSet_rcu_gpt_stdhash; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashSet< rcu_shb, key_val>, default_traits > FeldmanHashSet_rcu_shb_stdhash; + typedef FeldmanHashSet< rcu_sht, key_val>, default_traits > FeldmanHashSet_rcu_sht_stdhash; +#endif + + struct traits_FeldmanHashSet_stat: public cc::feldman_hashset::make_traits< + co::type_traits< default_traits >, + co::stat< cc::feldman_hashset::stat<>> + >::type + {}; + + typedef FeldmanHashSet< cds::gc::HP, key_val>, traits_FeldmanHashSet_stat > FeldmanHashSet_hp_stdhash_stat; + typedef FeldmanHashSet< cds::gc::DHP, key_val>, traits_FeldmanHashSet_stat > FeldmanHashSet_dhp_stdhash_stat; + typedef FeldmanHashSet< rcu_gpi, key_val>, traits_FeldmanHashSet_stat > FeldmanHashSet_rcu_gpi_stdhash_stat; + typedef FeldmanHashSet< rcu_gpb, key_val>, traits_FeldmanHashSet_stat > FeldmanHashSet_rcu_gpb_stdhash_stat; + typedef FeldmanHashSet< rcu_gpt, key_val>, traits_FeldmanHashSet_stat > FeldmanHashSet_rcu_gpt_stdhash_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashSet< rcu_shb, key_val>, traits_FeldmanHashSet_stat > FeldmanHashSet_rcu_shb_stdhash_stat; + typedef FeldmanHashSet< rcu_sht, key_val>, traits_FeldmanHashSet_stat > FeldmanHashSet_rcu_sht_stdhash_stat; +#endif + + // SHA256 + typedef FeldmanHashSet< cds::gc::HP, key_val<::hashing::sha256>, default_traits > FeldmanHashSet_hp_sha256; + typedef FeldmanHashSet< cds::gc::DHP, key_val<::hashing::sha256>, default_traits > FeldmanHashSet_dhp_sha256; + typedef FeldmanHashSet< rcu_gpi, key_val<::hashing::sha256>, default_traits > FeldmanHashSet_rcu_gpi_sha256; + typedef FeldmanHashSet< rcu_gpb, key_val<::hashing::sha256>, default_traits > FeldmanHashSet_rcu_gpb_sha256; + typedef FeldmanHashSet< rcu_gpt, key_val<::hashing::sha256>, default_traits > FeldmanHashSet_rcu_gpt_sha256; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashSet< rcu_shb, key_val<::hashing::sha256>, default_traits > FeldmanHashSet_rcu_shb_sha256; + typedef FeldmanHashSet< rcu_sht, key_val<::hashing::sha256>, default_traits > FeldmanHashSet_rcu_sht_sha256; +#endif + + struct traits_FeldmanHashSet_sha256_stat : public default_traits + { + typedef cc::feldman_hashset::stat<> stat; + }; + typedef FeldmanHashSet< cds::gc::HP, key_val<::hashing::sha256>, traits_FeldmanHashSet_sha256_stat > FeldmanHashSet_hp_sha256_stat; + typedef FeldmanHashSet< cds::gc::DHP, key_val<::hashing::sha256>, traits_FeldmanHashSet_sha256_stat > FeldmanHashSet_dhp_sha256_stat; + typedef FeldmanHashSet< rcu_gpi, key_val<::hashing::sha256>, traits_FeldmanHashSet_sha256_stat > FeldmanHashSet_rcu_gpi_sha256_stat; + typedef FeldmanHashSet< rcu_gpb, key_val<::hashing::sha256>, traits_FeldmanHashSet_sha256_stat > FeldmanHashSet_rcu_gpb_sha256_stat; + typedef FeldmanHashSet< rcu_gpt, key_val<::hashing::sha256>, traits_FeldmanHashSet_sha256_stat > FeldmanHashSet_rcu_gpt_sha256_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashSet< rcu_shb, key_val<::hashing::sha256>, traits_FeldmanHashSet_sha256_stat > FeldmanHashSet_rcu_shb_sha256_stat; + typedef FeldmanHashSet< rcu_sht, key_val<::hashing::sha256>, traits_FeldmanHashSet_sha256_stat > FeldmanHashSet_rcu_sht_sha256_stat; +#endif + + //MD5 + typedef FeldmanHashSet< cds::gc::HP, key_val<::hashing::md5>, default_traits > FeldmanHashSet_hp_md5; + typedef FeldmanHashSet< cds::gc::DHP, key_val<::hashing::md5>, default_traits > FeldmanHashSet_dhp_md5; + typedef FeldmanHashSet< rcu_gpi, key_val<::hashing::md5>, default_traits > FeldmanHashSet_rcu_gpi_md5; + typedef FeldmanHashSet< rcu_gpb, key_val<::hashing::md5>, default_traits > FeldmanHashSet_rcu_gpb_md5; + typedef FeldmanHashSet< rcu_gpt, key_val<::hashing::md5>, default_traits > FeldmanHashSet_rcu_gpt_md5; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashSet< rcu_shb, key_val<::hashing::md5>, default_traits > FeldmanHashSet_rcu_shb_md5; + typedef FeldmanHashSet< rcu_sht, key_val<::hashing::md5>, default_traits > FeldmanHashSet_rcu_sht_md5; +#endif + + struct traits_FeldmanHashSet_md5_stat : public default_traits + { + typedef cc::feldman_hashset::stat<> stat; + }; + typedef FeldmanHashSet< cds::gc::HP, key_val<::hashing::md5>, traits_FeldmanHashSet_md5_stat > FeldmanHashSet_hp_md5_stat; + typedef FeldmanHashSet< cds::gc::DHP, key_val<::hashing::md5>, traits_FeldmanHashSet_md5_stat > FeldmanHashSet_dhp_md5_stat; + typedef FeldmanHashSet< rcu_gpi, key_val<::hashing::md5>, traits_FeldmanHashSet_md5_stat > FeldmanHashSet_rcu_gpi_md5_stat; + typedef FeldmanHashSet< rcu_gpb, key_val<::hashing::md5>, traits_FeldmanHashSet_md5_stat > FeldmanHashSet_rcu_gpb_md5_stat; + typedef FeldmanHashSet< rcu_gpt, key_val<::hashing::md5>, traits_FeldmanHashSet_md5_stat > FeldmanHashSet_rcu_gpt_md5_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashSet< rcu_shb, key_val<::hashing::md5>, traits_FeldmanHashSet_md5_stat > FeldmanHashSet_rcu_shb_md5_stat; + typedef FeldmanHashSet< rcu_sht, key_val<::hashing::md5>, traits_FeldmanHashSet_md5_stat > FeldmanHashSet_rcu_sht_md5_stat; +#endif + + // CityHash +#if CDS_BUILD_BITS == 64 + struct traits_FeldmanHashSet_city64 : public default_traits + { + typedef ::hashing::city64::less less; + }; + typedef FeldmanHashSet< cds::gc::HP, key_val<::hashing::city64>, traits_FeldmanHashSet_city64 > FeldmanHashSet_hp_city64; + typedef FeldmanHashSet< cds::gc::DHP, key_val<::hashing::city64>, traits_FeldmanHashSet_city64 > FeldmanHashSet_dhp_city64; + typedef FeldmanHashSet< rcu_gpi, key_val<::hashing::city64>, traits_FeldmanHashSet_city64 > FeldmanHashSet_rcu_gpi_city64; + typedef FeldmanHashSet< rcu_gpb, key_val<::hashing::city64>, traits_FeldmanHashSet_city64 > FeldmanHashSet_rcu_gpb_city64; + typedef FeldmanHashSet< rcu_gpt, key_val<::hashing::city64>, traits_FeldmanHashSet_city64 > FeldmanHashSet_rcu_gpt_city64; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashSet< rcu_shb, key_val<::hashing::city64>, traits_FeldmanHashSet_city64 > FeldmanHashSet_rcu_shb_city64; + typedef FeldmanHashSet< rcu_sht, key_val<::hashing::city64>, traits_FeldmanHashSet_city64 > FeldmanHashSet_rcu_sht_city64; +#endif + + struct traits_FeldmanHashSet_city64_stat : public traits_FeldmanHashSet_city64 + { + typedef cc::feldman_hashset::stat<> stat; + }; + typedef FeldmanHashSet< cds::gc::HP, key_val<::hashing::city64>, traits_FeldmanHashSet_city64_stat > FeldmanHashSet_hp_city64_stat; + typedef FeldmanHashSet< cds::gc::DHP, key_val<::hashing::city64>, traits_FeldmanHashSet_city64_stat > FeldmanHashSet_dhp_city64_stat; + typedef FeldmanHashSet< rcu_gpi, key_val<::hashing::city64>, traits_FeldmanHashSet_city64_stat > FeldmanHashSet_rcu_gpi_city64_stat; + typedef FeldmanHashSet< rcu_gpb, key_val<::hashing::city64>, traits_FeldmanHashSet_city64_stat > FeldmanHashSet_rcu_gpb_city64_stat; + typedef FeldmanHashSet< rcu_gpt, key_val<::hashing::city64>, traits_FeldmanHashSet_city64_stat > FeldmanHashSet_rcu_gpt_city64_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashSet< rcu_shb, key_val<::hashing::city64>, traits_FeldmanHashSet_city64_stat > FeldmanHashSet_rcu_shb_city64_stat; + typedef FeldmanHashSet< rcu_sht, key_val<::hashing::city64>, traits_FeldmanHashSet_city64_stat > FeldmanHashSet_rcu_sht_city64_stat; +#endif + + struct traits_FeldmanHashSet_city128 : public default_traits + { + typedef ::hashing::city128::less less; + }; + typedef FeldmanHashSet< cds::gc::HP, key_val<::hashing::city128>, traits_FeldmanHashSet_city128 > FeldmanHashSet_hp_city128; + typedef FeldmanHashSet< cds::gc::DHP, key_val<::hashing::city128>, traits_FeldmanHashSet_city128 > FeldmanHashSet_dhp_city128; + typedef FeldmanHashSet< rcu_gpi, key_val<::hashing::city128>, traits_FeldmanHashSet_city128 > FeldmanHashSet_rcu_gpi_city128; + typedef FeldmanHashSet< rcu_gpb, key_val<::hashing::city128>, traits_FeldmanHashSet_city128 > FeldmanHashSet_rcu_gpb_city128; + typedef FeldmanHashSet< rcu_gpt, key_val<::hashing::city128>, traits_FeldmanHashSet_city128 > FeldmanHashSet_rcu_gpt_city128; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashSet< rcu_shb, key_val<::hashing::city128>, traits_FeldmanHashSet_city128 > FeldmanHashSet_rcu_shb_city128; + typedef FeldmanHashSet< rcu_sht, key_val<::hashing::city128>, traits_FeldmanHashSet_city128 > FeldmanHashSet_rcu_sht_city128; +#endif + + struct traits_FeldmanHashSet_city128_stat : public traits_FeldmanHashSet_city128 + { + typedef cc::feldman_hashset::stat<> stat; + }; + typedef FeldmanHashSet< cds::gc::HP, key_val<::hashing::city128>, traits_FeldmanHashSet_city128_stat > FeldmanHashSet_hp_city128_stat; + typedef FeldmanHashSet< cds::gc::DHP, key_val<::hashing::city128>, traits_FeldmanHashSet_city128_stat > FeldmanHashSet_dhp_city128_stat; + typedef FeldmanHashSet< rcu_gpi, key_val<::hashing::city128>, traits_FeldmanHashSet_city128_stat > FeldmanHashSet_rcu_gpi_city128_stat; + typedef FeldmanHashSet< rcu_gpb, key_val<::hashing::city128>, traits_FeldmanHashSet_city128_stat > FeldmanHashSet_rcu_gpb_city128_stat; + typedef FeldmanHashSet< rcu_gpt, key_val<::hashing::city128>, traits_FeldmanHashSet_city128_stat > FeldmanHashSet_rcu_gpt_city128_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashSet< rcu_shb, key_val<::hashing::city128>, traits_FeldmanHashSet_city128_stat > FeldmanHashSet_rcu_shb_city128_stat; + typedef FeldmanHashSet< rcu_sht, key_val<::hashing::city128>, traits_FeldmanHashSet_city128_stat > FeldmanHashSet_rcu_sht_city128_stat; +#endif + +#endif // #if CDS_BUILD_BITS == 64 + + + // for fixed-sized key + // No hash function is necessary + + struct fixed_sized_key + { + typedef typename set_type_base< Key, Val >::key_type key_type; + struct key_val : public set_type_base< Key, Val >::key_val + { + typedef typename set_type_base< Key, Val >::key_val base_class; + + /*explicit*/ key_val(key_type const& k) : base_class(k) {} + key_val(key_type const& k, value_type const& v) : base_class(k, v) {} + + template + /*explicit*/ key_val(K const& k) : base_class(k) {} + + template + key_val(K const& k, T const& v) : base_class(k, v) {} + + // mock hasher + struct hasher { + template + key_type operator()( Q const& k ) const + { + return key_type( k ); + } + }; + }; + + struct traits : public cc::feldman_hashset::traits + { + struct hash_accessor { + key_type operator()(key_val const& kv) + { + return kv.key; + } + }; + }; + + struct traits_stat : public traits + { + typedef cc::feldman_hashset::stat<> stat; + }; + }; + + typedef FeldmanHashSet< cds::gc::HP, typename fixed_sized_key::key_val, typename fixed_sized_key::traits > FeldmanHashSet_hp_fixed; + typedef FeldmanHashSet< cds::gc::DHP, typename fixed_sized_key::key_val, typename fixed_sized_key::traits > FeldmanHashSet_dhp_fixed; + typedef FeldmanHashSet< rcu_gpi, typename fixed_sized_key::key_val, typename fixed_sized_key::traits > FeldmanHashSet_rcu_gpi_fixed; + typedef FeldmanHashSet< rcu_gpb, typename fixed_sized_key::key_val, typename fixed_sized_key::traits > FeldmanHashSet_rcu_gpb_fixed; + typedef FeldmanHashSet< rcu_gpt, typename fixed_sized_key::key_val, typename fixed_sized_key::traits > FeldmanHashSet_rcu_gpt_fixed; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashSet< rcu_shb, typename fixed_sized_key::key_val, typename fixed_sized_key::traits > FeldmanHashSet_rcu_shb_fixed; + typedef FeldmanHashSet< rcu_sht, typename fixed_sized_key::key_val, typename fixed_sized_key::traits > FeldmanHashSet_rcu_sht_fixed; +#endif + + typedef FeldmanHashSet< cds::gc::HP, typename fixed_sized_key::key_val, typename fixed_sized_key::traits_stat > FeldmanHashSet_hp_fixed_stat; + typedef FeldmanHashSet< cds::gc::DHP, typename fixed_sized_key::key_val, typename fixed_sized_key::traits_stat > FeldmanHashSet_dhp_fixed_stat; + typedef FeldmanHashSet< rcu_gpi, typename fixed_sized_key::key_val, typename fixed_sized_key::traits_stat > FeldmanHashSet_rcu_gpi_fixed_stat; + typedef FeldmanHashSet< rcu_gpb, typename fixed_sized_key::key_val, typename fixed_sized_key::traits_stat > FeldmanHashSet_rcu_gpb_fixed_stat; + typedef FeldmanHashSet< rcu_gpt, typename fixed_sized_key::key_val, typename fixed_sized_key::traits_stat > FeldmanHashSet_rcu_gpt_fixed_stat; +#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED + typedef FeldmanHashSet< rcu_shb, typename fixed_sized_key::key_val, typename fixed_sized_key::traits_stat > FeldmanHashSet_rcu_shb_fixed_stat; + typedef FeldmanHashSet< rcu_sht, typename fixed_sized_key::key_val, typename fixed_sized_key::traits_stat > FeldmanHashSet_rcu_sht_fixed_stat; +#endif + + }; + + template + static inline void print_stat( FeldmanHashSet< GC, T, Traits > const& s ) + { + CPPUNIT_MSG( s.statistics() ); + } + +} // namespace set2 + +#endif // #ifndef CDSUNIT_SET_TYPE_MICHAEL_H diff --git a/tests/unit/set2/set_type_multilevel_hashset.h b/tests/unit/set2/set_type_multilevel_hashset.h deleted file mode 100644 index 26e38c1d..00000000 --- a/tests/unit/set2/set_type_multilevel_hashset.h +++ /dev/null @@ -1,341 +0,0 @@ -//$$CDS-header$$ - -#ifndef CDSUNIT_SET_TYPE_MICHAEL_H -#define CDSUNIT_SET_TYPE_MICHAEL_H - -#include "set2/set_type.h" - -#include -#include -#include - -#include "print_multilevel_hashset_stat.h" -#include "hashing/hash_func.h" - -namespace set2 { - - template - class MultiLevelHashSet : public cc::MultiLevelHashSet< GC, T, Traits > - { - typedef cc::MultiLevelHashSet< GC, T, Traits > base_class; - - template - struct get_extracted_ptr - { - typedef typename base_class::guarded_ptr extracted_ptr; - }; - - template - struct get_extracted_ptr> - { - typedef typename base_class::exempt_ptr extracted_ptr; - }; - - public: - typedef typename T::hasher hasher ; - typedef typename get_extracted_ptr::extracted_ptr extracted_ptr; - - template - MultiLevelHashSet( Config const& cfg ) - : base_class( cfg.c_nMultiLevelSet_HeadBits, cfg.c_nMultiLevelSet_ArrayBits ) - {} - - template - bool erase( Q const& key ) - { - return base_class::erase( hasher()( key )); - } - - template - bool erase( Q const& key, Func f ) - { - return base_class::erase( hasher()( key ), f ); - } - - template - extracted_ptr extract(Q const& key) - { - return base_class::extract( hasher()(key) ); - } - - template - bool contains( Q const& key ) - { - return base_class::contains( hasher()(key) ); - } - - // for testing - static CDS_CONSTEXPR bool const c_bExtractSupported = true; - static CDS_CONSTEXPR bool const c_bLoadFactorDepended = false; - static CDS_CONSTEXPR bool const c_bEraseExactKey = true; - }; - - struct tag_MultiLevelHashSet; - - template - struct set_type< tag_MultiLevelHashSet, Key, Val >: public set_type_base< Key, Val > - { - typedef set_type_base< Key, Val > base_class; - typedef typename base_class::compare compare; - typedef typename base_class::less less; - typedef typename base_class::hash hash; - typedef typename base_class::key_type key_type; - typedef typename base_class::value_type value_type; - - template - struct hash_type - { - typedef Hasher hasher; - typedef typename hasher::hash_type type; - }; - - template - struct hash_type> - { - typedef std::hash hasher; - typedef size_t type; - }; - - template - struct key_val: base_class::key_val - { - typedef typename base_class::key_val base; - typedef Hasher hasher; - typedef typename hash_type::type hash_type; - - hash_type hash; - - /*explicit*/ key_val( key_type const& k ): base(k), hash( hasher()( k )) {} - key_val( key_type const& k, value_type const& v ): base(k, v), hash( hasher()( k )) {} - - template - /*explicit*/ key_val( K const& k ): base(k), hash( hasher()( k )) {} - - template - key_val( K const& k, T const& v ): base(k, v), hash( hasher()( k )) {} - }; - - struct default_traits : public cc::multilevel_hashset::traits - { - struct hash_accessor { - template - typename key_val::hash_type const& operator()( key_val const& kv ) - { - return kv.hash; - } - }; - }; - - typedef MultiLevelHashSet< cds::gc::HP, key_val>, default_traits > MultiLevelHashSet_hp_stdhash; - typedef MultiLevelHashSet< cds::gc::DHP, key_val>, default_traits > MultiLevelHashSet_dhp_stdhash; - typedef MultiLevelHashSet< rcu_gpi, key_val>, default_traits > MultiLevelHashSet_rcu_gpi_stdhash; - typedef MultiLevelHashSet< rcu_gpb, key_val>, default_traits > MultiLevelHashSet_rcu_gpb_stdhash; - typedef MultiLevelHashSet< rcu_gpt, key_val>, default_traits > MultiLevelHashSet_rcu_gpt_stdhash; -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef MultiLevelHashSet< rcu_shb, key_val>, default_traits > MultiLevelHashSet_rcu_shb_stdhash; - typedef MultiLevelHashSet< rcu_sht, key_val>, default_traits > MultiLevelHashSet_rcu_sht_stdhash; -#endif - - struct traits_MultiLevelHashSet_stat: public cc::multilevel_hashset::make_traits< - co::type_traits< default_traits >, - co::stat< cc::multilevel_hashset::stat<>> - >::type - {}; - - typedef MultiLevelHashSet< cds::gc::HP, key_val>, traits_MultiLevelHashSet_stat > MultiLevelHashSet_hp_stdhash_stat; - typedef MultiLevelHashSet< cds::gc::DHP, key_val>, traits_MultiLevelHashSet_stat > MultiLevelHashSet_dhp_stdhash_stat; - typedef MultiLevelHashSet< rcu_gpi, key_val>, traits_MultiLevelHashSet_stat > MultiLevelHashSet_rcu_gpi_stdhash_stat; - typedef MultiLevelHashSet< rcu_gpb, key_val>, traits_MultiLevelHashSet_stat > MultiLevelHashSet_rcu_gpb_stdhash_stat; - typedef MultiLevelHashSet< rcu_gpt, key_val>, traits_MultiLevelHashSet_stat > MultiLevelHashSet_rcu_gpt_stdhash_stat; -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef MultiLevelHashSet< rcu_shb, key_val>, traits_MultiLevelHashSet_stat > MultiLevelHashSet_rcu_shb_stdhash_stat; - typedef MultiLevelHashSet< rcu_sht, key_val>, traits_MultiLevelHashSet_stat > MultiLevelHashSet_rcu_sht_stdhash_stat; -#endif - - // SHA256 - typedef MultiLevelHashSet< cds::gc::HP, key_val<::hashing::sha256>, default_traits > MultiLevelHashSet_hp_sha256; - typedef MultiLevelHashSet< cds::gc::DHP, key_val<::hashing::sha256>, default_traits > MultiLevelHashSet_dhp_sha256; - typedef MultiLevelHashSet< rcu_gpi, key_val<::hashing::sha256>, default_traits > MultiLevelHashSet_rcu_gpi_sha256; - typedef MultiLevelHashSet< rcu_gpb, key_val<::hashing::sha256>, default_traits > MultiLevelHashSet_rcu_gpb_sha256; - typedef MultiLevelHashSet< rcu_gpt, key_val<::hashing::sha256>, default_traits > MultiLevelHashSet_rcu_gpt_sha256; -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef MultiLevelHashSet< rcu_shb, key_val<::hashing::sha256>, default_traits > MultiLevelHashSet_rcu_shb_sha256; - typedef MultiLevelHashSet< rcu_sht, key_val<::hashing::sha256>, default_traits > MultiLevelHashSet_rcu_sht_sha256; -#endif - - struct traits_MultiLevelHashSet_sha256_stat : public default_traits - { - typedef cc::multilevel_hashset::stat<> stat; - }; - typedef MultiLevelHashSet< cds::gc::HP, key_val<::hashing::sha256>, traits_MultiLevelHashSet_sha256_stat > MultiLevelHashSet_hp_sha256_stat; - typedef MultiLevelHashSet< cds::gc::DHP, key_val<::hashing::sha256>, traits_MultiLevelHashSet_sha256_stat > MultiLevelHashSet_dhp_sha256_stat; - typedef MultiLevelHashSet< rcu_gpi, key_val<::hashing::sha256>, traits_MultiLevelHashSet_sha256_stat > MultiLevelHashSet_rcu_gpi_sha256_stat; - typedef MultiLevelHashSet< rcu_gpb, key_val<::hashing::sha256>, traits_MultiLevelHashSet_sha256_stat > MultiLevelHashSet_rcu_gpb_sha256_stat; - typedef MultiLevelHashSet< rcu_gpt, key_val<::hashing::sha256>, traits_MultiLevelHashSet_sha256_stat > MultiLevelHashSet_rcu_gpt_sha256_stat; -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef MultiLevelHashSet< rcu_shb, key_val<::hashing::sha256>, traits_MultiLevelHashSet_sha256_stat > MultiLevelHashSet_rcu_shb_sha256_stat; - typedef MultiLevelHashSet< rcu_sht, key_val<::hashing::sha256>, traits_MultiLevelHashSet_sha256_stat > MultiLevelHashSet_rcu_sht_sha256_stat; -#endif - - //MD5 - typedef MultiLevelHashSet< cds::gc::HP, key_val<::hashing::md5>, default_traits > MultiLevelHashSet_hp_md5; - typedef MultiLevelHashSet< cds::gc::DHP, key_val<::hashing::md5>, default_traits > MultiLevelHashSet_dhp_md5; - typedef MultiLevelHashSet< rcu_gpi, key_val<::hashing::md5>, default_traits > MultiLevelHashSet_rcu_gpi_md5; - typedef MultiLevelHashSet< rcu_gpb, key_val<::hashing::md5>, default_traits > MultiLevelHashSet_rcu_gpb_md5; - typedef MultiLevelHashSet< rcu_gpt, key_val<::hashing::md5>, default_traits > MultiLevelHashSet_rcu_gpt_md5; -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef MultiLevelHashSet< rcu_shb, key_val<::hashing::md5>, default_traits > MultiLevelHashSet_rcu_shb_md5; - typedef MultiLevelHashSet< rcu_sht, key_val<::hashing::md5>, default_traits > MultiLevelHashSet_rcu_sht_md5; -#endif - - struct traits_MultiLevelHashSet_md5_stat : public default_traits - { - typedef cc::multilevel_hashset::stat<> stat; - }; - typedef MultiLevelHashSet< cds::gc::HP, key_val<::hashing::md5>, traits_MultiLevelHashSet_md5_stat > MultiLevelHashSet_hp_md5_stat; - typedef MultiLevelHashSet< cds::gc::DHP, key_val<::hashing::md5>, traits_MultiLevelHashSet_md5_stat > MultiLevelHashSet_dhp_md5_stat; - typedef MultiLevelHashSet< rcu_gpi, key_val<::hashing::md5>, traits_MultiLevelHashSet_md5_stat > MultiLevelHashSet_rcu_gpi_md5_stat; - typedef MultiLevelHashSet< rcu_gpb, key_val<::hashing::md5>, traits_MultiLevelHashSet_md5_stat > MultiLevelHashSet_rcu_gpb_md5_stat; - typedef MultiLevelHashSet< rcu_gpt, key_val<::hashing::md5>, traits_MultiLevelHashSet_md5_stat > MultiLevelHashSet_rcu_gpt_md5_stat; -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef MultiLevelHashSet< rcu_shb, key_val<::hashing::md5>, traits_MultiLevelHashSet_md5_stat > MultiLevelHashSet_rcu_shb_md5_stat; - typedef MultiLevelHashSet< rcu_sht, key_val<::hashing::md5>, traits_MultiLevelHashSet_md5_stat > MultiLevelHashSet_rcu_sht_md5_stat; -#endif - - // CityHash -#if CDS_BUILD_BITS == 64 - struct traits_MultiLevelHashSet_city64 : public default_traits - { - typedef ::hashing::city64::less less; - }; - typedef MultiLevelHashSet< cds::gc::HP, key_val<::hashing::city64>, traits_MultiLevelHashSet_city64 > MultiLevelHashSet_hp_city64; - typedef MultiLevelHashSet< cds::gc::DHP, key_val<::hashing::city64>, traits_MultiLevelHashSet_city64 > MultiLevelHashSet_dhp_city64; - typedef MultiLevelHashSet< rcu_gpi, key_val<::hashing::city64>, traits_MultiLevelHashSet_city64 > MultiLevelHashSet_rcu_gpi_city64; - typedef MultiLevelHashSet< rcu_gpb, key_val<::hashing::city64>, traits_MultiLevelHashSet_city64 > MultiLevelHashSet_rcu_gpb_city64; - typedef MultiLevelHashSet< rcu_gpt, key_val<::hashing::city64>, traits_MultiLevelHashSet_city64 > MultiLevelHashSet_rcu_gpt_city64; -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef MultiLevelHashSet< rcu_shb, key_val<::hashing::city64>, traits_MultiLevelHashSet_city64 > MultiLevelHashSet_rcu_shb_city64; - typedef MultiLevelHashSet< rcu_sht, key_val<::hashing::city64>, traits_MultiLevelHashSet_city64 > MultiLevelHashSet_rcu_sht_city64; -#endif - - struct traits_MultiLevelHashSet_city64_stat : public traits_MultiLevelHashSet_city64 - { - typedef cc::multilevel_hashset::stat<> stat; - }; - typedef MultiLevelHashSet< cds::gc::HP, key_val<::hashing::city64>, traits_MultiLevelHashSet_city64_stat > MultiLevelHashSet_hp_city64_stat; - typedef MultiLevelHashSet< cds::gc::DHP, key_val<::hashing::city64>, traits_MultiLevelHashSet_city64_stat > MultiLevelHashSet_dhp_city64_stat; - typedef MultiLevelHashSet< rcu_gpi, key_val<::hashing::city64>, traits_MultiLevelHashSet_city64_stat > MultiLevelHashSet_rcu_gpi_city64_stat; - typedef MultiLevelHashSet< rcu_gpb, key_val<::hashing::city64>, traits_MultiLevelHashSet_city64_stat > MultiLevelHashSet_rcu_gpb_city64_stat; - typedef MultiLevelHashSet< rcu_gpt, key_val<::hashing::city64>, traits_MultiLevelHashSet_city64_stat > MultiLevelHashSet_rcu_gpt_city64_stat; -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef MultiLevelHashSet< rcu_shb, key_val<::hashing::city64>, traits_MultiLevelHashSet_city64_stat > MultiLevelHashSet_rcu_shb_city64_stat; - typedef MultiLevelHashSet< rcu_sht, key_val<::hashing::city64>, traits_MultiLevelHashSet_city64_stat > MultiLevelHashSet_rcu_sht_city64_stat; -#endif - - struct traits_MultiLevelHashSet_city128 : public default_traits - { - typedef ::hashing::city128::less less; - }; - typedef MultiLevelHashSet< cds::gc::HP, key_val<::hashing::city128>, traits_MultiLevelHashSet_city128 > MultiLevelHashSet_hp_city128; - typedef MultiLevelHashSet< cds::gc::DHP, key_val<::hashing::city128>, traits_MultiLevelHashSet_city128 > MultiLevelHashSet_dhp_city128; - typedef MultiLevelHashSet< rcu_gpi, key_val<::hashing::city128>, traits_MultiLevelHashSet_city128 > MultiLevelHashSet_rcu_gpi_city128; - typedef MultiLevelHashSet< rcu_gpb, key_val<::hashing::city128>, traits_MultiLevelHashSet_city128 > MultiLevelHashSet_rcu_gpb_city128; - typedef MultiLevelHashSet< rcu_gpt, key_val<::hashing::city128>, traits_MultiLevelHashSet_city128 > MultiLevelHashSet_rcu_gpt_city128; -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef MultiLevelHashSet< rcu_shb, key_val<::hashing::city128>, traits_MultiLevelHashSet_city128 > MultiLevelHashSet_rcu_shb_city128; - typedef MultiLevelHashSet< rcu_sht, key_val<::hashing::city128>, traits_MultiLevelHashSet_city128 > MultiLevelHashSet_rcu_sht_city128; -#endif - - struct traits_MultiLevelHashSet_city128_stat : public traits_MultiLevelHashSet_city128 - { - typedef cc::multilevel_hashset::stat<> stat; - }; - typedef MultiLevelHashSet< cds::gc::HP, key_val<::hashing::city128>, traits_MultiLevelHashSet_city128_stat > MultiLevelHashSet_hp_city128_stat; - typedef MultiLevelHashSet< cds::gc::DHP, key_val<::hashing::city128>, traits_MultiLevelHashSet_city128_stat > MultiLevelHashSet_dhp_city128_stat; - typedef MultiLevelHashSet< rcu_gpi, key_val<::hashing::city128>, traits_MultiLevelHashSet_city128_stat > MultiLevelHashSet_rcu_gpi_city128_stat; - typedef MultiLevelHashSet< rcu_gpb, key_val<::hashing::city128>, traits_MultiLevelHashSet_city128_stat > MultiLevelHashSet_rcu_gpb_city128_stat; - typedef MultiLevelHashSet< rcu_gpt, key_val<::hashing::city128>, traits_MultiLevelHashSet_city128_stat > MultiLevelHashSet_rcu_gpt_city128_stat; -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef MultiLevelHashSet< rcu_shb, key_val<::hashing::city128>, traits_MultiLevelHashSet_city128_stat > MultiLevelHashSet_rcu_shb_city128_stat; - typedef MultiLevelHashSet< rcu_sht, key_val<::hashing::city128>, traits_MultiLevelHashSet_city128_stat > MultiLevelHashSet_rcu_sht_city128_stat; -#endif - -#endif // #if CDS_BUILD_BITS == 64 - - - // for fixed-sized key - // No hash function is necessary - - struct fixed_sized_key - { - typedef typename set_type_base< Key, Val >::key_type key_type; - struct key_val : public set_type_base< Key, Val >::key_val - { - typedef typename set_type_base< Key, Val >::key_val base_class; - - /*explicit*/ key_val(key_type const& k) : base_class(k) {} - key_val(key_type const& k, value_type const& v) : base_class(k, v) {} - - template - /*explicit*/ key_val(K const& k) : base_class(k) {} - - template - key_val(K const& k, T const& v) : base_class(k, v) {} - - // mock hasher - struct hasher { - template - key_type operator()( Q const& k ) const - { - return key_type( k ); - } - }; - }; - - struct traits : public cc::multilevel_hashset::traits - { - struct hash_accessor { - key_type operator()(key_val const& kv) - { - return kv.key; - } - }; - }; - - struct traits_stat : public traits - { - typedef cc::multilevel_hashset::stat<> stat; - }; - }; - - typedef MultiLevelHashSet< cds::gc::HP, typename fixed_sized_key::key_val, typename fixed_sized_key::traits > MultiLevelHashSet_hp_fixed; - typedef MultiLevelHashSet< cds::gc::DHP, typename fixed_sized_key::key_val, typename fixed_sized_key::traits > MultiLevelHashSet_dhp_fixed; - typedef MultiLevelHashSet< rcu_gpi, typename fixed_sized_key::key_val, typename fixed_sized_key::traits > MultiLevelHashSet_rcu_gpi_fixed; - typedef MultiLevelHashSet< rcu_gpb, typename fixed_sized_key::key_val, typename fixed_sized_key::traits > MultiLevelHashSet_rcu_gpb_fixed; - typedef MultiLevelHashSet< rcu_gpt, typename fixed_sized_key::key_val, typename fixed_sized_key::traits > MultiLevelHashSet_rcu_gpt_fixed; -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef MultiLevelHashSet< rcu_shb, typename fixed_sized_key::key_val, typename fixed_sized_key::traits > MultiLevelHashSet_rcu_shb_fixed; - typedef MultiLevelHashSet< rcu_sht, typename fixed_sized_key::key_val, typename fixed_sized_key::traits > MultiLevelHashSet_rcu_sht_fixed; -#endif - - typedef MultiLevelHashSet< cds::gc::HP, typename fixed_sized_key::key_val, typename fixed_sized_key::traits_stat > MultiLevelHashSet_hp_fixed_stat; - typedef MultiLevelHashSet< cds::gc::DHP, typename fixed_sized_key::key_val, typename fixed_sized_key::traits_stat > MultiLevelHashSet_dhp_fixed_stat; - typedef MultiLevelHashSet< rcu_gpi, typename fixed_sized_key::key_val, typename fixed_sized_key::traits_stat > MultiLevelHashSet_rcu_gpi_fixed_stat; - typedef MultiLevelHashSet< rcu_gpb, typename fixed_sized_key::key_val, typename fixed_sized_key::traits_stat > MultiLevelHashSet_rcu_gpb_fixed_stat; - typedef MultiLevelHashSet< rcu_gpt, typename fixed_sized_key::key_val, typename fixed_sized_key::traits_stat > MultiLevelHashSet_rcu_gpt_fixed_stat; -#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED - typedef MultiLevelHashSet< rcu_shb, typename fixed_sized_key::key_val, typename fixed_sized_key::traits_stat > MultiLevelHashSet_rcu_shb_fixed_stat; - typedef MultiLevelHashSet< rcu_sht, typename fixed_sized_key::key_val, typename fixed_sized_key::traits_stat > MultiLevelHashSet_rcu_sht_fixed_stat; -#endif - - }; - - template - static inline void print_stat( MultiLevelHashSet< GC, T, Traits > const& s ) - { - CPPUNIT_MSG( s.statistics() ); - } - -} // namespace set2 - -#endif // #ifndef CDSUNIT_SET_TYPE_MICHAEL_H