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
void onRotateRightOverLeft() { ++m_nRightLeftRotation; }
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
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
}
}
else if ( nChildVersion != node_type::unlinked ) {
- if ( pNode->version( memory_model::memory_order_acquire ) != nVersion ) {
+ if ( pNode->version(memory_model::memory_order_acquire) != nVersion ) {
m_stat.onFindRetry();
return find_result::retry;
}
if ( pLRight != nullptr )
pLRight->m_pParent.store( pNode, memory_model::memory_order_relaxed );
+ atomics::atomic_thread_fence( memory_model::memory_order_acq_rel );
+
pLeft->m_pRight.store( pNode, memory_model::memory_order_relaxed );
pNode->m_pParent.store( pLeft, memory_model::memory_order_relaxed );
+ atomics::atomic_thread_fence( memory_model::memory_order_acq_rel );
+
if ( pParentLeft == pNode )
pParent->m_pLeft.store( pLeft, memory_model::memory_order_relaxed );
else {
}
pLeft->m_pParent.store( pParent, memory_model::memory_order_relaxed );
+ atomics::atomic_thread_fence( memory_model::memory_order_acq_rel );
+
// fix up heights links
int hNode = 1 + std::max( hLR, hR );
set_height( pNode, hNode );
int nodeBalance = hLR - hR;
if ( nodeBalance < -1 || nodeBalance > 1 ) {
// we need another rotation at pNode
+ m_stat.onRotateAfterRightRotation();
return pNode;
}
// extra-routing node damage
if ( (pLRight == nullptr || hR == 0) && !pNode->is_valued(memory_model::memory_order_relaxed)) {
// we need to remove pNode and then repair
+ m_stat.onRemoveAfterRightRotation();
return pNode;
}
// we've already fixed the height at pLeft, do we need a rotation here?
int leftBalance = hLL - hNode;
- if ( leftBalance < -1 || leftBalance > 1 )
+ if ( leftBalance < -1 || leftBalance > 1 ) {
+ m_stat.onRotateAfterRightRotation();
return pLeft;
+ }
// pLeft might also have routing node damage (if pLeft.left was null)
- if ( hLL == 0 && !pLeft->is_valued( memory_model::memory_order_relaxed ))
+ if ( hLL == 0 && !pLeft->is_valued(memory_model::memory_order_relaxed) ) {
+ m_stat.onDamageAfterRightRotation();
return pLeft;
+ }
// try to fix the parent height while we've still got the lock
return fix_height_locked( pParent );
if ( pRLeft != nullptr )
pRLeft->m_pParent.store( pNode, memory_model::memory_order_relaxed );
+ atomics::atomic_thread_fence( memory_model::memory_order_acq_rel );
+
pRight->m_pLeft.store( pNode, memory_model::memory_order_relaxed );
pNode->m_pParent.store( pRight, memory_model::memory_order_relaxed );
+ atomics::atomic_thread_fence( memory_model::memory_order_acq_rel );
+
if ( pParentLeft == pNode )
pParent->m_pLeft.store( pRight, memory_model::memory_order_relaxed );
else {
}
pRight->m_pParent.store( pParent, memory_model::memory_order_relaxed );
+ atomics::atomic_thread_fence( memory_model::memory_order_acq_rel );
+
// fix up heights
int hNode = 1 + std::max( hL, hRL );
set_height( pNode, hNode );
m_stat.onRotateLeft();
int nodeBalance = hRL - hL;
- if ( nodeBalance < -1 || nodeBalance > 1 )
+ if ( nodeBalance < -1 || nodeBalance > 1 ) {
+ m_stat.onRotateAfterLeftRotation();
return pNode;
+ }
- if ( (pRLeft == nullptr || hL == 0) && !pNode->is_valued( memory_model::memory_order_relaxed ))
+ if ( (pRLeft == nullptr || hL == 0) && !pNode->is_valued(memory_model::memory_order_relaxed) ) {
+ m_stat.onRemoveAfterLeftRotation();
return pNode;
+ }
int rightBalance = hRR - hNode;
- if ( rightBalance < -1 || rightBalance > 1 )
+ if ( rightBalance < -1 || rightBalance > 1 ) {
+ m_stat.onRotateAfterLeftRotation();
return pRight;
+ }
- if ( hRR == 0 && !pRight->is_valued( memory_model::memory_order_relaxed ))
+ if ( hRR == 0 && !pRight->is_valued(memory_model::memory_order_relaxed) ) {
+ m_stat.onDamageAfterLeftRotation();
return pRight;
+ }
return fix_height_locked( pParent );
}
pNode->m_pLeft.store( pLRR, memory_model::memory_order_relaxed );
if ( pLRR != nullptr )
pLRR->m_pParent.store( pNode, memory_model::memory_order_relaxed );
+ atomics::atomic_thread_fence( memory_model::memory_order_acq_rel );
pLeft->m_pRight.store( pLRL, memory_model::memory_order_relaxed );
if ( pLRL != nullptr )
pLRL->m_pParent.store( pLeft, memory_model::memory_order_relaxed );
+ atomics::atomic_thread_fence( memory_model::memory_order_acq_rel );
pLRight->m_pLeft.store( pLeft, memory_model::memory_order_relaxed );
pLeft->m_pParent.store( pLRight, memory_model::memory_order_relaxed );
+ atomics::atomic_thread_fence( memory_model::memory_order_acq_rel );
+
pLRight->m_pRight.store( pNode, memory_model::memory_order_relaxed );
pNode->m_pParent.store( pLRight, memory_model::memory_order_relaxed );
+ atomics::atomic_thread_fence( memory_model::memory_order_acq_rel );
if ( pPL == pNode )
pParent->m_pLeft.store( pLRight, memory_model::memory_order_relaxed );
pParent->m_pRight.store( pLRight, memory_model::memory_order_relaxed );
}
pLRight->m_pParent.store( pParent, memory_model::memory_order_relaxed );
+ atomics::atomic_thread_fence( memory_model::memory_order_acq_rel );
// fix up heights
int hNode = 1 + std::max( hLRR, hR );
int nodeBalance = hLRR - hR;
if ( nodeBalance < -1 || nodeBalance > 1 ) {
// we need another rotation at pNode
+ m_stat.onRotateAfterRLRotation();
return pNode;
}
// pNode might also be damaged by being an unnecessary routing node
if ( (pLRR == nullptr || hR == 0) && !pNode->is_valued( memory_model::memory_order_relaxed )) {
// repair involves splicing out pNode and maybe more rotations
+ m_stat.onRemoveAfterRLRotation();
return pNode;
}
// we've already fixed the height at pLRight, do we need a rotation here?
int balanceLR = hLeft - hNode;
- if ( balanceLR < -1 || balanceLR > 1 )
+ if ( balanceLR < -1 || balanceLR > 1 ) {
+ m_stat.onRotateAfterRLRotation();
return pLRight;
+ }
// try to fix the parent height while we've still got the lock
return fix_height_locked( pParent );
pNode->m_pRight.store( pRLL, memory_model::memory_order_relaxed );
if ( pRLL != nullptr )
pRLL->m_pParent.store( pNode, memory_model::memory_order_relaxed );
+ atomics::atomic_thread_fence( memory_model::memory_order_acq_rel );
pRight->m_pLeft.store( pRLR, memory_model::memory_order_relaxed );
if ( pRLR != nullptr )
pRLR->m_pParent.store( pRight, memory_model::memory_order_relaxed );
+ atomics::atomic_thread_fence( memory_model::memory_order_acq_rel );
pRLeft->m_pRight.store( pRight, memory_model::memory_order_relaxed );
pRight->m_pParent.store( pRLeft, memory_model::memory_order_relaxed );
+ atomics::atomic_thread_fence( memory_model::memory_order_acq_rel );
+
pRLeft->m_pLeft.store( pNode, memory_model::memory_order_relaxed );
pNode->m_pParent.store( pRLeft, memory_model::memory_order_relaxed );
+ atomics::atomic_thread_fence( memory_model::memory_order_acq_rel );
if ( pPL == pNode )
pParent->m_pLeft.store( pRLeft, memory_model::memory_order_relaxed );
pParent->m_pRight.store( pRLeft, memory_model::memory_order_relaxed );
}
pRLeft->m_pParent.store( pParent, memory_model::memory_order_relaxed );
+ atomics::atomic_thread_fence( memory_model::memory_order_acq_rel );
// fix up heights
int hNode = 1 + std::max( hL, hRLL );
assert( hRR - hRLR <= 1 && hRLR - hRR <= 1 );
int nodeBalance = hRLL - hL;
- if ( nodeBalance < -1 || nodeBalance > 1 )
+ if ( nodeBalance < -1 || nodeBalance > 1 ) {
+ m_stat.onRotateAfterLRRotation();
return pNode;
- if ( (pRLL == nullptr || hL == 0) && !pNode->is_valued( memory_model::memory_order_relaxed ))
+ }
+
+ if ( (pRLL == nullptr || hL == 0) && !pNode->is_valued(memory_model::memory_order_relaxed) ) {
+ m_stat.onRemoveAfterLRRotation();
return pNode;
+ }
int balRL = hRight - hNode;
- if ( balRL < -1 || balRL > 1 )
+ if ( balRL < -1 || balRL > 1 ) {
+ m_stat.onRotateAfterLRRotation();
return pRLeft;
+ }
return fix_height_locked( pParent );
}
static inline ostream& operator <<(ostream& o, cds::container::bronson_avltree::stat<> const& s)
{
return o << "\nBronsonAVLTree statistics [cds::container::bronson_avltree::stat]:\n"
- << "\t\t m_nFindSuccess: " << s.m_nFindSuccess.get() << "\n"
- << "\t\t m_nFindFailed: " << s.m_nFindFailed.get() << "\n"
- << "\t\t m_nFindRetry: " << s.m_nFindRetry.get() << "\n"
- << "\t\t m_nFindWaitShrinking: " << s.m_nFindWaitShrinking.get() << "\n"
- << "\t\t m_nInsertSuccess: " << s.m_nInsertSuccess.get() << "\n"
- << "\t\t m_nRelaxedInsertFailed: " << s.m_nRelaxedInsertFailed.get() << "\n"
- << "\t\t m_nInsertRetry: " << s.m_nInsertRetry.get() << "\n"
- << "\t\t m_nUpdateWaitShrinking: " << s.m_nUpdateWaitShrinking.get() << "\n"
- << "\t\t m_nUpdateRetry: " << s.m_nUpdateRetry.get() << "\n"
- << "\t\tm_nUpdateRootWaitShrinking: " << s.m_nUpdateRootWaitShrinking.get() << "\n"
- << "\t\t m_nUpdateSuccess: " << s.m_nUpdateSuccess.get() << "\n"
- << "\t\t m_nUpdateUnlinked: " << s.m_nUpdateUnlinked.get() << "\n"
- << "\t\t m_nRemoveRetry: " << s.m_nRemoveRetry.get() << "\n"
- << "\t\t m_nRemoveWaitShrinking: " << s.m_nRemoveWaitShrinking.get() << "\n"
- << "\t\tm_nRemoveRootWaitShrinking: " << s.m_nRemoveRootWaitShrinking.get() << "\n"
- << "\t\t m_nDisposedValue: " << s.m_nDisposedValue.get() << "\n"
- << "\t\t m_nDisposedNode: " << s.m_nDisposedNode.get() << "\n"
- << "\t\t m_nExtractedValue: " << s.m_nExtractedValue.get() << "\n"
- << "\t\t m_nRightRotation: " << s.m_nRightRotation.get() << "\n"
- << "\t\t m_nLeftRotation: " << s.m_nLeftRotation.get() << "\n"
- << "\t\t m_nLeftRightRotation: " << s.m_nLeftRightRotation.get() << "\n"
- << "\t\t m_nRightLeftRotation: " << s.m_nRightLeftRotation.get() << "\n"
- << "\t\t m_nInsertRebalanceReq: " << s.m_nInsertRebalanceReq.get() << "\n"
- << "\t\t m_nRemoveRebalanceReq: " << s.m_nRemoveRebalanceReq.get() << "\n"
- ;
+ << "\t\t m_nFindSuccess: " << s.m_nFindSuccess.get() << "\n"
+ << "\t\t m_nFindFailed: " << s.m_nFindFailed.get() << "\n"
+ << "\t\t m_nFindRetry: " << s.m_nFindRetry.get() << "\n"
+ << "\t\t m_nFindWaitShrinking: " << s.m_nFindWaitShrinking.get() << "\n"
+ << "\t\t m_nInsertSuccess: " << s.m_nInsertSuccess.get() << "\n"
+ << "\t\t m_nRelaxedInsertFailed: " << s.m_nRelaxedInsertFailed.get() << "\n"
+ << "\t\t m_nInsertRetry: " << s.m_nInsertRetry.get() << "\n"
+ << "\t\t m_nUpdateWaitShrinking: " << s.m_nUpdateWaitShrinking.get() << "\n"
+ << "\t\t m_nUpdateRetry: " << s.m_nUpdateRetry.get() << "\n"
+ << "\t\t m_nUpdateRootWaitShrinking: " << s.m_nUpdateRootWaitShrinking.get() << "\n"
+ << "\t\t m_nUpdateSuccess: " << s.m_nUpdateSuccess.get() << "\n"
+ << "\t\t m_nUpdateUnlinked: " << s.m_nUpdateUnlinked.get() << "\n"
+ << "\t\t m_nRemoveRetry: " << s.m_nRemoveRetry.get() << "\n"
+ << "\t\t m_nRemoveWaitShrinking: " << s.m_nRemoveWaitShrinking.get() << "\n"
+ << "\t\t m_nRemoveRootWaitShrinking: " << s.m_nRemoveRootWaitShrinking.get() << "\n"
+ << "\t\t m_nDisposedValue: " << s.m_nDisposedValue.get() << "\n"
+ << "\t\t m_nDisposedNode: " << s.m_nDisposedNode.get() << "\n"
+ << "\t\t m_nExtractedValue: " << s.m_nExtractedValue.get() << "\n"
+ << "\t\t m_nRightRotation: " << s.m_nRightRotation.get() << "\n"
+ << "\t\t m_nLeftRotation: " << s.m_nLeftRotation.get() << "\n"
+ << "\t\t m_nLeftRightRotation: " << s.m_nLeftRightRotation.get() << "\n"
+ << "\t\t m_nRightLeftRotation: " << s.m_nRightLeftRotation.get() << "\n"
+ << "\t\t m_nInsertRebalanceReq: " << s.m_nInsertRebalanceReq.get() << "\n"
+ << "\t\t m_nRemoveRebalanceReq: " << s.m_nRemoveRebalanceReq.get() << "\n"
+ << "\t\tm_nRotateAfterRightRotation: " << s.m_nRotateAfterRightRotation.get() << "\n"
+ << "\t\tm_nRemoveAfterRightRotation: " << s.m_nRemoveAfterRightRotation.get() << "\n"
+ << "\t\tm_nDamageAfterRightRotation: " << s.m_nDamageAfterRightRotation.get() << "\n"
+ << "\t\t m_nRotateAfterLeftRotation: " << s.m_nRotateAfterLeftRotation.get() << "\n"
+ << "\t\t m_nRemoveAfterLeftRotation: " << s.m_nRemoveAfterLeftRotation.get() << "\n"
+ << "\t\t m_nDamageAfterLeftRotation: " << s.m_nDamageAfterLeftRotation.get() << "\n"
+ << "\t\t m_nRotateAfterRLRotation: " << s.m_nRotateAfterRLRotation.get() << "\n"
+ << "\t\t m_nRemoveAfterRLRotation: " << s.m_nRemoveAfterRLRotation.get() << "\n"
+ << "\t\t m_nRotateAfterLRRotation: " << s.m_nRotateAfterLRRotation.get() << "\n"
+ << "\t\t m_nRemoveAfterLRRotation: " << s.m_nRemoveAfterLRRotation.get() << "\n";
}
} //namespace std