movable guarded_ptr: SkipList
[libcds.git] / cds / container / impl / skip_list_map.h
index 303ea953133ef2a2c8244f4769d74522155f4d2d..0d31172642d871f76c4d452db7644f8f8e3c8292 100644 (file)
@@ -3,7 +3,6 @@
 #ifndef __CDS_CONTAINER_IMPL_SKIP_LIST_MAP_H
 #define __CDS_CONTAINER_IMPL_SKIP_LIST_MAP_H
 
-#include <cds/gc/guarded_ptr.h>
 #include <cds/container/details/guarded_ptr_cast.h>
 
 namespace cds { namespace container {
@@ -36,32 +35,18 @@ namespace cds { namespace container {
         - \p GC - Garbage collector used.
         - \p K - type of a key to be stored in the list.
         - \p T - type of a value to be stored in the list.
-        - \p Traits - type traits. See skip_list::type_traits for explanation.
-
-        It is possible to declare option-based list with cds::container::skip_list::make_traits metafunction istead of \p Traits template
-        argument.
-        Template argument list \p Options of cds::container::skip_list::make_traits metafunction are:
-        - opt::compare - key compare functor. No default functor is provided.
-            If the option is not specified, the opt::less is used.
-        - opt::less - specifies binary predicate used for key comparison. Default is \p std::less<K>.
-        - opt::item_counter - the type of item counting feature. Default is \ref atomicity::empty_item_counter that is no item counting.
-        - opt::memory_model - C++ memory ordering model. Can be opt::v::relaxed_ordering (relaxed memory model, the default)
-            or opt::v::sequential_consistent (sequentially consisnent memory model).
-        - skip_list::random_level_generator - random level generator. Can be skip_list::xorshift, skip_list::turbo_pascal or
-            user-provided one. See skip_list::random_level_generator option description for explanation.
-            Default is \p %skip_list::turbo_pascal.
-        - opt::allocator - allocator for skip-list node. Default is \ref CDS_DEFAULT_ALLOCATOR.
-        - opt::back_off - back-off strategy used. If the option is not specified, the cds::backoff::Default is used.
-        - opt::stat - internal statistics. Available types: skip_list::stat, skip_list::empty_stat (the default)
-
-        Like STL map class, %SkipListMap stores its key-value pair as <tt>std:pair< K const, T></tt>.
-
-        \warning The skip-list requires up to 67 hazard pointers that may be critical for some GCs for which
+        - \p Traits - map traits, default is \p skip_list::traits
+            It is possible to declare option-based list with \p cds::container::skip_list::make_traits metafunction 
+            istead of \p Traits template argument.
+
+        Like STL map class, \p %SkipListMap stores the key-value pair as <tt>std:pair< K const, T></tt>.
+
+        @warning The skip-list requires up to 67 hazard pointers that may be critical for some GCs for which
             the guard count is limited (like \p gc::HP). Those GCs should be explicitly initialized with
             hazard pointer enough: \code cds::gc::HP myhp( 67 ) \endcode. Otherwise an run-time exception may be raised
             when you try to create skip-list object.
 
-        \note There are several specializations of \p %SkipListMap for each \p GC. You should include:
+        @note There are several specializations of \p %SkipListMap for each \p GC. You should include:
         - <tt><cds/container/skip_list_map_hp.h></tt> for \p gc::HP garbage collector
         - <tt><cds/container/skip_list_map_dhp.h></tt> for \p gc::DHP garbage collector
         - <tt><cds/container/skip_list_map_rcu.h></tt> for \ref cds_nonintrusive_SkipListMap_rcu "RCU type"
@@ -81,7 +66,7 @@ namespace cds { namespace container {
         before end of the map. Therefore, such iteration is more suitable for debugging purpose only
 
         Remember, each iterator object requires 2 additional hazard pointers, that may be
-        a limited resource for \p GC like \p gc::HP (for gc::PTB the count of
+        a limited resource for \p GC like \p gc::HP (for gc::DHP the count of
         guards is unlimited).
 
         The iterator class supports the following minimalistic interface:
@@ -114,7 +99,7 @@ namespace cds { namespace container {
         typename Key,
         typename T,
 #ifdef CDS_DOXYGEN_INVOKED
-        typename Traits = skip_list::type_traits
+        typename Traits = skip_list::traits
 #else
         typename Traits
 #endif
@@ -127,27 +112,27 @@ namespace cds { namespace container {
 #endif
     {
         //@cond
-        typedef details::make_skip_list_map< GC, Key, T, Traits >    maker;
+        typedef details::make_skip_list_map< GC, Key, T, Traits > maker;
         typedef typename maker::type base_class;
         //@endcond
     public:
-        typedef typename base_class::gc          gc  ; ///< Garbage collector used
-        typedef Key     key_type    ;   ///< Key type
-        typedef T       mapped_type ;   ///< Mapped type
+        typedef GC      gc;          ///< Garbage collector
+        typedef Key     key_type;    ///< Key type
+        typedef T       mapped_type; ///< Mapped type
+        typedef Traits  traits;      ///< Map traits
 #   ifdef CDS_DOXYGEN_INVOKED
-        typedef std::pair< K const, T> value_type   ;   ///< Value type stored in the map
+        typedef std::pair< K const, T> value_type;   ///< Key-value pair to be stored in the map
 #   else
         typedef typename maker::value_type  value_type;
 #   endif
-        typedef Traits  options     ;   ///< Options specified
 
-        typedef typename base_class::back_off       back_off        ;   ///< Back-off strategy used
-        typedef typename options::allocator         allocator_type  ;   ///< Allocator type used for allocate/deallocate the skip-list nodes
-        typedef typename base_class::item_counter   item_counter    ;   ///< Item counting policy used
-        typedef typename maker::key_comparator      key_comparator  ;   ///< key comparison functor
-        typedef typename base_class::memory_model   memory_model    ;   ///< Memory ordering. See cds::opt::memory_model option
-        typedef typename options::random_level_generator random_level_generator ; ///< random level generator
-        typedef typename options::stat              stat            ;   ///< internal statistics type
+        typedef typename base_class::back_off      back_off;       ///< Back-off strategy
+        typedef typename traits::allocator         allocator_type; ///< Allocator type used for allocate/deallocate the skip-list nodes
+        typedef typename base_class::item_counter  item_counter;   ///< Item counting policy used
+        typedef typename maker::key_comparator     key_comparator; ///< key comparison functor
+        typedef typename base_class::memory_model  memory_model;   ///< Memory ordering, see \p cds::opt::memory_model
+        typedef typename traits::random_level_generator random_level_generator ; ///< random level generator
+        typedef typename traits::stat              stat;           ///< internal statistics type
 
     protected:
         //@cond
@@ -155,12 +140,11 @@ namespace cds { namespace container {
         typedef typename maker::node_allocator      node_allocator;
 
         typedef std::unique_ptr< node_type, typename maker::node_deallocator >    scoped_node_ptr;
-
         //@endcond
 
     public:
         /// Guarded pointer
-        typedef cds::gc::guarded_ptr< gc, node_type, value_type, details::guarded_ptr_cast_set<node_type, value_type> > guarded_ptr;
+        typedef typename gc::template guarded_ptr< node_type, value_type, details::guarded_ptr_cast_set<node_type, value_type> > guarded_ptr;
 
     protected:
         //@cond
@@ -194,16 +178,15 @@ namespace cds { namespace container {
         }
 
         /// Returns a forward const iterator addressing the first element in a map
-        //@{
         const_iterator begin() const
         {
             return cbegin();
         }
-        const_iterator cbegin()
+        /// Returns a forward const iterator addressing the first element in a map
+        const_iterator cbegin() const
         {
             return const_iterator( base_class::cbegin() );
         }
-        //@}
 
         /// Returns a forward iterator that addresses the location succeeding the last element in a map.
         iterator end()
@@ -212,16 +195,15 @@ namespace cds { namespace container {
         }
 
         /// Returns a forward const iterator that addresses the location succeeding the last element in a map.
-        //@{
         const_iterator end() const
         {
             return cend();
         }
-        const_iterator cend()
+        /// Returns a forward const iterator that addresses the location succeeding the last element in a map.
+        const_iterator cend() const
         {
             return const_iterator( base_class::cend() );
         }
-        //@}
 
     public:
         /// Inserts new node with key and default value
@@ -229,9 +211,9 @@ namespace cds { namespace container {
             The function creates a node with \p key and default value, and then inserts the node created into the map.
 
             Preconditions:
-            - The \ref key_type should be constructible from a value of type \p K.
-                In trivial case, \p K is equal to \ref key_type.
-            - The \ref mapped_type should be default-constructible.
+            - The \p key_type should be constructible from a value of type \p K.
+                In trivial case, \p K is equal to \p key_type.
+            - The \p mapped_type should be default-constructible.
 
             Returns \p true if inserting successful, \p false otherwise.
         */
@@ -247,8 +229,8 @@ namespace cds { namespace container {
             and then inserts the node created into the map.
 
             Preconditions:
-            - The \ref key_type should be constructible from \p key of type \p K.
-            - The \ref value_type should be constructible from \p val of type \p V.
+            - The \p key_type should be constructible from \p key of type \p K.
+            - The \p value_type should be constructible from \p val of type \p V.
 
             Returns \p true if \p val is inserted into the set, \p false otherwise.
         */
@@ -273,10 +255,7 @@ namespace cds { namespace container {
                 - <tt>item.first</tt> is a const reference to item's key that cannot be changed.
                 - <tt>item.second</tt> is a reference to item's value that may be changed.
 
-            The user-defined functor can be passed by reference using \p std::ref
-            and it is called only if inserting is successful.
-
-            The key_type should be constructible from value of type \p K.
+            \p key_type should be constructible from value of type \p K.
 
             The function allows to split creating of new item into two part:
             - create item from \p key;
@@ -297,7 +276,7 @@ namespace cds { namespace container {
             return false;
         }
 
-        /// For key \p key inserts data of type \ref value_type constructed with <tt>std::forward<Args>(args)...</tt>
+        /// For key \p key inserts data of type \p value_type created in-place from <tt>std::forward<Args>(args)...</tt>
         /**
             Returns \p true if inserting successful, \p false otherwise.
         */
@@ -337,11 +316,11 @@ namespace cds { namespace container {
 
             The functor may change any fields of the \p item.second that is \ref value_type.
 
-            You may pass \p func argument by reference using \p std::ref
-
             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
             \p second is true if new item has been added or \p false if the item with \p key
             already is in the list.
+
+            @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
         */
         template <typename K, typename Func>
         std::pair<bool, bool> ensure( K const& key, Func func )
@@ -376,6 +355,7 @@ namespace cds { namespace container {
         template <typename K, typename Less>
         bool erase_with( K const& key, Less pred )
         {
+            CDS_UNUSED( pred );
             return base_class::erase_with( key, cds::details::predicate_wrapper< node_type, Less, typename maker::key_accessor >());
         }
 
@@ -391,7 +371,6 @@ namespace cds { namespace container {
                 void operator()(value_type& item) { ... }
             };
             \endcode
-            The functor may be passed by reference using <tt>boost:ref</tt>
 
             Return \p true if key is found and deleted, \p false otherwise
         */
@@ -411,6 +390,7 @@ namespace cds { namespace container {
         template <typename K, typename Less, typename Func>
         bool erase_with( K const& key, Less pred, Func f )
         {
+            CDS_UNUSED( pred );
             return base_class::erase_with( key,
                 cds::details::predicate_wrapper< node_type, Less, typename maker::key_accessor >(),
                 [&f]( node_type& node) { f( node.m_Value ); } );
@@ -419,13 +399,13 @@ namespace cds { namespace container {
         /// Extracts the item from the map with specified \p key
         /** \anchor cds_nonintrusive_SkipListMap_hp_extract
             The function searches an item with key equal to \p key in the map,
-            unlinks it from the map, and returns it in \p ptr parameter.
-            If the item with key equal to \p key is not found the function returns \p false.
+            unlinks it from the map, and returns a guarded pointer to the item found.
+            If \p key is not found the function returns an empty guarded pointer.
 
             Note the compare functor should accept a parameter of type \p K that can be not the same as \p key_type.
 
             The item extracted is freed automatically by garbage collector \p GC
-            when returned \ref guarded_ptr object will be destroyed or released.
+            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.
 
             Usage:
@@ -434,8 +414,8 @@ namespace cds { namespace container {
             skip_list theList;
             // ...
             {
-                skip_list::guarded_ptr gp;
-                if ( theList.extract( gp, 5 ) ) {
+                skip_list::guarded_ptr gp( theList.extract( 5 ));
+                if ( gp ) {
                     // Deal with gp
                     // ...
                 }
@@ -444,9 +424,11 @@ namespace cds { namespace container {
             \endcode
         */
         template <typename K>
-        bool extract( guarded_ptr& ptr, K const& key )
+        guarded_ptr extract( K const& key )
         {
-            return base_class::extract_( ptr.guard(), key, typename base_class::key_comparator() );
+            guarded_ptr gp;
+            base_class::extract_( gp.guard(), key, typename base_class::key_comparator() );
+            return gp;
         }
 
         /// Extracts the item from the map with comparing functor \p pred
@@ -459,19 +441,22 @@ 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>
-        bool extract_with( guarded_ptr& ptr, K const& key, Less pred )
+        guarded_ptr extract_with( K const& key, Less pred )
         {
+            CDS_UNUSED( pred );
             typedef cds::details::predicate_wrapper< node_type, Less, typename maker::key_accessor >  wrapped_less;
-            return base_class::extract_( ptr.guard(), key, cds::opt::details::make_comparator_from_less<wrapped_less>() );
+            guarded_ptr gp;
+            base_class::extract_( gp.guard(), key, cds::opt::details::make_comparator_from_less<wrapped_less>() );
+            return gp;
         }
 
         /// 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 ptr parameter.
-            If the skip-list is empty the function returns \p false.
+            The function searches an item with minimal key, unlinks it, and returns an guarded pointer to the item found.
+            If the skip-list is empty the function returns an empty guarded pointer.
 
             The item extracted is freed automatically by garbage collector \p GC
-            when returned \ref guarded_ptr object will be destroyed or released.
+            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.
 
             Usage:
@@ -480,8 +465,8 @@ namespace cds { namespace container {
             skip_list theList;
             // ...
             {
-                skip_list::guarded_ptr gp;
-                if ( theList.extract_min( gp )) {
+                skip_list::guarded_ptr gp( theList.extract_min());
+                if ( gp ) {
                     // Deal with gp
                     //...
                 }
@@ -489,18 +474,20 @@ namespace cds { namespace container {
             }
             \endcode
         */
-        bool extract_min( guarded_ptr& ptr)
+        guarded_ptr extract_min()
         {
-            return base_class::extract_min_( ptr.guard() );
+            guarded_ptr gp;
+            base_class::extract_min_( gp.guard() );
+            return gp;
         }
 
         /// Extracts an item with maximal key from the map
         /**
-            The function searches an item with maximal key, unlinks it, and returns the pointer to item found in \p ptr parameter.
-            If the skip-list is empty the function returns empty \p guarded_ptr.
+            The function searches an item with maximal key, unlinks it, and returns a guarded pointer to item found.
+            If the skip-list is empty the function returns an empty \p guarded_ptr.
 
             The item found is freed by garbage collector \p GC automatically
-            when returned \ref guarded_ptr object will be destroyed or released.
+            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.
 
             Usage:
@@ -509,8 +496,8 @@ namespace cds { namespace container {
             skip_list theList;
             // ...
             {
-                skip_list::guarded_ptr gp;
-                if ( theList.extract_max( gp )) {
+                skip_list::guarded_ptr gp( theList.extract_max());
+                if ( gp ) {
                     // Deal with gp
                     //...
                 }
@@ -518,9 +505,11 @@ namespace cds { namespace container {
             }
             \endcode
         */
-        bool extract_max( guarded_ptr& dest )
+        guarded_ptr extract_max()
         {
-            return base_class::extract_max_( dest.guard() );
+            guarded_ptr gp;
+            base_class::extract_max_( gp.guard() );
+            return gp;
         }
 
         /// Find the key \p key
@@ -535,8 +524,6 @@ namespace cds { namespace container {
             \endcode
             where \p item is the item found.
 
-            You can pass \p f argument by reference using \p std::ref
-
             The functor may change \p item.second.
 
             The function returns \p true if \p key is found, \p false otherwise.
@@ -557,6 +544,7 @@ namespace cds { namespace container {
         template <typename K, typename Less, typename Func>
         bool find_with( K const& key, Less pred, Func f )
         {
+            CDS_UNUSED( pred );
             return base_class::find_with( key,
                 cds::details::predicate_wrapper< node_type, Less, typename maker::key_accessor >(),
                 [&f](node_type& item, K const& ) { f( item.m_Value );});
@@ -584,17 +572,17 @@ namespace cds { namespace container {
         template <typename K, typename Less>
         bool find_with( K const& key, Less pred )
         {
+            CDS_UNUSED( pred );
             return base_class::find_with( key, cds::details::predicate_wrapper< node_type, Less, typename maker::key_accessor >() );
         }
 
         /// Finds the key \p key and return the item found
         /** \anchor cds_nonintrusive_SkipListMap_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 the item found.
+            If \p key is not found the function returns an empty guarded pointer.
 
-            It is safe when a concurrent thread erases the item returned in \p ptr guarded pointer.
+            It is safe when a concurrent thread erases the item returned as \p guarded_ptr.
             In this case the item will be freed later by garbage collector \p GC automatically
             when \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.
@@ -605,8 +593,8 @@ namespace cds { namespace container {
             skip_list theList;
             // ...
             {
-                skip_list::guarded_ptr gp;
-                if ( theList.get( gp, 5 ) ) {
+                skip_list::guarded_ptr gp( theList.get( 5 ));
+                if ( gp ) {
                     // Deal with gp
                     //...
                 }
@@ -618,14 +606,16 @@ namespace cds { namespace container {
             should accept a parameter of type \p K that can be not the same as \p value_type.
         */
         template <typename K>
-        bool get( guarded_ptr& ptr, K const& key )
+        guarded_ptr get( K const& key )
         {
-            return base_class::get_with_( ptr.guard(), key, typename base_class::key_comparator() );
+            guarded_ptr gp;
+            base_class::get_with_( gp.guard(), key, typename base_class::key_comparator() );
+            return gp;
         }
 
         /// Finds the key \p key and return the item found
         /**
-            The function is an analog of \ref cds_nonintrusive_SkipListMap_hp_get "get( guarded_ptr& ptr, K const&)"
+            The function is an analog of \ref cds_nonintrusive_SkipListMap_hp_get "get( K 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 key_type and \p K
@@ -633,10 +623,13 @@ 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>
-        bool get_with( guarded_ptr& ptr, K const& key, Less pred )
+        guarded_ptr get_with( K const& key, Less pred )
         {
+            CDS_UNUSED( pred );
             typedef cds::details::predicate_wrapper< node_type, Less, typename maker::key_accessor > wrapped_less;
-            return base_class::get_with_( ptr.guard(), key, cds::opt::details::make_comparator_from_less< wrapped_less >());
+            guarded_ptr gp;
+            base_class::get_with_( gp.guard(), key, cds::opt::details::make_comparator_from_less< wrapped_less >());
+            return gp;
         }
 
         /// Clears the map
@@ -646,9 +639,6 @@ namespace cds { namespace container {
         }
 
         /// Checks if the map is empty
-        /**
-            Emptiness is checked by item counting: if item count is zero then the map is empty.
-        */
         bool empty() const
         {
             return base_class::empty();
@@ -665,7 +655,6 @@ namespace cds { namespace container {
         {
             return base_class::statistics();
         }
-
     };
 }} // namespace cds::container