Changed MichaelSet/Map<RCU> for new MichaelList extract()/get() semantics
authorkhizmax <libcds.dev@gmail.com>
Sat, 23 May 2015 16:45:14 +0000 (19:45 +0300)
committerkhizmax <libcds.dev@gmail.com>
Sat, 23 May 2015 16:45:14 +0000 (19:45 +0300)
27 files changed:
cds/container/lazy_kvlist_rcu.h
cds/container/lazy_list_rcu.h
cds/container/michael_kvlist_rcu.h
cds/container/michael_list_rcu.h
cds/container/michael_map_rcu.h
cds/container/michael_set_rcu.h
cds/intrusive/lazy_list_rcu.h
cds/intrusive/michael_list_rcu.h
cds/intrusive/michael_set_rcu.h
tests/test-hdr/map/hdr_map.h
tests/test-hdr/map/hdr_michael_map_rcu_gpb.cpp
tests/test-hdr/map/hdr_michael_map_rcu_gpi.cpp
tests/test-hdr/map/hdr_michael_map_rcu_gpt.cpp
tests/test-hdr/map/hdr_michael_map_rcu_shb.cpp
tests/test-hdr/map/hdr_michael_map_rcu_sht.cpp
tests/test-hdr/set/hdr_intrusive_michael_set_rcu_gpb.cpp
tests/test-hdr/set/hdr_intrusive_michael_set_rcu_gpi.cpp
tests/test-hdr/set/hdr_intrusive_michael_set_rcu_gpt.cpp
tests/test-hdr/set/hdr_intrusive_michael_set_rcu_shb.cpp
tests/test-hdr/set/hdr_intrusive_michael_set_rcu_sht.cpp
tests/test-hdr/set/hdr_intrusive_set.h
tests/test-hdr/set/hdr_michael_set_rcu_gpb.cpp
tests/test-hdr/set/hdr_michael_set_rcu_gpi.cpp
tests/test-hdr/set/hdr_michael_set_rcu_gpt.cpp
tests/test-hdr/set/hdr_michael_set_rcu_shb.cpp
tests/test-hdr/set/hdr_michael_set_rcu_sht.cpp
tests/test-hdr/set/hdr_set.h

index de24d1312dc0124e0009786aff83085b80238fd9..625a2218636c87d84e47b2590b2b45cc68323d03 100644 (file)
@@ -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<node_type, value_type>
         >;
+        /// Type of \p get() member function return value
+        typedef value_type * get_result;
 
     protected:
         //@cond
index 8aec5b12ba7d0be6a9563a142b5a60684105ff67..0441885af33b898b9c9a597f30d99cf68787a360 100644 (file)
@@ -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
index 8b1e25ebf0eb6387a33549d623be6930e81fc75b..5dc7a07cd9eea419ea456df74b84da53684b00d2 100644 (file)
@@ -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
index b2a3fb700bb0e620fecadd05aa75263b30ddfc80..768646583a407e853d12d091a02371017be987a8 100644 (file)
@@ -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
index 34e53c32d1866163fe383bd2306a8a719aa953bc..4225aa39c583a8fffc8fb2c6d230d7e53798978d 100644 (file)
@@ -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 <cds/urcu/general_buffered.h>
@@ -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 <typename K, typename Func>
-        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 <typename K, typename Less, typename Func>
-        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 <typename K>
-        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 <typename K, typename Less>
-        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 <typename K>
-        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 <typename K, typename Less>
-        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 );
         }
index 3bf12d8c41827bdc34115b1530b8ab89ffb80aed..027619993a86b52430f763771cab241941e1ba06 100644 (file)
@@ -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 <cds/urcu/general_buffered.h>
@@ -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 <typename Q, typename Func>
-        bool find( Q& key, Func f ) const
+        bool find( Q& key, Func f )
         {
             return bucket( key ).find( key, f );
         }
         //@cond
         template <typename Q, typename Func>
-        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 <typename Q, typename Less, typename Func>
-        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 <typename Q, typename Less, typename Func>
-        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 <typename Q>
-        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 <typename Q, typename Less>
-        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 <typename Q>
-        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 <typename Q, typename Less>
-        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 );
         }
index 7fdb2ba1d44e2105753ea23c58595f14da11398c..bb9655d0d2ab65c1127e7cd963e4e33052434b04 100644 (file)
@@ -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
index 577485b2aebb12ed285cf3ea79f64e32695c9e1f..000a1b8dfef402d5d3adacd5e41a72dfa2fba5d7 100644 (file)
@@ -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
index 757850212f820578aefc62f8adf029f713597020..5aff39dd4713b5d29f3270a549f698f448d0e090 100644 (file)
@@ -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 <cds/urcu/general_buffered.h>
@@ -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 <typename Q>
-        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 <typename Q, typename Less>
-        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 <typename Q, typename Func>
-        bool find( Q& key, Func f ) const
+        bool find( Q& key, Func f )
         {
             return bucket( key ).find( key, f );
         }
         //@cond
         template <typename Q, typename Func>
-        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 <typename Q, typename Less, typename Func>
-        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 <typename Q, typename Less, typename Func>
-        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 <typename Q>
-        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 <typename Q, typename Less>
-        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 );
         }
index 8db81e989e4e93d6466de5b60496351536b88abc..d8986ee29423ef73fb0b74556ad3b251b5e2c210 100644 (file)
@@ -344,6 +344,95 @@ namespace map {
             test_iter<Map>();
         }
 
+        template <class Map>
+        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<Map>();
+        }
+
         template <class Map>
         void test_int_with( Map& m )
         {
index ce970d398f8919c803a432f3de6936fe67d16054..c4515d8892190c092a75107fc3686d63a2d93290 100644 (file)
@@ -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 >();
     }
 
 
index 907f1bf93ac715ec8d5b6e6d4287836aec8e5023..7d60631562032c1f11fe025a49ff918ca8c04803 100644 (file)
@@ -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 >();
     }
 
 
index 4fad97e0fecbbad8165bc682cd07318cdc10de7b..1105d60c113d121be3187ffcf69ade02da0af870 100644 (file)
@@ -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 >();
     }
 
 
index dc23222da4dba1ec8bca2b4e7b3e1c75bbb4fb39..07a7a979b0a9ddf2394ce2f2419b66499094c325 100644 (file)
@@ -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
     }
 
index f57742a0d1d1da4531bebd35503b3ad55a2885bc..cbecfe8b39debc05c1a5b012c01a135f7deb99e9 100644 (file)
@@ -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
     }
 
index e1b77afa884d9b73a7d8abd1e44f68da37fb575f..36417c7145a9d1c2a028852fa197a0d4389da051 100644 (file)
@@ -29,7 +29,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
     }
 
     void IntrusiveHashSetHdrTest::RCU_GPB_base_less()
@@ -50,7 +50,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
     }
 
     void IntrusiveHashSetHdrTest::RCU_GPB_base_cmpmix()
@@ -73,7 +73,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
     }
 
     void IntrusiveHashSetHdrTest::RCU_GPB_member_cmp()
@@ -97,7 +97,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
     }
 
     void IntrusiveHashSetHdrTest::RCU_GPB_member_less()
@@ -121,7 +121,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
     }
 
     void IntrusiveHashSetHdrTest::RCU_GPB_member_cmpmix()
@@ -147,7 +147,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
     }
 
 
index a126d61155d8de51705521d03db623b0d35aed40..1c98278ab625518d2902b71f1c553c9489afea1d 100644 (file)
@@ -29,7 +29,7 @@ namespace set {
         };
         typedef ci::MichaelHashSet< RCU, bucket_type, set_traits > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
     }
 
     void IntrusiveHashSetHdrTest::RCU_GPI_base_less()
@@ -50,7 +50,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
     }
 
     void IntrusiveHashSetHdrTest::RCU_GPI_base_cmpmix()
@@ -73,7 +73,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
     }
 
     void IntrusiveHashSetHdrTest::RCU_GPI_member_cmp()
@@ -97,7 +97,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
     }
 
     void IntrusiveHashSetHdrTest::RCU_GPI_member_less()
@@ -121,7 +121,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
     }
 
     void IntrusiveHashSetHdrTest::RCU_GPI_member_cmpmix()
@@ -147,7 +147,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
     }
 
 
index 5cead1efdc3d85a2da1ae249db1434a9463227d0..baf846037df1f05b2e1f69363c017f5526435b6e 100644 (file)
@@ -29,7 +29,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
     }
 
     void IntrusiveHashSetHdrTest::RCU_GPT_base_less()
@@ -50,7 +50,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
     }
 
     void IntrusiveHashSetHdrTest::RCU_GPT_base_cmpmix()
@@ -73,7 +73,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
     }
 
     void IntrusiveHashSetHdrTest::RCU_GPT_member_cmp()
@@ -97,7 +97,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
     }
 
     void IntrusiveHashSetHdrTest::RCU_GPT_member_less()
@@ -121,7 +121,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
     }
 
     void IntrusiveHashSetHdrTest::RCU_GPT_member_cmpmix()
@@ -147,7 +147,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
     }
 
 
index b97f68a34cbd5f1a7630fb22416e1d3cb732827c..6ee1ec2749afbb5d765b589d9c47de1f86bd4a54 100644 (file)
@@ -32,7 +32,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
 #endif
     }
 
@@ -55,7 +55,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
 #endif
     }
 
@@ -80,7 +80,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
 #endif
     }
 
@@ -106,7 +106,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
 #endif
     }
 
@@ -132,7 +132,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
 #endif
     }
 
@@ -160,7 +160,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
 #endif
     }
 
index 0d41411d290b80678e39223e192fc8505ae59e2d..2181eb82534c0d29b94bb8e2f90eb84825c504e8 100644 (file)
@@ -32,7 +32,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
 #endif
     }
 
@@ -55,7 +55,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
 #endif
     }
 
@@ -80,7 +80,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
 #endif
     }
 
@@ -106,7 +106,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
 #endif
     }
 
@@ -132,7 +132,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
 #endif
     }
 
@@ -160,7 +160,7 @@ namespace set {
             >::type
         > set;
 
-        test_rcu_int<set>();
+        test_rcu_int_michael_list<set>();
 #endif
     }
 
index 7da9e1541e1605ac4a005731862329ff76d65ff5..199551c97f5932998a48229a1036effecbc9c97a 100644 (file)
@@ -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 <class Set>
+        void test_rcu_int_michael_list()
+        {
+            {
+                Set s( 64, 4 );
+                test_rcu_int_with( s );
+            }
+
+            // Iterator test
+            test_iter<Set>();
+
+            // 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<value_type>() );
+                        CPPUNIT_ASSERT( gp );
+                        CPPUNIT_CHECK( gp->nKey == nKey );
+                        CPPUNIT_CHECK( gp->nVal == nKey * 2 );
+                    }
+                    gp.release();
+
+                    ep = s.extract_with( nKey, less<value_type>() );
+                    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<value_type>()));
+                    }
+                    ep = s.extract_with( nKey, less<value_type>() );
+                    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();
index 21c2809483641daf46d40c855a9a9f113a4256f9..9090d2fc4cb744272b85928214bfcc9c520c53a8 100644 (file)
@@ -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 >();
     }
 
 
index aed109b501e45b95f4255373e7ea0dc24bd35c02..b18a1806e2aed5ee3d988511e374d5f1c239efa8 100644 (file)
@@ -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 >();
     }
 
 
index c75eed96bd3a6aee64fdf8a7f9cbfcb39ab95fea..38269b8e4a2f0b9ecbcf1b0ae26ebbb0249e3305 100644 (file)
@@ -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 >();
     }
 
 
index fe37af6540001cb657572ff815e7ebfdddf6fba9..b592cac33dcf46e9f155b6cfaeab56647c1241bd 100644 (file)
@@ -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
     }
 
index 0122333fd496c1b0726b40ab2ab7555b685b5020..42a1dee163fb06b107e49a22b8a25efbbf932235 100644 (file)
@@ -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
     }
 
index aeaa2ac3e958c419c37d2de7ffdc6f7efbe6de1d..47d07ec48f6a1aaaca91c04fe94a79daf3e7c990 100644 (file)
@@ -494,6 +494,97 @@ namespace set {
             test_iter<Set>();
         }
 
+        template <class Set>
+        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<Set>();
+        }
+
+
         template <class Set>
         void test_int_with( Set& s)
         {