issue#11: cds: changed __CDS_ guard prefix to CDSLIB_ for all .h files
[libcds.git] / cds / container / impl / ellen_bintree_map.h
index 028f5d65e98029bb15ec0c215ea0fca644f55901..4dd23590abfd9b6cc047933b882504711d4a9258 100644 (file)
@@ -1,12 +1,11 @@
 //$$CDS-header$$
 
-#ifndef __CDS_CONTAINER_IMPL_ELLEN_BINTREE_MAP_H
-#define __CDS_CONTAINER_IMPL_ELLEN_BINTREE_MAP_H
+#ifndef CDSLIB_CONTAINER_IMPL_ELLEN_BINTREE_MAP_H
+#define CDSLIB_CONTAINER_IMPL_ELLEN_BINTREE_MAP_H
 
 #include <type_traits>
 #include <cds/container/details/ellen_bintree_base.h>
 #include <cds/intrusive/impl/ellen_bintree.h>
-#include <cds/details/functor_wrapper.h>
 #include <cds/container/details/guarded_ptr_cast.h>
 
 namespace cds { namespace container {
@@ -35,53 +34,23 @@ namespace cds { namespace container {
         @warning Recall the tree is <b>unbalanced</b>. The complexity of operations is <tt>O(log N)</tt>
         for uniformly distributed random keys, but in worst case the complexity is <tt>O(N)</tt>.
 
-        @note In the current implementation we do not use helping technique described in original paper.
-        So, the current implementation is near to fine-grained lock-based tree.
-        Helping will be implemented in future release
+        @note In the current implementation we do not use helping technique described in the original paper.
+        In Hazard Pointer schema helping is too complicated and does not give any observable benefits.
+        Instead of helping, when a thread encounters a concurrent operation it just spins waiting for
+        the operation done. Such solution allows greatly simplify implementation of the tree.
 
         <b>Template arguments</b> :
-        - \p GC - safe memory reclamation (i.e. light-weight garbage collector) type, like cds::gc::HP, cds::gc::PTB
-            Note that cds::gc::HRC is not supported.
+        - \p GC - safe memory reclamation (i.e. light-weight garbage collector) type, like \p cds::gc::HP, \p cds::gc::DHP
         - \p Key - key type
         - \p T - value type to be stored in tree's leaf nodes.
-        - \p Traits - type traits. See ellen_bintree::type_traits for explanation.
-
-        It is possible to declare option-based tree with ellen_bintree::make_map_traits metafunction
-        instead of \p Traits template argument.
-        Template argument list \p Options of ellen_bintree::make_map_traits metafunction are:
-        - opt::compare - key compare functor. No default functor is provided.
-            If the option is not specified, \p %opt::less is used.
-        - opt::less - specifies binary predicate used for key compare. At least \p %opt::compare or \p %opt::less should be defined.
-        - 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).
-        - opt::allocator - the allocator used for \ref ellen_bintree::map_node "leaf nodes" which contains data.
-            Default is \ref CDS_DEFAULT_ALLOCATOR.
-        - opt::node_allocator - the allocator used for \ref ellen_bintree::internal_node "internal nodes".
-            Default is \ref CDS_DEFAULT_ALLOCATOR.
-        - ellen_bintree::update_desc_allocator - an allocator of \ref ellen_bintree::update_desc "update descriptors",
-            default is \ref CDS_DEFAULT_ALLOCATOR.
-            Note that update descriptor is helping data structure with short lifetime and it is good candidate for pooling.
-            The number of simultaneously existing descriptors is a relatively small number limited the number of threads
-            working with the tree and GC buffer size.
-            Therefore, a bounded lock-free container like \p cds::container::VyukovMPMCCycleQueue is good choice for the free-list
-            of update descriptors, see cds::memory::vyukov_queue_pool free-list implementation.
-            Also notice that size of update descriptor is not dependent on the type of data
-            stored in the tree so single free-list object can be used for several EllenBinTree-based object.
-        - opt::stat - internal statistics. Available types: ellen_bintree::stat, ellen_bintree::empty_stat (the default)
-        - opt::copy_policy - key copy policy defines a functor to copy leaf node's key to internal node.
-            By default, assignment operator is used.
-            The copy functor interface is:
-            \code
-            struct copy_functor {
-                void operator()( Key& dest, Key const& src );
-            };
-            \endcode
+        - \p Traits - map traits, default is \p ellen_bintree::traits
+            It is possible to declare option-based tree with \p ellen_bintree::make_map_traits metafunction
+            instead of \p Traits template argument.
 
         @note Do not include <tt><cds/container/impl/ellen_bintree_map.h></tt> header file directly.
         There are header file for each GC type:
         - <tt><cds/container/ellen_bintree_map_hp.h></tt> - for Hazard Pointer GC cds::gc::HP
-        - <tt><cds/container/ellen_bintree_map_ptb.h></tt> - for Pass-the-Buck GC cds::gc::PTB
+        - <tt><cds/container/ellen_bintree_map_dhp.h></tt> - for Dynamic Hazard Pointer GC cds::gc::DHP
         - <tt><cds/container/ellen_bintree_map_rcu.h></tt> - for RCU GC
             (see \ref cds_container_EllenBinTreeMap_rcu "RCU-based EllenBinTreeMap")
     */
@@ -90,7 +59,7 @@ namespace cds { namespace container {
         typename Key,
         typename T,
 #ifdef CDS_DOXYGEN_INVOKED
-        class Traits = ellen_bintree::type_traits
+        class Traits = ellen_bintree::traits
 #else
         class Traits
 #endif
@@ -107,26 +76,27 @@ namespace cds { namespace container {
         typedef typename maker::type base_class;
         //@endcond
     public:
-        typedef GC      gc              ;   ///< Garbage collector
-        typedef Key     key_type        ;   ///< type of a key stored in the map
-        typedef T       mapped_type      ;  ///< type of value stored in the map
+        typedef GC      gc;          ///< Garbage collector
+        typedef Key     key_type   ///< type of a key stored in the map
+        typedef T       mapped_type; ///< type of value stored in the map
         typedef std::pair< key_type const, mapped_type >    value_type  ;   ///< Key-value pair stored in leaf node of the mp
-        typedef Traits  options         ;   ///< Traits template parameter
+        typedef Traits  traits;      ///< Map traits
 
 #   ifdef CDS_DOXYGEN_INVOKED
-        typedef implementation_defined key_comparator  ;    ///< key compare functor based on opt::compare and opt::less option setter.
+        typedef implementation_defined key_comparator; ///< key compare functor based on \p Traits::compare and \p Traits::less
 #   else
-        typedef typename maker::intrusive_type_traits::compare   key_comparator;
+        typedef typename maker::intrusive_traits::compare   key_comparator;
 #   endif
-        typedef typename base_class::item_counter           item_counter        ; ///< Item counting policy used
-        typedef typename base_class::memory_model           memory_model        ; ///< Memory ordering. See cds::opt::memory_model option
-        typedef typename base_class::node_allocator         node_allocator_type ; ///< allocator for maintaining internal node
-        typedef typename base_class::stat                   stat                ; ///< internal statistics type
-        typedef typename options::copy_policy               copy_policy         ; ///< key copy policy
+        typedef typename base_class::item_counter           item_counter; ///< Item counting policy
+        typedef typename base_class::memory_model           memory_model; ///< Memory ordering, see \p cds::opt::memory_model
+        typedef typename base_class::node_allocator         node_allocator_type; ///< allocator for maintaining internal node
+        typedef typename base_class::stat                   stat;         ///< internal statistics type
+        typedef typename traits::copy_policy                copy_policy;  ///< key copy policy
+        typedef typename traits::back_off                   back_off;      ///< Back-off strategy
 
-        typedef typename options::allocator                 allocator_type      ;   ///< Allocator for leaf nodes
-        typedef typename base_class::node_allocator         node_allocator      ;   ///< Internal node allocator
-        typedef typename base_class::update_desc_allocator  update_desc_allocator ; ///< Update descriptor allocator
+        typedef typename traits::allocator                  allocator_type;   ///< Allocator for leaf nodes
+        typedef typename base_class::node_allocator         node_allocator;   ///< Internal node allocator
+        typedef typename base_class::update_desc_allocator  update_desc_allocator; ///< Update descriptor allocator
 
     protected:
         //@cond
@@ -141,15 +111,13 @@ namespace cds { namespace container {
 
     public:
         /// Guarded pointer
-        typedef cds::gc::guarded_ptr< gc, leaf_node, value_type, details::guarded_ptr_cast_set<leaf_node, value_type> > guarded_ptr;
+        typedef typename gc::template guarded_ptr< leaf_node, value_type, details::guarded_ptr_cast_set<leaf_node, value_type> > guarded_ptr;
 
     public:
         /// Default constructor
         EllenBinTreeMap()
             : base_class()
-        {
-            //static_assert( (std::is_same<gc, cds::gc::HP>::value || std::is_same<gc, cds::gc::PTB>::value), "GC must be cds::gc::HP or cds:gc::PTB" );
-        }
+        {}
 
         /// Clears the map
         ~EllenBinTreeMap()
@@ -169,7 +137,7 @@ namespace cds { namespace container {
         template <typename K>
         bool insert( K const& key )
         {
-            return insert_key( key, [](value_type&){} );
+            return insert_with( key, [](value_type&){} );
         }
 
         /// Inserts new node
@@ -178,8 +146,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 map, \p false otherwise.
         */
@@ -210,9 +178,6 @@ 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 <tt>boost::ref</tt>
-            and it is called only if inserting is successful.
-
             The key_type should be constructible from value of type \p K.
 
             The function allows to split creating of new item into two part:
@@ -224,17 +189,17 @@ namespace cds { namespace container {
             it is preferable that the initialization should be completed only if inserting is successful.
         */
         template <typename K, typename Func>
-        bool insert_key( const K& key, Func func )
+        bool insert_with( const K& key, Func func )
         {
             scoped_node_ptr pNode( cxx_leaf_node_allocator().New( key ));
-            if ( base_class::insert( *pNode, [&func]( leaf_node& item ) { cds::unref(func)( item.m_Value ); } )) {
+            if ( base_class::insert( *pNode, [&func]( leaf_node& item ) { func( item.m_Value ); } )) {
                 pNode.release();
                 return true;
             }
             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 \p args
         /**
             Returns \p true if inserting successful, \p false otherwise.
         */
@@ -274,18 +239,18 @@ 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 <tt>boost::ref</tt>.
-
             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 )
         {
             scoped_node_ptr pNode( cxx_leaf_node_allocator().New( key ));
             std::pair<bool, bool> res = base_class::ensure( *pNode,
-                [&func](bool bNew, leaf_node& item, leaf_node const& ){ cds::unref(func)( bNew, item.m_Value ); }
+                [&func](bool bNew, leaf_node& item, leaf_node const& ){ func( bNew, item.m_Value ); }
             );
             if ( res.first && res.second )
                 pNode.release();
@@ -313,6 +278,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< leaf_node, Less, typename maker::key_accessor >());
         }
 
@@ -328,14 +294,13 @@ 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
         */
         template <typename K, typename Func>
         bool erase( K const& key, Func f )
         {
-            return base_class::erase( key, [&f]( leaf_node& node) { cds::unref(f)( node.m_Value ); } );
+            return base_class::erase( key, [&f]( leaf_node& node) { f( node.m_Value ); } );
         }
 
         /// Deletes the item from the map using \p pred predicate for searching
@@ -348,76 +313,86 @@ 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< leaf_node, Less, typename maker::key_accessor >(),
-                [&f]( leaf_node& node) { cds::unref(f)( node.m_Value ); } );
+                [&f]( leaf_node& node) { f( node.m_Value ); } );
         }
 
         /// Extracts an item with minimal key from the map
         /**
-            If the map is not empty, the function returns \p true, \p result contains a pointer to minimum value.
-            If the map is empty, the function returns \p false, \p result is left unchanged.
+            If the map is not empty, the function returns an guarded pointer to minimum value.
+            If the map is empty, the function returns an empty \p guarded_ptr.
 
             @note Due the concurrent nature of the map, the function extracts <i>nearly</i> minimum key.
             It means that the function gets leftmost leaf of the tree and tries to unlink it.
             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 tree traversing.
 
-            The guarded pointer \p result prevents deallocation of returned item,
-            see cds::gc::guarded_ptr for explanation.
+            The guarded pointer prevents deallocation of returned item,
+            see \p cds::gc::guarded_ptr for explanation.
             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
         */
-        bool extract_min( guarded_ptr& result )
+        guarded_ptr extract_min()
         {
-            return base_class::extract_min_( result.guard() );
+            guarded_ptr gp;
+            base_class::extract_min_( gp.guard() );
+            return gp;
         }
 
         /// Extracts an item with maximal key from the map
         /**
-            If the map is not empty, the function returns \p true, \p result contains a pointer to maximal value.
-            If the map is empty, the function returns \p false, \p result is left unchanged.
+            If the map is not empty, the function returns a guarded pointer to maximal value.
+            If the map is empty, the function returns an empty \p guarded_ptr.
 
             @note Due the concurrent nature of the map, the function extracts <i>nearly</i> maximal key.
             It means that the function gets rightmost leaf of the tree and tries to unlink it.
             During unlinking, a concurrent thread may insert an item with key great than leftmost item's key.
             So, the function returns the item with maximum key at the moment of tree traversing.
 
-            The guarded pointer \p result prevents deallocation of returned item,
-            see cds::gc::guarded_ptr for explanation.
+            The guarded pointer prevents deallocation of returned item,
+            see \p cds::gc::guarded_ptr for explanation.
             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
         */
-        bool extract_max( guarded_ptr& result )
+        guarded_ptr extract_max()
         {
-            return base_class::extract_max_( result.guard() );
+            guarded_ptr gp;
+            base_class::extract_max_( gp.guard() );
+            return gp;
         }
 
         /// Extracts an item from the tree
         /** \anchor cds_nonintrusive_EllenBinTreeMap_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  is not found the function returns \p false.
+            unlinks it, and returns a guarded pointer to an item found.
+            If the item  is not found the function returns an empty \p guarded_ptr.
 
-            The guarded pointer \p result prevents deallocation of returned item,
-            see cds::gc::guarded_ptr for explanation.
+            The guarded pointer prevents deallocation of returned item,
+            see \p cds::gc::guarded_ptr for explanation.
             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
         */
         template <typename Q>
-        bool extract( guarded_ptr& result, Q const& key )
+        guarded_ptr extract( Q const& key )
         {
-            return base_class::extract_( result.guard(), key );
+            guarded_ptr gp;
+            base_class::extract_( gp.guard(), key );
+            return gp;
         }
 
         /// Extracts an item from the map using \p pred for searching
         /**
-            The function is an analog of \ref cds_nonintrusive_EllenBinTreeMap_extract "extract(guarded_ptr&, Q const&)"
+            The function is an analog of \ref cds_nonintrusive_EllenBinTreeMap_extract "extract(Q const&)"
             but \p pred is used for key compare.
             \p Less has the interface like \p std::less.
             \p pred must imply the same element order as the comparator used for building the map.
         */
         template <typename Q, typename Less>
-        bool extract_with( guarded_ptr& result, Q const& key, Less pred )
+        guarded_ptr extract_with( Q const& key, Less pred )
         {
-            return base_class::extract_with_( result.guard(), key,
+            CDS_UNUSED( pred );
+            guarded_ptr gp;
+            base_class::extract_with_( gp.guard(), key,
                 cds::details::predicate_wrapper< leaf_node, Less, typename maker::key_accessor >());
+            return gp;
         }
 
         /// Find the key \p key
@@ -432,8 +407,6 @@ namespace cds { namespace container {
             \endcode
             where \p item is the item found.
 
-            You can pass \p f argument by reference using <tt>boost::ref</tt> or cds::ref.
-
             The functor may change \p item.second.
 
             The function returns \p true if \p key is found, \p false otherwise.
@@ -441,7 +414,7 @@ namespace cds { namespace container {
         template <typename K, typename Func>
         bool find( K const& key, Func f )
         {
-            return base_class::find( key, [&f](leaf_node& item, K const& ) { cds::unref(f)( item.m_Value );});
+            return base_class::find( key, [&f](leaf_node& item, K const& ) { f( item.m_Value );});
         }
 
         /// Finds the key \p val using \p pred predicate for searching
@@ -454,8 +427,9 @@ 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< leaf_node, Less, typename maker::key_accessor >(),
-                [&f](leaf_node& item, K const& ) { cds::unref(f)( item.m_Value );});
+                [&f](leaf_node& item, K const& ) { f( item.m_Value );});
         }
 
         /// Find the key \p key
@@ -480,39 +454,45 @@ 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< leaf_node, Less, typename maker::key_accessor >() );
         }
 
         /// Finds \p key and returns the item found
         /** @anchor cds_nonintrusive_EllenBinTreeMap_get
-            The function searches the item with key equal to \p key and returns the item found in \p result parameter.
-            The function returns \p true if \p key is found, \p false otherwise.
+            The function searches the item with key equal to \p key and returns the item found as a guarded pointer.
+            If \p key is not foudn the function returns an empty \p guarded_ptr.
 
-            The guarded pointer \p result prevents deallocation of returned item,
-            see cds::gc::guarded_ptr for explanation.
+            The guarded pointer prevents deallocation of returned item,
+            see \p cds::gc::guarded_ptr for explanation.
             @note Each \p guarded_ptr object uses the GC's guard that can be limited resource.
         */
         template <typename Q>
-        bool get( guarded_ptr& result, Q const& key )
+        guarded_ptr get( Q const& key )
         {
-            return base_class::get_( result.guard(), key );
+            guarded_ptr gp;
+            base_class::get_( gp.guard(), key );
+            return gp;
         }
 
         /// Finds \p key with predicate \p pred and returns the item found
         /**
-            The function is an analog of \ref cds_nonintrusive_EllenBinTreeMap_get "get(guarded_ptr&, Q const&)"
+            The function is an analog of \ref cds_nonintrusive_EllenBinTreeMap_get "get(Q const&)"
             but \p pred is used for key comparing.
             \p Less functor has the interface like \p std::less.
             \p pred must imply the same element order as the comparator used for building the map.
         */
         template <typename Q, typename Less>
-        bool get_with( guarded_ptr& result, Q const& key, Less pred )
+        guarded_ptr get_with( Q const& key, Less pred )
         {
-            return base_class::get_with_( result.guard(), key,
+            CDS_UNUSED( pred );
+            guarded_ptr gp;
+            base_class::get_with_( gp.guard(), key,
                 cds::details::predicate_wrapper< leaf_node, Less, typename maker::key_accessor >() );
+            return gp;
         }
 
-        /// Clears the map
+        /// Clears the map (not atomic)
         void clear()
         {
             base_class::clear();
@@ -527,7 +507,16 @@ namespace cds { namespace container {
             return base_class::empty();
         }
 
-        /// Returns item count in the map
+        /// Returns item count in the set
+        /**
+            Only leaf nodes containing user data are counted.
+
+            The value returned depends on item counter type provided by \p Traits template parameter.
+            If it is \p atomicity::empty_item_counter this function always returns 0.
+
+            The function is not suitable for checking the tree emptiness, use \p empty()
+            member function for this purpose.
+        */
         size_t size() const
         {
             return base_class::size();
@@ -551,4 +540,4 @@ namespace cds { namespace container {
     };
 }} // namespace cds::container
 
-#endif //#ifndef __CDS_CONTAINER_IMPL_ELLEN_BINTREE_MAP_H
+#endif //#ifndef CDSLIB_CONTAINER_IMPL_ELLEN_BINTREE_MAP_H