Removed redundant spaces
[libcds.git] / cds / intrusive / details / ellen_bintree_base.h
index 54e928b768f13fdc537eb2d5e5ef039cf4469e26..a3398f3b3777c25eefaede2ae77e69c2a4683f4a 100644 (file)
@@ -1,4 +1,32 @@
-//$$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_INTRUSIVE_DETAILS_ELLEN_BINTREE_BASE_H
 #define CDSLIB_INTRUSIVE_DETAILS_ELLEN_BINTREE_BASE_H
@@ -13,8 +41,6 @@ namespace cds { namespace intrusive {
 
     /// EllenBinTree related declarations
     namespace ellen_bintree {
-        struct implementation_tag;
-
         //Forwards
         template <class GC> struct base_node;
         template <class GC, typename Tag = opt::none> struct node;
@@ -70,7 +96,7 @@ namespace cds { namespace intrusive {
                 delete_info     dInfo;
             };
 
-            update_desc *   pNextRetire     ;   // for local retired list (RCU)
+            update_desc *   pNextRetire; // for local retired list (RCU)
 
             update_desc()
                 : pNextRetire( nullptr )
@@ -89,7 +115,7 @@ namespace cds { namespace intrusive {
                 key_infinite = key_infinite1 | key_infinite2    ///< Cumulative infinite flags
             };
 
-            unsigned int    m_nFlags    ;   ///< Internal flags
+            atomics::atomic<unsigned int> m_nFlags;   ///< Internal flags
 
             /// Constructs leaf (bIntrenal == false) or internal (bInternal == true) node
             explicit basic_node( bool bInternal )
@@ -105,25 +131,26 @@ namespace cds { namespace intrusive {
             /// Checks if the node is internal
             bool is_internal() const
             {
-                return (m_nFlags & internal) != 0;
+                return (m_nFlags.load(atomics::memory_order_relaxed) & internal) != 0;
             }
 
             /// Returns infinite key, 0 if the node is not infinite
             unsigned int infinite_key() const
             {
-                return m_nFlags & key_infinite;
+                return m_nFlags.load(atomics::memory_order_relaxed) & key_infinite;
             }
 
             /// Sets infinite key for the node (for internal use only!!!)
             void infinite_key( int nInf )
             {
-                m_nFlags &= ~key_infinite;
+                unsigned int nFlags = m_nFlags.load(atomics::memory_order_relaxed);
+                nFlags &= ~key_infinite;
                 switch ( nInf ) {
                 case 1:
-                    m_nFlags |= key_infinite1;
+                    nFlags |= key_infinite1;
                     break;
                 case 2:
-                    m_nFlags |= key_infinite2;
+                    nFlags |= key_infinite2;
                     break;
                 case 0:
                     break;
@@ -131,6 +158,7 @@ namespace cds { namespace intrusive {
                     assert( false );
                     break;
                 }
+                m_nFlags.store( nFlags, atomics::memory_order_relaxed );
             }
         };
 
@@ -212,14 +240,19 @@ namespace cds { namespace intrusive {
                 : base_class( true )
                 , m_pLeft( nullptr )
                 , m_pRight( nullptr )
-                , m_pUpdate( update_ptr() )
+                , m_pUpdate( update_ptr())
                 , m_nEmptyUpdate(0)
             {}
 
             //@cond
             update_ptr null_update_desc()
             {
-                return update_ptr( reinterpret_cast<update_desc_type *>( (++m_nEmptyUpdate << 2) & 0xFFFF ) );
+                return update_ptr( reinterpret_cast<update_desc_type *>( (++m_nEmptyUpdate << 2) & 0xFFFF ));
+            }
+
+            base_class * get_child( bool bRight, atomics::memory_order mo ) const
+            {
+                return bRight ? m_pRight.load( mo ) : m_pLeft.load( mo );
             }
             //@endcond
         };
@@ -341,9 +374,9 @@ namespace cds { namespace intrusive {
             event_counter   m_nInsertSuccess        ; ///< Count of success insertion
             event_counter   m_nInsertFailed         ; ///< Count of failed insertion
             event_counter   m_nInsertRetries        ; ///< Count of unsuccessful retries of insertion
-            event_counter   m_nEnsureExist          ; ///< Count of \p ensure call for existed node
-            event_counter   m_nEnsureNew            ; ///< Count of \p ensure call for new node
-            event_counter   m_nEnsureRetries        ; ///< Count of unsuccessful retries of ensuring
+            event_counter   m_nUpdateExist          ; ///< Count of \p update() call for existed node
+            event_counter   m_nUpdateNew            ; ///< Count of \p update() call for new node
+            event_counter   m_nUpdateRetries        ; ///< Count of unsuccessful retries of ensuring
             event_counter   m_nEraseSuccess         ; ///< Count of successful call of \p erase and \p unlink
             event_counter   m_nEraseFailed          ; ///< Count of failed call of \p erase and \p unlink
             event_counter   m_nEraseRetries         ; ///< Count of unsuccessful retries inside erasing/unlinking
@@ -371,9 +404,9 @@ namespace cds { namespace intrusive {
             void    onInsertSuccess()               { ++m_nInsertSuccess        ; }
             void    onInsertFailed()                { ++m_nInsertFailed         ; }
             void    onInsertRetry()                 { ++m_nInsertRetries        ; }
-            void    onEnsureExist()                 { ++m_nEnsureExist          ; }
-            void    onEnsureNew()                   { ++m_nEnsureNew            ; }
-            void    onEnsureRetry()                 { ++m_nEnsureRetries        ; }
+            void    onUpdateExist()                 { ++m_nUpdateExist          ; }
+            void    onUpdateNew()                   { ++m_nUpdateNew            ; }
+            void    onUpdateRetry()                 { ++m_nUpdateRetries        ; }
             void    onEraseSuccess()                { ++m_nEraseSuccess         ; }
             void    onEraseFailed()                 { ++m_nEraseFailed          ; }
             void    onEraseRetry()                  { ++m_nEraseRetries         ; }
@@ -397,46 +430,46 @@ namespace cds { namespace intrusive {
         /// EllenBinTree empty statistics
         struct empty_stat {
             //@cond
-            void    onInternalNodeCreated()         {}
-            void    onInternalNodeDeleted()         {}
-            void    onUpdateDescCreated()           {}
-            void    onUpdateDescDeleted()           {}
-            void    onInsertSuccess()               {}
-            void    onInsertFailed()                {}
-            void    onInsertRetry()                 {}
-            void    onEnsureExist()                 {}
-            void    onEnsureNew()                   {}
-            void    onEnsureRetry()                 {}
-            void    onEraseSuccess()                {}
-            void    onEraseFailed()                 {}
-            void    onEraseRetry()                  {}
-            void    onExtractMinSuccess()           {}
-            void    onExtractMinFailed()            {}
-            void    onExtractMinRetry()             {}
-            void    onExtractMaxSuccess()           {}
-            void    onExtractMaxFailed()            {}
-            void    onExtractMaxRetry()             {}
-            void    onFindSuccess()                 {}
-            void    onFindFailed()                  {}
-            void    onSearchRetry()                 {}
-            void    onHelpInsert()                  {}
-            void    onHelpDelete()                  {}
-            void    onHelpMark()                    {}
-            void    onHelpGuardSuccess()            {}
-            void    onHelpGuardFailed()             {}
+            void    onInternalNodeCreated()         const {}
+            void    onInternalNodeDeleted()         const {}
+            void    onUpdateDescCreated()           const {}
+            void    onUpdateDescDeleted()           const {}
+            void    onInsertSuccess()               const {}
+            void    onInsertFailed()                const {}
+            void    onInsertRetry()                 const {}
+            void    onUpdateExist()                 const {}
+            void    onUpdateNew()                   const {}
+            void    onUpdateRetry()                 const {}
+            void    onEraseSuccess()                const {}
+            void    onEraseFailed()                 const {}
+            void    onEraseRetry()                  const {}
+            void    onExtractMinSuccess()           const {}
+            void    onExtractMinFailed()            const {}
+            void    onExtractMinRetry()             const {}
+            void    onExtractMaxSuccess()           const {}
+            void    onExtractMaxFailed()            const {}
+            void    onExtractMaxRetry()             const {}
+            void    onFindSuccess()                 const {}
+            void    onFindFailed()                  const {}
+            void    onSearchRetry()                 const {}
+            void    onHelpInsert()                  const {}
+            void    onHelpDelete()                  const {}
+            void    onHelpMark()                    const {}
+            void    onHelpGuardSuccess()            const {}
+            void    onHelpGuardFailed()             const {}
             //@endcond
         };
 
         /// EllenBinTree traits
         struct traits
         {
-            /// Hook used
+            /// Hook used (mandatory)
             /**
                 Possible values are: \p ellen_bintree::base_hook, \p ellen_bintree::member_hook, \p ellen_bintree::traits_hook.
             */
             typedef base_hook<>       hook;
 
-            /// Key extracting functor
+            /// Key extracting functor (mandatory)
             /**
                 You should explicit define a valid functor.
                 The functor has the following prototype:
@@ -448,7 +481,7 @@ namespace cds { namespace intrusive {
                 It should initialize \p dest key from \p src data.
                 The functor is used to initialize internal nodes.
             */
-            typedef opt::none           key_extractor;
+            typedef opt::none key_extractor;
 
             /// Key comparison functor
             /**
@@ -459,7 +492,7 @@ namespace cds { namespace intrusive {
                 You should provide \p compare or \p less functor.
                 See \ref cds_intrusive_EllenBinTree_rcu_less "predicate requirements".
             */
-            typedef opt::none                       compare;
+            typedef opt::none compare;
 
             /// Specifies binary predicate used for key compare.
             /**
@@ -468,26 +501,26 @@ namespace cds { namespace intrusive {
                 You should provide \p compare or \p less functor.
                 See \ref cds_intrusive_EllenBinTree_rcu_less "predicate requirements".
             */
-            typedef opt::none                       less;
+            typedef opt::none less;
 
             /// Disposer
             /**
                 The functor used for dispose removed items. Default is \p opt::v::empty_disposer.
             */
-            typedef opt::v::empty_disposer          disposer;
+            typedef opt::v::empty_disposer disposer;
 
             /// Item counter
             /**
                 The type for item counter, by default it is disabled (\p atomicity::empty_item_counter).
                 To enable it use \p atomicity::item_counter
             */
-            typedef atomicity::empty_item_counter     item_counter;
+            typedef atomicity::empty_item_counter item_counter;
 
             /// C++ memory ordering model
             /**
                 List of available memory ordering see \p opt::memory_model
             */
-            typedef opt::v::relaxed_ordering        memory_model;
+            typedef opt::v::relaxed_ordering memory_model;
 
             /// Allocator for update descriptors
             /**
@@ -503,29 +536,29 @@ namespace cds { namespace intrusive {
                 Also notice that size of update descriptor is constant and not dependent on the type of data
                 stored in the tree so single free-list object can be used for several \p EllenBinTree object.
             */
-            typedef CDS_DEFAULT_ALLOCATOR           update_desc_allocator;
+            typedef CDS_DEFAULT_ALLOCATOR update_desc_allocator;
 
             /// Allocator for internal nodes
             /**
                 The allocator type is used for \p ellen_bintree::internal_node.
             */
-            typedef CDS_DEFAULT_ALLOCATOR           node_allocator;
+            typedef CDS_DEFAULT_ALLOCATOR node_allocator;
 
             /// Internal statistics
             /**
                 By default, internal statistics is disabled (\p ellen_bintree::empty_stat).
                 To enable it use \p ellen_bintree::stat.
             */
-            typedef empty_stat                      stat;
+            typedef empty_stat stat;
 
             /// Back-off strategy
-            typedef cds::backoff::empty             back_off;
+            typedef cds::backoff::empty back_off;
 
             /// RCU deadlock checking policy (only for \ref cds_intrusive_EllenBinTree_rcu "RCU-based EllenBinTree")
             /**
                 List of available options see \p opt::rcu_check_deadlock
             */
-            typedef cds::opt::v::rcu_throw_deadlock      rcu_check_deadlock;
+            typedef cds::opt::v::rcu_throw_deadlock rcu_check_deadlock;
         };
 
         /// Metafunction converting option list to EllenBinTree traits
@@ -596,9 +629,9 @@ namespace cds { namespace intrusive {
                 template <typename LeafNode>
                 int operator()( internal_node<key_type, LeafNode> const& n1, internal_node<key_type, LeafNode> const& n2 ) const
                 {
-                    if ( n1.infinite_key() )
+                    if ( n1.infinite_key())
                         return n2.infinite_key() ? n1.infinite_key() - n2.infinite_key() : 1;
-                    else if ( n2.infinite_key() )
+                    else if ( n2.infinite_key())
                         return -1;
                     return operator()( n1.m_Key, n2.m_Key );
                 }
@@ -606,7 +639,7 @@ namespace cds { namespace intrusive {
                 template <typename LeafNode, typename Q>
                 int operator()( internal_node<key_type, LeafNode> const& n, Q const& v ) const
                 {
-                    if ( n.infinite_key() )
+                    if ( n.infinite_key())
                         return 1;
                     return operator()( n.m_Key, v );
                 }
@@ -614,7 +647,7 @@ namespace cds { namespace intrusive {
                 template <typename LeafNode, typename Q>
                 int operator()( Q const& v, internal_node<key_type, LeafNode> const& n ) const
                 {
-                    if ( n.infinite_key() )
+                    if ( n.infinite_key())
                         return -1;
                     return operator()( v, n.m_Key );
                 }
@@ -622,7 +655,7 @@ namespace cds { namespace intrusive {
                 template <typename GC, typename Tag>
                 int operator()( node<GC, Tag> const& n1, node<GC, Tag> const& n2 ) const
                 {
-                    if ( n1.infinite_key() != n2.infinite_key() )
+                    if ( n1.infinite_key() != n2.infinite_key())
                         return n1.infinite_key() - n2.infinite_key();
                     return operator()( *node_traits::to_value_ptr( n1 ), *node_traits::to_value_ptr( n2 ));
                 }
@@ -630,7 +663,7 @@ namespace cds { namespace intrusive {
                 template <typename GC, typename Tag, typename Q>
                 int operator()( node<GC, Tag> const& n, Q const& v ) const
                 {
-                    if ( n.infinite_key() )
+                    if ( n.infinite_key())
                         return 1;
                     return operator()( *node_traits::to_value_ptr( n ), v );
                 }
@@ -638,24 +671,24 @@ namespace cds { namespace intrusive {
                 template <typename GC, typename Tag, typename Q>
                 int operator()( Q const& v, node<GC, Tag> const& n ) const
                 {
-                    if ( n.infinite_key() )
+                    if ( n.infinite_key())
                         return -1;
-                    return operator()( v, *node_traits::to_value_ptr( n ) );
+                    return operator()( v, *node_traits::to_value_ptr( n ));
                 }
 
                 template <typename GC>
                 int operator()( base_node<GC> const& n1, base_node<GC> const& n2 ) const
                 {
-                    if ( n1.infinite_key() != n2.infinite_key() )
+                    if ( n1.infinite_key() != n2.infinite_key())
                         return n1.infinite_key() - n2.infinite_key();
-                    if ( n1.is_leaf() ) {
-                        if ( n2.is_leaf() )
+                    if ( n1.is_leaf()) {
+                        if ( n2.is_leaf())
                             return operator()( node_traits::to_leaf_node( n1 ), node_traits::to_leaf_node( n2 ));
                         else
                             return operator()( node_traits::to_leaf_node( n1 ), node_traits::to_internal_node( n2 ));
                     }
 
-                    if ( n2.is_leaf() )
+                    if ( n2.is_leaf())
                         return operator()( node_traits::to_internal_node( n1 ), node_traits::to_leaf_node( n2 ));
                     else
                         return operator()( node_traits::to_internal_node( n1 ), node_traits::to_internal_node( n2 ));
@@ -666,7 +699,7 @@ namespace cds { namespace intrusive {
                 {
                     if ( n.infinite_key())
                         return 1;
-                    if ( n.is_leaf() )
+                    if ( n.is_leaf())
                         return operator()( node_traits::to_leaf_node( n ), v );
                     return operator()( node_traits::to_internal_node( n ), v );
                 }
@@ -680,7 +713,7 @@ namespace cds { namespace intrusive {
                 template <typename GC, typename LeafNode >
                 int operator()( base_node<GC> const& i, internal_node<key_type, LeafNode> const& n ) const
                 {
-                    if ( i.is_leaf() )
+                    if ( i.is_leaf())
                         return operator()( static_cast<LeafNode const&>(i), n );
                     return operator()( static_cast<internal_node<key_type, LeafNode> const&>(i), n );
                 }
@@ -694,8 +727,8 @@ namespace cds { namespace intrusive {
                 template <typename GC, typename Tag >
                 int operator()( node<GC, Tag> const& n, internal_node<key_type, node<GC, Tag> > const& i ) const
                 {
-                    if ( !n.infinite_key() ) {
-                        if ( i.infinite_key() )
+                    if ( !n.infinite_key()) {
+                        if ( i.infinite_key())
                             return -1;
                         return operator()( n, i.m_Key );
                     }