Fixed Clang build
[libcds.git] / cds / container / bronson_avltree_map_rcu.h
index 591596549502b4bdf1fb65a0c9fab04bd08ea5a2..be36d86d0f9b71b425c474704f1163660af6ecc6 100644 (file)
@@ -1,16 +1,45 @@
-//$$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 {
 
-    namespace bronson_avltree { 
+    namespace bronson_avltree {
         //@cond
         namespace details {
-            template < typename Key, typename T, typename Traits>
+            template < class RCU, typename Key, typename T, typename Traits>
             struct make_map
             {
                 typedef Key key_type;
@@ -22,8 +51,7 @@ namespace cds { namespace container {
                 struct traits : public original_traits
                 {
                     struct disposer {
-                        template <typename T>
-                        void operator()( mapped_type * p )
+                        void operator()( mapped_type * p ) const
                         {
                             cxx_allocator().Delete( p );
                         }
@@ -31,12 +59,7 @@ namespace cds { namespace container {
                 };
 
                 // Metafunction result
-                typedef BronsonAVLTreeMap <
-                    cds::urcu::gc<RCU>,
-                    Key,
-                    T *,
-                    traits
-                > type;
+                typedef BronsonAVLTreeMap< RCU, Key, mapped_type *, traits > type;
             };
         } // namespace details
         //@endcond
@@ -49,8 +72,25 @@ namespace cds { namespace container {
 
         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"
@@ -60,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.
 
+        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.
     */
@@ -77,11 +119,11 @@ namespace cds { namespace container {
 #ifdef CDS_DOXYGEN_INVOKED
         : private BronsonAVLTreeMap< cds::urcu::gc<RCU>, Key, T*, Traits >
 #else
-        : private bronson_avltree::details::make_map< Key, T, Traits >::type;
+        : private bronson_avltree::details::make_map< cds::urcu::gc<RCU>, Key, T, Traits >::type
 #endif
     {
         //@cond
-        typedef bronson_avltree::details::make_map< Key, T, Traits > maker;
+        typedef bronson_avltree::details::make_map< cds::urcu::gc<RCU>, Key, T, Traits > maker;
         typedef typename maker::type base_class;
         //@endcond
 
@@ -99,21 +141,26 @@ namespace cds { namespace container {
         typedef typename traits::stat                   stat;               ///< internal statistics
         typedef typename traits::rcu_check_deadlock     rcu_check_deadlock; ///< Deadlock checking policy
         typedef typename traits::back_off               back_off;           ///< Back-off strategy
-        typedef typename traits::lock_type              lock_type;          ///< Node lock type
+        typedef typename traits::sync_monitor           sync_monitor;       ///< @ref cds_sync_monitor "Synchronization monitor" type for node-level locking
 
         /// Enabled or disabled @ref bronson_avltree::relaxed_insert "relaxed insertion"
         static bool const c_bRelaxedInsert = traits::relaxed_insert;
 
-        /// Pointer to removed value object
+        /// 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::exempt_ptr exempt_ptr;
 
     protected:
         //@cond
-        typedef typename base_class::node_type  node_type;
+        typedef typename base_class::node_type        node_type;
         typedef typename base_class::node_scoped_lock node_scoped_lock;
-        typedef typename maker::cxx_allocator   cxx_allocator;
+        typedef typename maker::cxx_allocator         cxx_allocator;
 
-        using base_class::update_flags;
+        typedef typename base_class::update_flags update_flags;
         //@endcond
 
     public:
@@ -141,13 +188,14 @@ namespace cds { namespace container {
         bool insert( K const& key )
         {
             return base_class::do_update(key, key_comparator(),
-                []( node_type * pNode ) -> mapped_type* 
+                []( node_type * pNode ) -> mapped_type*
                 {
                     assert( pNode->m_pValue.load( memory_model::memory_order_relaxed ) == nullptr );
+                    CDS_UNUSED( pNode );
                     return cxx_allocator().New();
                 },
-                update_flags::allow_insert 
-            ) == update_flags::result_insert;
+                update_flags::allow_insert
+            ) == update_flags::result_inserted;
         }
 
         /// Inserts new node
@@ -167,13 +215,14 @@ namespace cds { namespace container {
         bool insert( K const& key, V const& val )
         {
             return base_class::do_update( key, key_comparator(),
-                [&val]( node_type * pNode )
+                [&val]( node_type * pNode ) -> mapped_type*
                 {
                     assert( pNode->m_pValue.load( memory_model::memory_order_relaxed ) == nullptr );
+                    CDS_UNUSED( pNode );
                     return cxx_allocator().New( val );
                 },
-                update_flags::allow_insert 
-            ) == update_flags::result_insert;
+                update_flags::allow_insert
+            ) == update_flags::result_inserted;
         }
 
         /// Inserts new node and initialize it by a functor
@@ -182,7 +231,7 @@ namespace cds { namespace container {
             \p func functor with signature
             \code
                 struct functor {
-                    void operator()( mapped_type& item );
+                    void operator()( key_type const& key, mapped_type& item );
                 };
             \endcode
 
@@ -203,18 +252,18 @@ namespace cds { namespace container {
         bool insert_with( K const& key, Func func )
         {
             return base_class::do_update( key, key_comparator(),
-                [&func]( node_type * pNode ) -> mapped_type* 
+                [&func]( node_type * pNode ) -> mapped_type*
                 {
                     assert( pNode->m_pValue.load( memory_model::memory_order_relaxed ) == nullptr );
                     mapped_type * pVal = cxx_allocator().New();
-                    func( *pVal );
+                    func( pNode->m_key, *pVal );
                     return pVal;
                 },
-                update_flags::allow_insert 
-            ) == update_flags::result_insert;
+                update_flags::allow_insert
+            ) == 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.
 
@@ -223,28 +272,34 @@ namespace cds { namespace container {
         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 );
-                    return cxx_allocator().New( std::forward<Args>(args)...);
-                },
-                update_flags::allow_insert 
-            ) == update_flags::result_insert;
+            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
-            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.
-            The functor \p Func may be a functor:
+            The functor \p Func signature is:
             \code
                 struct my_functor {
-                    void operator()( bool bNew, mapped_type& item );
+                    void operator()( bool bNew, key_type const& key, mapped_type& item );
                 };
             \endcode
 
@@ -252,34 +307,36 @@ 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 is in the tree.
+            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 ));
+                    mapped_type * pVal = pNode->m_pValue.load( memory_model::memory_order_relaxed );
                     if ( !pVal ) {
                         pVal = cxx_allocator().New();
-                        func( true, *pVal );
+                        func( true, pNode->m_key, *pVal );
                     }
                     else
-                        func( false, *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_insert) != 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.
@@ -314,7 +371,7 @@ namespace cds { namespace container {
             The functor \p Func interface:
             \code
             struct extractor {
-                void operator()(mapped_type& item) { ... }
+                void operator()(key_type const& key, mapped_type& item) { ... }
             };
             \endcode
 
@@ -341,11 +398,14 @@ namespace cds { namespace container {
             return base_class::erase_with( key, pred, f );
         }
 
-        /// Extracts an item with minimal key from the map
+        /// Extracts a value with minimal key from the map
         /**
-            Returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the leftmost item.
+            Returns \p exempt_ptr pointer to the leftmost item.
             If the set is empty, returns empty \p exempt_ptr.
 
+            Note that the function returns only the value for minimal key.
+            To retrieve its key use \p extract_min( Func ) member function.
+
             @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.
@@ -358,14 +418,65 @@ namespace cds { namespace container {
         */
         exempt_ptr extract_min()
         {
-            //TODO
+            return base_class::extract_min();
+        }
+
+        /// Extracts minimal key and corresponding value
+        /**
+            Returns \p exempt_ptr to the leftmost item.
+            If the tree is empty, returns empty \p exempt_ptr.
+
+            \p Func functor is used to store minimal key.
+            \p Func has the following signature:
+            \code
+                struct functor {
+                    void operator()( key_type const& key );
+                };
+            \endcode
+            If the tree is empty, \p f is not called.
+            Otherwise, is it called with minimal key, the pointer to corresponding value is returned
+            as \p exempt_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.
+
+            RCU \p synchronize method can be called. RCU should NOT be locked.
+            The function does not free the item.
+            The deallocator will be implicitly invoked when the returned object is destroyed or when
+            its \p release() member function is called.
+        */
+        template <typename Func>
+        exempt_ptr extract_min( Func f )
+        {
+            return base_class::extract_min( f );
+        }
+
+        /// 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; } );
+            \endcode
+            \p key_type should be copy-assignable. The copy of minimal key
+            is returned in \p min_key argument.
+        */
+        typename std::enable_if< std::is_copy_assignable<key_type>::value, exempt_ptr >::type
+        extract_min_key( key_type& min_key )
+        {
+            return base_class::extract_min_key( min_key );
         }
 
         /// Extracts an item with maximal key from the map
         /**
-            Returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the rightmost item.
+            Returns \p exempt_ptr pointer to the rightmost item.
             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 ) 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.
             During unlinking, a concurrent thread may insert an item with key great than leftmost item's key.
@@ -375,11 +486,58 @@ namespace cds { namespace container {
             The function does not free the item.
             The deallocator will be implicitly invoked when the returned object is destroyed or when
             its \p release() is called.
-            @note Before reusing \p result object you should call its \p release() method.
         */
         exempt_ptr extract_max()
         {
-            //TODO
+            return base_class::extract_max();
+        }
+
+        /// Extracts the maximal key and corresponding value
+        /**
+            Returns \p exempt_ptr pointer to the rightmost item.
+            If the set is empty, returns empty \p exempt_ptr.
+
+            \p Func functor is used to store maximal key.
+            \p Func has the following signature:
+            \code
+                struct functor {
+                    void operator()( key_type const& key );
+                };
+            \endcode
+            If the tree is empty, \p f is not called.
+            Otherwise, is it called with maximal key, the pointer to corresponding value is returned
+            as \p exempt_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.
+
+            RCU \p synchronize method can be called. RCU should NOT be locked.
+            The function does not free the item.
+            The deallocator will be implicitly invoked when the returned object is destroyed or when
+            its \p release() is called.
+        */
+        template <typename Func>
+        exempt_ptr extract_max( Func f )
+        {
+            return base_class::extract_max( f );
+        }
+
+        /// Extracts the maximal key and corresponding value
+        /**
+            This function is a shortcut for the following call:
+            \code
+                key_type key;
+                exempt_ptr xp = theTree.extract_max( [&key]( key_type const& k ) { key = k; } );
+            \endcode
+            \p key_type should be copy-assignable. The copy of maximal key
+            is returned in \p max_key argument.
+        */
+        typename std::enable_if< std::is_copy_assignable<key_type>::value, exempt_ptr >::type
+        extract_max_key( key_type& max_key )
+        {
+            return base_class::extract_max_key( max_key );
         }
 
         /// Extracts an item from the map
@@ -391,7 +549,7 @@ namespace cds { namespace container {
             RCU \p synchronize method can be called. RCU should NOT be locked.
             The function does not destroy the value found.
             The dealloctor will be implicitly invoked when the returned object is destroyed or when
-            its \p reset(nullptr) member function is called.
+            its \p release() member function is called.
         */
         template <typename Q>
         exempt_ptr extract( Q const& key )
@@ -403,8 +561,7 @@ namespace cds { namespace container {
         /**
             The function is an analog of \p extract(Q const&)
             but \p pred is used for key compare.
-            \p Less has the interface like \p std::less and should meet \ref cds_container_EllenBinTreeSet_rcu_less
-            "predicate requirements".
+            \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>
@@ -419,10 +576,10 @@ namespace cds { namespace container {
             The interface of \p Func functor is:
             \code
             struct functor {
-                void operator()( mapped_type& item );
+                void operator()( key_type const& key, mapped_type& val );
             };
             \endcode
-            where \p item is the item found.
+            where \p val is the item found for \p key
             The functor is called under node-level lock.
 
             The function applies RCU lock internally.
@@ -448,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.
@@ -456,52 +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 )
-        {
-            return base_class::find_with( key, pred );
-        }
-
-        /// Finds \p key and return the item found
-        /**
-            The function searches the item with key equal to \p key and returns the pointer to item found.
-            If \p key is not found it returns \p nullptr.
-
-            RCU should be locked before call the function.
-            Returned pointer is valid while RCU is locked.
-        */
-        template <typename Q>
-        mapped_type * get( Q const& key ) const
+        bool contains( K const& key, Less pred )
         {
-            //TODO
-        }
-
-        /// Finds \p key with \p pred predicate and return the item found
-        /**
-            The function is an analog of \p 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 \p key_type
-            and \p Q in any order.
-            \p pred must imply the same element order as the comparator used for building the map.
-        */
-        template <typename Q, typename Less>
-        mapped_type * get_with( Q const& key, Less pred ) const
-        {
-            CDS_UNUSED( pred );
-            //TODO
+            return base_class::contains( key, pred );
         }
 
         /// Clears the map
@@ -537,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.
@@ -546,6 +684,28 @@ namespace cds { namespace container {
             return base_class::check_consistency();
         }
 
+        /// Checks internal consistency (not atomic, not thread-safe)
+        /**
+            The debugging function to check internal consistency of the tree.
+            The functor \p Func is called if a violation of internal tree structure
+            is found:
+            \code
+            struct functor {
+                void operator()( size_t nLevel, size_t hLeft, size_t hRight );
+            };
+            \endcode
+            where
+            - \p nLevel - the level where the violation is found
+            - \p hLeft - the height of left subtree
+            - \p hRight - the height of right subtree
+
+            The functor is called for each violation found.
+        */
+        template <typename Func>
+        bool check_consistency( Func f ) const
+        {
+            return base_class::check_consistency( f );
+        }
     };
 }} // namespace cds::container