Fixed Clang 3.7 + libc++ issues
[libcds.git] / cds / container / bronson_avltree_map_rcu.h
index 532877ef159b742701ed6a4c3db93514c1021eb3..be36d86d0f9b71b425c474704f1163660af6ecc6 100644 (file)
@@ -1,8 +1,37 @@
-//$$CDS-header$$
+/*
+    This file is a part of libcds - Concurrent Data Structures library
+
+    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
+
+    Source code repo: http://github.com/khizmax/libcds/
+    Download: http://sourceforge.net/projects/libcds/files/
+    
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice, this
+      list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.     
+*/
 
 #ifndef CDSLIB_CONTAINER_BRONSON_AVLTREE_MAP_RCU_H
 #define CDSLIB_CONTAINER_BRONSON_AVLTREE_MAP_RCU_H
 
 
 #ifndef CDSLIB_CONTAINER_BRONSON_AVLTREE_MAP_RCU_H
 #define CDSLIB_CONTAINER_BRONSON_AVLTREE_MAP_RCU_H
 
+#include <functional>
 #include <cds/container/impl/bronson_avltree_map_rcu.h>
 
 namespace cds { namespace container {
 #include <cds/container/impl/bronson_avltree_map_rcu.h>
 
 namespace cds { namespace container {
@@ -43,8 +72,25 @@ namespace cds { namespace container {
 
         Source:
             - [2010] N.Bronson, J.Casper, H.Chafi, K.Olukotun "A Practical Concurrent Binary Search Tree"
 
         Source:
             - [2010] N.Bronson, J.Casper, H.Chafi, K.Olukotun "A Practical Concurrent Binary Search Tree"
-
-        bla-bla-bla
+            - <a href="http://github.com/nbronson/snaptree">Java implementation</a>
+
+        This is a concurrent AVL tree algorithm that uses hand-over-hand optimistic validation,
+        a concurrency control mechanism for searching and navigating a binary search tree.
+        This mechanism minimizes spurious retries when concurrent structural changes cannot
+        affect the correctness of the search or navigation result.
+        The algorithm is based on partially external trees, a simple scheme that simplifies deletions
+        by leaving a routing node in the tree when deleting a node that has two children,
+        then opportunistically unlinking routing nodes during rebalancing. As in external trees,
+        which store values only in leaf nodes, deletions can be performed locally while holding
+        a fixed number of locks. Partially external trees, however, require far fewer routing nodes
+        than an external tree for most sequences of insertions and deletions.
+        The algorithm uses optimistic concurrency control, but carefully manage the
+        tree in such a way that all atomic regions have fixed read and write sets
+        that are known ahead of time. This allows to reduce practical overheads by embedding
+        the concurrency control directly. To perform tree operations using only fixed sized
+        atomic regions the algo uses the following mechanisms: search operations overlap atomic blocks as
+        in the hand-over-hand locking technique; mutations perform rebalancing separately;
+        and deletions occasionally leave a routing node in the tree.
 
         <b>Template arguments</b>:
         - \p RCU - one of \ref cds_urcu_gc "RCU type"
 
         <b>Template arguments</b>:
         - \p RCU - one of \ref cds_urcu_gc "RCU type"
@@ -54,6 +100,8 @@ namespace cds { namespace container {
             It is possible to declare option-based tree with \p bronson_avltree::make_traits metafunction
             instead of \p Traits template argument.
 
             It is possible to declare option-based tree with \p bronson_avltree::make_traits metafunction
             instead of \p Traits template argument.
 
+        There is \ref cds_container_BronsonAVLTreeMap_rcu_ptr "a specialization" for "key -> value pointer" map.
+
         @note Before including <tt><cds/container/bronson_avltree_map_rcu.h></tt> you should include appropriate RCU header file,
         see \ref cds_urcu_gc "RCU type" for list of existing RCU class and corresponding header files.
     */
         @note Before including <tt><cds/container/bronson_avltree_map_rcu.h></tt> you should include appropriate RCU header file,
         see \ref cds_urcu_gc "RCU type" for list of existing RCU class and corresponding header files.
     */
@@ -97,6 +145,10 @@ namespace cds { namespace container {
 
         /// Enabled or disabled @ref bronson_avltree::relaxed_insert "relaxed insertion"
         static bool const c_bRelaxedInsert = traits::relaxed_insert;
 
         /// Enabled or disabled @ref bronson_avltree::relaxed_insert "relaxed insertion"
         static bool const c_bRelaxedInsert = traits::relaxed_insert;
+
+        /// Group of \p extract_xxx functions does not require external locking
+        static CDS_CONSTEXPR const bool c_bExtractLockExternal = base_class::c_bExtractLockExternal;
+
         typedef typename base_class::rcu_lock   rcu_lock;  ///< RCU scoped lock
 
         /// Returned pointer to \p mapped_type of extracted node
         typedef typename base_class::rcu_lock   rcu_lock;  ///< RCU scoped lock
 
         /// Returned pointer to \p mapped_type of extracted node
@@ -211,7 +263,7 @@ namespace cds { namespace container {
             ) == update_flags::result_inserted;
         }
 
             ) == update_flags::result_inserted;
         }
 
-        /// For key \p key inserts data of type \p mapped_type created in-place from \p args
+        /// For \p key inserts data of type \p mapped_type created in-place from \p args
         /**
             Returns \p true if inserting successful, \p false otherwise.
 
         /**
             Returns \p true if inserting successful, \p false otherwise.
 
@@ -220,26 +272,31 @@ namespace cds { namespace container {
         template <typename K, typename... Args>
         bool emplace( K&& key, Args&&... args )
         {
         template <typename K, typename... Args>
         bool emplace( K&& key, Args&&... args )
         {
-            return base_class::do_update( key, key_comparator(),
-                [&]( node_type * pNode ) -> mapped_type* 
-                {
-                    assert( pNode->m_pValue.load( memory_model::memory_order_relaxed ) == nullptr );
-                    CDS_UNUSED( pNode );
-                    return cxx_allocator().New( std::forward<Args>(args)...);
-                },
-                update_flags::allow_insert
-            ) == update_flags::result_inserted;
+            struct scoped_ptr
+            {
+                mapped_type * pVal;
+                scoped_ptr( mapped_type * p ): pVal( p ) {}
+                ~scoped_ptr() { if ( pVal ) cxx_allocator().Delete( pVal ); }
+                void release() { pVal = nullptr; }
+            };
+
+            scoped_ptr p( cxx_allocator().MoveNew( std::forward<Args>( args )... ));
+            if ( base_class::insert( std::forward<K>( key ), p.pVal )) {
+                p.release();
+                return true;
+            }
+            return false;
         }
 
         }
 
-        /// Ensures that the \p key exists in the map
+        /// Updates the value for \p key
         /**
             The operation performs inserting or changing data with lock-free manner.
 
             If the \p key not found in the map, then the new item created from \p key
         /**
             The operation performs inserting or changing data with lock-free manner.
 
             If the \p key not found in the map, then the new item created from \p key
-            is inserted into the map (note that in this case the \ref key_type should be
-            constructible from type \p K).
+            will be inserted into the map iff \p bAllowInsert is \p true
+            (note that in this case the \ref key_type should be constructible from type \p K).
             Otherwise, the functor \p func is called with item found.
             Otherwise, the functor \p func is called with item found.
-            The functor \p Func may be a functor:
+            The functor \p Func signature is:
             \code
                 struct my_functor {
                     void operator()( bool bNew, key_type const& key, mapped_type& item );
             \code
                 struct my_functor {
                     void operator()( bool bNew, key_type const& key, mapped_type& item );
@@ -250,19 +307,20 @@ namespace cds { namespace container {
             - \p bNew - \p true if the item has been inserted, \p false otherwise
             - \p item - value
 
             - \p bNew - \p true if the item has been inserted, \p false otherwise
             - \p item - value
 
-            The functor may change any fields of the \p item. The functor is called under the node lock.
+            The functor may change any fields of the \p item. The functor is called under the node lock,
+            the caller can change any field of \p item.
 
             RCU \p synchronize() method can be called. RCU should not be locked.
 
 
             RCU \p synchronize() method can be called. RCU should not be locked.
 
-            Returns <tt> std::pair<bool, bool> </tt> where \p first is \p true if operation is successfull,
+            Returns <tt> std::pair<bool, bool> </tt> where \p first is \p true if operation is successful,
             \p second is \p true if new item has been added or \p false if the item with \p key
             \p second is \p true if new item has been added or \p false if the item with \p key
-            already is in the tree.
+            already exists.
         */
         template <typename K, typename Func>
         */
         template <typename K, typename Func>
-        std::pair<bool, bool> update( K const& key, Func func )
+        std::pair<bool, bool> update( K const& key, Func func, bool bAllowInsert = true )
         {
             int result = base_class::do_update( key, key_comparator(),
         {
             int result = base_class::do_update( key, key_comparator(),
-                [&func]( node_type * pNode ) -> mapped_type* 
+                [&func]( node_type * pNode ) -> mapped_type*
                 {
                     mapped_type * pVal = pNode->m_pValue.load( memory_model::memory_order_relaxed );
                     if ( !pVal ) {
                 {
                     mapped_type * pVal = pNode->m_pValue.load( memory_model::memory_order_relaxed );
                     if ( !pVal ) {
@@ -273,11 +331,12 @@ namespace cds { namespace container {
                         func( false, pNode->m_key, *pVal );
                     return pVal;
                 },
                         func( false, pNode->m_key, *pVal );
                     return pVal;
                 },
-                update_flags::allow_insert | update_flags::allow_update 
+                (bAllowInsert ? update_flags::allow_insert : 0) | update_flags::allow_update
             );
             return std::make_pair( result != 0, (result & update_flags::result_inserted) != 0 );
         }
 
             );
             return std::make_pair( result != 0, (result & update_flags::result_inserted) != 0 );
         }
 
+
         /// Delete \p key from the map
         /**
             RCU \p synchronize() method can be called. RCU should not be locked.
         /// Delete \p key from the map
         /**
             RCU \p synchronize() method can be called. RCU should not be locked.
@@ -312,7 +371,7 @@ namespace cds { namespace container {
             The functor \p Func interface:
             \code
             struct extractor {
             The functor \p Func interface:
             \code
             struct extractor {
-                void operator()(mapped_type& item) { ... }
+                void operator()(key_type const& key, mapped_type& item) { ... }
             };
             \endcode
 
             };
             \endcode
 
@@ -362,7 +421,7 @@ namespace cds { namespace container {
             return base_class::extract_min();
         }
 
             return base_class::extract_min();
         }
 
-        /// Extracts minimal key key and corresponding value
+        /// Extracts minimal key and corresponding value
         /**
             Returns \p exempt_ptr to the leftmost item.
             If the tree is empty, returns empty \p exempt_ptr.
         /**
             Returns \p exempt_ptr to the leftmost item.
             If the tree is empty, returns empty \p exempt_ptr.
@@ -394,13 +453,13 @@ namespace cds { namespace container {
             return base_class::extract_min( f );
         }
 
             return base_class::extract_min( f );
         }
 
-        /// Extracts minimal key key and corresponding value
+        /// Extracts minimal key and corresponding value
         /**
             This function is a shortcut for the following call:
             \code
                 key_type key;
                 exempt_ptr xp = theTree.extract_min( [&key]( key_type const& k ) { key = k; } );
         /**
             This function is a shortcut for the following call:
             \code
                 key_type key;
                 exempt_ptr xp = theTree.extract_min( [&key]( key_type const& k ) { key = k; } );
-            \endode
+            \endcode
             \p key_type should be copy-assignable. The copy of minimal key
             is returned in \p min_key argument.
         */
             \p key_type should be copy-assignable. The copy of minimal key
             is returned in \p min_key argument.
         */
@@ -416,7 +475,7 @@ namespace cds { namespace container {
             If the set is empty, returns empty \p exempt_ptr.
 
             Note that the function returns only the value for maximal key.
             If the set is empty, returns empty \p exempt_ptr.
 
             Note that the function returns only the value for maximal key.
-            To retrieve its key use \p extract_max( Func ) member function.
+            To retrieve its key use \p extract_max( Func ) or \p extract_max_key(key_type&) member function.
 
             @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.
 
             @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.
@@ -471,7 +530,7 @@ namespace cds { namespace container {
             \code
                 key_type key;
                 exempt_ptr xp = theTree.extract_max( [&key]( key_type const& k ) { key = k; } );
             \code
                 key_type key;
                 exempt_ptr xp = theTree.extract_max( [&key]( key_type const& k ) { key = k; } );
-            \endode
+            \endcode
             \p key_type should be copy-assignable. The copy of maximal key
             is returned in \p max_key argument.
         */
             \p key_type should be copy-assignable. The copy of maximal key
             is returned in \p max_key argument.
         */
@@ -546,7 +605,7 @@ namespace cds { namespace container {
             return base_class::find_with( key, pred, f );
         }
 
             return base_class::find_with( key, pred, f );
         }
 
-        /// Find the key \p key
+        /// Checks whether the map contains \p key
         /**
             The function searches the item with key equal to \p key
             and returns \p true if it is found, and \p false otherwise.
         /**
             The function searches the item with key equal to \p key
             and returns \p true if it is found, and \p false otherwise.
@@ -554,22 +613,21 @@ namespace cds { namespace container {
             The function applies RCU lock internally.
         */
         template <typename K>
             The function applies RCU lock internally.
         */
         template <typename K>
-        bool find( K const& key )
+        bool contains( K const& key )
         {
         {
-            return base_class::find( key );
+            return base_class::contains( key );
         }
 
         }
 
-        /// Finds the key \p val using \p pred predicate for searching
+        /// Checks whether the map contains \p key using \p pred predicate for searching
         /**
         /**
-            The function is an analog of \p find(K const&)
-            but \p pred is used for key comparing.
+            The function is similar to <tt>contains( key )</tt> but \p pred is used for key comparing.
             \p Less functor has the interface like \p std::less.
             \p Less functor has the interface like \p std::less.
-            \p Less must imply the same element order as the comparator used for building the map.
+            \p Less must imply the same element order as the comparator used for building the set.
         */
         template <typename K, typename Less>
         */
         template <typename K, typename Less>
-        bool find_with( K const& key, Less pred )
+        bool contains( K const& key, Less pred )
         {
         {
-            return base_class::find_with( key, pred );
+            return base_class::contains( key, pred );
         }
 
         /// Clears the map
         }
 
         /// Clears the map
@@ -605,6 +663,18 @@ namespace cds { namespace container {
             return base_class::statistics();
         }
 
             return base_class::statistics();
         }
 
+        /// Returns reference to \p sync_monitor object
+        sync_monitor& monitor()
+        {
+            return base_class::monitor();
+        }
+        //@cond
+        sync_monitor const& monitor() const
+        {
+            return base_class::monitor();
+        }
+        //@endcond
+
         /// Checks internal consistency (not atomic, not thread-safe)
         /**
             The debugging function to check internal consistency of the tree.
         /// Checks internal consistency (not atomic, not thread-safe)
         /**
             The debugging function to check internal consistency of the tree.
@@ -624,7 +694,7 @@ namespace cds { namespace container {
                 void operator()( size_t nLevel, size_t hLeft, size_t hRight );
             };
             \endcode
                 void operator()( size_t nLevel, size_t hLeft, size_t hRight );
             };
             \endcode
-            where 
+            where
             - \p nLevel - the level where the violation is found
             - \p hLeft - the height of left subtree
             - \p hRight - the height of right subtree
             - \p nLevel - the level where the violation is found
             - \p hLeft - the height of left subtree
             - \p hRight - the height of right subtree