From: khizmax Date: Wed, 10 May 2017 21:01:35 +0000 (+0300) Subject: issue #76: added cds::atomicity::cache_friendly_item_counter to avoid false sharing X-Git-Tag: v2.3.0~39 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=51494783145ce52907dcb85e362629830ba46a97;p=libcds.git issue #76: added cds::atomicity::cache_friendly_item_counter to avoid false sharing issue #76: MichaelHashSet/Map: removed static_assert for empty_item_counter --- diff --git a/cds/algo/atomic.h b/cds/algo/atomic.h index 56b54ef7..dd8544de 100644 --- a/cds/algo/atomic.h +++ b/cds/algo/atomic.h @@ -32,6 +32,7 @@ #define CDSLIB_CXX11_ATOMIC_H #include +#include namespace cds { @@ -194,7 +195,9 @@ namespace cds { /// Atomic item counter /** This class is simplified interface around \p std::atomic_size_t. - The class supports getting of current value of the counter and increment/decrement its value. + The class supports getting current value of the counter and increment/decrement its value. + + See alûo improved version that eliminates false sharing: \p cache_friendly_item_counter. */ class item_counter { @@ -204,7 +207,7 @@ namespace cds { private: //@cond - atomic_type m_Counter ; ///< Atomic item counter + atomic_type m_Counter; ///< Atomic item counter //@endcond public: @@ -302,6 +305,121 @@ namespace cds { } }; + /// Atomic cache-friendly item counter + /** + Atomic item counter with cache-line padding to avoid false sharing. + Adding cache-line padding before and after atomic counter eliminates the contention + in read path of many containers and can notably improve search operations in sets/maps. + */ + class cache_friendly_item_counter + { + public: + typedef atomics::atomic_size_t atomic_type; ///< atomic type used + typedef size_t counter_type; ///< Integral item counter type (size_t) + + private: + //@cond + char pad1_[cds::c_nCacheLineSize]; + atomic_type m_Counter; ///< Atomic item counter + char pad2_[cds::c_nCacheLineSize - sizeof( atomic_type )]; + //@endcond + + public: + /// Default ctor initializes the counter to zero. + cache_friendly_item_counter() + : m_Counter(counter_type(0)) + {} + + /// Returns current value of the counter + counter_type value(atomics::memory_order order = atomics::memory_order_relaxed) const + { + return m_Counter.load( order ); + } + + /// Same as \ref value() with relaxed memory ordering + operator counter_type() const + { + return value(); + } + + /// Returns underlying atomic interface + atomic_type& getAtomic() + { + return m_Counter; + } + + /// Returns underlying atomic interface (const) + const atomic_type& getAtomic() const + { + return m_Counter; + } + + /// Increments the counter. Semantics: postincrement + counter_type inc(atomics::memory_order order = atomics::memory_order_relaxed ) + { + return m_Counter.fetch_add( 1, order ); + } + + /// Increments the counter. Semantics: postincrement + counter_type inc( counter_type count, atomics::memory_order order = atomics::memory_order_relaxed ) + { + return m_Counter.fetch_add( count, order ); + } + + /// Decrements the counter. Semantics: postdecrement + counter_type dec(atomics::memory_order order = atomics::memory_order_relaxed) + { + return m_Counter.fetch_sub( 1, order ); + } + + /// Decrements the counter. Semantics: postdecrement + counter_type dec( counter_type count, atomics::memory_order order = atomics::memory_order_relaxed ) + { + return m_Counter.fetch_sub( count, order ); + } + + /// Preincrement + counter_type operator ++() + { + return inc() + 1; + } + /// Postincrement + counter_type operator ++(int) + { + return inc(); + } + + /// Predecrement + counter_type operator --() + { + return dec() - 1; + } + /// Postdecrement + counter_type operator --(int) + { + return dec(); + } + + /// Increment by \p count + counter_type operator +=( counter_type count ) + { + return inc( count ) + count; + } + + /// Decrement by \p count + counter_type operator -=( counter_type count ) + { + return dec( count ) - count; + } + + /// Resets count to 0 + void reset(atomics::memory_order order = atomics::memory_order_relaxed) + { + m_Counter.store( 0, order ); + } + }; + + /// Empty item counter /** This class may be used instead of \ref item_counter when you do not need full \ref item_counter interface. diff --git a/cds/container/details/bronson_avltree_base.h b/cds/container/details/bronson_avltree_base.h index 49cfb877..52301645 100644 --- a/cds/container/details/bronson_avltree_base.h +++ b/cds/container/details/bronson_avltree_base.h @@ -440,7 +440,7 @@ namespace cds { namespace container { /// Item counter /** The type for item counter, by default it is disabled (\p atomicity::empty_item_counter). - To enable it use \p atomicity::item_counter + To enable it use \p atomicity::item_counter or \p atomicity::cache_friendly_item_counter. */ typedef atomicity::empty_item_counter item_counter; @@ -493,7 +493,7 @@ namespace cds { namespace container { - \p bronson_avltree::relaxed_insert - enable (\p true) or disable (\p false, the default) @ref bronson_avltree::relaxed_insert "relaxed insertion" - \p opt::item_counter - the type of item counting feature, by default it is disabled (\p atomicity::empty_item_counter) - To enable it use \p atomicity::item_counter + To enable it use \p atomicity::item_counter or \p atomicity::cache_friendly_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 bronson_avltree::empty_stat) diff --git a/cds/container/details/ellen_bintree_base.h b/cds/container/details/ellen_bintree_base.h index 91e2e2b2..5daf245a 100644 --- a/cds/container/details/ellen_bintree_base.h +++ b/cds/container/details/ellen_bintree_base.h @@ -162,7 +162,7 @@ namespace cds { namespace container { /// Item counter /** The type for item counter, by default it is disabled (\p atomicity::empty_item_counter). - To enable it use \p atomicity::item_counter + To enable it use \p atomicity::item_counter or \p atomicity::cache_friendly_item_counter */ typedef atomicity::empty_item_counter item_counter; @@ -247,7 +247,7 @@ namespace cds { namespace container { If the option is not specified, \p %opt::less is used. - \p opt::less - specifies binary predicate used for key compare. At least \p %opt::compare or \p %opt::less should be defined. - \p opt::item_counter - the type of item counter, default is disabled (\p atomicity::empty_item_counter). - To enable it use \p atomicity::item_counter + To enable it use \p atomicity::item_counter or \p atomicity::cache_friendly_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::allocator - the allocator for \ref ellen_bintree::node "leaf nodes" which contains data. @@ -287,7 +287,7 @@ namespace cds { namespace container { If the option is not specified, \p %opt::less is used. - \p opt::less - specifies binary predicate used for key compare. At least \p %opt::compare or \p %opt::less should be defined. - \p opt::item_counter - the type of item counter, default is disabled (\p atomicity::empty_item_counter). - To enable it use \p atomicity::item_counter + To enable it use \p atomicity::item_counter or \p atomicity::cache_friendly_item_counter - 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::allocator - the allocator used for \ref ellen_bintree::map_node "leaf nodes" which contains data. diff --git a/cds/container/details/iterable_list_base.h b/cds/container/details/iterable_list_base.h index 8200be39..69918019 100644 --- a/cds/container/details/iterable_list_base.h +++ b/cds/container/details/iterable_list_base.h @@ -78,7 +78,7 @@ namespace cds { namespace container { /// Back-off strategy typedef intrusive::iterable_list::traits::back_off back_off; - /// Item counting feature; by default, disabled. Use \p cds::atomicity::item_counter to enable item counting + /// Item counting feature; by default, disabled. Use \p cds::atomicity::item_counter or \p atomicity::cache_friendly_item_counter to enable item counting typedef intrusive::iterable_list::traits::item_counter item_counter; /// Internal statistics @@ -118,7 +118,7 @@ namespace cds { namespace container { - \p opt::node_allocator - node allocator, default is \p std::allocator. - \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. Default is disabled (\p atomicity::empty_item_counter). - To enable item counting use \p atomicity::item_counter. + To enable item counting use \p atomicity::item_counter or \p atomicity::cache_friendly_item_counter. - \p opt::stat - internal statistics. By default, it is disabled (\p iterable_list::empty_stat). To enable it use \p iterable_list::stat - \p opt::memory_model - C++ memory ordering model. Can be \p opt::v::relaxed_ordering (relaxed memory model, the default) diff --git a/cds/container/details/lazy_list_base.h b/cds/container/details/lazy_list_base.h index d4544355..95e6f2f2 100644 --- a/cds/container/details/lazy_list_base.h +++ b/cds/container/details/lazy_list_base.h @@ -144,7 +144,7 @@ namespace cds { namespace container { Note: unordering feature is not fully supported yet. - \p opt::back_off - back-off strategy used. If the option is not specified, \p cds::backoff::Default is used. - \p opt::item_counter - the type of item counting feature. Default is disabled (\p atomicity::empty_item_counter). - To enable item counting use \p atomicity::item_counter. + To enable item counting use \p atomicity::item_counter or \p atomicity::cache_friendly_item_counter - \p opt::stat - internal statistics. By default, it is disabled (\p lazy_list::empty_stat). To enable it use \p lazy_list::stat - \p opt::allocator - the allocator used for creating and freeing list's item. Default is \ref CDS_DEFAULT_ALLOCATOR macro. diff --git a/cds/container/details/michael_list_base.h b/cds/container/details/michael_list_base.h index fc10857a..866f4a8f 100644 --- a/cds/container/details/michael_list_base.h +++ b/cds/container/details/michael_list_base.h @@ -74,7 +74,7 @@ namespace cds { namespace container { /// Back-off strategy typedef cds::backoff::empty back_off; - /// Item counting feature; by default, disabled. Use \p cds::atomicity::item_counter to enable item counting + /// Item counting feature; by default, disabled. Use \p cds::atomicity::item_counter or \p atomicity::cache_friendly_item_counter to enable item counting typedef atomicity::empty_item_counter item_counter; /// Internal statistics @@ -113,7 +113,7 @@ namespace cds { namespace container { - \p opt::allocator - an allocator, default is \p CDS_DEFAULT_ALLOCATOR - \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. Default is disabled (\p atomicity::empty_item_counter). - To enable item counting use \p atomicity::item_counter. + To enable item counting use \p atomicity::item_counter or \p atomicity::cache_friendly_item_counter - \p opt::stat - internal statistics. By default, it is disabled (\p michael_list::empty_stat). To enable it use \p michael_list::stat - \p opt::memory_model - C++ memory ordering model. Can be \p opt::v::relaxed_ordering (relaxed memory model, the default) diff --git a/cds/container/michael_map.h b/cds/container/michael_map.h index 22b2dccf..9f851f69 100644 --- a/cds/container/michael_map.h +++ b/cds/container/michael_map.h @@ -171,10 +171,6 @@ namespace cds { namespace container { // GC and OrderedList::gc must be the same static_assert( std::is_same::value, "GC and OrderedList::gc must be the same"); - // atomicity::empty_item_counter is not allowed as a item counter - static_assert( !std::is_same::value, - "atomicity::empty_item_counter is not allowed as a item counter"); - static CDS_CONSTEXPR const size_t c_nHazardPtrCount = ordered_list::c_nHazardPtrCount; ///< Count of hazard pointer required //@cond @@ -194,8 +190,8 @@ namespace cds { namespace container { //@cond const size_t m_nHashBitmask; internal_bucket_type* m_Buckets; ///< bucket table - item_counter m_ItemCounter; ///< Item counter hash m_HashFunctor; ///< Hash functor + item_counter m_ItemCounter; ///< Item counter stat m_Stat; ///< Internal statistics //@endcond @@ -920,8 +916,8 @@ namespace cds { namespace container { /// 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 is an important part of the map implementation. + @warning If you use \p atomicity::empty_item_counter in \p traits::item_counter, + the function always returns \p true. */ bool empty() const { @@ -929,6 +925,10 @@ namespace cds { namespace container { } /// Returns item count in the map + /** + If you use \p atomicity::empty_item_counter in \p traits::item_counter, + the function always returns 0. + */ size_t size() const { return m_ItemCounter; diff --git a/cds/container/michael_map_nogc.h b/cds/container/michael_map_nogc.h index 7d3c2e84..04299da9 100644 --- a/cds/container/michael_map_nogc.h +++ b/cds/container/michael_map_nogc.h @@ -79,10 +79,6 @@ namespace cds { namespace container { // GC and OrderedList::gc must be the same static_assert(std::is_same::value, "GC and OrderedList::gc must be the same"); - // atomicity::empty_item_counter is not allowed as a item counter - static_assert(!std::is_same::value, - "cds::atomicity::empty_item_counter is not allowed as a item counter"); - protected: //@cond typedef typename ordered_list::template select_stat_wrapper< typename ordered_list::stat > bucket_stat; @@ -107,10 +103,10 @@ namespace cds { namespace container { protected: //@cond const size_t m_nHashBitmask; - item_counter m_ItemCounter; ///< Item counter - hash m_HashFunctor; ///< Hash functor + hash m_HashFunctor; ///< Hash functor internal_bucket_type* m_Buckets; ///< bucket table - stat m_Stat; ///< Internal statistics + item_counter m_ItemCounter; ///< Item counter + stat m_Stat; ///< Internal statistics //@endcond protected: @@ -530,8 +526,8 @@ namespace cds { namespace container { /// Checks whether 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 Michael's map implementation. + @warning If you use \p atomicity::empty_item_counter in \p traits::item_counter, + the function always returns \p true. */ bool empty() const { @@ -539,6 +535,10 @@ namespace cds { namespace container { } /// Returns item count in the map + /** + If you use \p atomicity::empty_item_counter in \p traits::item_counter, + the function always returns 0. + */ size_t size() const { return m_ItemCounter; diff --git a/cds/container/michael_map_rcu.h b/cds/container/michael_map_rcu.h index d036e0ab..93198b8d 100644 --- a/cds/container/michael_map_rcu.h +++ b/cds/container/michael_map_rcu.h @@ -109,10 +109,6 @@ namespace cds { namespace container { // GC and OrderedList::gc must be the same static_assert(std::is_same::value, "GC and OrderedList::gc must be the same"); - // atomicity::empty_item_counter is not allowed as a item counter - static_assert(!std::is_same::value, - "cds::atomicity::empty_item_counter is not allowed as a item counter"); - protected: //@cond typedef typename ordered_list::template select_stat_wrapper< typename ordered_list::stat > bucket_stat; @@ -137,10 +133,10 @@ namespace cds { namespace container { protected: //@cond const size_t m_nHashBitmask; - item_counter m_ItemCounter; ///< Item counter - hash m_HashFunctor; ///< Hash functor - internal_bucket_type * m_Buckets; ///< bucket table - stat m_Stat; ///< Internal statistics + hash m_HashFunctor; ///< Hash functor + internal_bucket_type* m_Buckets; ///< bucket table + item_counter m_ItemCounter; ///< Item counter + stat m_Stat; ///< Internal statistics //@endcond protected: @@ -791,8 +787,8 @@ namespace cds { namespace container { /// 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 is an important part of the map implementation. + @warning If you use \p atomicity::empty_item_counter in \p traits::item_counter, + the function always returns \p true. */ bool empty() const { @@ -800,6 +796,10 @@ namespace cds { namespace container { } /// Returns item count in the map + /** + @warning If you use \p atomicity::empty_item_counter in \p traits::item_counter, + the function always returns 0. + */ size_t size() const { return m_ItemCounter; diff --git a/cds/container/michael_set.h b/cds/container/michael_set.h index cdd383f4..fb23c442 100644 --- a/cds/container/michael_set.h +++ b/cds/container/michael_set.h @@ -188,10 +188,6 @@ namespace cds { namespace container { // GC and OrderedList::gc must be the same static_assert( std::is_same::value, "GC and OrderedList::gc must be the same"); - // atomicity::empty_item_counter is not allowed as a item counter - static_assert( !std::is_same::value, - "cds::atomicity::empty_item_counter is not allowed as a item counter"); - //@cond typedef typename ordered_list::template select_stat_wrapper< typename ordered_list::stat > bucket_stat; @@ -213,8 +209,8 @@ namespace cds { namespace container { //@cond size_t const m_nHashBitmask; internal_bucket_type * m_Buckets; ///< bucket table - item_counter m_ItemCounter; ///< Item counter hash m_HashFunctor; ///< Hash functor + item_counter m_ItemCounter; ///< Item counter stat m_Stat; ///< Internal statistics //@endcond @@ -868,8 +864,8 @@ namespace cds { namespace container { /// 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 Michael's set implementation. + @warning If you use \p atomicity::empty_item_counter in \p traits::item_counter, + the function always returns \p true. */ bool empty() const { @@ -877,6 +873,10 @@ namespace cds { namespace container { } /// Returns item count in the set + /** + @warning If you use \p atomicity::empty_item_counter in \p traits::item_counter, + the function always returns 0. + */ size_t size() const { return m_ItemCounter; diff --git a/cds/container/michael_set_nogc.h b/cds/container/michael_set_nogc.h index 6f1d293d..efb6901b 100644 --- a/cds/container/michael_set_nogc.h +++ b/cds/container/michael_set_nogc.h @@ -76,10 +76,6 @@ namespace cds { namespace container { // GC and OrderedList::gc must be the same static_assert(std::is_same::value, "GC and OrderedList::gc must be the same"); - // atomicity::empty_item_counter is not allowed as a item counter - static_assert(!std::is_same::value, - "cds::atomicity::empty_item_counter is not allowed as a item counter"); - protected: //@cond typedef typename ordered_list::template select_stat_wrapper< typename ordered_list::stat > bucket_stat; @@ -115,10 +111,10 @@ namespace cds { namespace container { protected: //@cond const size_t m_nHashBitmask; - item_counter m_ItemCounter; ///< Item counter hash m_HashFunctor; ///< Hash functor internal_bucket_type* m_Buckets; ///< bucket table - stat m_Stat; ///< Internal statistics + item_counter m_ItemCounter; ///< Item counter + stat m_Stat; ///< Internal statistics //@endcond public: @@ -379,8 +375,8 @@ namespace cds { namespace container { /// Checks if the set is empty /** - The emptiness is checked by the item counting: if item count is zero then the set is empty. - Thus, the correct item counting feature is an important part of Michael's set implementation. + @warning If you use \p atomicity::empty_item_counter in \p traits::item_counter, + the function always returns \p true. */ bool empty() const { @@ -388,6 +384,10 @@ namespace cds { namespace container { } /// Returns item count in the set + /** + @warning If you use \p atomicity::empty_item_counter in \p traits::item_counter, + the function always returns 0. + */ size_t size() const { return m_ItemCounter; diff --git a/cds/container/michael_set_rcu.h b/cds/container/michael_set_rcu.h index 75ab34da..34bc0c2b 100644 --- a/cds/container/michael_set_rcu.h +++ b/cds/container/michael_set_rcu.h @@ -159,9 +159,6 @@ namespace cds { namespace container { // GC and OrderedList::gc must be the same static_assert(std::is_same::value, "GC and OrderedList::gc must be the same"); - static_assert(!std::is_same::value, - "atomicity::empty_item_counter is not allowed as a item counter"); - //@cond typedef typename ordered_list::template select_stat_wrapper< typename ordered_list::stat > bucket_stat; @@ -192,9 +189,9 @@ namespace cds { namespace container { typedef typename allocator::template rebind< internal_bucket_type >::other bucket_table_allocator; const size_t m_nHashBitmask; - item_counter m_ItemCounter; ///< Item counter hash m_HashFunctor; ///< Hash functor internal_bucket_type* m_Buckets; ///< bucket table + item_counter m_ItemCounter; ///< Item counter stat m_Stat; ///< Internal statistics //@endcond @@ -743,8 +740,8 @@ namespace cds { namespace container { /// 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 Michael's set implementation. + @warning If you use \p atomicity::empty_item_counter in \p traits::item_counter, + the function always returns \p true. */ bool empty() const { @@ -752,6 +749,10 @@ namespace cds { namespace container { } /// Returns item count in the set + /** + @warning If you use \p atomicity::empty_item_counter in \p traits::item_counter, + the function always returns 0. + */ size_t size() const { return m_ItemCounter; diff --git a/cds/intrusive/details/ellen_bintree_base.h b/cds/intrusive/details/ellen_bintree_base.h index 75c6da8a..ed03e3b8 100644 --- a/cds/intrusive/details/ellen_bintree_base.h +++ b/cds/intrusive/details/ellen_bintree_base.h @@ -515,7 +515,7 @@ namespace cds { namespace intrusive { /// Item counter /** The type for item counter, by default it is disabled (\p atomicity::empty_item_counter). - To enable it use \p atomicity::item_counter + To enable it use \p atomicity::item_counter or \p atomicity::cache_friendly_item_counter */ typedef atomicity::empty_item_counter item_counter; @@ -582,7 +582,7 @@ namespace cds { namespace intrusive { - \p opt::disposer - the functor used for dispose removed nodes. Default is \p opt::v::empty_disposer. Due the nature of GC schema the disposer may be called asynchronously. The disposer is used only for leaf nodes. - \p opt::item_counter - the type of item counting feature, by default it is disabled (\p atomicity::empty_item_counter) - To enable it use \p atomicity::item_counter + To enable it use \p atomicity::item_counter or \p atomicity::cache_friendly_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 ellen_bintree::update_desc_allocator - an allocator of \ref ellen_bintree::update_desc "update descriptors", diff --git a/cds/intrusive/details/feldman_hashset_base.h b/cds/intrusive/details/feldman_hashset_base.h index 626e5bc7..60b00a62 100644 --- a/cds/intrusive/details/feldman_hashset_base.h +++ b/cds/intrusive/details/feldman_hashset_base.h @@ -243,7 +243,7 @@ namespace cds { namespace intrusive { 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. + Default is \p atomicity::item_counter. To avoid false sharing you can aldo use \p atomicity::cache_friendly_item_counter */ typedef cds::atomicity::item_counter item_counter; @@ -301,7 +301,7 @@ namespace cds { namespace intrusive { 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. + Default is \p atomicity::item_counter. To avoid false sharing you can use or \p atomicity::cache_friendly_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). diff --git a/cds/intrusive/details/iterable_list_base.h b/cds/intrusive/details/iterable_list_base.h index 3c69cf9f..113b72d6 100644 --- a/cds/intrusive/details/iterable_list_base.h +++ b/cds/intrusive/details/iterable_list_base.h @@ -212,7 +212,7 @@ namespace cds { namespace intrusive { */ typedef empty_stat stat; - /// Item counting feature; by default, disabled. Use \p cds::atomicity::item_counter to enable item counting + /// Item counting feature; by default, disabled. Use \p cds::atomicity::item_counter or \p atomicity::cache_friendly_item_counter to enable item counting typedef atomicity::empty_item_counter item_counter; /// C++ memory ordering model @@ -234,7 +234,7 @@ namespace cds { namespace intrusive { - \p opt::disposer - the functor used for disposing removed items. 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. Default is disabled (\p atomicity::empty_item_counter). - To enable item counting use \p atomicity::item_counter. + To enable item counting use \p atomicity::item_counter or \p atomicity::cache_friendly_item_counter - \p opt::stat - internal statistics. By default, it is disabled (\p iterable_list::empty_stat). To enable it use \p iterable_list::stat - \p opt::memory_model - C++ memory ordering model. Can be \p opt::v::relaxed_ordering (relaxed memory model, the default) diff --git a/cds/intrusive/details/lazy_list_base.h b/cds/intrusive/details/lazy_list_base.h index bda8b449..bf3731c7 100644 --- a/cds/intrusive/details/lazy_list_base.h +++ b/cds/intrusive/details/lazy_list_base.h @@ -352,7 +352,7 @@ namespace cds { namespace intrusive { /// Disposer for removing items typedef opt::v::empty_disposer disposer; - /// Item counting feature; by default, disabled. Use \p cds::atomicity::item_counter to enable item counting + /// Item counting feature; by default, disabled. Use \p cds::atomicity::item_counter or \p atomicity::cache_friendly_item_counter to enable item counting typedef atomicity::empty_item_counter item_counter; /// Internal statistics @@ -399,7 +399,7 @@ namespace cds { namespace intrusive { of GC schema the disposer may be called asynchronously. - \p opt::link_checker - the type of node's link fields checking. Default is \p opt::debug_check_link - \p opt::item_counter - the type of item counting feature. Default is disabled (\p atomicity::empty_item_counter). - To enable item counting use \p atomicity::item_counter. + To enable item counting use \p atomicity::item_counter or \p atomicity::cache_friendly_item_counter - \p opt::stat - internal statistics. By default, it is disabled (\p lazy_list::empty_stat). To enable it use \p lazy_list::stat - \p opt::memory_model - C++ memory ordering model. Can be \p opt::v::relaxed_ordering (relaxed memory model, the default) diff --git a/cds/intrusive/details/michael_list_base.h b/cds/intrusive/details/michael_list_base.h index 48e63c78..c789be08 100644 --- a/cds/intrusive/details/michael_list_base.h +++ b/cds/intrusive/details/michael_list_base.h @@ -318,7 +318,7 @@ namespace cds { namespace intrusive { /// Disposer for removing items typedef opt::v::empty_disposer disposer; - /// Item counting feature; by default, disabled. Use \p cds::atomicity::item_counter to enable item counting + /// Item counting feature; by default, disabled. Use \p cds::atomicity::item_counter or \p atomicity::cache_friendly_item_counter to enable item counting typedef atomicity::empty_item_counter item_counter; /// Internal statistics @@ -361,7 +361,7 @@ namespace cds { namespace intrusive { of GC schema the disposer may be called asynchronously. - \p opt::link_checker - the type of node's link fields checking. Default is \p opt::debug_check_link - \p opt::item_counter - the type of item counting feature. Default is disabled (\p atomicity::empty_item_counter). - To enable item counting use \p atomicity::item_counter. + To enable item counting use \p atomicity::item_counter or \p atomicity::cache_friendly_item_counter - \p opt::stat - internal statistics. By default, it is disabled (\p michael_list::empty_stat). To enable it use \p michael_list::stat - \p opt::memory_model - C++ memory ordering model. Can be \p opt::v::relaxed_ordering (relaxed memory model, the default) diff --git a/cds/intrusive/details/michael_set_base.h b/cds/intrusive/details/michael_set_base.h index 9bf2cd73..8e63cf38 100644 --- a/cds/intrusive/details/michael_set_base.h +++ b/cds/intrusive/details/michael_set_base.h @@ -58,9 +58,10 @@ namespace cds { namespace intrusive { /** The item counting is an important part of \p MichaelHashSet 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. + You may use \p atomicity::empty_item_counter if don't need \p empty() and \p size() + member functions. - Default is \p atomicity::item_counter. + Default is \p atomicity::item_counter; to avoid false sharing you may use \p atomicity::cache_friendly_item_counter */ typedef cds::atomicity::item_counter item_counter; diff --git a/cds/intrusive/details/skip_list_base.h b/cds/intrusive/details/skip_list_base.h index c902c770..e2f4d52d 100644 --- a/cds/intrusive/details/skip_list_base.h +++ b/cds/intrusive/details/skip_list_base.h @@ -613,7 +613,7 @@ namespace cds { namespace intrusive { /** The type for item counting feature. By default, item counting is disabled (\p atomicity::empty_item_counter), - \p atomicity::item_counter enables it. + \p atomicity::item_counter or \p atomicity::cache_friendly_item_counter enables it. */ typedef atomicity::empty_item_counter item_counter; @@ -680,7 +680,7 @@ namespace cds { namespace intrusive { - \p opt::disposer - the functor used for dispose removed items. 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. Default is disabled, i.e. \p atomicity::empty_item_counter. - To enable it use \p atomicity::item_counter + To enable it use \p atomicity::item_counter or \p atomicity::cache_friendly_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 skip_list::random_level_generator - random level generator. Can be \p skip_list::xor_shift, diff --git a/cds/intrusive/details/split_list_base.h b/cds/intrusive/details/split_list_base.h index 71d47744..e4ef11ad 100644 --- a/cds/intrusive/details/split_list_base.h +++ b/cds/intrusive/details/split_list_base.h @@ -257,7 +257,7 @@ namespace cds { namespace intrusive { the empty() member function depends on correct item counting. Therefore, \p cds::atomicity::empty_item_counter is not allowed as a type of the option. - Default is \p cds::atomicity::item_counter. + Default is \p cds::atomicity::item_counter; to avoid false sharing you may use \p atomicity::cache_friendly_item_counter */ typedef cds::atomicity::item_counter item_counter; diff --git a/cds/intrusive/impl/skip_list.h b/cds/intrusive/impl/skip_list.h index 8ee2d69e..c8cc11fd 100644 --- a/cds/intrusive/impl/skip_list.h +++ b/cds/intrusive/impl/skip_list.h @@ -1778,9 +1778,9 @@ namespace cds { namespace intrusive { //@cond skip_list::details::head_node< node_type > m_Head; ///< head tower (max height) - item_counter m_ItemCounter; ///< item counter random_level_generator m_RandomLevelGen; ///< random level generator instance atomics::atomic m_nHeight; ///< estimated high level + item_counter m_ItemCounter; ///< item counter mutable stat m_Stat; ///< internal statistics //@endcond }; diff --git a/cds/intrusive/michael_set.h b/cds/intrusive/michael_set.h index 8e21f85f..c1daccfc 100644 --- a/cds/intrusive/michael_set.h +++ b/cds/intrusive/michael_set.h @@ -271,10 +271,6 @@ namespace cds { namespace intrusive { // GC and OrderedList::gc must be the same static_assert(std::is_same::value, "GC and OrderedList::gc must be the same"); - // atomicity::empty_item_counter is not allowed as a item counter - static_assert(!std::is_same::value, - "cds::atomicity::empty_item_counter is not allowed as a item counter"); - protected: //@cond typedef typename ordered_list::template select_stat_wrapper< typename ordered_list::stat > bucket_stat; @@ -929,8 +925,8 @@ namespace cds { namespace intrusive { /// 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 Michael's set implementation. + @warning If you use \p atomicity::empty_item_counter in \p traits::item_counter, + the function always returns \p true. */ bool empty() const { @@ -938,6 +934,10 @@ namespace cds { namespace intrusive { } /// Returns item count in the set + /** + If you use \p atomicity::empty_item_counter in \p traits::item_counter, + the function always returns 0. + */ size_t size() const { return m_ItemCounter; diff --git a/cds/intrusive/michael_set_nogc.h b/cds/intrusive/michael_set_nogc.h index cd6b675b..883e8526 100644 --- a/cds/intrusive/michael_set_nogc.h +++ b/cds/intrusive/michael_set_nogc.h @@ -77,10 +77,6 @@ namespace cds { namespace intrusive { // GC and OrderedList::gc must be the same static_assert(std::is_same::value, "GC and OrderedList::gc must be the same"); - // atomicity::empty_item_counter is not allowed as a item counter - static_assert(!std::is_same::value, - "atomicity::empty_item_counter is not allowed as a item counter"); - protected: //@cond typedef typename ordered_list::template select_stat_wrapper< typename ordered_list::stat > bucket_stat; @@ -421,8 +417,8 @@ namespace cds { namespace intrusive { /// 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 Michael's set implementation. + @warning If you use \p atomicity::empty_item_counter in \p traits::item_counter, + the function always returns \p true. */ bool empty() const { @@ -430,6 +426,10 @@ namespace cds { namespace intrusive { } /// Returns item count in the set + /** + If you use \p atomicity::empty_item_counter in \p traits::item_counter, + the function always returns 0. + */ size_t size() const { return m_ItemCounter; diff --git a/cds/intrusive/michael_set_rcu.h b/cds/intrusive/michael_set_rcu.h index b105a8ef..43a26138 100644 --- a/cds/intrusive/michael_set_rcu.h +++ b/cds/intrusive/michael_set_rcu.h @@ -124,10 +124,6 @@ namespace cds { namespace intrusive { // GC and OrderedList::gc must be the same static_assert(std::is_same::value, "GC and OrderedList::gc must be the same"); - // atomicity::empty_item_counter is not allowed as a item counter - static_assert(!std::is_same::value, - "atomicity::empty_item_counter is not allowed as a item counter"); - protected: //@cond typedef typename ordered_list::template select_stat_wrapper< typename ordered_list::stat > bucket_stat; @@ -701,8 +697,8 @@ namespace cds { namespace intrusive { /// 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 Michael's set implementation. + @warning If you use \p atomicity::empty_item_counter in \p traits::item_counter, + the function always returns \p true. */ bool empty() const { @@ -710,6 +706,10 @@ namespace cds { namespace intrusive { } /// Returns item count in the set + /** + If you use \p atomicity::empty_item_counter in \p traits::item_counter, + the function always returns 0. + */ size_t size() const { return m_ItemCounter; diff --git a/cds/intrusive/skip_list_nogc.h b/cds/intrusive/skip_list_nogc.h index a37ec3dd..fc6ae8ed 100644 --- a/cds/intrusive/skip_list_nogc.h +++ b/cds/intrusive/skip_list_nogc.h @@ -445,9 +445,9 @@ namespace cds { namespace intrusive { protected: head_node m_Head; ///< head tower (max height) - item_counter m_ItemCounter; ///< item counter random_level_generator m_RandomLevelGen; ///< random level generator instance atomics::atomic m_nHeight; ///< estimated high level + item_counter m_ItemCounter; ///< item counter mutable stat m_Stat; ///< internal statistics protected: diff --git a/cds/intrusive/skip_list_rcu.h b/cds/intrusive/skip_list_rcu.h index 2e35c9af..b153aa80 100644 --- a/cds/intrusive/skip_list_rcu.h +++ b/cds/intrusive/skip_list_rcu.h @@ -632,10 +632,10 @@ namespace cds { namespace intrusive { protected: skip_list::details::head_node< node_type > m_Head; ///< head tower (max height) - item_counter m_ItemCounter; ///< item counter random_level_generator m_RandomLevelGen; ///< random level generator instance atomics::atomic m_nHeight; ///< estimated high level atomics::atomic m_pDeferredDelChain ; ///< Deferred deleted node chain + item_counter m_ItemCounter; ///< item counter mutable stat m_Stat; ///< internal statistics protected: diff --git a/cds/intrusive/split_list.h b/cds/intrusive/split_list.h index fe792e06..1eadcfe3 100644 --- a/cds/intrusive/split_list.h +++ b/cds/intrusive/split_list.h @@ -1453,8 +1453,8 @@ namespace cds { namespace intrusive { atomics::atomic m_nBucketCountLog2; ///< log2( current bucket count ) atomics::atomic m_nMaxItemCount; ///< number of items container can hold, before we have to resize - item_counter m_ItemCounter; ///< Item counter hash m_HashFunctor; ///< Hash functor + item_counter m_ItemCounter; ///< Item counter stat m_Stat; ///< Internal statistics //@endcond }; diff --git a/cds/intrusive/split_list_nogc.h b/cds/intrusive/split_list_nogc.h index 10cb0462..68c0d250 100644 --- a/cds/intrusive/split_list_nogc.h +++ b/cds/intrusive/split_list_nogc.h @@ -732,8 +732,8 @@ namespace cds { namespace intrusive { atomics::atomic m_nBucketCountLog2; ///< log2( current bucket count ) atomics::atomic m_nMaxItemCount; ///< number of items container can hold, before we have to resize - item_counter m_ItemCounter; ///< Item counter hash m_HashFunctor; ///< Hash functor + item_counter m_ItemCounter; ///< Item counter stat m_Stat; ///< Internal statistics //@endcond }; diff --git a/cds/intrusive/split_list_rcu.h b/cds/intrusive/split_list_rcu.h index 117e49fc..64583fe4 100644 --- a/cds/intrusive/split_list_rcu.h +++ b/cds/intrusive/split_list_rcu.h @@ -1118,8 +1118,8 @@ namespace cds { namespace intrusive { atomics::atomic m_nBucketCountLog2; ///< log2( current bucket count ) atomics::atomic m_nMaxItemCount; ///< number of items container can hold, before we have to resize - item_counter m_ItemCounter; ///< Item counter hash m_HashFunctor; ///< Hash functor + item_counter m_ItemCounter; ///< Item counter stat m_Stat; ///< Internal statistics accumulator //@endcond }; diff --git a/cds/opt/options.h b/cds/opt/options.h index 5ab9c169..70faba71 100644 --- a/cds/opt/options.h +++ b/cds/opt/options.h @@ -304,15 +304,16 @@ namespace opt { Predefined option \p Type: - \p atomicity::empty_item_counter - no item counting performed. It is default policy for many containers - - \p atomicity::item_counter - the class that provides atomically item counting - - \p opt::v::sequential_item_counter - simple non-atomic item counter. This item counter is not intended for + - \p atomicity::item_counter - the class that provides atomic item counting + - \p atomicity::cache_friendly_item_counter - cache-friendly atomic item counter + - \p opt::v::sequential_item_counter - simple non-atomic item counter. This counter is not intended for concurrent containers and may be used only if it is explicitly noted. You may provide other implementation of \p atomicity::item_counter interface for your needs. Note, the item counting in lock-free containers cannot be exact; for example, if item counter for a container returns zero it is not mean that the container is empty. - Thus, the item counter may be used for statistical purposes only. + So, the item counter may be used for statistical purposes only. */ template struct item_counter { diff --git a/test/stress/map/map_type_bronson_avltree.h b/test/stress/map/map_type_bronson_avltree.h index 757a1126..d12bca6e 100644 --- a/test/stress/map/map_type_bronson_avltree.h +++ b/test/stress/map/map_type_bronson_avltree.h @@ -93,7 +93,7 @@ namespace map { cc::bronson_avltree::make_traits< co::less< less > ,cc::bronson_avltree::relaxed_insert< false > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef BronsonAVLTreeMap< rcu_gpi, Key, Value, BronsonAVLTreeMap_less > BronsonAVLTreeMap_rcu_gpi_less; @@ -106,7 +106,7 @@ namespace map { cc::bronson_avltree::make_traits< co::compare< compare > ,cc::bronson_avltree::relaxed_insert< false > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > ,co::stat< cc::bronson_avltree::stat<>> >::type {}; diff --git a/test/stress/map/map_type_ellen_bintree.h b/test/stress/map/map_type_ellen_bintree.h index 2e40d85a..63ec8b63 100644 --- a/test/stress/map/map_type_ellen_bintree.h +++ b/test/stress/map/map_type_ellen_bintree.h @@ -121,7 +121,7 @@ namespace map { struct traits_EllenBinTreeMap: public cc::ellen_bintree::make_set_traits< co::less< less > ,co::node_allocator< ellen_bintree_pool::internal_node_allocator< int > > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; struct traits_EllenBinTreeMap_hp : traits_EllenBinTreeMap { @@ -183,7 +183,7 @@ namespace map { > ,co::node_allocator< ellen_bintree_pool::internal_node_allocator< int > > ,co::stat< cc::ellen_bintree::stat<> > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; diff --git a/test/stress/map/map_type_feldman_hashmap.h b/test/stress/map/map_type_feldman_hashmap.h index c12b73f0..16421568 100644 --- a/test/stress/map/map_type_feldman_hashmap.h +++ b/test/stress/map/map_type_feldman_hashmap.h @@ -105,6 +105,7 @@ namespace map { { typedef std::hash< Key > hash; typedef std::less less; + typedef cds::atomicity::cache_friendly_item_counter item_counter; }; typedef FeldmanHashMap< cds::gc::HP, Key, Value, traits_FeldmanHashMap_stdhash > FeldmanHashMap_hp_stdhash; @@ -137,6 +138,7 @@ namespace map { { typedef ::cds_test::city64 hash; typedef ::cds_test::city64::less less; + typedef cds::atomicity::cache_friendly_item_counter item_counter; }; 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; @@ -164,6 +166,7 @@ namespace map { { typedef ::cds_test::city128 hash; typedef ::cds_test::city128::less less; + typedef cds::atomicity::cache_friendly_item_counter item_counter; }; 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; @@ -193,6 +196,7 @@ namespace map { struct traits_FeldmanHashMap_fixed: public cc::feldman_hashmap::traits { typedef map::cmp compare; + typedef cds::atomicity::cache_friendly_item_counter item_counter; }; typedef FeldmanHashMap< cds::gc::HP, Key, Value, traits_FeldmanHashMap_fixed > FeldmanHashMap_hp_fixed; diff --git a/test/stress/map/map_type_michael.h b/test/stress/map/map_type_michael.h index 988b7380..bcab5ad2 100644 --- a/test/stress/map/map_type_michael.h +++ b/test/stress/map/map_type_michael.h @@ -85,6 +85,7 @@ namespace map { struct traits_MichaelMap_hash : public cc::michael_map::make_traits< co::hash< hash > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; diff --git a/test/stress/map/map_type_skip_list.h b/test/stress/map/map_type_skip_list.h index 7802a08c..5db6b6e5 100644 --- a/test/stress/map/map_type_skip_list.h +++ b/test/stress/map/map_type_skip_list.h @@ -86,7 +86,7 @@ namespace map { class traits_SkipListMap_less_turbo32: public cc::skip_list::make_traits < co::less< less > ,cc::skip_list::random_level_generator< cc::skip_list::turbo32 > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_less_turbo32 > SkipListMap_hp_less_turbo32; @@ -102,7 +102,7 @@ namespace map { class traits_SkipListMap_less_turbo24: public cc::skip_list::make_traits < co::less< less > , cc::skip_list::random_level_generator< cc::skip_list::turbo24 > - , co::item_counter< cds::atomicity::item_counter > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_less_turbo24 > SkipListMap_hp_less_turbo24; @@ -118,7 +118,7 @@ namespace map { class traits_SkipListMap_less_turbo16: public cc::skip_list::make_traits < co::less< less > , cc::skip_list::random_level_generator< cc::skip_list::turbo16 > - , co::item_counter< cds::atomicity::item_counter > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_less_turbo16 > SkipListMap_hp_less_turbo16; @@ -135,7 +135,7 @@ namespace map { co::less< less > ,cc::skip_list::random_level_generator< cc::skip_list::turbo32 > ,co::memory_model< co::v::sequential_consistent > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_less_turbo32_seqcst > SkipListMap_hp_less_turbo32_seqcst; @@ -152,7 +152,7 @@ namespace map { co::less< less > ,cc::skip_list::random_level_generator< cc::skip_list::turbo32 > ,co::stat< cc::skip_list::stat<> > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_less_turbo32_stat > SkipListMap_hp_less_turbo32_stat; @@ -169,7 +169,7 @@ namespace map { co::less< less > , cc::skip_list::random_level_generator< cc::skip_list::turbo24 > , co::stat< cc::skip_list::stat<> > - , co::item_counter< cds::atomicity::item_counter > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_less_turbo24_stat > SkipListMap_hp_less_turbo24_stat; @@ -186,7 +186,7 @@ namespace map { co::less< less > , cc::skip_list::random_level_generator< cc::skip_list::turbo16 > , co::stat< cc::skip_list::stat<> > - , co::item_counter< cds::atomicity::item_counter > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_less_turbo16_stat > SkipListMap_hp_less_turbo16_stat; @@ -202,7 +202,7 @@ namespace map { class traits_SkipListMap_cmp_turbo32: public cc::skip_list::make_traits < co::compare< compare > ,cc::skip_list::random_level_generator< cc::skip_list::turbo32 > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_cmp_turbo32 > SkipListMap_hp_cmp_turbo32; @@ -219,7 +219,7 @@ namespace map { co::compare< compare > ,cc::skip_list::random_level_generator< cc::skip_list::turbo32 > ,co::stat< cc::skip_list::stat<> > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_cmp_turbo32_stat > SkipListMap_hp_cmp_turbo32_stat; @@ -235,7 +235,7 @@ namespace map { class traits_SkipListMap_less_xorshift32: public cc::skip_list::make_traits < co::less< less > ,cc::skip_list::random_level_generator< cc::skip_list::xorshift32 > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_less_xorshift32 > SkipListMap_hp_less_xorshift32; @@ -251,7 +251,7 @@ namespace map { class traits_SkipListMap_less_xorshift24: public cc::skip_list::make_traits < co::less< less > , cc::skip_list::random_level_generator< cc::skip_list::xorshift24 > - , co::item_counter< cds::atomicity::item_counter > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_less_xorshift24 > SkipListMap_hp_less_xorshift24; @@ -267,7 +267,7 @@ namespace map { class traits_SkipListMap_less_xorshift16: public cc::skip_list::make_traits < co::less< less > , cc::skip_list::random_level_generator< cc::skip_list::xorshift16 > - , co::item_counter< cds::atomicity::item_counter > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_less_xorshift16 > SkipListMap_hp_less_xorshift16; @@ -284,7 +284,7 @@ namespace map { co::less< less > ,cc::skip_list::random_level_generator< cc::skip_list::xorshift32 > ,co::stat< cc::skip_list::stat<> > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_less_xorshift32_stat > SkipListMap_hp_less_xorshift32_stat; @@ -301,7 +301,7 @@ namespace map { co::less< less > , cc::skip_list::random_level_generator< cc::skip_list::xorshift24 > , co::stat< cc::skip_list::stat<> > - , co::item_counter< cds::atomicity::item_counter > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_less_xorshift24_stat > SkipListMap_hp_less_xorshift24_stat; @@ -318,7 +318,7 @@ namespace map { co::less< less > , cc::skip_list::random_level_generator< cc::skip_list::xorshift16 > , co::stat< cc::skip_list::stat<> > - , co::item_counter< cds::atomicity::item_counter > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_less_xorshift16_stat > SkipListMap_hp_less_xorshift16_stat; @@ -334,7 +334,7 @@ namespace map { class traits_SkipListMap_cmp_xorshift32: public cc::skip_list::make_traits < co::compare< compare > ,cc::skip_list::random_level_generator< cc::skip_list::xorshift32 > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_cmp_xorshift32 > SkipListMap_hp_cmp_xorshift32; @@ -351,7 +351,7 @@ namespace map { co::compare< compare > ,cc::skip_list::random_level_generator< cc::skip_list::xorshift32 > ,co::stat< cc::skip_list::stat<> > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListMap< cds::gc::HP, Key, Value, traits_SkipListMap_cmp_xorshift32_stat > SkipListMap_hp_cmp_xorshift32_stat; diff --git a/test/stress/map/map_type_split_list.h b/test/stress/map/map_type_split_list.h index f9265b2a..1efd127f 100644 --- a/test/stress/map/map_type_split_list.h +++ b/test/stress/map/map_type_split_list.h @@ -146,6 +146,7 @@ namespace map { struct traits_SplitList_Michael_dyn_cmp: public cc::split_list::make_traits< cc::split_list::ordered_list ,co::hash< hash > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > ,cc::split_list::ordered_list_traits< typename cc::michael_list::make_traits< co::compare< compare > @@ -198,6 +199,7 @@ namespace map { struct traits_SplitList_Michael_dyn_cmp_seqcst: public cc::split_list::make_traits< cc::split_list::ordered_list ,co::hash< hash > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > ,co::memory_model< co::v::sequential_consistent > ,cc::split_list::ordered_list_traits< typename cc::michael_list::make_traits< @@ -221,6 +223,7 @@ namespace map { cc::split_list::ordered_list ,cc::split_list::dynamic_bucket_table< false > ,co::hash< hash > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > ,cc::split_list::ordered_list_traits< typename cc::michael_list::make_traits< co::compare< compare > @@ -242,6 +245,7 @@ namespace map { struct traits_SplitList_Michael_dyn_less: public cc::split_list::make_traits< cc::split_list::ordered_list ,co::hash< hash > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > ,cc::split_list::ordered_list_traits< typename cc::michael_list::make_traits< co::less< less > @@ -264,6 +268,7 @@ namespace map { cc::split_list::ordered_list ,cc::split_list::dynamic_bucket_table< false > ,co::hash< hash > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > ,cc::split_list::ordered_list_traits< typename cc::michael_list::make_traits< co::less< less > @@ -308,6 +313,7 @@ namespace map { public cc::split_list::make_traits< cc::split_list::ordered_list ,co::hash< hash > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > ,cc::split_list::ordered_list_traits< typename cc::lazy_list::make_traits< co::compare< compare > @@ -347,6 +353,7 @@ namespace map { public cc::split_list::make_traits< cc::split_list::ordered_list ,co::hash< hash > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > ,co::memory_model< co::v::sequential_consistent > ,cc::split_list::ordered_list_traits< typename cc::lazy_list::make_traits< @@ -371,6 +378,7 @@ namespace map { cc::split_list::ordered_list ,cc::split_list::dynamic_bucket_table< false > ,co::hash< hash > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > ,cc::split_list::ordered_list_traits< typename cc::lazy_list::make_traits< co::compare< compare > @@ -393,6 +401,7 @@ namespace map { public cc::split_list::make_traits< cc::split_list::ordered_list ,co::hash< hash > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > ,cc::split_list::ordered_list_traits< typename cc::lazy_list::make_traits< co::less< less > @@ -415,6 +424,7 @@ namespace map { cc::split_list::ordered_list ,cc::split_list::dynamic_bucket_table< false > ,co::hash< hash > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > ,cc::split_list::ordered_list_traits< typename cc::lazy_list::make_traits< co::less< less > @@ -456,6 +466,7 @@ namespace map { struct traits_SplitList_Iterable_dyn_cmp: public cc::split_list::make_traits< cc::split_list::ordered_list ,co::hash< hash > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > ,cc::split_list::ordered_list_traits< typename cc::iterable_list::make_traits< co::compare< compare > @@ -480,6 +491,7 @@ namespace map { struct traits_SplitList_Iterable_dyn_cmp_seqcst: public cc::split_list::make_traits< cc::split_list::ordered_list ,co::hash< hash > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > ,co::memory_model< co::v::sequential_consistent > ,cc::split_list::ordered_list_traits< typename cc::iterable_list::make_traits< @@ -496,6 +508,7 @@ namespace map { cc::split_list::ordered_list ,cc::split_list::dynamic_bucket_table< false > ,co::hash< hash > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > ,cc::split_list::ordered_list_traits< typename cc::iterable_list::make_traits< co::compare< compare > @@ -510,6 +523,7 @@ namespace map { struct traits_SplitList_Iterable_dyn_less: public cc::split_list::make_traits< cc::split_list::ordered_list ,co::hash< hash > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > ,cc::split_list::ordered_list_traits< typename cc::iterable_list::make_traits< co::less< less > @@ -524,6 +538,7 @@ namespace map { cc::split_list::ordered_list ,cc::split_list::dynamic_bucket_table< false > ,co::hash< hash > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > ,cc::split_list::ordered_list_traits< typename cc::iterable_list::make_traits< co::less< less > diff --git a/test/stress/set/set_type_ellen_bintree.h b/test/stress/set/set_type_ellen_bintree.h index 09f2d9a8..90c01e54 100644 --- a/test/stress/set/set_type_ellen_bintree.h +++ b/test/stress/set/set_type_ellen_bintree.h @@ -136,6 +136,7 @@ namespace set { cc::ellen_bintree::key_extractor< typename ellen_bintree_props::key_extractor > ,co::less< typename ellen_bintree_props::less > ,co::node_allocator< ellen_bintree_pool::internal_node_allocator< int > > + ,co::item_counter >::type {}; @@ -208,6 +209,7 @@ namespace set { ,co::less< typename ellen_bintree_props::less > ,co::node_allocator< ellen_bintree_pool::internal_node_allocator< int > > ,co::stat< cc::ellen_bintree::stat<> > + ,co::item_counter >::type {}; diff --git a/test/stress/set/set_type_feldman_hashset.h b/test/stress/set/set_type_feldman_hashset.h index bfb9abeb..d9fcbbd1 100644 --- a/test/stress/set/set_type_feldman_hashset.h +++ b/test/stress/set/set_type_feldman_hashset.h @@ -186,6 +186,7 @@ namespace set { return kv.hash; } }; + typedef cds::atomicity::cache_friendly_item_counter item_counter; }; typedef FeldmanHashSet< cds::gc::HP, key_val>, default_traits > FeldmanHashSet_hp_stdhash; @@ -323,6 +324,7 @@ namespace set { }; typedef set::cmp compare; + typedef cds::atomicity::cache_friendly_item_counter item_counter; }; struct traits_stat : public traits diff --git a/test/stress/set/set_type_michael.h b/test/stress/set/set_type_michael.h index c1438133..9934904a 100644 --- a/test/stress/set/set_type_michael.h +++ b/test/stress/set/set_type_michael.h @@ -93,6 +93,7 @@ namespace set { struct traits_MichaelSet : public cc::michael_set::make_traits< co::hash< hash > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef MichaelHashSet< cds::gc::HP, typename ml::MichaelList_HP_cmp, traits_MichaelSet > MichaelSet_HP_cmp; diff --git a/test/stress/set/set_type_skip_list.h b/test/stress/set/set_type_skip_list.h index 02232098..648663f9 100644 --- a/test/stress/set/set_type_skip_list.h +++ b/test/stress/set/set_type_skip_list.h @@ -70,7 +70,7 @@ namespace set { class traits_SkipListSet_less_turbo32: public cc::skip_list::make_traits < co::less< less > ,cc::skip_list::random_level_generator< cc::skip_list::turbo32 > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_less_turbo32 > SkipListSet_hp_less_turbo32; @@ -85,7 +85,7 @@ namespace set { class traits_SkipListSet_less_turbo24: public cc::skip_list::make_traits < co::less< less > ,cc::skip_list::random_level_generator< cc::skip_list::turbo24 > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_less_turbo24 > SkipListSet_hp_less_turbo24; @@ -100,7 +100,7 @@ namespace set { class traits_SkipListSet_less_turbo16: public cc::skip_list::make_traits < co::less< less > ,cc::skip_list::random_level_generator< cc::skip_list::turbo16 > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_less_turbo16 > SkipListSet_hp_less_turbo16; @@ -116,7 +116,7 @@ namespace set { co::less< less > ,cc::skip_list::random_level_generator< cc::skip_list::turbo32 > ,co::memory_model< co::v::sequential_consistent > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_less_turbo32_seqcst > SkipListSet_hp_less_turbo32_seqcst; @@ -132,7 +132,7 @@ namespace set { co::less< less > ,cc::skip_list::random_level_generator< cc::skip_list::turbo32 > ,co::stat< cc::skip_list::stat<> > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_less_turbo32_stat > SkipListSet_hp_less_turbo32_stat; @@ -148,7 +148,7 @@ namespace set { co::less< less > ,cc::skip_list::random_level_generator< cc::skip_list::turbo24 > ,co::stat< cc::skip_list::stat<> > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_less_turbo24_stat > SkipListSet_hp_less_turbo24_stat; @@ -164,7 +164,7 @@ namespace set { co::less< less > ,cc::skip_list::random_level_generator< cc::skip_list::turbo16 > ,co::stat< cc::skip_list::stat<> > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_less_turbo16_stat > SkipListSet_hp_less_turbo16_stat; @@ -179,7 +179,7 @@ namespace set { class traits_SkipListSet_cmp_turbo32: public cc::skip_list::make_traits < co::compare< compare > ,cc::skip_list::random_level_generator< cc::skip_list::turbo32 > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_cmp_turbo32 > SkipListSet_hp_cmp_turbo32; @@ -195,7 +195,7 @@ namespace set { co::compare< compare > ,cc::skip_list::random_level_generator< cc::skip_list::turbo32 > ,co::stat< cc::skip_list::stat<> > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_cmp_turbo32_stat > SkipListSet_hp_cmp_turbo32_stat; @@ -210,7 +210,7 @@ namespace set { class traits_SkipListSet_less_xorshift32: public cc::skip_list::make_traits < co::less< less > ,cc::skip_list::random_level_generator< cc::skip_list::xorshift32 > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_less_xorshift32 > SkipListSet_hp_less_xorshift32; @@ -225,7 +225,7 @@ namespace set { class traits_SkipListSet_less_xorshift24: public cc::skip_list::make_traits < co::less< less > ,cc::skip_list::random_level_generator< cc::skip_list::xorshift24 > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_less_xorshift24 > SkipListSet_hp_less_xorshift24; @@ -240,7 +240,7 @@ namespace set { class traits_SkipListSet_less_xorshift16: public cc::skip_list::make_traits < co::less< less > , cc::skip_list::random_level_generator< cc::skip_list::xorshift16 > - , co::item_counter< cds::atomicity::item_counter > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_less_xorshift16 > SkipListSet_hp_less_xorshift16; @@ -256,7 +256,7 @@ namespace set { co::less< less > ,cc::skip_list::random_level_generator< cc::skip_list::xorshift32 > ,co::stat< cc::skip_list::stat<> > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_less_xorshift32_stat > SkipListSet_hp_less_xorshift32_stat; @@ -272,7 +272,7 @@ namespace set { co::less< less > , cc::skip_list::random_level_generator< cc::skip_list::xorshift24 > , co::stat< cc::skip_list::stat<> > - , co::item_counter< cds::atomicity::item_counter > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_less_xorshift24_stat > SkipListSet_hp_less_xorshift24_stat; @@ -288,7 +288,7 @@ namespace set { co::less< less > , cc::skip_list::random_level_generator< cc::skip_list::xorshift16 > , co::stat< cc::skip_list::stat<> > - , co::item_counter< cds::atomicity::item_counter > + , co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_less_xorshift16_stat > SkipListSet_hp_less_xorshift16_stat; @@ -303,7 +303,7 @@ namespace set { class traits_SkipListSet_cmp_xorshift32: public cc::skip_list::make_traits < co::compare< compare > ,cc::skip_list::random_level_generator< cc::skip_list::xorshift32 > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_cmp_xorshift32 > SkipListSet_hp_cmp_xorshift32; @@ -319,7 +319,7 @@ namespace set { co::compare< compare > ,cc::skip_list::random_level_generator< cc::skip_list::xorshift32 > ,co::stat< cc::skip_list::stat<> > - ,co::item_counter< cds::atomicity::item_counter > + ,co::item_counter< cds::atomicity::cache_friendly_item_counter > >::type {}; typedef SkipListSet< cds::gc::HP, key_val, traits_SkipListSet_cmp_xorshift32_stat > SkipListSet_hp_cmp_xorshift32_stat; diff --git a/test/stress/set/set_type_split_list.h b/test/stress/set/set_type_split_list.h index b0bddacc..ed9317c3 100644 --- a/test/stress/set/set_type_split_list.h +++ b/test/stress/set/set_type_split_list.h @@ -100,6 +100,7 @@ namespace set { public cc::split_list::make_traits< cc::split_list::ordered_list ,co::hash< hash > + ,co::item_counter ,cc::split_list::ordered_list_traits< typename cc::michael_list::make_traits< co::compare< compare > @@ -133,6 +134,7 @@ namespace set { public cc::split_list::make_traits< cc::split_list::ordered_list ,co::hash< hash > + , co::item_counter ,co::stat< cc::split_list::stat<> > ,cc::split_list::ordered_list_traits< typename cc::michael_list::make_traits< @@ -155,6 +157,7 @@ namespace set { public cc::split_list::make_traits< cc::split_list::ordered_list ,co::hash< hash > + ,co::item_counter ,co::memory_model< co::v::sequential_consistent > ,cc::split_list::ordered_list_traits< typename cc::michael_list::make_traits< @@ -178,6 +181,7 @@ namespace set { cc::split_list::ordered_list ,cc::split_list::dynamic_bucket_table< false > ,co::hash< hash > + ,co::item_counter ,cc::split_list::ordered_list_traits< typename cc::michael_list::make_traits< co::compare< compare > @@ -199,6 +203,7 @@ namespace set { public cc::split_list::make_traits< cc::split_list::ordered_list ,co::hash< hash > + , co::item_counter ,cc::split_list::ordered_list_traits< typename cc::michael_list::make_traits< co::less< less > @@ -220,6 +225,7 @@ namespace set { cc::split_list::ordered_list ,cc::split_list::dynamic_bucket_table< false > ,co::hash< hash > + , co::item_counter ,cc::split_list::ordered_list_traits< typename cc::michael_list::make_traits< co::less< less > @@ -241,6 +247,7 @@ namespace set { cc::split_list::ordered_list ,cc::split_list::dynamic_bucket_table< false > ,co::hash< hash > + , co::item_counter ,co::stat< cc::split_list::stat<>> ,cc::split_list::ordered_list_traits< typename cc::michael_list::make_traits< @@ -266,6 +273,7 @@ namespace set { public cc::split_list::make_traits< cc::split_list::ordered_list ,co::hash< hash > + , co::item_counter ,cc::split_list::ordered_list_traits< typename cc::lazy_list::make_traits< co::compare< compare > @@ -303,6 +311,7 @@ namespace set { public cc::split_list::make_traits< cc::split_list::ordered_list ,co::hash< hash > + , co::item_counter ,co::memory_model< co::v::sequential_consistent > ,cc::split_list::ordered_list_traits< typename cc::lazy_list::make_traits< @@ -326,6 +335,7 @@ namespace set { cc::split_list::ordered_list ,cc::split_list::dynamic_bucket_table< false > ,co::hash< hash > + , co::item_counter ,cc::split_list::ordered_list_traits< typename cc::lazy_list::make_traits< co::compare< compare > @@ -346,6 +356,7 @@ namespace set { public cc::split_list::make_traits< cc::split_list::ordered_list ,co::hash< hash > + , co::item_counter ,cc::split_list::ordered_list_traits< typename cc::lazy_list::make_traits< co::less< less > @@ -367,6 +378,7 @@ namespace set { cc::split_list::ordered_list ,cc::split_list::dynamic_bucket_table< false > ,co::hash< hash > + , co::item_counter ,cc::split_list::ordered_list_traits< typename cc::lazy_list::make_traits< co::less< less > @@ -407,6 +419,7 @@ namespace set { public cc::split_list::make_traits< cc::split_list::ordered_list ,co::hash< hash > + , co::item_counter ,cc::split_list::ordered_list_traits< typename cc::iterable_list::make_traits< co::compare< compare > @@ -421,6 +434,7 @@ namespace set { public cc::split_list::make_traits< cc::split_list::ordered_list ,co::hash< hash > + , co::item_counter ,co::stat< cc::split_list::stat<> > ,cc::split_list::ordered_list_traits< typename cc::iterable_list::make_traits< @@ -437,6 +451,7 @@ namespace set { public cc::split_list::make_traits< cc::split_list::ordered_list ,co::hash< hash > + , co::item_counter ,co::memory_model< co::v::sequential_consistent > ,cc::split_list::ordered_list_traits< typename cc::iterable_list::make_traits< @@ -454,6 +469,7 @@ namespace set { cc::split_list::ordered_list ,cc::split_list::dynamic_bucket_table< false > ,co::hash< hash > + , co::item_counter ,cc::split_list::ordered_list_traits< typename cc::iterable_list::make_traits< co::compare< compare > @@ -469,6 +485,7 @@ namespace set { public cc::split_list::make_traits< cc::split_list::ordered_list ,co::hash< hash > + , co::item_counter ,cc::split_list::ordered_list_traits< typename cc::iterable_list::make_traits< co::less< less > @@ -484,6 +501,7 @@ namespace set { cc::split_list::ordered_list ,cc::split_list::dynamic_bucket_table< false > ,co::hash< hash > + , co::item_counter ,cc::split_list::ordered_list_traits< typename cc::iterable_list::make_traits< co::less< less > @@ -499,6 +517,7 @@ namespace set { cc::split_list::ordered_list ,cc::split_list::dynamic_bucket_table< false > ,co::hash< hash > + , co::item_counter ,co::stat< cc::split_list::stat<>> ,cc::split_list::ordered_list_traits< typename cc::iterable_list::make_traits< diff --git a/test/unit/intrusive-list/intrusive_michael_dhp.cpp b/test/unit/intrusive-list/intrusive_michael_dhp.cpp index 8f19c84c..ae694ea7 100644 --- a/test/unit/intrusive-list/intrusive_michael_dhp.cpp +++ b/test/unit/intrusive-list/intrusive_michael_dhp.cpp @@ -229,6 +229,23 @@ namespace { test_hp( l ); } + TEST_F( IntrusiveMichaelList_DHP, member_hook_cache_friendly_item_counting ) + { + struct traits: public ci::michael_list::traits { + typedef ci::michael_list::member_hook< offsetof( member_item, hMember ), cds::opt::gc< gc_type >> hook; + typedef mock_disposer disposer; + typedef cmp< member_item > compare; + typedef intrusive_list_common::less< member_item > less; + typedef cds::atomicity::cache_friendly_item_counter item_counter; + }; + typedef ci::MichaelList< gc_type, member_item, traits > list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + TEST_F( IntrusiveMichaelList_DHP, member_hook_seqcst ) { struct traits : public ci::michael_list::traits { diff --git a/test/unit/intrusive-list/intrusive_michael_hp.cpp b/test/unit/intrusive-list/intrusive_michael_hp.cpp index 3ad0802b..608040be 100644 --- a/test/unit/intrusive-list/intrusive_michael_hp.cpp +++ b/test/unit/intrusive-list/intrusive_michael_hp.cpp @@ -111,6 +111,23 @@ namespace { test_hp( l ); } + TEST_F( IntrusiveMichaelList_HP, base_hook_cache_friendly_item_counting ) + { + struct traits: public ci::michael_list::traits { + typedef ci::michael_list::base_hook< cds::opt::gc< gc_type >> hook; + typedef mock_disposer disposer; + typedef cmp< base_item > compare; + typedef intrusive_list_common::less< base_item > less; + typedef cds::atomicity::cache_friendly_item_counter item_counter; + }; + typedef ci::MichaelList< gc_type, base_item, traits > list_type; + + list_type l; + test_common( l ); + test_ordered_iterator( l ); + test_hp( l ); + } + TEST_F( IntrusiveMichaelList_HP, base_hook_backoff ) { struct traits : public ci::michael_list::traits {