movable exempt_ptr: SkipList
authorkhizmax <khizmax@gmail.com>
Thu, 13 Nov 2014 12:13:48 +0000 (15:13 +0300)
committerkhizmax <khizmax@gmail.com>
Thu, 13 Nov 2014 12:13:48 +0000 (15:13 +0300)
cds/container/skip_list_map_rcu.h
cds/container/skip_list_set_rcu.h
cds/intrusive/skip_list_rcu.h
tests/test-hdr/map/hdr_skiplist_map_rcu.h
tests/test-hdr/set/hdr_intrusive_skiplist_set_rcu.h
tests/test-hdr/set/hdr_skiplist_set_rcu.h
tests/unit/map2/map_delodd.cpp
tests/unit/set2/set_delodd.cpp
tests/unit/set2/set_insdel_string.cpp

index 25087d94428adffa26e2f942c9b087f0d596b5d4..129e85f1450b21a8e63512d9a5c9744ee9faf83f 100644 (file)
@@ -138,7 +138,7 @@ namespace cds { namespace container {
         static CDS_CONSTEXPR const bool c_bExtractLockExternal = base_class::c_bExtractLockExternal;
 
         /// pointer to extracted node
         static CDS_CONSTEXPR const bool c_bExtractLockExternal = base_class::c_bExtractLockExternal;
 
         /// pointer to extracted node
-        typedef cds::urcu::exempt_ptr< gc, node_type, value_type, typename maker::intrusive_type_traits::disposer > exempt_ptr;
+        using exempt_ptr = cds::urcu::exempt_ptr< gc, node_type, value_type, typename maker::intrusive_type_traits::disposer >;
 
     protected:
         //@cond
 
     protected:
         //@cond
@@ -408,8 +408,8 @@ namespace cds { namespace container {
         /// Extracts the item from the map with specified \p key
         /** \anchor cds_nonintrusive_SkipListMap_rcu_extract
             The function searches an item with key equal to \p key in the map,
         /// Extracts the item from the map with specified \p key
         /** \anchor cds_nonintrusive_SkipListMap_rcu_extract
             The function searches an item with key equal to \p key in the map,
-            unlinks it from the set, and returns it in \p result parameter.
-            If the item with key equal to \p key is not found the function returns \p false.
+            unlinks it from the set, and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the item found.
+            If the item is not found the function returns an empty \p exempt_ptr
 
             Note the compare functor from \p Traits class' template argument
             should accept a parameter of type \p K that can be not the same as \p key_type.
 
             Note the compare functor from \p Traits class' template argument
             should accept a parameter of type \p K that can be not the same as \p key_type.
@@ -417,14 +417,13 @@ namespace cds { namespace container {
             RCU \p synchronize() method can be called. RCU should NOT be locked.
 
             The function does not free the item found.
             RCU \p synchronize() method can be called. RCU should NOT be locked.
 
             The function does not free the item found.
-            The item will be implicitly freed when \p result object is destroyed or when
-            <tt>result.release()</tt> is called, see cds::urcu::exempt_ptr for explanation.
-            @note Before reusing \p result object you should call its \p release() method.
+            The item will be implicitly freed when the returned object is destroyed or when
+            its \p release() member function is called.
         */
         template <typename K>
         */
         template <typename K>
-        bool extract( exempt_ptr& result, K const& key )
+        exempt_ptr extract( K const& key )
         {
         {
-            return base_class::do_extract( result, key );
+            return exempt_ptr( base_class::do_extract( key ));
         }
 
         /// Extracts the item from the map with comparing functor \p pred
         }
 
         /// Extracts the item from the map with comparing functor \p pred
@@ -435,43 +434,43 @@ 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>
             \p pred must imply the same element order as the comparator used for building the map.
         */
         template <typename K, typename Less>
-        bool extract_with( exempt_ptr& result, K const& key, Less pred )
+        exempt_ptr extract_with( K const& key, Less pred )
         {
         {
-            return base_class::do_extract_with( result, key, cds::details::predicate_wrapper< node_type, Less, typename maker::key_accessor >());
+            return exempt_ptr( base_class::do_extract_with( key, cds::details::predicate_wrapper< node_type, Less, typename maker::key_accessor >()));
         }
 
         /// Extracts an item with minimal key from the map
         /**
         }
 
         /// Extracts an item with minimal key from the map
         /**
-            The function searches an item with minimal key, unlinks it, and returns the item found in \p result parameter.
-            If the skip-list is empty the function returns \p false.
+            The function searches an item with minimal key, unlinks it, 
+            and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the item.
+            If the skip-list is empty the function returns an empty \p exempt_ptr.
 
             RCU \p synchronize method can be called. RCU should NOT be locked.
 
             The function does not free the item found.
 
             RCU \p synchronize method can be called. RCU should NOT be locked.
 
             The function does not free the item found.
-            The item will be implicitly freed when \p result object is destroyed or when
-            <tt>result.release()</tt> is called, see cds::urcu::exempt_ptr for explanation.
-            @note Before reusing \p result object you should call its \p release() method.
+            The item will be implicitly freed when the returned object is destroyed or when
+            its \p release() member function is called.
         */
         */
-        bool extract_min( exempt_ptr& result )
+        exempt_ptr extract_min()
         {
         {
-            return base_class::do_extract_min(result);
+            return exempt_ptr( base_class::do_extract_min());
         }
 
         /// Extracts an item with maximal key from the map
         /**
         }
 
         /// Extracts an item with maximal key from the map
         /**
-            The function searches an item with maximal key, unlinks it from the set, and returns the item found
-            in \p result parameter. If the skip-list is empty the function returns \p false.
+            The function searches an item with maximal key, unlinks it from the set, 
+            and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the item.
+            If the skip-list is empty the function returns an empty \p exempt_ptr.
 
             RCU \p synchronize method can be called. RCU should NOT be locked.
 
             The function does not free the item found.
 
             RCU \p synchronize method can be called. RCU should NOT be locked.
 
             The function does not free the item found.
-            The item will be implicitly freed when \p result object is destroyed or when
-            <tt>result.release()</tt> is called, see cds::urcu::exempt_ptr for explanation.
-            @note Before reusing \p result object you should call its \p release() method.
-        */
-        bool extract_max( exempt_ptr& result )
+            The item will be implicitly freed when the returned object is destroyed or when
+            its \p release() member function is called.
+            */
+        exempt_ptr extract_max()
         {
         {
-            return base_class::do_extract_max(result);
+            return exempt_ptr( base_class::do_extract_max());
         }
 
         /// Find the key \p key
         }
 
         /// Find the key \p key
index 82b7b838bb20dc1a0695f411cca83361f05d8c04..e0c15e2bd89d9b63473d0525096fa799683c574e 100644 (file)
@@ -185,7 +185,7 @@ namespace cds { namespace container {
         static CDS_CONSTEXPR const bool c_bExtractLockExternal = base_class::c_bExtractLockExternal;
 
         /// pointer to extracted node
         static CDS_CONSTEXPR const bool c_bExtractLockExternal = base_class::c_bExtractLockExternal;
 
         /// pointer to extracted node
-        typedef cds::urcu::exempt_ptr< gc, node_type, value_type, typename maker::intrusive_traits::disposer > exempt_ptr;
+        using exempt_ptr = cds::urcu::exempt_ptr< gc, node_type, value_type, typename maker::intrusive_traits::disposer >;
 
     protected:
         //@cond
 
     protected:
         //@cond
@@ -441,22 +441,22 @@ namespace cds { namespace container {
         /// Extracts the item from the set with specified \p key
         /** \anchor cds_nonintrusive_SkipListSet_rcu_extract
             The function searches an item with key equal to \p key in the set,
         /// Extracts the item from the set with specified \p key
         /** \anchor cds_nonintrusive_SkipListSet_rcu_extract
             The function searches an item with key equal to \p key in the set,
-            unlinks it from the set, and returns it in \p result parameter.
-            If the item with key equal to \p key is not found the function returns \p false.
+            unlinks it from the set, and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the item found.
+            If the item is not found the function returns an empty \p exempt_ptr
 
             Note the compare functor from \p Traits class' template argument
             should accept a parameter of type \p Q that can be not the same as \p value_type.
 
             RCU \p synchronize method can be called. RCU should NOT be locked.
 
             Note the compare functor from \p Traits class' template argument
             should accept a parameter of type \p Q that can be not the same as \p value_type.
 
             RCU \p synchronize method can be called. RCU should NOT be locked.
+
             The function does not free the item found.
             The function does not free the item found.
-            The item will be implicitly freed when \p result object is destroyed or when
-            <tt>result.release()</tt> is called, see \p cds::urcu::exempt_ptr for explanation.
-            @note Before reusing \p result object you should call its \p release() method.
+            The item will be implicitly freed when the returned object is destroyed or when
+            its \p release() member function is called.
         */
         template <typename Q>
         */
         template <typename Q>
-        bool extract( exempt_ptr& result, Q const& key )
+        exempt_ptr extract( Q const& key )
         {
         {
-            return base_class::do_extract( result, key );
+            return exempt_ptr( base_class::do_extract( key ));
         }
 
         /// Extracts the item from the set with comparing functor \p pred
         }
 
         /// Extracts the item from the set with comparing functor \p pred
@@ -467,41 +467,43 @@ 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>
             \p pred must imply the same element order as the comparator used for building the set.
         */
         template <typename Q, typename Less>
-        bool extract_with( exempt_ptr& result, Q const& key, Less pred )
+        exempt_ptr extract_with( Q const& key, Less pred )
         {
         {
-            return base_class::do_extract_with( result, key, cds::details::predicate_wrapper< node_type, Less, typename maker::value_accessor >());
+            return exempt_ptr( base_class::do_extract_with( key, cds::details::predicate_wrapper< node_type, Less, typename maker::value_accessor >()));
         }
 
         /// Extracts an item with minimal key from the set
         /**
         }
 
         /// Extracts an item with minimal key from the set
         /**
-            The function searches an item with minimal key, unlinks it, and returns the item found in \p result parameter.
-            If the skip-list is empty the function returns \p false.
+            The function searches an item with minimal key, unlinks it, 
+            and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the item.
+            If the skip-list is empty the function returns an empty \p exempt_ptr.
 
             RCU \p synchronize method can be called. RCU should NOT be locked.
 
             RCU \p synchronize method can be called. RCU should NOT be locked.
+
             The function does not free the item found.
             The function does not free the item found.
-            The item will be implicitly freed when \p result object is destroyed or when
-            <tt>result.release()</tt> is called, see cds::urcu::exempt_ptr for explanation.
-            @note Before reusing \p result object you should call its \p release() method.
+            The item will be implicitly freed when the returned object is destroyed or when
+            its \p release() member function is called.
         */
         */
-        bool extract_min( exempt_ptr& result )
+        exempt_ptr extract_min()
         {
         {
-            return base_class::do_extract_min(result);
+            return exempt_ptr( base_class::do_extract_min());
         }
 
         /// Extracts an item with maximal key from the set
         /**
         }
 
         /// Extracts an item with maximal key from the set
         /**
-            The function searches an item with maximal key, unlinks it from the set, and returns the item found
-            in \p result parameter. If the skip-list is empty the function returns \p false.
+            The function searches an item with maximal key, unlinks it from the set, 
+            and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the item.
+            If the skip-list is empty the function returns an empty \p exempt_ptr.
 
             RCU \p synchronize method can be called. RCU should NOT be locked.
 
             RCU \p synchronize method can be called. RCU should NOT be locked.
+
             The function does not free the item found.
             The function does not free the item found.
-            The item will be implicitly freed when \p result object is destroyed or when
-            <tt>result.release()</tt> is called, see cds::urcu::exempt_ptr for explanation.
-            @note Before reusing \p result object you should call its \p release() method.
+            The item will be implicitly freed when the returned object is destroyed or when
+            its \p release() member function is called.
         */
         */
-        bool extract_max(exempt_ptr& result)
+        exempt_ptr extract_max()
         {
         {
-            return base_class::do_extract_max(result);
+            return exempt_ptr( base_class::do_extract_max());
         }
 
         /// Find the key \p val
         }
 
         /// Find the key \p val
index 3b9bb82d93b4e0c06584711af58b246e42fc3f82..d8223573b8aeb498e4b821c64caf26d1b685deb4 100644 (file)
@@ -614,7 +614,7 @@ namespace cds { namespace intrusive {
         //@endcond
 
     public:
         //@endcond
 
     public:
-        typedef cds::urcu::exempt_ptr< gc, value_type, value_type, node_disposer, void > exempt_ptr; ///< pointer to extracted node
+        using exempt_ptr = cds::urcu::exempt_ptr< gc, value_type, value_type, node_disposer, void >; ///< pointer to extracted node
 
     protected:
         //@cond
 
     protected:
         //@cond
@@ -1133,136 +1133,105 @@ retry:
             return pDel ? node_traits::to_value_ptr( pDel ) : nullptr;
         }
 
             return pDel ? node_traits::to_value_ptr( pDel ) : nullptr;
         }
 
-        template <typename ExemptPtr, typename Q>
-        bool do_extract( ExemptPtr& result, Q const& key )
+        template <typename Q>
+        value_type * do_extract( Q const& key )
         {
             check_deadlock_policy::check();
         {
             check_deadlock_policy::check();
-
-            bool bReturn;
+            value_type * pDel = nullptr;
             {
                 rcu_lock l;
             {
                 rcu_lock l;
-                value_type * pDel = do_extract_key( key, key_comparator() );
-                bReturn = pDel != nullptr;
-                if ( bReturn )
-                    result = pDel;
+                pDel = do_extract_key( key, key_comparator() );
             }
 
             dispose_deferred();
             }
 
             dispose_deferred();
-            return bReturn;
+            return pDel;
         }
 
         }
 
-        template <typename ExemptPtr, typename Q, typename Less>
-        bool do_extract_with( ExemptPtr& result, Q const& key, Less pred )
+        template <typename Q, typename Less>
+        value_type * do_extract_with( Q const& key, Less pred )
         {
             check_deadlock_policy::check();
         {
             check_deadlock_policy::check();
+            value_type * pDel = nullptr;
 
 
-            bool bReturn;
             {
                 rcu_lock l;
             {
                 rcu_lock l;
-                value_type * pDel = do_extract_key( key, cds::opt::details::make_comparator_from_less<Less>() );
-                bReturn = pDel != nullptr;
-                if ( bReturn )
-                    result = pDel;
+                pDel = do_extract_key( key, cds::opt::details::make_comparator_from_less<Less>() );
             }
 
             dispose_deferred();
             }
 
             dispose_deferred();
-            return bReturn;
+            return pDel;
         }
 
         }
 
-        node_type * do_extract_min()
+        value_type * do_extract_min()
         {
         {
-            assert( gc::is_locked() );
+            assert( !gc::is_locked() );
 
             position pos;
             node_type * pDel;
 
 
             position pos;
             node_type * pDel;
 
-            if ( !find_min_position( pos ) ) {
-                m_Stat.onExtractMinFailed();
-                pDel = nullptr;
-            }
-            else {
-                pDel = pos.pCur;
-                unsigned int const nHeight = pDel->height();
+            {
+                rcu_lock l;
 
 
-                if ( try_remove_at( pDel, pos, [](value_type const&) {}, true )) {
-                    --m_ItemCounter;
-                    m_Stat.onRemoveNode( nHeight );
-                    m_Stat.onExtractMinSuccess();
-                }
-                else {
+                if ( !find_min_position( pos ) ) {
                     m_Stat.onExtractMinFailed();
                     pDel = nullptr;
                 }
                     m_Stat.onExtractMinFailed();
                     pDel = nullptr;
                 }
-            }
-
-            defer_chain( pos );
-            return pDel;
-        }
+                else {
+                    pDel = pos.pCur;
+                    unsigned int const nHeight = pDel->height();
 
 
-        template <typename ExemptPtr>
-        bool do_extract_min( ExemptPtr& result )
-        {
-            check_deadlock_policy::check();
+                    if ( try_remove_at( pDel, pos, []( value_type const& ) {}, true ) ) {
+                        --m_ItemCounter;
+                        m_Stat.onRemoveNode( nHeight );
+                        m_Stat.onExtractMinSuccess();
+                    }
+                    else {
+                        m_Stat.onExtractMinFailed();
+                        pDel = nullptr;
+                    }
+                }
 
 
-            bool bReturn;
-            {
-                rcu_lock l;
-                node_type * pDel = do_extract_min();
-                bReturn = pDel != nullptr;
-                if ( bReturn )
-                    result = node_traits::to_value_ptr(pDel);
+                defer_chain( pos );
             }
 
             dispose_deferred();
             }
 
             dispose_deferred();
-            return bReturn;
+            return pDel ? node_traits::to_value_ptr( pDel ) : nullptr;
         }
 
         }
 
-        node_type * do_extract_max()
+        value_type * do_extract_max()
         {
         {
-            assert( gc::is_locked() );
+            assert( !gc::is_locked() );
 
             position pos;
             node_type * pDel;
 
 
             position pos;
             node_type * pDel;
 
-            if ( !find_max_position( pos ) ) {
-                m_Stat.onExtractMaxFailed();
-                pDel = nullptr;
-            }
-            else {
-                pDel = pos.pCur;
-                unsigned int const nHeight = pDel->height();
+            {
+                rcu_lock l;
 
 
-                if ( try_remove_at( pDel, pos, [](value_type const&) {}, true )) {
-                    --m_ItemCounter;
-                    m_Stat.onRemoveNode( nHeight );
-                    m_Stat.onExtractMaxSuccess();
-                }
-                else {
+                if ( !find_max_position( pos ) ) {
                     m_Stat.onExtractMaxFailed();
                     pDel = nullptr;
                 }
                     m_Stat.onExtractMaxFailed();
                     pDel = nullptr;
                 }
-            }
-
-            defer_chain( pos );
-            return pDel;
-        }
+                else {
+                    pDel = pos.pCur;
+                    unsigned int const nHeight = pDel->height();
 
 
-        template <typename ExemptPtr>
-        bool do_extract_max( ExemptPtr& result )
-        {
-            check_deadlock_policy::check();
+                    if ( try_remove_at( pDel, pos, []( value_type const& ) {}, true ) ) {
+                        --m_ItemCounter;
+                        m_Stat.onRemoveNode( nHeight );
+                        m_Stat.onExtractMaxSuccess();
+                    }
+                    else {
+                        m_Stat.onExtractMaxFailed();
+                        pDel = nullptr;
+                    }
+                }
 
 
-            bool bReturn;
-            {
-                rcu_lock l;
-                node_type * pDel = do_extract_max();
-                bReturn = pDel != nullptr;
-                if ( bReturn )
-                    result = node_traits::to_value_ptr(pDel);
+                defer_chain( pos );
             }
 
             dispose_deferred();
             }
 
             dispose_deferred();
-            return bReturn;
+            return pDel ? node_traits::to_value_ptr( pDel ) : nullptr;
         }
 
         void increase_height( unsigned int nHeight )
         }
 
         void increase_height( unsigned int nHeight )
@@ -1645,24 +1614,23 @@ retry:
         /// Extracts the item from the set with specified \p key
         /** \anchor cds_intrusive_SkipListSet_rcu_extract
             The function searches an item with key equal to \p key in the set,
         /// Extracts the item from the set with specified \p key
         /** \anchor cds_intrusive_SkipListSet_rcu_extract
             The function searches an item with key equal to \p key in the set,
-            unlinks it from the set, places it to \p result parameter, and returns \p true.
-            If the item with key equal to \p key is not found the function returns \p false.
+            unlinks it from the set, and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the item found.
+            If the item with key equal to \p key is not found the function returns an empty \p exempt_ptr.
 
             Note the compare functor should accept a parameter of type \p Q that can be not the same as \p value_type.
 
             RCU \p synchronize method can be called. RCU should NOT be locked.
             The function does not call the disposer for the item found.
 
             Note the compare functor should accept a parameter of type \p Q that can be not the same as \p value_type.
 
             RCU \p synchronize method can be called. RCU should NOT be locked.
             The function does not call the disposer for the item found.
-            The disposer will be implicitly invoked when \p result object is destroyed or when
-            <tt>result.release()</tt> is called, see cds::urcu::exempt_ptr for explanation.
-            @note Before reusing \p result object you should call its \p release() method.
+            The disposer will be implicitly invoked when the returned object is destroyed or when
+            its \p release() member function is called.
             Example:
             \code
             typedef cds::intrusive::SkipListSet< cds::urcu::gc< cds::urcu::general_buffered<> >, foo, my_traits > skip_list;
             skip_list theList;
             // ...
 
             Example:
             \code
             typedef cds::intrusive::SkipListSet< cds::urcu::gc< cds::urcu::general_buffered<> >, foo, my_traits > skip_list;
             skip_list theList;
             // ...
 
-            typename skip_list::exempt_ptr ep;
-            if ( theList.extract( ep, 5 ) ) {
+            typename skip_list::exempt_ptr ep( theList.extract( 5 ));
+            if ( ep ) {
                 // Deal with ep
                 //...
 
                 // Deal with ep
                 //...
 
@@ -1672,9 +1640,9 @@ retry:
             \endcode
         */
         template <typename Q>
             \endcode
         */
         template <typename Q>
-        bool extract( exempt_ptr& result, Q const& key )
+        exempt_ptr extract( Q const& key )
         {
         {
-            return do_extract( result, key );
+            return exempt_ptr( do_extract( key ));
         }
 
         /// Extracts the item from the set with comparing functor \p pred
         }
 
         /// Extracts the item from the set with comparing functor \p pred
@@ -1685,29 +1653,28 @@ retry:
             \p pred must imply the same element order as the comparator used for building the set.
         */
         template <typename Q, typename Less>
             \p pred must imply the same element order as the comparator used for building the set.
         */
         template <typename Q, typename Less>
-        bool extract_with( exempt_ptr& result, Q const& key, Less pred )
+        exempt_ptr extract_with( Q const& key, Less pred )
         {
         {
-            return do_extract_with( result, key, pred );
+            return exempt_ptr( do_extract_with( key, pred ));
         }
 
         /// Extracts an item with minimal key from the list
         /**
         }
 
         /// Extracts an item with minimal key from the list
         /**
-            The function searches an item with minimal key, unlinks it, and returns the item found in \p result parameter.
-            If the skip-list is empty the function returns \p false.
+            The function searches an item with minimal key, unlinks it, and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the item.
+            If the skip-list is empty the function returns an empty \p exempt_ptr.
 
             RCU \p synchronize method can be called. RCU should NOT be locked.
             The function does not call the disposer for the item found.
 
             RCU \p synchronize method can be called. RCU should NOT be locked.
             The function does not call the disposer for the item found.
-            The disposer will be implicitly invoked when \p result object is destroyed or when
-            <tt>result.release()</tt> is called, see cds::urcu::exempt_ptr for explanation.
-            @note Before reusing \p result object you should call its \p release() method.
+            The disposer will be implicitly invoked when the returned object is destroyed or when
+            its \p release() member function is manually called.
             Example:
             \code
             typedef cds::intrusive::SkipListSet< cds::urcu::gc< cds::urcu::general_buffered<> >, foo, my_traits > skip_list;
             skip_list theList;
             // ...
 
             Example:
             \code
             typedef cds::intrusive::SkipListSet< cds::urcu::gc< cds::urcu::general_buffered<> >, foo, my_traits > skip_list;
             skip_list theList;
             // ...
 
-            typename skip_list::exempt_ptr ep;
-            if ( theList.extract_min(ep)) {
+            typename skip_list::exempt_ptr ep(theList.extract_min());
+            if ( ep ) {
                 // Deal with ep
                 //...
 
                 // Deal with ep
                 //...
 
@@ -1721,29 +1688,28 @@ retry:
             During unlinking, a concurrent thread may insert an item with key less than leftmost item's key.
             So, the function returns the item with minimum key at the moment of list traversing.
         */
             During unlinking, a concurrent thread may insert an item with key less than leftmost item's key.
             So, the function returns the item with minimum key at the moment of list traversing.
         */
-        bool extract_min( exempt_ptr& result )
+        exempt_ptr extract_min()
         {
         {
-            return do_extract_min( result );
+            return exempt_ptr( do_extract_min());
         }
 
         /// Extracts an item with maximal key from the list
         /**
         }
 
         /// Extracts an item with maximal key from the list
         /**
-            The function searches an item with maximal key, unlinks it, and returns the item found in \p result parameter.
-            If the skip-list is empty the function returns \p false.
+            The function searches an item with maximal key, unlinks it, and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the item.
+            If the skip-list is empty the function returns an empty \p exempt_ptr.
 
             RCU \p synchronize method can be called. RCU should NOT be locked.
             The function does not call the disposer for the item found.
 
             RCU \p synchronize method can be called. RCU should NOT be locked.
             The function does not call the disposer for the item found.
-            The disposer will be implicitly invoked when \p result object is destroyed or when
-            <tt>result.release()</tt> is called, see cds::urcu::exempt_ptr for explanation.
-            @note Before reusing \p result object you should call its \p release() method.
+            The disposer will be implicitly invoked when the returned object is destroyed or when
+            its \p release() member function is manually called.
             Example:
             \code
             typedef cds::intrusive::SkipListSet< cds::urcu::gc< cds::urcu::general_buffered<> >, foo, my_traits > skip_list;
             skip_list theList;
             // ...
 
             Example:
             \code
             typedef cds::intrusive::SkipListSet< cds::urcu::gc< cds::urcu::general_buffered<> >, foo, my_traits > skip_list;
             skip_list theList;
             // ...
 
-            typename skip_list::exempt_ptr ep;
-            if ( theList.extract_max(ep) ) {
+            typename skip_list::exempt_ptr ep( theList.extract_max() );
+            if ( ep ) {
                 // Deal with ep
                 //...
                 // Dispose returned item.
                 // Deal with ep
                 //...
                 // Dispose returned item.
@@ -1756,9 +1722,9 @@ retry:
             During unlinking, a concurrent thread can insert an item with key greater than rightmost item's key.
             So, the function returns the item with maximum key at the moment of list traversing.
         */
             During unlinking, a concurrent thread can insert an item with key greater than rightmost item's key.
             So, the function returns the item with maximum key at the moment of list traversing.
         */
-        bool extract_max( exempt_ptr& result )
+        exempt_ptr extract_max()
         {
         {
-            return do_extract_max( result );
+            return exempt_ptr( do_extract_max());
         }
 
         /// Deletes the item from the set
         }
 
         /// Deletes the item from the set
@@ -1990,8 +1956,7 @@ retry:
         void clear()
         {
             exempt_ptr ep;
         void clear()
         {
             exempt_ptr ep;
-            while ( extract_min(ep) )
-                ep.release();
+            while ( (ep = extract_min()) );
         }
 
         /// Returns maximum height of skip-list. The max height is a constant for each object and does not exceed 32.
         }
 
         /// Returns maximum height of skip-list. The max height is a constant for each object and does not exceed 32.
index f4cd7b51eaa3004a1f320f6f1d2bd5ff001d27f0..c3a5d436f4618469ec91f124b743fbde34dbba34 100644 (file)
@@ -174,17 +174,18 @@ namespace map {
                         CPPUNIT_CHECK( pVal->second.m_val == nKey * 2 );
                     }
 
                         CPPUNIT_CHECK( pVal->second.m_val == nKey * 2 );
                     }
 
-                    CPPUNIT_ASSERT( m.extract( ep, nKey ));
+                    ep = m.extract( nKey );
+                    CPPUNIT_ASSERT( ep );
                     CPPUNIT_ASSERT( !ep.empty() );
                     CPPUNIT_CHECK( ep->first == nKey );
                     CPPUNIT_CHECK( ep->second.m_val == nKey * 2 );
                     CPPUNIT_ASSERT( !ep.empty() );
                     CPPUNIT_CHECK( ep->first == nKey );
                     CPPUNIT_CHECK( ep->second.m_val == nKey * 2 );
-                    ep.release();
 
                     {
                         rcu_lock l;
                         CPPUNIT_CHECK( m.get( nKey ) ==  nullptr );
                     }
 
                     {
                         rcu_lock l;
                         CPPUNIT_CHECK( m.get( nKey ) ==  nullptr );
                     }
-                    CPPUNIT_CHECK( !m.extract(ep, nKey) );
+                    ep = m.extract( nKey );
+                    CPPUNIT_CHECK( !ep );
                 }
                 CPPUNIT_ASSERT( m.empty() );
 
                 }
                 CPPUNIT_ASSERT( m.empty() );
 
@@ -202,17 +203,18 @@ namespace map {
                         CPPUNIT_CHECK( pVal->second.m_val == nKey * 2 );
                     }
 
                         CPPUNIT_CHECK( pVal->second.m_val == nKey * 2 );
                     }
 
-                    CPPUNIT_ASSERT( m.extract_with( ep, wrapped_item(nKey), wrapped_less() ));
+                    ep = m.extract_with( wrapped_item( nKey ), wrapped_less() );
+                    CPPUNIT_ASSERT( ep );
                     CPPUNIT_ASSERT( !ep.empty() );
                     CPPUNIT_CHECK( ep->first == nKey );
                     CPPUNIT_CHECK( ep->second.m_val == nKey * 2 );
                     CPPUNIT_ASSERT( !ep.empty() );
                     CPPUNIT_CHECK( ep->first == nKey );
                     CPPUNIT_CHECK( ep->second.m_val == nKey * 2 );
-                    ep.release();
 
                     {
                         rcu_lock l;
                         CPPUNIT_CHECK( m.get_with( wrapped_item(nKey), wrapped_less() ) ==  nullptr );
                     }
 
                     {
                         rcu_lock l;
                         CPPUNIT_CHECK( m.get_with( wrapped_item(nKey), wrapped_less() ) ==  nullptr );
                     }
-                    CPPUNIT_CHECK( !m.extract_with(ep, wrapped_item(nKey), wrapped_less()) );
+                    ep = m.extract_with( wrapped_item( nKey ), wrapped_less() );
+                    CPPUNIT_CHECK( !ep );
                 }
                 CPPUNIT_ASSERT( m.empty() );
 
                 }
                 CPPUNIT_ASSERT( m.empty() );
 
@@ -220,27 +222,29 @@ namespace map {
                 for ( int i = 0; i < nLimit; ++i )
                     CPPUNIT_ASSERT( m.insert(arrItem[i], arrItem[i]*2) );
                 for ( int i = 0; i < nLimit; ++i ) {
                 for ( int i = 0; i < nLimit; ++i )
                     CPPUNIT_ASSERT( m.insert(arrItem[i], arrItem[i]*2) );
                 for ( int i = 0; i < nLimit; ++i ) {
-                    CPPUNIT_ASSERT( m.extract_min(ep));
+                    ep = m.extract_min();
+                    CPPUNIT_ASSERT( ep );
                     CPPUNIT_ASSERT( !ep.empty() );
                     CPPUNIT_CHECK( ep->first == i );
                     CPPUNIT_CHECK( ep->second.m_val == i * 2 );
                     CPPUNIT_ASSERT( !ep.empty() );
                     CPPUNIT_CHECK( ep->first == i );
                     CPPUNIT_CHECK( ep->second.m_val == i * 2 );
-                    ep.release();
                 }
                 CPPUNIT_ASSERT( m.empty() );
                 }
                 CPPUNIT_ASSERT( m.empty() );
-                CPPUNIT_CHECK( !m.extract_min(ep) );
+                ep = m.extract_min();
+                CPPUNIT_CHECK( !ep );
 
                 // extract_max
                 for ( int i = 0; i < nLimit; ++i )
                     CPPUNIT_ASSERT( m.insert(arrItem[i], arrItem[i]*2) );
                 for ( int i = nLimit-1; i >= 0; --i ) {
 
                 // extract_max
                 for ( int i = 0; i < nLimit; ++i )
                     CPPUNIT_ASSERT( m.insert(arrItem[i], arrItem[i]*2) );
                 for ( int i = nLimit-1; i >= 0; --i ) {
-                    CPPUNIT_ASSERT( m.extract_max(ep));
+                    ep = m.extract_max();
+                    CPPUNIT_ASSERT( ep );
                     CPPUNIT_ASSERT( !ep.empty() );
                     CPPUNIT_CHECK( ep->first == i );
                     CPPUNIT_CHECK( ep->second.m_val == i * 2 );
                     CPPUNIT_ASSERT( !ep.empty() );
                     CPPUNIT_CHECK( ep->first == i );
                     CPPUNIT_CHECK( ep->second.m_val == i * 2 );
-                    ep.release();
                 }
                 CPPUNIT_ASSERT( m.empty() );
                 }
                 CPPUNIT_ASSERT( m.empty() );
-                CPPUNIT_CHECK( !m.extract_max(ep) );
+                ep = m.extract_max();
+                CPPUNIT_CHECK( !ep );
             }
 
             CPPUNIT_MSG( PrintStat()(m, nullptr) );
             }
 
             CPPUNIT_MSG( PrintStat()(m, nullptr) );
index 973cea299298a0311c3775d8a5e9d947bf418645..cd7d0ffd27034428dda9d30bd471ddd36805122e 100644 (file)
@@ -268,17 +268,19 @@ namespace set {
                             pVal->nVal *= 2;
                         }
 
                             pVal->nVal *= 2;
                         }
 
-                        CPPUNIT_ASSERT( s.extract( ep, i ));
+                        ep = s.extract( i );
+                        CPPUNIT_ASSERT( ep );
                         CPPUNIT_ASSERT( !ep.empty() );
                         CPPUNIT_CHECK( ep->nKey == i );
                         CPPUNIT_CHECK( ep->nVal == i * 4 );
                         CPPUNIT_ASSERT( !ep.empty() );
                         CPPUNIT_CHECK( ep->nKey == i );
                         CPPUNIT_CHECK( ep->nVal == i * 4 );
-                        ep.release();
+                        //ep.release();
 
                         {
                             rcu_lock l;
                             CPPUNIT_CHECK( s.get( i ) == nullptr );
                         }
 
                         {
                             rcu_lock l;
                             CPPUNIT_CHECK( s.get( i ) == nullptr );
                         }
-                        CPPUNIT_CHECK( !s.extract( ep, i ) );
+                        ep = s.extract( i );
+                        CPPUNIT_CHECK( !ep );
                         CPPUNIT_ASSERT( ep.empty() );
                     }
                     CPPUNIT_CHECK( s.empty() );
                         CPPUNIT_ASSERT( ep.empty() );
                     }
                     CPPUNIT_CHECK( s.empty() );
@@ -298,17 +300,19 @@ namespace set {
                             pVal->nVal *= 2;
                         }
 
                             pVal->nVal *= 2;
                         }
 
-                        CPPUNIT_ASSERT( s.extract_with( ep, other_key(i), other_key_less<typename Set::value_type>() ));
+                        ep = s.extract_with( other_key( i ), other_key_less<typename Set::value_type>() );
+                        CPPUNIT_ASSERT( ep );
                         CPPUNIT_ASSERT( !ep.empty() );
                         CPPUNIT_CHECK( ep->nKey == i );
                         CPPUNIT_CHECK( ep->nVal == i * 4 );
                         CPPUNIT_ASSERT( !ep.empty() );
                         CPPUNIT_CHECK( ep->nKey == i );
                         CPPUNIT_CHECK( ep->nVal == i * 4 );
-                        ep.release();
+                        //ep.release();
 
                         {
                             rcu_lock l;
                             CPPUNIT_CHECK( s.get_with( other_key( i ), other_key_less<typename Set::value_type>() ) == nullptr );
                         }
 
                         {
                             rcu_lock l;
                             CPPUNIT_CHECK( s.get_with( other_key( i ), other_key_less<typename Set::value_type>() ) == nullptr );
                         }
-                        CPPUNIT_CHECK( !s.extract_with( ep, other_key(i), other_key_less<typename Set::value_type>() ));
+                        ep = s.extract_with( other_key( i ), other_key_less<typename Set::value_type>() );
+                        CPPUNIT_CHECK( !ep );
                     }
                     CPPUNIT_CHECK( s.empty() );
                 }
                     }
                     CPPUNIT_CHECK( s.empty() );
                 }
@@ -319,21 +323,24 @@ namespace set {
                     fill_skiplist( s, v );
                     int nPrevKey;
 
                     fill_skiplist( s, v );
                     int nPrevKey;
 
-                    CPPUNIT_ASSERT( s.extract_min(ep));
+                    ep = s.extract_min();
+                    CPPUNIT_ASSERT( ep );
                     CPPUNIT_ASSERT( !ep.empty());
                     nPrevKey = ep->nKey;
                     CPPUNIT_ASSERT( !ep.empty());
                     nPrevKey = ep->nKey;
-                    ep.release();
+                    //ep.release();
 
                     while ( !s.empty() ) {
 
                     while ( !s.empty() ) {
-                        CPPUNIT_ASSERT( s.extract_min(ep) );
+                        ep = s.extract_min();
+                        CPPUNIT_ASSERT( ep );
                         CPPUNIT_ASSERT( !ep.empty());
                         CPPUNIT_CHECK( ep->nKey == nPrevKey + 1 );
                         CPPUNIT_CHECK( ep->nVal == (nPrevKey + 1) * 2 );
                         nPrevKey = ep->nKey;
                         CPPUNIT_ASSERT( !ep.empty());
                         CPPUNIT_CHECK( ep->nKey == nPrevKey + 1 );
                         CPPUNIT_CHECK( ep->nVal == (nPrevKey + 1) * 2 );
                         nPrevKey = ep->nKey;
-                        ep.release();
+                        //ep.release();
                     }
                     }
-                    CPPUNIT_CHECK( !s.extract_min(ep) );
-                    CPPUNIT_CHECK( !s.extract_max(ep) );
+                    ep = s.extract_min();
+                    CPPUNIT_CHECK( !ep );
+                    CPPUNIT_CHECK( !s.extract_max() );
                 }
                 Set::gc::force_dispose();
 
                 }
                 Set::gc::force_dispose();
 
@@ -342,23 +349,26 @@ namespace set {
                     fill_skiplist( s, v );
                     int nPrevKey;
 
                     fill_skiplist( s, v );
                     int nPrevKey;
 
-                    CPPUNIT_ASSERT( s.extract_max(ep));
+                    ep = s.extract_max();
+                    CPPUNIT_ASSERT( ep );
                     CPPUNIT_ASSERT( !ep.empty());
                     nPrevKey = ep->nKey;
                     CPPUNIT_ASSERT( !ep.empty());
                     nPrevKey = ep->nKey;
-                    ep.release();
+                    //ep.release();
 
                     while ( !s.empty() ) {
 
                     while ( !s.empty() ) {
-                        CPPUNIT_ASSERT( s.extract_max(ep));
+                        ep = s.extract_max();
+                        CPPUNIT_ASSERT( ep );
                         CPPUNIT_ASSERT( !ep.empty());
                         CPPUNIT_CHECK( ep->nKey == nPrevKey - 1 );
                         CPPUNIT_CHECK( ep->nVal == (nPrevKey - 1) * 2 );
                         nPrevKey = ep->nKey;
                         CPPUNIT_ASSERT( !ep.empty());
                         CPPUNIT_CHECK( ep->nKey == nPrevKey - 1 );
                         CPPUNIT_CHECK( ep->nVal == (nPrevKey - 1) * 2 );
                         nPrevKey = ep->nKey;
-                        ep.release();
+                        //ep.release();
                     }
                     }
+                    ep = s.extract_min();
+                    CPPUNIT_CHECK( !ep );
+                    CPPUNIT_CHECK( !s.extract_max() );
                 }
                 Set::gc::force_dispose();
                 }
                 Set::gc::force_dispose();
-                CPPUNIT_CHECK( !s.extract_min(ep) );
-                CPPUNIT_CHECK( !s.extract_max(ep) );
             }
 
             CPPUNIT_MSG( PrintStat()(s, nullptr) );
             }
 
             CPPUNIT_MSG( PrintStat()(s, nullptr) );
index ff99ebdbfee4af9717db278475da856165e4fd0f..ad10c40d4dfed65dccd12b819f4d02564e22404b 100644 (file)
@@ -168,17 +168,18 @@ namespace set {
                         CPPUNIT_CHECK( pVal->nVal == nKey * 2 );
                     }
 
                         CPPUNIT_CHECK( pVal->nVal == nKey * 2 );
                     }
 
-                    CPPUNIT_ASSERT( s.extract( ep, nKey ));
+                    ep = s.extract( nKey );
+                    CPPUNIT_ASSERT( ep );
                     CPPUNIT_ASSERT( !ep.empty() );
                     CPPUNIT_CHECK( ep->nKey == nKey );
                     CPPUNIT_CHECK( ep->nVal == nKey * 2 );
                     CPPUNIT_ASSERT( !ep.empty() );
                     CPPUNIT_CHECK( ep->nKey == nKey );
                     CPPUNIT_CHECK( ep->nVal == nKey * 2 );
-                    ep.release();
 
                     {
                         rcu_lock l;
                         CPPUNIT_CHECK( s.get( nKey ) == nullptr );
                     }
 
                     {
                         rcu_lock l;
                         CPPUNIT_CHECK( s.get( nKey ) == nullptr );
                     }
-                    CPPUNIT_CHECK( !s.extract( ep, nKey ));
+                    ep = s.extract( nKey );
+                    CPPUNIT_CHECK( !ep );
                 }
                 CPPUNIT_CHECK( s.empty());
 
                 }
                 CPPUNIT_CHECK( s.empty());
 
@@ -196,17 +197,18 @@ namespace set {
                         CPPUNIT_CHECK( pVal->nVal == nKey );
                     }
 
                         CPPUNIT_CHECK( pVal->nVal == nKey );
                     }
 
-                    CPPUNIT_ASSERT( s.extract_with( ep, wrapped_item(nKey), wrapped_less() ));
+                    ep = s.extract_with( wrapped_item( nKey ), wrapped_less() );
+                    CPPUNIT_ASSERT( ep );
                     CPPUNIT_ASSERT( !ep.empty() );
                     CPPUNIT_CHECK( ep->nKey == nKey );
                     CPPUNIT_CHECK( ep->nVal == nKey );
                     CPPUNIT_ASSERT( !ep.empty() );
                     CPPUNIT_CHECK( ep->nKey == nKey );
                     CPPUNIT_CHECK( ep->nVal == nKey );
-                    ep.release();
 
                     {
                         rcu_lock l;
                         CPPUNIT_CHECK( s.get_with( wrapped_item( nKey ), wrapped_less() ) == nullptr );
                     }
 
                     {
                         rcu_lock l;
                         CPPUNIT_CHECK( s.get_with( wrapped_item( nKey ), wrapped_less() ) == nullptr );
                     }
-                    CPPUNIT_CHECK( !s.extract_with( ep, wrapped_item(nKey), wrapped_less() ));
+                    ep = s.extract_with( wrapped_item( nKey ), wrapped_less() );
+                    CPPUNIT_CHECK( !ep );
                 }
                 CPPUNIT_CHECK( s.empty());
 
                 }
                 CPPUNIT_CHECK( s.empty());
 
@@ -215,12 +217,12 @@ namespace set {
                     CPPUNIT_ASSERT( s.insert( arrRandom[i]) );
 
                 for ( int i = 0; i < nLimit; ++i ) {
                     CPPUNIT_ASSERT( s.insert( arrRandom[i]) );
 
                 for ( int i = 0; i < nLimit; ++i ) {
-                    CPPUNIT_ASSERT( s.extract_min(ep) );
+                    ep = s.extract_min();
+                    CPPUNIT_ASSERT( ep );
                     CPPUNIT_ASSERT( !ep.empty() );
                     CPPUNIT_CHECK( ep->nKey == i );
                     CPPUNIT_CHECK( ep->nVal == i );
                     CPPUNIT_CHECK( !s.find(i) );
                     CPPUNIT_ASSERT( !ep.empty() );
                     CPPUNIT_CHECK( ep->nKey == i );
                     CPPUNIT_CHECK( ep->nVal == i );
                     CPPUNIT_CHECK( !s.find(i) );
-                    ep.release();
                 }
                 CPPUNIT_CHECK( s.empty());
 
                 }
                 CPPUNIT_CHECK( s.empty());
 
@@ -229,16 +231,17 @@ namespace set {
                     CPPUNIT_ASSERT( s.insert( arrRandom[i]) );
 
                 for ( int i = nLimit-1; i >= 0; --i ) {
                     CPPUNIT_ASSERT( s.insert( arrRandom[i]) );
 
                 for ( int i = nLimit-1; i >= 0; --i ) {
-                    CPPUNIT_ASSERT( s.extract_max(ep) );
+                    ep = s.extract_max();
+                    CPPUNIT_ASSERT( ep );
                     CPPUNIT_ASSERT( !ep.empty() );
                     CPPUNIT_CHECK( ep->nKey == i );
                     CPPUNIT_CHECK( ep->nVal == i );
                     CPPUNIT_CHECK( !s.find(i) );
                     CPPUNIT_ASSERT( !ep.empty() );
                     CPPUNIT_CHECK( ep->nKey == i );
                     CPPUNIT_CHECK( ep->nVal == i );
                     CPPUNIT_CHECK( !s.find(i) );
-                    ep.release();
                 }
                 CPPUNIT_CHECK( s.empty());
                 }
                 CPPUNIT_CHECK( s.empty());
-                CPPUNIT_CHECK( !s.extract_min(ep) );
-                CPPUNIT_CHECK( !s.extract_max(ep) );
+                ep = s.extract_min();
+                CPPUNIT_CHECK( !ep );
+                CPPUNIT_CHECK( !s.extract_max() );
             }
 
             CPPUNIT_MSG( PrintStat()(s, nullptr) );
             }
 
             CPPUNIT_MSG( PrintStat()(s, nullptr) );
index 4eb1512d284e36a9a9718a9b44b8fb5f656ad7c5..e450051fff35b05686803a3de0f9c91e64cf2502 100644 (file)
@@ -435,22 +435,21 @@ namespace map2 {
                                 if ( Map::c_bExtractLockExternal ) {
                                     {
                                         typename Map::rcu_lock l;
                                 if ( Map::c_bExtractLockExternal ) {
                                     {
                                         typename Map::rcu_lock l;
-                                        if ( rMap.extract_with( xp, arrData[i], key_less() )) {
+                                        xp = rMap.extract_with( arrData[i], key_less() );
+                                        if ( xp )
                                             ++m_nDeleteSuccess;
                                             ++m_nDeleteSuccess;
-                                        }
                                         else
                                             ++m_nDeleteFailed;
                                     }
                                         else
                                             ++m_nDeleteFailed;
                                     }
-                                    xp.release();
                                 }
                                 else {
                                 }
                                 else {
-                                    if ( rMap.extract_with( xp, arrData[i], key_less() )) {
+                                    xp = rMap.extract_with( arrData[i], key_less() );
+                                    if ( xp )
                                         ++m_nDeleteSuccess;
                                         ++m_nDeleteSuccess;
-                                        xp.release();
-                                    }
                                     else
                                         ++m_nDeleteFailed;
                                 }
                                     else
                                         ++m_nDeleteFailed;
                                 }
+                                xp.release();
                             }
                         }
                         if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
                             }
                         }
                         if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
@@ -464,21 +463,21 @@ namespace map2 {
                                 if ( Map::c_bExtractLockExternal ) {
                                     {
                                         typename Map::rcu_lock l;
                                 if ( Map::c_bExtractLockExternal ) {
                                     {
                                         typename Map::rcu_lock l;
-                                        if ( rMap.extract_with( xp, arrData[i], key_less() ))
+                                        xp = rMap.extract_with( arrData[i], key_less() );
+                                        if ( xp )
                                             ++m_nDeleteSuccess;
                                         else
                                             ++m_nDeleteFailed;
                                     }
                                             ++m_nDeleteSuccess;
                                         else
                                             ++m_nDeleteFailed;
                                     }
-                                    xp.release();
                                 }
                                 else {
                                 }
                                 else {
-                                    if ( rMap.extract_with( xp, arrData[i], key_less() )) {
+                                    xp = rMap.extract_with( arrData[i], key_less() );
+                                    if ( xp )
                                         ++m_nDeleteSuccess;
                                         ++m_nDeleteSuccess;
-                                        xp.release();
-                                    }
                                     else
                                         ++m_nDeleteFailed;
                                 }
                                     else
                                         ++m_nDeleteFailed;
                                 }
+                                xp.release();
                             }
                         }
                         if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
                             }
                         }
                         if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
index 29782a6649c5cbd57f6c38cc19f8b214c5251482..82bc58eed5c60b8d4570fa5ffc61f243dd492a2e 100644 (file)
@@ -475,13 +475,15 @@ namespace set2 {
                             if ( arrData[i] & 1 ) {
                                 if ( Set::c_bExtractLockExternal ) {
                                     typename Set::rcu_lock l;
                             if ( arrData[i] & 1 ) {
                                 if ( Set::c_bExtractLockExternal ) {
                                     typename Set::rcu_lock l;
-                                    if ( rSet.extract_with( xp, arrData[i], key_less() ))
+                                    xp = rSet.extract_with( arrData[i], key_less() );
+                                    if ( xp )
                                         ++m_nExtractSuccess;
                                     else
                                         ++m_nExtractFailed;
                                 }
                                 else {
                                         ++m_nExtractSuccess;
                                     else
                                         ++m_nExtractFailed;
                                 }
                                 else {
-                                    if ( rSet.extract_with( xp, arrData[i], key_less() ))
+                                    xp = rSet.extract_with( arrData[i], key_less() );
+                                    if ( xp )
                                         ++m_nExtractSuccess;
                                     else
                                         ++m_nExtractFailed;
                                         ++m_nExtractSuccess;
                                     else
                                         ++m_nExtractFailed;
@@ -499,13 +501,15 @@ namespace set2 {
                             if ( arrData[i] & 1 ) {
                                 if ( Set::c_bExtractLockExternal ) {
                                     typename Set::rcu_lock l;
                             if ( arrData[i] & 1 ) {
                                 if ( Set::c_bExtractLockExternal ) {
                                     typename Set::rcu_lock l;
-                                    if ( rSet.extract_with( xp, arrData[i], key_less() ))
+                                    xp = rSet.extract_with( arrData[i], key_less() );
+                                    if ( xp )
                                         ++m_nExtractSuccess;
                                     else
                                         ++m_nExtractFailed;
                                 }
                                 else {
                                         ++m_nExtractSuccess;
                                     else
                                         ++m_nExtractFailed;
                                 }
                                 else {
-                                    if ( rSet.extract_with( xp, arrData[i], key_less() ))
+                                    xp = rSet.extract_with( arrData[i], key_less() );
+                                    if ( xp )
                                         ++m_nExtractSuccess;
                                     else
                                         ++m_nExtractFailed;
                                         ++m_nExtractSuccess;
                                     else
                                         ++m_nExtractFailed;
index 4b1179189a2ad66f0aa5bb4987294482fb177d40..3f5ffcdd29cabb22bf431f7b20fcfcb4731f7ff8 100644 (file)
@@ -272,21 +272,21 @@ namespace set2 {
                             if ( Set::c_bExtractLockExternal ) {
                                 {
                                     typename Set::rcu_lock l;
                             if ( Set::c_bExtractLockExternal ) {
                                 {
                                     typename Set::rcu_lock l;
-                                    if ( rSet.extract( xp, arrString[nItem % nArrSize] ) )
+                                    xp = rSet.extract( arrString[nItem % nArrSize] );
+                                    if ( xp )
                                         ++m_nDeleteSuccess;
                                     else
                                         ++m_nDeleteFailed;
                                 }
                                         ++m_nDeleteSuccess;
                                     else
                                         ++m_nDeleteFailed;
                                 }
-                                xp.release();
                             }
                             else {
                             }
                             else {
-                                if ( rSet.extract( xp, arrString[nItem % nArrSize] ) ) {
+                                xp = rSet.extract( arrString[nItem % nArrSize] );
+                                if ( xp )
                                     ++m_nDeleteSuccess;
                                     ++m_nDeleteSuccess;
-                                    xp.release();
-                                }
                                 else
                                     ++m_nDeleteFailed;
                             }
                                 else
                                     ++m_nDeleteFailed;
                             }
+                            xp.release();
                         }
                     }
                 }
                         }
                     }
                 }
@@ -296,21 +296,21 @@ namespace set2 {
                             if ( Set::c_bExtractLockExternal ) {
                                 {
                                     typename Set::rcu_lock l;
                             if ( Set::c_bExtractLockExternal ) {
                                 {
                                     typename Set::rcu_lock l;
-                                    if ( rSet.extract( xp, arrString[nItem % nArrSize] ) )
+                                    xp = rSet.extract( arrString[nItem % nArrSize] );
+                                    if ( xp )
                                         ++m_nDeleteSuccess;
                                     else
                                         ++m_nDeleteFailed;
                                 }
                                         ++m_nDeleteSuccess;
                                     else
                                         ++m_nDeleteFailed;
                                 }
-                                xp.release();
                             }
                             else {
                             }
                             else {
-                                if ( rSet.extract( xp, arrString[nItem % nArrSize] ) ) {
+                                xp = rSet.extract( arrString[nItem % nArrSize] );
+                                if ( xp )
                                     ++m_nDeleteSuccess;
                                     ++m_nDeleteSuccess;
-                                    xp.release();
-                                }
                                 else
                                     ++m_nDeleteFailed;
                             }
                                 else
                                     ++m_nDeleteFailed;
                             }
+                            xp.release();
                         }
                     }
                 }
                         }
                     }
                 }