Fixed Clang build
[libcds.git] / cds / container / bronson_avltree_map_rcu.h
index f36f53d22b7d73ef5315a0499b32f246fe64fc9e..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
 
+#include <functional>
 #include <cds/container/impl/bronson_avltree_map_rcu.h>
 
 namespace cds { namespace container {
@@ -45,16 +74,23 @@ namespace cds { namespace container {
             - [2010] N.Bronson, J.Casper, H.Chafi, K.Olukotun "A Practical Concurrent Binary Search Tree"
             - <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.
+        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"
@@ -63,7 +99,7 @@ namespace cds { namespace container {
         - \p Traits - tree traits, default is \p bronson_avltree::traits
             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,
@@ -227,7 +263,7 @@ namespace cds { namespace container {
             ) == 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.
 
@@ -236,38 +272,31 @@ namespace cds { namespace container {
         template <typename K, typename... Args>
         bool emplace( K&& key, Args&&... args )
         {
-#       if CDS_COMPILER != CDS_COMPILER_MSVC
-            auto helper = []( typename std::decay<Args>::type&&... args ) -> mapped_type *
-                            {
-                                return cxx_allocator().New( std::move(args)...);
-                            };
-#       endif
-            
-            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 );
-#       if CDS_COMPILER == CDS_COMPILER_MSVC
-                    return cxx_allocator().New( std::forward<Args>(args)...);
-#       else
-                    // gcc/clang error: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47226
-                    return helper( args... );
-#       endif
-                },
-                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
-            will be 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.
-            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 );
@@ -278,19 +307,20 @@ namespace cds { namespace container {
             - \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.
 
-            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
             already exists.
         */
         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(),
-                [&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 ) {
@@ -301,19 +331,11 @@ namespace cds { namespace container {
                         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 );
         }
 
-        //@cond
-        template <typename K, typename Func>
-        std::pair<bool, bool> ensure( K const& key, Func func )
-        {
-            return update( key, func );
-        }
-        //@endcond
-
 
         /// Delete \p key from the map
         /**
@@ -399,7 +421,7 @@ namespace cds { namespace container {
             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.
@@ -431,7 +453,7 @@ namespace cds { namespace container {
             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
@@ -583,7 +605,7 @@ namespace cds { namespace container {
             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.
@@ -591,22 +613,21 @@ namespace cds { namespace container {
             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 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>
-        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
@@ -642,6 +663,18 @@ namespace cds { namespace container {
             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.
@@ -661,7 +694,7 @@ namespace cds { namespace container {
                 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