From d55395baed549c738cbf2caa0c0b90d2624eda96 Mon Sep 17 00:00:00 2001 From: khizmax Date: Wed, 24 Aug 2016 23:08:44 +0300 Subject: [PATCH] Added internal statistics to MichaelSet/Map --- cds/container/lazy_kvlist_nogc.h | 16 ++ cds/container/lazy_kvlist_rcu.h | 17 ++ cds/container/michael_kvlist_nogc.h | 102 ++++++----- cds/container/michael_kvlist_rcu.h | 99 ++++++----- cds/container/michael_map.h | 24 +-- cds/container/michael_map_nogc.h | 160 ++++++++++------- cds/container/michael_map_rcu.h | 166 +++++++++++------- cds/container/michael_set.h | 24 +-- cds/container/michael_set_nogc.h | 11 +- cds/container/michael_set_rcu.h | 23 ++- cds/intrusive/michael_set.h | 20 ++- cds/intrusive/michael_set_nogc.h | 20 ++- cds/intrusive/michael_set_rcu.h | 16 +- projects/Win/vc14/gtest-map.vcxproj | 6 + .../intrusive_michael_iterable_dhp.cpp | 2 + .../intrusive_michael_iterable_hp.cpp | 2 + .../intrusive_michael_lazy_dhp.cpp | 4 + .../intrusive_michael_lazy_hp.cpp | 4 + .../intrusive_michael_lazy_nogc.cpp | 4 + .../intrusive_michael_michael_dhp.cpp | 4 + .../intrusive_michael_michael_hp.cpp | 4 + .../intrusive_michael_michael_nogc.cpp | 4 + .../test_intrusive_michael_lazy_rcu.h | 4 + .../test_intrusive_michael_michael_rcu.h | 4 + test/unit/map/michael_iterable_dhp.cpp | 10 +- test/unit/map/michael_iterable_hp.cpp | 10 +- test/unit/map/michael_lazy_dhp.cpp | 2 + test/unit/map/michael_lazy_hp.cpp | 2 + test/unit/map/michael_lazy_nogc.cpp | 48 ++++- test/unit/map/michael_michael_dhp.cpp | 10 +- test/unit/map/michael_michael_hp.cpp | 10 +- test/unit/map/michael_michael_nogc.cpp | 46 ++++- test/unit/map/test_michael_lazy_rcu.h | 56 +++++- test/unit/map/test_michael_michael_rcu.h | 55 +++++- test/unit/set/michael_iterable_dhp.cpp | 2 + test/unit/set/michael_iterable_hp.cpp | 2 + test/unit/set/michael_lazy_dhp.cpp | 2 + test/unit/set/michael_lazy_hp.cpp | 2 + test/unit/set/michael_lazy_nogc.cpp | 2 + test/unit/set/michael_michael_dhp.cpp | 2 + test/unit/set/michael_michael_hp.cpp | 2 + test/unit/set/michael_michael_nogc.cpp | 2 + test/unit/set/test_michael_lazy_rcu.h | 2 + test/unit/set/test_michael_michael_rcu.h | 2 + 44 files changed, 714 insertions(+), 295 deletions(-) diff --git a/cds/container/lazy_kvlist_nogc.h b/cds/container/lazy_kvlist_nogc.h index c2150836..ce3663cd 100644 --- a/cds/container/lazy_kvlist_nogc.h +++ b/cds/container/lazy_kvlist_nogc.h @@ -88,6 +88,22 @@ namespace cds { namespace container { typedef typename base_class::stat stat; ///< Internal statistics static CDS_CONSTEXPR bool const c_bSort = base_class::c_bSort; ///< List type: ordered (\p true) or unordered (\p false) + //@cond + // Rebind traits (split-list support) + template + struct rebind_traits { + typedef LazyKVList< + gc + , key_type, mapped_type + , typename cds::opt::make_options< traits, Options...>::type + > type; + }; + + // Stat selector + template + using select_stat_wrapper = typename base_class::template select_stat_wrapper< Stat >; + //@endcond + protected: //@cond typedef typename base_class::value_type node_type; diff --git a/cds/container/lazy_kvlist_rcu.h b/cds/container/lazy_kvlist_rcu.h index 155237c4..678ee5df 100644 --- a/cds/container/lazy_kvlist_rcu.h +++ b/cds/container/lazy_kvlist_rcu.h @@ -118,6 +118,7 @@ namespace cds { namespace container { public: typedef cds::urcu::gc gc; ///< Garbage collector + typedef Traits traits; ///< List traits #ifdef CDS_DOXYGEN_INVOKED typedef Key key_type ; ///< Key type typedef Value mapped_type ; ///< Type of value stored in the list @@ -138,6 +139,22 @@ namespace cds { namespace container { typedef typename gc::scoped_lock rcu_lock ; ///< RCU scoped lock static CDS_CONSTEXPR const bool c_bExtractLockExternal = base_class::c_bExtractLockExternal; ///< Group of \p extract_xxx functions require external locking + //@cond + // Rebind traits (split-list support) + template + struct rebind_traits { + typedef LazyKVList< + gc + , key_type, mapped_type + , typename cds::opt::make_options< traits, Options...>::type + > type; + }; + + // Stat selector + template + using select_stat_wrapper = typename base_class::template select_stat_wrapper< Stat >; + //@endcond + protected: //@cond typedef typename base_class::value_type node_type; diff --git a/cds/container/michael_kvlist_nogc.h b/cds/container/michael_kvlist_nogc.h index 89974bf5..f1b20003 100644 --- a/cds/container/michael_kvlist_nogc.h +++ b/cds/container/michael_kvlist_nogc.h @@ -114,6 +114,22 @@ namespace cds { namespace container { typedef typename base_class::memory_model memory_model; ///< Memory ordering. See cds::opt::memory_model option typedef typename base_class::stat stat; ///< Internal statistics + //@cond + // Rebind traits (split-list support) + template + struct rebind_traits { + typedef MichaelKVList< + gc + , key_type, mapped_type + , typename cds::opt::make_options< traits, Options...>::type + > type; + }; + + // Stat selector + template + using select_stat_wrapper = typename base_class::template select_stat_wrapper< Stat >; + //@endcond + protected: //@cond typedef typename base_class::value_type node_type; @@ -122,32 +138,6 @@ namespace cds { namespace container { typedef typename maker::intrusive_traits::compare intrusive_key_comparator; typedef typename base_class::atomic_node_ptr head_type; - //@endcond - - protected: - //@cond - template - static node_type * alloc_node(const K& key) - { - return cxx_allocator().New( key ); - } - - template - static node_type * alloc_node( const K& key, const V& val ) - { - return cxx_allocator().New( key, val ); - } - - template - static node_type * alloc_node( K&& key, Args&&... args ) - { - return cxx_allocator().MoveNew( std::forward(key), std::forward(args)... ); - } - - static void free_node( node_type * pNode ) - { - cxx_allocator().Delete( pNode ); - } struct node_disposer { void operator()( node_type * pNode ) @@ -156,16 +146,6 @@ namespace cds { namespace container { } }; typedef std::unique_ptr< node_type, node_disposer > scoped_node_ptr; - - head_type& head() - { - return base_class::m_pHead; - } - - head_type const& head() const - { - return base_class::m_pHead; - } //@endcond protected: @@ -329,16 +309,6 @@ namespace cds { namespace container { } //@} - protected: - //@cond - iterator node_to_iterator( node_type * pNode ) - { - if ( pNode ) - return iterator( *pNode ); - return end(); - } - //@endcond - public: /// Default constructor /** @@ -601,6 +571,46 @@ namespace cds { namespace container { { return base_class::find_at( refHead, key, cmp ); } + + template + static node_type * alloc_node( const K& key ) + { + return cxx_allocator().New( key ); + } + + template + static node_type * alloc_node( const K& key, const V& val ) + { + return cxx_allocator().New( key, val ); + } + + template + static node_type * alloc_node( K&& key, Args&&... args ) + { + return cxx_allocator().MoveNew( std::forward( key ), std::forward( args )... ); + } + + static void free_node( node_type * pNode ) + { + cxx_allocator().Delete( pNode ); + } + + head_type& head() + { + return base_class::m_pHead; + } + + head_type const& head() const + { + return base_class::m_pHead; + } + + iterator node_to_iterator( node_type * pNode ) + { + if ( pNode ) + return iterator( *pNode ); + return end(); + } //@endcond }; diff --git a/cds/container/michael_kvlist_rcu.h b/cds/container/michael_kvlist_rcu.h index 2dbe9ffe..a01489c1 100644 --- a/cds/container/michael_kvlist_rcu.h +++ b/cds/container/michael_kvlist_rcu.h @@ -144,6 +144,22 @@ namespace cds { namespace container { typedef typename gc::scoped_lock rcu_lock ; ///< RCU scoped lock static CDS_CONSTEXPR const bool c_bExtractLockExternal = base_class::c_bExtractLockExternal; ///< Group of \p extract_xxx functions do not require external locking + //@cond + // Rebind traits (split-list support) + template + struct rebind_traits { + typedef MichaelKVList< + gc + , key_type, mapped_type + , typename cds::opt::make_options< traits, Options...>::type + > type; + }; + + // Stat selector + template + using select_stat_wrapper = typename base_class::template select_stat_wrapper< Stat >; + //@endcond + protected: //@cond typedef typename base_class::value_type node_type; @@ -152,6 +168,14 @@ namespace cds { namespace container { typedef typename maker::intrusive_traits::compare intrusive_key_comparator; typedef typename base_class::atomic_node_ptr head_type; + + struct node_disposer { + void operator()( node_type * pNode ) + { + free_node( pNode ); + } + }; + typedef std::unique_ptr< node_type, node_disposer > scoped_node_ptr; //@endcond public: @@ -185,49 +209,6 @@ namespace cds { namespace container { /// Result of \p get(), \p get_with() functions - pointer to the node found typedef cds::urcu::raw_ptr_adaptor< value_type, typename base_class::raw_ptr, raw_ptr_converter > raw_ptr; - protected: - //@cond - template - static node_type * alloc_node(const K& key) - { - return cxx_allocator().New( key ); - } - - template - static node_type * alloc_node( const K& key, const V& val ) - { - return cxx_allocator().New( key, val ); - } - - template - static node_type * alloc_node( K&& key, Args&&... args ) - { - return cxx_allocator().MoveNew( std::forward(key), std::forward(args)...); - } - - static void free_node( node_type * pNode ) - { - cxx_allocator().Delete( pNode ); - } - - struct node_disposer { - void operator()( node_type * pNode ) - { - free_node( pNode ); - } - }; - typedef std::unique_ptr< node_type, node_disposer > scoped_node_ptr; - - head_type& head() - { - return base_class::m_pHead; - } - - head_type& head() const - { - return const_cast( base_class::m_pHead ); - } - //@endcond protected: //@cond @@ -933,6 +914,38 @@ namespace cds { namespace container { return raw_ptr( base_class::get_at( refHead, val, cmp )); } + template + static node_type * alloc_node( const K& key ) + { + return cxx_allocator().New( key ); + } + + template + static node_type * alloc_node( const K& key, const V& val ) + { + return cxx_allocator().New( key, val ); + } + + template + static node_type * alloc_node( K&& key, Args&&... args ) + { + return cxx_allocator().MoveNew( std::forward( key ), std::forward( args )... ); + } + + static void free_node( node_type * pNode ) + { + cxx_allocator().Delete( pNode ); + } + + head_type& head() + { + return base_class::m_pHead; + } + + head_type& head() const + { + return const_cast(base_class::m_pHead); + } //@endcond }; diff --git a/cds/container/michael_map.h b/cds/container/michael_map.h index 123ef869..f0cd8597 100644 --- a/cds/container/michael_map.h +++ b/cds/container/michael_map.h @@ -158,7 +158,11 @@ namespace cds { namespace container { typedef typename traits::allocator allocator; ///< Bucket table allocator typedef typename ordered_list::key_comparator key_comparator; ///< key compare functor +#ifdef CDS_DOXYGEN_INVOKED typedef typename ordered_list::stat stat; ///< Internal statistics + /// Guarded pointer - a result of \p get() and \p extract() functions + typedef typename ordered_list::guarded_ptr guarded_ptr; +#endif /// Hash functor for \ref key_type and all its derivatives that you use typedef typename cds::opt::v::hash_selector< typename traits::hash >::type hash; @@ -173,38 +177,26 @@ namespace cds { namespace container { static CDS_CONSTEXPR const size_t c_nHazardPtrCount = ordered_list::c_nHazardPtrCount; ///< Count of hazard pointer required -#ifdef CDS_DOXYGEN_INVOKED - /// Wrapped internal statistics for \p ordered_list - typedef implementatin_specific bucket_stat; -#else + //@cond typedef typename ordered_list::template select_stat_wrapper< typename ordered_list::stat > bucket_stat; -#endif -#ifdef CDS_DOXYGEN_INVOKED - /// Internal bucket type - rebind \p ordered_list with empty item counter and wrapped internal statistics - typedef modified_ordered_list internal_bucket_type; -#else typedef typename ordered_list::template rebind_traits< cds::opt::item_counter< cds::atomicity::empty_item_counter > , cds::opt::stat< typename bucket_stat::wrapped_stat > >::type internal_bucket_type; -#endif - /// Guarded pointer - a result of \p get() and \p extract() functions typedef typename internal_bucket_type::guarded_ptr guarded_ptr; - - //@cond - /// Bucket table allocator typedef typename allocator::template rebind< internal_bucket_type >::other bucket_table_allocator; + typedef typename bucket_stat::stat stat; //@endcond protected: //@cond const size_t m_nHashBitmask; - internal_bucket_type * m_Buckets; ///< bucket table + internal_bucket_type* m_Buckets; ///< bucket table item_counter m_ItemCounter; ///< Item counter hash m_HashFunctor; ///< Hash functor - typename bucket_stat::stat m_Stat; ///< Internal statistics + stat m_Stat; ///< Internal statistics //@endcond protected: diff --git a/cds/container/michael_map_nogc.h b/cds/container/michael_map_nogc.h index 61ec5dc9..049307ff 100644 --- a/cds/container/michael_map_nogc.h +++ b/cds/container/michael_map_nogc.h @@ -25,7 +25,7 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef CDSLIB_CONTAINER_MICHAEL_MAP_NOGC_H @@ -58,61 +58,67 @@ namespace cds { namespace container { { public: typedef cds::gc::nogc gc; ///< No garbage collector - typedef OrderedList bucket_type; ///< type of ordered list used as a bucket implementation + typedef OrderedList ordered_list; ///< type of ordered list used as a bucket implementation typedef Traits traits; ///< Map traits - typedef typename bucket_type::key_type key_type; ///< key type - typedef typename bucket_type::mapped_type mapped_type; ///< type of value to be stored in the map - typedef typename bucket_type::value_type value_type; ///< Pair used as the some functor's argument + typedef typename ordered_list::key_type key_type; ///< key type + typedef typename ordered_list::mapped_type mapped_type; ///< type of value to be stored in the map + typedef typename ordered_list::value_type value_type; ///< Pair used as the some functor's argument - typedef typename bucket_type::key_comparator key_comparator; ///< key comparing functor + typedef typename ordered_list::key_comparator key_comparator; ///< key comparing functor /// Hash functor for \ref key_type and all its derivatives that you use typedef typename cds::opt::v::hash_selector< typename traits::hash >::type hash; - typedef typename traits::item_counter item_counter; ///< Item counter type + typedef typename traits::item_counter item_counter; ///< Item counter type + typedef typename traits::allocator allocator; ///< Bucket table allocator - /// Bucket table allocator - typedef cds::details::Allocator< bucket_type, typename traits::allocator > bucket_table_allocator; +#ifdef CDS_DOXYGEN_INVOKED + typedef typename ordered_list::stat stat; ///< Internal statistics +#endif + + // 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 bucket_type::iterator bucket_iterator; - typedef typename bucket_type::const_iterator bucket_const_iterator; - //@endcond + typedef typename ordered_list::template select_stat_wrapper< typename ordered_list::stat > bucket_stat; - protected: - item_counter m_ItemCounter; ///< Item counter - hash m_HashFunctor; ///< Hash functor - bucket_type * m_Buckets; ///< bucket table + typedef typename ordered_list::template rebind_traits< + cds::opt::item_counter< cds::atomicity::empty_item_counter > + , cds::opt::stat< typename bucket_stat::wrapped_stat > + >::type internal_bucket_type; - private: + /// Bucket table allocator + typedef typename allocator::template rebind< internal_bucket_type >::other bucket_table_allocator; + + typedef typename internal_bucket_type::iterator bucket_iterator; + typedef typename internal_bucket_type::const_iterator bucket_const_iterator; + //@endcond + + public: //@cond - const size_t m_nHashBitmask; + typedef typename bucket_stat::stat stat; //@endcond protected: //@cond - /// Calculates hash value of \p key - template - size_t hash_value( K const & key ) const - { - return m_HashFunctor( key ) & m_nHashBitmask; - } - - /// Returns the bucket (ordered list) for \p key - template - bucket_type& bucket( K const& key ) - { - return m_Buckets[ hash_value( key ) ]; - } + 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 //@endcond protected: //@cond template - class iterator_type: private cds::intrusive::michael_set::details::iterator< bucket_type, IsConst > + class iterator_type: private cds::intrusive::michael_set::details::iterator< internal_bucket_type, IsConst > { - typedef cds::intrusive::michael_set::details::iterator< bucket_type, IsConst > base_class; + typedef cds::intrusive::michael_set::details::iterator< internal_bucket_type, IsConst > base_class; friend class MichaelHashMap; protected: @@ -282,18 +288,6 @@ namespace cds { namespace container { } //@} - private: - //@cond - const_iterator get_const_begin() const - { - return const_iterator( const_cast(m_Buckets[0]).begin(), m_Buckets, m_Buckets + bucket_count() ); - } - const_iterator get_const_end() const - { - return const_iterator( const_cast(m_Buckets[bucket_count() - 1]).end(), m_Buckets + bucket_count() - 1, m_Buckets + bucket_count() ); - } - //@endcond - public: /// Initialize the map /** @@ -309,22 +303,19 @@ namespace cds { namespace container { size_t nMaxItemCount, ///< estimation of max item count in the hash set size_t nLoadFactor ///< load factor: estimation of max number of items in the bucket ) : m_nHashBitmask( michael_map::details::init_hash_bitmask( nMaxItemCount, nLoadFactor )) + , m_Buckets( bucket_table_allocator().allocate( bucket_count())) { - // 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"); - - m_Buckets = bucket_table_allocator().NewArray( bucket_count() ); + for ( auto it = m_Buckets, itEnd = m_Buckets + bucket_count(); it != itEnd; ++it ) + construct_bucket( it ); } /// Clears hash set and destroys it ~MichaelHashMap() { clear(); - bucket_table_allocator().Delete( m_Buckets, bucket_count() ); + for ( auto it = m_Buckets, itEnd = m_Buckets + bucket_count(); it != itEnd; ++it ) + it->~internal_bucket_type(); + bucket_table_allocator().deallocate( m_Buckets, bucket_count() ); } /// Inserts new node with key and default value @@ -341,7 +332,7 @@ namespace cds { namespace container { template iterator insert( const K& key ) { - bucket_type& refBucket = bucket( key ); + internal_bucket_type& refBucket = bucket( key ); bucket_iterator it = refBucket.insert( key ); if ( it != refBucket.end() ) { @@ -366,7 +357,7 @@ namespace cds { namespace container { template iterator insert( K const& key, V const& val ) { - bucket_type& refBucket = bucket( key ); + internal_bucket_type& refBucket = bucket( key ); bucket_iterator it = refBucket.insert( key, val ); if ( it != refBucket.end() ) { @@ -410,7 +401,7 @@ namespace cds { namespace container { template iterator insert_with( const K& key, Func func ) { - bucket_type& refBucket = bucket( key ); + internal_bucket_type& refBucket = bucket( key ); bucket_iterator it = refBucket.insert_with( key, func ); if ( it != refBucket.end() ) { @@ -430,7 +421,7 @@ namespace cds { namespace container { template iterator emplace( K&& key, Args&&... args ) { - bucket_type& refBucket = bucket( key ); + internal_bucket_type& refBucket = bucket( key ); bucket_iterator it = refBucket.emplace( std::forward(key), std::forward(args)... ); if ( it != refBucket.end() ) { @@ -459,7 +450,7 @@ namespace cds { namespace container { template std::pair update( const K& key, bool bAllowInsert = true ) { - bucket_type& refBucket = bucket( key ); + internal_bucket_type& refBucket = bucket( key ); std::pair ret = refBucket.update( key, bAllowInsert ); if ( ret.second ) @@ -485,7 +476,7 @@ namespace cds { namespace container { template iterator contains( K const& key ) { - bucket_type& refBucket = bucket( key ); + internal_bucket_type& refBucket = bucket( key ); bucket_iterator it = refBucket.contains( key ); if ( it != refBucket.end() ) @@ -512,7 +503,7 @@ namespace cds { namespace container { template iterator contains( K const& key, Less pred ) { - bucket_type& refBucket = bucket( key ); + internal_bucket_type& refBucket = bucket( key ); bucket_iterator it = refBucket.contains( key, pred ); if ( it != refBucket.end() ) @@ -553,6 +544,12 @@ namespace cds { namespace container { return m_ItemCounter; } + /// Returns const reference to internal statistics + stat const& statistics() const + { + return m_Stat; + } + /// Returns the size of hash table /** Since \p %MichaelHashMap cannot dynamically extend the hash table size, @@ -563,6 +560,47 @@ namespace cds { namespace container { { return m_nHashBitmask + 1; } + + protected: + //@cond + /// Calculates hash value of \p key + template + size_t hash_value( K const & key ) const + { + return m_HashFunctor( key ) & m_nHashBitmask; + } + + /// Returns the bucket (ordered list) for \p key + template + internal_bucket_type& bucket( K const& key ) + { + return m_Buckets[hash_value( key )]; + } + //@endcond + + private: + //@cond + const_iterator get_const_begin() const + { + return const_iterator( const_cast(m_Buckets[0]).begin(), m_Buckets, m_Buckets + bucket_count() ); + } + const_iterator get_const_end() const + { + return const_iterator( const_cast(m_Buckets[bucket_count() - 1]).end(), m_Buckets + bucket_count() - 1, m_Buckets + bucket_count() ); + } + + template + typename std::enable_if< Stat::empty >::type construct_bucket( internal_bucket_type* bucket ) + { + new (bucket) internal_bucket_type; + } + + template + typename std::enable_if< !Stat::empty >::type construct_bucket( internal_bucket_type* bucket ) + { + new (bucket) internal_bucket_type( m_Stat ); + } + //@endcond }; }} // namespace cds::container diff --git a/cds/container/michael_map_rcu.h b/cds/container/michael_map_rcu.h index 9bce287d..d2e0f420 100644 --- a/cds/container/michael_map_rcu.h +++ b/cds/container/michael_map_rcu.h @@ -25,7 +25,7 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef CDSLIB_CONTAINER_MICHAEL_MAP_RCU_H @@ -83,66 +83,72 @@ namespace cds { namespace container { { public: typedef cds::urcu::gc< RCU > gc; ///< RCU used as garbage collector - typedef OrderedList bucket_type; ///< type of ordered list used as a bucket implementation + typedef OrderedList ordered_list; ///< type of ordered list used as a bucket implementation typedef Traits traits; ///< Map traits - typedef typename bucket_type::key_type key_type ; ///< key type - typedef typename bucket_type::mapped_type mapped_type ; ///< value type - typedef typename bucket_type::value_type value_type ; ///< key/value pair stored in the list - typedef typename bucket_type::key_comparator key_comparator ; ///< key comparison functor + typedef typename ordered_list::key_type key_type; ///< key type + typedef typename ordered_list::mapped_type mapped_type; ///< value type + typedef typename ordered_list::value_type value_type; ///< key/value pair stored in the list + typedef typename ordered_list::key_comparator key_comparator;///< key comparison functor +#ifdef CDS_DOXYGEN_INVOKED + typedef typename ordered_list::stat stat; ///< Internal statistics + typedef typename ordered_list::exempt_ptr exempt_ptr; ///< pointer to extracted node + /// Type of \p get() member function return value + typedef typename ordered_list::raw_ptr raw_ptr; + typedef typename ordered_list::rcu_lock rcu_lock; ///< RCU scoped lock +#endif /// Hash functor for \ref key_type and all its derivatives that you use typedef typename cds::opt::v::hash_selector< typename traits::hash >::type hash; typedef typename traits::item_counter item_counter; ///< Item counter type + typedef typename traits::allocator allocator; ///< Bucket table allocator - /// Bucket table allocator - typedef cds::details::Allocator< bucket_type, typename traits::allocator > bucket_table_allocator; - - typedef typename bucket_type::rcu_lock rcu_lock; ///< RCU scoped lock - typedef typename bucket_type::exempt_ptr exempt_ptr; ///< pointer to extracted node /// Group of \p extract_xxx functions require external locking if underlying ordered list requires that - static CDS_CONSTEXPR const bool c_bExtractLockExternal = bucket_type::c_bExtractLockExternal; - /// Type of \p get() member function return value - typedef typename bucket_type::raw_ptr raw_ptr; + static CDS_CONSTEXPR const bool c_bExtractLockExternal = ordered_list::c_bExtractLockExternal; + + // 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: - item_counter m_ItemCounter; ///< Item counter - hash m_HashFunctor; ///< Hash functor - bucket_type * m_Buckets; ///< bucket table + //@cond + typedef typename ordered_list::template select_stat_wrapper< typename ordered_list::stat > bucket_stat; - private: + typedef typename ordered_list::template rebind_traits< + cds::opt::item_counter< cds::atomicity::empty_item_counter > + , cds::opt::stat< typename bucket_stat::wrapped_stat > + >::type internal_bucket_type; + + /// Bucket table allocator + typedef typename allocator::template rebind< internal_bucket_type >::other bucket_table_allocator; + //@endcond + + public: //@cond - const size_t m_nHashBitmask; + typedef typename bucket_stat::stat stat; + typedef typename internal_bucket_type::exempt_ptr exempt_ptr; + typedef typename internal_bucket_type::raw_ptr raw_ptr; + typedef typename internal_bucket_type::rcu_lock rcu_lock; //@endcond protected: //@cond - /// Calculates hash value of \p key - template - size_t hash_value( Q const& key ) const - { - return m_HashFunctor( key ) & m_nHashBitmask; - } - - /// Returns the bucket (ordered list) for \p key - template - bucket_type& bucket( Q const& key ) - { - return m_Buckets[ hash_value( key ) ]; - } - template - bucket_type const& bucket( Q const& key ) const - { - return m_Buckets[ hash_value( key ) ]; - } + 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 //@endcond protected: //@cond template - class iterator_type: private cds::intrusive::michael_set::details::iterator< bucket_type, IsConst > + class iterator_type: private cds::intrusive::michael_set::details::iterator< internal_bucket_type, IsConst > { - typedef cds::intrusive::michael_set::details::iterator< bucket_type, IsConst > base_class; + typedef cds::intrusive::michael_set::details::iterator< internal_bucket_type, IsConst > base_class; friend class MichaelHashMap; protected: @@ -316,18 +322,6 @@ namespace cds { namespace container { } //@} - private: - //@cond - const_iterator get_const_begin() const - { - return const_iterator( const_cast(m_Buckets[0]).begin(), m_Buckets, m_Buckets + bucket_count() ); - } - const_iterator get_const_end() const - { - return const_iterator( const_cast(m_Buckets[bucket_count() - 1]).end(), m_Buckets + bucket_count() - 1, m_Buckets + bucket_count() ); - } - //@endcond - public: /// Initializes the map /** @@ -343,22 +337,19 @@ namespace cds { namespace container { size_t nMaxItemCount, ///< estimation of max item count in the hash map size_t nLoadFactor ///< load factor: estimation of max number of items in the bucket ) : m_nHashBitmask( michael_map::details::init_hash_bitmask( nMaxItemCount, nLoadFactor )) + , m_Buckets( bucket_table_allocator().allocate( bucket_count())) { - // 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"); - - m_Buckets = bucket_table_allocator().NewArray( bucket_count() ); + for ( auto it = m_Buckets, itEnd = m_Buckets + bucket_count(); it != itEnd; ++it ) + construct_bucket( it ); } /// Clears hash map and destroys it ~MichaelHashMap() { clear(); - bucket_table_allocator().Delete( m_Buckets, bucket_count() ); + for ( auto it = m_Buckets, itEnd = m_Buckets + bucket_count(); it != itEnd; ++it ) + it->~internal_bucket_type(); + bucket_table_allocator().deallocate( m_Buckets, bucket_count() ); } /// Inserts new node with key and default value @@ -591,7 +582,7 @@ namespace cds { namespace container { If the item is not found the function return an empty \p exempt_ptr. The function just excludes the key from the map and returns a pointer to item found. - Depends on \p bucket_type you should or should not lock RCU before calling of this function: + Depends on \p ordered_list you should or should not lock RCU before calling of this function: - for the set based on \ref cds_nonintrusive_MichaelList_rcu "MichaelList" RCU should not be locked - for the set based on \ref cds_nonintrusive_LazyList_rcu "LazyList" RCU should be locked See ordered list implementation for details. @@ -733,7 +724,7 @@ namespace cds { namespace container { /** \anchor cds_nonintrusive_MichaelHashMap_rcu_get The function searches the item with key equal to \p key and returns the pointer to item found. If \p key is not found it returns \p nullptr. - Note the type of returned value depends on underlying \p bucket_type. + Note the type of returned value depends on underlying \p ordered_list. For details, see documentation of ordered list you use. Note the compare functor should accept a parameter of type \p K that can be not the same as \p key_type. @@ -814,6 +805,12 @@ namespace cds { namespace container { return m_ItemCounter; } + /// Returns const reference to internal statistics + stat const& statistics() const + { + return m_Stat; + } + /// Returns the size of hash table /** Since \p %MichaelHashMap cannot dynamically extend the hash table size, @@ -824,6 +821,51 @@ namespace cds { namespace container { { return m_nHashBitmask + 1; } + + protected: + //@cond + /// Calculates hash value of \p key + template + size_t hash_value( Q const& key ) const + { + return m_HashFunctor( key ) & m_nHashBitmask; + } + + /// Returns the bucket (ordered list) for \p key + template + internal_bucket_type& bucket( Q const& key ) + { + return m_Buckets[hash_value( key )]; + } + template + internal_bucket_type const& bucket( Q const& key ) const + { + return m_Buckets[hash_value( key )]; + } + //@endcond + private: + //@cond + const_iterator get_const_begin() const + { + return const_iterator( const_cast(m_Buckets[0]).begin(), m_Buckets, m_Buckets + bucket_count() ); + } + const_iterator get_const_end() const + { + return const_iterator( const_cast(m_Buckets[bucket_count() - 1]).end(), m_Buckets + bucket_count() - 1, m_Buckets + bucket_count() ); + } + + template + typename std::enable_if< Stat::empty >::type construct_bucket( internal_bucket_type* bucket ) + { + new (bucket) internal_bucket_type; + } + + template + typename std::enable_if< !Stat::empty >::type construct_bucket( internal_bucket_type* bucket ) + { + new (bucket) internal_bucket_type( m_Stat ); + } + //@endcond }; }} // namespace cds::container diff --git a/cds/container/michael_set.h b/cds/container/michael_set.h index c324710b..b025e817 100644 --- a/cds/container/michael_set.h +++ b/cds/container/michael_set.h @@ -174,7 +174,9 @@ namespace cds { namespace container { typedef typename ordered_list::value_type value_type; ///< type of value to be stored in the list typedef typename ordered_list::key_comparator key_comparator; ///< key comparison functor +#ifdef CDS_DOXYGEN_INVOKED typedef typename ordered_list::stat stat; ///< Internal statistics +#endif /// Hash functor for \ref value_type and all its derivatives that you use typedef typename cds::opt::v::hash_selector< typename traits::hash >::type hash; @@ -190,38 +192,30 @@ namespace cds { namespace container { static_assert( !std::is_same::value, "cds::atomicity::empty_item_counter is not allowed as a item counter"); -#ifdef CDS_DOXYGEN_INVOKED - /// Wrapped internal statistics for \p ordered_list - typedef implementatin_specific bucket_stat; -#else + //@cond typedef typename ordered_list::template select_stat_wrapper< typename ordered_list::stat > bucket_stat; -#endif -#ifdef CDS_DOXYGEN_INVOKED - /// Internal bucket type - rebind \p ordered_list with empty item counter and wrapped internal statistics - typedef modified_ordered_list internal_bucket_type; -#else typedef typename ordered_list::template rebind_traits< cds::opt::item_counter< cds::atomicity::empty_item_counter > , cds::opt::stat< typename bucket_stat::wrapped_stat > >::type internal_bucket_type; -#endif - /// Guarded pointer - a result of \p get() and \p extract() functions - typedef typename internal_bucket_type::guarded_ptr guarded_ptr; - - //@cond /// Bucket table allocator typedef typename allocator::template rebind< internal_bucket_type >::other bucket_table_allocator; + + typedef typename bucket_stat::stat stat; //@endcond + /// Guarded pointer - a result of \p get() and \p extract() functions + typedef typename internal_bucket_type::guarded_ptr guarded_ptr; + protected: //@cond size_t const m_nHashBitmask; internal_bucket_type * m_Buckets; ///< bucket table item_counter m_ItemCounter; ///< Item counter hash m_HashFunctor; ///< Hash functor - typename bucket_stat::stat m_Stat; ///< Internal statistics + stat m_Stat; ///< Internal statistics //@endcond public: diff --git a/cds/container/michael_set_nogc.h b/cds/container/michael_set_nogc.h index aaa7ee5b..6e0cceac 100644 --- a/cds/container/michael_set_nogc.h +++ b/cds/container/michael_set_nogc.h @@ -25,7 +25,7 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef CDSLIB_CONTAINER_MICHAEL_SET_NOGC_H @@ -64,7 +64,9 @@ namespace cds { namespace container { typedef typename ordered_list::value_type value_type; ///< type of value stored in the list typedef typename ordered_list::key_comparator key_comparator; ///< key comparison functor +#ifdef CDS_DOXYGEN_INVOKED typedef typename ordered_list::stat stat; ///< Internal statistics +#endif /// Hash functor for \ref value_type and all its derivatives that you use typedef typename cds::opt::v::hash_selector< typename traits::hash >::type hash; @@ -105,13 +107,18 @@ namespace cds { namespace container { typedef typename internal_bucket_type::const_iterator bucket_const_iterator; //@endcond + public: + //@cond + typedef typename bucket_stat::stat stat; + //@endcond + 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 - typename bucket_stat::stat m_Stat; ///< Internal statistics + stat m_Stat; ///< Internal statistics //@endcond public: diff --git a/cds/container/michael_set_rcu.h b/cds/container/michael_set_rcu.h index c3c1adf8..c5ca7d4e 100644 --- a/cds/container/michael_set_rcu.h +++ b/cds/container/michael_set_rcu.h @@ -141,7 +141,11 @@ namespace cds { namespace container { typedef typename ordered_list::value_type value_type; ///< type of value to be stored in the list typedef typename ordered_list::key_comparator key_comparator; ///< key comparing functor - typedef typename ordered_list::stat stat; ///< Internal statistics +#ifdef CDS_DOXYGEN_INVOKED + typedef typename ordered_list::stat stat; ///< Internal statistics + typedef typename ordered_list::exempt_ptr exempt_ptr; ///< pointer to extracted node + typedef typename ordered_list::raw_ptr raw_ptr; ///< Return type of \p get() member function and its derivatives +#endif /// Hash functor for \ref value_type and all its derivatives that you use typedef typename cds::opt::v::hash_selector< typename traits::hash >::type hash; @@ -158,13 +162,7 @@ namespace cds { namespace container { static_assert(!std::is_same::value, "atomicity::empty_item_counter is not allowed as a item counter"); -#ifdef CDS_DOXYGEN_INVOKED - /// Wrapped internal statistics for \p ordered_list - typedef implementatin_specific bucket_stat; - - /// Internal bucket type - rebind \p ordered_list with empty item counter and wrapped internal statistics - typedef modified_ordered_list internal_bucket_type; -#else + //@cond typedef typename ordered_list::template select_stat_wrapper< typename ordered_list::stat > bucket_stat; typedef typename ordered_list::template rebind_traits< @@ -182,10 +180,11 @@ namespace cds { namespace container { using base_class::insert_node; using base_class::node_to_value; }; -#endif - typedef typename internal_bucket_type::exempt_ptr exempt_ptr; ///< pointer to extracted node - typedef typename internal_bucket_type::raw_ptr raw_ptr; ///< Return type of \p get() member function and its derivatives + typedef typename internal_bucket_type::exempt_ptr exempt_ptr; + typedef typename internal_bucket_type::raw_ptr raw_ptr; + typedef typename bucket_stat::stat stat; + //@endcond protected: //@cond @@ -196,7 +195,7 @@ namespace cds { namespace container { item_counter m_ItemCounter; ///< Item counter hash m_HashFunctor; ///< Hash functor internal_bucket_type* m_Buckets; ///< bucket table - typename bucket_stat::stat m_Stat; ///< Internal statistics + stat m_Stat; ///< Internal statistics //@endcond public: diff --git a/cds/intrusive/michael_set.h b/cds/intrusive/michael_set.h index 8cc7fe9a..1f396855 100644 --- a/cds/intrusive/michael_set.h +++ b/cds/intrusive/michael_set.h @@ -254,7 +254,9 @@ namespace cds { namespace intrusive { typedef typename ordered_list::value_type value_type ; ///< type of value to be stored in the set typedef typename ordered_list::key_comparator key_comparator ; ///< key comparing functor typedef typename ordered_list::disposer disposer ; ///< Node disposer functor +#ifdef CDS_DOXYGEN_INVOKED typedef typename ordered_list::stat stat ; ///< Internal statistics +#endif /// Hash functor for \p value_type and all its derivatives that you use typedef typename cds::opt::v::hash_selector< typename traits::hash >::type hash; @@ -283,12 +285,20 @@ namespace cds { namespace intrusive { >::type internal_bucket_type; typedef typename allocator::template rebind< internal_bucket_type >::other bucket_table_allocator; + //@endcond - hash m_HashFunctor; ///< Hash functor - size_t const m_nHashBitmask; - internal_bucket_type* m_Buckets; ///< bucket table - item_counter m_ItemCounter; ///< Item counter - typename bucket_stat::stat m_Stat; ///< Internal statistics + public: + //@cond + typedef typename bucket_stat::stat stat; + //@endcond + + protected: + //@cond + hash m_HashFunctor; ///< Hash functor + size_t const m_nHashBitmask; + internal_bucket_type* m_Buckets; ///< bucket table + item_counter m_ItemCounter; ///< Item counter + stat m_Stat; ///< Internal statistics //@endcond public: diff --git a/cds/intrusive/michael_set_nogc.h b/cds/intrusive/michael_set_nogc.h index 51ea022c..54904bac 100644 --- a/cds/intrusive/michael_set_nogc.h +++ b/cds/intrusive/michael_set_nogc.h @@ -65,7 +65,9 @@ namespace cds { namespace intrusive { typedef typename ordered_list::value_type value_type; ///< type of value to be stored in the set typedef typename ordered_list::key_comparator key_comparator; ///< key comparing functor typedef typename ordered_list::disposer disposer; ///< Node disposer functor +#ifdef CDS_DOXYGEN_INVOKED typedef typename ordered_list::stat stat; ///< Internal statistics +#endif /// Hash functor for \p value_type and all its derivatives that you use typedef typename cds::opt::v::hash_selector< typename traits::hash >::type hash; @@ -89,12 +91,20 @@ namespace cds { namespace intrusive { >::type internal_bucket_type; typedef typename allocator::template rebind< internal_bucket_type >::other bucket_table_allocator; + //@endcond - hash m_HashFunctor; ///< Hash functor - const size_t m_nHashBitmask; - internal_bucket_type * m_Buckets; ///< bucket table - item_counter m_ItemCounter; ///< Item counter - typename bucket_stat::stat m_Stat; ///< Internal statistics + public: + //@cond + typedef typename bucket_stat::stat stat; + //@endcond + + protected: + //@cond + hash m_HashFunctor; ///< Hash functor + const size_t m_nHashBitmask; + internal_bucket_type * m_Buckets; ///< bucket table + item_counter m_ItemCounter; ///< Item counter + stat m_Stat; ///< Internal statistics //@endcond protected: diff --git a/cds/intrusive/michael_set_rcu.h b/cds/intrusive/michael_set_rcu.h index 75e09217..7e64976b 100644 --- a/cds/intrusive/michael_set_rcu.h +++ b/cds/intrusive/michael_set_rcu.h @@ -108,7 +108,9 @@ namespace cds { namespace intrusive { typedef typename ordered_list::value_type value_type; ///< type of value stored in the list typedef typename ordered_list::key_comparator key_comparator; ///< key comparing functor typedef typename ordered_list::disposer disposer; ///< Node disposer functor +#ifdef CDS_DOXYGEN_INVOKED typedef typename ordered_list::stat stat; ///< Internal statistics +#endif /// Hash functor for \ref value_type and all its derivatives that you use typedef typename cds::opt::v::hash_selector< typename traits::hash >::type hash; @@ -142,13 +144,17 @@ namespace cds { namespace intrusive { typedef typename internal_bucket_type::exempt_ptr exempt_ptr; ///< pointer to extracted node typedef typename internal_bucket_type::raw_ptr raw_ptr; ///< Return type of \p get() member function and its derivatives + //@cond + typedef typename bucket_stat::stat stat; + //@endcond + private: //@cond - hash m_HashFunctor; ///< Hash functor - size_t const m_nHashBitmask; - internal_bucket_type* m_Buckets; ///< bucket table - item_counter m_ItemCounter; ///< Item counter - typename bucket_stat::stat m_Stat; ///< Internal statistics + hash m_HashFunctor; ///< Hash functor + size_t const m_nHashBitmask; + internal_bucket_type* m_Buckets; ///< bucket table + item_counter m_ItemCounter; ///< Item counter + stat m_Stat; ///< Internal statistics //@endcond public: diff --git a/projects/Win/vc14/gtest-map.vcxproj b/projects/Win/vc14/gtest-map.vcxproj index 0a081884..ebaaf3d8 100644 --- a/projects/Win/vc14/gtest-map.vcxproj +++ b/projects/Win/vc14/gtest-map.vcxproj @@ -326,6 +326,7 @@ _ENABLE_ATOMIC_ALIGNMENT_FIX;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) $(SolutionDir)..\..\..;$(GTEST_ROOT)/include;$(SolutionDir)..\..\..\test\include;$(BOOST_PATH);%(AdditionalIncludeDirectories) /bigobj %(AdditionalOptions) + 4503 Console @@ -342,6 +343,7 @@ _ENABLE_ATOMIC_ALIGNMENT_FIX;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) $(SolutionDir)..\..\..;$(GTEST_ROOT)/include;$(SolutionDir)..\..\..\test\include;$(BOOST_PATH);%(AdditionalIncludeDirectories) /bigobj %(AdditionalOptions) + 4503 Console @@ -358,6 +360,7 @@ _ENABLE_ATOMIC_ALIGNMENT_FIX;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) $(SolutionDir)..\..\..;$(GTEST_ROOT)/include;$(SolutionDir)..\..\..\test\include;$(BOOST_PATH);%(AdditionalIncludeDirectories) /bigobj %(AdditionalOptions) + 4503 Console @@ -374,6 +377,7 @@ _ENABLE_ATOMIC_ALIGNMENT_FIX;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) $(SolutionDir)..\..\..;$(GTEST_ROOT)/include;$(SolutionDir)..\..\..\test\include;$(BOOST_PATH);%(AdditionalIncludeDirectories) /bigobj %(AdditionalOptions) + 4503 Console @@ -392,6 +396,7 @@ _ENABLE_ATOMIC_ALIGNMENT_FIX;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) $(SolutionDir)..\..\..;$(GTEST_ROOT)/include;$(SolutionDir)..\..\..\test\include;$(BOOST_PATH);%(AdditionalIncludeDirectories) /bigobj %(AdditionalOptions) + 4503 Console @@ -412,6 +417,7 @@ _ENABLE_ATOMIC_ALIGNMENT_FIX;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) $(SolutionDir)..\..\..;$(GTEST_ROOT)/include;$(SolutionDir)..\..\..\test\include;$(BOOST_PATH);%(AdditionalIncludeDirectories) /bigobj %(AdditionalOptions) + 4503 Console diff --git a/test/unit/intrusive-set/intrusive_michael_iterable_dhp.cpp b/test/unit/intrusive-set/intrusive_michael_iterable_dhp.cpp index 527a2f03..50753454 100644 --- a/test/unit/intrusive-set/intrusive_michael_iterable_dhp.cpp +++ b/test/unit/intrusive-set/intrusive_michael_iterable_dhp.cpp @@ -142,6 +142,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( IntrusiveMichaelIterableSet_DHP, wrapped_stat ) @@ -163,6 +164,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } } // namespace diff --git a/test/unit/intrusive-set/intrusive_michael_iterable_hp.cpp b/test/unit/intrusive-set/intrusive_michael_iterable_hp.cpp index 98af775e..4ed2bb89 100644 --- a/test/unit/intrusive-set/intrusive_michael_iterable_hp.cpp +++ b/test/unit/intrusive-set/intrusive_michael_iterable_hp.cpp @@ -144,6 +144,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( IntrusiveMichaelIterableSet_HP, wrapped_stat ) @@ -166,6 +167,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } } // namespace diff --git a/test/unit/intrusive-set/intrusive_michael_lazy_dhp.cpp b/test/unit/intrusive-set/intrusive_michael_lazy_dhp.cpp index 5931528a..e4a6abaa 100644 --- a/test/unit/intrusive-set/intrusive_michael_lazy_dhp.cpp +++ b/test/unit/intrusive-set/intrusive_michael_lazy_dhp.cpp @@ -178,6 +178,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( IntrusiveMichaelLazySet_DHP, base_wrapped_stat ) @@ -200,6 +201,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( IntrusiveMichaelLazySet_DHP, member_cmp ) @@ -314,6 +316,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( IntrusiveMichaelLazySet_DHP, member_wrapped_stat ) @@ -336,6 +339,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } } // namespace diff --git a/test/unit/intrusive-set/intrusive_michael_lazy_hp.cpp b/test/unit/intrusive-set/intrusive_michael_lazy_hp.cpp index 1379e832..5a833357 100644 --- a/test/unit/intrusive-set/intrusive_michael_lazy_hp.cpp +++ b/test/unit/intrusive-set/intrusive_michael_lazy_hp.cpp @@ -179,6 +179,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( IntrusiveMichaelLazySet_HP, base_wrapped_stat ) @@ -201,6 +202,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } @@ -316,6 +318,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( IntrusiveMichaelLazySet_HP, member_wrapped_stat ) @@ -338,6 +341,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } } // namespace diff --git a/test/unit/intrusive-set/intrusive_michael_lazy_nogc.cpp b/test/unit/intrusive-set/intrusive_michael_lazy_nogc.cpp index 0c282dd0..52cc7614 100644 --- a/test/unit/intrusive-set/intrusive_michael_lazy_nogc.cpp +++ b/test/unit/intrusive-set/intrusive_michael_lazy_nogc.cpp @@ -165,6 +165,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( IntrusiveMichaelLazySet_NoGC, base_wrapped_stat ) @@ -187,6 +188,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( IntrusiveMichaelLazySet_NoGC, member_cmp ) @@ -301,6 +303,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( IntrusiveMichaelLazySet_NoGC, member_wrapped_stat ) @@ -323,6 +326,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } } // namespace diff --git a/test/unit/intrusive-set/intrusive_michael_michael_dhp.cpp b/test/unit/intrusive-set/intrusive_michael_michael_dhp.cpp index 77e0d25e..238705e6 100644 --- a/test/unit/intrusive-set/intrusive_michael_michael_dhp.cpp +++ b/test/unit/intrusive-set/intrusive_michael_michael_dhp.cpp @@ -152,6 +152,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( IntrusiveMichaelSet_DHP, base_wrapped_stat ) @@ -175,6 +176,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( IntrusiveMichaelSet_DHP, member_cmp ) @@ -268,6 +270,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( IntrusiveMichaelSet_DHP, member_wrapped_stat ) @@ -291,6 +294,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } } // namespace diff --git a/test/unit/intrusive-set/intrusive_michael_michael_hp.cpp b/test/unit/intrusive-set/intrusive_michael_michael_hp.cpp index 92e000de..9c2a3b8f 100644 --- a/test/unit/intrusive-set/intrusive_michael_michael_hp.cpp +++ b/test/unit/intrusive-set/intrusive_michael_michael_hp.cpp @@ -153,6 +153,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( IntrusiveMichaelSet_HP, base_wrapped_stat ) @@ -175,6 +176,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( IntrusiveMichaelSet_HP, member_cmp ) @@ -268,6 +270,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( IntrusiveMichaelSet_HP, member_wrapped_stat ) @@ -291,6 +294,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } } // namespace diff --git a/test/unit/intrusive-set/intrusive_michael_michael_nogc.cpp b/test/unit/intrusive-set/intrusive_michael_michael_nogc.cpp index 02ab228c..0d1d8dde 100644 --- a/test/unit/intrusive-set/intrusive_michael_michael_nogc.cpp +++ b/test/unit/intrusive-set/intrusive_michael_michael_nogc.cpp @@ -138,6 +138,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( IntrusiveMichaelSet_NoGC, base_wrapped_stat ) @@ -160,6 +161,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( IntrusiveMichaelSet_NoGC, member_cmp ) @@ -252,6 +254,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( IntrusiveMichaelSet_NoGC, member_wrapped_stat ) @@ -274,6 +277,7 @@ namespace { set_type s( kSize, 2 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } } // namespace diff --git a/test/unit/intrusive-set/test_intrusive_michael_lazy_rcu.h b/test/unit/intrusive-set/test_intrusive_michael_lazy_rcu.h index 13d9591a..e4d83881 100644 --- a/test/unit/intrusive-set/test_intrusive_michael_lazy_rcu.h +++ b/test/unit/intrusive-set/test_intrusive_michael_lazy_rcu.h @@ -196,6 +196,7 @@ TYPED_TEST_P( IntrusiveMichaelLazySet, base_stat ) set_type s( TestFixture::kSize, 2 ); this->test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TYPED_TEST_P( IntrusiveMichaelLazySet, base_wrapped_stat ) @@ -223,6 +224,7 @@ TYPED_TEST_P( IntrusiveMichaelLazySet, base_wrapped_stat ) set_type s( TestFixture::kSize, 2 ); this->test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TYPED_TEST_P( IntrusiveMichaelLazySet, member_cmp ) @@ -364,6 +366,7 @@ TYPED_TEST_P( IntrusiveMichaelLazySet, member_stat ) set_type s( TestFixture::kSize, 2 ); this->test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TYPED_TEST_P( IntrusiveMichaelLazySet, member_wrapped_stat ) @@ -391,6 +394,7 @@ TYPED_TEST_P( IntrusiveMichaelLazySet, member_wrapped_stat ) set_type s( TestFixture::kSize, 2 ); this->test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } // GCC 5: All test names should be written on single line, otherwise a runtime error will be encountered like as diff --git a/test/unit/intrusive-set/test_intrusive_michael_michael_rcu.h b/test/unit/intrusive-set/test_intrusive_michael_michael_rcu.h index a8b02e21..c713bf94 100644 --- a/test/unit/intrusive-set/test_intrusive_michael_michael_rcu.h +++ b/test/unit/intrusive-set/test_intrusive_michael_michael_rcu.h @@ -168,6 +168,7 @@ TYPED_TEST_P( IntrusiveMichaelSet, base_stat ) set_type s( TestFixture::kSize, 2 ); this->test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TYPED_TEST_P( IntrusiveMichaelSet, base_wrapped_stat ) @@ -196,6 +197,7 @@ TYPED_TEST_P( IntrusiveMichaelSet, base_wrapped_stat ) set_type s( TestFixture::kSize, 2 ); this->test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TYPED_TEST_P( IntrusiveMichaelSet, member_cmp ) @@ -310,6 +312,7 @@ TYPED_TEST_P( IntrusiveMichaelSet, member_stat ) set_type s( TestFixture::kSize, 2 ); this->test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TYPED_TEST_P( IntrusiveMichaelSet, member_wrapped_stat ) @@ -337,6 +340,7 @@ TYPED_TEST_P( IntrusiveMichaelSet, member_wrapped_stat ) set_type s( TestFixture::kSize, 2 ); this->test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } // GCC 5: All test names should be written on single line, otherwise a runtime error will be encountered like as diff --git a/test/unit/map/michael_iterable_dhp.cpp b/test/unit/map/michael_iterable_dhp.cpp index 70637b1a..8398ddfc 100644 --- a/test/unit/map/michael_iterable_dhp.cpp +++ b/test/unit/map/michael_iterable_dhp.cpp @@ -170,8 +170,9 @@ namespace { }; typedef cc::MichaelHashMap< gc_type, list_type, map_traits > map_type; - map_type s( kSize, 8 ); - test( s ); + map_type m( kSize, 8 ); + test( m ); + EXPECT_GE( m.statistics().m_nInsertSuccess, 0 ); } TEST_F( MichaelIterableMap_DHP, wrapped_stat ) @@ -189,8 +190,9 @@ namespace { }; typedef cc::MichaelHashMap< gc_type, list_type, map_traits > map_type; - map_type s( kSize, 8 ); - test( s ); + map_type m( kSize, 8 ); + test( m ); + EXPECT_GE( m.statistics().m_nInsertSuccess, 0 ); } } // namespace diff --git a/test/unit/map/michael_iterable_hp.cpp b/test/unit/map/michael_iterable_hp.cpp index 1f0f0339..71e37a0f 100644 --- a/test/unit/map/michael_iterable_hp.cpp +++ b/test/unit/map/michael_iterable_hp.cpp @@ -171,8 +171,9 @@ namespace { }; typedef cc::MichaelHashMap< gc_type, list_type, map_traits > map_type; - map_type s( kSize, 8 ); - test( s ); + map_type m( kSize, 8 ); + test( m ); + EXPECT_GE( m.statistics().m_nInsertSuccess, 0 ); } TEST_F( MichaelIterableMap_HP, wrapped_stat ) @@ -190,8 +191,9 @@ namespace { }; typedef cc::MichaelHashMap< gc_type, list_type, map_traits > map_type; - map_type s( kSize, 8 ); - test( s ); + map_type m( kSize, 8 ); + test( m ); + EXPECT_GE( m.statistics().m_nInsertSuccess, 0 ); } } // namespace diff --git a/test/unit/map/michael_lazy_dhp.cpp b/test/unit/map/michael_lazy_dhp.cpp index 27968f5c..e995945c 100644 --- a/test/unit/map/michael_lazy_dhp.cpp +++ b/test/unit/map/michael_lazy_dhp.cpp @@ -192,6 +192,7 @@ namespace { map_type m( kSize, 2 ); test( m ); + EXPECT_GE( m.statistics().m_nInsertSuccess, 0 ); } TEST_F( MichaelLazyMap_DHP, wrapped_stat ) @@ -212,6 +213,7 @@ namespace { map_type m( kSize, 2 ); test( m ); + EXPECT_GE( m.statistics().m_nInsertSuccess, 0 ); } } // namespace diff --git a/test/unit/map/michael_lazy_hp.cpp b/test/unit/map/michael_lazy_hp.cpp index 209fc27b..b6db024f 100644 --- a/test/unit/map/michael_lazy_hp.cpp +++ b/test/unit/map/michael_lazy_hp.cpp @@ -193,6 +193,7 @@ namespace { map_type m( kSize, 2 ); test( m ); + EXPECT_GE( m.statistics().m_nInsertSuccess, 0 ); } TEST_F( MichaelLazyMap_HP, wrapped_stat ) @@ -213,6 +214,7 @@ namespace { map_type m( kSize, 2 ); test( m ); + EXPECT_GE( m.statistics().m_nInsertSuccess, 0 ); } } // namespace diff --git a/test/unit/map/michael_lazy_nogc.cpp b/test/unit/map/michael_lazy_nogc.cpp index 9ad73c67..293bb78e 100644 --- a/test/unit/map/michael_lazy_nogc.cpp +++ b/test/unit/map/michael_lazy_nogc.cpp @@ -25,7 +25,7 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "test_map_nogc.h" @@ -160,10 +160,54 @@ namespace { typedef hash1 hash; typedef cds::atomicity::item_counter item_counter; }; - typedef cc::MichaelHashMap< gc_type, list_type, map_traits >map_type; + typedef cc::MichaelHashMap< gc_type, list_type, map_traits > map_type; + + map_type m( kSize, 4 ); + test( m ); + } + + TEST_F( MichaelLazyMap_NoGC, stat ) + { + struct list_traits: public cc::lazy_list::traits + { + typedef base_class::less less; + typedef cds::backoff::pause back_off; + typedef cc::lazy_list::stat<> stat; + }; + typedef cc::LazyKVList< gc_type, key_type, value_type, list_traits > list_type; + + struct map_traits: public cc::michael_map::traits + { + typedef hash1 hash; + typedef cds::atomicity::item_counter item_counter; + }; + typedef cc::MichaelHashMap< gc_type, list_type, map_traits > map_type; + + map_type m( kSize, 4 ); + test( m ); + EXPECT_GE( m.statistics().m_nInsertSuccess, 0 ); + } + + TEST_F( MichaelLazyMap_NoGC, wrapped_stat ) + { + struct list_traits: public cc::lazy_list::traits + { + typedef base_class::less less; + typedef cds::backoff::pause back_off; + typedef cc::lazy_list::wrapped_stat<> stat; + }; + typedef cc::LazyKVList< gc_type, key_type, value_type, list_traits > list_type; + + struct map_traits: public cc::michael_map::traits + { + typedef hash1 hash; + typedef cds::atomicity::item_counter item_counter; + }; + typedef cc::MichaelHashMap< gc_type, list_type, map_traits > map_type; map_type m( kSize, 4 ); test( m ); + EXPECT_GE( m.statistics().m_nInsertSuccess, 0 ); } } // namespace diff --git a/test/unit/map/michael_michael_dhp.cpp b/test/unit/map/michael_michael_dhp.cpp index a1cad613..cfd4a2b6 100644 --- a/test/unit/map/michael_michael_dhp.cpp +++ b/test/unit/map/michael_michael_dhp.cpp @@ -170,8 +170,9 @@ namespace { }; typedef cc::MichaelHashMap< gc_type, list_type, map_traits > map_type; - map_type s( kSize, 8 ); - test( s ); + map_type m( kSize, 8 ); + test( m ); + EXPECT_GE( m.statistics().m_nInsertSuccess, 0 ); } TEST_F( MichaelMap_DHP, wrapped_stat ) @@ -189,8 +190,9 @@ namespace { }; typedef cc::MichaelHashMap< gc_type, list_type, map_traits > map_type; - map_type s( kSize, 8 ); - test( s ); + map_type m( kSize, 8 ); + test( m ); + EXPECT_GE( m.statistics().m_nInsertSuccess, 0 ); } } // namespace diff --git a/test/unit/map/michael_michael_hp.cpp b/test/unit/map/michael_michael_hp.cpp index 6b48b784..4c3a7ae4 100644 --- a/test/unit/map/michael_michael_hp.cpp +++ b/test/unit/map/michael_michael_hp.cpp @@ -171,8 +171,9 @@ namespace { }; typedef cc::MichaelHashMap< gc_type, list_type, map_traits > map_type; - map_type s( kSize, 8 ); - test( s ); + map_type m( kSize, 8 ); + test( m ); + EXPECT_GE( m.statistics().m_nInsertSuccess, 0 ); } TEST_F( MichaelMap_HP, wrapped_stat ) @@ -191,8 +192,9 @@ namespace { }; typedef cc::MichaelHashMap< gc_type, list_type, map_traits > map_type; - map_type s( kSize, 8 ); - test( s ); + map_type m( kSize, 8 ); + test( m ); + EXPECT_GE( m.statistics().m_nInsertSuccess, 0 ); } } // namespace diff --git a/test/unit/map/michael_michael_nogc.cpp b/test/unit/map/michael_michael_nogc.cpp index b791e439..b66e81b2 100644 --- a/test/unit/map/michael_michael_nogc.cpp +++ b/test/unit/map/michael_michael_nogc.cpp @@ -25,7 +25,7 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "test_map_nogc.h" @@ -145,4 +145,48 @@ namespace { test( m ); } + TEST_F( MichaelMap_NoGC, stat ) + { + struct list_traits: public cc::michael_list::traits + { + typedef base_class::less less; + typedef cds::backoff::pause back_off; + typedef cc::michael_list::stat<> stat; + }; + typedef cc::MichaelKVList< gc_type, key_type, value_type, list_traits > list_type; + + struct map_traits: public cc::michael_map::traits + { + typedef hash1 hash; + typedef cds::atomicity::item_counter item_counter; + }; + typedef cc::MichaelHashMap< gc_type, list_type, map_traits > map_type; + + map_type m( kSize, 4 ); + test( m ); + EXPECT_GE( m.statistics().m_nInsertSuccess, 0 ); + } + + TEST_F( MichaelMap_NoGC, wrapped_stat ) + { + struct list_traits: public cc::michael_list::traits + { + typedef base_class::less less; + typedef cds::backoff::pause back_off; + typedef cc::michael_list::wrapped_stat<> stat; + }; + typedef cc::MichaelKVList< gc_type, key_type, value_type, list_traits > list_type; + + struct map_traits: public cc::michael_map::traits + { + typedef hash1 hash; + typedef cds::atomicity::item_counter item_counter; + }; + typedef cc::MichaelHashMap< gc_type, list_type, map_traits > map_type; + + map_type m( kSize, 4 ); + test( m ); + EXPECT_GE( m.statistics().m_nInsertSuccess, 0 ); + } + } // namespace diff --git a/test/unit/map/test_michael_lazy_rcu.h b/test/unit/map/test_michael_lazy_rcu.h index db97971f..d69dd36f 100644 --- a/test/unit/map/test_michael_lazy_rcu.h +++ b/test/unit/map/test_michael_lazy_rcu.h @@ -25,7 +25,7 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef CDSUNIT_MAP_TEST_MICHAEL_LAZY_RCU_H #define CDSUNIT_MAP_TEST_MICHAEL_LAZY_RCU_H @@ -201,11 +201,63 @@ namespace { this->test( m ); } + TYPED_TEST_P( MichaelLazyMap, stat ) + { + typedef typename TestFixture::rcu_type rcu_type; + typedef typename TestFixture::key_type key_type; + typedef typename TestFixture::value_type value_type; + + struct list_traits: public cc::lazy_list::traits + { + typedef typename TestFixture::less less; + typedef cds::backoff::pause back_off; + typedef cc::lazy_list::stat<> stat; + }; + typedef cc::LazyKVList< rcu_type, key_type, value_type, list_traits > list_type; + + struct set_traits: public cc::michael_map::traits + { + typedef typename TestFixture::hash1 hash; + typedef cds::atomicity::item_counter item_counter; + }; + typedef cc::MichaelHashMap< rcu_type, list_type, set_traits >map_type; + + map_type m( TestFixture::kSize, 4 ); + this->test( m ); + EXPECT_GE( m.statistics().m_nInsertSuccess, 0 ); + } + + TYPED_TEST_P( MichaelLazyMap, wrapped_stat ) + { + typedef typename TestFixture::rcu_type rcu_type; + typedef typename TestFixture::key_type key_type; + typedef typename TestFixture::value_type value_type; + + struct list_traits: public cc::lazy_list::traits + { + typedef typename TestFixture::less less; + typedef cds::backoff::pause back_off; + typedef cc::lazy_list::wrapped_stat<> stat; + }; + typedef cc::LazyKVList< rcu_type, key_type, value_type, list_traits > list_type; + + struct set_traits: public cc::michael_map::traits + { + typedef typename TestFixture::hash1 hash; + typedef cds::atomicity::item_counter item_counter; + }; + typedef cc::MichaelHashMap< rcu_type, list_type, set_traits >map_type; + + map_type m( TestFixture::kSize, 4 ); + this->test( m ); + EXPECT_GE( m.statistics().m_nInsertSuccess, 0 ); + } + // GCC 5: All test names should be written on single line, otherwise a runtime error will be encountered like as // "No test named can be found in this test case" REGISTER_TYPED_TEST_CASE_P( MichaelLazyMap, - compare, less, cmpmix, backoff, seq_cst, mutex + compare, less, cmpmix, backoff, seq_cst, mutex, stat, wrapped_stat ); } // namespace diff --git a/test/unit/map/test_michael_michael_rcu.h b/test/unit/map/test_michael_michael_rcu.h index dc66ad82..68e6964a 100644 --- a/test/unit/map/test_michael_michael_rcu.h +++ b/test/unit/map/test_michael_michael_rcu.h @@ -25,7 +25,7 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef CDSUNIT_MAP_TEST_MICHAEL_MICHAEL_RCU_H #define CDSUNIT_MAP_TEST_MICHAEL_MICHAEL_RCU_H @@ -176,9 +176,60 @@ namespace { this->test( m ); } + TYPED_TEST_P( MichaelMap, stat ) + { + typedef typename TestFixture::rcu_type rcu_type; + typedef typename TestFixture::key_type key_type; + typedef typename TestFixture::value_type value_type; + + struct list_traits: public cc::michael_list::traits + { + typedef typename TestFixture::less less; + typedef cds::backoff::pause back_off; + typedef cc::michael_list::stat<> stat; + }; + typedef cc::MichaelKVList< rcu_type, key_type, value_type, list_traits > list_type; + + struct map_traits: public cc::michael_map::traits + { + typedef typename TestFixture::hash1 hash; + typedef cds::atomicity::item_counter item_counter; + }; + typedef cc::MichaelHashMap< rcu_type, list_type, map_traits >map_type; + + map_type m( TestFixture::kSize, 4 ); + this->test( m ); + EXPECT_GE( m.statistics().m_nInsertSuccess, 0 ); + } + + TYPED_TEST_P( MichaelMap, wrapped_stat ) + { + typedef typename TestFixture::rcu_type rcu_type; + typedef typename TestFixture::key_type key_type; + typedef typename TestFixture::value_type value_type; + + struct list_traits: public cc::michael_list::traits + { + typedef typename TestFixture::less less; + typedef cds::backoff::pause back_off; + typedef cc::michael_list::wrapped_stat<> stat; + }; + typedef cc::MichaelKVList< rcu_type, key_type, value_type, list_traits > list_type; + + struct map_traits: public cc::michael_map::traits + { + typedef typename TestFixture::hash1 hash; + typedef cds::atomicity::item_counter item_counter; + }; + typedef cc::MichaelHashMap< rcu_type, list_type, map_traits >map_type; + + map_type m( TestFixture::kSize, 4 ); + this->test( m ); + EXPECT_GE( m.statistics().m_nInsertSuccess, 0 ); + } REGISTER_TYPED_TEST_CASE_P( MichaelMap, - compare, less, cmpmix, backoff, seq_cst + compare, less, cmpmix, backoff, seq_cst, stat, wrapped_stat ); } diff --git a/test/unit/set/michael_iterable_dhp.cpp b/test/unit/set/michael_iterable_dhp.cpp index 0ff99a88..9c09643b 100644 --- a/test/unit/set/michael_iterable_dhp.cpp +++ b/test/unit/set/michael_iterable_dhp.cpp @@ -192,6 +192,7 @@ namespace { set_type s( kSize, 4 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( MichaelIterableSet_DHP, wrapped_stat ) @@ -213,6 +214,7 @@ namespace { set_type s( kSize, 4 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } } // namespace diff --git a/test/unit/set/michael_iterable_hp.cpp b/test/unit/set/michael_iterable_hp.cpp index b3313e75..444dc68d 100644 --- a/test/unit/set/michael_iterable_hp.cpp +++ b/test/unit/set/michael_iterable_hp.cpp @@ -193,6 +193,7 @@ namespace { set_type s( kSize, 4 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( MichaelIterableSet_HP, wrapped_stat ) @@ -214,6 +215,7 @@ namespace { set_type s( kSize, 4 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } } // namespace diff --git a/test/unit/set/michael_lazy_dhp.cpp b/test/unit/set/michael_lazy_dhp.cpp index be57e996..b362edca 100644 --- a/test/unit/set/michael_lazy_dhp.cpp +++ b/test/unit/set/michael_lazy_dhp.cpp @@ -213,6 +213,7 @@ namespace { set_type s( kSize, 4 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( MichaelLazySet_DHP, wrapped_stat ) @@ -234,6 +235,7 @@ namespace { set_type s( kSize, 4 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } } // namespace diff --git a/test/unit/set/michael_lazy_hp.cpp b/test/unit/set/michael_lazy_hp.cpp index 8e3cee2a..88ddd892 100644 --- a/test/unit/set/michael_lazy_hp.cpp +++ b/test/unit/set/michael_lazy_hp.cpp @@ -214,6 +214,7 @@ namespace { set_type s( kSize, 4 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( MichaelLazySet_HP, wrapped_stat ) @@ -235,6 +236,7 @@ namespace { set_type s( kSize, 4 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } } // namespace diff --git a/test/unit/set/michael_lazy_nogc.cpp b/test/unit/set/michael_lazy_nogc.cpp index 76b9cb18..8a14438d 100644 --- a/test/unit/set/michael_lazy_nogc.cpp +++ b/test/unit/set/michael_lazy_nogc.cpp @@ -204,6 +204,7 @@ namespace { set_type s( kSize, 4 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( MichaelLazySet_NoGC, wrapped_stat ) @@ -225,6 +226,7 @@ namespace { set_type s( kSize, 4 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } } // namespace diff --git a/test/unit/set/michael_michael_dhp.cpp b/test/unit/set/michael_michael_dhp.cpp index 046e0c21..97a1be2b 100644 --- a/test/unit/set/michael_michael_dhp.cpp +++ b/test/unit/set/michael_michael_dhp.cpp @@ -192,6 +192,7 @@ namespace { set_type s( kSize, 4 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( MichaelSet_DHP, wrapped_stat ) @@ -213,6 +214,7 @@ namespace { set_type s( kSize, 4 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } } // namespace diff --git a/test/unit/set/michael_michael_hp.cpp b/test/unit/set/michael_michael_hp.cpp index dc85ec73..081b3450 100644 --- a/test/unit/set/michael_michael_hp.cpp +++ b/test/unit/set/michael_michael_hp.cpp @@ -193,6 +193,7 @@ namespace { set_type s( kSize, 4 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( MichaelSet_HP, wrapped_stat ) @@ -214,6 +215,7 @@ namespace { set_type s( kSize, 4 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } } // namespace diff --git a/test/unit/set/michael_michael_nogc.cpp b/test/unit/set/michael_michael_nogc.cpp index 5dda78bb..e8066231 100644 --- a/test/unit/set/michael_michael_nogc.cpp +++ b/test/unit/set/michael_michael_nogc.cpp @@ -183,6 +183,7 @@ namespace { set_type s( kSize, 4 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TEST_F( MichaelSet_NoGC, wrapped_stat ) @@ -204,6 +205,7 @@ namespace { set_type s( kSize, 4 ); test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } } // namespace diff --git a/test/unit/set/test_michael_lazy_rcu.h b/test/unit/set/test_michael_lazy_rcu.h index ffe1e100..e5e99e03 100644 --- a/test/unit/set/test_michael_lazy_rcu.h +++ b/test/unit/set/test_michael_lazy_rcu.h @@ -238,6 +238,7 @@ TYPED_TEST_P( MichaelLazySet, stat ) set_type s( TestFixture::kSize, 4 ); this->test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TYPED_TEST_P( MichaelLazySet, wrapped_stat ) @@ -262,6 +263,7 @@ TYPED_TEST_P( MichaelLazySet, wrapped_stat ) set_type s( TestFixture::kSize, 4 ); this->test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } // GCC 5: All test names should be written on single line, otherwise a runtime error will be encountered like as diff --git a/test/unit/set/test_michael_michael_rcu.h b/test/unit/set/test_michael_michael_rcu.h index c6b9ea0d..73163d8d 100644 --- a/test/unit/set/test_michael_michael_rcu.h +++ b/test/unit/set/test_michael_michael_rcu.h @@ -214,6 +214,7 @@ TYPED_TEST_P( MichaelSet, stat ) set_type s( TestFixture::kSize, 4 ); this->test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } TYPED_TEST_P( MichaelSet, wrapped_stat ) @@ -238,6 +239,7 @@ TYPED_TEST_P( MichaelSet, wrapped_stat ) set_type s( TestFixture::kSize, 4 ); this->test( s ); + EXPECT_GE( s.statistics().m_nInsertSuccess, 0 ); } // GCC 5: All test names should be written on single line, otherwise a runtime error will be encountered like as -- 2.34.1