add find(Q const&, Func), find_with(Q const&, Pred, Func) to all sets
[libcds.git] / cds / intrusive / ellen_bintree_rcu.h
index 79b9e751c323e86fc3ab7e565a9df3d4b4e021e7..20ec705d19ad14eb26e40649fdb6206aa3bdc93a 100644 (file)
@@ -436,6 +436,7 @@ namespace cds { namespace intrusive {
         typedef typename hook::node_type node_type; ///< node type
 
         typedef typename traits::disposer disposer;   ///< leaf node disposer
+        typedef typename traits::back_off back_off;   ///< back-off strategy
 
     protected:
         //@cond
@@ -447,7 +448,7 @@ namespace cds { namespace intrusive {
         //@endcond
 
     public:
-        typedef cds::urcu::exempt_ptr< gc, value_type, value_type, disposer, void > exempt_ptr; ///< pointer to extracted node
+        using exempt_ptr = cds::urcu::exempt_ptr< gc, value_type, value_type, disposer, void >; ///< pointer to extracted node
 
     public:
 #   ifdef CDS_DOXYGEN_INVOKED
@@ -734,6 +735,7 @@ namespace cds { namespace intrusive {
 
             unique_internal_node_ptr pNewInternal;
             retired_list updRetire;
+            back_off bkoff;
 
             {
                 rcu_lock l;
@@ -760,6 +762,7 @@ namespace cds { namespace intrusive {
                         }
                     }
 
+                    bkoff();
                     m_Stat.onInsertRetry();
                 }
             }
@@ -805,6 +808,7 @@ namespace cds { namespace intrusive {
 
             unique_internal_node_ptr pNewInternal;
             retired_list updRetire;
+            back_off bkoff;
 
             {
                 rcu_lock l;
@@ -831,6 +835,8 @@ namespace cds { namespace intrusive {
                             break;
                         }
                     }
+
+                    bkoff();
                     m_Stat.onEnsureRetry();
                 }
             }
@@ -959,8 +965,9 @@ namespace cds { namespace intrusive {
 
         /// Extracts an item with minimal key from the tree
         /**
-            The function searches an item with minimal key, unlinks it, and returns pointer to an item found in \p result parameter.
-            If the tree 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 leftmost item.
+            If the tree is empty the function returns empty \p exempt_ptr.
 
             @note Due the concurrent nature of the tree, the function extracts <i>nearly</i> minimum key.
             It means that the function gets leftmost leaf of the tree and tries to unlink it.
@@ -969,19 +976,19 @@ namespace cds { namespace intrusive {
 
             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.
         */
-        bool extract_min(exempt_ptr& result)
+        exempt_ptr extract_min()
         {
-            return extract_min_(result);
+            return exempt_ptr( extract_min_() );
         }
 
         /// Extracts an item with maximal key from the tree
         /**
-            The function searches an item with maximal key, unlinks it, and returns pointer to an item found in \p result prameter.
-            If the tree 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 rightmost item.
+            If the tree is empty the function returns empty \p exempt_ptr.
 
             @note Due the concurrent nature of the tree, the function extracts <i>nearly</i> maximal key.
             It means that the function gets rightmost leaf of the tree and tries to unlink it.
@@ -990,31 +997,29 @@ namespace cds { namespace intrusive {
 
             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.
         */
-        bool extract_max(exempt_ptr& result)
+        exempt_ptr extract_max()
         {
-            return extract_max_(result);
+            return exempt_ptr( extract_max_() );
         }
 
         /// Extracts an item from the tree
         /** \anchor cds_intrusive_EllenBinTree_rcu_extract
             The function searches an item with key equal to \p key in the tree,
-            unlinks it, and returns pointer to an item found in \p result parameter.
-            If the item with the key equal to \p key is not found the function returns \p false.
+            unlinks it, and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to an item found.
+            If the item with the key equal to \p key is not found the function returns 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.
-            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.
         */
         template <typename Q>
-        bool extract( exempt_ptr& result, Q const& key )
+        exempt_ptr extract( Q const& key )
         {
-            return extract_( result, key, node_compare() );
+            return exempt_ptr( extract_( key, node_compare() ));
         }
 
         /// Extracts an item from the set using \p pred for searching
@@ -1026,9 +1031,9 @@ namespace cds { namespace intrusive {
             \p pred must imply the same element order as the comparator used for building the tree.
         */
         template <typename Q, typename Less>
-        bool extract_with( exempt_ptr& dest,  Q const& key, Less pred )
+        exempt_ptr extract_with( Q const& key, Less pred )
         {
-            return extract_with_( dest, key, pred );
+            return exempt_ptr( extract_with_( key, pred ));
         }
 
         /// Finds the key \p key
@@ -1197,8 +1202,7 @@ namespace cds { namespace intrusive {
         */
         void clear()
         {
-            exempt_ptr ep;
-            while ( extract_min(ep) )
+            for ( exempt_ptr ep = extract_min(); !ep.empty(); ep = extract_min() )
                 ep.release();
         }
 
@@ -1577,6 +1581,7 @@ namespace cds { namespace intrusive {
             retired_list updRetire;
             update_desc * pOp = nullptr;
             search_result res;
+            back_off bkoff;
 
             {
                 rcu_lock l;
@@ -1622,6 +1627,7 @@ namespace cds { namespace intrusive {
                         }
                     }
 
+                    bkoff();
                     m_Stat.onEraseRetry();
                 }
             }
@@ -1631,8 +1637,8 @@ namespace cds { namespace intrusive {
             return true;
         }
 
-        template <typename ExemptPtr, typename Q, typename Less>
-        bool extract_with_( ExemptPtr& dest,  Q const& val, Less pred )
+        template <typename Q, typename Less>
+        value_type * extract_with_( Q const& val, Less pred )
         {
             typedef ellen_bintree::details::compare<
                 key_type,
@@ -1641,17 +1647,19 @@ namespace cds { namespace intrusive {
                 node_traits
             > compare_functor;
 
-            return extract_( dest, val, compare_functor() );
+            return extract_( val, compare_functor() );
         }
 
-        template <typename ExemptPtr, typename Q, typename Compare>
-        bool extract_( ExemptPtr& ptr, Q const& val, Compare cmp )
+        template <typename Q, typename Compare>
+        value_type * extract_( Q const& val, Compare cmp )
         {
             check_deadlock_policy::check();
 
             retired_list updRetire;
             update_desc * pOp = nullptr;
             search_result res;
+            back_off bkoff;
+            value_type * pResult;
 
             {
                 rcu_lock l;
@@ -1660,7 +1668,7 @@ namespace cds { namespace intrusive {
                         if ( pOp )
                             retire_update_desc( pOp, updRetire, false );
                         m_Stat.onEraseFailed();
-                        return false;
+                        return nullptr;
                     }
 
                     if ( res.updGrandParent.bits() != update_desc::Clean )
@@ -1684,7 +1692,7 @@ namespace cds { namespace intrusive {
                                 memory_model::memory_order_acquire, atomics::memory_order_relaxed ))
                             {
                                 if ( help_delete( pOp, updRetire )) {
-                                    ptr = node_traits::to_value_ptr( res.pLeaf );
+                                    pResult = node_traits::to_value_ptr( res.pLeaf );
                                     break;
                                 }
                                 pOp = nullptr;
@@ -1696,24 +1704,26 @@ namespace cds { namespace intrusive {
                         }
                     }
 
+                    bkoff();
                     m_Stat.onEraseRetry();
                 }
             }
 
             --m_ItemCounter;
             m_Stat.onEraseSuccess();
-            return true;
+            return pResult;
         }
 
 
-        template <typename ExemptPtr>
-        bool extract_max_( ExemptPtr& result )
+        value_type * extract_max_()
         {
             check_deadlock_policy::check();
 
             retired_list updRetire;
             update_desc * pOp = nullptr;
             search_result res;
+            back_off bkoff;
+            value_type * pResult;
 
             {
                 rcu_lock l;
@@ -1723,7 +1733,7 @@ namespace cds { namespace intrusive {
                         if ( pOp )
                             retire_update_desc( pOp, updRetire, false );
                         m_Stat.onExtractMaxFailed();
-                        return false;
+                        return nullptr;
                     }
 
                     if ( res.updGrandParent.bits() != update_desc::Clean )
@@ -1747,7 +1757,7 @@ namespace cds { namespace intrusive {
                                 memory_model::memory_order_acquire, atomics::memory_order_relaxed ))
                             {
                                 if ( help_delete( pOp, updRetire )) {
-                                    result = node_traits::to_value_ptr( res.pLeaf );
+                                    pResult = node_traits::to_value_ptr( res.pLeaf );
                                     break;
                                 }
                                 pOp = nullptr;
@@ -1758,23 +1768,26 @@ namespace cds { namespace intrusive {
                             }
                         }
                     }
+
+                    bkoff();
                     m_Stat.onExtractMaxRetry();
                 }
             }
 
             --m_ItemCounter;
             m_Stat.onExtractMaxSuccess();
-            return true;
+            return pResult;
         }
 
-        template <typename ExemptPtr>
-        bool extract_min_(ExemptPtr& result)
+        value_type * extract_min_()
         {
             check_deadlock_policy::check();
 
             retired_list updRetire;
             update_desc * pOp = nullptr;
             search_result res;
+            back_off bkoff;
+            value_type * pResult;
 
             {
                 rcu_lock l;
@@ -1784,7 +1797,7 @@ namespace cds { namespace intrusive {
                         if ( pOp )
                             retire_update_desc( pOp, updRetire, false );
                         m_Stat.onExtractMinFailed();
-                        return false;
+                        return nullptr;
                     }
 
                     if ( res.updGrandParent.bits() != update_desc::Clean )
@@ -1808,7 +1821,7 @@ namespace cds { namespace intrusive {
                                 memory_model::memory_order_acquire, atomics::memory_order_relaxed ))
                             {
                                 if ( help_delete( pOp, updRetire )) {
-                                    result = node_traits::to_value_ptr( res.pLeaf );
+                                    pResult = node_traits::to_value_ptr( res.pLeaf );
                                     break;
                                 }
                                 pOp = nullptr;
@@ -1820,13 +1833,14 @@ namespace cds { namespace intrusive {
                         }
                     }
 
+                    bkoff();
                     m_Stat.onExtractMinRetry();
                 }
             }
 
             --m_ItemCounter;
             m_Stat.onExtractMinSuccess();
-            return true;
+            return pResult;
         }
 
         template <typename Q, typename Less, typename Func>