Removed unused implementation_tag typedef
[libcds.git] / cds / container / details / bronson_avltree_base.h
index 0d99b66047cd1072606f680a5ef77334241a1b22..d24bb3e2899b98c26c3eba01b51f923aa40a726f 100644 (file)
@@ -18,10 +18,11 @@ namespace cds { namespace container {
         struct node;
 
         //@cond
-        template <typename Node, typename SyncMonitor>
+        template <typename Node, typename T, typename SyncMonitor>
         struct link_node
         {
-            typedef Node node_type;
+            typedef Node     node_type;
+            typedef T        mapped_type;
             typedef uint32_t version_type;  ///< version type (internal)
 
             enum
@@ -38,15 +39,16 @@ namespace cds { namespace container {
             atomics::atomic<node_type *>    m_pLeft;    ///< Left child
             atomics::atomic<node_type *>    m_pRight;   ///< Right child
             typename SyncMonitor::node_injection m_SyncMonitorInjection;    ///< @ref cds_sync_monitor "synchronization monitor" injected data
+            atomics::atomic<mapped_type *>  m_pValue;   ///< Value
 
         public:
-            //@cond
             link_node()
                 : m_nHeight( 0 )
                 , m_nVersion( 0 )
                 , m_pParent( nullptr )
                 , m_pLeft( nullptr )
                 , m_pRight( nullptr )
+                , m_pValue( nullptr )
             {}
 
             link_node( int nHeight, version_type version, node_type * pParent, node_type * pLeft, node_type * pRight )
@@ -55,12 +57,23 @@ namespace cds { namespace container {
                 , m_pParent( pParent )
                 , m_pLeft( pLeft )
                 , m_pRight( pRight )
+                , m_pValue( nullptr )
             {}
 
-            atomics::atomic<node_type *>& child( int nDirection )
+            node_type * parent( atomics::memory_order order ) const
+            {
+                return m_pParent.load( order );
+            }
+
+            void parent( node_type * p, atomics::memory_order order )
+            {
+                m_pParent.store( p, order );
+            }
+
+            node_type * child( int nDirection, atomics::memory_order order ) const
             {
                 assert( nDirection != 0 );
-                return nDirection < 0 ? m_pLeft : m_pRight;
+                return nDirection < 0 ? m_pLeft.load( order ) : m_pRight.load( order );
             }
 
             void child( node_type * pChild, int nDirection, atomics::memory_order order )
@@ -109,22 +122,34 @@ namespace cds { namespace container {
             {
                 return (m_nVersion.load( order ) & shrinking) != 0;
             }
-            //@endcond
+
+            mapped_type * value( atomics::memory_order order ) const
+            {
+                return m_pValue.load( order );
+            }
+
+            bool is_valued( atomics::memory_order order ) const
+            {
+                return value( order ) != nullptr;
+            }
         };
         //@endcond
 
-        // BronsonAVLTree internal node
+        /// BronsonAVLTree internal node
         template <typename Key, typename T, typename SyncMonitor >
-        struct node<Key, T*, SyncMonitor>: public link_node< node<Key, T*, SyncMonitor>, SyncMonitor >
+        struct node<Key, T*, SyncMonitor>: public link_node< node<Key, T*, SyncMonitor>, T, SyncMonitor >
         {
-            typedef link_node< node<Key, T*, SyncMonitor>, SyncMonitor > base_class;
+            //@cond
+            typedef link_node< node<Key, T*, SyncMonitor>, T, SyncMonitor > base_class;
+            //@endcond
 
             typedef Key key_type;       ///< key type
             typedef T   mapped_type;    ///< value type
+            //@cond
             typedef typename base_class::version_type version_type;
+            //@endcond
 
             key_type const                  m_key;      ///< Key
-            atomics::atomic<mapped_type *>  m_pValue;   ///< Value
             node *                          m_pNextRemoved; ///< thread-local list of removed node
 
         public:
@@ -133,7 +158,6 @@ namespace cds { namespace container {
             node( Q&& key )
                 : base_class()
                 , m_key( std::forward<Q>( key ) )
-                , m_pValue( nullptr )
                 , m_pNextRemoved( nullptr )
             {}
 
@@ -141,18 +165,8 @@ namespace cds { namespace container {
             node( Q&& key, int nHeight, version_type version, node * pParent, node * pLeft, node * pRight )
                 : base_class( nHeight, version, pParent, pLeft, pRight )
                 , m_key( std::forward<Q>( key ) )
-                , m_pValue( nullptr )
                 , m_pNextRemoved( nullptr )
             {}
-            T * value( atomics::memory_order order ) const
-            {
-                return m_pValue.load( order );
-            }
-
-            bool is_valued( atomics::memory_order order ) const
-            {
-                return value( order ) != nullptr;
-            }
             //@endcond
         };
 
@@ -167,29 +181,55 @@ namespace cds { namespace container {
             event_counter   m_nFindWaitShrinking;   ///< Count of waiting until shrinking completed duting \p find() call
 
             event_counter   m_nInsertSuccess;       ///< Count of inserting data node
+            event_counter   m_nInsertFailed;        ///< Count of insert failures
             event_counter   m_nRelaxedInsertFailed; ///< Count of false creating of data nodes (only if @ref bronson_avltree::relaxed_insert "relaxed insertion" is enabled)
             event_counter   m_nInsertRetry;         ///< Count of insert retries via concurrent operations
-            event_counter   m_nUpdateWaitShrinking; ///< Count of waiting until shrinking completed duting \p update() call
+            event_counter   m_nUpdateWaitShrinking; ///< Count of waiting until shrinking completed during \p update() call
             event_counter   m_nUpdateRetry;         ///< Count of update retries via concurrent operations
             event_counter   m_nUpdateRootWaitShrinking;  ///< Count of waiting until root shrinking completed duting \p update() call
             event_counter   m_nUpdateSuccess;       ///< Count of updating data node
-            event_counter   m_nUpdateUnlinked;      ///< Count of updating of unlinked node attempts
+            event_counter   m_nUpdateUnlinked;      ///< Count of attempts to update unlinked node
             event_counter   m_nDisposedNode;        ///< Count of disposed node
             event_counter   m_nDisposedValue;       ///< Count of disposed value
             event_counter   m_nExtractedValue;      ///< Count of extracted value
+            event_counter   m_nRemoveSuccess;       ///< Count of successfully \p erase() call
+            event_counter   m_nRemoveFailed;        ///< Count of failed \p erase() call
+            event_counter   m_nRemoveRetry;         ///< Count o erase/extract retries
+            event_counter   m_nExtractSuccess;      ///< Count of successfully \p extract() call
+            event_counter   m_nExtractFailed;       ///< Count of failed \p extract() call
+            event_counter   m_nRemoveWaitShrinking; ///< ount of waiting until shrinking completed during \p erase() or \p extract() call
+            event_counter   m_nRemoveRootWaitShrinking;  ///< Count of waiting until root shrinking completed duting \p erase() or \p extract() call
+            event_counter   m_nMakeRoutingNode;     ///< How many nodes were converted to routing (valueless) nodes
 
             event_counter   m_nRightRotation;       ///< Count of single right rotation
             event_counter   m_nLeftRotation;        ///< Count of single left rotation
             event_counter   m_nLeftRightRotation;   ///< Count of double left-over-right rotation
             event_counter   m_nRightLeftRotation;   ///< Count of double right-over-left rotation
 
+            event_counter   m_nRotateAfterRightRotation; ///< Count of rotation required after single right rotation
+            event_counter   m_nRemoveAfterRightRotation; ///< Count of removal required after single right rotation
+            event_counter   m_nDamageAfterRightRotation; ///< Count of damaged node after single right rotation
+
+            event_counter   m_nRotateAfterLeftRotation;  ///< Count of rotation required after signle left rotation
+            event_counter   m_nRemoveAfterLeftRotation;  ///< Count of removal required after single left rotation
+            event_counter   m_nDamageAfterLeftRotation;  ///< Count of damaged node after single left rotation
+
+            event_counter   m_nRotateAfterRLRotation;    ///< Count of rotation required after right-over-left rotation
+            event_counter   m_nRemoveAfterRLRotation;    ///< Count of removal required after right-over-left rotation
+            event_counter   m_nRotateAfterLRRotation;    ///< Count of rotation required after left-over-right rotation
+            event_counter   m_nRemoveAfterLRRotation;    ///< Count of removal required after left-over-right rotation
+
+            event_counter   m_nInsertRebalanceReq;  ///< Count of rebalance required after inserting
+            event_counter   m_nRemoveRebalanceReq;  ///< Count of rebalance required after removing
+
             //@cond
             void onFindSuccess()        { ++m_nFindSuccess      ; }
             void onFindFailed()         { ++m_nFindFailed       ; }
             void onFindRetry()          { ++m_nFindRetry        ; }
             void onFindWaitShrinking()  { ++m_nFindWaitShrinking; }
 
-            void onInsertSuccess()          { ++m_nInsertSuccess    ; }
+            void onInsertSuccess()          { ++m_nInsertSuccess; }
+            void onInsertFailed()           { ++m_nInsertFailed; }
             void onRelaxedInsertFailed()    { ++m_nRelaxedInsertFailed; }
             void onInsertRetry()            { ++m_nInsertRetry      ; }
             void onUpdateWaitShrinking()    { ++m_nUpdateWaitShrinking; }
@@ -200,11 +240,45 @@ namespace cds { namespace container {
             void onDisposeNode()            { ++m_nDisposedNode; }
             void onDisposeValue()           { ++m_nDisposedValue; }
             void onExtractValue()           { ++m_nExtractedValue; }
+            void onRemove(bool bSuccess)
+            {
+                if ( bSuccess )
+                    ++m_nRemoveSuccess;
+                else
+                    ++m_nRemoveFailed;
+            }
+            void onExtract( bool bSuccess )
+            {
+                if ( bSuccess )
+                    ++m_nExtractSuccess;
+                else
+                    ++m_nExtractFailed;
+            }
+            void onRemoveRetry()            { ++m_nRemoveRetry; }
+            void onRemoveWaitShrinking()    { ++m_nRemoveWaitShrinking; }
+            void onRemoveRootWaitShrinking() { ++m_nRemoveRootWaitShrinking; }
+            void onMakeRoutingNode()        { ++m_nMakeRoutingNode; }
 
             void onRotateRight()            { ++m_nRightRotation; }
             void onRotateLeft()             { ++m_nLeftRotation; }
             void onRotateRightOverLeft()    { ++m_nRightLeftRotation; }
-            void onRotateLeftOverRight()    { ++m_nLeftRghtRotation; }
+            void onRotateLeftOverRight()    { ++m_nLeftRightRotation; }
+
+            void onRotateAfterRightRotation() { ++m_nRotateAfterRightRotation; }
+            void onRemoveAfterRightRotation() { ++m_nRemoveAfterRightRotation; }
+            void onDamageAfterRightRotation() { ++m_nDamageAfterRightRotation; }
+
+            void onRotateAfterLeftRotation()  { ++m_nRotateAfterLeftRotation; }
+            void onRemoveAfterLeftRotation()  { ++m_nRemoveAfterLeftRotation; }
+            void onDamageAfterLeftRotation()  { ++m_nDamageAfterLeftRotation; }
+
+            void onRotateAfterRLRotation()    { ++m_nRotateAfterRLRotation; }
+            void onRemoveAfterRLRotation()    { ++m_nRemoveAfterRLRotation; }
+            void onRotateAfterLRRotation()    { ++m_nRotateAfterLRRotation; }
+            void onRemoveAfterLRRotation()    { ++m_nRemoveAfterLRRotation; }
+
+            void onInsertRebalanceRequired() { ++m_nInsertRebalanceReq; }
+            void onRemoveRebalanceRequired() { ++m_nRemoveRebalanceReq; }
             //@endcond
         };
 
@@ -217,6 +291,7 @@ namespace cds { namespace container {
             void onFindWaitShrinking()  const {}
 
             void onInsertSuccess()          const {}
+            void onInsertFailed()           const {}
             void onRelaxedInsertFailed()    const {}
             void onInsertRetry()            const {}
             void onUpdateWaitShrinking()    const {}
@@ -227,23 +302,45 @@ namespace cds { namespace container {
             void onDisposeNode()            const {}
             void onDisposeValue()           const {}
             void onExtractValue()           const {}
+            void onRemove(bool /*bSuccess*/) const {}
+            void onExtract(bool /*bSuccess*/) const {}
+            void onRemoveRetry()            const {}
+            void onRemoveWaitShrinking()    const {}
+            void onRemoveRootWaitShrinking() const {}
+            void onMakeRoutingNode()        const {}
 
             void onRotateRight()            const {}
             void onRotateLeft()             const {}
             void onRotateRightOverLeft()    const {}
             void onRotateLeftOverRight()    const {}
+
+            void onRotateAfterRightRotation() const {}
+            void onRemoveAfterRightRotation() const {}
+            void onDamageAfterRightRotation() const {}
+
+            void onRotateAfterLeftRotation()  const {}
+            void onRemoveAfterLeftRotation()  const {}
+            void onDamageAfterLeftRotation()  const {}
+
+            void onRotateAfterRLRotation()    const {}
+            void onRemoveAfterRLRotation()    const {}
+            void onRotateAfterLRRotation()    const {}
+            void onRemoveAfterLRRotation()    const {}
+
+            void onInsertRebalanceRequired() const {}
+            void onRemoveRebalanceRequired() const {}
             //@endcond
         };
 
-        /// Option to allow relaxed insert into Bronson et al AVL-tree
+        /// Option to allow relaxed insert into \ref cds_container_BronsonAVLTreeMap_rcu "Bronson et al AVL-tree"
         /**
-            By default, this opton is disabled and the new node is created under its parent lock.
+            By default, this option is disabled and the new node is created under its parent lock.
             In this case, it is guaranteed the new node will be attached to its parent.
             On the other hand, constructing of the new node can be too complex to make it under the lock,
             that can lead to lock contention.
 
             When this option is enabled, the new node is created before locking the parent node.
-            After that, the parent is locked and checked whether the new node can be attached to the parent.
+            After that, the parent is locked and checked whether the new node may be attached to the parent.
             In this case, false node creating can be performed, but locked section can be significantly small.
         */
         template <bool Enable>
@@ -256,11 +353,11 @@ namespace cds { namespace container {
             //@endcond
         };
 
-        /// BronsnAVLTreeMap traits
+        /// \p BronsonAVLTreeMap traits
         /**
             Note that there are two main specialization of Bronson et al AVL-tree:
-            - pointer-oriented - the tree node stores an user-provided pointer to value: <tt>BronsonAVLTreeMap<GC, Key, T *, Traits> </tt>
-            - data-oriented - the tree node contains a copy of values: <tt>BronsonAVLTreeMap<GC, Key, T, Traits> </tt> where \p T is not a pointer type.
+            - \ref cds_container_BronsonAVLTreeMap_rcu_ptr "pointer-oriented" - the tree node stores an user-provided pointer to value
+            - \ref cds_container_BronsonAVLTreeMap_rcu "data-oriented" - the tree node contains a copy of values
 
             Depends on tree specialization, different traits member can be used.
         */
@@ -294,7 +391,7 @@ namespace cds { namespace container {
             /**
                 The functor used for dispose removed values.
                 The user-provided disposer is used only for pointer-oriented tree specialization
-                like \p BronsonAVLTreeMap<GC, Key, T*, Traits>. When the node becomes the rounting node without value,
+                like \p BronsonAVLTreeMap<GC, Key, T*, Traits>. When the node becomes the routing node without value,
                 the disposer will be called to signal that the memory for the value can be safely freed.
                 Default is \ref cds::intrusive::opt::delete_disposer "cds::container::opt::v::delete_disposer<>" which calls \p delete operator.
             */
@@ -343,8 +440,8 @@ namespace cds { namespace container {
         /// Metafunction converting option list to BronsonAVLTreeMap traits
         /**
             Note that there are two main specialization of Bronson et al AVL-tree:
-            - pointer-oriented - the tree node stores an user-provided pointer to value: <tt>BronsonAVLTreeMap<GC, Key, T *, Traits> </tt>
-            - data-oriented - the tree node contains a copy of values: <tt>BronsonAVLTreeMap<GC, Key, T, Traits> </tt> where \p T is not a pointer type.
+            - \ref cds_container_BronsonAVLTreeMap_rcu_ptr "pointer-oriented" - the tree node stores an user-provided pointer to value
+            - \ref cds_container_BronsonAVLTreeMap_rcu "data-oriented" - the tree node contains a copy of values
 
             Depends on tree specialization, different options can be specified.
 
@@ -363,7 +460,7 @@ namespace cds { namespace container {
                 Due the nature of GC schema the disposer may be called asynchronously.
             - \p opt::sync_monitor -  @ref cds_sync_monitor "synchronization monitor" type for node-level locking,
                 default is \p cds::sync::injecting_monitor<cds::sync::spin>
-            - \p bronson_avltree::relaxed_insert - enable (\p true) or disable (\p false, the default) 
+            - \p bronson_avltree::relaxed_insert - enable (\p true) or disable (\p false, the default)
                 @ref bronson_avltree::relaxed_insert "relaxed insertion"
             - \p opt::item_counter - the type of item counting feature, by default it is disabled (\p atomicity::empty_item_counter)
                 To enable it use \p atomicity::item_counter
@@ -393,5 +490,4 @@ namespace cds { namespace container {
 
 }} // namespace cds::container
 
-
 #endif // #ifndef CDSLIB_CONTAINER_DETAILS_BRONSON_AVLTREE_BASE_H