BronsonAVLTreeMap: fixed extract_min/max functions
authorkhizmax <libcds.dev@gmail.com>
Fri, 3 Feb 2017 20:54:07 +0000 (23:54 +0300)
committerkhizmax <libcds.dev@gmail.com>
Fri, 3 Feb 2017 20:54:07 +0000 (23:54 +0300)
cds/container/details/bronson_avltree_base.h
cds/container/impl/bronson_avltree_map_rcu.h
test/stress/map/map_type_bronson_avltree.h

index c4fe4de4875ed9820132148fb5443117142962c3..9f83ba23446e4d9175f81da01c9f4ad2575bfd71 100644 (file)
@@ -450,15 +450,15 @@ namespace cds { namespace container {
 
             /// Internal statistics
             /**
-                By default, internal statistics is disabled (\p ellen_bintree::empty_stat).
-                To enable it use \p ellen_bintree::stat.
+                By default, internal statistics is disabled (\p bronson_avltree::empty_stat).
+                To enable it use \p bronson_avltree::stat.
             */
             typedef empty_stat                      stat;
 
             /// Back-off strategy
             typedef cds::backoff::empty             back_off;
 
-            /// RCU deadlock checking policy (only for \ref cds_container_BronsonAVLTreeMap_rcu "RCU-based BronsonAVLTree")
+            /// RCU deadlock checking policy
             /**
                 List of available options see \p opt::rcu_check_deadlock
             */
index 746ffae470d85248bafe54e0560622ad24f7f770..a7d682fefc6b8d87b0ee9ded2725831806dee58c 100644 (file)
@@ -1339,21 +1339,36 @@ namespace cds { namespace container {
                 nVersion = stack[pos].nVersion;
 
                 while ( true ) {
-                    node_type * pChild = child( pNode, nDir, memory_model::memory_order_acquire );
+                    int iterDir = nDir;
+                    node_type * pChild = child( pNode, iterDir, memory_model::memory_order_acquire );
                     if ( pNode->version(memory_model::memory_order_acquire) != nVersion ) {
                         --pos;
                         m_stat.onRemoveRetry();
                         break;
                     }
 
-                    if ( pChild == nullptr ) {
+                    if ( !pChild ) {
                         // Found min/max
-                        int result = try_remove_node( pParent, pNode, nVersion, func, disp );
-                        if ( result != update_flags::retry )
-                            return result;
-                        --pos;
-                        m_stat.onRemoveRetry();
-                        break;
+                        if ( pNode->is_valued( memory_model::memory_order_acquire ) ) {
+                            int result = try_remove_node( pParent, pNode, nVersion, func, disp );
+
+                            if ( result == update_flags::result_removed )
+                                return result;
+
+                            --pos;
+                            m_stat.onRemoveRetry();
+                            break;
+                        }
+                        else {
+                            // check right (for min) or left (for max) child node
+                            iterDir = -iterDir;
+                            pChild = child( pNode, iterDir, memory_model::memory_order_acquire );
+                            if ( !pChild ) {
+                                --pos;
+                                m_stat.onRemoveRetry();
+                                break;
+                            }
+                        }
                     }
 
                     version_type nChildVersion = pChild->version( memory_model::memory_order_acquire );
@@ -1362,7 +1377,7 @@ namespace cds { namespace container {
                         pChild->template wait_until_shrink_completed<back_off>( memory_model::memory_order_acquire );
                         // retry
                     }
-                    else if ( pChild == child( pNode, nDir, memory_model::memory_order_acquire )) {
+                    else if ( pChild == child( pNode, iterDir, memory_model::memory_order_acquire )) {
                         // this second read is important, because it is protected by nChildVersion
 
                         // validate the read that our caller took to get to node
@@ -1848,13 +1863,9 @@ namespace cds { namespace container {
             if ( pLRight != nullptr )
                 pLRight->parent( pNode, memory_model::memory_order_release  );
 
-            atomics::atomic_thread_fence( memory_model::memory_order_release );
-
             pLeft->m_pRight.store( pNode, memory_model::memory_order_release );
             pNode->parent( pLeft, memory_model::memory_order_release );
 
-            atomics::atomic_thread_fence( memory_model::memory_order_release );
-
             if ( pParentLeft == pNode )
                 pParent->m_pLeft.store( pLeft, memory_model::memory_order_release );
             else {
@@ -1863,8 +1874,6 @@ namespace cds { namespace container {
             }
             pLeft->parent( pParent, memory_model::memory_order_release );
 
-            atomics::atomic_thread_fence( memory_model::memory_order_release );
-
             // fix up heights links
             int hNode = 1 + std::max( hLR, hR );
             set_height( pNode, hNode, memory_model::memory_order_release );
@@ -1924,13 +1933,9 @@ namespace cds { namespace container {
             if ( pRLeft != nullptr )
                 pRLeft->parent( pNode, memory_model::memory_order_release );
 
-            atomics::atomic_thread_fence( memory_model::memory_order_release );
-
             pRight->m_pLeft.store( pNode, memory_model::memory_order_release );
             pNode->parent( pRight, memory_model::memory_order_release );
 
-            atomics::atomic_thread_fence( memory_model::memory_order_release );
-
             if ( pParentLeft == pNode )
                 pParent->m_pLeft.store( pRight, memory_model::memory_order_release );
             else {
@@ -1939,8 +1944,6 @@ namespace cds { namespace container {
             }
             pRight->parent( pParent, memory_model::memory_order_release );
 
-            atomics::atomic_thread_fence( memory_model::memory_order_release );
-
             // fix up heights
             int hNode = 1 + std::max( hL, hRL );
             set_height( pNode, hNode, memory_model::memory_order_release );
index 7f6ee03a8657217fc856af1d6890caf2a3607a90..58a55b458c1273fe9d548ac67dfd62928f49a06c 100644 (file)
@@ -190,7 +190,7 @@ namespace map {
             {
                 EXPECT_TRUE( false ) << "Tree violation on level=" << nLevel << ": hLeft=" << hLeft << ", hRight=" << hRight;
             });
-        EXPECT_TRUE( check_consistency_result );
+        EXPECT_TRUE( check_consistency_result ) << "Internal tree structure violation";
     }