--- /dev/null
+//$$CDS-header$$
+
+#ifndef CDSLIB_CONTAINER_DETAILS_FELDMAN_HASHMAP_BASE_H
+#define CDSLIB_CONTAINER_DETAILS_FELDMAN_HASHMAP_BASE_H
+
+#include <cds/intrusive/details/feldman_hashset_base.h>
+#include <cds/container/details/base.h>
+#include <cds/opt/hash.h>
+
+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 <typename EventCounter = cds::atomicity::event_counter>
+ 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 <typename T>
+ 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, <a href="https://en.wikipedia.org/wiki/Secure_Hash_Algorithm">SHA1, SHA2</a>,
+ <a href="https://en.wikipedia.org/wiki/MurmurHash">MurmurHash</a>,
+ <a href="https://en.wikipedia.org/wiki/CityHash">CityHash</a>
+ or its successor <a href="https://code.google.com/p/farmhash/">FarmHash</a>.
+
+ 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 <tt> std::less<std::string> </tt> will be used by default
+ struct url_map_traits: public cds::container::multilevl_hashmap::traits
+ {
+ typedef std::hash<std::string> 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 <typename... Options>
+ 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 <typename Key, typename Value, typename Hash>
+ 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<key_type>()))
+ >::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 <typename Q>
+ node_type(hasher& h, Q const& key)
+ : m_Value(std::move(std::make_pair(key, mapped_type())))
+ , m_hash(h(m_Value.first))
+ {}
+
+ template <typename Q, typename U >
+ 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 <typename Q, typename... Args>
+ node_type(hasher& h, Q&& key, Args&&... args)
+ : m_Value(std::move(std::make_pair(std::forward<Q>(key), std::move(mapped_type(std::forward<Args>(args)...)))))
+ , m_hash(h(m_Value.first))
+ {}
+ };
+
+ struct hash_accessor
+ {
+ hash_type const& operator()(node_type const& node) const
+ {
+ return node.m_hash;
+ }
+ };
+ };
+
+ template <typename Key, typename Value>
+ struct hash_selector<Key, Value, opt::none>
+ {
+ 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 <typename Q>
+ node_type(hasher /*h*/, Q const& key)
+ : m_Value(std::move(std::make_pair(key, mapped_type())))
+ {}
+
+ template <typename Q, typename U >
+ node_type(hasher /*h*/, Q const& key, U const& val)
+ : m_Value(std::move(std::make_pair(key, mapped_type(val))))
+ {}
+
+ template <typename Q, typename... Args>
+ node_type(hasher /*h*/, Q&& key, Args&&... args)
+ : m_Value(std::move(std::make_pair(std::forward<Q>(key), std::move(mapped_type(std::forward<Args>(args)...)))))
+ {}
+ };
+
+ struct hash_accessor
+ {
+ hash_type const& operator()(node_type const& node) const
+ {
+ return node.m_Value.first;
+ }
+ };
+ };
+
+ template <typename GC, typename Key, typename T, typename Traits>
+ 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
--- /dev/null
+//$$CDS-header$$
+
+#ifndef CDSLIB_CONTAINER_DETAILS_FELDMAN_HASHSET_BASE_H
+#define CDSLIB_CONTAINER_DETAILS_FELDMAN_HASHSET_BASE_H
+
+#include <cds/intrusive/details/feldman_hashset_base.h>
+#include <cds/container/details/base.h>
+
+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 <typename Accessor>
+ using hash_accessor = cds::intrusive::feldman_hashset::hash_accessor< Accessor >;
+
+ /// \p FeldmanHashSet internal statistics, see cds::intrusive::feldman_hashset::stat
+ template <typename EventCounter = cds::atomicity::event_counter>
+ 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 <typename T>
+ 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 <typename... Options>
+ 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 <typename GC, typename T, typename Traits>
+ 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
+++ /dev/null
-//$$CDS-header$$
-
-#ifndef CDSLIB_CONTAINER_DETAILS_MULTILEVEL_HASHMAP_BASE_H
-#define CDSLIB_CONTAINER_DETAILS_MULTILEVEL_HASHMAP_BASE_H
-
-#include <cds/intrusive/details/multilevel_hashset_base.h>
-#include <cds/container/details/base.h>
-#include <cds/opt/hash.h>
-
-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 <typename EventCounter = cds::atomicity::event_counter>
- 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 <typename T>
- 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, <a href="https://en.wikipedia.org/wiki/Secure_Hash_Algorithm">SHA1, SHA2</a>,
- <a href="https://en.wikipedia.org/wiki/MurmurHash">MurmurHash</a>,
- <a href="https://en.wikipedia.org/wiki/CityHash">CityHash</a>
- or its successor <a href="https://code.google.com/p/farmhash/">FarmHash</a>.
-
- 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 <tt> std::less<std::string> </tt> will be used by default
- struct url_map_traits: public cds::container::multilevl_hashmap::traits
- {
- typedef std::hash<std::string> 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 <typename... Options>
- 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 <typename Key, typename Value, typename Hash>
- 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<key_type>()))
- >::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 <typename Q>
- node_type(hasher& h, Q const& key)
- : m_Value(std::move(std::make_pair(key, mapped_type())))
- , m_hash(h(m_Value.first))
- {}
-
- template <typename Q, typename U >
- 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 <typename Q, typename... Args>
- node_type(hasher& h, Q&& key, Args&&... args)
- : m_Value(std::move(std::make_pair(std::forward<Q>(key), std::move(mapped_type(std::forward<Args>(args)...)))))
- , m_hash(h(m_Value.first))
- {}
- };
-
- struct hash_accessor
- {
- hash_type const& operator()(node_type const& node) const
- {
- return node.m_hash;
- }
- };
- };
-
- template <typename Key, typename Value>
- struct hash_selector<Key, Value, opt::none>
- {
- 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 <typename Q>
- node_type(hasher /*h*/, Q const& key)
- : m_Value(std::move(std::make_pair(key, mapped_type())))
- {}
-
- template <typename Q, typename U >
- node_type(hasher /*h*/, Q const& key, U const& val)
- : m_Value(std::move(std::make_pair(key, mapped_type(val))))
- {}
-
- template <typename Q, typename... Args>
- node_type(hasher /*h*/, Q&& key, Args&&... args)
- : m_Value(std::move(std::make_pair(std::forward<Q>(key), std::move(mapped_type(std::forward<Args>(args)...)))))
- {}
- };
-
- struct hash_accessor
- {
- hash_type const& operator()(node_type const& node) const
- {
- return node.m_Value.first;
- }
- };
- };
-
- template <typename GC, typename Key, typename T, typename Traits>
- 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
+++ /dev/null
-//$$CDS-header$$
-
-#ifndef CDSLIB_CONTAINER_DETAILS_MULTILEVEL_HASHSET_BASE_H
-#define CDSLIB_CONTAINER_DETAILS_MULTILEVEL_HASHSET_BASE_H
-
-#include <cds/intrusive/details/multilevel_hashset_base.h>
-#include <cds/container/details/base.h>
-
-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 <typename Accessor>
- using hash_accessor = cds::intrusive::multilevel_hashset::hash_accessor< Accessor >;
-
- /// \p MultiLevelHashSet internal statistics, see cds::intrusive::multilevel_hashset::stat
- template <typename EventCounter = cds::atomicity::event_counter>
- 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 <typename T>
- 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 <typename... Options>
- 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 <typename GC, typename T, typename Traits>
- 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
--- /dev/null
+//$$CDS-header$$
+
+#ifndef CDSLIB_CONTAINER_FELDMAN_HASHMAP_DHP_H
+#define CDSLIB_CONTAINER_FELDMAN_HASHMAP_DHP_H
+
+#include <cds/container/impl/feldman_hashmap.h>
+#include <cds/gc/dhp.h>
+
+#endif // #ifndef CDSLIB_CONTAINER_FELDMAN_HASHMAP_DHP_H
--- /dev/null
+//$$CDS-header$$
+
+#ifndef CDSLIB_CONTAINER_FELDMAN_HASHMAP_HP_H
+#define CDSLIB_CONTAINER_FELDMAN_HASHMAP_HP_H
+
+#include <cds/container/impl/feldman_hashmap.h>
+#include <cds/gc/hp.h>
+
+#endif // #ifndef CDSLIB_CONTAINER_FELDMAN_HASHMAP_HP_H
--- /dev/null
+//$$CDS-header$$
+
+#ifndef CDSLIB_CONTAINER_FELDMAN_HASHMAP_RCU_H
+#define CDSLIB_CONTAINER_FELDMAN_HASHMAP_RCU_H
+
+#include <cds/intrusive/feldman_hashset_rcu.h>
+#include <cds/container/details/feldman_hashmap_base.h>
+
+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 <a href="https://en.wikipedia.org/wiki/Secure_Hash_Algorithm">SHA1, SHA2</a>,
+ <a href="https://en.wikipedia.org/wiki/MurmurHash">MurmurHash</a>, <a href="https://en.wikipedia.org/wiki/CityHash">CityHash</a>
+ or its successor <a href="https://code.google.com/p/farmhash/">FarmHash</a> 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 <tt><cds/intrusive/feldman_hashset_rcu.h></tt> 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<Key const, T>, 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 <bool IsConst>
+ 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 IsConst2>
+ bool operator ==(bidirectional_iterator<IsConst2> const& rhs) const CDS_NOEXCEPT
+ {
+ return iterator_base::operator==( rhs );
+ }
+
+ template <bool IsConst2>
+ bool operator !=(bidirectional_iterator<IsConst2> 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 <bool IsConst>
+ 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 IsConst2>
+ bool operator ==(reverse_bidirectional_iterator<IsConst2> const& rhs) const
+ {
+ return iterator_base::operator==( rhs );
+ }
+
+ template <bool IsConst2>
+ bool operator !=(reverse_bidirectional_iterator<IsConst2> 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<false> iterator;
+ typedef bidirectional_iterator<true> const_iterator;
+ typedef reverse_bidirectional_iterator<false> reverse_iterator;
+ typedef reverse_bidirectional_iterator<true> const_reverse_iterator;
+#endif
+
+ protected:
+ //@cond
+ hasher m_Hasher;
+ //@endcond
+
+ public:
+ /// Creates empty map
+ /**
+ @param head_bits: 2<sup>head_bits</sup> specifies the size of head array, minimum is 4.
+ @param array_bits: 2<sup>array_bits</sup> 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 <typename K>
+ bool insert( K&& key )
+ {
+ scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward<K>(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 <typename K, typename V>
+ bool insert( K&& key, V&& val )
+ {
+ scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward<K>(key), std::forward<V>(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:
+ - <tt>item.first</tt> is a const reference to item's key that cannot be changed.
+ - <tt>item.second</tt> 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 <typename K, typename Func>
+ bool insert_with( K&& key, Func func )
+ {
+ scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward<K>(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 <tt>std::forward<Args>(args)...</tt>
+ /**
+ Returns \p true if inserting successful, \p false otherwise.
+
+ The function locks RCU internally.
+ */
+ template <typename K, typename... Args>
+ bool emplace( K&& key, Args&&... args )
+ {
+ scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward<K>(key), std::forward<Args>(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 <tt> std::pair<bool, bool> </tt> 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 <typename K, typename Func>
+ std::pair<bool, bool> update( K&& key, Func func, bool bInsert = true )
+ {
+ scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward<K>(key)));
+ std::pair<bool, bool> 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 <tt>hash( key_type( key ))</tt>
+
+ Return \p true if \p key is found and deleted, \p false otherwise.
+
+ RCU should not be locked. The function locks RCU internally.
+ */
+ template <typename K>
+ 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 <tt>hash( key_type( key ))</tt>,
+ 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 <typename K, typename Func>
+ 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 <tt>hash( key_type( key ))</tt> 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 <typename K>
+ 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 <tt>hash( key_type( key ))</tt>
+ and returns \p true if it is found, or \p false otherwise.
+ */
+ template <typename K>
+ 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 <tt>hash( key_type( key ))</tt>
+ 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 <typename K, typename Func>
+ 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 <typename K>
+ 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 <tt>==</tt> and <tt>!=</tt>.
+ 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 <tt> it1 == it2 </tt>
+ does not entail <tt> &(*it1) == &(*it2) </tt>: 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<iterator>();
+ }
+
+ /// Returns an const iterator to the beginning of the map
+ const_iterator begin() const
+ {
+ return base_class::template init_begin<const_iterator>();
+ }
+
+ /// Returns an const iterator to the beginning of the map
+ const_iterator cbegin()
+ {
+ return base_class::template init_begin<const_iterator>();
+ }
+
+ /// 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<iterator>();
+ }
+
+ /// 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<const_iterator>();
+ }
+
+ /// 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<const_iterator>();
+ }
+
+ /// Returns a reverse iterator to the first element of the reversed map
+ reverse_iterator rbegin()
+ {
+ return base_class::template init_rbegin<reverse_iterator>();
+ }
+
+ /// Returns a const reverse iterator to the first element of the reversed map
+ const_reverse_iterator rbegin() const
+ {
+ return base_class::template init_rbegin<const_reverse_iterator>();
+ }
+
+ /// Returns a const reverse iterator to the first element of the reversed map
+ const_reverse_iterator crbegin()
+ {
+ return base_class::template init_rbegin<const_reverse_iterator>();
+ }
+
+ /// 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<reverse_iterator>();
+ }
+
+ /// 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<const_reverse_iterator>();
+ }
+
+ /// 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<const_reverse_iterator>();
+ }
+ ///@}
+ };
+}} // namespace cds::container
+
+#endif // #ifndef CDSLIB_CONTAINER_FELDMAN_HASHMAP_RCU_H
--- /dev/null
+//$$CDS-header$$
+
+#ifndef CDSLIB_CONTAINER_FELDMAN_HASHSET_DHP_H
+#define CDSLIB_CONTAINER_FELDMAN_HASHSET_DHP_H
+
+#include <cds/container/impl/feldman_hashset.h>
+#include <cds/gc/dhp.h>
+
+#endif // #ifndef CDSLIB_CONTAINER_FELDMAN_HASHSET_DHP_H
--- /dev/null
+//$$CDS-header$$
+
+#ifndef CDSLIB_CONTAINER_FELDMAN_HASHSET_HP_H
+#define CDSLIB_CONTAINER_FELDMAN_HASHSET_HP_H
+
+#include <cds/container/impl/feldman_hashset.h>
+#include <cds/gc/hp.h>
+
+#endif // #ifndef CDSLIB_CONTAINER_FELDMAN_HASHSET_HP_H
--- /dev/null
+//$$CDS-header$$
+
+#ifndef CDSLIB_CONTAINER_FELDMAN_HASHSET_RCU_H
+#define CDSLIB_CONTAINER_FELDMAN_HASHSET_RCU_H
+
+#include <cds/intrusive/feldman_hashset_rcu.h>
+#include <cds/container/details/feldman_hashset_base.h>
+
+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 <a href="https://en.wikipedia.org/wiki/Secure_Hash_Algorithm">SHA1, SHA2</a>,
+ <a href="https://en.wikipedia.org/wiki/MurmurHash">MurmurHash</a>, <a href="https://en.wikipedia.org/wiki/CityHash">CityHash</a>
+ or its successor <a href="https://code.google.com/p/farmhash/">FarmHash</a> 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 <tt><cds/intrusive/feldman_hashset_rcu.h></tt> 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: 2<sup>head_bits</sup> specifies the size of head array, minimum is 4.
+ @param array_bits: 2<sup>array_bits</sup> 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 <typename Q>
+ 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 <typename Q, typename Func>
+ 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 <tt> std::pair<bool, bool> </tt> 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 <typename Q, typename Func>
+ std::pair<bool, bool> update( Q const& val, Func func, bool bInsert = true )
+ {
+ scoped_node_ptr sp( cxx_node_allocator().New( val ));
+ std::pair<bool, bool> 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 <tt>std::forward<Args>(args)...</tt>
+ /**
+ Returns \p true if inserting successful, \p false otherwise.
+ */
+ template <typename... Args>
+ bool emplace( Args&&... args )
+ {
+ scoped_node_ptr sp( cxx_node_allocator().New( std::forward<Args>(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 <typename Func>
+ 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 <typename Func>
+ 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 <tt>==</tt> and <tt>!=</tt>.
+ 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 <tt> it1 == it2 </tt>
+ does not entail <tt> &(*it1) == &(*it2) </tt>: 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
--- /dev/null
+//$$CDS-header$$
+
+#ifndef CDSLIB_CONTAINER_IMPL_FELDMAN_HASHMAP_H
+#define CDSLIB_CONTAINER_IMPL_FELDMAN_HASHMAP_H
+
+#include <cds/intrusive/impl/feldman_hashset.h>
+#include <cds/container/details/feldman_hashmap_base.h>
+#include <cds/container/details/guarded_ptr_cast.h>
+
+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 <b>perfect hashing</b>, 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; <b> the hash value is treated as a bit
+ string</b> 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 <a href="https://en.wikipedia.org/wiki/Secure_Hash_Algorithm">SHA1, SHA2</a>,
+ <a href="https://en.wikipedia.org/wiki/MurmurHash">MurmurHash</a>, <a href="https://en.wikipedia.org/wiki/CityHash">CityHash</a>
+ or its successor <a href="https://code.google.com/p/farmhash/">FarmHash</a> 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:
+ - <tt><cds/container/feldman_hashmap_hp.h></tt> for \p gc::HP garbage collector
+ - <tt><cds/container/feldman_hashmap_dhp.h></tt> for \p gc::DHP garbage collector
+ - <tt><cds/container/feldman_hashmap_rcu.h></tt> 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<Key const, T>, 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 <bool IsConst>
+ 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 IsConst2>
+ bool operator ==(bidirectional_iterator<IsConst2> const& rhs) const CDS_NOEXCEPT
+ {
+ return iterator_base::operator==( rhs );
+ }
+
+ template <bool IsConst2>
+ bool operator !=(bidirectional_iterator<IsConst2> 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 <bool IsConst>
+ 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 IsConst2>
+ bool operator ==(reverse_bidirectional_iterator<IsConst2> const& rhs) const
+ {
+ return iterator_base::operator==( rhs );
+ }
+
+ template <bool IsConst2>
+ bool operator !=(reverse_bidirectional_iterator<IsConst2> 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<node_type, value_type> > 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<false> iterator;
+ typedef bidirectional_iterator<true> const_iterator;
+ typedef reverse_bidirectional_iterator<false> reverse_iterator;
+ typedef reverse_bidirectional_iterator<true> const_reverse_iterator;
+#endif
+
+ protected:
+ //@cond
+ hasher m_Hasher;
+ //@endcond
+
+ public:
+ /// Creates empty map
+ /**
+ @param head_bits: 2<sup>head_bits</sup> specifies the size of head array, minimum is 4.
+ @param array_bits: 2<sup>array_bits</sup> 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 <typename K>
+ bool insert( K&& key )
+ {
+ scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward<K>(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 <typename K, typename V>
+ bool insert( K&& key, V&& val )
+ {
+ scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward<K>(key), std::forward<V>(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:
+ - <tt>item.first</tt> is a const reference to item's key that cannot be changed.
+ - <tt>item.second</tt> 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 <typename K, typename Func>
+ bool insert_with( K&& key, Func func )
+ {
+ scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward<K>(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 <tt>std::forward<Args>(args)...</tt>
+ /**
+ Returns \p true if inserting successful, \p false otherwise.
+ */
+ template <typename K, typename... Args>
+ bool emplace( K&& key, Args&&... args )
+ {
+ scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward<K>(key), std::forward<Args>(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 <tt> std::pair<bool, bool> </tt> 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 <typename K, typename Func>
+ std::pair<bool, bool> update( K&& key, Func func, bool bInsert = true )
+ {
+ scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward<K>(key)));
+ std::pair<bool, bool> 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 <tt>hash( key_type( key ))</tt>
+
+ Return \p true if \p key is found and deleted, \p false otherwise.
+ */
+ template <typename K>
+ 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 <tt>hash( key_type( key ))</tt>,
+ 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 <typename K, typename Func>
+ 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 <tt>hash( key_type( key ))</tt> 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 <typename K>
+ 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 <tt>hash( key_type( key ))</tt>
+ and returns \p true if it is found, or \p false otherwise.
+ */
+ template <typename K>
+ 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 <tt>hash( key_type( key ))</tt>
+ 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 <typename K, typename Func>
+ 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 <tt>hash( key_type( key ))</tt>
+ 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 <typename K>
+ 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 <tt>==</tt> and <tt>!=</tt>.
+ 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 <tt> it1 == it2 </tt>
+ does not entail <tt> &(*it1) == &(*it2) </tt>
+ - 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<iterator>();
+ }
+
+ /// Returns an const iterator to the beginning of the map
+ const_iterator begin() const
+ {
+ return base_class::template init_begin<const_iterator>();
+ }
+
+ /// Returns an const iterator to the beginning of the map
+ const_iterator cbegin()
+ {
+ return base_class::template init_begin<const_iterator>();
+ }
+
+ /// 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<iterator>();
+ }
+
+ /// 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<const_iterator>();
+ }
+
+ /// 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<const_iterator>();
+ }
+
+ /// Returns a reverse iterator to the first element of the reversed map
+ reverse_iterator rbegin()
+ {
+ return base_class::template init_rbegin<reverse_iterator>();
+ }
+
+ /// Returns a const reverse iterator to the first element of the reversed map
+ const_reverse_iterator rbegin() const
+ {
+ return base_class::template init_rbegin<const_reverse_iterator>();
+ }
+
+ /// Returns a const reverse iterator to the first element of the reversed map
+ const_reverse_iterator crbegin()
+ {
+ return base_class::template init_rbegin<const_reverse_iterator>();
+ }
+
+ /// 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<reverse_iterator>();
+ }
+
+ /// 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<const_reverse_iterator>();
+ }
+
+ /// 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<const_reverse_iterator>();
+ }
+ ///@}
+ };
+
+}} // namespace cds::container
+
+#endif // #ifndef CDSLIB_CONTAINER_IMPL_FELDMAN_HASHMAP_H
--- /dev/null
+//$$CDS-header$$
+
+#ifndef CDSLIB_CONTAINER_IMPL_FELDMAN_HASHSET_H
+#define CDSLIB_CONTAINER_IMPL_FELDMAN_HASHSET_H
+
+#include <cds/intrusive/impl/feldman_hashset.h>
+#include <cds/container/details/feldman_hashset_base.h>
+
+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 <b>perfect hashing</b>, 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; <b> the hash value is treated as a bit
+ string</b> 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 <a href="https://en.wikipedia.org/wiki/Secure_Hash_Algorithm">SHA1, SHA2</a>,
+ <a href="https://en.wikipedia.org/wiki/MurmurHash">MurmurHash</a>, <a href="https://en.wikipedia.org/wiki/CityHash">CityHash</a>
+ or its successor <a href="https://code.google.com/p/farmhash/">FarmHash</a> 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:
+ - <tt><cds/container/feldman_hashset_hp.h></tt> for \p gc::HP garbage collector
+ - <tt><cds/container/feldman_hashset_dhp.h></tt> for \p gc::DHP garbage collector
+ - <tt><cds/container/feldman_hashset_rcu.h></tt> 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: 2<sup>head_bits</sup> specifies the size of head array, minimum is 4.
+ @param array_bits: 2<sup>array_bits</sup> 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 <typename Q>
+ 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 <typename Q, typename Func>
+ 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 <tt> std::pair<bool, bool> </tt> 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 <typename Q, typename Func>
+ std::pair<bool, bool> update( Q const& val, Func func, bool bInsert = true )
+ {
+ scoped_node_ptr sp( cxx_node_allocator().New( val ));
+ std::pair<bool, bool> 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 <tt>std::forward<Args>(args)...</tt>
+ /**
+ Returns \p true if inserting successful, \p false otherwise.
+ */
+ template <typename... Args>
+ bool emplace( Args&&... args )
+ {
+ scoped_node_ptr sp( cxx_node_allocator().New( std::forward<Args>(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 <typename Func>
+ 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 <typename Func>
+ 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 <tt>==</tt> and <tt>!=</tt>.
+ 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 <tt> it1 == it2 </tt>
+ does not entail <tt> &(*it1) == &(*it2) </tt>
+ - 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
+++ /dev/null
-//$$CDS-header$$
-
-#ifndef CDSLIB_CONTAINER_IMPL_MULTILEVEL_HASHMAP_H
-#define CDSLIB_CONTAINER_IMPL_MULTILEVEL_HASHMAP_H
-
-#include <cds/intrusive/impl/multilevel_hashset.h>
-#include <cds/container/details/multilevel_hashmap_base.h>
-#include <cds/container/details/guarded_ptr_cast.h>
-
-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 <b>perfect hashing</b>, 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; <b> the hash value is treated as a bit
- string</b> 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 <a href="https://en.wikipedia.org/wiki/Secure_Hash_Algorithm">SHA1, SHA2</a>,
- <a href="https://en.wikipedia.org/wiki/MurmurHash">MurmurHash</a>, <a href="https://en.wikipedia.org/wiki/CityHash">CityHash</a>
- or its successor <a href="https://code.google.com/p/farmhash/">FarmHash</a> 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:
- - <tt><cds/container/multilevel_hashmap_hp.h></tt> for \p gc::HP garbage collector
- - <tt><cds/container/multilevel_hashmap_dhp.h></tt> for \p gc::DHP garbage collector
- - <tt><cds/container/multilevel_hashmap_rcu.h></tt> 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<Key const, T>, 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 <bool IsConst>
- 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 IsConst2>
- bool operator ==(bidirectional_iterator<IsConst2> const& rhs) const CDS_NOEXCEPT
- {
- return iterator_base::operator==( rhs );
- }
-
- template <bool IsConst2>
- bool operator !=(bidirectional_iterator<IsConst2> 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 <bool IsConst>
- 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 IsConst2>
- bool operator ==(reverse_bidirectional_iterator<IsConst2> const& rhs) const
- {
- return iterator_base::operator==( rhs );
- }
-
- template <bool IsConst2>
- bool operator !=(reverse_bidirectional_iterator<IsConst2> 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<node_type, value_type> > 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<false> iterator;
- typedef bidirectional_iterator<true> const_iterator;
- typedef reverse_bidirectional_iterator<false> reverse_iterator;
- typedef reverse_bidirectional_iterator<true> const_reverse_iterator;
-#endif
-
- protected:
- //@cond
- hasher m_Hasher;
- //@endcond
-
- public:
- /// Creates empty map
- /**
- @param head_bits: 2<sup>head_bits</sup> specifies the size of head array, minimum is 4.
- @param array_bits: 2<sup>array_bits</sup> 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 <typename K>
- bool insert( K&& key )
- {
- scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward<K>(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 <typename K, typename V>
- bool insert( K&& key, V&& val )
- {
- scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward<K>(key), std::forward<V>(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:
- - <tt>item.first</tt> is a const reference to item's key that cannot be changed.
- - <tt>item.second</tt> 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 <typename K, typename Func>
- bool insert_with( K&& key, Func func )
- {
- scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward<K>(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 <tt>std::forward<Args>(args)...</tt>
- /**
- Returns \p true if inserting successful, \p false otherwise.
- */
- template <typename K, typename... Args>
- bool emplace( K&& key, Args&&... args )
- {
- scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward<K>(key), std::forward<Args>(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 <tt> std::pair<bool, bool> </tt> 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 <typename K, typename Func>
- std::pair<bool, bool> update( K&& key, Func func, bool bInsert = true )
- {
- scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward<K>(key)));
- std::pair<bool, bool> 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 <tt>hash( key_type( key ))</tt>
-
- Return \p true if \p key is found and deleted, \p false otherwise.
- */
- template <typename K>
- 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 <tt>hash( key_type( key ))</tt>,
- 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 <typename K, typename Func>
- 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 <tt>hash( key_type( key ))</tt> 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 <typename K>
- 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 <tt>hash( key_type( key ))</tt>
- and returns \p true if it is found, or \p false otherwise.
- */
- template <typename K>
- 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 <tt>hash( key_type( key ))</tt>
- 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 <typename K, typename Func>
- 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 <tt>hash( key_type( key ))</tt>
- 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 <typename K>
- 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 <tt>==</tt> and <tt>!=</tt>.
- 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 <tt> it1 == it2 </tt>
- does not entail <tt> &(*it1) == &(*it2) </tt>
- - 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<iterator>();
- }
-
- /// Returns an const iterator to the beginning of the map
- const_iterator begin() const
- {
- return base_class::template init_begin<const_iterator>();
- }
-
- /// Returns an const iterator to the beginning of the map
- const_iterator cbegin()
- {
- return base_class::template init_begin<const_iterator>();
- }
-
- /// 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<iterator>();
- }
-
- /// 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<const_iterator>();
- }
-
- /// 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<const_iterator>();
- }
-
- /// Returns a reverse iterator to the first element of the reversed map
- reverse_iterator rbegin()
- {
- return base_class::template init_rbegin<reverse_iterator>();
- }
-
- /// Returns a const reverse iterator to the first element of the reversed map
- const_reverse_iterator rbegin() const
- {
- return base_class::template init_rbegin<const_reverse_iterator>();
- }
-
- /// Returns a const reverse iterator to the first element of the reversed map
- const_reverse_iterator crbegin()
- {
- return base_class::template init_rbegin<const_reverse_iterator>();
- }
-
- /// 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<reverse_iterator>();
- }
-
- /// 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<const_reverse_iterator>();
- }
-
- /// 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<const_reverse_iterator>();
- }
- ///@}
- };
-
-}} // namespace cds::container
-
-#endif // #ifndef CDSLIB_CONTAINER_IMPL_MULTILEVEL_HASHMAP_H
+++ /dev/null
-//$$CDS-header$$
-
-#ifndef CDSLIB_CONTAINER_IMPL_MULTILEVEL_HASHSET_H
-#define CDSLIB_CONTAINER_IMPL_MULTILEVEL_HASHSET_H
-
-#include <cds/intrusive/impl/multilevel_hashset.h>
-#include <cds/container/details/multilevel_hashset_base.h>
-
-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 <b>perfect hashing</b>, 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; <b> the hash value is treated as a bit
- string</b> 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 <a href="https://en.wikipedia.org/wiki/Secure_Hash_Algorithm">SHA1, SHA2</a>,
- <a href="https://en.wikipedia.org/wiki/MurmurHash">MurmurHash</a>, <a href="https://en.wikipedia.org/wiki/CityHash">CityHash</a>
- or its successor <a href="https://code.google.com/p/farmhash/">FarmHash</a> 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:
- - <tt><cds/container/multilevel_hashset_hp.h></tt> for \p gc::HP garbage collector
- - <tt><cds/container/multilevel_hashset_dhp.h></tt> for \p gc::DHP garbage collector
- - <tt><cds/container/multilevel_hashset_rcu.h></tt> 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: 2<sup>head_bits</sup> specifies the size of head array, minimum is 4.
- @param array_bits: 2<sup>array_bits</sup> 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 <typename Q>
- 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 <typename Q, typename Func>
- 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 <tt> std::pair<bool, bool> </tt> 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 <typename Q, typename Func>
- std::pair<bool, bool> update( Q const& val, Func func, bool bInsert = true )
- {
- scoped_node_ptr sp( cxx_node_allocator().New( val ));
- std::pair<bool, bool> 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 <tt>std::forward<Args>(args)...</tt>
- /**
- Returns \p true if inserting successful, \p false otherwise.
- */
- template <typename... Args>
- bool emplace( Args&&... args )
- {
- scoped_node_ptr sp( cxx_node_allocator().New( std::forward<Args>(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 <typename Func>
- 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 <typename Func>
- 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 <tt>==</tt> and <tt>!=</tt>.
- 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 <tt> it1 == it2 </tt>
- does not entail <tt> &(*it1) == &(*it2) </tt>
- - 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
+++ /dev/null
-//$$CDS-header$$
-
-#ifndef CDSLIB_CONTAINER_MULTILEVEL_HASHMAP_DHP_H
-#define CDSLIB_CONTAINER_MULTILEVEL_HASHMAP_DHP_H
-
-#include <cds/container/impl/multilevel_hashmap.h>
-#include <cds/gc/dhp.h>
-
-#endif // #ifndef CDSLIB_CONTAINER_MULTILEVEL_HASHMAP_DHP_H
+++ /dev/null
-//$$CDS-header$$
-
-#ifndef CDSLIB_CONTAINER_MULTILEVEL_HASHMAP_HP_H
-#define CDSLIB_CONTAINER_MULTILEVEL_HASHMAP_HP_H
-
-#include <cds/container/impl/multilevel_hashmap.h>
-#include <cds/gc/hp.h>
-
-#endif // #ifndef CDSLIB_CONTAINER_MULTILEVEL_HASHMAP_HP_H
+++ /dev/null
-//$$CDS-header$$
-
-#ifndef CDSLIB_CONTAINER_MULTILEVEL_HASHMAP_RCU_H
-#define CDSLIB_CONTAINER_MULTILEVEL_HASHMAP_RCU_H
-
-#include <cds/intrusive/multilevel_hashset_rcu.h>
-#include <cds/container/details/multilevel_hashmap_base.h>
-
-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 <a href="https://en.wikipedia.org/wiki/Secure_Hash_Algorithm">SHA1, SHA2</a>,
- <a href="https://en.wikipedia.org/wiki/MurmurHash">MurmurHash</a>, <a href="https://en.wikipedia.org/wiki/CityHash">CityHash</a>
- or its successor <a href="https://code.google.com/p/farmhash/">FarmHash</a> 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 <tt><cds/intrusive/multilevel_hashset_rcu.h></tt> 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<Key const, T>, 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 <bool IsConst>
- 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 IsConst2>
- bool operator ==(bidirectional_iterator<IsConst2> const& rhs) const CDS_NOEXCEPT
- {
- return iterator_base::operator==( rhs );
- }
-
- template <bool IsConst2>
- bool operator !=(bidirectional_iterator<IsConst2> 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 <bool IsConst>
- 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 IsConst2>
- bool operator ==(reverse_bidirectional_iterator<IsConst2> const& rhs) const
- {
- return iterator_base::operator==( rhs );
- }
-
- template <bool IsConst2>
- bool operator !=(reverse_bidirectional_iterator<IsConst2> 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<false> iterator;
- typedef bidirectional_iterator<true> const_iterator;
- typedef reverse_bidirectional_iterator<false> reverse_iterator;
- typedef reverse_bidirectional_iterator<true> const_reverse_iterator;
-#endif
-
- protected:
- //@cond
- hasher m_Hasher;
- //@endcond
-
- public:
- /// Creates empty map
- /**
- @param head_bits: 2<sup>head_bits</sup> specifies the size of head array, minimum is 4.
- @param array_bits: 2<sup>array_bits</sup> 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 <typename K>
- bool insert( K&& key )
- {
- scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward<K>(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 <typename K, typename V>
- bool insert( K&& key, V&& val )
- {
- scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward<K>(key), std::forward<V>(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:
- - <tt>item.first</tt> is a const reference to item's key that cannot be changed.
- - <tt>item.second</tt> 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 <typename K, typename Func>
- bool insert_with( K&& key, Func func )
- {
- scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward<K>(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 <tt>std::forward<Args>(args)...</tt>
- /**
- Returns \p true if inserting successful, \p false otherwise.
-
- The function locks RCU internally.
- */
- template <typename K, typename... Args>
- bool emplace( K&& key, Args&&... args )
- {
- scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward<K>(key), std::forward<Args>(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 <tt> std::pair<bool, bool> </tt> 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 <typename K, typename Func>
- std::pair<bool, bool> update( K&& key, Func func, bool bInsert = true )
- {
- scoped_node_ptr sp( cxx_node_allocator().MoveNew( m_Hasher, std::forward<K>(key)));
- std::pair<bool, bool> 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 <tt>hash( key_type( key ))</tt>
-
- Return \p true if \p key is found and deleted, \p false otherwise.
-
- RCU should not be locked. The function locks RCU internally.
- */
- template <typename K>
- 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 <tt>hash( key_type( key ))</tt>,
- 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 <typename K, typename Func>
- 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 <tt>hash( key_type( key ))</tt> 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 <typename K>
- 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 <tt>hash( key_type( key ))</tt>
- and returns \p true if it is found, or \p false otherwise.
- */
- template <typename K>
- 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 <tt>hash( key_type( key ))</tt>
- 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 <typename K, typename Func>
- 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 <typename K>
- 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 <tt>==</tt> and <tt>!=</tt>.
- 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 <tt> it1 == it2 </tt>
- does not entail <tt> &(*it1) == &(*it2) </tt>: 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<iterator>();
- }
-
- /// Returns an const iterator to the beginning of the map
- const_iterator begin() const
- {
- return base_class::template init_begin<const_iterator>();
- }
-
- /// Returns an const iterator to the beginning of the map
- const_iterator cbegin()
- {
- return base_class::template init_begin<const_iterator>();
- }
-
- /// 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<iterator>();
- }
-
- /// 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<const_iterator>();
- }
-
- /// 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<const_iterator>();
- }
-
- /// Returns a reverse iterator to the first element of the reversed map
- reverse_iterator rbegin()
- {
- return base_class::template init_rbegin<reverse_iterator>();
- }
-
- /// Returns a const reverse iterator to the first element of the reversed map
- const_reverse_iterator rbegin() const
- {
- return base_class::template init_rbegin<const_reverse_iterator>();
- }
-
- /// Returns a const reverse iterator to the first element of the reversed map
- const_reverse_iterator crbegin()
- {
- return base_class::template init_rbegin<const_reverse_iterator>();
- }
-
- /// 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<reverse_iterator>();
- }
-
- /// 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<const_reverse_iterator>();
- }
-
- /// 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<const_reverse_iterator>();
- }
- ///@}
- };
-}} // namespace cds::container
-
-#endif // #ifndef CDSLIB_CONTAINER_MULTILEVEL_HASHMAP_RCU_H
+++ /dev/null
-//$$CDS-header$$
-
-#ifndef CDSLIB_CONTAINER_MULTILEVEL_HASHSET_DHP_H
-#define CDSLIB_CONTAINER_MULTILEVEL_HASHSET_DHP_H
-
-#include <cds/container/impl/multilevel_hashset.h>
-#include <cds/gc/dhp.h>
-
-#endif // #ifndef CDSLIB_CONTAINER_MULTILEVEL_HASHSET_DHP_H
+++ /dev/null
-//$$CDS-header$$
-
-#ifndef CDSLIB_CONTAINER_MULTILEVEL_HASHSET_HP_H
-#define CDSLIB_CONTAINER_MULTILEVEL_HASHSET_HP_H
-
-#include <cds/container/impl/multilevel_hashset.h>
-#include <cds/gc/hp.h>
-
-#endif // #ifndef CDSLIB_CONTAINER_MULTILEVEL_HASHSET_HP_H
+++ /dev/null
-//$$CDS-header$$
-
-#ifndef CDSLIB_CONTAINER_MULTILEVEL_HASHSET_RCU_H
-#define CDSLIB_CONTAINER_MULTILEVEL_HASHSET_RCU_H
-
-#include <cds/intrusive/multilevel_hashset_rcu.h>
-#include <cds/container/details/multilevel_hashset_base.h>
-
-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 <a href="https://en.wikipedia.org/wiki/Secure_Hash_Algorithm">SHA1, SHA2</a>,
- <a href="https://en.wikipedia.org/wiki/MurmurHash">MurmurHash</a>, <a href="https://en.wikipedia.org/wiki/CityHash">CityHash</a>
- or its successor <a href="https://code.google.com/p/farmhash/">FarmHash</a> 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 <tt><cds/intrusive/multilevel_hashset_rcu.h></tt> 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: 2<sup>head_bits</sup> specifies the size of head array, minimum is 4.
- @param array_bits: 2<sup>array_bits</sup> 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 <typename Q>
- 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 <typename Q, typename Func>
- 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 <tt> std::pair<bool, bool> </tt> 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 <typename Q, typename Func>
- std::pair<bool, bool> update( Q const& val, Func func, bool bInsert = true )
- {
- scoped_node_ptr sp( cxx_node_allocator().New( val ));
- std::pair<bool, bool> 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 <tt>std::forward<Args>(args)...</tt>
- /**
- Returns \p true if inserting successful, \p false otherwise.
- */
- template <typename... Args>
- bool emplace( Args&&... args )
- {
- scoped_node_ptr sp( cxx_node_allocator().New( std::forward<Args>(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 <typename Func>
- 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 <typename Func>
- 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 <tt>==</tt> and <tt>!=</tt>.
- 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 <tt> it1 == it2 </tt>
- does not entail <tt> &(*it1) == &(*it2) </tt>: 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
--- /dev/null
+//$$CDS-header$$
+
+#ifndef CDSLIB_INTRUSIVE_DETAILS_FELDMAN_HASHSET_BASE_H
+#define CDSLIB_INTRUSIVE_DETAILS_FELDMAN_HASHSET_BASE_H
+
+#include <memory.h> // memcmp, memcpy
+#include <type_traits>
+
+#include <cds/intrusive/details/base.h>
+#include <cds/opt/compare.h>
+#include <cds/algo/atomic.h>
+#include <cds/algo/split_bitstring.h>
+#include <cds/details/marked_ptr.h>
+#include <cds/urcu/options.h>
+
+namespace cds { namespace intrusive {
+
+ /// FeldmanHashSet related definitions
+ /** @ingroup cds_intrusive_helper
+ */
+ namespace feldman_hashset {
+ /// Hash accessor option
+ /**
+ @copydetails traits::hash_accessor
+ */
+ template <typename Accessor>
+ struct hash_accessor {
+ //@cond
+ template <typename Base> struct pack: public Base
+ {
+ typedef Accessor hash_accessor;
+ };
+ //@endcond
+ };
+
+ /// \p FeldmanHashSet internal statistics
+ template <typename EventCounter = cds::atomicity::event_counter>
+ 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 <typename... Options>
+ 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 <typename T>
+ struct bitwise_compare
+ {
+ /// Compares \p lhs and \p rhs
+ /**
+ Returns:
+ - <tt> < 0</tt> if <tt>lhs < rhs</tt>
+ - <tt>0</tt> if <tt>lhs == rhs</tt>
+ - <tt> > 0</tt> if <tt>lhs > rhs</tt>
+ */
+ int operator()( T const& lhs, T const& rhs ) const
+ {
+ return memcmp( &lhs, &rhs, sizeof(T));
+ }
+ };
+
+ //@cond
+ namespace details {
+ template <typename HashType, typename UInt = size_t >
+ 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
+++ /dev/null
-//$$CDS-header$$
-
-#ifndef CDSLIB_INTRUSIVE_DETAILS_MULTILEVEL_HASHSET_BASE_H
-#define CDSLIB_INTRUSIVE_DETAILS_MULTILEVEL_HASHSET_BASE_H
-
-#include <memory.h> // memcmp, memcpy
-#include <type_traits>
-
-#include <cds/intrusive/details/base.h>
-#include <cds/opt/compare.h>
-#include <cds/algo/atomic.h>
-#include <cds/algo/split_bitstring.h>
-#include <cds/details/marked_ptr.h>
-#include <cds/urcu/options.h>
-
-namespace cds { namespace intrusive {
-
- /// MultiLevelHashSet related definitions
- /** @ingroup cds_intrusive_helper
- */
- namespace multilevel_hashset {
- /// Hash accessor option
- /**
- @copydetails traits::hash_accessor
- */
- template <typename Accessor>
- struct hash_accessor {
- //@cond
- template <typename Base> struct pack: public Base
- {
- typedef Accessor hash_accessor;
- };
- //@endcond
- };
-
- /// \p MultiLevelHashSet internal statistics
- template <typename EventCounter = cds::atomicity::event_counter>
- 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 <typename... Options>
- 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 <typename T>
- struct bitwise_compare
- {
- /// Compares \p lhs and \p rhs
- /**
- Returns:
- - <tt> < 0</tt> if <tt>lhs < rhs</tt>
- - <tt>0</tt> if <tt>lhs == rhs</tt>
- - <tt> > 0</tt> if <tt>lhs > rhs</tt>
- */
- int operator()( T const& lhs, T const& rhs ) const
- {
- return memcmp( &lhs, &rhs, sizeof(T));
- }
- };
-
- //@cond
- namespace details {
- template <typename HashType, typename UInt = size_t >
- 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
--- /dev/null
+//$$CDS-header$$
+
+#ifndef CDSLIB_INTRUSIVE_FELDMAN_HASHSET_DHP_H
+#define CDSLIB_INTRUSIVE_FELDMAN_HASHSET_DHP_H
+
+#include <cds/intrusive/impl/feldman_hashset.h>
+#include <cds/gc/dhp.h>
+
+#endif // #ifndef CDSLIB_INTRUSIVE_FELDMAN_HASHSET_DHP_H
--- /dev/null
+//$$CDS-header$$
+
+#ifndef CDSLIB_INTRUSIVE_FELDMAN_HASHSET_HP_H
+#define CDSLIB_INTRUSIVE_FELDMAN_HASHSET_HP_H
+
+#include <cds/intrusive/impl/feldman_hashset.h>
+#include <cds/gc/hp.h>
+
+#endif // #ifndef CDSLIB_INTRUSIVE_FELDMAN_HASHSET_HP_H
--- /dev/null
+//$$CDS-header$$
+
+#ifndef CDSLIB_INTRUSIVE_FELDMAN_HASHSET_RCU_H
+#define CDSLIB_INTRUSIVE_FELDMAN_HASHSET_RCU_H
+
+#include <functional> // std::ref
+#include <iterator> // std::iterator_traits
+
+#include <cds/intrusive/details/feldman_hashset_base.h>
+#include <cds/details/allocator.h>
+#include <cds/urcu/details/check_deadlock.h>
+#include <cds/urcu/exempt_ptr.h>
+#include <cds/intrusive/details/raw_ptr_disposer.h>
+
+
+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 <a href="https://en.wikipedia.org/wiki/Secure_Hash_Algorithm">SHA1, SHA2</a>,
+ <a href="https://en.wikipedia.org/wiki/MurmurHash">MurmurHash</a>, <a href="https://en.wikipedia.org/wiki/CityHash">CityHash</a>
+ or its successor <a href="https://code.google.com/p/farmhash/">FarmHash</a> 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 <tt><cds/intrusive/feldman_hashset_rcu.h></tt> 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<T>()))
+ >::type
+ >::type hash_type;
+ //typedef typename std::result_of< hash_accessor( std::declval<T>()) >::type hash_type;
+ static_assert(!std::is_pointer<hash_type>::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: 2<sup>head_bits</sup> specifies the size of head array, minimum is 4.
+ @param array_bits: 2<sup>array_bits</sup> 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 <typename Func>
+ 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 <tt> std::pair<true, false> </tt>
+ - If hash value is not found and \p bInsert is \p true then \p val is inserted,
+ the function returns <tt> std::pair<true, true> </tt>
+ - If hash value is not found and \p bInsert is \p false then the set is unchanged,
+ the function returns <tt> std::pair<false, false> </tt>
+
+ Returns <tt> std::pair<bool, bool> </tt> 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<bool, bool> 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 <tt>&val</tt>.
+
+ 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<disposer>( 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 <typename Func>
+ 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<disposer>(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 <typename Func>
+ 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 <class Iterator>
+ Iterator init_begin() const
+ {
+ return Iterator(*this, m_Head, size_t(0) - 1);
+ }
+
+ template <class Iterator>
+ Iterator init_end() const
+ {
+ return Iterator(*this, m_Head, head_size(), false);
+ }
+
+ template <class Iterator>
+ Iterator init_rbegin() const
+ {
+ return Iterator(*this, m_Head, head_size());
+ }
+
+ template <class Iterator>
+ Iterator init_rend() const
+ {
+ return Iterator(*this, m_Head, size_t(0) - 1, false);
+ }
+
+ /// Bidirectional iterator class
+ template <bool IsConst>
+ 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 IsConst2>
+ bool operator ==(bidirectional_iterator<IsConst2> const& rhs) const CDS_NOEXCEPT
+ {
+ return iterator_base::operator==(rhs);
+ }
+
+ template <bool IsConst2>
+ bool operator !=(bidirectional_iterator<IsConst2> 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 <bool IsConst>
+ 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 IsConst2>
+ bool operator ==(reverse_bidirectional_iterator<IsConst2> const& rhs) const
+ {
+ return iterator_base::operator==(rhs);
+ }
+
+ template <bool IsConst2>
+ bool operator !=(reverse_bidirectional_iterator<IsConst2> 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<false> iterator;
+ typedef bidirectional_iterator<true> const_iterator;
+ typedef reverse_bidirectional_iterator<false> reverse_iterator;
+ typedef reverse_bidirectional_iterator<true> 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 <tt>==</tt> and <tt>!=</tt>.
+ 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 <tt> it1 == it2 </tt>
+ does not entail <tt> &(*it1) == &(*it2) </tt>: 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 <typename Func>
+ std::pair<bool, bool> 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<disposer>( pOld );
+ return std::make_pair(true, false);
+ }
+ } // while
+ }
+
+ template <typename Predicate>
+ 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<disposer>(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
--- /dev/null
+//$$CDS-header$$
+
+#ifndef CDSLIB_INTRUSIVE_IMPL_FELDMAN_HASHSET_H
+#define CDSLIB_INTRUSIVE_IMPL_FELDMAN_HASHSET_H
+
+#include <functional> // std::ref
+#include <iterator> // std::iterator_traits
+
+#include <cds/intrusive/details/feldman_hashset_base.h>
+#include <cds/details/allocator.h>
+
+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 <b>perfect hashing</b>, 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; <b> the hash value is treated as a bit
+ string</b> 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 <a href="https://en.wikipedia.org/wiki/Secure_Hash_Algorithm">SHA1, SHA2</a>,
+ <a href="https://en.wikipedia.org/wiki/MurmurHash">MurmurHash</a>, <a href="https://en.wikipedia.org/wiki/CityHash">CityHash</a>
+ or its successor <a href="https://code.google.com/p/farmhash/">FarmHash</a> 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:
+ - <tt><cds/intrusive/feldman_hashset_hp.h></tt> for \p gc::HP garbage collector
+ - <tt><cds/intrusive/feldman_hashset_dhp.h></tt> for \p gc::DHP garbage collector
+ - <tt><cds/intrusive/feldman_hashset_rcu.h></tt> 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<T>()) )
+ >::type
+ >::type hash_type;
+ //typedef typename std::result_of< hash_accessor( std::declval<T>()) >::type hash_type;
+ static_assert( !std::is_pointer<hash_type>::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<value_type>();
+ }
+
+ 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 <class Iterator>
+ Iterator init_begin() const
+ {
+ return Iterator( *this, m_Head, size_t(0) - 1 );
+ }
+
+ template <class Iterator>
+ Iterator init_end() const
+ {
+ return Iterator( *this, m_Head, head_size(), false );
+ }
+
+ template <class Iterator>
+ Iterator init_rbegin() const
+ {
+ return Iterator( *this, m_Head, head_size() );
+ }
+
+ template <class Iterator>
+ Iterator init_rend() const
+ {
+ return Iterator( *this, m_Head, size_t(0) - 1, false );
+ }
+
+ /// Bidirectional iterator class
+ template <bool IsConst>
+ 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 IsConst2>
+ bool operator ==(bidirectional_iterator<IsConst2> const& rhs) const CDS_NOEXCEPT
+ {
+ return iterator_base::operator==( rhs );
+ }
+
+ template <bool IsConst2>
+ bool operator !=(bidirectional_iterator<IsConst2> 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 <bool IsConst>
+ 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 IsConst2>
+ bool operator ==(reverse_bidirectional_iterator<IsConst2> const& rhs) const
+ {
+ return iterator_base::operator==( rhs );
+ }
+
+ template <bool IsConst2>
+ bool operator !=(reverse_bidirectional_iterator<IsConst2> 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<false> iterator;
+ typedef bidirectional_iterator<true> const_iterator;
+ typedef reverse_bidirectional_iterator<false> reverse_iterator;
+ typedef reverse_bidirectional_iterator<true> 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: 2<sup>head_bits</sup> specifies the size of head array, minimum is 4.
+ @param array_bits: 2<sup>array_bits</sup> 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 <typename Func>
+ 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 <tt> std::pair<true, false> </tt>
+ - If hash value is not found and \p bInsert is \p true then \p val is inserted,
+ the function returns <tt> std::pair<true, true> </tt>
+ - If hash value is not found and \p bInsert is \p false then the set is unchanged,
+ the function returns <tt> std::pair<false, false> </tt>
+
+ Returns <tt> std::pair<bool, bool> </tt> 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<bool, bool> 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 <tt>&val</tt>.
+
+ 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 <typename Func>
+ 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 <typename Func>
+ 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 <tt>==</tt> and <tt>!=</tt>.
+ 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 <tt> it1 == it2 </tt>
+ does not entail <tt> &(*it1) == &(*it2) </tt>: 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<disposer>( 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 <typename Predicate>
+ 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<disposer>( 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<disposer>( slot.ptr() );
+ --m_ItemCounter;
+ m_Stat.onEraseSuccess();
+ return true;
+ }
+ }
+ else
+ return false;
+ }
+ }
+
+ template <typename Func>
+ std::pair<bool, bool> 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<disposer>( 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 <class GC, typename T, typename Traits>
+ 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 <class GC, typename T, typename Traits>
+ 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
+++ /dev/null
-//$$CDS-header$$
-
-#ifndef CDSLIB_INTRUSIVE_IMPL_MULTILEVEL_HASHSET_H
-#define CDSLIB_INTRUSIVE_IMPL_MULTILEVEL_HASHSET_H
-
-#include <functional> // std::ref
-#include <iterator> // std::iterator_traits
-
-#include <cds/intrusive/details/multilevel_hashset_base.h>
-#include <cds/details/allocator.h>
-
-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 <b>perfect hashing</b>, 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; <b> the hash value is treated as a bit
- string</b> 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 <a href="https://en.wikipedia.org/wiki/Secure_Hash_Algorithm">SHA1, SHA2</a>,
- <a href="https://en.wikipedia.org/wiki/MurmurHash">MurmurHash</a>, <a href="https://en.wikipedia.org/wiki/CityHash">CityHash</a>
- or its successor <a href="https://code.google.com/p/farmhash/">FarmHash</a> 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:
- - <tt><cds/intrusive/multilevel_hashset_hp.h></tt> for \p gc::HP garbage collector
- - <tt><cds/intrusive/multilevel_hashset_dhp.h></tt> for \p gc::DHP garbage collector
- - <tt><cds/intrusive/multilevel_hashset_rcu.h></tt> 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<T>()) )
- >::type
- >::type hash_type;
- //typedef typename std::result_of< hash_accessor( std::declval<T>()) >::type hash_type;
- static_assert( !std::is_pointer<hash_type>::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<value_type>();
- }
-
- 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 <class Iterator>
- Iterator init_begin() const
- {
- return Iterator( *this, m_Head, size_t(0) - 1 );
- }
-
- template <class Iterator>
- Iterator init_end() const
- {
- return Iterator( *this, m_Head, head_size(), false );
- }
-
- template <class Iterator>
- Iterator init_rbegin() const
- {
- return Iterator( *this, m_Head, head_size() );
- }
-
- template <class Iterator>
- Iterator init_rend() const
- {
- return Iterator( *this, m_Head, size_t(0) - 1, false );
- }
-
- /// Bidirectional iterator class
- template <bool IsConst>
- 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 IsConst2>
- bool operator ==(bidirectional_iterator<IsConst2> const& rhs) const CDS_NOEXCEPT
- {
- return iterator_base::operator==( rhs );
- }
-
- template <bool IsConst2>
- bool operator !=(bidirectional_iterator<IsConst2> 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 <bool IsConst>
- 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 IsConst2>
- bool operator ==(reverse_bidirectional_iterator<IsConst2> const& rhs) const
- {
- return iterator_base::operator==( rhs );
- }
-
- template <bool IsConst2>
- bool operator !=(reverse_bidirectional_iterator<IsConst2> 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<false> iterator;
- typedef bidirectional_iterator<true> const_iterator;
- typedef reverse_bidirectional_iterator<false> reverse_iterator;
- typedef reverse_bidirectional_iterator<true> 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: 2<sup>head_bits</sup> specifies the size of head array, minimum is 4.
- @param array_bits: 2<sup>array_bits</sup> 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 <typename Func>
- 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 <tt> std::pair<true, false> </tt>
- - If hash value is not found and \p bInsert is \p true then \p val is inserted,
- the function returns <tt> std::pair<true, true> </tt>
- - If hash value is not found and \p bInsert is \p false then the set is unchanged,
- the function returns <tt> std::pair<false, false> </tt>
-
- Returns <tt> std::pair<bool, bool> </tt> 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<bool, bool> 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 <tt>&val</tt>.
-
- 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 <typename Func>
- 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 <typename Func>
- 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 <tt>==</tt> and <tt>!=</tt>.
- 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 <tt> it1 == it2 </tt>
- does not entail <tt> &(*it1) == &(*it2) </tt>: 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<disposer>( 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 <typename Predicate>
- 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<disposer>( 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<disposer>( slot.ptr() );
- --m_ItemCounter;
- m_Stat.onEraseSuccess();
- return true;
- }
- }
- else
- return false;
- }
- }
-
- template <typename Func>
- std::pair<bool, bool> 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<disposer>( 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 <class GC, typename T, typename Traits>
- 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 <class GC, typename T, typename Traits>
- 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
+++ /dev/null
-//$$CDS-header$$
-
-#ifndef CDSLIB_INTRUSIVE_MULTILEVEL_HASHSET_DHP_H
-#define CDSLIB_INTRUSIVE_MULTILEVEL_HASHSET_DHP_H
-
-#include <cds/intrusive/impl/multilevel_hashset.h>
-#include <cds/gc/dhp.h>
-
-#endif // #ifndef CDSLIB_INTRUSIVE_MULTILEVEL_HASHSET_DHP_H
+++ /dev/null
-//$$CDS-header$$
-
-#ifndef CDSLIB_INTRUSIVE_MULTILEVEL_HASHSET_HP_H
-#define CDSLIB_INTRUSIVE_MULTILEVEL_HASHSET_HP_H
-
-#include <cds/intrusive/impl/multilevel_hashset.h>
-#include <cds/gc/hp.h>
-
-#endif // #ifndef CDSLIB_INTRUSIVE_MULTILEVEL_HASHSET_HP_H
+++ /dev/null
-//$$CDS-header$$
-
-#ifndef CDSLIB_INTRUSIVE_MULTILEVEL_HASHSET_RCU_H
-#define CDSLIB_INTRUSIVE_MULTILEVEL_HASHSET_RCU_H
-
-#include <functional> // std::ref
-#include <iterator> // std::iterator_traits
-
-#include <cds/intrusive/details/multilevel_hashset_base.h>
-#include <cds/details/allocator.h>
-#include <cds/urcu/details/check_deadlock.h>
-#include <cds/urcu/exempt_ptr.h>
-#include <cds/intrusive/details/raw_ptr_disposer.h>
-
-
-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 <a href="https://en.wikipedia.org/wiki/Secure_Hash_Algorithm">SHA1, SHA2</a>,
- <a href="https://en.wikipedia.org/wiki/MurmurHash">MurmurHash</a>, <a href="https://en.wikipedia.org/wiki/CityHash">CityHash</a>
- or its successor <a href="https://code.google.com/p/farmhash/">FarmHash</a> 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 <tt><cds/intrusive/multilevel_hashset_rcu.h></tt> 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<T>()))
- >::type
- >::type hash_type;
- //typedef typename std::result_of< hash_accessor( std::declval<T>()) >::type hash_type;
- static_assert(!std::is_pointer<hash_type>::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: 2<sup>head_bits</sup> specifies the size of head array, minimum is 4.
- @param array_bits: 2<sup>array_bits</sup> 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 <typename Func>
- 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 <tt> std::pair<true, false> </tt>
- - If hash value is not found and \p bInsert is \p true then \p val is inserted,
- the function returns <tt> std::pair<true, true> </tt>
- - If hash value is not found and \p bInsert is \p false then the set is unchanged,
- the function returns <tt> std::pair<false, false> </tt>
-
- Returns <tt> std::pair<bool, bool> </tt> 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<bool, bool> 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 <tt>&val</tt>.
-
- 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<disposer>( 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 <typename Func>
- 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<disposer>(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 <typename Func>
- 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 <class Iterator>
- Iterator init_begin() const
- {
- return Iterator(*this, m_Head, size_t(0) - 1);
- }
-
- template <class Iterator>
- Iterator init_end() const
- {
- return Iterator(*this, m_Head, head_size(), false);
- }
-
- template <class Iterator>
- Iterator init_rbegin() const
- {
- return Iterator(*this, m_Head, head_size());
- }
-
- template <class Iterator>
- Iterator init_rend() const
- {
- return Iterator(*this, m_Head, size_t(0) - 1, false);
- }
-
- /// Bidirectional iterator class
- template <bool IsConst>
- 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 IsConst2>
- bool operator ==(bidirectional_iterator<IsConst2> const& rhs) const CDS_NOEXCEPT
- {
- return iterator_base::operator==(rhs);
- }
-
- template <bool IsConst2>
- bool operator !=(bidirectional_iterator<IsConst2> 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 <bool IsConst>
- 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 IsConst2>
- bool operator ==(reverse_bidirectional_iterator<IsConst2> const& rhs) const
- {
- return iterator_base::operator==(rhs);
- }
-
- template <bool IsConst2>
- bool operator !=(reverse_bidirectional_iterator<IsConst2> 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<false> iterator;
- typedef bidirectional_iterator<true> const_iterator;
- typedef reverse_bidirectional_iterator<false> reverse_iterator;
- typedef reverse_bidirectional_iterator<true> 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 <tt>==</tt> and <tt>!=</tt>.
- 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 <tt> it1 == it2 </tt>
- does not entail <tt> &(*it1) == &(*it2) </tt>: 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 <typename Func>
- std::pair<bool, bool> 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<disposer>( pOld );
- return std::make_pair(true, false);
- }
- } // while
- }
-
- template <typename Predicate>
- 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<disposer>(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
..\..\..\tests\unit\print_cuckoo_stat.h = ..\..\..\tests\unit\print_cuckoo_stat.h\r
..\..\..\tests\unit\print_ellenbintree_stat.h = ..\..\..\tests\unit\print_ellenbintree_stat.h\r
..\..\..\tests\unit\print_mspriorityqueue_stat.h = ..\..\..\tests\unit\print_mspriorityqueue_stat.h\r
- ..\..\..\tests\unit\print_multilevel_hashset_stat.h = ..\..\..\tests\unit\print_multilevel_hashset_stat.h\r
+ ..\..\..\tests\unit\print_feldman_hashset_stat.h = ..\..\..\tests\unit\print_feldman_hashset_stat.h\r
..\..\..\tests\unit\print_segmentedqueue_stat.h = ..\..\..\tests\unit\print_segmentedqueue_stat.h\r
..\..\..\tests\unit\print_skip_list_stat.h = ..\..\..\tests\unit\print_skip_list_stat.h\r
..\..\..\tests\unit\print_split_list_stat.h = ..\..\..\tests\unit\print_split_list_stat.h\r
..\..\..\tests\unit\map2\map_type_lazy_list.h = ..\..\..\tests\unit\map2\map_type_lazy_list.h\r
..\..\..\tests\unit\map2\map_type_michael.h = ..\..\..\tests\unit\map2\map_type_michael.h\r
..\..\..\tests\unit\map2\map_type_michael_list.h = ..\..\..\tests\unit\map2\map_type_michael_list.h\r
- ..\..\..\tests\unit\map2\map_type_multilevel_hashmap.h = ..\..\..\tests\unit\map2\map_type_multilevel_hashmap.h\r
+ ..\..\..\tests\unit\map2\map_type_feldman_hashmap.h = ..\..\..\tests\unit\map2\map_type_feldman_hashmap.h\r
..\..\..\tests\unit\map2\map_type_skip_list.h = ..\..\..\tests\unit\map2\map_type_skip_list.h\r
..\..\..\tests\unit\map2\map_type_split_list.h = ..\..\..\tests\unit\map2\map_type_split_list.h\r
..\..\..\tests\unit\map2\map_type_std.h = ..\..\..\tests\unit\map2\map_type_std.h\r
..\..\..\tests\unit\set2\set_type_lazy_list.h = ..\..\..\tests\unit\set2\set_type_lazy_list.h\r
..\..\..\tests\unit\set2\set_type_michael.h = ..\..\..\tests\unit\set2\set_type_michael.h\r
..\..\..\tests\unit\set2\set_type_michael_list.h = ..\..\..\tests\unit\set2\set_type_michael_list.h\r
- ..\..\..\tests\unit\set2\set_type_multilevel_hashset.h = ..\..\..\tests\unit\set2\set_type_multilevel_hashset.h\r
+ ..\..\..\tests\unit\set2\set_type_feldman_hashset.h = ..\..\..\tests\unit\set2\set_type_feldman_hashset.h\r
..\..\..\tests\unit\set2\set_type_skip_list.h = ..\..\..\tests\unit\set2\set_type_skip_list.h\r
..\..\..\tests\unit\set2\set_type_split_list.h = ..\..\..\tests\unit\set2\set_type_split_list.h\r
..\..\..\tests\unit\set2\set_type_std.h = ..\..\..\tests\unit\set2\set_type_std.h\r
<ClInclude Include="..\..\..\cds\container\details\michael_list_base.h" />\r
<ClInclude Include="..\..\..\cds\container\details\michael_map_base.h" />\r
<ClInclude Include="..\..\..\cds\container\details\michael_set_base.h" />\r
- <ClInclude Include="..\..\..\cds\container\details\multilevel_hashmap_base.h" />\r
- <ClInclude Include="..\..\..\cds\container\details\multilevel_hashset_base.h" />\r
+ <ClInclude Include="..\..\..\cds\container\details\feldman_hashmap_base.h" />\r
+ <ClInclude Include="..\..\..\cds\container\details\feldman_hashset_base.h" />\r
<ClInclude Include="..\..\..\cds\container\details\skip_list_base.h" />\r
<ClInclude Include="..\..\..\cds\container\details\split_list_base.h" />\r
<ClInclude Include="..\..\..\cds\container\ellen_bintree_map_dhp.h" />\r
<ClInclude Include="..\..\..\cds\container\impl\lazy_list.h" />\r
<ClInclude Include="..\..\..\cds\container\impl\michael_kvlist.h" />\r
<ClInclude Include="..\..\..\cds\container\impl\michael_list.h" />\r
- <ClInclude Include="..\..\..\cds\container\impl\multilevel_hashmap.h" />\r
- <ClInclude Include="..\..\..\cds\container\impl\multilevel_hashset.h" />\r
+ <ClInclude Include="..\..\..\cds\container\impl\feldman_hashmap.h" />\r
+ <ClInclude Include="..\..\..\cds\container\impl\feldman_hashset.h" />\r
<ClInclude Include="..\..\..\cds\container\impl\skip_list_map.h" />\r
<ClInclude Include="..\..\..\cds\container\impl\skip_list_set.h" />\r
<ClInclude Include="..\..\..\cds\container\lazy_kvlist_dhp.h" />\r
<ClInclude Include="..\..\..\cds\container\michael_map_rcu.h" />\r
<ClInclude Include="..\..\..\cds\container\michael_set_rcu.h" />\r
<ClInclude Include="..\..\..\cds\container\mspriority_queue.h" />\r
- <ClInclude Include="..\..\..\cds\container\multilevel_hashmap_dhp.h" />\r
- <ClInclude Include="..\..\..\cds\container\multilevel_hashmap_hp.h" />\r
- <ClInclude Include="..\..\..\cds\container\multilevel_hashmap_rcu.h" />\r
- <ClInclude Include="..\..\..\cds\container\multilevel_hashset_dhp.h" />\r
- <ClInclude Include="..\..\..\cds\container\multilevel_hashset_hp.h" />\r
- <ClInclude Include="..\..\..\cds\container\multilevel_hashset_rcu.h" />\r
+ <ClInclude Include="..\..\..\cds\container\feldman_hashmap_dhp.h" />\r
+ <ClInclude Include="..\..\..\cds\container\feldman_hashmap_hp.h" />\r
+ <ClInclude Include="..\..\..\cds\container\feldman_hashmap_rcu.h" />\r
+ <ClInclude Include="..\..\..\cds\container\feldman_hashset_dhp.h" />\r
+ <ClInclude Include="..\..\..\cds\container\feldman_hashset_hp.h" />\r
+ <ClInclude Include="..\..\..\cds\container\feldman_hashset_rcu.h" />\r
<ClInclude Include="..\..\..\cds\container\skip_list_map_dhp.h" />\r
<ClInclude Include="..\..\..\cds\container\skip_list_map_hp.h" />\r
<ClInclude Include="..\..\..\cds\container\skip_list_map_nogc.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\details\lazy_list_base.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\details\michael_list_base.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\details\michael_set_base.h" />\r
- <ClInclude Include="..\..\..\cds\intrusive\details\multilevel_hashset_base.h" />\r
+ <ClInclude Include="..\..\..\cds\intrusive\details\feldman_hashset_base.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\details\node_traits.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\details\raw_ptr_disposer.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\details\single_link_struct.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\impl\ellen_bintree.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\impl\lazy_list.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\impl\michael_list.h" />\r
- <ClInclude Include="..\..\..\cds\intrusive\impl\multilevel_hashset.h" />\r
+ <ClInclude Include="..\..\..\cds\intrusive\impl\feldman_hashset.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\impl\skip_list.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\lazy_list_dhp.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\lazy_list_rcu.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\michael_list_rcu.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\michael_set_rcu.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\mspriority_queue.h" />\r
- <ClInclude Include="..\..\..\cds\intrusive\multilevel_hashset_dhp.h" />\r
- <ClInclude Include="..\..\..\cds\intrusive\multilevel_hashset_hp.h" />\r
- <ClInclude Include="..\..\..\cds\intrusive\multilevel_hashset_rcu.h" />\r
+ <ClInclude Include="..\..\..\cds\intrusive\feldman_hashset_dhp.h" />\r
+ <ClInclude Include="..\..\..\cds\intrusive\feldman_hashset_hp.h" />\r
+ <ClInclude Include="..\..\..\cds\intrusive\feldman_hashset_rcu.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\options.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\skip_list_dhp.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\skip_list_hp.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\details\raw_ptr_disposer.h">\r
<Filter>Header Files\cds\intrusive\details</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\intrusive\impl\multilevel_hashset.h">\r
+ <ClInclude Include="..\..\..\cds\intrusive\impl\feldman_hashset.h">\r
<Filter>Header Files\cds\intrusive\impl</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\intrusive\details\multilevel_hashset_base.h">\r
+ <ClInclude Include="..\..\..\cds\intrusive\details\feldman_hashset_base.h">\r
<Filter>Header Files\cds\intrusive\details</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\intrusive\multilevel_hashset_hp.h">\r
+ <ClInclude Include="..\..\..\cds\intrusive\feldman_hashset_hp.h">\r
<Filter>Header Files\cds\intrusive</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\intrusive\multilevel_hashset_dhp.h">\r
+ <ClInclude Include="..\..\..\cds\intrusive\feldman_hashset_dhp.h">\r
<Filter>Header Files\cds\intrusive</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\cds\algo\split_bitstring.h">\r
<Filter>Header Files\cds\algo</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\container\details\multilevel_hashset_base.h">\r
+ <ClInclude Include="..\..\..\cds\container\details\feldman_hashset_base.h">\r
<Filter>Header Files\cds\container\details</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\container\impl\multilevel_hashset.h">\r
+ <ClInclude Include="..\..\..\cds\container\impl\feldman_hashset.h">\r
<Filter>Header Files\cds\container\impl</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\container\multilevel_hashset_hp.h">\r
+ <ClInclude Include="..\..\..\cds\container\feldman_hashset_hp.h">\r
<Filter>Header Files\cds\container</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\container\multilevel_hashset_dhp.h">\r
+ <ClInclude Include="..\..\..\cds\container\feldman_hashset_dhp.h">\r
<Filter>Header Files\cds\container</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\container\details\multilevel_hashmap_base.h">\r
+ <ClInclude Include="..\..\..\cds\container\details\feldman_hashmap_base.h">\r
<Filter>Header Files\cds\container\details</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\container\impl\multilevel_hashmap.h">\r
+ <ClInclude Include="..\..\..\cds\container\impl\feldman_hashmap.h">\r
<Filter>Header Files\cds\container\impl</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\container\multilevel_hashmap_dhp.h">\r
+ <ClInclude Include="..\..\..\cds\container\feldman_hashmap_dhp.h">\r
<Filter>Header Files\cds\container</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\container\multilevel_hashmap_hp.h">\r
+ <ClInclude Include="..\..\..\cds\container\feldman_hashmap_hp.h">\r
<Filter>Header Files\cds\container</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\intrusive\multilevel_hashset_rcu.h">\r
+ <ClInclude Include="..\..\..\cds\intrusive\feldman_hashset_rcu.h">\r
<Filter>Header Files\cds\intrusive</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\container\multilevel_hashset_rcu.h">\r
+ <ClInclude Include="..\..\..\cds\container\feldman_hashset_rcu.h">\r
<Filter>Header Files\cds\container</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\container\multilevel_hashmap_rcu.h">\r
+ <ClInclude Include="..\..\..\cds\container\feldman_hashmap_rcu.h">\r
<Filter>Header Files\cds\container</Filter>\r
</ClInclude>\r
</ItemGroup>\r
<ClInclude Include="..\..\..\tests\test-hdr\map\hdr_skiplist_map.h" />\r
<ClInclude Include="..\..\..\tests\test-hdr\map\hdr_skiplist_map_rcu.h" />\r
<ClInclude Include="..\..\..\tests\test-hdr\map\hdr_striped_map.h" />\r
- <ClInclude Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap.h" />\r
+ <ClInclude Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap.h" />\r
<ClInclude Include="..\..\..\tests\test-hdr\map\print_skiplist_stat.h" />\r
</ItemGroup>\r
<ItemGroup>\r
<ClCompile Include="..\..\..\tests\test-hdr\map\hdr_michael_map_rcu_gpt.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\map\hdr_michael_map_rcu_shb.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\map\hdr_michael_map_rcu_sht.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_dhp.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_hp.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_rcu_gpb.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_rcu_gpi.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_rcu_gpt.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_rcu_shb.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_rcu_sht.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_dhp.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_hp.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_rcu_gpb.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_rcu_gpi.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_rcu_gpt.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_rcu_shb.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_rcu_sht.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\map\hdr_refinable_hashmap_boost_flat_map.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\map\hdr_refinable_hashmap_boost_list.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\map\hdr_refinable_hashmap_boost_map.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\map\hdr_skiplist_map_dhp.cpp">\r
<Filter>skip_list</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_hp.cpp">\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_hp.cpp">\r
<Filter>multilvel_hashmap</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_dhp.cpp">\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_dhp.cpp">\r
<Filter>multilvel_hashmap</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_rcu_gpb.cpp">\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_rcu_gpb.cpp">\r
<Filter>multilvel_hashmap</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_rcu_gpi.cpp">\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_rcu_gpi.cpp">\r
<Filter>multilvel_hashmap</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_rcu_gpt.cpp">\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_rcu_gpt.cpp">\r
<Filter>multilvel_hashmap</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_rcu_shb.cpp">\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_rcu_shb.cpp">\r
<Filter>multilvel_hashmap</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_rcu_sht.cpp">\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_rcu_sht.cpp">\r
<Filter>multilvel_hashmap</Filter>\r
</ClCompile>\r
</ItemGroup>\r
<ClInclude Include="..\..\..\tests\test-hdr\map\hdr_cuckoo_map.h">\r
<Filter>cuckoo</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap.h">\r
+ <ClInclude Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap.h">\r
<Filter>multilvel_hashmap</Filter>\r
</ClInclude>\r
</ItemGroup>\r
</Link>\r
</ItemDefinitionGroup>\r
<ItemGroup>\r
- <ClInclude Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset.h" />\r
+ <ClInclude Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset.h" />\r
<ClInclude Include="..\..\..\tests\test-hdr\set\hdr_intrusive_set.h" />\r
<ClInclude Include="..\..\..\tests\test-hdr\set\hdr_intrusive_skiplist_set.h" />\r
<ClInclude Include="..\..\..\tests\test-hdr\set\hdr_intrusive_skiplist_set_rcu.h" />\r
- <ClInclude Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset.h" />\r
+ <ClInclude Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset.h" />\r
<ClInclude Include="..\..\..\tests\test-hdr\set\hdr_set.h" />\r
<ClInclude Include="..\..\..\tests\test-hdr\set\hdr_skiplist_set.h" />\r
<ClInclude Include="..\..\..\tests\test-hdr\set\hdr_skiplist_set_rcu.h" />\r
<ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_michael_set_rcu_shb_lazy.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_michael_set_rcu_sht.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_michael_set_rcu_sht_lazy.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_dhp.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_hp.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_rcu_gpb.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_rcu_gpi.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_rcu_gpt.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_rcu_shb.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_rcu_sht.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_dhp.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_hp.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_rcu_gpb.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_rcu_gpi.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_rcu_gpt.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_rcu_shb.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_rcu_sht.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_skiplist_dhp.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_skiplist_dhp_member.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_skiplist_hp.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\set\hdr_michael_set_rcu_gpt.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\set\hdr_michael_set_rcu_shb.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\set\hdr_michael_set_rcu_sht.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_dhp.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_hp.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_rcu_gpb.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_rcu_gpi.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_rcu_gpt.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_rcu_shb.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_rcu_sht.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_dhp.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_hp.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_rcu_gpb.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_rcu_gpi.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_rcu_gpt.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_rcu_shb.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_rcu_sht.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\set\hdr_skiplist_set_dhp.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\set\hdr_skiplist_set_hp.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\set\hdr_skiplist_set_nogc.cpp" />\r
<ClInclude Include="..\..\..\tests\test-hdr\set\hdr_skiplist_set_rcu.h">\r
<Filter>container\skip_list</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset.h">\r
- <Filter>intrusive\multilevel_hashset</Filter>\r
+ <ClInclude Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset.h">\r
+ <Filter>intrusive\feldman_hashset</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset.h">\r
- <Filter>container\multilevel_hashset</Filter>\r
+ <ClInclude Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset.h">\r
+ <Filter>container\feldman_hashset</Filter>\r
</ClInclude>\r
</ItemGroup>\r
<ItemGroup>\r
<Filter Include="container\split_list">\r
<UniqueIdentifier>{61f94a40-c964-4233-af67-66a1be1e0aab}</UniqueIdentifier>\r
</Filter>\r
- <Filter Include="intrusive\multilevel_hashset">\r
+ <Filter Include="intrusive\feldman_hashset">\r
<UniqueIdentifier>{a878aed0-83c9-4ca7-95bb-74f10aad8bde}</UniqueIdentifier>\r
</Filter>\r
- <Filter Include="container\multilevel_hashset">\r
+ <Filter Include="container\feldman_hashset">\r
<UniqueIdentifier>{5268f225-1474-413e-a1cb-5f00b8df5e1e}</UniqueIdentifier>\r
</Filter>\r
</ItemGroup>\r
<ClCompile Include="..\..\..\tests\test-hdr\set\hdr_skiplist_set_dhp.cpp">\r
<Filter>container\skip_list</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_hp.cpp">\r
- <Filter>intrusive\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_hp.cpp">\r
+ <Filter>intrusive\feldman_hashset</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_dhp.cpp">\r
- <Filter>intrusive\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_dhp.cpp">\r
+ <Filter>intrusive\feldman_hashset</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_hp.cpp">\r
- <Filter>container\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_hp.cpp">\r
+ <Filter>container\feldman_hashset</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_dhp.cpp">\r
- <Filter>container\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_dhp.cpp">\r
+ <Filter>container\feldman_hashset</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_rcu_gpb.cpp">\r
- <Filter>intrusive\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_rcu_gpb.cpp">\r
+ <Filter>intrusive\feldman_hashset</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_rcu_gpi.cpp">\r
- <Filter>intrusive\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_rcu_gpi.cpp">\r
+ <Filter>intrusive\feldman_hashset</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_rcu_gpt.cpp">\r
- <Filter>intrusive\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_rcu_gpt.cpp">\r
+ <Filter>intrusive\feldman_hashset</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_rcu_shb.cpp">\r
- <Filter>intrusive\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_rcu_shb.cpp">\r
+ <Filter>intrusive\feldman_hashset</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_rcu_sht.cpp">\r
- <Filter>intrusive\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_rcu_sht.cpp">\r
+ <Filter>intrusive\feldman_hashset</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_rcu_gpb.cpp">\r
- <Filter>container\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_rcu_gpb.cpp">\r
+ <Filter>container\feldman_hashset</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_rcu_gpi.cpp">\r
- <Filter>container\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_rcu_gpi.cpp">\r
+ <Filter>container\feldman_hashset</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_rcu_gpt.cpp">\r
- <Filter>container\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_rcu_gpt.cpp">\r
+ <Filter>container\feldman_hashset</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_rcu_shb.cpp">\r
- <Filter>container\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_rcu_shb.cpp">\r
+ <Filter>container\feldman_hashset</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_rcu_sht.cpp">\r
- <Filter>container\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_rcu_sht.cpp">\r
+ <Filter>container\feldman_hashset</Filter>\r
</ClCompile>\r
</ItemGroup>\r
</Project>
\ No newline at end of file
<ClCompile Include="..\..\..\tests\unit\map2\map_delodd_michael.cpp">\r
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DebugVLD|x64'">false</ExcludedFromBuild>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_delodd_multilevelhashmap.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_delodd_feldmanhashmap.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_delodd_skip.cpp">\r
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DebugVLD|x64'">false</ExcludedFromBuild>\r
</ClCompile>\r
<ClCompile Include="..\..\..\tests\unit\map2\map_find_int_cuckoo.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_find_int_ellentree.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_find_int_michael.cpp" />\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_multilevelhashmap.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_feldmanhashmap.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_find_int_skip.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_find_int_split.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_find_int_std.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_find_string_cuckoo.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_find_string_ellentree.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_find_string_michael.cpp" />\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_multilevelhashmap.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_feldmanhashmap.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_find_string_skip.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_find_string_split.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_find_string_std.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_cuckoo.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_ellentree.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_michael.cpp" />\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_multilevelhashmap.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_feldmanhashmap.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_skip.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_split.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_std.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_striped.cpp">\r
<Filter>map_insfind_int</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_multilevelhashmap.cpp">\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_feldmanhashmap.cpp">\r
<Filter>map_find_int</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_multilevelhashmap.cpp">\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_feldmanhashmap.cpp">\r
<Filter>map_find_string</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_multilevelhashmap.cpp">\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_feldmanhashmap.cpp">\r
<Filter>map_insfind_int</Filter>\r
</ClCompile>\r
</ItemGroup>\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_cuckoo.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_ellentree.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_michael.cpp" />\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_multilevelhashmap.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_feldmanhashmap.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_skip.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_split.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_striped.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_cuckoo.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_ellentree.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_michael.cpp" />\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_multilevelhashmap.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_feldmanhashmap.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_skip.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_split.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_striped.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_striped.cpp">\r
<Filter>map_insdel_item_string</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_multilevelhashmap.cpp">\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_feldmanhashmap.cpp">\r
<Filter>map_insdel_item_int</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_multilevelhashmap.cpp">\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_feldmanhashmap.cpp">\r
<Filter>map_insdel_item_string</Filter>\r
</ClCompile>\r
</ItemGroup>\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_cuckoo.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_ellentree.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_michael.cpp" />\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_multilevelhashmap.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_feldmanhashmap.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_skip.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_split.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_striped.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_cuckoo.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_ellentree.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_michael.cpp" />\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_multilevelhashmap.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_feldmanhashmap.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_skip.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_split.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_std.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_cuckoo.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_ellentree.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_michael.cpp" />\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_multilevelhashmap.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_feldmanhashmap.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_skip.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_split.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_std.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_striped.cpp">\r
<Filter>map_insdel_string</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_multilevelhashmap.cpp">\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_feldmanhashmap.cpp">\r
<Filter>map_insdel_int</Filter>\r
</ClCompile>\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_std.cpp">\r
<Filter>map_insdel_int</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_multilevelhashmap.cpp">\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_feldmanhashmap.cpp">\r
<Filter>map_insdel_func</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_multilevelhashmap.cpp">\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_feldmanhashmap.cpp">\r
<Filter>map_insdel_string</Filter>\r
</ClCompile>\r
</ItemGroup>\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_cuckoo.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_ellentree.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_michael.cpp" />\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_multilevelhashmap.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_feldmanhashmap.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_skip.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_split.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_std.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_delodd_cuckoo.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_delodd_ellentree.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_delodd_michael.cpp" />\r
- <ClCompile Include="..\..\..\tests\unit\set2\set_delodd_multilevelhashset.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\set2\set_delodd_feldmanhashset.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_delodd_skip.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_delodd_split.cpp" />\r
</ItemGroup>\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_cuckoo.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_ellentree.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_michael.cpp" />\r
- <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_multilevelhashset.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_feldmanhashset.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_skip.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_split.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_striped.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_cuckoo.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_ellentree.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_michael.cpp" />\r
- <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_multilevelhashset.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_feldmanhashset.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_skip.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_split.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_std.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_michael.cpp">\r
<Filter>set_insdel_func</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_multilevelhashset.cpp">\r
+ <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_feldmanhashset.cpp">\r
<Filter>set_insdel_func</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_multilevelhashset.cpp">\r
+ <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_feldmanhashset.cpp">\r
<Filter>set_insdel_string</Filter>\r
</ClCompile>\r
</ItemGroup>\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_cuckoo.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_ellentree.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_michael.cpp" />\r
- <ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_multilevelhashset.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_feldmanhashset.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_skip.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_split.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_std.cpp" />\r
..\..\..\tests\unit\print_cuckoo_stat.h = ..\..\..\tests\unit\print_cuckoo_stat.h\r
..\..\..\tests\unit\print_ellenbintree_stat.h = ..\..\..\tests\unit\print_ellenbintree_stat.h\r
..\..\..\tests\unit\print_mspriorityqueue_stat.h = ..\..\..\tests\unit\print_mspriorityqueue_stat.h\r
- ..\..\..\tests\unit\print_multilevel_hashset_stat.h = ..\..\..\tests\unit\print_multilevel_hashset_stat.h\r
+ ..\..\..\tests\unit\print_feldman_hashset_stat.h = ..\..\..\tests\unit\print_feldman_hashset_stat.h\r
..\..\..\tests\unit\print_segmentedqueue_stat.h = ..\..\..\tests\unit\print_segmentedqueue_stat.h\r
..\..\..\tests\unit\print_skip_list_stat.h = ..\..\..\tests\unit\print_skip_list_stat.h\r
..\..\..\tests\unit\print_split_list_stat.h = ..\..\..\tests\unit\print_split_list_stat.h\r
..\..\..\tests\unit\map2\map_type_lazy_list.h = ..\..\..\tests\unit\map2\map_type_lazy_list.h\r
..\..\..\tests\unit\map2\map_type_michael.h = ..\..\..\tests\unit\map2\map_type_michael.h\r
..\..\..\tests\unit\map2\map_type_michael_list.h = ..\..\..\tests\unit\map2\map_type_michael_list.h\r
- ..\..\..\tests\unit\map2\map_type_multilevel_hashmap.h = ..\..\..\tests\unit\map2\map_type_multilevel_hashmap.h\r
+ ..\..\..\tests\unit\map2\map_type_feldman_hashmap.h = ..\..\..\tests\unit\map2\map_type_feldman_hashmap.h\r
..\..\..\tests\unit\map2\map_type_skip_list.h = ..\..\..\tests\unit\map2\map_type_skip_list.h\r
..\..\..\tests\unit\map2\map_type_split_list.h = ..\..\..\tests\unit\map2\map_type_split_list.h\r
..\..\..\tests\unit\map2\map_type_std.h = ..\..\..\tests\unit\map2\map_type_std.h\r
..\..\..\tests\unit\set2\set_type_lazy_list.h = ..\..\..\tests\unit\set2\set_type_lazy_list.h\r
..\..\..\tests\unit\set2\set_type_michael.h = ..\..\..\tests\unit\set2\set_type_michael.h\r
..\..\..\tests\unit\set2\set_type_michael_list.h = ..\..\..\tests\unit\set2\set_type_michael_list.h\r
- ..\..\..\tests\unit\set2\set_type_multilevel_hashset.h = ..\..\..\tests\unit\set2\set_type_multilevel_hashset.h\r
+ ..\..\..\tests\unit\set2\set_type_feldman_hashset.h = ..\..\..\tests\unit\set2\set_type_feldman_hashset.h\r
..\..\..\tests\unit\set2\set_type_skip_list.h = ..\..\..\tests\unit\set2\set_type_skip_list.h\r
..\..\..\tests\unit\set2\set_type_split_list.h = ..\..\..\tests\unit\set2\set_type_split_list.h\r
..\..\..\tests\unit\set2\set_type_std.h = ..\..\..\tests\unit\set2\set_type_std.h\r
<ClInclude Include="..\..\..\cds\container\details\michael_list_base.h" />\r
<ClInclude Include="..\..\..\cds\container\details\michael_map_base.h" />\r
<ClInclude Include="..\..\..\cds\container\details\michael_set_base.h" />\r
- <ClInclude Include="..\..\..\cds\container\details\multilevel_hashmap_base.h" />\r
- <ClInclude Include="..\..\..\cds\container\details\multilevel_hashset_base.h" />\r
+ <ClInclude Include="..\..\..\cds\container\details\feldman_hashmap_base.h" />\r
+ <ClInclude Include="..\..\..\cds\container\details\feldman_hashset_base.h" />\r
<ClInclude Include="..\..\..\cds\container\details\skip_list_base.h" />\r
<ClInclude Include="..\..\..\cds\container\details\split_list_base.h" />\r
<ClInclude Include="..\..\..\cds\container\ellen_bintree_map_dhp.h" />\r
<ClInclude Include="..\..\..\cds\container\impl\lazy_list.h" />\r
<ClInclude Include="..\..\..\cds\container\impl\michael_kvlist.h" />\r
<ClInclude Include="..\..\..\cds\container\impl\michael_list.h" />\r
- <ClInclude Include="..\..\..\cds\container\impl\multilevel_hashmap.h" />\r
- <ClInclude Include="..\..\..\cds\container\impl\multilevel_hashset.h" />\r
+ <ClInclude Include="..\..\..\cds\container\impl\feldman_hashmap.h" />\r
+ <ClInclude Include="..\..\..\cds\container\impl\feldman_hashset.h" />\r
<ClInclude Include="..\..\..\cds\container\impl\skip_list_map.h" />\r
<ClInclude Include="..\..\..\cds\container\impl\skip_list_set.h" />\r
<ClInclude Include="..\..\..\cds\container\lazy_kvlist_dhp.h" />\r
<ClInclude Include="..\..\..\cds\container\michael_map_rcu.h" />\r
<ClInclude Include="..\..\..\cds\container\michael_set_rcu.h" />\r
<ClInclude Include="..\..\..\cds\container\mspriority_queue.h" />\r
- <ClInclude Include="..\..\..\cds\container\multilevel_hashmap_dhp.h" />\r
- <ClInclude Include="..\..\..\cds\container\multilevel_hashmap_hp.h" />\r
- <ClInclude Include="..\..\..\cds\container\multilevel_hashmap_rcu.h" />\r
- <ClInclude Include="..\..\..\cds\container\multilevel_hashset_dhp.h" />\r
- <ClInclude Include="..\..\..\cds\container\multilevel_hashset_hp.h" />\r
- <ClInclude Include="..\..\..\cds\container\multilevel_hashset_rcu.h" />\r
+ <ClInclude Include="..\..\..\cds\container\feldman_hashmap_dhp.h" />\r
+ <ClInclude Include="..\..\..\cds\container\feldman_hashmap_hp.h" />\r
+ <ClInclude Include="..\..\..\cds\container\feldman_hashmap_rcu.h" />\r
+ <ClInclude Include="..\..\..\cds\container\feldman_hashset_dhp.h" />\r
+ <ClInclude Include="..\..\..\cds\container\feldman_hashset_hp.h" />\r
+ <ClInclude Include="..\..\..\cds\container\feldman_hashset_rcu.h" />\r
<ClInclude Include="..\..\..\cds\container\skip_list_map_dhp.h" />\r
<ClInclude Include="..\..\..\cds\container\skip_list_map_hp.h" />\r
<ClInclude Include="..\..\..\cds\container\skip_list_map_nogc.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\details\lazy_list_base.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\details\michael_list_base.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\details\michael_set_base.h" />\r
- <ClInclude Include="..\..\..\cds\intrusive\details\multilevel_hashset_base.h" />\r
+ <ClInclude Include="..\..\..\cds\intrusive\details\feldman_hashset_base.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\details\node_traits.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\details\raw_ptr_disposer.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\details\single_link_struct.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\impl\ellen_bintree.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\impl\lazy_list.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\impl\michael_list.h" />\r
- <ClInclude Include="..\..\..\cds\intrusive\impl\multilevel_hashset.h" />\r
+ <ClInclude Include="..\..\..\cds\intrusive\impl\feldman_hashset.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\impl\skip_list.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\lazy_list_dhp.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\lazy_list_rcu.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\michael_list_rcu.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\michael_set_rcu.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\mspriority_queue.h" />\r
- <ClInclude Include="..\..\..\cds\intrusive\multilevel_hashset_dhp.h" />\r
- <ClInclude Include="..\..\..\cds\intrusive\multilevel_hashset_hp.h" />\r
- <ClInclude Include="..\..\..\cds\intrusive\multilevel_hashset_rcu.h" />\r
+ <ClInclude Include="..\..\..\cds\intrusive\feldman_hashset_dhp.h" />\r
+ <ClInclude Include="..\..\..\cds\intrusive\feldman_hashset_hp.h" />\r
+ <ClInclude Include="..\..\..\cds\intrusive\feldman_hashset_rcu.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\options.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\skip_list_dhp.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\skip_list_hp.h" />\r
<ClInclude Include="..\..\..\cds\intrusive\details\raw_ptr_disposer.h">\r
<Filter>Header Files\cds\intrusive\details</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\intrusive\impl\multilevel_hashset.h">\r
+ <ClInclude Include="..\..\..\cds\intrusive\impl\feldman_hashset.h">\r
<Filter>Header Files\cds\intrusive\impl</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\intrusive\details\multilevel_hashset_base.h">\r
+ <ClInclude Include="..\..\..\cds\intrusive\details\feldman_hashset_base.h">\r
<Filter>Header Files\cds\intrusive\details</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\intrusive\multilevel_hashset_hp.h">\r
+ <ClInclude Include="..\..\..\cds\intrusive\feldman_hashset_hp.h">\r
<Filter>Header Files\cds\intrusive</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\intrusive\multilevel_hashset_dhp.h">\r
+ <ClInclude Include="..\..\..\cds\intrusive\feldman_hashset_dhp.h">\r
<Filter>Header Files\cds\intrusive</Filter>\r
</ClInclude>\r
<ClInclude Include="..\..\..\cds\algo\split_bitstring.h">\r
<Filter>Header Files\cds\algo</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\container\details\multilevel_hashset_base.h">\r
+ <ClInclude Include="..\..\..\cds\container\details\feldman_hashset_base.h">\r
<Filter>Header Files\cds\container\details</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\container\impl\multilevel_hashset.h">\r
+ <ClInclude Include="..\..\..\cds\container\impl\feldman_hashset.h">\r
<Filter>Header Files\cds\container\impl</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\container\multilevel_hashset_hp.h">\r
+ <ClInclude Include="..\..\..\cds\container\feldman_hashset_hp.h">\r
<Filter>Header Files\cds\container</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\container\multilevel_hashset_dhp.h">\r
+ <ClInclude Include="..\..\..\cds\container\feldman_hashset_dhp.h">\r
<Filter>Header Files\cds\container</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\container\details\multilevel_hashmap_base.h">\r
+ <ClInclude Include="..\..\..\cds\container\details\feldman_hashmap_base.h">\r
<Filter>Header Files\cds\container\details</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\container\impl\multilevel_hashmap.h">\r
+ <ClInclude Include="..\..\..\cds\container\impl\feldman_hashmap.h">\r
<Filter>Header Files\cds\container\impl</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\container\multilevel_hashmap_dhp.h">\r
+ <ClInclude Include="..\..\..\cds\container\feldman_hashmap_dhp.h">\r
<Filter>Header Files\cds\container</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\container\multilevel_hashmap_hp.h">\r
+ <ClInclude Include="..\..\..\cds\container\feldman_hashmap_hp.h">\r
<Filter>Header Files\cds\container</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\intrusive\multilevel_hashset_rcu.h">\r
+ <ClInclude Include="..\..\..\cds\intrusive\feldman_hashset_rcu.h">\r
<Filter>Header Files\cds\intrusive</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\container\multilevel_hashset_rcu.h">\r
+ <ClInclude Include="..\..\..\cds\container\feldman_hashset_rcu.h">\r
<Filter>Header Files\cds\container</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\cds\container\multilevel_hashmap_rcu.h">\r
+ <ClInclude Include="..\..\..\cds\container\feldman_hashmap_rcu.h">\r
<Filter>Header Files\cds\container</Filter>\r
</ClInclude>\r
</ItemGroup>\r
<ClInclude Include="..\..\..\tests\test-hdr\map\hdr_skiplist_map.h" />\r
<ClInclude Include="..\..\..\tests\test-hdr\map\hdr_skiplist_map_rcu.h" />\r
<ClInclude Include="..\..\..\tests\test-hdr\map\hdr_striped_map.h" />\r
- <ClInclude Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap.h" />\r
+ <ClInclude Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap.h" />\r
<ClInclude Include="..\..\..\tests\test-hdr\map\print_skiplist_stat.h" />\r
</ItemGroup>\r
<ItemGroup>\r
<ClCompile Include="..\..\..\tests\test-hdr\map\hdr_michael_map_rcu_gpt.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\map\hdr_michael_map_rcu_shb.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\map\hdr_michael_map_rcu_sht.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_dhp.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_hp.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_rcu_gpb.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_rcu_gpi.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_rcu_gpt.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_rcu_shb.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_rcu_sht.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_dhp.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_hp.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_rcu_gpb.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_rcu_gpi.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_rcu_gpt.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_rcu_shb.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_rcu_sht.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\map\hdr_refinable_hashmap_boost_flat_map.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\map\hdr_refinable_hashmap_boost_list.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\map\hdr_refinable_hashmap_boost_map.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\map\hdr_skiplist_map_dhp.cpp">\r
<Filter>skip_list</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_hp.cpp">\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_hp.cpp">\r
<Filter>multilvel_hashmap</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_dhp.cpp">\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_dhp.cpp">\r
<Filter>multilvel_hashmap</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_rcu_gpb.cpp">\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_rcu_gpb.cpp">\r
<Filter>multilvel_hashmap</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_rcu_gpi.cpp">\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_rcu_gpi.cpp">\r
<Filter>multilvel_hashmap</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_rcu_gpt.cpp">\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_rcu_gpt.cpp">\r
<Filter>multilvel_hashmap</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_rcu_shb.cpp">\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_rcu_shb.cpp">\r
<Filter>multilvel_hashmap</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap_rcu_sht.cpp">\r
+ <ClCompile Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap_rcu_sht.cpp">\r
<Filter>multilvel_hashmap</Filter>\r
</ClCompile>\r
</ItemGroup>\r
<ClInclude Include="..\..\..\tests\test-hdr\map\hdr_cuckoo_map.h">\r
<Filter>cuckoo</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\tests\test-hdr\map\hdr_multilevel_hashmap.h">\r
+ <ClInclude Include="..\..\..\tests\test-hdr\map\hdr_feldman_hashmap.h">\r
<Filter>multilvel_hashmap</Filter>\r
</ClInclude>\r
</ItemGroup>\r
</Link>\r
</ItemDefinitionGroup>\r
<ItemGroup>\r
- <ClInclude Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset.h" />\r
+ <ClInclude Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset.h" />\r
<ClInclude Include="..\..\..\tests\test-hdr\set\hdr_intrusive_set.h" />\r
<ClInclude Include="..\..\..\tests\test-hdr\set\hdr_intrusive_skiplist_set.h" />\r
<ClInclude Include="..\..\..\tests\test-hdr\set\hdr_intrusive_skiplist_set_rcu.h" />\r
- <ClInclude Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset.h" />\r
+ <ClInclude Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset.h" />\r
<ClInclude Include="..\..\..\tests\test-hdr\set\hdr_set.h" />\r
<ClInclude Include="..\..\..\tests\test-hdr\set\hdr_skiplist_set.h" />\r
<ClInclude Include="..\..\..\tests\test-hdr\set\hdr_skiplist_set_rcu.h" />\r
<ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_michael_set_rcu_shb_lazy.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_michael_set_rcu_sht.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_michael_set_rcu_sht_lazy.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_dhp.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_hp.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_rcu_gpb.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_rcu_gpi.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_rcu_gpt.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_rcu_shb.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_rcu_sht.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_dhp.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_hp.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_rcu_gpb.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_rcu_gpi.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_rcu_gpt.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_rcu_shb.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_rcu_sht.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_skiplist_dhp.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_skiplist_dhp_member.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_skiplist_hp.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\set\hdr_michael_set_rcu_gpt.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\set\hdr_michael_set_rcu_shb.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\set\hdr_michael_set_rcu_sht.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_dhp.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_hp.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_rcu_gpb.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_rcu_gpi.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_rcu_gpt.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_rcu_shb.cpp" />\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_rcu_sht.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_dhp.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_hp.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_rcu_gpb.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_rcu_gpi.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_rcu_gpt.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_rcu_shb.cpp" />\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_rcu_sht.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\set\hdr_skiplist_set_dhp.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\set\hdr_skiplist_set_hp.cpp" />\r
<ClCompile Include="..\..\..\tests\test-hdr\set\hdr_skiplist_set_nogc.cpp" />\r
<ClInclude Include="..\..\..\tests\test-hdr\set\hdr_skiplist_set_rcu.h">\r
<Filter>container\skip_list</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset.h">\r
- <Filter>intrusive\multilevel_hashset</Filter>\r
+ <ClInclude Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset.h">\r
+ <Filter>intrusive\feldman_hashset</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset.h">\r
- <Filter>container\multilevel_hashset</Filter>\r
+ <ClInclude Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset.h">\r
+ <Filter>container\feldman_hashset</Filter>\r
</ClInclude>\r
</ItemGroup>\r
<ItemGroup>\r
<Filter Include="container\split_list">\r
<UniqueIdentifier>{61f94a40-c964-4233-af67-66a1be1e0aab}</UniqueIdentifier>\r
</Filter>\r
- <Filter Include="intrusive\multilevel_hashset">\r
+ <Filter Include="intrusive\feldman_hashset">\r
<UniqueIdentifier>{a878aed0-83c9-4ca7-95bb-74f10aad8bde}</UniqueIdentifier>\r
</Filter>\r
- <Filter Include="container\multilevel_hashset">\r
+ <Filter Include="container\feldman_hashset">\r
<UniqueIdentifier>{5268f225-1474-413e-a1cb-5f00b8df5e1e}</UniqueIdentifier>\r
</Filter>\r
</ItemGroup>\r
<ClCompile Include="..\..\..\tests\test-hdr\set\hdr_skiplist_set_dhp.cpp">\r
<Filter>container\skip_list</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_hp.cpp">\r
- <Filter>intrusive\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_hp.cpp">\r
+ <Filter>intrusive\feldman_hashset</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_dhp.cpp">\r
- <Filter>intrusive\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_dhp.cpp">\r
+ <Filter>intrusive\feldman_hashset</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_hp.cpp">\r
- <Filter>container\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_hp.cpp">\r
+ <Filter>container\feldman_hashset</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_dhp.cpp">\r
- <Filter>container\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_dhp.cpp">\r
+ <Filter>container\feldman_hashset</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_rcu_gpi.cpp">\r
- <Filter>intrusive\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_rcu_gpi.cpp">\r
+ <Filter>intrusive\feldman_hashset</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_rcu_gpb.cpp">\r
- <Filter>intrusive\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_rcu_gpb.cpp">\r
+ <Filter>intrusive\feldman_hashset</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_rcu_gpt.cpp">\r
- <Filter>intrusive\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_rcu_gpt.cpp">\r
+ <Filter>intrusive\feldman_hashset</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_rcu_shb.cpp">\r
- <Filter>intrusive\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_rcu_shb.cpp">\r
+ <Filter>intrusive\feldman_hashset</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_multilevel_hashset_rcu_sht.cpp">\r
- <Filter>intrusive\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_intrusive_feldman_hashset_rcu_sht.cpp">\r
+ <Filter>intrusive\feldman_hashset</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_rcu_gpi.cpp">\r
- <Filter>container\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_rcu_gpi.cpp">\r
+ <Filter>container\feldman_hashset</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_rcu_gpb.cpp">\r
- <Filter>container\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_rcu_gpb.cpp">\r
+ <Filter>container\feldman_hashset</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_rcu_gpt.cpp">\r
- <Filter>container\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_rcu_gpt.cpp">\r
+ <Filter>container\feldman_hashset</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_rcu_shb.cpp">\r
- <Filter>container\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_rcu_shb.cpp">\r
+ <Filter>container\feldman_hashset</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_multilevel_hashset_rcu_sht.cpp">\r
- <Filter>container\multilevel_hashset</Filter>\r
+ <ClCompile Include="..\..\..\tests\test-hdr\set\hdr_feldman_hashset_rcu_sht.cpp">\r
+ <Filter>container\feldman_hashset</Filter>\r
</ClCompile>\r
</ItemGroup>\r
</Project>
\ No newline at end of file
<ClCompile Include="..\..\..\tests\unit\map2\map_delodd_michael.cpp">\r
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DebugVLD|x64'">false</ExcludedFromBuild>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_delodd_multilevelhashmap.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_delodd_feldmanhashmap.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_delodd_skip.cpp">\r
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DebugVLD|x64'">false</ExcludedFromBuild>\r
</ClCompile>\r
<ClCompile Include="..\..\..\tests\unit\map2\map_find_int_cuckoo.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_find_int_ellentree.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_find_int_michael.cpp" />\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_multilevelhashmap.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_feldmanhashmap.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_find_int_skip.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_find_int_split.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_find_int_std.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_find_string_cuckoo.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_find_string_ellentree.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_find_string_michael.cpp" />\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_multilevelhashmap.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_feldmanhashmap.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_find_string_skip.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_find_string_split.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_find_string_std.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_cuckoo.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_ellentree.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_michael.cpp" />\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_multilevelhashmap.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_feldmanhashmap.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_skip.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_split.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_std.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_striped.cpp">\r
<Filter>map_insfind_int</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_multilevelhashmap.cpp">\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_feldmanhashmap.cpp">\r
<Filter>map_find_int</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_multilevelhashmap.cpp">\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_feldmanhashmap.cpp">\r
<Filter>map_find_string</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_multilevelhashmap.cpp">\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_feldmanhashmap.cpp">\r
<Filter>map_insfind_int</Filter>\r
</ClCompile>\r
</ItemGroup>\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_cuckoo.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_ellentree.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_michael.cpp" />\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_multilevelhashmap.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_feldmanhashmap.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_skip.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_split.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_striped.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_cuckoo.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_ellentree.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_michael.cpp" />\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_multilevelhashmap.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_feldmanhashmap.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_skip.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_split.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_striped.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_striped.cpp">\r
<Filter>map_insdel_item_string</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_multilevelhashmap.cpp">\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_feldmanhashmap.cpp">\r
<Filter>map_insdel_item_int</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_multilevelhashmap.cpp">\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_feldmanhashmap.cpp">\r
<Filter>map_insdel_item_string</Filter>\r
</ClCompile>\r
</ItemGroup>\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_cuckoo.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_ellentree.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_michael.cpp" />\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_multilevelhashmap.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_feldmanhashmap.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_skip.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_split.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_striped.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_cuckoo.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_ellentree.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_michael.cpp" />\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_multilevelhashmap.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_feldmanhashmap.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_skip.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_split.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_std.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_cuckoo.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_ellentree.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_michael.cpp" />\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_multilevelhashmap.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_feldmanhashmap.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_skip.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_split.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_std.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_striped.cpp">\r
<Filter>map_insdel_string</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_multilevelhashmap.cpp">\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_feldmanhashmap.cpp">\r
<Filter>map_insdel_int</Filter>\r
</ClCompile>\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_std.cpp">\r
<Filter>map_insdel_int</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_multilevelhashmap.cpp">\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_feldmanhashmap.cpp">\r
<Filter>map_insdel_func</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_multilevelhashmap.cpp">\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_feldmanhashmap.cpp">\r
<Filter>map_insdel_string</Filter>\r
</ClCompile>\r
</ItemGroup>\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_cuckoo.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_ellentree.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_michael.cpp" />\r
- <ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_multilevelhashmap.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_feldmanhashmap.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_skip.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_split.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_std.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_delodd_cuckoo.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_delodd_ellentree.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_delodd_michael.cpp" />\r
- <ClCompile Include="..\..\..\tests\unit\set2\set_delodd_multilevelhashset.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\set2\set_delodd_feldmanhashset.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_delodd_skip.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_delodd_split.cpp" />\r
</ItemGroup>\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_cuckoo.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_ellentree.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_michael.cpp" />\r
- <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_multilevelhashset.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_feldmanhashset.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_skip.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_split.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_striped.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_cuckoo.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_ellentree.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_michael.cpp" />\r
- <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_multilevelhashset.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_feldmanhashset.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_skip.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_split.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_std.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_michael.cpp">\r
<Filter>set_insdel_func</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_multilevelhashset.cpp">\r
+ <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_feldmanhashset.cpp">\r
<Filter>set_insdel_func</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_multilevelhashset.cpp">\r
+ <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_feldmanhashset.cpp">\r
<Filter>set_insdel_string</Filter>\r
</ClCompile>\r
</ItemGroup>\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_cuckoo.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_ellentree.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_michael.cpp" />\r
- <ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_multilevelhashset.cpp" />\r
+ <ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_feldmanhashset.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_skip.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_split.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_std.cpp" />\r
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 \
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 \
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 \
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 \
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 \
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 \
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 \
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 \
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 \
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 \
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 \
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 \
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 \
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 \
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 \
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 \
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 \
CuckooProbesetSize=8\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=8\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=8\r
+FeldmanMapArrayBits=4\r
\r
[Map_find_string]\r
ThreadCount=2\r
CuckooProbesetSize=8\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=8\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=8\r
+FeldmanMapArrayBits=4\r
\r
[Map_InsDel_int]\r
InsertThreadCount=4\r
CuckooProbesetSize=8\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=8\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=8\r
+FeldmanMapArrayBits=4\r
\r
[Map_InsDel_func]\r
InsertThreadCount=4\r
CuckooProbesetSize=8\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=8\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=8\r
+FeldmanMapArrayBits=4\r
\r
[Map_InsDel_Item_int]\r
ThreadCount=4\r
CuckooProbesetSize=8\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=8\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=8\r
+FeldmanMapArrayBits=4\r
\r
[Map_InsDel_string]\r
InsertThreadCount=4\r
CuckooProbesetSize=8\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=8\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=8\r
+FeldmanMapArrayBits=4\r
\r
[Map_InsDel_Item_string]\r
ThreadCount=4\r
CuckooProbesetSize=8\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=8\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=8\r
+FeldmanMapArrayBits=4\r
\r
[Map_InsFind_int]\r
ThreadCount=0\r
CuckooProbesetSize=8\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=8\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=8\r
+FeldmanMapArrayBits=4\r
\r
[Map_InsDelFind]\r
InitialMapSize=50000\r
CuckooProbesetSize=8\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=8\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=8\r
+FeldmanMapArrayBits=4\r
\r
[Map_DelOdd]\r
MapSize=50000\r
CuckooProbesetSize=8\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=8\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=8\r
+FeldmanMapArrayBits=4\r
CuckooProbesetSize=16\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=8\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=8\r
+FeldmanMapArrayBits=4\r
\r
[Map_find_string]\r
ThreadCount=8\r
CuckooProbesetSize=16\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=8\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=8\r
+FeldmanMapArrayBits=4\r
\r
[Map_InsDel_int]\r
InsertThreadCount=4\r
CuckooProbesetSize=16\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=8\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=8\r
+FeldmanMapArrayBits=4\r
\r
[Map_InsDel_func]\r
InsertThreadCount=4\r
CuckooProbesetSize=16\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=8\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=8\r
+FeldmanMapArrayBits=4\r
\r
[Map_InsDel_Item_int]\r
ThreadCount=8\r
CuckooProbesetSize=16\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=8\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=8\r
+FeldmanMapArrayBits=4\r
\r
[Map_InsDel_string]\r
InsertThreadCount=4\r
CuckooProbesetSize=16\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=8\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=8\r
+FeldmanMapArrayBits=4\r
\r
[Map_InsDel_Item_string]\r
ThreadCount=8\r
CuckooProbesetSize=16\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=8\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=8\r
+FeldmanMapArrayBits=4\r
\r
[Map_InsFind_int]\r
ThreadCount=0\r
CuckooProbesetSize=16\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=8\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=8\r
+FeldmanMapArrayBits=4\r
\r
[Map_InsDelFind]\r
InitialMapSize=500000\r
CuckooProbesetSize=16\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=8\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=8\r
+FeldmanMapArrayBits=4\r
\r
[Map_DelOdd]\r
MapSize=500000\r
CuckooProbesetSize=16\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=8\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=8\r
+FeldmanMapArrayBits=4\r
CuckooProbesetSize=16\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=10\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=10\r
+FeldmanMapArrayBits=4\r
\r
[Map_find_string]\r
ThreadCount=8\r
CuckooProbesetSize=16\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=10\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=10\r
+FeldmanMapArrayBits=4\r
\r
[Map_InsDel_int]\r
InsertThreadCount=4\r
CuckooProbesetSize=16\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=10\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=10\r
+FeldmanMapArrayBits=4\r
\r
[Map_InsDel_func]\r
InsertThreadCount=4\r
CuckooProbesetSize=16\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=10\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=10\r
+FeldmanMapArrayBits=4\r
\r
[Map_InsDel_Item_int]\r
ThreadCount=8\r
CuckooProbesetSize=16\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=10\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=10\r
+FeldmanMapArrayBits=4\r
\r
[Map_InsDel_string]\r
InsertThreadCount=4\r
CuckooProbesetSize=16\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=10\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=10\r
+FeldmanMapArrayBits=4\r
\r
[Map_InsDel_Item_string]\r
ThreadCount=8\r
CuckooProbesetSize=16\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=10\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=10\r
+FeldmanMapArrayBits=4\r
\r
[Map_InsFind_int]\r
ThreadCount=0\r
CuckooProbesetSize=16\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=10\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=10\r
+FeldmanMapArrayBits=4\r
\r
[Map_InsDelFind]\r
InitialMapSize=500000\r
CuckooProbesetSize=16\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=10\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=10\r
+FeldmanMapArrayBits=4\r
\r
\r
[Map_DelOdd]\r
CuckooProbesetSize=16\r
# 0 - use default\r
CuckooProbesetThreshold=0 \r
-# *** MultiLevelHashMap properties\r
-MultiLevelMapHeadBits=10\r
-MultiLevelMapArrayBits=4\r
+# *** FeldmanHashMap properties\r
+FeldmanMapHeadBits=10\r
+FeldmanMapArrayBits=4\r
map/hdr_michael_map_lazy_rcu_shb.cpp\r
map/hdr_michael_map_lazy_rcu_sht.cpp\r
map/hdr_michael_map_lazy_nogc.cpp\r
- map/hdr_multilevel_hashmap_hp.cpp\r
- map/hdr_multilevel_hashmap_dhp.cpp\r
- map/hdr_multilevel_hashmap_rcu_gpb.cpp\r
- map/hdr_multilevel_hashmap_rcu_gpi.cpp\r
- map/hdr_multilevel_hashmap_rcu_gpt.cpp\r
- map/hdr_multilevel_hashmap_rcu_shb.cpp\r
- map/hdr_multilevel_hashmap_rcu_sht.cpp\r
+ map/hdr_feldman_hashmap_hp.cpp\r
+ map/hdr_feldman_hashmap_dhp.cpp\r
+ map/hdr_feldman_hashmap_rcu_gpb.cpp\r
+ map/hdr_feldman_hashmap_rcu_gpi.cpp\r
+ map/hdr_feldman_hashmap_rcu_gpt.cpp\r
+ map/hdr_feldman_hashmap_rcu_shb.cpp\r
+ map/hdr_feldman_hashmap_rcu_sht.cpp\r
map/hdr_refinable_hashmap_hashmap_std.cpp\r
map/hdr_refinable_hashmap_boost_list.cpp\r
map/hdr_refinable_hashmap_list.cpp\r
queue/hdr_vyukov_mpmc_cyclic.cpp)\r
\r
set(CDS_TESTHDR_SET\r
- set/hdr_intrusive_multilevel_hashset_hp.cpp\r
- set/hdr_intrusive_multilevel_hashset_dhp.cpp\r
- set/hdr_intrusive_multilevel_hashset_rcu_gpi.cpp\r
- set/hdr_intrusive_multilevel_hashset_rcu_gpb.cpp\r
- set/hdr_intrusive_multilevel_hashset_rcu_gpt.cpp\r
- set/hdr_intrusive_multilevel_hashset_rcu_shb.cpp\r
- set/hdr_intrusive_multilevel_hashset_rcu_sht.cpp\r
+ set/hdr_intrusive_feldman_hashset_hp.cpp\r
+ set/hdr_intrusive_feldman_hashset_dhp.cpp\r
+ set/hdr_intrusive_feldman_hashset_rcu_gpi.cpp\r
+ set/hdr_intrusive_feldman_hashset_rcu_gpb.cpp\r
+ set/hdr_intrusive_feldman_hashset_rcu_gpt.cpp\r
+ set/hdr_intrusive_feldman_hashset_rcu_shb.cpp\r
+ set/hdr_intrusive_feldman_hashset_rcu_sht.cpp\r
set/hdr_intrusive_refinable_hashset_avlset.cpp\r
set/hdr_intrusive_refinable_hashset_list.cpp\r
set/hdr_intrusive_refinable_hashset_set.cpp\r
set/hdr_michael_set_lazy_rcu_shb.cpp\r
set/hdr_michael_set_lazy_rcu_sht.cpp\r
set/hdr_michael_set_lazy_nogc.cpp\r
- set/hdr_multilevel_hashset_hp.cpp\r
- set/hdr_multilevel_hashset_dhp.cpp\r
- set/hdr_multilevel_hashset_rcu_gpb.cpp\r
- set/hdr_multilevel_hashset_rcu_gpi.cpp\r
- set/hdr_multilevel_hashset_rcu_gpt.cpp\r
- set/hdr_multilevel_hashset_rcu_shb.cpp\r
- set/hdr_multilevel_hashset_rcu_sht.cpp\r
+ set/hdr_feldman_hashset_hp.cpp\r
+ set/hdr_feldman_hashset_dhp.cpp\r
+ set/hdr_feldman_hashset_rcu_gpb.cpp\r
+ set/hdr_feldman_hashset_rcu_gpi.cpp\r
+ set/hdr_feldman_hashset_rcu_gpt.cpp\r
+ set/hdr_feldman_hashset_rcu_shb.cpp\r
+ set/hdr_feldman_hashset_rcu_sht.cpp\r
set/hdr_refinable_hashset_hashset_std.cpp\r
set/hdr_refinable_hashset_boost_flat_set.cpp\r
set/hdr_refinable_hashset_boost_list.cpp\r
--- /dev/null
+//$$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<size_t>()( n ), std::hash<size_t>()( ~n ));
+ }
+ hash128 operator()( hash128 const& n ) const
+ {
+ return hash128( std::hash<size_t>()( n.lo ), std::hash<size_t>()( ~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 <typename Map>
+ 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 <typename Map>
+ 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<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);
+
+ // 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<unsigned int>(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
--- /dev/null
+//$$CDS-header$$
+
+#include "map/hdr_feldman_hashmap.h"
+#include <cds/container/feldman_hashmap_dhp.h>
+#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<map_type>(4, 2);
+ }
+
+ void FeldmanHashMapHdrTest::dhp_stdhash()
+ {
+ struct traits : public cc::feldman_hashmap::traits {
+ typedef std::hash<size_t> hash;
+ };
+ typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type;
+
+ test_hp<map_type>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(4, 2);
+ }
+
+ void FeldmanHashMapHdrTest::dhp_stdhash_stat()
+ {
+ struct traits : public cc::feldman_hashmap::traits {
+ typedef std::hash<size_t> hash;
+ typedef cc::feldman_hashmap::stat<> stat;
+ };
+ typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type;
+ test_hp<map_type>(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<size_t>>
+ >::type
+ > map_type2;
+ test_hp<map_type2>(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<map_type>(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<map_type2>(4, 2);
+ }
+
+ void FeldmanHashMapHdrTest::dhp_nohash_5_3()
+ {
+ typedef cc::FeldmanHashMap< gc_type, size_t, Item > map_type;
+
+ test_hp<map_type>(5, 3);
+ }
+
+
+ void FeldmanHashMapHdrTest::dhp_stdhash_5_3()
+ {
+ struct traits : public cc::feldman_hashmap::traits {
+ typedef std::hash<size_t> hash;
+ };
+ typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type;
+
+ test_hp<map_type>(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<map_type>(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<map_type2>(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<size_t> hash;
+ };
+ typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type;
+ test_hp<map_type>(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<size_t>>
+ >::type
+ > map_type2;
+ test_hp<map_type2>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(4, 3);
+ }
+} // namespace map
+
+CPPUNIT_TEST_SUITE_REGISTRATION(map::FeldmanHashMapHdrTest);
--- /dev/null
+//$$CDS-header$$
+
+#include "map/hdr_feldman_hashmap.h"
+#include <cds/container/feldman_hashmap_hp.h>
+#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<map_type>(4, 2);
+ }
+
+ void FeldmanHashMapHdrTest::hp_stdhash()
+ {
+ struct traits : public cc::feldman_hashmap::traits {
+ typedef std::hash<size_t> hash;
+ };
+ typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type;
+
+ test_hp<map_type>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(4, 2);
+ }
+
+ void FeldmanHashMapHdrTest::hp_stdhash_stat()
+ {
+ struct traits : public cc::feldman_hashmap::traits {
+ typedef std::hash<size_t> hash;
+ typedef cc::feldman_hashmap::stat<> stat;
+ };
+ typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type;
+ test_hp<map_type>(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<size_t>>
+ >::type
+ > map_type2;
+ test_hp<map_type2>(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<map_type>(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<map_type2>(4, 2);
+ }
+
+ void FeldmanHashMapHdrTest::hp_nohash_5_3()
+ {
+ typedef cc::FeldmanHashMap< gc_type, size_t, Item > map_type;
+
+ test_hp<map_type>(5, 3);
+ }
+
+
+ void FeldmanHashMapHdrTest::hp_stdhash_5_3()
+ {
+ struct traits : public cc::feldman_hashmap::traits {
+ typedef std::hash<size_t> hash;
+ };
+ typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type;
+
+ test_hp<map_type>(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<map_type>(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<map_type2>(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<size_t> hash;
+ };
+ typedef cc::FeldmanHashMap< gc_type, size_t, Item, traits > map_type;
+ test_hp<map_type>(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<size_t>>
+ >::type
+ > map_type2;
+ test_hp<map_type2>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(4, 3);
+ }
+} // namespace map
+
+CPPUNIT_TEST_SUITE_REGISTRATION(map::FeldmanHashMapHdrTest);
--- /dev/null
+//$$CDS-header$$
+
+#include "map/hdr_feldman_hashmap.h"
+#include <cds/urcu/general_buffered.h>
+#include <cds/container/feldman_hashmap_rcu.h>
+#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<map_type>(4, 2);
+ }
+
+ void FeldmanHashMapHdrTest::rcu_gpb_stdhash()
+ {
+ struct traits : public cc::feldman_hashmap::traits {
+ typedef std::hash<size_t> hash;
+ };
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type;
+
+ test_rcu<map_type>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(4, 2);
+ }
+
+ void FeldmanHashMapHdrTest::rcu_gpb_stdhash_stat()
+ {
+ struct traits : public cc::feldman_hashmap::traits {
+ typedef std::hash<size_t> hash;
+ typedef cc::feldman_hashmap::stat<> stat;
+ };
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type;
+ test_rcu<map_type>(4, 2);
+
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item,
+ typename cc::feldman_hashmap::make_traits<
+ co::stat< cc::feldman_hashmap::stat<>>
+ ,co::hash<std::hash<size_t>>
+ >::type
+ > map_type2;
+ test_rcu<map_type2>(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<map_type>(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<map_type2>(4, 2);
+ }
+
+ void FeldmanHashMapHdrTest::rcu_gpb_nohash_5_3()
+ {
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item > map_type;
+
+ test_rcu<map_type>(5, 3);
+ }
+
+ void FeldmanHashMapHdrTest::rcu_gpb_stdhash_5_3()
+ {
+ struct traits : public cc::feldman_hashmap::traits {
+ typedef std::hash<size_t> hash;
+ };
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type;
+
+ test_rcu<map_type>(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<map_type>(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<map_type2>(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<size_t> hash;
+ };
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type;
+ test_rcu<map_type>(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<size_t>>
+ >::type
+ > map_type2;
+ test_rcu<map_type2>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(4, 3);
+ }
+
+} // namespace map
--- /dev/null
+//$$CDS-header$$
+
+#include "map/hdr_feldman_hashmap.h"
+#include <cds/urcu/general_instant.h>
+#include <cds/container/feldman_hashmap_rcu.h>
+#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<map_type>(4, 2);
+ }
+
+ void FeldmanHashMapHdrTest::rcu_gpi_stdhash()
+ {
+ struct traits : public cc::feldman_hashmap::traits {
+ typedef std::hash<size_t> hash;
+ };
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type;
+
+ test_rcu<map_type>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(4, 2);
+ }
+
+ void FeldmanHashMapHdrTest::rcu_gpi_stdhash_stat()
+ {
+ struct traits : public cc::feldman_hashmap::traits {
+ typedef std::hash<size_t> hash;
+ typedef cc::feldman_hashmap::stat<> stat;
+ };
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type;
+ test_rcu<map_type>(4, 2);
+
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item,
+ typename cc::feldman_hashmap::make_traits<
+ co::stat< cc::feldman_hashmap::stat<>>
+ ,co::hash<std::hash<size_t>>
+ >::type
+ > map_type2;
+ test_rcu<map_type2>(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<map_type>(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<map_type2>(4, 2);
+ }
+
+ void FeldmanHashMapHdrTest::rcu_gpi_nohash_5_3()
+ {
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item > map_type;
+
+ test_rcu<map_type>(5, 3);
+ }
+
+ void FeldmanHashMapHdrTest::rcu_gpi_stdhash_5_3()
+ {
+ struct traits : public cc::feldman_hashmap::traits {
+ typedef std::hash<size_t> hash;
+ };
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type;
+
+ test_rcu<map_type>(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<map_type>(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<map_type2>(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<size_t> hash;
+ };
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type;
+ test_rcu<map_type>(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<size_t>>
+ >::type
+ > map_type2;
+ test_rcu<map_type2>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(4, 3);
+ }
+
+} // namespace map
--- /dev/null
+//$$CDS-header$$
+
+#include "map/hdr_feldman_hashmap.h"
+#include <cds/urcu/general_threaded.h>
+#include <cds/container/feldman_hashmap_rcu.h>
+#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<map_type>(4, 2);
+ }
+
+ void FeldmanHashMapHdrTest::rcu_gpt_stdhash()
+ {
+ struct traits : public cc::feldman_hashmap::traits {
+ typedef std::hash<size_t> hash;
+ };
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type;
+
+ test_rcu<map_type>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(4, 2);
+ }
+
+ void FeldmanHashMapHdrTest::rcu_gpt_stdhash_stat()
+ {
+ struct traits : public cc::feldman_hashmap::traits {
+ typedef std::hash<size_t> hash;
+ typedef cc::feldman_hashmap::stat<> stat;
+ };
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type;
+ test_rcu<map_type>(4, 2);
+
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item,
+ typename cc::feldman_hashmap::make_traits<
+ co::stat< cc::feldman_hashmap::stat<>>
+ ,co::hash<std::hash<size_t>>
+ >::type
+ > map_type2;
+ test_rcu<map_type2>(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<map_type>(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<map_type2>(4, 2);
+ }
+
+ void FeldmanHashMapHdrTest::rcu_gpt_nohash_5_3()
+ {
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item > map_type;
+
+ test_rcu<map_type>(5, 3);
+ }
+
+ void FeldmanHashMapHdrTest::rcu_gpt_stdhash_5_3()
+ {
+ struct traits : public cc::feldman_hashmap::traits {
+ typedef std::hash<size_t> hash;
+ };
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type;
+
+ test_rcu<map_type>(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<map_type>(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<map_type2>(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<size_t> hash;
+ };
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type;
+ test_rcu<map_type>(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<size_t>>
+ >::type
+ > map_type2;
+ test_rcu<map_type2>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(4, 3);
+ }
+
+} // namespace map
--- /dev/null
+//$$CDS-header$$
+
+#include "map/hdr_feldman_hashmap.h"
+#include <cds/urcu/signal_buffered.h>
+#include <cds/container/feldman_hashmap_rcu.h>
+#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<map_type>(4, 2);
+#endif
+ }
+
+ void FeldmanHashMapHdrTest::rcu_shb_stdhash()
+ {
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ struct traits : public cc::feldman_hashmap::traits {
+ typedef std::hash<size_t> hash;
+ };
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type;
+
+ test_rcu<map_type>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(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<size_t> hash;
+ typedef cc::feldman_hashmap::stat<> stat;
+ };
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type;
+ test_rcu<map_type>(4, 2);
+
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item,
+ typename cc::feldman_hashmap::make_traits<
+ co::stat< cc::feldman_hashmap::stat<>>
+ ,co::hash<std::hash<size_t>>
+ >::type
+ > map_type2;
+ test_rcu<map_type2>(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<map_type>(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<map_type2>(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<map_type>(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<size_t> hash;
+ };
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type;
+
+ test_rcu<map_type>(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<map_type>(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<map_type2>(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<size_t> hash;
+ };
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type;
+ test_rcu<map_type>(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<size_t>>
+ >::type
+ > map_type2;
+ test_rcu<map_type2>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(4, 3);
+#endif
+ }
+
+} // namespace map
--- /dev/null
+//$$CDS-header$$
+
+#include "map/hdr_feldman_hashmap.h"
+#include <cds/urcu/signal_threaded.h>
+#include <cds/container/feldman_hashmap_rcu.h>
+#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<map_type>(4, 2);
+#endif
+ }
+
+ void FeldmanHashMapHdrTest::rcu_sht_stdhash()
+ {
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ struct traits : public cc::feldman_hashmap::traits {
+ typedef std::hash<size_t> hash;
+ };
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type;
+
+ test_rcu<map_type>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(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<size_t> hash;
+ typedef cc::feldman_hashmap::stat<> stat;
+ };
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type;
+ test_rcu<map_type>(4, 2);
+
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item,
+ typename cc::feldman_hashmap::make_traits<
+ co::stat< cc::feldman_hashmap::stat<>>
+ ,co::hash<std::hash<size_t>>
+ >::type
+ > map_type2;
+ test_rcu<map_type2>(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<map_type>(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<map_type2>(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<map_type>(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<size_t> hash;
+ };
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type;
+
+ test_rcu<map_type>(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<map_type>(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<map_type2>(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<size_t> hash;
+ };
+ typedef cc::FeldmanHashMap< rcu_type, size_t, Item, traits > map_type;
+ test_rcu<map_type>(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<size_t>>
+ >::type
+ > map_type2;
+ test_rcu<map_type2>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(4, 3);
+#endif
+ }
+
+} // namespace map
+++ /dev/null
-//$$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<size_t>()( n ), std::hash<size_t>()( ~n ));
- }
- hash128 operator()( hash128 const& n ) const
- {
- return hash128( std::hash<size_t>()( n.lo ), std::hash<size_t>()( ~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 <typename Map>
- 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 <typename Map>
- 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<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);
-
- // 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<unsigned int>(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
+++ /dev/null
-//$$CDS-header$$
-
-#include "map/hdr_multilevel_hashmap.h"
-#include <cds/container/multilevel_hashmap_dhp.h>
-#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<map_type>(4, 2);
- }
-
- void MultiLevelHashMapHdrTest::dhp_stdhash()
- {
- struct traits : public cc::multilevel_hashmap::traits {
- typedef std::hash<size_t> hash;
- };
- typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type;
-
- test_hp<map_type>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(4, 2);
- }
-
- void MultiLevelHashMapHdrTest::dhp_stdhash_stat()
- {
- struct traits : public cc::multilevel_hashmap::traits {
- typedef std::hash<size_t> hash;
- typedef cc::multilevel_hashmap::stat<> stat;
- };
- typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type;
- test_hp<map_type>(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<size_t>>
- >::type
- > map_type2;
- test_hp<map_type2>(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<map_type>(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<map_type2>(4, 2);
- }
-
- void MultiLevelHashMapHdrTest::dhp_nohash_5_3()
- {
- typedef cc::MultiLevelHashMap< gc_type, size_t, Item > map_type;
-
- test_hp<map_type>(5, 3);
- }
-
-
- void MultiLevelHashMapHdrTest::dhp_stdhash_5_3()
- {
- struct traits : public cc::multilevel_hashmap::traits {
- typedef std::hash<size_t> hash;
- };
- typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type;
-
- test_hp<map_type>(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<map_type>(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<map_type2>(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<size_t> hash;
- };
- typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type;
- test_hp<map_type>(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<size_t>>
- >::type
- > map_type2;
- test_hp<map_type2>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(4, 3);
- }
-} // namespace map
-
-CPPUNIT_TEST_SUITE_REGISTRATION(map::MultiLevelHashMapHdrTest);
+++ /dev/null
-//$$CDS-header$$
-
-#include "map/hdr_multilevel_hashmap.h"
-#include <cds/container/multilevel_hashmap_hp.h>
-#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<map_type>(4, 2);
- }
-
- void MultiLevelHashMapHdrTest::hp_stdhash()
- {
- struct traits : public cc::multilevel_hashmap::traits {
- typedef std::hash<size_t> hash;
- };
- typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type;
-
- test_hp<map_type>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(4, 2);
- }
-
- void MultiLevelHashMapHdrTest::hp_stdhash_stat()
- {
- struct traits : public cc::multilevel_hashmap::traits {
- typedef std::hash<size_t> hash;
- typedef cc::multilevel_hashmap::stat<> stat;
- };
- typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type;
- test_hp<map_type>(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<size_t>>
- >::type
- > map_type2;
- test_hp<map_type2>(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<map_type>(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<map_type2>(4, 2);
- }
-
- void MultiLevelHashMapHdrTest::hp_nohash_5_3()
- {
- typedef cc::MultiLevelHashMap< gc_type, size_t, Item > map_type;
-
- test_hp<map_type>(5, 3);
- }
-
-
- void MultiLevelHashMapHdrTest::hp_stdhash_5_3()
- {
- struct traits : public cc::multilevel_hashmap::traits {
- typedef std::hash<size_t> hash;
- };
- typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type;
-
- test_hp<map_type>(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<map_type>(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<map_type2>(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<size_t> hash;
- };
- typedef cc::MultiLevelHashMap< gc_type, size_t, Item, traits > map_type;
- test_hp<map_type>(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<size_t>>
- >::type
- > map_type2;
- test_hp<map_type2>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(4, 3);
- }
-} // namespace map
-
-CPPUNIT_TEST_SUITE_REGISTRATION(map::MultiLevelHashMapHdrTest);
+++ /dev/null
-//$$CDS-header$$
-
-#include "map/hdr_multilevel_hashmap.h"
-#include <cds/urcu/general_buffered.h>
-#include <cds/container/multilevel_hashmap_rcu.h>
-#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<map_type>(4, 2);
- }
-
- void MultiLevelHashMapHdrTest::rcu_gpb_stdhash()
- {
- struct traits : public cc::multilevel_hashmap::traits {
- typedef std::hash<size_t> hash;
- };
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type;
-
- test_rcu<map_type>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(4, 2);
- }
-
- void MultiLevelHashMapHdrTest::rcu_gpb_stdhash_stat()
- {
- struct traits : public cc::multilevel_hashmap::traits {
- typedef std::hash<size_t> hash;
- typedef cc::multilevel_hashmap::stat<> stat;
- };
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type;
- test_rcu<map_type>(4, 2);
-
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item,
- typename cc::multilevel_hashmap::make_traits<
- co::stat< cc::multilevel_hashmap::stat<>>
- ,co::hash<std::hash<size_t>>
- >::type
- > map_type2;
- test_rcu<map_type2>(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<map_type>(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<map_type2>(4, 2);
- }
-
- void MultiLevelHashMapHdrTest::rcu_gpb_nohash_5_3()
- {
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item > map_type;
-
- test_rcu<map_type>(5, 3);
- }
-
- void MultiLevelHashMapHdrTest::rcu_gpb_stdhash_5_3()
- {
- struct traits : public cc::multilevel_hashmap::traits {
- typedef std::hash<size_t> hash;
- };
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type;
-
- test_rcu<map_type>(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<map_type>(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<map_type2>(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<size_t> hash;
- };
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type;
- test_rcu<map_type>(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<size_t>>
- >::type
- > map_type2;
- test_rcu<map_type2>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(4, 3);
- }
-
-} // namespace map
+++ /dev/null
-//$$CDS-header$$
-
-#include "map/hdr_multilevel_hashmap.h"
-#include <cds/urcu/general_instant.h>
-#include <cds/container/multilevel_hashmap_rcu.h>
-#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<map_type>(4, 2);
- }
-
- void MultiLevelHashMapHdrTest::rcu_gpi_stdhash()
- {
- struct traits : public cc::multilevel_hashmap::traits {
- typedef std::hash<size_t> hash;
- };
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type;
-
- test_rcu<map_type>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(4, 2);
- }
-
- void MultiLevelHashMapHdrTest::rcu_gpi_stdhash_stat()
- {
- struct traits : public cc::multilevel_hashmap::traits {
- typedef std::hash<size_t> hash;
- typedef cc::multilevel_hashmap::stat<> stat;
- };
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type;
- test_rcu<map_type>(4, 2);
-
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item,
- typename cc::multilevel_hashmap::make_traits<
- co::stat< cc::multilevel_hashmap::stat<>>
- ,co::hash<std::hash<size_t>>
- >::type
- > map_type2;
- test_rcu<map_type2>(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<map_type>(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<map_type2>(4, 2);
- }
-
- void MultiLevelHashMapHdrTest::rcu_gpi_nohash_5_3()
- {
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item > map_type;
-
- test_rcu<map_type>(5, 3);
- }
-
- void MultiLevelHashMapHdrTest::rcu_gpi_stdhash_5_3()
- {
- struct traits : public cc::multilevel_hashmap::traits {
- typedef std::hash<size_t> hash;
- };
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type;
-
- test_rcu<map_type>(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<map_type>(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<map_type2>(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<size_t> hash;
- };
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type;
- test_rcu<map_type>(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<size_t>>
- >::type
- > map_type2;
- test_rcu<map_type2>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(4, 3);
- }
-
-} // namespace map
+++ /dev/null
-//$$CDS-header$$
-
-#include "map/hdr_multilevel_hashmap.h"
-#include <cds/urcu/general_threaded.h>
-#include <cds/container/multilevel_hashmap_rcu.h>
-#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<map_type>(4, 2);
- }
-
- void MultiLevelHashMapHdrTest::rcu_gpt_stdhash()
- {
- struct traits : public cc::multilevel_hashmap::traits {
- typedef std::hash<size_t> hash;
- };
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type;
-
- test_rcu<map_type>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(4, 2);
- }
-
- void MultiLevelHashMapHdrTest::rcu_gpt_stdhash_stat()
- {
- struct traits : public cc::multilevel_hashmap::traits {
- typedef std::hash<size_t> hash;
- typedef cc::multilevel_hashmap::stat<> stat;
- };
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type;
- test_rcu<map_type>(4, 2);
-
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item,
- typename cc::multilevel_hashmap::make_traits<
- co::stat< cc::multilevel_hashmap::stat<>>
- ,co::hash<std::hash<size_t>>
- >::type
- > map_type2;
- test_rcu<map_type2>(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<map_type>(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<map_type2>(4, 2);
- }
-
- void MultiLevelHashMapHdrTest::rcu_gpt_nohash_5_3()
- {
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item > map_type;
-
- test_rcu<map_type>(5, 3);
- }
-
- void MultiLevelHashMapHdrTest::rcu_gpt_stdhash_5_3()
- {
- struct traits : public cc::multilevel_hashmap::traits {
- typedef std::hash<size_t> hash;
- };
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type;
-
- test_rcu<map_type>(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<map_type>(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<map_type2>(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<size_t> hash;
- };
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type;
- test_rcu<map_type>(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<size_t>>
- >::type
- > map_type2;
- test_rcu<map_type2>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(4, 3);
- }
-
-} // namespace map
+++ /dev/null
-//$$CDS-header$$
-
-#include "map/hdr_multilevel_hashmap.h"
-#include <cds/urcu/signal_buffered.h>
-#include <cds/container/multilevel_hashmap_rcu.h>
-#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<map_type>(4, 2);
-#endif
- }
-
- void MultiLevelHashMapHdrTest::rcu_shb_stdhash()
- {
-#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
- struct traits : public cc::multilevel_hashmap::traits {
- typedef std::hash<size_t> hash;
- };
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type;
-
- test_rcu<map_type>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(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<size_t> hash;
- typedef cc::multilevel_hashmap::stat<> stat;
- };
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type;
- test_rcu<map_type>(4, 2);
-
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item,
- typename cc::multilevel_hashmap::make_traits<
- co::stat< cc::multilevel_hashmap::stat<>>
- ,co::hash<std::hash<size_t>>
- >::type
- > map_type2;
- test_rcu<map_type2>(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<map_type>(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<map_type2>(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<map_type>(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<size_t> hash;
- };
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type;
-
- test_rcu<map_type>(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<map_type>(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<map_type2>(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<size_t> hash;
- };
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type;
- test_rcu<map_type>(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<size_t>>
- >::type
- > map_type2;
- test_rcu<map_type2>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(4, 3);
-#endif
- }
-
-} // namespace map
+++ /dev/null
-//$$CDS-header$$
-
-#include "map/hdr_multilevel_hashmap.h"
-#include <cds/urcu/signal_threaded.h>
-#include <cds/container/multilevel_hashmap_rcu.h>
-#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<map_type>(4, 2);
-#endif
- }
-
- void MultiLevelHashMapHdrTest::rcu_sht_stdhash()
- {
-#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
- struct traits : public cc::multilevel_hashmap::traits {
- typedef std::hash<size_t> hash;
- };
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type;
-
- test_rcu<map_type>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(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<size_t> hash;
- typedef cc::multilevel_hashmap::stat<> stat;
- };
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type;
- test_rcu<map_type>(4, 2);
-
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item,
- typename cc::multilevel_hashmap::make_traits<
- co::stat< cc::multilevel_hashmap::stat<>>
- ,co::hash<std::hash<size_t>>
- >::type
- > map_type2;
- test_rcu<map_type2>(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<map_type>(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<map_type2>(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<map_type>(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<size_t> hash;
- };
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type;
-
- test_rcu<map_type>(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<map_type>(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<map_type2>(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<size_t> hash;
- };
- typedef cc::MultiLevelHashMap< rcu_type, size_t, Item, traits > map_type;
- test_rcu<map_type>(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<size_t>>
- >::type
- > map_type2;
- test_rcu<map_type2>(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<map_type>(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<map_type2>(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<map_type>(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<map_type2>(4, 3);
-#endif
- }
-
-} // namespace map
--- /dev/null
+//$$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 <typename Hash>
+ struct Arg
+ {
+ size_t key;
+ Hash hash;
+
+ Arg( size_t k, Hash const& h )
+ : key( k )
+ , hash( h )
+ {}
+ };
+
+ template <typename Hash>
+ 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<Hash> 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 <typename Hash>
+ struct get_hash
+ {
+ Hash const& operator()( Item<Hash> const& i ) const
+ {
+ return i.hash;
+ }
+ };
+
+ template <typename Key>
+ struct get_key
+ {
+ Key operator()(Item<Key> const& i)const
+ {
+ return i.hash;
+ }
+ };
+
+ template <typename Key>
+ 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<size_t>()( n ), std::hash<size_t>()( ~n ));
+ }
+ hash128 operator()( hash128 const& n ) const
+ {
+ return hash128( std::hash<size_t>()( n.lo ), std::hash<size_t>()( ~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 <typename Set, typename Hasher>
+ 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<hash_type> 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<bool, bool> 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<bool, bool> 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 <typename Set, typename Hasher>
+ 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<hash_type> 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<bool, bool> 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<bool, bool> 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
--- /dev/null
+//$$CDS-header$$
+
+#include "set/hdr_feldman_hashset.h"
+#include <cds/container/feldman_hashset_dhp.h>
+#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<key_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< gc_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_hp<set_type, nohash<key_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ gc_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ >::type
+ > set_type2;
+ test_hp<set_type2, nohash<key_type>>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::dhp_stdhash()
+ {
+ typedef size_t hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_hp<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ >::type
+ > set_type2;
+ test_hp<set_type2, std::hash<hash_type>>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::dhp_hash128()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef hash128::less less;
+ };
+ typedef cc::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
+ test_hp<set_type, hash128::make>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , co::less< hash_type::less >
+ >::type
+ > set_type2;
+ test_hp<set_type2, hash128::make>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::dhp_nohash_stat()
+ {
+ typedef size_t key_type;
+
+ struct traits : public cc::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< gc_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_hp<set_type, nohash<key_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ gc_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ , co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_hp<set_type2, nohash<key_type>>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::dhp_stdhash_stat()
+ {
+ typedef size_t hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_hp<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_hp<set_type2, std::hash<hash_type>>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::dhp_hash128_stat()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef hash128::cmp compare;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_hp<set_type, hash_type::make>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ ,co::compare< hash128::cmp >
+ >::type
+ > set_type2;
+ test_hp<set_type2, hash_type::make>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::dhp_nohash_5_3()
+ {
+ typedef size_t key_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< gc_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_hp<set_type, nohash<key_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ gc_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ >::type
+ > set_type2;
+ test_hp<set_type2, nohash<key_type>>(5, 3);
+ }
+
+ void FeldmanHashSetHdrTest::dhp_stdhash_5_3()
+ {
+ typedef size_t hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_hp<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ >::type
+ > set_type2;
+ test_hp<set_type2, std::hash<hash_type>>(5, 3);
+ }
+
+ void FeldmanHashSetHdrTest::dhp_hash128_4_3()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef co::v::sequential_consistent memory_model;
+ };
+ typedef cc::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_hp<set_type, hash128::make >(4, 3);
+
+ typedef cc::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::memory_model< co::v::sequential_consistent >
+ >::type
+ > set_type2;
+ test_hp<set_type2, hash128::make >(4, 3);
+ }
+
+ void FeldmanHashSetHdrTest::dhp_nohash_5_3_stat()
+ {
+ typedef size_t key_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< gc_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_hp<set_type, nohash<key_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ gc_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_hp<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_hp<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_hp<set_type2, std::hash<hash_type>>(5, 3);
+ }
+
+ void FeldmanHashSetHdrTest::dhp_hash128_4_3_stat()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ typedef hash128::less less;
+ typedef hash128::cmp compare;
+ };
+ typedef cc::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_hp<set_type, hash_type::make>(4, 3);
+
+ typedef cc::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , co::stat< cc::feldman_hashset::stat<>>
+ , co::less< hash_type::less >
+ , co::compare< hash128::cmp >
+ >::type
+ > set_type2;
+ test_hp<set_type2, hash_type::make>(4, 3);
+ }
+
+
+} // namespace set
--- /dev/null
+//$$CDS-header$$
+
+#include "set/hdr_feldman_hashset.h"
+#include <cds/container/feldman_hashset_hp.h>
+#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<key_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< gc_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_hp<set_type, nohash<key_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ gc_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ >::type
+ > set_type2;
+ test_hp<set_type2, nohash<key_type>>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::hp_stdhash()
+ {
+ typedef size_t hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_hp<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ >::type
+ > set_type2;
+ test_hp<set_type2, std::hash<hash_type>>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::hp_hash128()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef hash128::less less;
+ };
+ typedef cc::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
+ test_hp<set_type, hash128::make>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , co::less< hash_type::less >
+ >::type
+ > set_type2;
+ test_hp<set_type2, hash128::make>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::hp_nohash_stat()
+ {
+ typedef size_t key_type;
+
+ struct traits : public cc::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< gc_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_hp<set_type, nohash<key_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ gc_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ , co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_hp<set_type2, nohash<key_type>>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::hp_stdhash_stat()
+ {
+ typedef size_t hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_hp<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_hp<set_type2, std::hash<hash_type>>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::hp_hash128_stat()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef hash128::cmp compare;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_hp<set_type, hash_type::make>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ ,co::compare< hash128::cmp >
+ >::type
+ > set_type2;
+ test_hp<set_type2, hash_type::make>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::hp_nohash_5_3()
+ {
+ typedef size_t key_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< gc_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_hp<set_type, nohash<key_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ gc_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ >::type
+ > set_type2;
+ test_hp<set_type2, nohash<key_type>>(5, 3);
+ }
+
+ void FeldmanHashSetHdrTest::hp_stdhash_5_3()
+ {
+ typedef size_t hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_hp<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ >::type
+ > set_type2;
+ test_hp<set_type2, std::hash<hash_type>>(5, 3);
+ }
+
+ void FeldmanHashSetHdrTest::hp_hash128_4_3()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef co::v::sequential_consistent memory_model;
+ };
+ typedef cc::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_hp<set_type, hash128::make >(4, 3);
+
+ typedef cc::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::memory_model< co::v::sequential_consistent >
+ >::type
+ > set_type2;
+ test_hp<set_type2, hash128::make >(4, 3);
+ }
+
+ void FeldmanHashSetHdrTest::hp_nohash_5_3_stat()
+ {
+ typedef size_t key_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< gc_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_hp<set_type, nohash<key_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ gc_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_hp<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_hp<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_hp<set_type2, std::hash<hash_type>>(5, 3);
+ }
+
+ void FeldmanHashSetHdrTest::hp_hash128_4_3_stat()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ typedef hash128::less less;
+ typedef hash128::cmp compare;
+ };
+ typedef cc::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_hp<set_type, hash_type::make>(4, 3);
+
+ typedef cc::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , co::stat< cc::feldman_hashset::stat<>>
+ , co::less< hash_type::less >
+ , co::compare< hash128::cmp >
+ >::type
+ > set_type2;
+ test_hp<set_type2, hash_type::make>(4, 3);
+ }
+
+
+} // namespace set
+
+CPPUNIT_TEST_SUITE_REGISTRATION(set::FeldmanHashSetHdrTest);
--- /dev/null
+//$$CDS-header$$
+
+#include "set/hdr_feldman_hashset.h"
+#include <cds/urcu/general_buffered.h>
+#include <cds/container/feldman_hashset_rcu.h>
+#include "unit/print_feldman_hashset_stat.h"
+
+namespace set {
+ namespace {
+ typedef cds::urcu::gc<cds::urcu::general_buffered<>> rcu_type;
+ } // namespace
+
+ void FeldmanHashSetHdrTest::rcu_gpb_nohash()
+ {
+ typedef size_t key_type;
+
+ struct traits : public cc::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_rcu<set_type, nohash<key_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::rcu_gpb_stdhash()
+ {
+ typedef size_t hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::rcu_gpb_hash128()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef hash128::less less;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
+ test_rcu<set_type, hash128::make>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , co::less< hash_type::less >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash128::make>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::rcu_gpb_nohash_stat()
+ {
+ typedef size_t key_type;
+
+ struct traits : public cc::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_rcu<set_type, nohash<key_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ , co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::rcu_gpb_stdhash_stat()
+ {
+ typedef size_t hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::rcu_gpb_hash128_stat()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef hash128::cmp compare;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash_type::make>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ ,co::compare< hash128::cmp >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash_type::make>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::rcu_gpb_nohash_5_3()
+ {
+ typedef size_t key_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, nohash<key_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(5, 3);
+ }
+
+ void FeldmanHashSetHdrTest::rcu_gpb_hash128_4_3()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef co::v::sequential_consistent memory_model;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash128::make >(4, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::memory_model< co::v::sequential_consistent >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash128::make >(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<key_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, nohash<key_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ typedef hash128::less less;
+ typedef hash128::cmp compare;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash_type::make>(4, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , co::stat< cc::feldman_hashset::stat<>>
+ , co::less< hash_type::less >
+ , co::compare< hash128::cmp >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash_type::make>(4, 3);
+ }
+
+
+} // namespace set
--- /dev/null
+//$$CDS-header$$
+
+#include "set/hdr_feldman_hashset.h"
+#include <cds/urcu/general_instant.h>
+#include <cds/container/feldman_hashset_rcu.h>
+#include "unit/print_feldman_hashset_stat.h"
+
+namespace set {
+ namespace {
+ typedef cds::urcu::gc<cds::urcu::general_instant<>> rcu_type;
+ } // namespace
+
+ void FeldmanHashSetHdrTest::rcu_gpi_nohash()
+ {
+ typedef size_t key_type;
+
+ struct traits : public cc::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_rcu<set_type, nohash<key_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::rcu_gpi_stdhash()
+ {
+ typedef size_t hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::rcu_gpi_hash128()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef hash128::less less;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
+ test_rcu<set_type, hash128::make>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , co::less< hash_type::less >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash128::make>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::rcu_gpi_nohash_stat()
+ {
+ typedef size_t key_type;
+
+ struct traits : public cc::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_rcu<set_type, nohash<key_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ , co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::rcu_gpi_stdhash_stat()
+ {
+ typedef size_t hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::rcu_gpi_hash128_stat()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef hash128::cmp compare;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash_type::make>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ ,co::compare< hash128::cmp >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash_type::make>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::rcu_gpi_nohash_5_3()
+ {
+ typedef size_t key_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, nohash<key_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(5, 3);
+ }
+
+ void FeldmanHashSetHdrTest::rcu_gpi_hash128_4_3()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef co::v::sequential_consistent memory_model;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash128::make >(4, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::memory_model< co::v::sequential_consistent >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash128::make >(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<key_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, nohash<key_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ typedef hash128::less less;
+ typedef hash128::cmp compare;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash_type::make>(4, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , co::stat< cc::feldman_hashset::stat<>>
+ , co::less< hash_type::less >
+ , co::compare< hash128::cmp >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash_type::make>(4, 3);
+ }
+
+
+} // namespace set
--- /dev/null
+//$$CDS-header$$
+
+#include "set/hdr_feldman_hashset.h"
+#include <cds/urcu/general_threaded.h>
+#include <cds/container/feldman_hashset_rcu.h>
+#include "unit/print_feldman_hashset_stat.h"
+
+namespace set {
+ namespace {
+ typedef cds::urcu::gc<cds::urcu::general_threaded<>> rcu_type;
+ } // namespace
+
+ void FeldmanHashSetHdrTest::rcu_gpt_nohash()
+ {
+ typedef size_t key_type;
+
+ struct traits : public cc::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_rcu<set_type, nohash<key_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::rcu_gpt_stdhash()
+ {
+ typedef size_t hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::rcu_gpt_hash128()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef hash128::less less;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
+ test_rcu<set_type, hash128::make>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , co::less< hash_type::less >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash128::make>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::rcu_gpt_nohash_stat()
+ {
+ typedef size_t key_type;
+
+ struct traits : public cc::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_rcu<set_type, nohash<key_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ , co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::rcu_gpt_stdhash_stat()
+ {
+ typedef size_t hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::rcu_gpt_hash128_stat()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef hash128::cmp compare;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash_type::make>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ ,co::compare< hash128::cmp >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash_type::make>(4, 2);
+ }
+
+ void FeldmanHashSetHdrTest::rcu_gpt_nohash_5_3()
+ {
+ typedef size_t key_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, nohash<key_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(5, 3);
+ }
+
+ void FeldmanHashSetHdrTest::rcu_gpt_hash128_4_3()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public cc::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef co::v::sequential_consistent memory_model;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash128::make >(4, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::memory_model< co::v::sequential_consistent >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash128::make >(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<key_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, nohash<key_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ typedef hash128::less less;
+ typedef hash128::cmp compare;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash_type::make>(4, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , co::stat< cc::feldman_hashset::stat<>>
+ , co::less< hash_type::less >
+ , co::compare< hash128::cmp >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash_type::make>(4, 3);
+ }
+
+
+} // namespace set
--- /dev/null
+//$$CDS-header$$
+
+#include "set/hdr_feldman_hashset.h"
+#include <cds/urcu/signal_buffered.h>
+#include <cds/container/feldman_hashset_rcu.h>
+#include "unit/print_feldman_hashset_stat.h"
+
+namespace set {
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ namespace {
+ typedef cds::urcu::gc<cds::urcu::signal_buffered<>> 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<key_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_rcu<set_type, nohash<key_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
+ typedef hash128::less less;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
+ test_rcu<set_type, hash128::make>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , co::less< hash_type::less >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash128::make>(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<key_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_rcu<set_type, nohash<key_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ , co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
+ typedef hash128::cmp compare;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash_type::make>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ ,co::compare< hash128::cmp >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash_type::make>(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<key_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, nohash<key_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
+ typedef co::v::sequential_consistent memory_model;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash128::make >(4, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::memory_model< co::v::sequential_consistent >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash128::make >(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<key_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, nohash<key_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ typedef hash128::less less;
+ typedef hash128::cmp compare;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash_type::make>(4, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , co::stat< cc::feldman_hashset::stat<>>
+ , co::less< hash_type::less >
+ , co::compare< hash128::cmp >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash_type::make>(4, 3);
+#endif
+ }
+} // namespace set
--- /dev/null
+//$$CDS-header$$
+
+#include "set/hdr_feldman_hashset.h"
+#include <cds/urcu/signal_threaded.h>
+#include <cds/container/feldman_hashset_rcu.h>
+#include "unit/print_feldman_hashset_stat.h"
+
+namespace set {
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ namespace {
+ typedef cds::urcu::gc<cds::urcu::signal_threaded<>> 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<key_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_rcu<set_type, nohash<key_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
+ typedef hash128::less less;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
+ test_rcu<set_type, hash128::make>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , co::less< hash_type::less >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash128::make>(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<key_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_rcu<set_type, nohash<key_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ , co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
+ typedef hash128::cmp compare;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash_type::make>(4, 2);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ ,co::compare< hash128::cmp >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash_type::make>(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<key_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, nohash<key_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
+ typedef co::v::sequential_consistent memory_model;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash128::make >(4, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::memory_model< co::v::sequential_consistent >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash128::make >(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<key_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, nohash<key_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_key<key_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ ,co::stat< cc::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
+ typedef cc::feldman_hashset::stat<> stat;
+ typedef hash128::less less;
+ typedef hash128::cmp compare;
+ };
+ typedef cc::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash_type::make>(4, 3);
+
+ typedef cc::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename cc::feldman_hashset::make_traits<
+ cc::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , co::stat< cc::feldman_hashset::stat<>>
+ , co::less< hash_type::less >
+ , co::compare< hash128::cmp >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash_type::make>(4, 3);
+#endif
+ }
+} // namespace set
--- /dev/null
+//$$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 <typename Hash>
+ 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 <typename Hash>
+ struct get_hash
+ {
+ Hash const& operator()( Item<Hash> const& i ) const
+ {
+ return i.hash;
+ }
+ };
+
+ template <typename Key>
+ struct get_key
+ {
+ Key const& operator()(Item<Key> const& i) const
+ {
+ return i.hash;
+ }
+ };
+
+ struct item_disposer {
+ template <typename Hash>
+ void operator()( Item<Hash> * p )
+ {
+ ++p->nDisposeCount;
+ }
+ };
+
+ template <typename Key>
+ 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<size_t>()( n ), std::hash<size_t>()( ~n ));
+ }
+ hash128 operator()( hash128 const& n ) const
+ {
+ return hash128( std::hash<size_t>()( n.lo ), std::hash<size_t>()( ~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 <typename Set, typename Hash>
+ 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 <typename Set, typename Hash>
+ 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
--- /dev/null
+//$$CDS-header$$
+
+#include "set/hdr_intrusive_feldman_hashset.h"
+#include <cds/intrusive/feldman_hashset_dhp.h>
+#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<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< gc_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_hp<set_type, nohash<key_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ gc_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_hp<set_type2, nohash<key_type>>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::dhp_stdhash()
+ {
+ typedef size_t hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_hp<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_hp<set_type2, std::hash<hash_type>>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::dhp_hash128()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef hash128::less less;
+ };
+ typedef ci::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
+ test_hp<set_type, hash128::make>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ , ci::opt::less< hash_type::less >
+ >::type
+ > set_type2;
+ test_hp<set_type2, hash128::make>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::dhp_nohash_stat()
+ {
+ typedef size_t key_type;
+
+ struct traits : public ci::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< gc_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_hp<set_type, nohash<key_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ gc_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ , co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_hp<set_type2, nohash<key_type>>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::dhp_stdhash_stat()
+ {
+ typedef size_t hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_hp<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_hp<set_type2, std::hash<hash_type>>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::dhp_hash128_stat()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef hash128::cmp compare;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_hp<set_type, hash_type::make>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ ,co::compare< hash128::cmp >
+ >::type
+ > set_type2;
+ test_hp<set_type2, hash_type::make>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::dhp_nohash_5_3()
+ {
+ typedef size_t key_type;
+
+ struct traits : public ci::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< gc_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_hp<set_type, nohash<key_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ gc_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_hp<set_type2, nohash<key_type>>(5, 3);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::dhp_stdhash_5_3()
+ {
+ typedef size_t hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_hp<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_hp<set_type2, std::hash<hash_type>>(5, 3);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::dhp_hash128_4_3()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef co::v::sequential_consistent memory_model;
+ };
+ typedef ci::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_hp<set_type, hash128::make >(4, 3);
+
+ typedef ci::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::memory_model< co::v::sequential_consistent >
+ >::type
+ > set_type2;
+ test_hp<set_type2, hash128::make >(4, 3);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::dhp_nohash_5_3_stat()
+ {
+ typedef size_t key_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< gc_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_hp<set_type, nohash<key_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ gc_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_hp<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_hp<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_hp<set_type2, std::hash<hash_type>>(5, 3);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::dhp_hash128_4_3_stat()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> 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<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_hp<set_type, hash_type::make>(4, 3);
+
+ typedef ci::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , 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<set_type2, hash_type::make>(4, 3);
+ }
+
+} // namespace set
--- /dev/null
+//$$CDS-header$$
+
+#include "set/hdr_intrusive_feldman_hashset.h"
+#include <cds/intrusive/feldman_hashset_hp.h>
+#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<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< gc_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_hp<set_type, nohash<key_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ gc_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_hp<set_type2, nohash<key_type>>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::hp_stdhash()
+ {
+ typedef size_t hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_hp<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_hp<set_type2, std::hash<hash_type>>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::hp_hash128()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef hash128::less less;
+ };
+ typedef ci::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
+ test_hp<set_type, hash128::make>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ , ci::opt::less< hash_type::less >
+ >::type
+ > set_type2;
+ test_hp<set_type2, hash128::make>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::hp_nohash_stat()
+ {
+ typedef size_t key_type;
+
+ struct traits : public ci::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< gc_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_hp<set_type, nohash<key_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ gc_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ , co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_hp<set_type2, nohash<key_type>>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::hp_stdhash_stat()
+ {
+ typedef size_t hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_hp<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_hp<set_type2, std::hash<hash_type>>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::hp_hash128_stat()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef hash128::cmp compare;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_hp<set_type, hash_type::make>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ ,co::compare< hash128::cmp >
+ >::type
+ > set_type2;
+ test_hp<set_type2, hash_type::make>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::hp_nohash_5_3()
+ {
+ typedef size_t key_type;
+
+ struct traits : public ci::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< gc_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_hp<set_type, nohash<key_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ gc_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_hp<set_type2, nohash<key_type>>(5, 3);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::hp_stdhash_5_3()
+ {
+ typedef size_t hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_hp<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_hp<set_type2, std::hash<hash_type>>(5, 3);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::hp_hash128_4_3()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef co::v::sequential_consistent memory_model;
+ };
+ typedef ci::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_hp<set_type, hash128::make >(4, 3);
+
+ typedef ci::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::memory_model< co::v::sequential_consistent >
+ >::type
+ > set_type2;
+ test_hp<set_type2, hash128::make >(4, 3);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::hp_nohash_5_3_stat()
+ {
+ typedef size_t key_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< gc_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_hp<set_type, nohash<key_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ gc_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_hp<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< gc_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_hp<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_hp<set_type2, std::hash<hash_type>>(5, 3);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::hp_hash128_4_3_stat()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> 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<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_hp<set_type, hash_type::make>(4, 3);
+
+ typedef ci::FeldmanHashSet<
+ gc_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , 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<set_type2, hash_type::make>(4, 3);
+ }
+
+} // namespace set
+
+CPPUNIT_TEST_SUITE_REGISTRATION(set::IntrusiveFeldmanHashSetHdrTest);
--- /dev/null
+//$$CDS-header$$
+
+#include "set/hdr_intrusive_feldman_hashset.h"
+#include <cds/urcu/general_buffered.h>
+#include <cds/intrusive/feldman_hashset_rcu.h>
+#include "unit/print_feldman_hashset_stat.h"
+
+namespace set {
+ namespace {
+ typedef cds::urcu::gc<cds::urcu::general_buffered<>> rcu_type;
+ } // namespace
+
+ void IntrusiveFeldmanHashSetHdrTest::rcu_gpb_nohash()
+ {
+ typedef size_t key_type;
+
+ struct traits : public ci::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_rcu<set_type, nohash<key_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::rcu_gpb_stdhash()
+ {
+ typedef size_t hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::rcu_gpb_hash128()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef hash128::less less;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
+ test_rcu<set_type, hash128::make>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ , ci::opt::less< hash_type::less >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash128::make>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::rcu_gpb_nohash_stat()
+ {
+ typedef size_t key_type;
+
+ struct traits : public ci::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_rcu<set_type, nohash<key_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ , co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::rcu_gpb_stdhash_stat()
+ {
+ typedef size_t hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::rcu_gpb_hash128_stat()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef hash128::cmp compare;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash_type::make>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ ,co::compare< hash128::cmp >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash_type::make>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::rcu_gpb_nohash_5_3()
+ {
+ typedef size_t key_type;
+
+ struct traits : public ci::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_rcu<set_type, nohash<key_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(5, 3);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::rcu_gpb_hash128_4_3()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef co::v::sequential_consistent memory_model;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash128::make >(4, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::memory_model< co::v::sequential_consistent >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash128::make >(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<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, nohash<key_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(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_type> 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<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash_type::make>(4, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , 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<set_type2, hash_type::make>(4, 3);
+ }
+
+} // namespace set
--- /dev/null
+//$$CDS-header$$
+
+#include "set/hdr_intrusive_feldman_hashset.h"
+#include <cds/urcu/general_instant.h>
+#include <cds/intrusive/feldman_hashset_rcu.h>
+#include "unit/print_feldman_hashset_stat.h"
+
+namespace set {
+ namespace {
+ typedef cds::urcu::gc<cds::urcu::general_instant<>> rcu_type;
+ } // namespace
+
+ void IntrusiveFeldmanHashSetHdrTest::rcu_gpi_nohash()
+ {
+ typedef size_t key_type;
+
+ struct traits : public ci::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_rcu<set_type, nohash<key_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::rcu_gpi_stdhash()
+ {
+ typedef size_t hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::rcu_gpi_hash128()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef hash128::less less;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
+ test_rcu<set_type, hash128::make>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ , ci::opt::less< hash_type::less >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash128::make>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::rcu_gpi_nohash_stat()
+ {
+ typedef size_t key_type;
+
+ struct traits : public ci::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_rcu<set_type, nohash<key_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ , co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::rcu_gpi_stdhash_stat()
+ {
+ typedef size_t hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::rcu_gpi_hash128_stat()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef hash128::cmp compare;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash_type::make>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ ,co::compare< hash128::cmp >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash_type::make>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::rcu_gpi_nohash_5_3()
+ {
+ typedef size_t key_type;
+
+ struct traits : public ci::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_rcu<set_type, nohash<key_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(5, 3);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::rcu_gpi_hash128_4_3()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef co::v::sequential_consistent memory_model;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash128::make >(4, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::memory_model< co::v::sequential_consistent >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash128::make >(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<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, nohash<key_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(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_type> 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<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash_type::make>(4, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , 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<set_type2, hash_type::make>(4, 3);
+ }
+
+} // namespace set
--- /dev/null
+//$$CDS-header$$
+
+#include "set/hdr_intrusive_feldman_hashset.h"
+#include <cds/urcu/general_threaded.h>
+#include <cds/intrusive/feldman_hashset_rcu.h>
+#include "unit/print_feldman_hashset_stat.h"
+
+namespace set {
+ namespace {
+ typedef cds::urcu::gc<cds::urcu::general_threaded<>> rcu_type;
+ } // namespace
+
+ void IntrusiveFeldmanHashSetHdrTest::rcu_gpt_nohash()
+ {
+ typedef size_t key_type;
+
+ struct traits : public ci::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_rcu<set_type, nohash<key_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::rcu_gpt_stdhash()
+ {
+ typedef size_t hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::rcu_gpt_hash128()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef hash128::less less;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
+ test_rcu<set_type, hash128::make>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ , ci::opt::less< hash_type::less >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash128::make>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::rcu_gpt_nohash_stat()
+ {
+ typedef size_t key_type;
+
+ struct traits : public ci::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_rcu<set_type, nohash<key_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ , co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::rcu_gpt_stdhash_stat()
+ {
+ typedef size_t hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::rcu_gpt_hash128_stat()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef hash128::cmp compare;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash_type::make>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ ,co::compare< hash128::cmp >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash_type::make>(4, 2);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::rcu_gpt_nohash_5_3()
+ {
+ typedef size_t key_type;
+
+ struct traits : public ci::feldman_hashset::traits
+ {
+ typedef get_key<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_rcu<set_type, nohash<key_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(5, 3);
+ }
+
+ void IntrusiveFeldmanHashSetHdrTest::rcu_gpt_hash128_4_3()
+ {
+ typedef hash128 hash_type;
+
+ struct traits: public ci::feldman_hashset::traits
+ {
+ typedef get_hash<hash_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef co::v::sequential_consistent memory_model;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash128::make >(4, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::memory_model< co::v::sequential_consistent >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash128::make >(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<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, nohash<key_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(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_type> 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<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash_type::make>(4, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , 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<set_type2, hash_type::make>(4, 3);
+ }
+
+} // namespace set
--- /dev/null
+//$$CDS-header$$
+
+#include "set/hdr_intrusive_feldman_hashset.h"
+#include <cds/urcu/signal_buffered.h>
+#include <cds/intrusive/feldman_hashset_rcu.h>
+#include "unit/print_feldman_hashset_stat.h"
+
+namespace set {
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ namespace {
+ typedef cds::urcu::gc<cds::urcu::signal_buffered<>> 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<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_rcu<set_type, nohash<key_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef hash128::less less;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
+ test_rcu<set_type, hash128::make>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ , ci::opt::less< hash_type::less >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash128::make>(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<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_rcu<set_type, nohash<key_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ , co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef hash128::cmp compare;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash_type::make>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ ,co::compare< hash128::cmp >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash_type::make>(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<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_rcu<set_type, nohash<key_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef co::v::sequential_consistent memory_model;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash128::make >(4, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::memory_model< co::v::sequential_consistent >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash128::make >(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<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, nohash<key_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(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_type> 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<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash_type::make>(4, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , 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<set_type2, hash_type::make>(4, 3);
+#endif
+ }
+
+} // namespace set
--- /dev/null
+//$$CDS-header$$
+
+#include "set/hdr_intrusive_feldman_hashset.h"
+#include <cds/urcu/signal_threaded.h>
+#include <cds/intrusive/feldman_hashset_rcu.h>
+#include "unit/print_feldman_hashset_stat.h"
+
+namespace set {
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ namespace {
+ typedef cds::urcu::gc<cds::urcu::signal_threaded<>> 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<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_rcu<set_type, nohash<key_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef hash128::less less;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
+ test_rcu<set_type, hash128::make>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ , ci::opt::less< hash_type::less >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash128::make>(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<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_rcu<set_type, nohash<key_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ , co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef hash128::cmp compare;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash_type::make>(4, 2);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ ,co::compare< hash128::cmp >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash_type::make>(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<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
+ test_rcu<set_type, nohash<key_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ typedef item_disposer disposer;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef co::v::sequential_consistent memory_model;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash128::make >(4, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::memory_model< co::v::sequential_consistent >
+ >::type
+ > set_type2;
+ test_rcu<set_type2, hash128::make >(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<key_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<key_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, nohash<key_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<key_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_key<key_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
+ typedef item_disposer disposer;
+ typedef ci::feldman_hashset::stat<> stat;
+ };
+ typedef ci::FeldmanHashSet< rcu_type, Item<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
+ test_rcu<set_type, std::hash<hash_type>>(5, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , ci::opt::disposer< item_disposer >
+ ,co::stat< ci::feldman_hashset::stat<>>
+ >::type
+ > set_type2;
+ test_rcu<set_type2, std::hash<hash_type>>(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_type> 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<hash_type>, traits > set_type;
+ static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
+ test_rcu<set_type, hash_type::make>(4, 3);
+
+ typedef ci::FeldmanHashSet<
+ rcu_type,
+ Item<hash_type>,
+ typename ci::feldman_hashset::make_traits<
+ ci::feldman_hashset::hash_accessor< get_hash<hash_type>>
+ , 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<set_type2, hash_type::make>(4, 3);
+#endif
+ }
+
+} // namespace set
+++ /dev/null
-//$$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 <typename Hash>
- 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 <typename Hash>
- struct get_hash
- {
- Hash const& operator()( Item<Hash> const& i ) const
- {
- return i.hash;
- }
- };
-
- template <typename Key>
- struct get_key
- {
- Key const& operator()(Item<Key> const& i) const
- {
- return i.hash;
- }
- };
-
- struct item_disposer {
- template <typename Hash>
- void operator()( Item<Hash> * p )
- {
- ++p->nDisposeCount;
- }
- };
-
- template <typename Key>
- 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<size_t>()( n ), std::hash<size_t>()( ~n ));
- }
- hash128 operator()( hash128 const& n ) const
- {
- return hash128( std::hash<size_t>()( n.lo ), std::hash<size_t>()( ~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 <typename Set, typename Hash>
- 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 <typename Set, typename Hash>
- 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
+++ /dev/null
-//$$CDS-header$$
-
-#include "set/hdr_intrusive_multilevel_hashset.h"
-#include <cds/intrusive/multilevel_hashset_dhp.h>
-#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<key_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< gc_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_hp<set_type, nohash<key_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- gc_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_hp<set_type2, nohash<key_type>>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::dhp_stdhash()
- {
- typedef size_t hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_hp<set_type, std::hash<hash_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_hp<set_type2, std::hash<hash_type>>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::dhp_hash128()
- {
- typedef hash128 hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- typedef hash128::less less;
- };
- typedef ci::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
- test_hp<set_type, hash128::make>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- , ci::opt::less< hash_type::less >
- >::type
- > set_type2;
- test_hp<set_type2, hash128::make>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::dhp_nohash_stat()
- {
- typedef size_t key_type;
-
- struct traits : public ci::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< gc_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_hp<set_type, nohash<key_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- gc_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- , co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_hp<set_type2, nohash<key_type>>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::dhp_stdhash_stat()
- {
- typedef size_t hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_hp<set_type, std::hash<hash_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_hp<set_type2, std::hash<hash_type>>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::dhp_hash128_stat()
- {
- typedef hash128 hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- typedef hash128::cmp compare;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_hp<set_type, hash_type::make>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- ,co::compare< hash128::cmp >
- >::type
- > set_type2;
- test_hp<set_type2, hash_type::make>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::dhp_nohash_5_3()
- {
- typedef size_t key_type;
-
- struct traits : public ci::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< gc_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_hp<set_type, nohash<key_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- gc_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_hp<set_type2, nohash<key_type>>(5, 3);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::dhp_stdhash_5_3()
- {
- typedef size_t hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_hp<set_type, std::hash<hash_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_hp<set_type2, std::hash<hash_type>>(5, 3);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::dhp_hash128_4_3()
- {
- typedef hash128 hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- typedef co::v::sequential_consistent memory_model;
- };
- typedef ci::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_hp<set_type, hash128::make >(4, 3);
-
- typedef ci::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::memory_model< co::v::sequential_consistent >
- >::type
- > set_type2;
- test_hp<set_type2, hash128::make >(4, 3);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::dhp_nohash_5_3_stat()
- {
- typedef size_t key_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< gc_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_hp<set_type, nohash<key_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- gc_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_hp<set_type2, nohash<key_type>>(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_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_hp<set_type, std::hash<hash_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_hp<set_type2, std::hash<hash_type>>(5, 3);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::dhp_hash128_4_3_stat()
- {
- typedef hash128 hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> 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<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_hp<set_type, hash_type::make>(4, 3);
-
- typedef ci::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , 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<set_type2, hash_type::make>(4, 3);
- }
-
-} // namespace set
+++ /dev/null
-//$$CDS-header$$
-
-#include "set/hdr_intrusive_multilevel_hashset.h"
-#include <cds/intrusive/multilevel_hashset_hp.h>
-#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<key_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< gc_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_hp<set_type, nohash<key_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- gc_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_hp<set_type2, nohash<key_type>>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::hp_stdhash()
- {
- typedef size_t hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_hp<set_type, std::hash<hash_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_hp<set_type2, std::hash<hash_type>>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::hp_hash128()
- {
- typedef hash128 hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- typedef hash128::less less;
- };
- typedef ci::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
- test_hp<set_type, hash128::make>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- , ci::opt::less< hash_type::less >
- >::type
- > set_type2;
- test_hp<set_type2, hash128::make>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::hp_nohash_stat()
- {
- typedef size_t key_type;
-
- struct traits : public ci::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< gc_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_hp<set_type, nohash<key_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- gc_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- , co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_hp<set_type2, nohash<key_type>>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::hp_stdhash_stat()
- {
- typedef size_t hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_hp<set_type, std::hash<hash_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_hp<set_type2, std::hash<hash_type>>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::hp_hash128_stat()
- {
- typedef hash128 hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- typedef hash128::cmp compare;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_hp<set_type, hash_type::make>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- ,co::compare< hash128::cmp >
- >::type
- > set_type2;
- test_hp<set_type2, hash_type::make>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::hp_nohash_5_3()
- {
- typedef size_t key_type;
-
- struct traits : public ci::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< gc_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_hp<set_type, nohash<key_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- gc_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_hp<set_type2, nohash<key_type>>(5, 3);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::hp_stdhash_5_3()
- {
- typedef size_t hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_hp<set_type, std::hash<hash_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_hp<set_type2, std::hash<hash_type>>(5, 3);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::hp_hash128_4_3()
- {
- typedef hash128 hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- typedef co::v::sequential_consistent memory_model;
- };
- typedef ci::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_hp<set_type, hash128::make >(4, 3);
-
- typedef ci::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::memory_model< co::v::sequential_consistent >
- >::type
- > set_type2;
- test_hp<set_type2, hash128::make >(4, 3);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::hp_nohash_5_3_stat()
- {
- typedef size_t key_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< gc_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_hp<set_type, nohash<key_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- gc_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_hp<set_type2, nohash<key_type>>(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_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_hp<set_type, std::hash<hash_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_hp<set_type2, std::hash<hash_type>>(5, 3);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::hp_hash128_4_3_stat()
- {
- typedef hash128 hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> 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<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_hp<set_type, hash_type::make>(4, 3);
-
- typedef ci::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , 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<set_type2, hash_type::make>(4, 3);
- }
-
-} // namespace set
-
-CPPUNIT_TEST_SUITE_REGISTRATION(set::IntrusiveMultiLevelHashSetHdrTest);
+++ /dev/null
-//$$CDS-header$$
-
-#include "set/hdr_intrusive_multilevel_hashset.h"
-#include <cds/urcu/general_buffered.h>
-#include <cds/intrusive/multilevel_hashset_rcu.h>
-#include "unit/print_multilevel_hashset_stat.h"
-
-namespace set {
- namespace {
- typedef cds::urcu::gc<cds::urcu::general_buffered<>> rcu_type;
- } // namespace
-
- void IntrusiveMultiLevelHashSetHdrTest::rcu_gpb_nohash()
- {
- typedef size_t key_type;
-
- struct traits : public ci::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_rcu<set_type, nohash<key_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::rcu_gpb_stdhash()
- {
- typedef size_t hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::rcu_gpb_hash128()
- {
- typedef hash128 hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- typedef hash128::less less;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
- test_rcu<set_type, hash128::make>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- , ci::opt::less< hash_type::less >
- >::type
- > set_type2;
- test_rcu<set_type2, hash128::make>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::rcu_gpb_nohash_stat()
- {
- typedef size_t key_type;
-
- struct traits : public ci::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_rcu<set_type, nohash<key_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- , co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::rcu_gpb_stdhash_stat()
- {
- typedef size_t hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::rcu_gpb_hash128_stat()
- {
- typedef hash128 hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- typedef hash128::cmp compare;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash_type::make>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- ,co::compare< hash128::cmp >
- >::type
- > set_type2;
- test_rcu<set_type2, hash_type::make>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::rcu_gpb_nohash_5_3()
- {
- typedef size_t key_type;
-
- struct traits : public ci::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_rcu<set_type, nohash<key_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(5, 3);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::rcu_gpb_hash128_4_3()
- {
- typedef hash128 hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- typedef co::v::sequential_consistent memory_model;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash128::make >(4, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::memory_model< co::v::sequential_consistent >
- >::type
- > set_type2;
- test_rcu<set_type2, hash128::make >(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<key_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, nohash<key_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(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_type> 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<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash_type::make>(4, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , 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<set_type2, hash_type::make>(4, 3);
- }
-
-} // namespace set
+++ /dev/null
-//$$CDS-header$$
-
-#include "set/hdr_intrusive_multilevel_hashset.h"
-#include <cds/urcu/general_instant.h>
-#include <cds/intrusive/multilevel_hashset_rcu.h>
-#include "unit/print_multilevel_hashset_stat.h"
-
-namespace set {
- namespace {
- typedef cds::urcu::gc<cds::urcu::general_instant<>> rcu_type;
- } // namespace
-
- void IntrusiveMultiLevelHashSetHdrTest::rcu_gpi_nohash()
- {
- typedef size_t key_type;
-
- struct traits : public ci::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_rcu<set_type, nohash<key_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::rcu_gpi_stdhash()
- {
- typedef size_t hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::rcu_gpi_hash128()
- {
- typedef hash128 hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- typedef hash128::less less;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
- test_rcu<set_type, hash128::make>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- , ci::opt::less< hash_type::less >
- >::type
- > set_type2;
- test_rcu<set_type2, hash128::make>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::rcu_gpi_nohash_stat()
- {
- typedef size_t key_type;
-
- struct traits : public ci::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_rcu<set_type, nohash<key_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- , co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::rcu_gpi_stdhash_stat()
- {
- typedef size_t hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::rcu_gpi_hash128_stat()
- {
- typedef hash128 hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- typedef hash128::cmp compare;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash_type::make>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- ,co::compare< hash128::cmp >
- >::type
- > set_type2;
- test_rcu<set_type2, hash_type::make>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::rcu_gpi_nohash_5_3()
- {
- typedef size_t key_type;
-
- struct traits : public ci::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_rcu<set_type, nohash<key_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(5, 3);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::rcu_gpi_hash128_4_3()
- {
- typedef hash128 hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- typedef co::v::sequential_consistent memory_model;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash128::make >(4, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::memory_model< co::v::sequential_consistent >
- >::type
- > set_type2;
- test_rcu<set_type2, hash128::make >(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<key_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, nohash<key_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(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_type> 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<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash_type::make>(4, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , 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<set_type2, hash_type::make>(4, 3);
- }
-
-} // namespace set
+++ /dev/null
-//$$CDS-header$$
-
-#include "set/hdr_intrusive_multilevel_hashset.h"
-#include <cds/urcu/general_threaded.h>
-#include <cds/intrusive/multilevel_hashset_rcu.h>
-#include "unit/print_multilevel_hashset_stat.h"
-
-namespace set {
- namespace {
- typedef cds::urcu::gc<cds::urcu::general_threaded<>> rcu_type;
- } // namespace
-
- void IntrusiveMultiLevelHashSetHdrTest::rcu_gpt_nohash()
- {
- typedef size_t key_type;
-
- struct traits : public ci::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_rcu<set_type, nohash<key_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::rcu_gpt_stdhash()
- {
- typedef size_t hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::rcu_gpt_hash128()
- {
- typedef hash128 hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- typedef hash128::less less;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
- test_rcu<set_type, hash128::make>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- , ci::opt::less< hash_type::less >
- >::type
- > set_type2;
- test_rcu<set_type2, hash128::make>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::rcu_gpt_nohash_stat()
- {
- typedef size_t key_type;
-
- struct traits : public ci::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_rcu<set_type, nohash<key_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- , co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::rcu_gpt_stdhash_stat()
- {
- typedef size_t hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::rcu_gpt_hash128_stat()
- {
- typedef hash128 hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- typedef hash128::cmp compare;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash_type::make>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- ,co::compare< hash128::cmp >
- >::type
- > set_type2;
- test_rcu<set_type2, hash_type::make>(4, 2);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::rcu_gpt_nohash_5_3()
- {
- typedef size_t key_type;
-
- struct traits : public ci::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_rcu<set_type, nohash<key_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(5, 3);
- }
-
- void IntrusiveMultiLevelHashSetHdrTest::rcu_gpt_hash128_4_3()
- {
- typedef hash128 hash_type;
-
- struct traits: public ci::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef item_disposer disposer;
- typedef co::v::sequential_consistent memory_model;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash128::make >(4, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::memory_model< co::v::sequential_consistent >
- >::type
- > set_type2;
- test_rcu<set_type2, hash128::make >(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<key_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, nohash<key_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(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_type> 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<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash_type::make>(4, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , 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<set_type2, hash_type::make>(4, 3);
- }
-
-} // namespace set
+++ /dev/null
-//$$CDS-header$$
-
-#include "set/hdr_intrusive_multilevel_hashset.h"
-#include <cds/urcu/signal_buffered.h>
-#include <cds/intrusive/multilevel_hashset_rcu.h>
-#include "unit/print_multilevel_hashset_stat.h"
-
-namespace set {
-#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
- namespace {
- typedef cds::urcu::gc<cds::urcu::signal_buffered<>> 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<key_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_rcu<set_type, nohash<key_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
- typedef item_disposer disposer;
- typedef hash128::less less;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
- test_rcu<set_type, hash128::make>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- , ci::opt::less< hash_type::less >
- >::type
- > set_type2;
- test_rcu<set_type2, hash128::make>(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<key_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_rcu<set_type, nohash<key_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- , co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
- typedef item_disposer disposer;
- typedef hash128::cmp compare;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash_type::make>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- ,co::compare< hash128::cmp >
- >::type
- > set_type2;
- test_rcu<set_type2, hash_type::make>(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<key_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_rcu<set_type, nohash<key_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
- typedef item_disposer disposer;
- typedef co::v::sequential_consistent memory_model;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash128::make >(4, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::memory_model< co::v::sequential_consistent >
- >::type
- > set_type2;
- test_rcu<set_type2, hash128::make >(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<key_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, nohash<key_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(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_type> 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<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash_type::make>(4, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , 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<set_type2, hash_type::make>(4, 3);
-#endif
- }
-
-} // namespace set
+++ /dev/null
-//$$CDS-header$$
-
-#include "set/hdr_intrusive_multilevel_hashset.h"
-#include <cds/urcu/signal_threaded.h>
-#include <cds/intrusive/multilevel_hashset_rcu.h>
-#include "unit/print_multilevel_hashset_stat.h"
-
-namespace set {
-#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
- namespace {
- typedef cds::urcu::gc<cds::urcu::signal_threaded<>> 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<key_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_rcu<set_type, nohash<key_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
- typedef item_disposer disposer;
- typedef hash128::less less;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
- test_rcu<set_type, hash128::make>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- , ci::opt::less< hash_type::less >
- >::type
- > set_type2;
- test_rcu<set_type2, hash128::make>(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<key_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_rcu<set_type, nohash<key_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- , co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
- typedef item_disposer disposer;
- typedef hash128::cmp compare;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash_type::make>(4, 2);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- ,co::compare< hash128::cmp >
- >::type
- > set_type2;
- test_rcu<set_type2, hash_type::make>(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<key_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_rcu<set_type, nohash<key_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- typedef item_disposer disposer;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
- typedef item_disposer disposer;
- typedef co::v::sequential_consistent memory_model;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash128::make >(4, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::memory_model< co::v::sequential_consistent >
- >::type
- > set_type2;
- test_rcu<set_type2, hash128::make >(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<key_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, nohash<key_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_key<key_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- typedef item_disposer disposer;
- typedef ci::multilevel_hashset::stat<> stat;
- };
- typedef ci::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(5, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , ci::opt::disposer< item_disposer >
- ,co::stat< ci::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(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_type> 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<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash_type::make>(4, 3);
-
- typedef ci::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename ci::multilevel_hashset::make_traits<
- ci::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , 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<set_type2, hash_type::make>(4, 3);
-#endif
- }
-
-} // namespace set
+++ /dev/null
-//$$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 <typename Hash>
- struct Arg
- {
- size_t key;
- Hash hash;
-
- Arg( size_t k, Hash const& h )
- : key( k )
- , hash( h )
- {}
- };
-
- template <typename Hash>
- 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<Hash> 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 <typename Hash>
- struct get_hash
- {
- Hash const& operator()( Item<Hash> const& i ) const
- {
- return i.hash;
- }
- };
-
- template <typename Key>
- struct get_key
- {
- Key operator()(Item<Key> const& i)const
- {
- return i.hash;
- }
- };
-
- template <typename Key>
- 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<size_t>()( n ), std::hash<size_t>()( ~n ));
- }
- hash128 operator()( hash128 const& n ) const
- {
- return hash128( std::hash<size_t>()( n.lo ), std::hash<size_t>()( ~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 <typename Set, typename Hasher>
- 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<hash_type> 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<bool, bool> 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<bool, bool> 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 <typename Set, typename Hasher>
- 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<hash_type> 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<bool, bool> 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<bool, bool> 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
+++ /dev/null
-//$$CDS-header$$
-
-#include "set/hdr_multilevel_hashset.h"
-#include <cds/container/multilevel_hashset_dhp.h>
-#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<key_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< gc_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_hp<set_type, nohash<key_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- gc_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- >::type
- > set_type2;
- test_hp<set_type2, nohash<key_type>>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::dhp_stdhash()
- {
- typedef size_t hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_hp<set_type, std::hash<hash_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- >::type
- > set_type2;
- test_hp<set_type2, std::hash<hash_type>>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::dhp_hash128()
- {
- typedef hash128 hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef hash128::less less;
- };
- typedef cc::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
- test_hp<set_type, hash128::make>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , co::less< hash_type::less >
- >::type
- > set_type2;
- test_hp<set_type2, hash128::make>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::dhp_nohash_stat()
- {
- typedef size_t key_type;
-
- struct traits : public cc::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< gc_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_hp<set_type, nohash<key_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- gc_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- , co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_hp<set_type2, nohash<key_type>>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::dhp_stdhash_stat()
- {
- typedef size_t hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_hp<set_type, std::hash<hash_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_hp<set_type2, std::hash<hash_type>>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::dhp_hash128_stat()
- {
- typedef hash128 hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef hash128::cmp compare;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_hp<set_type, hash_type::make>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- ,co::compare< hash128::cmp >
- >::type
- > set_type2;
- test_hp<set_type2, hash_type::make>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::dhp_nohash_5_3()
- {
- typedef size_t key_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< gc_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_hp<set_type, nohash<key_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- gc_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- >::type
- > set_type2;
- test_hp<set_type2, nohash<key_type>>(5, 3);
- }
-
- void MultiLevelHashSetHdrTest::dhp_stdhash_5_3()
- {
- typedef size_t hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_hp<set_type, std::hash<hash_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- >::type
- > set_type2;
- test_hp<set_type2, std::hash<hash_type>>(5, 3);
- }
-
- void MultiLevelHashSetHdrTest::dhp_hash128_4_3()
- {
- typedef hash128 hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef co::v::sequential_consistent memory_model;
- };
- typedef cc::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_hp<set_type, hash128::make >(4, 3);
-
- typedef cc::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::memory_model< co::v::sequential_consistent >
- >::type
- > set_type2;
- test_hp<set_type2, hash128::make >(4, 3);
- }
-
- void MultiLevelHashSetHdrTest::dhp_nohash_5_3_stat()
- {
- typedef size_t key_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< gc_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_hp<set_type, nohash<key_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- gc_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_hp<set_type2, nohash<key_type>>(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_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_hp<set_type, std::hash<hash_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_hp<set_type2, std::hash<hash_type>>(5, 3);
- }
-
- void MultiLevelHashSetHdrTest::dhp_hash128_4_3_stat()
- {
- typedef hash128 hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- typedef hash128::less less;
- typedef hash128::cmp compare;
- };
- typedef cc::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_hp<set_type, hash_type::make>(4, 3);
-
- typedef cc::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , co::stat< cc::multilevel_hashset::stat<>>
- , co::less< hash_type::less >
- , co::compare< hash128::cmp >
- >::type
- > set_type2;
- test_hp<set_type2, hash_type::make>(4, 3);
- }
-
-
-} // namespace set
+++ /dev/null
-//$$CDS-header$$
-
-#include "set/hdr_multilevel_hashset.h"
-#include <cds/container/multilevel_hashset_hp.h>
-#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<key_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< gc_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_hp<set_type, nohash<key_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- gc_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- >::type
- > set_type2;
- test_hp<set_type2, nohash<key_type>>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::hp_stdhash()
- {
- typedef size_t hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_hp<set_type, std::hash<hash_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- >::type
- > set_type2;
- test_hp<set_type2, std::hash<hash_type>>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::hp_hash128()
- {
- typedef hash128 hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef hash128::less less;
- };
- typedef cc::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
- test_hp<set_type, hash128::make>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , co::less< hash_type::less >
- >::type
- > set_type2;
- test_hp<set_type2, hash128::make>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::hp_nohash_stat()
- {
- typedef size_t key_type;
-
- struct traits : public cc::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< gc_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_hp<set_type, nohash<key_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- gc_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- , co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_hp<set_type2, nohash<key_type>>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::hp_stdhash_stat()
- {
- typedef size_t hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_hp<set_type, std::hash<hash_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_hp<set_type2, std::hash<hash_type>>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::hp_hash128_stat()
- {
- typedef hash128 hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef hash128::cmp compare;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_hp<set_type, hash_type::make>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- ,co::compare< hash128::cmp >
- >::type
- > set_type2;
- test_hp<set_type2, hash_type::make>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::hp_nohash_5_3()
- {
- typedef size_t key_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< gc_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_hp<set_type, nohash<key_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- gc_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- >::type
- > set_type2;
- test_hp<set_type2, nohash<key_type>>(5, 3);
- }
-
- void MultiLevelHashSetHdrTest::hp_stdhash_5_3()
- {
- typedef size_t hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_hp<set_type, std::hash<hash_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- >::type
- > set_type2;
- test_hp<set_type2, std::hash<hash_type>>(5, 3);
- }
-
- void MultiLevelHashSetHdrTest::hp_hash128_4_3()
- {
- typedef hash128 hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef co::v::sequential_consistent memory_model;
- };
- typedef cc::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_hp<set_type, hash128::make >(4, 3);
-
- typedef cc::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::memory_model< co::v::sequential_consistent >
- >::type
- > set_type2;
- test_hp<set_type2, hash128::make >(4, 3);
- }
-
- void MultiLevelHashSetHdrTest::hp_nohash_5_3_stat()
- {
- typedef size_t key_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< gc_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_hp<set_type, nohash<key_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- gc_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_hp<set_type2, nohash<key_type>>(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_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_hp<set_type, std::hash<hash_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_hp<set_type2, std::hash<hash_type>>(5, 3);
- }
-
- void MultiLevelHashSetHdrTest::hp_hash128_4_3_stat()
- {
- typedef hash128 hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- typedef hash128::less less;
- typedef hash128::cmp compare;
- };
- typedef cc::MultiLevelHashSet< gc_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_hp<set_type, hash_type::make>(4, 3);
-
- typedef cc::MultiLevelHashSet<
- gc_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , co::stat< cc::multilevel_hashset::stat<>>
- , co::less< hash_type::less >
- , co::compare< hash128::cmp >
- >::type
- > set_type2;
- test_hp<set_type2, hash_type::make>(4, 3);
- }
-
-
-} // namespace set
-
-CPPUNIT_TEST_SUITE_REGISTRATION(set::MultiLevelHashSetHdrTest);
+++ /dev/null
-//$$CDS-header$$
-
-#include "set/hdr_multilevel_hashset.h"
-#include <cds/urcu/general_buffered.h>
-#include <cds/container/multilevel_hashset_rcu.h>
-#include "unit/print_multilevel_hashset_stat.h"
-
-namespace set {
- namespace {
- typedef cds::urcu::gc<cds::urcu::general_buffered<>> rcu_type;
- } // namespace
-
- void MultiLevelHashSetHdrTest::rcu_gpb_nohash()
- {
- typedef size_t key_type;
-
- struct traits : public cc::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_rcu<set_type, nohash<key_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::rcu_gpb_stdhash()
- {
- typedef size_t hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::rcu_gpb_hash128()
- {
- typedef hash128 hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef hash128::less less;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
- test_rcu<set_type, hash128::make>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , co::less< hash_type::less >
- >::type
- > set_type2;
- test_rcu<set_type2, hash128::make>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::rcu_gpb_nohash_stat()
- {
- typedef size_t key_type;
-
- struct traits : public cc::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_rcu<set_type, nohash<key_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- , co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::rcu_gpb_stdhash_stat()
- {
- typedef size_t hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::rcu_gpb_hash128_stat()
- {
- typedef hash128 hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef hash128::cmp compare;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash_type::make>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- ,co::compare< hash128::cmp >
- >::type
- > set_type2;
- test_rcu<set_type2, hash_type::make>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::rcu_gpb_nohash_5_3()
- {
- typedef size_t key_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, nohash<key_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(5, 3);
- }
-
- void MultiLevelHashSetHdrTest::rcu_gpb_hash128_4_3()
- {
- typedef hash128 hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef co::v::sequential_consistent memory_model;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash128::make >(4, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::memory_model< co::v::sequential_consistent >
- >::type
- > set_type2;
- test_rcu<set_type2, hash128::make >(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<key_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, nohash<key_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- typedef hash128::less less;
- typedef hash128::cmp compare;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash_type::make>(4, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , co::stat< cc::multilevel_hashset::stat<>>
- , co::less< hash_type::less >
- , co::compare< hash128::cmp >
- >::type
- > set_type2;
- test_rcu<set_type2, hash_type::make>(4, 3);
- }
-
-
-} // namespace set
+++ /dev/null
-//$$CDS-header$$
-
-#include "set/hdr_multilevel_hashset.h"
-#include <cds/urcu/general_instant.h>
-#include <cds/container/multilevel_hashset_rcu.h>
-#include "unit/print_multilevel_hashset_stat.h"
-
-namespace set {
- namespace {
- typedef cds::urcu::gc<cds::urcu::general_instant<>> rcu_type;
- } // namespace
-
- void MultiLevelHashSetHdrTest::rcu_gpi_nohash()
- {
- typedef size_t key_type;
-
- struct traits : public cc::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_rcu<set_type, nohash<key_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::rcu_gpi_stdhash()
- {
- typedef size_t hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::rcu_gpi_hash128()
- {
- typedef hash128 hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef hash128::less less;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
- test_rcu<set_type, hash128::make>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , co::less< hash_type::less >
- >::type
- > set_type2;
- test_rcu<set_type2, hash128::make>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::rcu_gpi_nohash_stat()
- {
- typedef size_t key_type;
-
- struct traits : public cc::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_rcu<set_type, nohash<key_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- , co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::rcu_gpi_stdhash_stat()
- {
- typedef size_t hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::rcu_gpi_hash128_stat()
- {
- typedef hash128 hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef hash128::cmp compare;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash_type::make>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- ,co::compare< hash128::cmp >
- >::type
- > set_type2;
- test_rcu<set_type2, hash_type::make>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::rcu_gpi_nohash_5_3()
- {
- typedef size_t key_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, nohash<key_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(5, 3);
- }
-
- void MultiLevelHashSetHdrTest::rcu_gpi_hash128_4_3()
- {
- typedef hash128 hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef co::v::sequential_consistent memory_model;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash128::make >(4, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::memory_model< co::v::sequential_consistent >
- >::type
- > set_type2;
- test_rcu<set_type2, hash128::make >(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<key_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, nohash<key_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- typedef hash128::less less;
- typedef hash128::cmp compare;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash_type::make>(4, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , co::stat< cc::multilevel_hashset::stat<>>
- , co::less< hash_type::less >
- , co::compare< hash128::cmp >
- >::type
- > set_type2;
- test_rcu<set_type2, hash_type::make>(4, 3);
- }
-
-
-} // namespace set
+++ /dev/null
-//$$CDS-header$$
-
-#include "set/hdr_multilevel_hashset.h"
-#include <cds/urcu/general_threaded.h>
-#include <cds/container/multilevel_hashset_rcu.h>
-#include "unit/print_multilevel_hashset_stat.h"
-
-namespace set {
- namespace {
- typedef cds::urcu::gc<cds::urcu::general_threaded<>> rcu_type;
- } // namespace
-
- void MultiLevelHashSetHdrTest::rcu_gpt_nohash()
- {
- typedef size_t key_type;
-
- struct traits : public cc::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_rcu<set_type, nohash<key_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::rcu_gpt_stdhash()
- {
- typedef size_t hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::rcu_gpt_hash128()
- {
- typedef hash128 hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef hash128::less less;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
- test_rcu<set_type, hash128::make>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , co::less< hash_type::less >
- >::type
- > set_type2;
- test_rcu<set_type2, hash128::make>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::rcu_gpt_nohash_stat()
- {
- typedef size_t key_type;
-
- struct traits : public cc::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_rcu<set_type, nohash<key_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- , co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::rcu_gpt_stdhash_stat()
- {
- typedef size_t hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::rcu_gpt_hash128_stat()
- {
- typedef hash128 hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef hash128::cmp compare;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash_type::make>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- ,co::compare< hash128::cmp >
- >::type
- > set_type2;
- test_rcu<set_type2, hash_type::make>(4, 2);
- }
-
- void MultiLevelHashSetHdrTest::rcu_gpt_nohash_5_3()
- {
- typedef size_t key_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_key<key_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, nohash<key_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(5, 3);
- }
-
- void MultiLevelHashSetHdrTest::rcu_gpt_hash128_4_3()
- {
- typedef hash128 hash_type;
-
- struct traits: public cc::multilevel_hashset::traits
- {
- typedef get_hash<hash_type> hash_accessor;
- typedef co::v::sequential_consistent memory_model;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash128::make >(4, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::memory_model< co::v::sequential_consistent >
- >::type
- > set_type2;
- test_rcu<set_type2, hash128::make >(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<key_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, nohash<key_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- typedef hash128::less less;
- typedef hash128::cmp compare;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash_type::make>(4, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , co::stat< cc::multilevel_hashset::stat<>>
- , co::less< hash_type::less >
- , co::compare< hash128::cmp >
- >::type
- > set_type2;
- test_rcu<set_type2, hash_type::make>(4, 3);
- }
-
-
-} // namespace set
+++ /dev/null
-//$$CDS-header$$
-
-#include "set/hdr_multilevel_hashset.h"
-#include <cds/urcu/signal_buffered.h>
-#include <cds/container/multilevel_hashset_rcu.h>
-#include "unit/print_multilevel_hashset_stat.h"
-
-namespace set {
-#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
- namespace {
- typedef cds::urcu::gc<cds::urcu::signal_buffered<>> 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<key_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_rcu<set_type, nohash<key_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
- typedef hash128::less less;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
- test_rcu<set_type, hash128::make>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , co::less< hash_type::less >
- >::type
- > set_type2;
- test_rcu<set_type2, hash128::make>(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<key_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_rcu<set_type, nohash<key_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- , co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
- typedef hash128::cmp compare;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash_type::make>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- ,co::compare< hash128::cmp >
- >::type
- > set_type2;
- test_rcu<set_type2, hash_type::make>(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<key_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, nohash<key_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
- typedef co::v::sequential_consistent memory_model;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash128::make >(4, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::memory_model< co::v::sequential_consistent >
- >::type
- > set_type2;
- test_rcu<set_type2, hash128::make >(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<key_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, nohash<key_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- typedef hash128::less less;
- typedef hash128::cmp compare;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash_type::make>(4, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , co::stat< cc::multilevel_hashset::stat<>>
- , co::less< hash_type::less >
- , co::compare< hash128::cmp >
- >::type
- > set_type2;
- test_rcu<set_type2, hash_type::make>(4, 3);
-#endif
- }
-} // namespace set
+++ /dev/null
-//$$CDS-header$$
-
-#include "set/hdr_multilevel_hashset.h"
-#include <cds/urcu/signal_threaded.h>
-#include <cds/container/multilevel_hashset_rcu.h>
-#include "unit/print_multilevel_hashset_stat.h"
-
-namespace set {
-#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
- namespace {
- typedef cds::urcu::gc<cds::urcu::signal_threaded<>> 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<key_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_rcu<set_type, nohash<key_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
- typedef hash128::less less;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash128!!!" );
- test_rcu<set_type, hash128::make>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , co::less< hash_type::less >
- >::type
- > set_type2;
- test_rcu<set_type2, hash128::make>(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<key_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!");
- test_rcu<set_type, nohash<key_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- , co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
- typedef hash128::cmp compare;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash_type::make>(4, 2);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- ,co::compare< hash128::cmp >
- >::type
- > set_type2;
- test_rcu<set_type2, hash_type::make>(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<key_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, nohash<key_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
- typedef co::v::sequential_consistent memory_model;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash128::make >(4, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::memory_model< co::v::sequential_consistent >
- >::type
- > set_type2;
- test_rcu<set_type2, hash128::make >(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<key_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<key_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, nohash<key_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<key_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_key<key_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, nohash<key_type>>(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_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, size_t>::value, "set::hash_type != size_t!!!" );
- test_rcu<set_type, std::hash<hash_type>>(5, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- ,co::stat< cc::multilevel_hashset::stat<>>
- >::type
- > set_type2;
- test_rcu<set_type2, std::hash<hash_type>>(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_type> hash_accessor;
- typedef cc::multilevel_hashset::stat<> stat;
- typedef hash128::less less;
- typedef hash128::cmp compare;
- };
- typedef cc::MultiLevelHashSet< rcu_type, Item<hash_type>, traits > set_type;
- static_assert(std::is_same< typename set_type::hash_type, hash_type>::value, "set::hash_type != hash_type!!!" );
- test_rcu<set_type, hash_type::make>(4, 3);
-
- typedef cc::MultiLevelHashSet<
- rcu_type,
- Item<hash_type>,
- typename cc::multilevel_hashset::make_traits<
- cc::multilevel_hashset::hash_accessor< get_hash<hash_type>>
- , co::stat< cc::multilevel_hashset::stat<>>
- , co::less< hash_type::less >
- , co::compare< hash128::cmp >
- >::type
- > set_type2;
- test_rcu<set_type2, hash_type::make>(4, 3);
-#endif
- }
-} // namespace set
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
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
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
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
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
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
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
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
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
)
// **************************************************************************************
-// 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
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();
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;
void operator()( bool /*bNew*/, Q const&, V& )
{}
- // MultiLevelHashMap
+ // FeldmanHashMap
template <typename Q>
void operator()( Q&, Q*)
{}
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)
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();
--- /dev/null
+//$$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<typename map_type< TAG, key_type, value_type>::X>(); }
+#include "map2/map_defs.h"
+
+namespace map2 {
+ CDSUNIT_DECLARE_FeldmanHashMap_fixed
+ CDSUNIT_DECLARE_FeldmanHashMap_city
+} // namespace map2
+++ /dev/null
-//$$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<typename map_type< TAG, key_type, value_type>::X>(); }
-#include "map2/map_defs.h"
-
-namespace map2 {
- CDSUNIT_DECLARE_MultiLevelHashMap_fixed
- CDSUNIT_DECLARE_MultiLevelHashMap_city
-} // 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();
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
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
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
--- /dev/null
+//$$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<typename map_type< TAG, key_type, value_type>::X>(); }
+#include "map2/map_defs.h"
+
+namespace map2 {
+ CDSUNIT_DECLARE_FeldmanHashMap
+} // namespace map2
+++ /dev/null
-//$$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<typename map_type< TAG, key_type, value_type>::X>(); }
-#include "map2/map_defs.h"
-
-namespace map2 {
- CDSUNIT_DECLARE_MultiLevelHashMap
-} // 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();
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
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
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
--- /dev/null
+//$$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<typename map_type< TAG, key_type, value_type>::X>(); }
+#include "map2/map_defs.h"
+
+namespace map2 {
+ CDSUNIT_DECLARE_FeldmanHashMap_md5
+ CDSUNIT_DECLARE_FeldmanHashMap_sha256
+ CDSUNIT_DECLARE_FeldmanHashMap_city
+} // namespace map2
+++ /dev/null
-//$$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<typename map_type< TAG, key_type, value_type>::X>(); }
-#include "map2/map_defs.h"
-
-namespace map2 {
- CDSUNIT_DECLARE_MultiLevelHashMap_md5
- CDSUNIT_DECLARE_MultiLevelHashMap_sha256
- CDSUNIT_DECLARE_MultiLevelHashMap_city
-} // namespace map2
c_nCuckooProbesetSize = cfg.getULong("CuckooProbesetSize", static_cast<unsigned long>(c_nCuckooProbesetSize) );
c_nCuckooProbesetThreshold = cfg.getULong("CuckooProbesetThreshold", static_cast<unsigned long>(c_nCuckooProbesetThreshold) );
- c_nMultiLevelMap_HeadBits = cfg.getULong("MultiLevelMapHeadBits", static_cast<unsigned long>(c_nMultiLevelMap_HeadBits) );
- c_nMultiLevelMap_ArrayBits = cfg.getULong("MultiLevelMapArrayBits", static_cast<unsigned long>(c_nMultiLevelMap_ArrayBits) );
+ c_nFeldmanMap_HeadBits = cfg.getULong("FeldmanMapHeadBits", static_cast<unsigned long>(c_nFeldmanMap_HeadBits) );
+ c_nFeldmanMap_ArrayBits = cfg.getULong("FeldmanMapArrayBits", static_cast<unsigned long>(c_nFeldmanMap_ArrayBits) );
}
} // 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
operator()( bNew, val.first, val.second );
}
- // For MultiLevelHashMap
+ // For FeldmanHashMap
template <typename Val>
void operator()( Val& cur, Val * old )
{
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
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
--- /dev/null
+//$$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<typename map_type< TAG, key_type, value_type>::X>(); }
+#include "map2/map_defs.h"
+
+namespace map2 {
+ CDSUNIT_DECLARE_FeldmanHashMap_fixed
+ CDSUNIT_DECLARE_FeldmanHashMap_city
+} // namespace map2
+++ /dev/null
-//$$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<typename map_type< TAG, key_type, value_type>::X>(); }
-#include "map2/map_defs.h"
-
-namespace map2 {
- CDSUNIT_DECLARE_MultiLevelHashMap_fixed
- CDSUNIT_DECLARE_MultiLevelHashMap_city
-} // namespace map2
c_nCuckooProbesetSize = cfg.getULong("CuckooProbesetSize", static_cast<unsigned long>(c_nCuckooProbesetSize) );
c_nCuckooProbesetThreshold = cfg.getULong("CuckooProbesetThreshold", static_cast<unsigned long>(c_nCuckooProbesetThreshold) );
- c_nMultiLevelMap_HeadBits = cfg.getULong("MultiLevelMapHeadBits", static_cast<unsigned long>(c_nMultiLevelMap_HeadBits) );
- c_nMultiLevelMap_ArrayBits = cfg.getULong("MultiLevelMapArrayBits", static_cast<unsigned long>(c_nMultiLevelMap_ArrayBits) );
+ c_nFeldmanMap_HeadBits = cfg.getULong("FeldmanMapHeadBits", static_cast<unsigned long>(c_nFeldmanMap_HeadBits) );
+ c_nFeldmanMap_ArrayBits = cfg.getULong("FeldmanMapArrayBits", static_cast<unsigned long>(c_nFeldmanMap_ArrayBits) );
c_bPrintGCState = cfg.getBool("PrintGCStateFlag", c_bPrintGCState );
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;
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
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
--- /dev/null
+//$$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<typename map_type< TAG, key_type, value_type>::X>(); }
+#include "map2/map_defs.h"
+
+namespace map2 {
+ CDSUNIT_DECLARE_FeldmanHashMap_fixed
+ CDSUNIT_DECLARE_FeldmanHashMap_city
+} // namespace map2
+++ /dev/null
-//$$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<typename map_type< TAG, key_type, value_type>::X>(); }
-#include "map2/map_defs.h"
-
-namespace map2 {
- CDSUNIT_DECLARE_MultiLevelHashMap_fixed
- CDSUNIT_DECLARE_MultiLevelHashMap_city
-} // 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;
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
val = key;
}
- // for MultiLevelHashMap
+ // for FeldmanHashMap
void operator()( std::pair<key_type const, value_type>& item, std::pair<key_type const, value_type> * pOld )
{
if ( !pOld )
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
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
--- /dev/null
+//$$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<typename map_type< TAG, key_type, value_type>::X>(); }
+#include "map2/map_defs.h"
+
+namespace map2 {
+ CDSUNIT_DECLARE_FeldmanHashMap_fixed
+ CDSUNIT_DECLARE_FeldmanHashMap_city
+} // namespace map2
+++ /dev/null
-//$$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<typename map_type< TAG, key_type, value_type>::X>(); }
-#include "map2/map_defs.h"
-
-namespace map2 {
- CDSUNIT_DECLARE_MultiLevelHashMap_fixed
- CDSUNIT_DECLARE_MultiLevelHashMap_city
-} // 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;
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
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
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
--- /dev/null
+//$$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<typename map_type< TAG, key_type, value_type>::X>(); }
+#include "map2/map_defs.h"
+
+namespace map2 {
+ CDSUNIT_DECLARE_FeldmanHashMap_md5
+ CDSUNIT_DECLARE_FeldmanHashMap_sha256
+ CDSUNIT_DECLARE_FeldmanHashMap_city
+} // namespace map2
+++ /dev/null
-//$$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<typename map_type< TAG, key_type, value_type>::X>(); }
-#include "map2/map_defs.h"
-
-namespace map2 {
- CDSUNIT_DECLARE_MultiLevelHashMap_md5
- CDSUNIT_DECLARE_MultiLevelHashMap_sha256
- CDSUNIT_DECLARE_MultiLevelHashMap_city
-} // 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();
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;
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
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
--- /dev/null
+//$$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<typename map_type< TAG, key_type, value_type>::X>(); }
+#include "map2/map_defs.h"
+
+namespace map2 {
+ CDSUNIT_DECLARE_FeldmanHashMap_sha256
+ CDSUNIT_DECLARE_FeldmanHashMap_city
+} // namespace map2
+++ /dev/null
-//$$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<typename map_type< TAG, key_type, value_type>::X>(); }
-#include "map2/map_defs.h"
-
-namespace map2 {
- CDSUNIT_DECLARE_MultiLevelHashMap_sha256
- CDSUNIT_DECLARE_MultiLevelHashMap_city
-} // 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;
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
void operator()( bool /*bNew*/, map_value_type& /*cur*/, Q const& /*val*/ )
{}
- // MultiLevelHashMap
+ // FeldmanHashMap
void operator()( map_value_type& /*cur*/, map_value_type * /*old*/)
{}
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
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
--- /dev/null
+//$$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<typename map_type< TAG, key_type, value_type>::X>(); }
+#include "map2/map_defs.h"
+
+namespace map2 {
+ CDSUNIT_DECLARE_FeldmanHashMap_fixed
+ CDSUNIT_DECLARE_FeldmanHashMap_city
+} // namespace map2
+++ /dev/null
-//$$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<typename map_type< TAG, key_type, value_type>::X>(); }
-#include "map2/map_defs.h"
-
-namespace map2 {
- CDSUNIT_DECLARE_MultiLevelHashMap_fixed
- CDSUNIT_DECLARE_MultiLevelHashMap_city
-} // 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();
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
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
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
--- /dev/null
+//$$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<typename map_type< TAG, key_type, value_type>::X>(); }
+#include "map2/map_defs.h"
+
+namespace map2 {
+ CDSUNIT_DECLARE_FeldmanHashMap_fixed
+ CDSUNIT_DECLARE_FeldmanHashMap_city
+} // namespace map2
+++ /dev/null
-//$$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<typename map_type< TAG, key_type, value_type>::X>(); }
-#include "map2/map_defs.h"
-
-namespace map2 {
- CDSUNIT_DECLARE_MultiLevelHashMap_fixed
- CDSUNIT_DECLARE_MultiLevelHashMap_city
-} // namespace map2
--- /dev/null
+//$$CDS-header$$
+
+#ifndef CDSUNIT_MAP_TYPE_FELDMAN_HASHMAP_H
+#define CDSUNIT_MAP_TYPE_FELDMAN_HASHMAP_H
+
+#include "map2/map_type.h"
+
+#include <cds/container/feldman_hashmap_hp.h>
+#include <cds/container/feldman_hashmap_dhp.h>
+#include <cds/container/feldman_hashmap_rcu.h>
+
+#include "print_feldman_hashset_stat.h"
+#include "hashing/hash_func.h"
+
+namespace map2 {
+
+ template <class GC, typename Key, typename T, typename Traits = cc::feldman_hashmap::traits>
+ class FeldmanHashMap : public cc::FeldmanHashMap< GC, Key, T, Traits >
+ {
+ typedef cc::FeldmanHashMap< GC, Key, T, Traits > base_class;
+ public:
+ template <typename Config>
+ 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 <typename Key, typename Value>
+ 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 <typename GC, typename K, typename T, typename Traits >
+ 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
+++ /dev/null
-//$$CDS-header$$
-
-#ifndef CDSUNIT_MAP_TYPE_MULTILEVEL_HASHMAP_H
-#define CDSUNIT_MAP_TYPE_MULTILEVEL_HASHMAP_H
-
-#include "map2/map_type.h"
-
-#include <cds/container/multilevel_hashmap_hp.h>
-#include <cds/container/multilevel_hashmap_dhp.h>
-#include <cds/container/multilevel_hashmap_rcu.h>
-
-#include "print_multilevel_hashset_stat.h"
-#include "hashing/hash_func.h"
-
-namespace map2 {
-
- template <class GC, typename Key, typename T, typename Traits = cc::multilevel_hashmap::traits>
- class MultiLevelHashMap : public cc::MultiLevelHashMap< GC, Key, T, Traits >
- {
- typedef cc::MultiLevelHashMap< GC, Key, T, Traits > base_class;
- public:
- template <typename Config>
- 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 <typename Key, typename Value>
- 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 <typename GC, typename K, typename T, typename Traits >
- 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
--- /dev/null
+//$$CDS-header$$
+
+#ifndef CDSUNIT_PRINT_FELDMAN_HASHSET_STAT_H
+#define CDSUNIT_PRINT_FELDMAN_HASHSET_STAT_H
+
+#include <cds/intrusive/details/feldman_hashset_base.h>
+#include <ostream>
+
+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
+++ /dev/null
-//$$CDS-header$$
-
-#ifndef CDSUNIT_PRINT_MULTILEVEL_HASHSET_STAT_H
-#define CDSUNIT_PRINT_MULTILEVEL_HASHSET_STAT_H
-
-#include <cds/intrusive/details/multilevel_hashset_base.h>
-#include <ostream>
-
-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
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
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
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
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
)
//***********************************************
-// 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
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();
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<size_t> m_arrData;
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();
};
--- /dev/null
+//$$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<typename set_type< TAG, key_type, value_type>::X>(); }
+#include "set2/set_defs.h"
+
+namespace set2 {
+ CDSUNIT_DECLARE_FeldmanHashSet_fixed
+ CDSUNIT_DECLARE_FeldmanHashSet_city
+} // namespace set2
+++ /dev/null
-//$$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<typename set_type< TAG, key_type, value_type>::X>(); }
-#include "set2/set_defs.h"
-
-namespace set2 {
- CDSUNIT_DECLARE_MultiLevelHashSet_fixed
- CDSUNIT_DECLARE_MultiLevelHashSet_city
-} // 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();
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;
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
--- /dev/null
+//$$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<typename set_type< TAG, key_type, value_type>::X>(); }
+#include "set2/set_defs.h"
+
+namespace set2 {
+ CDSUNIT_DECLARE_FeldmanHashSet_fixed
+ CDSUNIT_DECLARE_FeldmanHashSet_city
+} // namespace set2
+++ /dev/null
-//$$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<typename set_type< TAG, key_type, value_type>::X>(); }
-#include "set2/set_defs.h"
-
-namespace set2 {
- CDSUNIT_DECLARE_MultiLevelHashSet_fixed
- CDSUNIT_DECLARE_MultiLevelHashSet_city
-} // 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();
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;
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
--- /dev/null
+//$$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<typename set_type< TAG, key_type, value_type>::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
+++ /dev/null
-//$$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<typename set_type< TAG, key_type, value_type>::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
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();
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;
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
--- /dev/null
+//$$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<typename set_type< TAG, key_type, value_type>::X>(); }
+#include "set2/set_defs.h"
+
+namespace set2 {
+ CDSUNIT_DECLARE_FeldmanHashSet
+} // namespace set2
+++ /dev/null
-//$$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<typename set_type< TAG, key_type, value_type>::X>(); }
-#include "set2/set_defs.h"
-
-namespace set2 {
- CDSUNIT_DECLARE_MultiLevelHashSet
-} // namespace set2
--- /dev/null
+//$$CDS-header$$
+
+#ifndef CDSUNIT_SET_TYPE_MICHAEL_H
+#define CDSUNIT_SET_TYPE_MICHAEL_H
+
+#include "set2/set_type.h"
+
+#include <cds/container/feldman_hashset_hp.h>
+#include <cds/container/feldman_hashset_dhp.h>
+#include <cds/container/feldman_hashset_rcu.h>
+
+#include "print_feldman_hashset_stat.h"
+#include "hashing/hash_func.h"
+
+namespace set2 {
+
+ template <class GC, typename T, typename Traits = cc::feldman_hashset::traits>
+ class FeldmanHashSet : public cc::FeldmanHashSet< GC, T, Traits >
+ {
+ typedef cc::FeldmanHashSet< GC, T, Traits > base_class;
+
+ template <typename G>
+ struct get_extracted_ptr
+ {
+ typedef typename base_class::guarded_ptr extracted_ptr;
+ };
+
+ template <typename RCU>
+ struct get_extracted_ptr<cds::urcu::gc<RCU>>
+ {
+ typedef typename base_class::exempt_ptr extracted_ptr;
+ };
+
+ public:
+ typedef typename T::hasher hasher ;
+ typedef typename get_extracted_ptr<GC>::extracted_ptr extracted_ptr;
+
+ template <class Config>
+ FeldmanHashSet( Config const& cfg )
+ : base_class( cfg.c_nFeldmanSet_HeadBits, cfg.c_nFeldmanSet_ArrayBits )
+ {}
+
+ template <typename Q>
+ bool erase( Q const& key )
+ {
+ return base_class::erase( hasher()( key ));
+ }
+
+ template <typename Q, typename Func>
+ bool erase( Q const& key, Func f )
+ {
+ return base_class::erase( hasher()( key ), f );
+ }
+
+ template <typename Q>
+ extracted_ptr extract(Q const& key)
+ {
+ return base_class::extract( hasher()(key) );
+ }
+
+ template <typename Q>
+ 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 <typename Key, typename Val>
+ 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 <typename Hasher>
+ struct hash_type
+ {
+ typedef Hasher hasher;
+ typedef typename hasher::hash_type type;
+ };
+
+ template <typename TH>
+ struct hash_type<std::hash<TH>>
+ {
+ typedef std::hash<TH> hasher;
+ typedef size_t type;
+ };
+
+ template <typename Hasher>
+ struct key_val: base_class::key_val
+ {
+ typedef typename base_class::key_val base;
+ typedef Hasher hasher;
+ typedef typename hash_type<hasher>::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 <typename K>
+ /*explicit*/ key_val( K const& k ): base(k), hash( hasher()( k )) {}
+
+ template <typename K, typename T>
+ 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 Hasher>
+ typename key_val<Hasher>::hash_type const& operator()( key_val<Hasher> const& kv )
+ {
+ return kv.hash;
+ }
+ };
+ };
+
+ typedef FeldmanHashSet< cds::gc::HP, key_val<std::hash<key_type>>, default_traits > FeldmanHashSet_hp_stdhash;
+ typedef FeldmanHashSet< cds::gc::DHP, key_val<std::hash<key_type>>, default_traits > FeldmanHashSet_dhp_stdhash;
+ typedef FeldmanHashSet< rcu_gpi, key_val<std::hash<key_type>>, default_traits > FeldmanHashSet_rcu_gpi_stdhash;
+ typedef FeldmanHashSet< rcu_gpb, key_val<std::hash<key_type>>, default_traits > FeldmanHashSet_rcu_gpb_stdhash;
+ typedef FeldmanHashSet< rcu_gpt, key_val<std::hash<key_type>>, default_traits > FeldmanHashSet_rcu_gpt_stdhash;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef FeldmanHashSet< rcu_shb, key_val<std::hash<key_type>>, default_traits > FeldmanHashSet_rcu_shb_stdhash;
+ typedef FeldmanHashSet< rcu_sht, key_val<std::hash<key_type>>, 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<std::hash<key_type>>, traits_FeldmanHashSet_stat > FeldmanHashSet_hp_stdhash_stat;
+ typedef FeldmanHashSet< cds::gc::DHP, key_val<std::hash<key_type>>, traits_FeldmanHashSet_stat > FeldmanHashSet_dhp_stdhash_stat;
+ typedef FeldmanHashSet< rcu_gpi, key_val<std::hash<key_type>>, traits_FeldmanHashSet_stat > FeldmanHashSet_rcu_gpi_stdhash_stat;
+ typedef FeldmanHashSet< rcu_gpb, key_val<std::hash<key_type>>, traits_FeldmanHashSet_stat > FeldmanHashSet_rcu_gpb_stdhash_stat;
+ typedef FeldmanHashSet< rcu_gpt, key_val<std::hash<key_type>>, traits_FeldmanHashSet_stat > FeldmanHashSet_rcu_gpt_stdhash_stat;
+#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
+ typedef FeldmanHashSet< rcu_shb, key_val<std::hash<key_type>>, traits_FeldmanHashSet_stat > FeldmanHashSet_rcu_shb_stdhash_stat;
+ typedef FeldmanHashSet< rcu_sht, key_val<std::hash<key_type>>, 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 <typename K>
+ /*explicit*/ key_val(K const& k) : base_class(k) {}
+
+ template <typename K, typename T>
+ key_val(K const& k, T const& v) : base_class(k, v) {}
+
+ // mock hasher
+ struct hasher {
+ template <typename Q>
+ 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 <typename GC, typename T, typename Traits >
+ static inline void print_stat( FeldmanHashSet< GC, T, Traits > const& s )
+ {
+ CPPUNIT_MSG( s.statistics() );
+ }
+
+} // namespace set2
+
+#endif // #ifndef CDSUNIT_SET_TYPE_MICHAEL_H
+++ /dev/null
-//$$CDS-header$$
-
-#ifndef CDSUNIT_SET_TYPE_MICHAEL_H
-#define CDSUNIT_SET_TYPE_MICHAEL_H
-
-#include "set2/set_type.h"
-
-#include <cds/container/multilevel_hashset_hp.h>
-#include <cds/container/multilevel_hashset_dhp.h>
-#include <cds/container/multilevel_hashset_rcu.h>
-
-#include "print_multilevel_hashset_stat.h"
-#include "hashing/hash_func.h"
-
-namespace set2 {
-
- template <class GC, typename T, typename Traits = cc::multilevel_hashset::traits>
- class MultiLevelHashSet : public cc::MultiLevelHashSet< GC, T, Traits >
- {
- typedef cc::MultiLevelHashSet< GC, T, Traits > base_class;
-
- template <typename G>
- struct get_extracted_ptr
- {
- typedef typename base_class::guarded_ptr extracted_ptr;
- };
-
- template <typename RCU>
- struct get_extracted_ptr<cds::urcu::gc<RCU>>
- {
- typedef typename base_class::exempt_ptr extracted_ptr;
- };
-
- public:
- typedef typename T::hasher hasher ;
- typedef typename get_extracted_ptr<GC>::extracted_ptr extracted_ptr;
-
- template <class Config>
- MultiLevelHashSet( Config const& cfg )
- : base_class( cfg.c_nMultiLevelSet_HeadBits, cfg.c_nMultiLevelSet_ArrayBits )
- {}
-
- template <typename Q>
- bool erase( Q const& key )
- {
- return base_class::erase( hasher()( key ));
- }
-
- template <typename Q, typename Func>
- bool erase( Q const& key, Func f )
- {
- return base_class::erase( hasher()( key ), f );
- }
-
- template <typename Q>
- extracted_ptr extract(Q const& key)
- {
- return base_class::extract( hasher()(key) );
- }
-
- template <typename Q>
- 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 <typename Key, typename Val>
- 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 <typename Hasher>
- struct hash_type
- {
- typedef Hasher hasher;
- typedef typename hasher::hash_type type;
- };
-
- template <typename TH>
- struct hash_type<std::hash<TH>>
- {
- typedef std::hash<TH> hasher;
- typedef size_t type;
- };
-
- template <typename Hasher>
- struct key_val: base_class::key_val
- {
- typedef typename base_class::key_val base;
- typedef Hasher hasher;
- typedef typename hash_type<hasher>::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 <typename K>
- /*explicit*/ key_val( K const& k ): base(k), hash( hasher()( k )) {}
-
- template <typename K, typename T>
- 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 Hasher>
- typename key_val<Hasher>::hash_type const& operator()( key_val<Hasher> const& kv )
- {
- return kv.hash;
- }
- };
- };
-
- typedef MultiLevelHashSet< cds::gc::HP, key_val<std::hash<key_type>>, default_traits > MultiLevelHashSet_hp_stdhash;
- typedef MultiLevelHashSet< cds::gc::DHP, key_val<std::hash<key_type>>, default_traits > MultiLevelHashSet_dhp_stdhash;
- typedef MultiLevelHashSet< rcu_gpi, key_val<std::hash<key_type>>, default_traits > MultiLevelHashSet_rcu_gpi_stdhash;
- typedef MultiLevelHashSet< rcu_gpb, key_val<std::hash<key_type>>, default_traits > MultiLevelHashSet_rcu_gpb_stdhash;
- typedef MultiLevelHashSet< rcu_gpt, key_val<std::hash<key_type>>, default_traits > MultiLevelHashSet_rcu_gpt_stdhash;
-#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
- typedef MultiLevelHashSet< rcu_shb, key_val<std::hash<key_type>>, default_traits > MultiLevelHashSet_rcu_shb_stdhash;
- typedef MultiLevelHashSet< rcu_sht, key_val<std::hash<key_type>>, 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<std::hash<key_type>>, traits_MultiLevelHashSet_stat > MultiLevelHashSet_hp_stdhash_stat;
- typedef MultiLevelHashSet< cds::gc::DHP, key_val<std::hash<key_type>>, traits_MultiLevelHashSet_stat > MultiLevelHashSet_dhp_stdhash_stat;
- typedef MultiLevelHashSet< rcu_gpi, key_val<std::hash<key_type>>, traits_MultiLevelHashSet_stat > MultiLevelHashSet_rcu_gpi_stdhash_stat;
- typedef MultiLevelHashSet< rcu_gpb, key_val<std::hash<key_type>>, traits_MultiLevelHashSet_stat > MultiLevelHashSet_rcu_gpb_stdhash_stat;
- typedef MultiLevelHashSet< rcu_gpt, key_val<std::hash<key_type>>, traits_MultiLevelHashSet_stat > MultiLevelHashSet_rcu_gpt_stdhash_stat;
-#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
- typedef MultiLevelHashSet< rcu_shb, key_val<std::hash<key_type>>, traits_MultiLevelHashSet_stat > MultiLevelHashSet_rcu_shb_stdhash_stat;
- typedef MultiLevelHashSet< rcu_sht, key_val<std::hash<key_type>>, 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 <typename K>
- /*explicit*/ key_val(K const& k) : base_class(k) {}
-
- template <typename K, typename T>
- key_val(K const& k, T const& v) : base_class(k, v) {}
-
- // mock hasher
- struct hasher {
- template <typename Q>
- 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 <typename GC, typename T, typename Traits >
- static inline void print_stat( MultiLevelHashSet< GC, T, Traits > const& s )
- {
- CPPUNIT_MSG( s.statistics() );
- }
-
-} // namespace set2
-
-#endif // #ifndef CDSUNIT_SET_TYPE_MICHAEL_H