movable guarded_ptr: LazyList, MichaelList
[libcds.git] / cds / intrusive / impl / lazy_list.h
index fd19d277f7cd9f6c4b3267a8103da46edbcd6e47..f2c9eaf6a7a75927401c1afece810ca7035a4697 100644 (file)
@@ -5,7 +5,6 @@
 
 #include <mutex>        // unique_lock
 #include <cds/intrusive/details/lazy_list_base.h>
-#include <cds/gc/guarded_ptr.h>
 
 namespace cds { namespace intrusive {
 
@@ -29,7 +28,7 @@ namespace cds { namespace intrusive {
         - \p GC - Garbage collector used. Note the \p GC must be the same as the GC used for item type \p T (see lazy_list::node).
         - \p T - type to be stored in the list. The type must be based on lazy_list::node (for lazy_list::base_hook)
             or it must have a member of type lazy_list::node (for lazy_list::member_hook).
-        - \p Traits - type traits. See lazy_list::traits for explanation. 
+        - \p Traits - type traits. See lazy_list::traits for explanation.
             It is possible to declare option-based list with cds::intrusive::lazy_list::make_traits metafunction istead of \p Traits template
             argument. For example, the following traits-based declaration of \p gc::HP lazy list
             \code
@@ -178,12 +177,12 @@ namespace cds { namespace intrusive {
         typedef typename traits::item_counter item_counter ;   ///< Item counting policy used
         typedef typename traits::memory_model  memory_model;   ///< C++ memory ordering (see \p lazy_list::traits::memory_model)
 
-        typedef cds::gc::guarded_ptr< gc, value_type > guarded_ptr; ///< Guarded pointer
+        typedef typename gc::template guarded_ptr< value_type > guarded_ptr; ///< Guarded pointer
 
         //@cond
         // Rebind traits (split-list support)
         template <typename... Options>
-        struct rebind_options {
+        struct rebind_traits {
             typedef LazyList<
                 gc
                 , value_type
@@ -443,7 +442,7 @@ namespace cds { namespace intrusive {
         {
             return get_const_begin();
         }
-        const_iterator cbegin()
+        const_iterator cbegin() const
         {
             return get_const_begin();
         }
@@ -455,7 +454,7 @@ namespace cds { namespace intrusive {
         {
             return get_const_end();
         }
-        const_iterator cend()
+        const_iterator cend() const
         {
             return get_const_end();
         }
@@ -517,7 +516,8 @@ namespace cds { namespace intrusive {
                 void func( value_type& val );
             \endcode
             where \p val is the item inserted.
-            While the functor \p f is working the item \p val is locked.
+            While the functor \p f is called the item \p val is locked so
+            the functor has an exclusive access to the item.
             The user-defined functor is called only if the inserting is success.
         */
         template <typename Func>
@@ -544,7 +544,8 @@ namespace cds { namespace intrusive {
             refer to the same thing.
 
             The functor may change non-key fields of the \p item.
-            While the functor \p f is working the item \p item is locked.
+            While the functor \p f is working the item \p item is locked,
+            so \p f has exclusive access to the item.
 
             Returns std::pair<bool, bool> where \p first is \p true if operation is successfull,
             \p second is \p true if new item has been added or \p false if the item with \p key
@@ -633,13 +634,13 @@ namespace cds { namespace intrusive {
         /// Extracts the item from the list with specified \p key
         /** \anchor cds_intrusive_LazyList_hp_extract
             The function searches an item with key equal to \p key,
-            unlinks it from the list, and returns it in \p dest parameter.
-            If the item with key equal to \p key is not found the function returns \p false.
+            unlinks it from the list, and returns it as \p guarded_ptr.
+            If \p key is not found the function returns an empty guarded pointer.
 
             Note the compare functor should accept a parameter of type \p Q that can be not the same as \p value_type.
 
             The \ref disposer specified in \p Traits class template parameter is called automatically
-            by garbage collector \p GC specified in class' template parameters when returned \ref guarded_ptr object
+            by garbage collector \p GC specified in class' template parameters when returned \p guarded_ptr object
             will be destroyed or released.
             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
 
@@ -649,8 +650,7 @@ namespace cds { namespace intrusive {
             ord_list theList;
             // ...
             {
-                ord_list::guarded_ptr gp;
-                theList.extract( gp, 5 );
+                ord_list::guarded_ptr gp( theList.extract( 5 ));
                 // Deal with gp
                 // ...
 
@@ -659,14 +659,16 @@ namespace cds { namespace intrusive {
             \endcode
         */
         template <typename Q>
-        bool extract( guarded_ptr& dest, Q const& key )
+        guarded_ptr extract( Q const& key )
         {
-            return extract_at( &m_Head, dest.guard(), key, key_comparator() );
+            guarded_ptr gp;
+            extract_at( &m_Head, gp.guard(), key, key_comparator() );
+            return gp;
         }
 
         /// Extracts the item from the list with comparing functor \p pred
         /**
-            The function is an analog of \ref cds_intrusive_LazyList_hp_extract "extract(guarded_ptr&, Q const&)"
+            The function is an analog of \ref cds_intrusive_LazyList_hp_extract "extract(Q const&)"
             but \p pred predicate is used for key comparing.
 
             \p Less functor has the semantics like \p std::less but should take arguments of type \ref value_type and \p Q
@@ -674,9 +676,11 @@ namespace cds { namespace intrusive {
             \p pred must imply the same element order as the comparator used for building the list.
         */
         template <typename Q, typename Less>
-        bool extract_with( guarded_ptr& dest, Q const& key, Less pred )
+        guarded_ptr extract_with( Q const& key, Less pred )
         {
-            return extract_at( &m_Head, dest.guard(), key, cds::opt::details::make_comparator_from_less<Less>() );
+            guarded_ptr gp;
+            extract_at( &m_Head, gp.guard(), key, cds::opt::details::make_comparator_from_less<Less>() );
+            return gp;
         }
 
         /// Finds the key \p key
@@ -700,6 +704,13 @@ namespace cds { namespace intrusive {
         {
             return find_at( &m_Head, key, key_comparator(), f );
         }
+        //@cond
+        template <typename Q, typename Func>
+        bool find( Q const& key, Func f )
+        {
+            return find_at( &m_Head, key, key_comparator(), f );
+        }
+        //@endcond
 
         /// Finds the key \p key using \p pred predicate for searching
         /**
@@ -713,6 +724,13 @@ namespace cds { namespace intrusive {
         {
             return find_at( &m_Head, key, cds::opt::details::make_comparator_from_less<Less>(), f );
         }
+        //@cond
+        template <typename Q, typename Less, typename Func>
+        bool find_with( Q const& key, Less pred, Func f )
+        {
+            return find_at( &m_Head, key, cds::opt::details::make_comparator_from_less<Less>(), f );
+        }
+        //@endcond
 
         /// Finds the key \p key
         /** \anchor cds_intrusive_LazyList_hp_find_val
@@ -720,7 +738,7 @@ namespace cds { namespace intrusive {
             and returns \p true if it is found, and \p false otherwise
         */
         template <typename Q>
-        bool find( Q const & key )
+        bool find( Q const& key )
         {
             return find_at( &m_Head, key, key_comparator() );
         }
@@ -741,12 +759,11 @@ namespace cds { namespace intrusive {
         /// Finds \p key and return the item found
         /** \anchor cds_intrusive_LazyList_hp_get
             The function searches the item with key equal to \p key
-            and assigns the item found to guarded pointer \p ptr.
-            The function returns \p true if \p key is found, and \p false otherwise.
-            If \p key is not found the \p ptr parameter is not changed.
+            and returns an guarded pointer to it.
+            If \p key is not found the function returns an empty guarded pointer.
 
             The \ref disposer specified in \p Traits class template parameter is called
-            by garbage collector \p GC automatically when returned \ref guarded_ptr object
+            by garbage collector \p GC automatically when returned \p guarded_ptr object
             will be destroyed or released.
             @note Each \p guarded_ptr object uses one GC's guard which can be limited resource.
 
@@ -756,8 +773,8 @@ namespace cds { namespace intrusive {
             ord_list theList;
             // ...
             {
-                ord_list::guarded_ptr gp;
-                if ( theList.get( gp, 5 )) {
+                ord_list::guarded_ptr gp(theList.get( 5 ));
+                if ( gp ) {
                     // Deal with gp
                     //...
                 }
@@ -769,14 +786,16 @@ namespace cds { namespace intrusive {
             should accept a parameter of type \p Q that can be not the same as \p value_type.
         */
         template <typename Q>
-        bool get( guarded_ptr& ptr, Q const& key )
+        guarded_ptr get( Q const& key )
         {
-            return get_at( &m_Head, ptr.guard(), key, key_comparator() );
+            guarded_ptr gp;
+            get_at( &m_Head, gp.guard(), key, key_comparator() );
+            return gp;
         }
 
         /// Finds \p key and return the item found
         /**
-            The function is an analog of \ref cds_intrusive_LazyList_hp_get "get( guarded_ptr& ptr, Q const&)"
+            The function is an analog of \ref cds_intrusive_LazyList_hp_get "get( Q const&)"
             but \p pred is used for comparing the keys.
 
             \p Less functor has the semantics like \p std::less but should take arguments of type \ref value_type and \p Q
@@ -784,9 +803,11 @@ namespace cds { namespace intrusive {
             \p pred must imply the same element order as the comparator used for building the list.
         */
         template <typename Q, typename Less>
-        bool get_with( guarded_ptr& ptr, Q const& key, Less pred )
+        guarded_ptr get_with( Q const& key, Less pred )
         {
-            return get_at( &m_Head, ptr.guard(), key, cds::opt::details::make_comparator_from_less<Less>() );
+            guarded_ptr gp;
+            get_at( &m_Head, gp.guard(), key, cds::opt::details::make_comparator_from_less<Less>() );
+            return gp;
         }
 
         /// Clears the list
@@ -1016,11 +1037,11 @@ namespace cds { namespace intrusive {
         }
 
         template <typename Q, typename Compare>
-        bool extract_at( node_type * pHead, typename gc::Guard& gp, const Q& val, Compare cmp )
+        bool extract_at( node_type * pHead, typename guarded_ptr::native_guard& gp, const Q& val, Compare cmp )
         {
             position pos;
             if ( erase_at( pHead, val, cmp, [](value_type const &){}, pos )) {
-                gp.assign( pos.guards.template get<value_type>(position::guard_current_item) );
+                gp.set( pos.guards.template get<value_type>(position::guard_current_item) );
                 return true;
             }
             return false;
@@ -1056,7 +1077,7 @@ namespace cds { namespace intrusive {
         }
 
         template <typename Q, typename Compare>
-        bool get_at( node_type * pHead, typename gc::Guard& gp, Q const& val, Compare cmp )
+        bool get_at( node_type * pHead, typename guarded_ptr::native_guard& gp, Q const& val, Compare cmp )
         {
             position pos;
 
@@ -1065,7 +1086,7 @@ namespace cds { namespace intrusive {
                 && !pos.pCur->is_marked()
                 && cmp( *node_traits::to_value_ptr( *pos.pCur ), val ) == 0 )
             {
-                gp.assign( pos.guards.template get<value_type>( position::guard_current_item ));
+                gp.set( pos.guards.template get<value_type>( position::guard_current_item ));
                 return true;
             }
             return false;