From 3b8c11d9d713f617ad055ab8006c4cb43f9dee50 Mon Sep 17 00:00:00 2001 From: khizmax Date: Sat, 23 May 2015 19:45:14 +0300 Subject: [PATCH] Changed MichaelSet/Map for new MichaelList extract()/get() semantics --- cds/container/lazy_kvlist_rcu.h | 2 + cds/container/lazy_list_rcu.h | 2 + cds/container/michael_kvlist_rcu.h | 2 + cds/container/michael_list_rcu.h | 2 + cds/container/michael_map_rcu.h | 54 +++++----- cds/container/michael_set_rcu.h | 57 +++++----- cds/intrusive/lazy_list_rcu.h | 2 + cds/intrusive/michael_list_rcu.h | 4 +- cds/intrusive/michael_set_rcu.h | 58 +++++----- tests/test-hdr/map/hdr_map.h | 89 +++++++++++++++ .../test-hdr/map/hdr_michael_map_rcu_gpb.cpp | 12 +-- .../test-hdr/map/hdr_michael_map_rcu_gpi.cpp | 12 +-- .../test-hdr/map/hdr_michael_map_rcu_gpt.cpp | 12 +-- .../test-hdr/map/hdr_michael_map_rcu_shb.cpp | 12 +-- .../test-hdr/map/hdr_michael_map_rcu_sht.cpp | 12 +-- .../set/hdr_intrusive_michael_set_rcu_gpb.cpp | 12 +-- .../set/hdr_intrusive_michael_set_rcu_gpi.cpp | 12 +-- .../set/hdr_intrusive_michael_set_rcu_gpt.cpp | 12 +-- .../set/hdr_intrusive_michael_set_rcu_shb.cpp | 12 +-- .../set/hdr_intrusive_michael_set_rcu_sht.cpp | 12 +-- tests/test-hdr/set/hdr_intrusive_set.h | 101 +++++++++++++++++- .../test-hdr/set/hdr_michael_set_rcu_gpb.cpp | 12 +-- .../test-hdr/set/hdr_michael_set_rcu_gpi.cpp | 12 +-- .../test-hdr/set/hdr_michael_set_rcu_gpt.cpp | 12 +-- .../test-hdr/set/hdr_michael_set_rcu_shb.cpp | 12 +-- .../test-hdr/set/hdr_michael_set_rcu_sht.cpp | 12 +-- tests/test-hdr/set/hdr_set.h | 91 ++++++++++++++++ 27 files changed, 470 insertions(+), 174 deletions(-) diff --git a/cds/container/lazy_kvlist_rcu.h b/cds/container/lazy_kvlist_rcu.h index de24d131..625a2218 100644 --- a/cds/container/lazy_kvlist_rcu.h +++ b/cds/container/lazy_kvlist_rcu.h @@ -124,6 +124,8 @@ namespace cds { namespace container { using exempt_ptr = cds::urcu::exempt_ptr< gc, node_type, value_type, typename maker::intrusive_traits::disposer, cds::urcu::details::conventional_exempt_pair_cast >; + /// Type of \p get() member function return value + typedef value_type * get_result; protected: //@cond diff --git a/cds/container/lazy_list_rcu.h b/cds/container/lazy_list_rcu.h index 8aec5b12..0441885a 100644 --- a/cds/container/lazy_list_rcu.h +++ b/cds/container/lazy_list_rcu.h @@ -130,6 +130,8 @@ namespace cds { namespace container { public: using exempt_ptr = cds::urcu::exempt_ptr< gc, node_type, value_type, typename maker::intrusive_traits::disposer >; ///< pointer to extracted node + /// Type of \p get() member function return value + typedef value_type * get_result; private: //@cond diff --git a/cds/container/michael_kvlist_rcu.h b/cds/container/michael_kvlist_rcu.h index 8b1e25eb..5dc7a07c 100644 --- a/cds/container/michael_kvlist_rcu.h +++ b/cds/container/michael_kvlist_rcu.h @@ -153,6 +153,8 @@ namespace cds { namespace container { public: /// 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; + /// Type of \p get() member function return value + typedef raw_ptr get_result; protected: //@cond diff --git a/cds/container/michael_list_rcu.h b/cds/container/michael_list_rcu.h index b2a3fb70..76864658 100644 --- a/cds/container/michael_list_rcu.h +++ b/cds/container/michael_list_rcu.h @@ -160,6 +160,8 @@ namespace cds { namespace container { public: /// 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; + /// Type of \p get() member function return value + typedef raw_ptr get_result; private: //@cond diff --git a/cds/container/michael_map_rcu.h b/cds/container/michael_map_rcu.h index 34e53c32..4225aa39 100644 --- a/cds/container/michael_map_rcu.h +++ b/cds/container/michael_map_rcu.h @@ -74,6 +74,8 @@ namespace cds { namespace container { 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::get_result get_result; //@cond typedef cds::container::michael_map::implementation_tag implementation_tag; @@ -534,11 +536,11 @@ namespace cds { namespace container { unlinks it from the map, and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the item found. If the item is not found the function return an empty \p exempt_ptr. - @note The function does NOT call RCU read-side lock or synchronization, - and does NOT dispose the item found. It just excludes the item from the map - and returns a pointer to item found. - You should lock RCU before calling of the function, and you should synchronize RCU - outside the RCU lock to free extracted item + 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: + - 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. \code #include @@ -553,17 +555,14 @@ namespace cds { namespace container { // ... rcu_michael_map::exempt_ptr p; - { - // first, we should lock RCU - rcu_michael_map::rcu_lock lock; - - // Now, you can apply extract function - // Note that you must not delete the item found inside the RCU lock - p = theMap.extract( 10 ); - if ( p ) { - // do something with p - ... - } + + // For MichaelList we should not lock RCU + + // Note that you must not delete the item found inside the RCU lock + p = theMap.extract( 10 ); + if ( p ) { + // do something with p + ... } // We may safely release p here @@ -617,7 +616,7 @@ namespace cds { namespace container { The function returns \p true if \p key is found, \p false otherwise. */ template - bool find( K const& key, Func f ) const + bool find( K const& key, Func f ) { return bucket( key ).find( key, f ); } @@ -630,7 +629,7 @@ namespace cds { namespace container { \p Less must imply the same element order as the comparator used for building the map. */ template - bool find_with( K const& key, Less pred, Func f ) const + bool find_with( K const& key, Less pred, Func f ) { return bucket( key ).find_with( key, pred, f ); } @@ -644,7 +643,7 @@ namespace cds { namespace container { The function applies RCU lock internally. */ template - bool find( K const& key ) const + bool find( K const& key ) { return bucket( key ).find( key ); } @@ -657,7 +656,7 @@ namespace cds { namespace container { \p Less must imply the same element order as the comparator used for building the map. */ template - bool find_with( K const& key, Less pred ) const + bool find_with( K const& key, Less pred ) { return bucket( key ).find_with( key, pred ); } @@ -666,6 +665,8 @@ 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. + 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. @@ -675,22 +676,23 @@ namespace cds { namespace container { typedef cds::container::MichaelHashMap< your_template_parameters > hash_map; hash_map theMap; // ... + typename hash_map::get_result gp; { // Lock RCU hash_map::rcu_lock lock; - hash_map::value_type * = theMap.get( 5 ); - if ( pVal ) { - // Deal with pVal + gp = theMap.get( 5 ); + if ( gp ) { + // Deal with gp //... } // Unlock RCU by rcu_lock destructor - // pVal can be freed at any time after RCU has been unlocked + // gp can be reclaimed at any time after RCU has been unlocked } \endcode */ template - value_type * get( K const& key ) const + get_result get( K const& key ) { return bucket( key ).get( key ); } @@ -705,7 +707,7 @@ namespace cds { namespace container { \p pred must imply the same element order as the comparator used for building the map. */ template - value_type * get_with( K const& key, Less pred ) const + get_result get_with( K const& key, Less pred ) { return bucket( key ).get_with( key, pred ); } diff --git a/cds/container/michael_set_rcu.h b/cds/container/michael_set_rcu.h index 3bf12d8c..02761999 100644 --- a/cds/container/michael_set_rcu.h +++ b/cds/container/michael_set_rcu.h @@ -123,6 +123,7 @@ namespace cds { namespace container { typedef typename bucket_type::rcu_lock rcu_lock; ///< RCU scoped lock typedef typename bucket_type::exempt_ptr exempt_ptr; ///< pointer to extracted node + typedef typename bucket_type::get_result get_result; ///< Return type of \p get() member function and its derivatives /// 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; @@ -456,11 +457,11 @@ namespace cds { namespace container { unlinks it from the set, and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the item found. If the item with the key equal to \p key is not found the function return an empty \p exempt_ptr. - @note The function does NOT call RCU read-side lock or synchronization, - and does NOT dispose the item found. It just excludes the item from the set - and returns a pointer to item found. - You should lock RCU before calling of the function, and you should synchronize RCU - outside the RCU lock to free extracted item + The function just excludes the item from the set and returns a pointer to item found. + Depends on \p bucket_type 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. \code #include @@ -474,18 +475,15 @@ namespace cds { namespace container { rcu_michael_set theSet; // ... - rcu_michael_set::exempt_ptr p; - { - // first, we should lock RCU - rcu_michael_set::rcu_lock lock; - - // Now, you can apply extract function - // Note that you must not delete the item found inside the RCU lock - p = theSet.extract( 10 ); - if ( p ) { - // do something with p - ... - } + typename rcu_michael_set::exempt_ptr p; + + // For MichaelList we should not lock RCU + + // Note that you must not delete the item found inside the RCU lock + p = theSet.extract( 10 ); + if ( p ) { + // do something with p + ... } // We may safely release p here @@ -545,13 +543,13 @@ namespace cds { namespace container { The function returns \p true if \p key is found, \p false otherwise. */ template - bool find( Q& key, Func f ) const + bool find( Q& key, Func f ) { return bucket( key ).find( key, f ); } //@cond template - bool find( Q const& key, Func f ) const + bool find( Q const& key, Func f ) { return bucket( key ).find( key, f ); } @@ -565,13 +563,13 @@ namespace cds { namespace container { \p Less must imply the same element order as the comparator used for building the set. */ template - bool find_with( Q& key, Less pred, Func f ) const + bool find_with( Q& key, Less pred, Func f ) { return bucket( key ).find_with( key, pred, f ); } //@cond template - bool find_with( Q const& key, Less pred, Func f ) const + bool find_with( Q const& key, Less pred, Func f ) { return bucket( key ).find_with( key, pred, f ); } @@ -587,7 +585,7 @@ namespace cds { namespace container { should accept a parameter of type \p Q that may be not the same as \p value_type. */ template - bool find( Q const & key ) const + bool find( Q const & key ) { return bucket( key ).find( key ); } @@ -600,7 +598,7 @@ namespace cds { namespace container { \p Less must imply the same element order as the comparator used for building the set. */ template - bool find_with( Q const & key, Less pred ) const + bool find_with( Q const & key, Less pred ) { return bucket( key ).find_with( key, pred ); } @@ -609,6 +607,8 @@ namespace cds { namespace container { /** \anchor cds_nonintrusive_MichaelHashSet_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. + For details, see documentation of ordered list you use. Note the compare functor should accept a parameter of type \p Q that can be not the same as \p value_type. @@ -617,23 +617,24 @@ namespace cds { namespace container { \code typedef cds::container::MichaelHashSet< your_template_parameters > hash_set; hash_set theSet; + typename hash_set::get_result gp; // ... { // Lock RCU hash_set::rcu_lock lock; - foo * pVal = theSet.get( 5 ); - if ( pVal ) { + gp = theSet.get( 5 ); + if ( gp ) { // Deal with pVal //... } // Unlock RCU by rcu_lock destructor - // pVal can be freed at any time after RCU has been unlocked + // gp can be reclaimed at any time after RCU has been unlocked } \endcode */ template - value_type * get( Q const& key ) const + get_result get( Q const& key ) { return bucket( key ).get( key ); } @@ -648,7 +649,7 @@ namespace cds { namespace container { \p pred must imply the same element order as the comparator used for building the set. */ template - value_type * get_with( Q const& key, Less pred ) const + get_result get_with( Q const& key, Less pred ) { return bucket( key ).get_with( key, pred ); } diff --git a/cds/intrusive/lazy_list_rcu.h b/cds/intrusive/lazy_list_rcu.h index 7fdb2ba1..bb9655d0 100644 --- a/cds/intrusive/lazy_list_rcu.h +++ b/cds/intrusive/lazy_list_rcu.h @@ -232,6 +232,8 @@ namespace cds { namespace intrusive { public: /// pointer to extracted node using exempt_ptr = cds::urcu::exempt_ptr< gc, value_type, value_type, clear_and_dispose, void >; + /// Type of \p get() member function return value + typedef value_type * get_result; protected: //@cond diff --git a/cds/intrusive/michael_list_rcu.h b/cds/intrusive/michael_list_rcu.h index 577485b2..000a1b8d 100644 --- a/cds/intrusive/michael_list_rcu.h +++ b/cds/intrusive/michael_list_rcu.h @@ -235,7 +235,9 @@ namespace cds { namespace intrusive { public: /// Result of \p get(), \p get_with() functions - pointer to the node found - typedef cds::urcu::raw_ptr< gc, value_type, raw_ptr_disposer > raw_ptr; + typedef cds::urcu::raw_ptr< gc, value_type, raw_ptr_disposer > raw_ptr; + /// Type of \p get() member function return value + typedef raw_ptr get_result; protected: //@cond diff --git a/cds/intrusive/michael_set_rcu.h b/cds/intrusive/michael_set_rcu.h index 75785021..5aff39dd 100644 --- a/cds/intrusive/michael_set_rcu.h +++ b/cds/intrusive/michael_set_rcu.h @@ -91,6 +91,7 @@ namespace cds { namespace intrusive { typedef typename bucket_type::rcu_lock rcu_lock; ///< RCU scoped lock typedef typename bucket_type::exempt_ptr exempt_ptr; ///< pointer to extracted node + typedef typename bucket_type::get_result get_result; ///< Return type of \p get() member function and its derivatives /// 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; @@ -401,11 +402,10 @@ namespace cds { namespace intrusive { unlinks it from the set, and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the item found. If the item with the key equal to \p key is not found the function returns an empty \p exempt_ptr. - @note The function does NOT call RCU read-side lock or synchronization, - and does NOT dispose the item found. It just excludes the item from the set - and returns a pointer to item found. - You should lock RCU before calling of the function, and you should synchronize RCU - outside the RCU lock before reusing returned pointer. + Depends on \p bucket_type you should or should not lock RCU before calling of this function: + - for the set based on \ref cds_intrusive_MichaelList_rcu "MichaelList" RCU should not be locked + - for the set based on \ref cds_intrusive_LazyList_rcu "LazyList" RCU should be locked + See ordered list implementation for details. \code #include @@ -420,17 +420,15 @@ namespace cds { namespace intrusive { // ... typename rcu_michael_set::exempt_ptr p; - { - // first, we should lock RCU - typename rcu_michael_set::rcu_lock lock; - - // Now, you can apply extract function - // Note that you must not delete the item found inside the RCU lock - p = theSet.extract( 10 ) - if ( p ) { - // do something with p - ... - } + + // For MichaelList we should not lock RCU + + // Now, you can apply extract function + // Note that you must not delete the item found inside the RCU lock + p = theSet.extract( 10 ) + if ( p ) { + // do something with p + ... } // We may safely release p here @@ -469,7 +467,7 @@ namespace cds { namespace intrusive { and returns \p true if \p key found or \p false otherwise. */ template - bool find( Q const& key ) const + bool find( Q const& key ) { return bucket( key ).find( key ); } @@ -482,7 +480,7 @@ namespace cds { namespace intrusive { \p pred must imply the same element order as the comparator used for building the set. */ template - bool find_with( Q const& key, Less pred ) const + bool find_with( Q const& key, Less pred ) { return bucket( key ).find_with( key, pred ); } @@ -511,13 +509,13 @@ namespace cds { namespace intrusive { The function returns \p true if \p key is found, \p false otherwise. */ template - bool find( Q& key, Func f ) const + bool find( Q& key, Func f ) { return bucket( key ).find( key, f ); } //@cond template - bool find( Q const& key, Func f ) const + bool find( Q const& key, Func f ) { return bucket( key ).find( key, f ); } @@ -531,13 +529,13 @@ namespace cds { namespace intrusive { \p pred must imply the same element order as the comparator used for building the set. */ template - bool find_with( Q& key, Less pred, Func f ) const + bool find_with( Q& key, Less pred, Func f ) { return bucket( key ).find_with( key, pred, f ); } //@cond template - bool find_with( Q const& key, Less pred, Func f ) const + bool find_with( Q const& key, Less pred, Func f ) { return bucket( key ).find_with( key, pred, f ); } @@ -547,6 +545,8 @@ namespace cds { namespace intrusive { /** \anchor cds_intrusive_MichaelHashSet_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. + For details, see documentation of ordered list you use. Note the compare functor should accept a parameter of type \p Q that can be not the same as \p value_type. @@ -556,22 +556,24 @@ namespace cds { namespace intrusive { typedef cds::intrusive::MichaelHashSet< your_template_parameters > hash_set; hash_set theSet; // ... + // Result of get() call + typename hash_set::get_result ptr; { // Lock RCU hash_set::rcu_lock lock; - foo * pVal = theSet.get( 5 ); - if ( pVal ) { - // Deal with pVal + ptr = theSet.get( 5 ); + if ( ptr ) { + // Deal with ptr //... } // Unlock RCU by rcu_lock destructor - // pVal can be retired by disposer at any time after RCU has been unlocked + // ptr can be reclaimed by disposer at any time after RCU has been unlocked } \endcode */ template - value_type * get( Q const& key ) const + get_result get( Q const& key ) { return bucket( key ).get( key ); } @@ -586,7 +588,7 @@ namespace cds { namespace intrusive { \p pred must imply the same element order as the comparator used for building the set. */ template - value_type * get_with( Q const& key, Less pred ) const + get_result get_with( Q const& key, Less pred ) { return bucket( key ).get_with( key, pred ); } diff --git a/tests/test-hdr/map/hdr_map.h b/tests/test-hdr/map/hdr_map.h index 8db81e98..d8986ee2 100644 --- a/tests/test-hdr/map/hdr_map.h +++ b/tests/test-hdr/map/hdr_map.h @@ -344,6 +344,95 @@ namespace map { test_iter(); } + template + void test_rcu_michael_list() + { + Map m( 52, 4 ); + + test_int_with(m); + + // extract/get test + { + typedef typename Map::gc rcu; + typedef typename Map::rcu_lock rcu_lock; + typedef typename Map::value_type value_type; + typename Map::exempt_ptr ep; + typename Map::get_result gp; + + static size_t const nLimit = 100; + int arr[nLimit]; + for ( size_t i = 0; i < nLimit; ++i ) + arr[i] = (int) i; + shuffle( arr, arr + nLimit ); + + for ( size_t i = 0; i < nLimit; ++i ) + CPPUNIT_ASSERT( m.insert( arr[i], arr[i] )); + + for ( size_t i = 0; i < nLimit; i += 2 ) { + int nKey = arr[i]; + { + rcu_lock l; + gp = m.get( nKey ); + CPPUNIT_ASSERT( gp ); + CPPUNIT_CHECK( gp->first == nKey ); + CPPUNIT_CHECK( gp->second.m_val == nKey ); + } + gp.release(); + + ep = m.extract( nKey ); + CPPUNIT_ASSERT( ep ); + CPPUNIT_ASSERT( !ep.empty() ); + CPPUNIT_CHECK( nKey == ep->first ); + CPPUNIT_CHECK( nKey == ep->second.m_val ); + ep.release(); + + { + rcu_lock l; + CPPUNIT_CHECK( !m.get( nKey )); + } + ep = m.extract( nKey ); + CPPUNIT_CHECK( !ep ); + CPPUNIT_CHECK( ep.empty() ); + + { + rcu_lock l; + nKey = arr[i+1]; + gp = m.get_with( other_item(nKey), other_less() ); + CPPUNIT_ASSERT( gp ); + CPPUNIT_CHECK( gp->first == nKey ); + CPPUNIT_CHECK( gp->second.m_val == nKey ); + } + gp.release(); + + ep = m.extract_with( other_item( nKey ), other_less() ); + CPPUNIT_ASSERT( ep ); + CPPUNIT_ASSERT( !ep.empty() ); + CPPUNIT_CHECK( nKey == ep->first ); + CPPUNIT_CHECK( nKey == (*ep).second.m_val ); + ep.release(); + + { + rcu_lock l; + CPPUNIT_CHECK( !m.get_with( other_item(nKey), other_less() )); + } + CPPUNIT_CHECK( !m.extract_with( other_item(nKey), other_less() )); + CPPUNIT_CHECK( ep.empty() ); + } + CPPUNIT_CHECK( m.empty() ); + CPPUNIT_CHECK( check_size( m, 0 )); + { + rcu_lock l; + CPPUNIT_CHECK( !m.get( int(nLimit / 2) )); + } + ep = m.extract( int( nLimit / 2 ) ); + CPPUNIT_CHECK( !ep ); + CPPUNIT_CHECK( ep.empty() ); + } + + // iterator test + test_iter(); + } + template void test_int_with( Map& m ) { diff --git a/tests/test-hdr/map/hdr_michael_map_rcu_gpb.cpp b/tests/test-hdr/map/hdr_michael_map_rcu_gpb.cpp index ce970d39..c4515d88 100644 --- a/tests/test-hdr/map/hdr_michael_map_rcu_gpb.cpp +++ b/tests/test-hdr/map/hdr_michael_map_rcu_gpb.cpp @@ -37,7 +37,7 @@ namespace map { // traits-based version typedef cc::MichaelHashMap< rcu_type, list, map_traits > map; - test_rcu< map >(); + test_rcu_michael_list< map >(); // option-based version typedef cc::MichaelHashMap< rcu_type, list, @@ -46,7 +46,7 @@ namespace map { ,cc::opt::item_counter< simple_item_counter > >::type > opt_map; - test_rcu< opt_map >(); + test_rcu_michael_list< opt_map >(); } void HashMapHdrTest::Michael_RCU_GPB_less() @@ -55,7 +55,7 @@ namespace map { // traits-based version typedef cc::MichaelHashMap< rcu_type, list, map_traits > map; - test_rcu< map >(); + test_rcu_michael_list< map >(); // option-based version typedef cc::MichaelHashMap< rcu_type, list, @@ -64,7 +64,7 @@ namespace map { ,cc::opt::item_counter< simple_item_counter > >::type > opt_map; - test_rcu< opt_map >(); + test_rcu_michael_list< opt_map >(); } void HashMapHdrTest::Michael_RCU_GPB_cmpmix() @@ -73,7 +73,7 @@ namespace map { // traits-based version typedef cc::MichaelHashMap< rcu_type, list, map_traits > map; - test_rcu< map >(); + test_rcu_michael_list< map >(); // option-based version typedef cc::MichaelHashMap< rcu_type, list, @@ -82,7 +82,7 @@ namespace map { ,cc::opt::item_counter< simple_item_counter > >::type > opt_map; - test_rcu< opt_map >(); + test_rcu_michael_list< opt_map >(); } diff --git a/tests/test-hdr/map/hdr_michael_map_rcu_gpi.cpp b/tests/test-hdr/map/hdr_michael_map_rcu_gpi.cpp index 907f1bf9..7d606315 100644 --- a/tests/test-hdr/map/hdr_michael_map_rcu_gpi.cpp +++ b/tests/test-hdr/map/hdr_michael_map_rcu_gpi.cpp @@ -37,7 +37,7 @@ namespace map { // traits-based version typedef cc::MichaelHashMap< rcu_type, list, map_traits > map; - test_rcu< map >(); + test_rcu_michael_list< map >(); // option-based version typedef cc::MichaelHashMap< rcu_type, list, @@ -46,7 +46,7 @@ namespace map { ,cc::opt::item_counter< simple_item_counter > >::type > opt_map; - test_rcu< opt_map >(); + test_rcu_michael_list< opt_map >(); } void HashMapHdrTest::Michael_RCU_GPI_less() @@ -55,7 +55,7 @@ namespace map { // traits-based version typedef cc::MichaelHashMap< rcu_type, list, map_traits > map; - test_rcu< map >(); + test_rcu_michael_list< map >(); // option-based version typedef cc::MichaelHashMap< rcu_type, list, @@ -64,7 +64,7 @@ namespace map { ,cc::opt::item_counter< simple_item_counter > >::type > opt_map; - test_rcu< opt_map >(); + test_rcu_michael_list< opt_map >(); } void HashMapHdrTest::Michael_RCU_GPI_cmpmix() @@ -73,7 +73,7 @@ namespace map { // traits-based version typedef cc::MichaelHashMap< rcu_type, list, map_traits > map; - test_rcu< map >(); + test_rcu_michael_list< map >(); // option-based version typedef cc::MichaelHashMap< rcu_type, list, @@ -82,7 +82,7 @@ namespace map { ,cc::opt::item_counter< simple_item_counter > >::type > opt_map; - test_rcu< opt_map >(); + test_rcu_michael_list< opt_map >(); } diff --git a/tests/test-hdr/map/hdr_michael_map_rcu_gpt.cpp b/tests/test-hdr/map/hdr_michael_map_rcu_gpt.cpp index 4fad97e0..1105d60c 100644 --- a/tests/test-hdr/map/hdr_michael_map_rcu_gpt.cpp +++ b/tests/test-hdr/map/hdr_michael_map_rcu_gpt.cpp @@ -37,7 +37,7 @@ namespace map { // traits-based version typedef cc::MichaelHashMap< rcu_type, list, map_traits > map; - test_rcu< map >(); + test_rcu_michael_list< map >(); // option-based version typedef cc::MichaelHashMap< rcu_type, list, @@ -46,7 +46,7 @@ namespace map { ,cc::opt::item_counter< simple_item_counter > >::type > opt_map; - test_rcu< opt_map >(); + test_rcu_michael_list< opt_map >(); } void HashMapHdrTest::Michael_RCU_GPT_less() @@ -55,7 +55,7 @@ namespace map { // traits-based version typedef cc::MichaelHashMap< rcu_type, list, map_traits > map; - test_rcu< map >(); + test_rcu_michael_list< map >(); // option-based version typedef cc::MichaelHashMap< rcu_type, list, @@ -64,7 +64,7 @@ namespace map { ,cc::opt::item_counter< simple_item_counter > >::type > opt_map; - test_rcu< opt_map >(); + test_rcu_michael_list< opt_map >(); } void HashMapHdrTest::Michael_RCU_GPT_cmpmix() @@ -73,7 +73,7 @@ namespace map { // traits-based version typedef cc::MichaelHashMap< rcu_type, list, map_traits > map; - test_rcu< map >(); + test_rcu_michael_list< map >(); // option-based version typedef cc::MichaelHashMap< rcu_type, list, @@ -82,7 +82,7 @@ namespace map { ,cc::opt::item_counter< simple_item_counter > >::type > opt_map; - test_rcu< opt_map >(); + test_rcu_michael_list< opt_map >(); } diff --git a/tests/test-hdr/map/hdr_michael_map_rcu_shb.cpp b/tests/test-hdr/map/hdr_michael_map_rcu_shb.cpp index dc23222d..07a7a979 100644 --- a/tests/test-hdr/map/hdr_michael_map_rcu_shb.cpp +++ b/tests/test-hdr/map/hdr_michael_map_rcu_shb.cpp @@ -40,7 +40,7 @@ namespace map { // traits-based version typedef cc::MichaelHashMap< rcu_type, list, map_traits > map; - test_rcu< map >(); + test_rcu_michael_list< map >(); // option-based version typedef cc::MichaelHashMap< rcu_type, list, @@ -49,7 +49,7 @@ namespace map { ,cc::opt::item_counter< simple_item_counter > >::type > opt_map; - test_rcu< opt_map >(); + test_rcu_michael_list< opt_map >(); #endif } @@ -60,7 +60,7 @@ namespace map { // traits-based version typedef cc::MichaelHashMap< rcu_type, list, map_traits > map; - test_rcu< map >(); + test_rcu_michael_list< map >(); // option-based version typedef cc::MichaelHashMap< rcu_type, list, @@ -69,7 +69,7 @@ namespace map { ,cc::opt::item_counter< simple_item_counter > >::type > opt_map; - test_rcu< opt_map >(); + test_rcu_michael_list< opt_map >(); #endif } @@ -80,7 +80,7 @@ namespace map { // traits-based version typedef cc::MichaelHashMap< rcu_type, list, map_traits > map; - test_rcu< map >(); + test_rcu_michael_list< map >(); // option-based version typedef cc::MichaelHashMap< rcu_type, list, @@ -89,7 +89,7 @@ namespace map { ,cc::opt::item_counter< simple_item_counter > >::type > opt_map; - test_rcu< opt_map >(); + test_rcu_michael_list< opt_map >(); #endif } diff --git a/tests/test-hdr/map/hdr_michael_map_rcu_sht.cpp b/tests/test-hdr/map/hdr_michael_map_rcu_sht.cpp index f57742a0..cbecfe8b 100644 --- a/tests/test-hdr/map/hdr_michael_map_rcu_sht.cpp +++ b/tests/test-hdr/map/hdr_michael_map_rcu_sht.cpp @@ -40,7 +40,7 @@ namespace map { // traits-based version typedef cc::MichaelHashMap< rcu_type, list, map_traits > map; - test_rcu< map >(); + test_rcu_michael_list< map >(); // option-based version typedef cc::MichaelHashMap< rcu_type, list, @@ -49,7 +49,7 @@ namespace map { ,cc::opt::item_counter< simple_item_counter > >::type > opt_map; - test_rcu< opt_map >(); + test_rcu_michael_list< opt_map >(); #endif } @@ -60,7 +60,7 @@ namespace map { // traits-based version typedef cc::MichaelHashMap< rcu_type, list, map_traits > map; - test_rcu< map >(); + test_rcu_michael_list< map >(); // option-based version typedef cc::MichaelHashMap< rcu_type, list, @@ -69,7 +69,7 @@ namespace map { ,cc::opt::item_counter< simple_item_counter > >::type > opt_map; - test_rcu< opt_map >(); + test_rcu_michael_list< opt_map >(); #endif } @@ -80,7 +80,7 @@ namespace map { // traits-based version typedef cc::MichaelHashMap< rcu_type, list, map_traits > map; - test_rcu< map >(); + test_rcu_michael_list< map >(); // option-based version typedef cc::MichaelHashMap< rcu_type, list, @@ -89,7 +89,7 @@ namespace map { ,cc::opt::item_counter< simple_item_counter > >::type > opt_map; - test_rcu< opt_map >(); + test_rcu_michael_list< opt_map >(); #endif } diff --git a/tests/test-hdr/set/hdr_intrusive_michael_set_rcu_gpb.cpp b/tests/test-hdr/set/hdr_intrusive_michael_set_rcu_gpb.cpp index e1b77afa..36417c71 100644 --- a/tests/test-hdr/set/hdr_intrusive_michael_set_rcu_gpb.cpp +++ b/tests/test-hdr/set/hdr_intrusive_michael_set_rcu_gpb.cpp @@ -29,7 +29,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); } void IntrusiveHashSetHdrTest::RCU_GPB_base_less() @@ -50,7 +50,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); } void IntrusiveHashSetHdrTest::RCU_GPB_base_cmpmix() @@ -73,7 +73,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); } void IntrusiveHashSetHdrTest::RCU_GPB_member_cmp() @@ -97,7 +97,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); } void IntrusiveHashSetHdrTest::RCU_GPB_member_less() @@ -121,7 +121,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); } void IntrusiveHashSetHdrTest::RCU_GPB_member_cmpmix() @@ -147,7 +147,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); } diff --git a/tests/test-hdr/set/hdr_intrusive_michael_set_rcu_gpi.cpp b/tests/test-hdr/set/hdr_intrusive_michael_set_rcu_gpi.cpp index a126d611..1c98278a 100644 --- a/tests/test-hdr/set/hdr_intrusive_michael_set_rcu_gpi.cpp +++ b/tests/test-hdr/set/hdr_intrusive_michael_set_rcu_gpi.cpp @@ -29,7 +29,7 @@ namespace set { }; typedef ci::MichaelHashSet< RCU, bucket_type, set_traits > set; - test_rcu_int(); + test_rcu_int_michael_list(); } void IntrusiveHashSetHdrTest::RCU_GPI_base_less() @@ -50,7 +50,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); } void IntrusiveHashSetHdrTest::RCU_GPI_base_cmpmix() @@ -73,7 +73,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); } void IntrusiveHashSetHdrTest::RCU_GPI_member_cmp() @@ -97,7 +97,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); } void IntrusiveHashSetHdrTest::RCU_GPI_member_less() @@ -121,7 +121,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); } void IntrusiveHashSetHdrTest::RCU_GPI_member_cmpmix() @@ -147,7 +147,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); } diff --git a/tests/test-hdr/set/hdr_intrusive_michael_set_rcu_gpt.cpp b/tests/test-hdr/set/hdr_intrusive_michael_set_rcu_gpt.cpp index 5cead1ef..baf84603 100644 --- a/tests/test-hdr/set/hdr_intrusive_michael_set_rcu_gpt.cpp +++ b/tests/test-hdr/set/hdr_intrusive_michael_set_rcu_gpt.cpp @@ -29,7 +29,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); } void IntrusiveHashSetHdrTest::RCU_GPT_base_less() @@ -50,7 +50,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); } void IntrusiveHashSetHdrTest::RCU_GPT_base_cmpmix() @@ -73,7 +73,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); } void IntrusiveHashSetHdrTest::RCU_GPT_member_cmp() @@ -97,7 +97,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); } void IntrusiveHashSetHdrTest::RCU_GPT_member_less() @@ -121,7 +121,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); } void IntrusiveHashSetHdrTest::RCU_GPT_member_cmpmix() @@ -147,7 +147,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); } diff --git a/tests/test-hdr/set/hdr_intrusive_michael_set_rcu_shb.cpp b/tests/test-hdr/set/hdr_intrusive_michael_set_rcu_shb.cpp index b97f68a3..6ee1ec27 100644 --- a/tests/test-hdr/set/hdr_intrusive_michael_set_rcu_shb.cpp +++ b/tests/test-hdr/set/hdr_intrusive_michael_set_rcu_shb.cpp @@ -32,7 +32,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); #endif } @@ -55,7 +55,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); #endif } @@ -80,7 +80,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); #endif } @@ -106,7 +106,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); #endif } @@ -132,7 +132,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); #endif } @@ -160,7 +160,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); #endif } diff --git a/tests/test-hdr/set/hdr_intrusive_michael_set_rcu_sht.cpp b/tests/test-hdr/set/hdr_intrusive_michael_set_rcu_sht.cpp index 0d41411d..2181eb82 100644 --- a/tests/test-hdr/set/hdr_intrusive_michael_set_rcu_sht.cpp +++ b/tests/test-hdr/set/hdr_intrusive_michael_set_rcu_sht.cpp @@ -32,7 +32,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); #endif } @@ -55,7 +55,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); #endif } @@ -80,7 +80,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); #endif } @@ -106,7 +106,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); #endif } @@ -132,7 +132,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); #endif } @@ -160,7 +160,7 @@ namespace set { >::type > set; - test_rcu_int(); + test_rcu_int_michael_list(); #endif } diff --git a/tests/test-hdr/set/hdr_intrusive_set.h b/tests/test-hdr/set/hdr_intrusive_set.h index 7da9e154..199551c9 100644 --- a/tests/test-hdr/set/hdr_intrusive_set.h +++ b/tests/test-hdr/set/hdr_intrusive_set.h @@ -1033,7 +1033,7 @@ namespace set { CPPUNIT_ASSERT( s.insert( arrItems[i] )); for ( size_t i = 0; i < nLimit; i += 2 ) { - value_type * pVal; + value_type * 1; int nKey = arr[i]; { rcu_lock l; @@ -1090,6 +1090,105 @@ namespace set { } } + template + void test_rcu_int_michael_list() + { + { + Set s( 64, 4 ); + test_rcu_int_with( s ); + } + + // Iterator test + test_iter(); + + // Extract tests + typedef typename Set::gc rcu; + typedef typename Set::value_type value_type; + typedef typename Set::rcu_lock rcu_lock; + + typename Set::exempt_ptr ep; + typename Set::get_result gp; + + { + static size_t const nLimit = 1024; + value_type arrItems[nLimit]; + int arr[nLimit]; + for ( size_t i = 0; i < nLimit; ++i ) + arr[i] = (int) i; + shuffle( arr, arr + nLimit ); + + for ( size_t i = 0; i < nLimit; ++i ) { + arrItems[i].nKey = arr[i]; + arrItems[i].nVal = arr[i] * 2; + } + + Set s( nLimit, 2 ); + for ( size_t i = 0; i < nLimit; ++i ) + CPPUNIT_ASSERT( s.insert( arrItems[i] )); + + for ( size_t i = 0; i < nLimit; i += 2 ) { + int nKey = arr[i]; + { + rcu_lock l; + gp = s.get( nKey ); + CPPUNIT_ASSERT( gp ); + CPPUNIT_CHECK( gp->nKey == nKey ); + CPPUNIT_CHECK( (*gp).nVal == nKey * 2 ); + } + gp.release(); + + ep = s.extract( nKey ); + CPPUNIT_ASSERT( ep ); + CPPUNIT_ASSERT( !ep.empty() ); + CPPUNIT_CHECK( nKey == ep->nKey ); + CPPUNIT_CHECK( nKey * 2 == (*ep).nVal ); + ep.release(); + { + rcu_lock l; + CPPUNIT_CHECK( !s.get( nKey )); + } + CPPUNIT_CHECK( !s.extract( nKey )); + CPPUNIT_CHECK( ep.empty() ); + + nKey = arr[i+1]; + { + rcu_lock l; + gp = s.get_with( nKey, less() ); + CPPUNIT_ASSERT( gp ); + CPPUNIT_CHECK( gp->nKey == nKey ); + CPPUNIT_CHECK( gp->nVal == nKey * 2 ); + } + gp.release(); + + ep = s.extract_with( nKey, less() ); + CPPUNIT_ASSERT( ep ); + CPPUNIT_ASSERT( !ep.empty() ); + CPPUNIT_CHECK( nKey == ep->nKey ); + CPPUNIT_CHECK( nKey * 2 == (*ep).nVal ); + ep.release(); + + { + rcu_lock l; + CPPUNIT_CHECK( !s.get_with( nKey, less())); + } + ep = s.extract_with( nKey, less() ); + CPPUNIT_CHECK( !ep ); + CPPUNIT_CHECK( ep.empty() ); + } + CPPUNIT_CHECK( s.empty() ); + CPPUNIT_CHECK( check_size( s, 0 )); + { + rcu_lock l; + CPPUNIT_CHECK( !s.get( 100 )); + } + ep = s.extract( 100 ); + CPPUNIT_CHECK( !ep ); + CPPUNIT_CHECK( ep.empty() ); + + Set::gc::force_dispose(); + } + } + // MichaelHashSet + MichaelList void HP_base_cmp(); void HP_base_less(); diff --git a/tests/test-hdr/set/hdr_michael_set_rcu_gpb.cpp b/tests/test-hdr/set/hdr_michael_set_rcu_gpb.cpp index 21c28094..9090d2fc 100644 --- a/tests/test-hdr/set/hdr_michael_set_rcu_gpb.cpp +++ b/tests/test-hdr/set/hdr_michael_set_rcu_gpb.cpp @@ -39,7 +39,7 @@ namespace set { // traits-based version typedef cc::MichaelHashSet< rcu_type, list, set_traits > set; - test_int_rcu< set >(); + test_int_rcu_michael_list< set >(); // option-based version typedef cc::MichaelHashSet< rcu_type, list, @@ -48,7 +48,7 @@ namespace set { ,cc::opt::item_counter< simple_item_counter > >::type > opt_set; - test_int_rcu< opt_set >(); + test_int_rcu_michael_list< opt_set >(); } void HashSetHdrTest::Michael_RCU_GPB_less() @@ -57,7 +57,7 @@ namespace set { // traits-based version typedef cc::MichaelHashSet< rcu_type, list, set_traits > set; - test_int_rcu< set >(); + test_int_rcu_michael_list< set >(); // option-based version typedef cc::MichaelHashSet< rcu_type, list, @@ -66,7 +66,7 @@ namespace set { ,cc::opt::item_counter< simple_item_counter > >::type > opt_set; - test_int_rcu< opt_set >(); + test_int_rcu_michael_list< opt_set >(); } void HashSetHdrTest::Michael_RCU_GPB_cmpmix() @@ -75,7 +75,7 @@ namespace set { // traits-based version typedef cc::MichaelHashSet< rcu_type, list, set_traits > set; - test_int_rcu< set >(); + test_int_rcu_michael_list< set >(); // option-based version typedef cc::MichaelHashSet< rcu_type, list, @@ -84,7 +84,7 @@ namespace set { ,cc::opt::item_counter< simple_item_counter > >::type > opt_set; - test_int_rcu< opt_set >(); + test_int_rcu_michael_list< opt_set >(); } diff --git a/tests/test-hdr/set/hdr_michael_set_rcu_gpi.cpp b/tests/test-hdr/set/hdr_michael_set_rcu_gpi.cpp index aed109b5..b18a1806 100644 --- a/tests/test-hdr/set/hdr_michael_set_rcu_gpi.cpp +++ b/tests/test-hdr/set/hdr_michael_set_rcu_gpi.cpp @@ -39,7 +39,7 @@ namespace set { // traits-based version typedef cc::MichaelHashSet< rcu_type, list, set_traits > set; - test_int_rcu< set >(); + test_int_rcu_michael_list< set >(); // option-based version typedef cc::MichaelHashSet< rcu_type, list, @@ -48,7 +48,7 @@ namespace set { ,cc::opt::item_counter< simple_item_counter > >::type > opt_set; - test_int_rcu< opt_set >(); + test_int_rcu_michael_list< opt_set >(); } void HashSetHdrTest::Michael_RCU_GPI_less() @@ -57,7 +57,7 @@ namespace set { // traits-based version typedef cc::MichaelHashSet< rcu_type, list, set_traits > set; - test_int_rcu< set >(); + test_int_rcu_michael_list< set >(); // option-based version typedef cc::MichaelHashSet< rcu_type, list, @@ -66,7 +66,7 @@ namespace set { ,cc::opt::item_counter< simple_item_counter > >::type > opt_set; - test_int_rcu< opt_set >(); + test_int_rcu_michael_list< opt_set >(); } void HashSetHdrTest::Michael_RCU_GPI_cmpmix() @@ -75,7 +75,7 @@ namespace set { // traits-based version typedef cc::MichaelHashSet< rcu_type, list, set_traits > set; - test_int_rcu< set >(); + test_int_rcu_michael_list< set >(); // option-based version typedef cc::MichaelHashSet< rcu_type, list, @@ -84,7 +84,7 @@ namespace set { ,cc::opt::item_counter< simple_item_counter > >::type > opt_set; - test_int_rcu< opt_set >(); + test_int_rcu_michael_list< opt_set >(); } diff --git a/tests/test-hdr/set/hdr_michael_set_rcu_gpt.cpp b/tests/test-hdr/set/hdr_michael_set_rcu_gpt.cpp index c75eed96..38269b8e 100644 --- a/tests/test-hdr/set/hdr_michael_set_rcu_gpt.cpp +++ b/tests/test-hdr/set/hdr_michael_set_rcu_gpt.cpp @@ -39,7 +39,7 @@ namespace set { // traits-based version typedef cc::MichaelHashSet< rcu_type, list, set_traits > set; - test_int_rcu< set >(); + test_int_rcu_michael_list< set >(); // option-based version typedef cc::MichaelHashSet< rcu_type, list, @@ -48,7 +48,7 @@ namespace set { ,cc::opt::item_counter< simple_item_counter > >::type > opt_set; - test_int_rcu< opt_set >(); + test_int_rcu_michael_list< opt_set >(); } void HashSetHdrTest::Michael_RCU_GPT_less() @@ -57,7 +57,7 @@ namespace set { // traits-based version typedef cc::MichaelHashSet< rcu_type, list, set_traits > set; - test_int_rcu< set >(); + test_int_rcu_michael_list< set >(); // option-based version typedef cc::MichaelHashSet< rcu_type, list, @@ -66,7 +66,7 @@ namespace set { ,cc::opt::item_counter< simple_item_counter > >::type > opt_set; - test_int_rcu< opt_set >(); + test_int_rcu_michael_list< opt_set >(); } void HashSetHdrTest::Michael_RCU_GPT_cmpmix() @@ -75,7 +75,7 @@ namespace set { // traits-based version typedef cc::MichaelHashSet< rcu_type, list, set_traits > set; - test_int_rcu< set >(); + test_int_rcu_michael_list< set >(); // option-based version typedef cc::MichaelHashSet< rcu_type, list, @@ -84,7 +84,7 @@ namespace set { ,cc::opt::item_counter< simple_item_counter > >::type > opt_set; - test_int_rcu< opt_set >(); + test_int_rcu_michael_list< opt_set >(); } diff --git a/tests/test-hdr/set/hdr_michael_set_rcu_shb.cpp b/tests/test-hdr/set/hdr_michael_set_rcu_shb.cpp index fe37af65..b592cac3 100644 --- a/tests/test-hdr/set/hdr_michael_set_rcu_shb.cpp +++ b/tests/test-hdr/set/hdr_michael_set_rcu_shb.cpp @@ -42,7 +42,7 @@ namespace set { // traits-based version typedef cc::MichaelHashSet< rcu_type, list, set_traits > set; - test_int_rcu< set >(); + test_int_rcu_michael_list< set >(); // option-based version typedef cc::MichaelHashSet< rcu_type, list, @@ -51,7 +51,7 @@ namespace set { ,cc::opt::item_counter< simple_item_counter > >::type > opt_set; - test_int_rcu< opt_set >(); + test_int_rcu_michael_list< opt_set >(); #endif } @@ -62,7 +62,7 @@ namespace set { // traits-based version typedef cc::MichaelHashSet< rcu_type, list, set_traits > set; - test_int_rcu< set >(); + test_int_rcu_michael_list< set >(); // option-based version typedef cc::MichaelHashSet< rcu_type, list, @@ -71,7 +71,7 @@ namespace set { ,cc::opt::item_counter< simple_item_counter > >::type > opt_set; - test_int_rcu< opt_set >(); + test_int_rcu_michael_list< opt_set >(); #endif } @@ -82,7 +82,7 @@ namespace set { // traits-based version typedef cc::MichaelHashSet< rcu_type, list, set_traits > set; - test_int_rcu< set >(); + test_int_rcu_michael_list< set >(); // option-based version typedef cc::MichaelHashSet< rcu_type, list, @@ -91,7 +91,7 @@ namespace set { ,cc::opt::item_counter< simple_item_counter > >::type > opt_set; - test_int_rcu< opt_set >(); + test_int_rcu_michael_list< opt_set >(); #endif } diff --git a/tests/test-hdr/set/hdr_michael_set_rcu_sht.cpp b/tests/test-hdr/set/hdr_michael_set_rcu_sht.cpp index 0122333f..42a1dee1 100644 --- a/tests/test-hdr/set/hdr_michael_set_rcu_sht.cpp +++ b/tests/test-hdr/set/hdr_michael_set_rcu_sht.cpp @@ -42,7 +42,7 @@ namespace set { // traits-based version typedef cc::MichaelHashSet< rcu_type, list, set_traits > set; - test_int_rcu< set >(); + test_int_rcu_michael_list< set >(); // option-based version typedef cc::MichaelHashSet< rcu_type, list, @@ -51,7 +51,7 @@ namespace set { ,cc::opt::item_counter< simple_item_counter > >::type > opt_set; - test_int_rcu< opt_set >(); + test_int_rcu_michael_list< opt_set >(); #endif } @@ -62,7 +62,7 @@ namespace set { // traits-based version typedef cc::MichaelHashSet< rcu_type, list, set_traits > set; - test_int_rcu< set >(); + test_int_rcu_michael_list< set >(); // option-based version typedef cc::MichaelHashSet< rcu_type, list, @@ -71,7 +71,7 @@ namespace set { ,cc::opt::item_counter< simple_item_counter > >::type > opt_set; - test_int_rcu< opt_set >(); + test_int_rcu_michael_list< opt_set >(); #endif } @@ -82,7 +82,7 @@ namespace set { // traits-based version typedef cc::MichaelHashSet< rcu_type, list, set_traits > set; - test_int_rcu< set >(); + test_int_rcu_michael_list< set >(); // option-based version typedef cc::MichaelHashSet< rcu_type, list, @@ -91,7 +91,7 @@ namespace set { ,cc::opt::item_counter< simple_item_counter > >::type > opt_set; - test_int_rcu< opt_set >(); + test_int_rcu_michael_list< opt_set >(); #endif } diff --git a/tests/test-hdr/set/hdr_set.h b/tests/test-hdr/set/hdr_set.h index aeaa2ac3..47d07ec4 100644 --- a/tests/test-hdr/set/hdr_set.h +++ b/tests/test-hdr/set/hdr_set.h @@ -494,6 +494,97 @@ namespace set { test_iter(); } + template + void test_int_rcu_michael_list() + { + Set s( 100, 4 ); + test_int_with( s ); + + // extract/get test + { + typedef typename Set::gc rcu; + typedef typename Set::rcu_lock rcu_lock; + typedef typename Set::value_type value_type; + typename Set::exempt_ptr ep; + typename Set::get_result gp; + + static size_t const nLimit = 100; + int arr[nLimit]; + for ( size_t i = 0; i < nLimit; ++i ) + arr[i] = (int) i; + shuffle( arr, arr + nLimit ); + + for ( size_t i = 0; i < nLimit; ++i ) + CPPUNIT_ASSERT( s.insert( arr[i] )); + + for ( size_t i = 0; i < nLimit; i += 2 ) { + int nKey = arr[i]; + { + rcu_lock l; + gp = s.get( nKey ); + CPPUNIT_ASSERT( gp ); + CPPUNIT_CHECK( gp->nKey == nKey ); + CPPUNIT_CHECK( gp->nVal == nKey ); + } + gp.release(); + + ep = s.extract( nKey ); + CPPUNIT_ASSERT( ep ); + CPPUNIT_ASSERT( !ep.empty() ); + CPPUNIT_CHECK( nKey == ep->nKey ); + CPPUNIT_CHECK( nKey == (*ep).nVal ); + ep.release(); + + { + rcu_lock l; + CPPUNIT_CHECK( !s.get( nKey )); + } + ep = s.extract( nKey ); + CPPUNIT_CHECK( !ep ); + CPPUNIT_CHECK( ep.empty() ); + + { + rcu_lock l; + nKey = arr[i+1]; + gp = s.get_with( other_item(nKey), other_less() ); + CPPUNIT_ASSERT( gp ); + CPPUNIT_CHECK( gp->nKey == nKey ); + CPPUNIT_CHECK( gp->nVal == nKey ); + } + gp.release(); + + ep = s.extract_with( other_item( nKey ), other_less() ); + CPPUNIT_ASSERT( ep ); + CPPUNIT_ASSERT( !ep.empty() ); + CPPUNIT_CHECK( nKey == ep->nKey ); + CPPUNIT_CHECK( nKey == (*ep).nVal ); + ep.release(); + + { + rcu_lock l; + CPPUNIT_CHECK( !s.get_with( other_item( nKey ), other_less())); + } + CPPUNIT_CHECK( !s.extract_with( other_item(nKey), other_less() )); + CPPUNIT_CHECK( ep.empty() ); + } + CPPUNIT_CHECK( s.empty() ); + CPPUNIT_CHECK( check_size( s, 0 )); + + { + rcu_lock l; + CPPUNIT_CHECK( !s.get( int( nLimit / 2 ))); + } + + ep = s.extract( int( nLimit / 2 ) ); + CPPUNIT_CHECK( !ep ); + CPPUNIT_CHECK( ep.empty() ); + } + + // iterator test + test_iter(); + } + + template void test_int_with( Set& s) { -- 2.34.1