From 35ab98de8b15c243de8bc192ffe5e8099b540fcd Mon Sep 17 00:00:00 2001 From: Danila Klimenko Date: Mon, 15 Jun 2015 23:03:33 +0200 Subject: [PATCH] chromatic_tree: lock-free implementation (with rebalancing) --- containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-inl.h | 318 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------------------------------------------------------------------------------------------------------------------- containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-rebalance.h | 1910 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ containers_cpp/include/embb/containers/lock_free_chromatic_tree.h | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------- containers_cpp/test/tree_test-inl.h | 10 +++++----- 4 files changed, 1420 insertions(+), 914 deletions(-) diff --git a/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-inl.h b/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-inl.h index c7383eb..42625d8 100644 --- a/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-inl.h +++ b/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-inl.h @@ -626,59 +626,69 @@ FreeOperation(Operation* operation) { template bool ChromaticTree:: CleanUp(const Key& key) { - (void)(key); + HazardNodePtr grandgrandparent(GetNodeGuard(HIDX_GRANDGRANDPARENT)); + HazardNodePtr grandparent(GetNodeGuard(HIDX_GRANDPARENT)); + HazardNodePtr parent(GetNodeGuard(HIDX_PARENT)); + HazardNodePtr leaf(GetNodeGuard(HIDX_LEAF)); + bool reached_leaf = false; + + while (!reached_leaf) { + bool found_violation = false; + + grandgrandparent.ProtectSafe(entry_); + grandparent.ProtectSafe(entry_); + parent.ProtectSafe(entry_); + leaf.ProtectSafe(entry_); + + reached_leaf = IsLeaf(leaf); + while (!reached_leaf && !found_violation) { + grandgrandparent.AdoptHazard(grandparent); + grandparent.AdoptHazard(parent); + parent.AdoptHazard(leaf); + + AtomicNodePtr& next_leaf = + (IsSentinel(leaf) || compare_(key, leaf->GetKey())) ? + leaf->GetLeft() : leaf->GetRight(); + + // Parent is protected, so we can tolerate a changing child pointer + while(!leaf.ProtectHazard(next_leaf)); + + // Parent is retired - make sure it is actually removed from the tree + if (parent->IsRetired()) { + HazardOperationPtr op(GetOperationGuard(HIDX_HELPING)); + if (op.ProtectHazard(parent->GetOperation())) { + op->HelpCommit(GetNodeGuard(HIDX_HELPING)); + } + // Can't follow a child pointer in a retired node - restart from root + break; + } + + VERIFY_ADDRESS(static_cast(leaf)); + + // Check for violations + if ((leaf->GetWeight() > 1) || (leaf->GetWeight() == 0 && + parent->GetWeight() == 0)) { + if (Rebalance(grandgrandparent, grandparent, parent, leaf) == + EMBB_NOMEM) { + assert(false && "No memory for rebalancing!"); + return false; + } + break; + } + + reached_leaf = IsLeaf(leaf); + } + } + return true; -// HazardNodePtr grandgrandparent(node_hazard_manager_.GetGuardedPointer(0)); -// HazardNodePtr grandparent (node_hazard_manager_.GetGuardedPointer(1)); -// HazardNodePtr parent (node_hazard_manager_.GetGuardedPointer(2)); -// HazardNodePtr leaf (node_hazard_manager_.GetGuardedPointer(3)); -// bool reached_leaf = false; -// -// while (!reached_leaf) { -// bool found_violation = false; -// -// grandgrandparent.ProtectSafe(entry_); -// grandparent.ProtectSafe(entry_); -// parent.ProtectSafe(entry_); -// leaf.ProtectHazard(entry_->GetLeft()); -// if (parent->IsRetired() || !leaf.IsActive()) continue; -// -// reached_leaf = IsLeaf(leaf); -// while (!reached_leaf && !found_violation) { -// grandgrandparent.AdoptGuard(grandparent); -// grandparent.AdoptGuard(parent); -// parent.AdoptGuard(leaf); -// leaf.ProtectHazard((IsSentinel(leaf) || compare_(key, leaf->GetKey())) ? -// leaf->GetLeft() : leaf->GetRight()); -// if (parent->IsRetired() || !leaf.IsActive()) break; -// VERIFY_ADDRESS(static_cast(leaf)); -// -// found_violation = (leaf->GetWeight() > 1) || -// (leaf->GetWeight() == 0 && parent->GetWeight() == 0); -// -// reached_leaf = IsLeaf(leaf); -// } -// -// if (found_violation) { -// reached_leaf = false; -// -// if (Rebalance(grandgrandparent, grandparent, parent, leaf) == -// EMBB_NOMEM) { -// assert(false && "No memory for rebalancing!"); -// return false; -// } -// } -// } -// -// return true; } -#define PROTECT_NODE_WITH_LOCK(node, lock_name) \ - UniqueLock lock_name(node->GetMutex(), embb::base::try_lock); \ - if (!lock_name.OwnsLock() || node->IsRetired()) return EMBB_BUSY; +#define PROTECT_NODE_WITH_LLX(h_idx, node, op_name) \ + HazardOperationPtr op_name(GetOperationGuard(h_idx)); \ + if (!WeakLLX(node, op_name)) return EMBB_BUSY -#define DEFINE_NODE_WITH_HAZARD(h_num, node, parent, method) \ - HazardNodePtr node(node_hazard_manager_.GetGuardedPointer(h_num)); \ +#define DEFINE_HAZARDOUS_NODE(h_idx, node, parent, method) \ + HazardNodePtr node(GetNodeGuard(h_idx)); \ node.ProtectHazard(parent->method()); \ if (parent->IsRetired() || !node.IsActive()) return EMBB_BUSY; \ VERIFY_ADDRESS(static_cast(node)) @@ -688,24 +698,24 @@ embb_errors_t ChromaticTree:: Rebalance(HazardNodePtr& u, HazardNodePtr& ux, HazardNodePtr& uxx, HazardNodePtr& uxxx) { // Protect node 'u' - PROTECT_NODE_WITH_LOCK(u, u_lock); + PROTECT_NODE_WITH_LLX(HIDX_U, u, u_op); // Verify that ux is still a child of u if (!HasChild(u, ux)) return EMBB_BUSY; // Protect node 'ux' - PROTECT_NODE_WITH_LOCK(ux, ux_lock); + PROTECT_NODE_WITH_LLX(HIDX_UX, ux, ux_op); // Get children of 'ux' - DEFINE_NODE_WITH_HAZARD(4, uxl, ux, GetLeft); - DEFINE_NODE_WITH_HAZARD(5, uxr, ux, GetRight); + DEFINE_HAZARDOUS_NODE(HIDX_UXL, uxl, ux, GetLeft); + DEFINE_HAZARDOUS_NODE(HIDX_UXR, uxr, ux, GetRight); // Verify that 'uxx' is still a child of 'ux' bool uxx_is_left = (uxx == uxl); (void)uxx_is_left; if (!HasChild(ux, uxx)) return EMBB_BUSY; // Protect node 'uxx' - PROTECT_NODE_WITH_LOCK(uxx, uxx_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXX, uxx, uxx_op); // Get children of 'uxx' - DEFINE_NODE_WITH_HAZARD(6, uxxl, uxx, GetLeft); - DEFINE_NODE_WITH_HAZARD(7, uxxr, uxx, GetRight); + DEFINE_HAZARDOUS_NODE(HIDX_UXXL, uxxl, uxx, GetLeft); + DEFINE_HAZARDOUS_NODE(HIDX_UXXR, uxxr, uxx, GetRight); // Verify that 'uxxx' is still a child of 'uxx' bool uxxx_is_left = (uxxx == uxxl); if (!HasChild(uxx, uxxx)) return EMBB_BUSY; @@ -713,40 +723,40 @@ Rebalance(HazardNodePtr& u, HazardNodePtr& ux, HazardNodePtr& uxx, if (uxxx->GetWeight() > 1) { if (uxxx_is_left) { // Protect node 'uxxl' - PROTECT_NODE_WITH_LOCK(uxxl, uxxl_lock); - return OverweightLeft(u, u_lock, ux, ux_lock, uxx, uxx_lock, uxl, uxr, - uxxl, uxxl_lock, uxxr, uxx_is_left); + PROTECT_NODE_WITH_LLX(HIDX_UXXL, uxxl, uxxl_op); + return OverweightLeft(u, u_op, ux, ux_op, uxx, uxx_op, uxl, uxr, + uxxl, uxxl_op, uxxr, uxx_is_left); } else { // Protect node 'uxxr' - PROTECT_NODE_WITH_LOCK(uxxr, uxxr_lock); - return OverweightRight(u, u_lock, ux, ux_lock, uxx, uxx_lock, uxl, uxr, - uxxl, uxxr, uxxr_lock, !uxx_is_left); + PROTECT_NODE_WITH_LLX(HIDX_UXXR, uxxr, uxxr_op); + return OverweightRight(u, u_op, ux, ux_op, uxx, uxx_op, uxl, uxr, + uxxl, uxxr, uxxr_op, !uxx_is_left); } } else { assert(uxxx->GetWeight() == 0 && uxx->GetWeight() == 0); //Red-red violation if (uxx_is_left) { if (uxr->GetWeight() == 0) { // Protect node 'uxr' - PROTECT_NODE_WITH_LOCK(uxr, uxr_lock); - return BLK(u, u_lock, ux, ux_lock, uxx, uxx_lock, uxr, uxr_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXR, uxr, uxr_op); + return BLK(u, u_op, ux, ux_op, uxx, uxx_op, uxr, uxr_op); } else if (uxxx_is_left) { - return RB1_L(u, u_lock, ux, ux_lock, uxx, uxx_lock); + return RB1_L(u, u_op, ux, ux_op, uxx, uxx_op); } else { // Protect node 'uxxr' - PROTECT_NODE_WITH_LOCK(uxxr, uxxr_lock); - return RB2_L(u, u_lock, ux, ux_lock, uxx, uxx_lock, uxxr, uxxr_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXXR, uxxr, uxxr_op); + return RB2_L(u, u_op, ux, ux_op, uxx, uxx_op, uxxr, uxxr_op); } } else { if (uxl->GetWeight() == 0) { // Protect node 'uxl' - PROTECT_NODE_WITH_LOCK(uxl, uxl_lock); - return BLK(u, u_lock, ux, ux_lock, uxl, uxl_lock, uxx, uxx_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXL, uxl, uxl_op); + return BLK(u, u_op, ux, ux_op, uxl, uxl_op, uxx, uxx_op); } else if (!uxxx_is_left) { - return RB1_R(u, u_lock, ux, ux_lock, uxx, uxx_lock); + return RB1_R(u, u_op, ux, ux_op, uxx, uxx_op); } else { // Protect node 'uxxl' - PROTECT_NODE_WITH_LOCK(uxxl, uxxl_lock); - return RB2_R(u, u_lock, ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXXL, uxxl, uxxl_op); + return RB2_R(u, u_op, ux, ux_op, uxx, uxx_op, uxxl, uxxl_op); } } } @@ -754,11 +764,11 @@ Rebalance(HazardNodePtr& u, HazardNodePtr& ux, HazardNodePtr& uxx, template embb_errors_t ChromaticTree:: -OverweightLeft(HazardNodePtr& u, UniqueLock& u_lock, - HazardNodePtr& ux, UniqueLock& ux_lock, - HazardNodePtr& uxx, UniqueLock& uxx_lock, +OverweightLeft(HazardNodePtr& u, HazardOperationPtr& u_op, + HazardNodePtr& ux, HazardOperationPtr& ux_op, + HazardNodePtr& uxx, HazardOperationPtr& uxx_op, HazardNodePtr& uxl, HazardNodePtr& uxr, - HazardNodePtr& uxxl, UniqueLock& uxxl_lock, + HazardNodePtr& uxxl, HazardOperationPtr& uxxl_op, HazardNodePtr& uxxr, bool uxx_is_left) { // Let "Root" be the top of the overweight violation decision tree (see p.30) // Root -> Middle @@ -770,15 +780,15 @@ OverweightLeft(HazardNodePtr& u, UniqueLock& u_lock, // Root -> Middle -> Left -> Left -> Left if (uxr->GetWeight() == 0) { // Protect node 'uxr' - PROTECT_NODE_WITH_LOCK(uxr, uxr_lock); - return BLK(u, u_lock, ux, ux_lock, uxx, uxx_lock, uxr, uxr_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXR, uxr, uxr_op); + return BLK(u, u_op, ux, ux_op, uxx, uxx_op, uxr, uxr_op); // Root -> Middle -> Left -> Left -> Right } else { assert(uxr->GetWeight() > 0); // Protect node 'uxxr' - PROTECT_NODE_WITH_LOCK(uxxr, uxxr_lock); - return RB2_L(u, u_lock, ux, ux_lock, uxx, uxx_lock, uxxr, uxxr_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXXR, uxxr, uxxr_op); + return RB2_L(u, u_op, ux, ux_op, uxx, uxx_op, uxxr, uxxr_op); } // Root -> Middle -> Left -> Right @@ -787,13 +797,13 @@ OverweightLeft(HazardNodePtr& u, UniqueLock& u_lock, // Root -> Middle -> Left -> Right -> Left if (uxl->GetWeight() == 0) { // Protect node 'uxl' - PROTECT_NODE_WITH_LOCK(uxl, uxl_lock); - return BLK(u, u_lock, ux, ux_lock, uxl, uxl_lock, uxx, uxx_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXL, uxl, uxl_op); + return BLK(u, u_op, ux, ux_op, uxl, uxl_op, uxx, uxx_op); // Root -> Middle -> Left -> Right -> Right } else { assert(uxl->GetWeight() > 0); - return RB1_R(u, u_lock, ux, ux_lock, uxx, uxx_lock); + return RB1_R(u, u_op, ux, ux_op, uxx, uxx_op); } } @@ -801,75 +811,75 @@ OverweightLeft(HazardNodePtr& u, UniqueLock& u_lock, } else { assert(uxx->GetWeight() > 0); // Protect node 'uxxr' - PROTECT_NODE_WITH_LOCK(uxxr, uxxr_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXXR, uxxr, uxxr_op); // Get left child of 'uxxr' // Note: we know that 'uxxr' is not a leaf because it has weight 0. - DEFINE_NODE_WITH_HAZARD(8, uxxrl, uxxr, GetLeft); + DEFINE_HAZARDOUS_NODE(HIDX_UXXRL, uxxrl, uxxr, GetLeft); // Protect node 'uxxrl' - PROTECT_NODE_WITH_LOCK(uxxrl, uxxrl_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXXRL, uxxrl, uxxrl_op); // Root -> Middle -> Right -> Left if (uxxrl->GetWeight() == 0) { - return RB2_R(ux, ux_lock, uxx, uxx_lock, - uxxr, uxxr_lock, uxxrl, uxxrl_lock); + return RB2_R(ux, ux_op, uxx, uxx_op, + uxxr, uxxr_op, uxxrl, uxxrl_op); // Root -> Middle -> Right -> Middle } else if (uxxrl->GetWeight() == 1) { - DEFINE_NODE_WITH_HAZARD(9, uxxrlr, uxxrl, GetRight); + DEFINE_HAZARDOUS_NODE(HIDX_UXXRLR, uxxrlr, uxxrl, GetRight); if (uxxrlr == NULL) return EMBB_BUSY; // Root -> Middle -> Right -> Middle -> Left if (uxxrlr->GetWeight() == 0) { // Protect node 'uxxrlr' - PROTECT_NODE_WITH_LOCK(uxxrlr, uxxrlr_lock); - return W4_L(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, - uxxr, uxxr_lock, uxxrl, uxxrl_lock, uxxrlr, uxxrlr_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXXRLR, uxxrlr, uxxrlr_op); + return W4_L(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op, + uxxr, uxxr_op, uxxrl, uxxrl_op, uxxrlr, uxxrlr_op); // Root -> Middle -> Right -> Middle -> Right } else { assert(uxxrlr->GetWeight() > 0); // Root -> Middle -> Right -> Middle -> Right -> Left // Node: reusing hazard of node 'uxxrlr' as it is no longer used - DEFINE_NODE_WITH_HAZARD(9, uxxrll, uxxrl, GetLeft); + DEFINE_HAZARDOUS_NODE(HIDX_UXXRLL, uxxrll, uxxrl, GetLeft); if (uxxrll->GetWeight() == 0) { // Protect node 'uxxrll' - PROTECT_NODE_WITH_LOCK(uxxrll, uxxrll_lock); - return W3_L(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, uxxr, - uxxr_lock, uxxrl, uxxrl_lock, uxxrll, uxxrll_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXXRLL, uxxrll, uxxrll_op); + return W3_L(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op, uxxr, + uxxr_op, uxxrl, uxxrl_op, uxxrll, uxxrll_op); // Root -> Middle -> Right -> Middle -> Right -> Right } else { assert(uxxrll->GetWeight() > 0); - return W2_L(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, - uxxr, uxxr_lock, uxxrl, uxxrl_lock); + return W2_L(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op, + uxxr, uxxr_op, uxxrl, uxxrl_op); } } // Root -> Middle -> Right -> Right } else { assert(uxxrl->GetWeight() > 1); - return W1_L(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, - uxxr, uxxr_lock, uxxrl, uxxrl_lock); + return W1_L(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op, + uxxr, uxxr_op, uxxrl, uxxrl_op); } } // Root -> Right } else if (uxxr->GetWeight() == 1) { // Protect node 'uxxr' - PROTECT_NODE_WITH_LOCK(uxxr, uxxr_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXXR, uxxr, uxxr_op); // Get children of 'uxxr' - DEFINE_NODE_WITH_HAZARD(8, uxxrl, uxxr, GetLeft); - DEFINE_NODE_WITH_HAZARD(9, uxxrr, uxxr, GetRight); + DEFINE_HAZARDOUS_NODE(HIDX_UXXRL, uxxrl, uxxr, GetLeft); + DEFINE_HAZARDOUS_NODE(HIDX_UXXRR, uxxrr, uxxr, GetRight); if (uxxrl == NULL) return EMBB_BUSY; // Root -> Right -> Left if (uxxrr->GetWeight() == 0) { // Protect node 'uxxrr' - PROTECT_NODE_WITH_LOCK(uxxrr, uxxrr_lock); - return W5_L(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, - uxxr, uxxr_lock, uxxrr, uxxrr_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXXRR, uxxrr, uxxrr_op); + return W5_L(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op, + uxxr, uxxr_op, uxxrr, uxxrr_op); // Root -> Right -> Right } else { @@ -877,15 +887,15 @@ OverweightLeft(HazardNodePtr& u, UniqueLock& u_lock, // Root -> Right -> Right -> Left if (uxxrl->GetWeight() == 0) { // Protect node 'uxxrl' - PROTECT_NODE_WITH_LOCK(uxxrl, uxxrl_lock); - return W6_L(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, - uxxr, uxxr_lock, uxxrl, uxxrl_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXXRL, uxxrl, uxxrl_op); + return W6_L(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op, + uxxr, uxxr_op, uxxrl, uxxrl_op); // Root -> Right -> Right -> Right } else { assert(uxxrl->GetWeight() > 0); - return PUSH_L(ux, ux_lock, uxx, uxx_lock, - uxxl, uxxl_lock, uxxr, uxxr_lock); + return PUSH_L(ux, ux_op, uxx, uxx_op, + uxxl, uxxl_op, uxxr, uxxr_op); } } @@ -893,19 +903,19 @@ OverweightLeft(HazardNodePtr& u, UniqueLock& u_lock, } else { assert(uxxr->GetWeight() > 1); // Protect node 'uxxr' - PROTECT_NODE_WITH_LOCK(uxxr, uxxr_lock); - return W7(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, uxxr, uxxr_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXXR, uxxr, uxxr_op); + return W7(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op, uxxr, uxxr_op); } } template embb_errors_t ChromaticTree:: -OverweightRight(HazardNodePtr& u, UniqueLock& u_lock, - HazardNodePtr& ux, UniqueLock& ux_lock, - HazardNodePtr& uxx, UniqueLock& uxx_lock, +OverweightRight(HazardNodePtr& u, HazardOperationPtr& u_op, + HazardNodePtr& ux, HazardOperationPtr& ux_op, + HazardNodePtr& uxx, HazardOperationPtr& uxx_op, HazardNodePtr& uxl, HazardNodePtr& uxr, HazardNodePtr& uxxl, HazardNodePtr& uxxr, - UniqueLock& uxxr_lock, bool uxx_is_right) { + HazardOperationPtr& uxxr_op, bool uxx_is_right) { // Let "Root" be the top of the overweight violation decision tree (see p.30) // Root -> Middle if (uxxl->GetWeight() == 0) { @@ -916,15 +926,15 @@ OverweightRight(HazardNodePtr& u, UniqueLock& u_lock, // Root -> Middle -> Left -> Left -> Left if (uxl->GetWeight() == 0) { // Protect node 'uxl' - PROTECT_NODE_WITH_LOCK(uxl, uxl_lock); - return BLK(u, u_lock, ux, ux_lock, uxl, uxl_lock, uxx, uxx_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXL, uxl, uxl_op); + return BLK(u, u_op, ux, ux_op, uxl, uxl_op, uxx, uxx_op); // Root -> Middle -> Left -> Left -> Right } else { assert(uxl->GetWeight() > 0); // Protect node 'uxxl' - PROTECT_NODE_WITH_LOCK(uxxl, uxxl_lock); - return RB2_R(u, u_lock, ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXXL, uxxl, uxxl_op); + return RB2_R(u, u_op, ux, ux_op, uxx, uxx_op, uxxl, uxxl_op); } // Root -> Middle -> Left -> Right @@ -933,13 +943,13 @@ OverweightRight(HazardNodePtr& u, UniqueLock& u_lock, // Root -> Middle -> Left -> Right -> Left if (uxr->GetWeight() == 0) { // Protect node 'uxr' - PROTECT_NODE_WITH_LOCK(uxr, uxr_lock); - return BLK(u, u_lock, ux, ux_lock, uxx, uxx_lock, uxr, uxr_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXR, uxr, uxr_op); + return BLK(u, u_op, ux, ux_op, uxx, uxx_op, uxr, uxr_op); // Root -> Middle -> Left -> Right -> Right } else { assert(uxr->GetWeight() > 0); - return RB1_L(u, u_lock, ux, ux_lock, uxx, uxx_lock); + return RB1_L(u, u_op, ux, ux_op, uxx, uxx_op); } } @@ -947,75 +957,75 @@ OverweightRight(HazardNodePtr& u, UniqueLock& u_lock, } else { assert(uxx->GetWeight() > 0); // Protect node 'uxxl' - PROTECT_NODE_WITH_LOCK(uxxl, uxxl_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXXL, uxxl, uxxl_op); // Get left child of 'uxxl' // Note: we know that 'uxxl' is not a leaf because it has weight 0. - DEFINE_NODE_WITH_HAZARD(8, uxxlr, uxxl, GetRight); + DEFINE_HAZARDOUS_NODE(HIDX_UXXLR, uxxlr, uxxl, GetRight); // Protect node 'uxxlr' - PROTECT_NODE_WITH_LOCK(uxxlr, uxxlr_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXXLR, uxxlr, uxxlr_op); // Root -> Middle -> Right -> Left if (uxxlr->GetWeight() == 0) { - return RB2_L(ux, ux_lock, uxx, uxx_lock, - uxxl, uxxl_lock, uxxlr, uxxlr_lock); + return RB2_L(ux, ux_op, uxx, uxx_op, + uxxl, uxxl_op, uxxlr, uxxlr_op); // Root -> Middle -> Right -> Middle } else if (uxxlr->GetWeight() == 1) { - DEFINE_NODE_WITH_HAZARD(9, uxxlrl, uxxlr, GetLeft); + DEFINE_HAZARDOUS_NODE(HIDX_UXXLRL, uxxlrl, uxxlr, GetLeft); if (uxxlrl == NULL) return EMBB_BUSY; // Root -> Middle -> Right -> Middle -> Left if (uxxlrl->GetWeight() == 0) { // Protect node 'uxxlrl' - PROTECT_NODE_WITH_LOCK(uxxlrl, uxxlrl_lock); - return W4_R(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, - uxxr, uxxr_lock, uxxlr, uxxlr_lock, uxxlrl, uxxlrl_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXXLRL, uxxlrl, uxxlrl_op); + return W4_R(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op, + uxxr, uxxr_op, uxxlr, uxxlr_op, uxxlrl, uxxlrl_op); // Root -> Middle -> Right -> Middle -> Right } else { assert(uxxlrl->GetWeight() > 0); // Root -> Middle -> Right -> Middle -> Right -> Left // Node: reusing hazard of node 'uxxlrl' as it is no longer used - DEFINE_NODE_WITH_HAZARD(9, uxxlrr, uxxlr, GetRight); + DEFINE_HAZARDOUS_NODE(HIDX_UXXLRR, uxxlrr, uxxlr, GetRight); if (uxxlrr->GetWeight() == 0) { // Protect node 'uxxlrr' - PROTECT_NODE_WITH_LOCK(uxxlrr, uxxlrr_lock); - return W3_R(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, uxxr, - uxxr_lock, uxxlr, uxxlr_lock, uxxlrr, uxxlrr_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXXLRR, uxxlrr, uxxlrr_op); + return W3_R(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op, uxxr, + uxxr_op, uxxlr, uxxlr_op, uxxlrr, uxxlrr_op); // Root -> Middle -> Right -> Middle -> Right -> Right } else { assert(uxxlrr->GetWeight() > 0); - return W2_R(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, - uxxr, uxxr_lock, uxxlr, uxxlr_lock); + return W2_R(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op, + uxxr, uxxr_op, uxxlr, uxxlr_op); } } // Root -> Middle -> Right -> Right } else { assert(uxxlr->GetWeight() > 1); - return W1_R(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, - uxxr, uxxr_lock, uxxlr, uxxlr_lock); + return W1_R(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op, + uxxr, uxxr_op, uxxlr, uxxlr_op); } } // Root -> Right } else if (uxxl->GetWeight() == 1) { // Protect node 'uxxl' - PROTECT_NODE_WITH_LOCK(uxxl, uxxl_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXXL, uxxl, uxxl_op); // Get children of 'uxxl' - DEFINE_NODE_WITH_HAZARD(8, uxxll, uxxl, GetLeft); - DEFINE_NODE_WITH_HAZARD(9, uxxlr, uxxl, GetRight); + DEFINE_HAZARDOUS_NODE(HIDX_UXXLL, uxxll, uxxl, GetLeft); + DEFINE_HAZARDOUS_NODE(HIDX_UXXLR, uxxlr, uxxl, GetRight); if (uxxll == NULL) return EMBB_BUSY; // Root -> Right -> Left if (uxxll->GetWeight() == 0) { // Protect node 'uxxll' - PROTECT_NODE_WITH_LOCK(uxxll, uxxll_lock); - return W5_R(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, - uxxr, uxxr_lock, uxxll, uxxll_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXXLL, uxxll, uxxll_op); + return W5_R(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op, + uxxr, uxxr_op, uxxll, uxxll_op); // Root -> Right -> Right } else { @@ -1023,15 +1033,15 @@ OverweightRight(HazardNodePtr& u, UniqueLock& u_lock, // Root -> Right -> Right -> Left if (uxxlr->GetWeight() == 0) { // Protect node 'uxxlr' - PROTECT_NODE_WITH_LOCK(uxxlr, uxxlr_lock); - return W6_R(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, - uxxr, uxxr_lock, uxxlr, uxxlr_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXXLR, uxxlr, uxxlr_op); + return W6_R(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op, + uxxr, uxxr_op, uxxlr, uxxlr_op); // Root -> Right -> Right -> Right } else { assert(uxxlr->GetWeight() > 0); - return PUSH_R(ux, ux_lock, uxx, uxx_lock, - uxxl, uxxl_lock, uxxr, uxxr_lock); + return PUSH_R(ux, ux_op, uxx, uxx_op, + uxxl, uxxl_op, uxxr, uxxr_op); } } @@ -1039,8 +1049,8 @@ OverweightRight(HazardNodePtr& u, UniqueLock& u_lock, } else { assert(uxxl->GetWeight() > 1); // Protect node 'uxxl' - PROTECT_NODE_WITH_LOCK(uxxl, uxxl_lock); - return W7(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, uxxr, uxxr_lock); + PROTECT_NODE_WITH_LLX(HIDX_UXXL, uxxl, uxxl_op); + return W7(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op, uxxr, uxxr_op); } } diff --git a/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-rebalance.h b/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-rebalance.h index f96d75c..f6b5117 100644 --- a/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-rebalance.h +++ b/containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-rebalance.h @@ -32,896 +32,1330 @@ #ifndef EMBB_CONTAINERS_INTERNAL_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_ #define EMBB_CONTAINERS_INTERNAL_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_ -embb_errors_t BLK( - HazardNodePtr& u, UniqueLock& u_lock, - HazardNodePtr& ux, UniqueLock& ux_lock, - HazardNodePtr& uxl, UniqueLock& uxl_lock, - HazardNodePtr& uxr, UniqueLock& uxr_lock) { - Node* nxl = node_pool_.Allocate( - uxl->GetKey(), uxl->GetValue(), - 1, - uxl->GetLeft(), uxl->GetRight()); - Node* nxr = node_pool_.Allocate( - uxr->GetKey(), uxr->GetValue(), - 1, - uxr->GetLeft(), uxr->GetRight()); - Node* nx = node_pool_.Allocate( - ux->GetKey(), ux->GetValue(), - IsSentinel(u) ? 1 : ux->GetWeight() - 1, - nxl, nxr); - - if (nxl == NULL || - nxr == NULL || - nx == NULL) { +embb_errors_t BLK(HazardNodePtr& u, HazardOperationPtr& u_op, + HazardNodePtr& ux, HazardOperationPtr& ux_op, + HazardNodePtr& uxl, HazardOperationPtr& uxl_op, + HazardNodePtr& uxr, HazardOperationPtr& uxr_op) { + embb_errors_t result = EMBB_NOMEM; + Node* nxl; + Node* nxr; + Node* nx; + + while (result != EMBB_SUCCESS) { + nxl = node_pool_.Allocate( + uxl->GetKey(), uxl->GetValue(), 1, + uxl->GetLeft(), uxl->GetRight(), Operation::INITIAL_DUMMY); + if (nxl == NULL) break; + nxr = node_pool_.Allocate( + uxr->GetKey(), uxr->GetValue(), 1, + uxr->GetLeft(), uxr->GetRight(), Operation::INITIAL_DUMMY); + if (nxr == NULL) break; + nx = node_pool_.Allocate( + ux->GetKey(), ux->GetValue(), IsSentinel(u) ? 1 : ux->GetWeight() - 1, + nxl, nxr, Operation::INITIAL_DUMMY); + if (nx == NULL) break; + + HazardOperationPtr op(GetOperationGuard(HIDX_CURRENT_OP)); + op.ProtectSafe(operation_pool_.Allocate()); + if (op == NULL) break; + + op->SetRoot(u, u_op); + op->SetNewChild(nx); + op->SetOldNodes(ux, ux_op, + uxl, uxl_op, + uxr, uxr_op); + + bool succeeded = op->Help(GetNodeGuard(HIDX_HELPING), + GetOperationGuard(HIDX_HELPING)); + op->CleanUp(); + + if (!succeeded) { + RetireOperation(op); + result = EMBB_BUSY; + break; + } + + RetireOperation(u_op); + RetireNode(ux); RetireOperation(ux_op); + RetireNode(uxl); RetireOperation(uxl_op); + RetireNode(uxr); RetireOperation(uxr_op); + + result = EMBB_SUCCESS; + } + + if (result != EMBB_SUCCESS) { if (nxl) FreeNode(nxl); if (nxr) FreeNode(nxr); if (nx) FreeNode(nx); - return EMBB_NOMEM; } - bool rotation_succeeded = u->ReplaceChild(ux, nx); - assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail - if (!rotation_succeeded) return EMBB_BUSY; - - RetireHazardousNode(ux, ux_lock); - RetireHazardousNode(uxl, uxl_lock); - RetireHazardousNode(uxr, uxr_lock); - (void)u_lock; // For now (FGL tree) u_lock is not used here - - return EMBB_SUCCESS; + return result; } -embb_errors_t PUSH_L( - HazardNodePtr& u, UniqueLock& u_lock, - HazardNodePtr& ux, UniqueLock& ux_lock, - HazardNodePtr& uxl, UniqueLock& uxl_lock, - HazardNodePtr& uxr, UniqueLock& uxr_lock) { - Node* nxl = node_pool_.Allocate( - uxl->GetKey(), uxl->GetValue(), - uxl->GetWeight() - 1, - uxl->GetLeft(), uxl->GetRight()); - Node* nxr = node_pool_.Allocate( - uxr->GetKey(), uxr->GetValue(), - 0, - uxr->GetLeft(), uxr->GetRight()); - Node* nx = node_pool_.Allocate( - ux->GetKey(), ux->GetValue(), - IsSentinel(u) ? 1 : ux->GetWeight() + 1, - nxl, nxr); - - if (nxl == NULL || - nxr == NULL || - nx == NULL) { +embb_errors_t PUSH_L(HazardNodePtr& u, HazardOperationPtr& u_op, + HazardNodePtr& ux, HazardOperationPtr& ux_op, + HazardNodePtr& uxl, HazardOperationPtr& uxl_op, + HazardNodePtr& uxr, HazardOperationPtr& uxr_op) { + embb_errors_t result = EMBB_NOMEM; + Node* nxl; + Node* nxr; + Node* nx; + + while (result != EMBB_SUCCESS) { + nxl = node_pool_.Allocate( + uxl->GetKey(), uxl->GetValue(), uxl->GetWeight() - 1, + uxl->GetLeft(), uxl->GetRight(), Operation::INITIAL_DUMMY); + if (nxl == NULL) break; + nxr = node_pool_.Allocate( + uxr->GetKey(), uxr->GetValue(), 0, + uxr->GetLeft(), uxr->GetRight(), Operation::INITIAL_DUMMY); + if (nxr == NULL) break; + nx = node_pool_.Allocate( + ux->GetKey(), ux->GetValue(), IsSentinel(u) ? 1 : ux->GetWeight() + 1, + nxl, nxr, Operation::INITIAL_DUMMY); + if (nx == NULL) break; + + HazardOperationPtr op(GetOperationGuard(HIDX_CURRENT_OP)); + op.ProtectSafe(operation_pool_.Allocate()); + if (op == NULL) break; + + op->SetRoot(u, u_op); + op->SetNewChild(nx); + op->SetOldNodes(ux, ux_op, + uxl, uxl_op, + uxr, uxr_op); + + bool succeeded = op->Help(GetNodeGuard(HIDX_HELPING), + GetOperationGuard(HIDX_HELPING)); + op->CleanUp(); + + if (!succeeded) { + RetireOperation(op); + result = EMBB_BUSY; + break; + } + + RetireOperation(u_op); + RetireNode(ux); RetireOperation(ux_op); + RetireNode(uxl); RetireOperation(uxl_op); + RetireNode(uxr); RetireOperation(uxr_op); + + result = EMBB_SUCCESS; + } + + if (result != EMBB_SUCCESS) { if (nxl) FreeNode(nxl); if (nxr) FreeNode(nxr); if (nx) FreeNode(nx); - return EMBB_NOMEM; } - bool rotation_succeeded = u->ReplaceChild(ux, nx); - assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail - if (!rotation_succeeded) return EMBB_BUSY; - - RetireHazardousNode(ux, ux_lock); - RetireHazardousNode(uxl, uxl_lock); - RetireHazardousNode(uxr, uxr_lock); - (void)u_lock; // For now (FGL tree) u_lock is not used here - - return EMBB_SUCCESS; + return result; } -embb_errors_t PUSH_R( - HazardNodePtr& u, UniqueLock& u_lock, - HazardNodePtr& ux, UniqueLock& ux_lock, - HazardNodePtr& uxl, UniqueLock& uxl_lock, - HazardNodePtr& uxr, UniqueLock& uxr_lock) { - Node* nxr = node_pool_.Allocate( - uxr->GetKey(), uxr->GetValue(), - uxr->GetWeight() - 1, - uxr->GetLeft(), uxr->GetRight()); - Node* nxl = node_pool_.Allocate( - uxl->GetKey(), uxl->GetValue(), - 0, - uxl->GetLeft(), uxl->GetRight()); - Node* nx = node_pool_.Allocate( - ux->GetKey(), ux->GetValue(), - IsSentinel(u) ? 1 : ux->GetWeight() + 1, - nxl, nxr); - - if (nxr == NULL || - nxl == NULL || - nx == NULL) { +embb_errors_t PUSH_R(HazardNodePtr& u, HazardOperationPtr& u_op, + HazardNodePtr& ux, HazardOperationPtr& ux_op, + HazardNodePtr& uxl, HazardOperationPtr& uxl_op, + HazardNodePtr& uxr, HazardOperationPtr& uxr_op) { + embb_errors_t result = EMBB_NOMEM; + Node* nxr; + Node* nxl; + Node* nx; + + while (result != EMBB_SUCCESS) { + nxr = node_pool_.Allocate( + uxr->GetKey(), uxr->GetValue(), uxr->GetWeight() - 1, + uxr->GetLeft(), uxr->GetRight(), Operation::INITIAL_DUMMY); + if (nxr == NULL) break; + nxl = node_pool_.Allocate( + uxl->GetKey(), uxl->GetValue(), 0, + uxl->GetLeft(), uxl->GetRight(), Operation::INITIAL_DUMMY); + if (nxl == NULL) break; + nx = node_pool_.Allocate( + ux->GetKey(), ux->GetValue(), IsSentinel(u) ? 1 : ux->GetWeight() + 1, + nxl, nxr, Operation::INITIAL_DUMMY); + if (nx == NULL) break; + + HazardOperationPtr op(GetOperationGuard(HIDX_CURRENT_OP)); + op.ProtectSafe(operation_pool_.Allocate()); + if (op == NULL) break; + + op->SetRoot(u, u_op); + op->SetNewChild(nx); + op->SetOldNodes(ux, ux_op, + uxl, uxl_op, + uxr, uxr_op); + + bool succeeded = op->Help(GetNodeGuard(HIDX_HELPING), + GetOperationGuard(HIDX_HELPING)); + op->CleanUp(); + + if (!succeeded) { + RetireOperation(op); + result = EMBB_BUSY; + break; + } + + RetireOperation(u_op); + RetireNode(ux); RetireOperation(ux_op); + RetireNode(uxl); RetireOperation(uxl_op); + RetireNode(uxr); RetireOperation(uxr_op); + + result = EMBB_SUCCESS; + } + + if (result != EMBB_SUCCESS) { if (nxr) FreeNode(nxr); if (nxl) FreeNode(nxl); if (nx) FreeNode(nx); - return EMBB_NOMEM; } - bool rotation_succeeded = u->ReplaceChild(ux, nx); - assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail - if (!rotation_succeeded) return EMBB_BUSY; - - RetireHazardousNode(ux, ux_lock); - RetireHazardousNode(uxl, uxl_lock); - RetireHazardousNode(uxr, uxr_lock); - (void)u_lock; // For now (FGL tree) u_lock is not used here - - return EMBB_SUCCESS; + return result; } -embb_errors_t RB1_L( - HazardNodePtr& u, UniqueLock& u_lock, - HazardNodePtr& ux, UniqueLock& ux_lock, - HazardNodePtr& uxl, UniqueLock& uxl_lock) { - Node* nxr = node_pool_.Allocate( - ux->GetKey(), ux->GetValue(), - 0, - uxl->GetRight(), ux->GetRight()); - Node* nx = node_pool_.Allocate( - uxl->GetKey(), uxl->GetValue(), - ux->GetWeight(), - uxl->GetLeft(), nxr); - - if (nxr == NULL || - nx == NULL) { +embb_errors_t RB1_L(HazardNodePtr& u, HazardOperationPtr& u_op, + HazardNodePtr& ux, HazardOperationPtr& ux_op, + HazardNodePtr& uxl, HazardOperationPtr& uxl_op) { + embb_errors_t result = EMBB_NOMEM; + Node* nxr; + Node* nx; + + while (result != EMBB_SUCCESS) { + nxr = node_pool_.Allocate( + ux->GetKey(), ux->GetValue(), 0, + uxl->GetRight(), ux->GetRight(), Operation::INITIAL_DUMMY); + if (nxr == NULL) break; + nx = node_pool_.Allocate( + uxl->GetKey(), uxl->GetValue(), ux->GetWeight(), + uxl->GetLeft(), nxr, Operation::INITIAL_DUMMY); + if (nx == NULL) break; + + HazardOperationPtr op(GetOperationGuard(HIDX_CURRENT_OP)); + op.ProtectSafe(operation_pool_.Allocate()); + if (op == NULL) break; + + op->SetRoot(u, u_op); + op->SetNewChild(nx); + op->SetOldNodes(ux, ux_op, + uxl, uxl_op); + + bool succeeded = op->Help(GetNodeGuard(HIDX_HELPING), + GetOperationGuard(HIDX_HELPING)); + op->CleanUp(); + + if (!succeeded) { + RetireOperation(op); + result = EMBB_BUSY; + break; + } + + RetireOperation(u_op); + RetireNode(ux); RetireOperation(ux_op); + RetireNode(uxl); RetireOperation(uxl_op); + + result = EMBB_SUCCESS; + } + + if (result != EMBB_SUCCESS) { if (nxr) FreeNode(nxr); if (nx) FreeNode(nx); - return EMBB_NOMEM; } - bool rotation_succeeded = u->ReplaceChild(ux, nx); - assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail - if (!rotation_succeeded) return EMBB_BUSY; - - RetireHazardousNode(ux, ux_lock); - RetireHazardousNode(uxl, uxl_lock); - (void)u_lock; // For now (FGL tree) u_lock is not used here - - return EMBB_SUCCESS; + return result; } -embb_errors_t RB1_R( - HazardNodePtr& u, UniqueLock& u_lock, - HazardNodePtr& ux, UniqueLock& ux_lock, - HazardNodePtr& uxr, UniqueLock& uxr_lock) { - Node* nxl = node_pool_.Allocate( - ux->GetKey(), ux->GetValue(), - 0, - ux->GetLeft(), uxr->GetLeft()); - Node* nx = node_pool_.Allocate( - uxr->GetKey(), uxr->GetValue(), - ux->GetWeight(), - nxl, uxr->GetRight()); - - if (nxl == NULL || - nx == NULL) { +embb_errors_t RB1_R(HazardNodePtr& u, HazardOperationPtr& u_op, + HazardNodePtr& ux, HazardOperationPtr& ux_op, + HazardNodePtr& uxr, HazardOperationPtr& uxr_op) { + embb_errors_t result = EMBB_NOMEM; + Node* nxl; + Node* nx; + + while (result != EMBB_SUCCESS) { + nxl = node_pool_.Allocate( + ux->GetKey(), ux->GetValue(), 0, + ux->GetLeft(), uxr->GetLeft(), Operation::INITIAL_DUMMY); + if (nxl == NULL) break; + nx = node_pool_.Allocate( + uxr->GetKey(), uxr->GetValue(), ux->GetWeight(), + nxl, uxr->GetRight(), Operation::INITIAL_DUMMY); + if (nx == NULL) break; + + HazardOperationPtr op(GetOperationGuard(HIDX_CURRENT_OP)); + op.ProtectSafe(operation_pool_.Allocate()); + if (op == NULL) break; + + op->SetRoot(u, u_op); + op->SetNewChild(nx); + op->SetOldNodes(ux, ux_op, + uxr, uxr_op); + + bool succeeded = op->Help(GetNodeGuard(HIDX_HELPING), + GetOperationGuard(HIDX_HELPING)); + op->CleanUp(); + + if (!succeeded) { + RetireOperation(op); + result = EMBB_BUSY; + break; + } + + RetireOperation(u_op); + RetireNode(ux); RetireOperation(ux_op); + RetireNode(uxr); RetireOperation(uxr_op); + + result = EMBB_SUCCESS; + } + + if (result != EMBB_SUCCESS) { if (nxl) FreeNode(nxl); if (nx) FreeNode(nx); - return EMBB_NOMEM; } - bool rotation_succeeded = u->ReplaceChild(ux, nx); - assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail - if (!rotation_succeeded) return EMBB_BUSY; - - RetireHazardousNode(ux, ux_lock); - RetireHazardousNode(uxr, uxr_lock); - (void)u_lock; // For now (FGL tree) u_lock is not used here - - return EMBB_SUCCESS; + return result; } -embb_errors_t RB2_L( - HazardNodePtr& u, UniqueLock& u_lock, - HazardNodePtr& ux, UniqueLock& ux_lock, - HazardNodePtr& uxl, UniqueLock& uxl_lock, - HazardNodePtr& uxlr, UniqueLock& uxlr_lock) { - Node* nxl = node_pool_.Allocate( - uxl->GetKey(), uxl->GetValue(), - 0, - uxl->GetLeft(), uxlr->GetLeft()); - Node* nxr = node_pool_.Allocate( - ux->GetKey(), ux->GetValue(), - 0, - uxlr->GetRight(), ux->GetRight()); - Node* nx = node_pool_.Allocate( - uxlr->GetKey(), uxlr->GetValue(), - ux->GetWeight(), - nxl, nxr); - - if (nxl == NULL || - nxr == NULL || - nx == NULL) { +embb_errors_t RB2_L(HazardNodePtr& u, HazardOperationPtr& u_op, + HazardNodePtr& ux, HazardOperationPtr& ux_op, + HazardNodePtr& uxl, HazardOperationPtr& uxl_op, + HazardNodePtr& uxlr, HazardOperationPtr& uxlr_op) { + embb_errors_t result = EMBB_NOMEM; + Node* nxl; + Node* nxr; + Node* nx; + + while (result != EMBB_SUCCESS) { + nxl = node_pool_.Allocate( + uxl->GetKey(), uxl->GetValue(), 0, + uxl->GetLeft(), uxlr->GetLeft(), Operation::INITIAL_DUMMY); + if (nxl == NULL) break; + nxr = node_pool_.Allocate( + ux->GetKey(), ux->GetValue(), 0, + uxlr->GetRight(), ux->GetRight(), Operation::INITIAL_DUMMY); + if (nxr == NULL) break; + nx = node_pool_.Allocate( + uxlr->GetKey(), uxlr->GetValue(), ux->GetWeight(), + nxl, nxr, Operation::INITIAL_DUMMY); + if (nx == NULL) break; + + HazardOperationPtr op(GetOperationGuard(HIDX_CURRENT_OP)); + op.ProtectSafe(operation_pool_.Allocate()); + if (op == NULL) break; + + op->SetRoot(u, u_op); + op->SetNewChild(nx); + op->SetOldNodes(ux, ux_op, + uxl, uxl_op, + uxlr, uxlr_op); + + bool succeeded = op->Help(GetNodeGuard(HIDX_HELPING), + GetOperationGuard(HIDX_HELPING)); + op->CleanUp(); + + if (!succeeded) { + RetireOperation(op); + result = EMBB_BUSY; + break; + } + + RetireOperation(u_op); + RetireNode(ux); RetireOperation(ux_op); + RetireNode(uxl); RetireOperation(uxl_op); + RetireNode(uxlr); RetireOperation(uxlr_op); + + result = EMBB_SUCCESS; + } + + if (result != EMBB_SUCCESS) { if (nxl) FreeNode(nxl); if (nxr) FreeNode(nxr); if (nx) FreeNode(nx); - return EMBB_NOMEM; } - bool rotation_succeeded = u->ReplaceChild(ux, nx); - assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail - if (!rotation_succeeded) return EMBB_BUSY; - - RetireHazardousNode(ux, ux_lock); - RetireHazardousNode(uxl, uxl_lock); - RetireHazardousNode(uxlr, uxlr_lock); - (void)u_lock; // For now (FGL tree) u_lock is not used here - - return EMBB_SUCCESS; + return result; } -embb_errors_t RB2_R( - HazardNodePtr& u, UniqueLock& u_lock, - HazardNodePtr& ux, UniqueLock& ux_lock, - HazardNodePtr& uxr, UniqueLock& uxr_lock, - HazardNodePtr& uxrl, UniqueLock& uxrl_lock) { - Node* nxr = node_pool_.Allocate( - uxr->GetKey(), uxr->GetValue(), - 0, - uxrl->GetRight(), uxr->GetRight()); - Node* nxl = node_pool_.Allocate( - ux->GetKey(), ux->GetValue(), - 0, - ux->GetLeft(), uxrl->GetLeft()); - Node* nx = node_pool_.Allocate( - uxrl->GetKey(), uxrl->GetValue(), - ux->GetWeight(), - nxl, nxr); - - if (nxr == NULL || - nxl == NULL || - nx == NULL) { +embb_errors_t RB2_R(HazardNodePtr& u, HazardOperationPtr& u_op, + HazardNodePtr& ux, HazardOperationPtr& ux_op, + HazardNodePtr& uxr, HazardOperationPtr& uxr_op, + HazardNodePtr& uxrl, HazardOperationPtr& uxrl_op) { + embb_errors_t result = EMBB_NOMEM; + Node* nxr; + Node* nxl; + Node* nx; + + while (result != EMBB_SUCCESS) { + nxr = node_pool_.Allocate( + uxr->GetKey(), uxr->GetValue(), 0, + uxrl->GetRight(), uxr->GetRight(), Operation::INITIAL_DUMMY); + if (nxr == NULL) break; + nxl = node_pool_.Allocate( + ux->GetKey(), ux->GetValue(), 0, + ux->GetLeft(), uxrl->GetLeft(), Operation::INITIAL_DUMMY); + if (nxl == NULL) break; + nx = node_pool_.Allocate( + uxrl->GetKey(), uxrl->GetValue(), ux->GetWeight(), + nxl, nxr, Operation::INITIAL_DUMMY); + if (nx == NULL) break; + + HazardOperationPtr op(GetOperationGuard(HIDX_CURRENT_OP)); + op.ProtectSafe(operation_pool_.Allocate()); + if (op == NULL) break; + + op->SetRoot(u, u_op); + op->SetNewChild(nx); + op->SetOldNodes(ux, ux_op, + uxr, uxr_op, + uxrl, uxrl_op); + + bool succeeded = op->Help(GetNodeGuard(HIDX_HELPING), + GetOperationGuard(HIDX_HELPING)); + op->CleanUp(); + + if (!succeeded) { + RetireOperation(op); + result = EMBB_BUSY; + break; + } + + RetireOperation(u_op); + RetireNode(ux); RetireOperation(ux_op); + RetireNode(uxr); RetireOperation(uxr_op); + RetireNode(uxrl); RetireOperation(uxrl_op); + + result = EMBB_SUCCESS; + } + + if (result != EMBB_SUCCESS) { if (nxr) FreeNode(nxr); if (nxl) FreeNode(nxl); if (nx) FreeNode(nx); - return EMBB_NOMEM; } - bool rotation_succeeded = u->ReplaceChild(ux, nx); - assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail - if (!rotation_succeeded) return EMBB_BUSY; - - RetireHazardousNode(ux, ux_lock); - RetireHazardousNode(uxr, uxr_lock); - RetireHazardousNode(uxrl, uxrl_lock); - (void)u_lock; // For now (FGL tree) u_lock is not used here - - return EMBB_SUCCESS; + return result; } -embb_errors_t W1_L( - HazardNodePtr& u, UniqueLock& u_lock, - HazardNodePtr& ux, UniqueLock& ux_lock, - HazardNodePtr& uxl, UniqueLock& uxl_lock, - HazardNodePtr& uxr, UniqueLock& uxr_lock, - HazardNodePtr& uxrl, UniqueLock& uxrl_lock) { - Node* nxll = node_pool_.Allocate( - uxl->GetKey(), uxl->GetValue(), - uxl->GetWeight() - 1, - uxl->GetLeft(), uxl->GetRight()); - Node* nxlr = node_pool_.Allocate( - uxrl->GetKey(), uxrl->GetValue(), - uxrl->GetWeight() - 1, - uxrl->GetLeft(), uxrl->GetRight()); - Node* nxl = node_pool_.Allocate( - ux->GetKey(), ux->GetValue(), - 1, - nxll, nxlr); - Node* nx = node_pool_.Allocate( - uxr->GetKey(), uxr->GetValue(), - ux->GetWeight(), - nxl, uxr->GetRight()); - - if (nxll == NULL || - nxlr == NULL || - nxl == NULL || - nx == NULL) { +embb_errors_t W1_L(HazardNodePtr& u, HazardOperationPtr& u_op, + HazardNodePtr& ux, HazardOperationPtr& ux_op, + HazardNodePtr& uxl, HazardOperationPtr& uxl_op, + HazardNodePtr& uxr, HazardOperationPtr& uxr_op, + HazardNodePtr& uxrl, HazardOperationPtr& uxrl_op) { + embb_errors_t result = EMBB_NOMEM; + Node* nxll; + Node* nxlr; + Node* nxl; + Node* nx; + + while (result != EMBB_SUCCESS) { + nxll = node_pool_.Allocate( + uxl->GetKey(), uxl->GetValue(), uxl->GetWeight() - 1, + uxl->GetLeft(), uxl->GetRight(), Operation::INITIAL_DUMMY); + if (nxll == NULL) break; + nxlr = node_pool_.Allocate( + uxrl->GetKey(), uxrl->GetValue(), uxrl->GetWeight() - 1, + uxrl->GetLeft(), uxrl->GetRight(), Operation::INITIAL_DUMMY); + if (nxlr == NULL) break; + nxl = node_pool_.Allocate( + ux->GetKey(), ux->GetValue(), 1, + nxll, nxlr, Operation::INITIAL_DUMMY); + if (nxl == NULL) break; + nx = node_pool_.Allocate( + uxr->GetKey(), uxr->GetValue(), ux->GetWeight(), + nxl, uxr->GetRight(), Operation::INITIAL_DUMMY); + if (nx == NULL) break; + + HazardOperationPtr op(GetOperationGuard(HIDX_CURRENT_OP)); + op.ProtectSafe(operation_pool_.Allocate()); + if (op == NULL) break; + + op->SetRoot(u, u_op); + op->SetNewChild(nx); + op->SetOldNodes(ux, ux_op, + uxl, uxl_op, + uxr, uxr_op, + uxrl, uxrl_op); + + bool succeeded = op->Help(GetNodeGuard(HIDX_HELPING), + GetOperationGuard(HIDX_HELPING)); + op->CleanUp(); + + if (!succeeded) { + RetireOperation(op); + result = EMBB_BUSY; + break; + } + + RetireOperation(u_op); + RetireNode(ux); RetireOperation(ux_op); + RetireNode(uxl); RetireOperation(uxl_op); + RetireNode(uxr); RetireOperation(uxr_op); + RetireNode(uxrl); RetireOperation(uxrl_op); + + result = EMBB_SUCCESS; + } + + if (result != EMBB_SUCCESS) { if (nxll) FreeNode(nxll); if (nxlr) FreeNode(nxlr); if (nxl) FreeNode(nxl); if (nx) FreeNode(nx); - return EMBB_NOMEM; } - bool rotation_succeeded = u->ReplaceChild(ux, nx); - assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail - if (!rotation_succeeded) return EMBB_BUSY; - - RetireHazardousNode(ux, ux_lock); - RetireHazardousNode(uxl, uxl_lock); - RetireHazardousNode(uxr, uxr_lock); - RetireHazardousNode(uxrl, uxrl_lock); - (void)u_lock; // For now (FGL tree) u_lock is not used here - - return EMBB_SUCCESS; + return result; } -embb_errors_t W1_R( - HazardNodePtr& u, UniqueLock& u_lock, - HazardNodePtr& ux, UniqueLock& ux_lock, - HazardNodePtr& uxl, UniqueLock& uxl_lock, - HazardNodePtr& uxr, UniqueLock& uxr_lock, - HazardNodePtr& uxlr, UniqueLock& uxlr_lock) { - Node* nxrr = node_pool_.Allocate( - uxr->GetKey(), uxr->GetValue(), - uxr->GetWeight() - 1, - uxr->GetLeft(), uxr->GetRight()); - Node* nxrl = node_pool_.Allocate( - uxlr->GetKey(), uxlr->GetValue(), - uxlr->GetWeight() - 1, - uxlr->GetLeft(), uxlr->GetRight()); - Node* nxr = node_pool_.Allocate( - ux->GetKey(), ux->GetValue(), - 1, - nxrl, nxrr); - Node* nx = node_pool_.Allocate( - uxl->GetKey(), uxl->GetValue(), - ux->GetWeight(), - uxl->GetLeft(), nxr); - - if (nxrr == NULL || - nxrl == NULL || - nxr == NULL || - nx == NULL) { +embb_errors_t W1_R(HazardNodePtr& u, HazardOperationPtr& u_op, + HazardNodePtr& ux, HazardOperationPtr& ux_op, + HazardNodePtr& uxl, HazardOperationPtr& uxl_op, + HazardNodePtr& uxr, HazardOperationPtr& uxr_op, + HazardNodePtr& uxlr, HazardOperationPtr& uxlr_op) { + embb_errors_t result = EMBB_NOMEM; + Node* nxrr; + Node* nxrl; + Node* nxr; + Node* nx; + + while (result != EMBB_SUCCESS) { + nxrr = node_pool_.Allocate( + uxr->GetKey(), uxr->GetValue(), uxr->GetWeight() - 1, + uxr->GetLeft(), uxr->GetRight(), Operation::INITIAL_DUMMY); + if (nxrr == NULL) break; + nxrl = node_pool_.Allocate( + uxlr->GetKey(), uxlr->GetValue(), uxlr->GetWeight() - 1, + uxlr->GetLeft(), uxlr->GetRight(), Operation::INITIAL_DUMMY); + if (nxrl == NULL) break; + nxr = node_pool_.Allocate( + ux->GetKey(), ux->GetValue(), 1, + nxrl, nxrr, Operation::INITIAL_DUMMY); + if (nxr == NULL) break; + nx = node_pool_.Allocate( + uxl->GetKey(), uxl->GetValue(), ux->GetWeight(), + uxl->GetLeft(), nxr, Operation::INITIAL_DUMMY); + if (nx == NULL) break; + + HazardOperationPtr op(GetOperationGuard(HIDX_CURRENT_OP)); + op.ProtectSafe(operation_pool_.Allocate()); + if (op == NULL) break; + + op->SetRoot(u, u_op); + op->SetNewChild(nx); + op->SetOldNodes(ux, ux_op, + uxl, uxl_op, + uxr, uxr_op, + uxlr, uxlr_op); + + bool succeeded = op->Help(GetNodeGuard(HIDX_HELPING), + GetOperationGuard(HIDX_HELPING)); + op->CleanUp(); + + if (!succeeded) { + RetireOperation(op); + result = EMBB_BUSY; + break; + } + + RetireOperation(u_op); + RetireNode(ux); RetireOperation(ux_op); + RetireNode(uxl); RetireOperation(uxl_op); + RetireNode(uxr); RetireOperation(uxr_op); + RetireNode(uxlr); RetireOperation(uxlr_op); + + result = EMBB_SUCCESS; + } + + if (result != EMBB_SUCCESS) { if (nxrr) FreeNode(nxrr); if (nxrl) FreeNode(nxrl); if (nxr) FreeNode(nxr); if (nx) FreeNode(nx); - return EMBB_NOMEM; } - bool rotation_succeeded = u->ReplaceChild(ux, nx); - assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail - if (!rotation_succeeded) return EMBB_BUSY; - - RetireHazardousNode(ux, ux_lock); - RetireHazardousNode(uxl, uxl_lock); - RetireHazardousNode(uxr, uxr_lock); - RetireHazardousNode(uxlr, uxlr_lock); - (void)u_lock; // For now (FGL tree) u_lock is not used here - - return EMBB_SUCCESS; + return result; } -embb_errors_t W2_L( - HazardNodePtr& u, UniqueLock& u_lock, - HazardNodePtr& ux, UniqueLock& ux_lock, - HazardNodePtr& uxl, UniqueLock& uxl_lock, - HazardNodePtr& uxr, UniqueLock& uxr_lock, - HazardNodePtr& uxrl, UniqueLock& uxrl_lock) { - Node* nxll = node_pool_.Allocate( - uxl->GetKey(), uxl->GetValue(), - uxl->GetWeight() - 1, - uxl->GetLeft(), uxl->GetRight()); - Node* nxlr = node_pool_.Allocate( - uxrl->GetKey(), uxrl->GetValue(), - 0, - uxrl->GetLeft(), uxrl->GetRight()); - Node* nxl = node_pool_.Allocate( - ux->GetKey(), ux->GetValue(), - 1, - nxll, nxlr); - Node* nx = node_pool_.Allocate( - uxr->GetKey(), uxr->GetValue(), - ux->GetWeight(), - nxl, uxr->GetRight()); - - if (nxll == NULL || - nxlr == NULL || - nxl == NULL || - nx == NULL) { +embb_errors_t W2_L(HazardNodePtr& u, HazardOperationPtr& u_op, + HazardNodePtr& ux, HazardOperationPtr& ux_op, + HazardNodePtr& uxl, HazardOperationPtr& uxl_op, + HazardNodePtr& uxr, HazardOperationPtr& uxr_op, + HazardNodePtr& uxrl, HazardOperationPtr& uxrl_op) { + embb_errors_t result = EMBB_NOMEM; + Node* nxll; + Node* nxlr; + Node* nxl; + Node* nx; + + while (result != EMBB_SUCCESS) { + nxll = node_pool_.Allocate( + uxl->GetKey(), uxl->GetValue(), uxl->GetWeight() - 1, + uxl->GetLeft(), uxl->GetRight(), Operation::INITIAL_DUMMY); + if (nxll == NULL) break; + nxlr = node_pool_.Allocate( + uxrl->GetKey(), uxrl->GetValue(), 0, + uxrl->GetLeft(), uxrl->GetRight(), Operation::INITIAL_DUMMY); + if (nxlr == NULL) break; + nxl = node_pool_.Allocate( + ux->GetKey(), ux->GetValue(), 1, + nxll, nxlr, Operation::INITIAL_DUMMY); + if (nxl == NULL) break; + nx = node_pool_.Allocate( + uxr->GetKey(), uxr->GetValue(), ux->GetWeight(), + nxl, uxr->GetRight(), Operation::INITIAL_DUMMY); + if (nx == NULL) break; + + HazardOperationPtr op(GetOperationGuard(HIDX_CURRENT_OP)); + op.ProtectSafe(operation_pool_.Allocate()); + if (op == NULL) break; + + op->SetRoot(u, u_op); + op->SetNewChild(nx); + op->SetOldNodes(ux, ux_op, + uxl, uxl_op, + uxr, uxr_op, + uxrl, uxrl_op); + + bool succeeded = op->Help(GetNodeGuard(HIDX_HELPING), + GetOperationGuard(HIDX_HELPING)); + op->CleanUp(); + + if (!succeeded) { + RetireOperation(op); + result = EMBB_BUSY; + break; + } + + RetireOperation(u_op); + RetireNode(ux); RetireOperation(ux_op); + RetireNode(uxl); RetireOperation(uxl_op); + RetireNode(uxr); RetireOperation(uxr_op); + RetireNode(uxrl); RetireOperation(uxrl_op); + + result = EMBB_SUCCESS; + } + + if (result != EMBB_SUCCESS) { if (nxll) FreeNode(nxll); if (nxlr) FreeNode(nxlr); if (nxl) FreeNode(nxl); if (nx) FreeNode(nx); - return EMBB_NOMEM; } - bool rotation_succeeded = u->ReplaceChild(ux, nx); - assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail - if (!rotation_succeeded) return EMBB_BUSY; - - RetireHazardousNode(ux, ux_lock); - RetireHazardousNode(uxl, uxl_lock); - RetireHazardousNode(uxr, uxr_lock); - RetireHazardousNode(uxrl, uxrl_lock); - (void)u_lock; // For now (FGL tree) u_lock is not used here - - return EMBB_SUCCESS; + return result; } -embb_errors_t W2_R( - HazardNodePtr& u, UniqueLock& u_lock, - HazardNodePtr& ux, UniqueLock& ux_lock, - HazardNodePtr& uxl, UniqueLock& uxl_lock, - HazardNodePtr& uxr, UniqueLock& uxr_lock, - HazardNodePtr& uxlr, UniqueLock& uxlr_lock) { - Node* nxrr = node_pool_.Allocate( - uxr->GetKey(), uxr->GetValue(), - uxr->GetWeight() - 1, - uxr->GetLeft(), uxr->GetRight()); - Node* nxrl = node_pool_.Allocate( - uxlr->GetKey(), uxlr->GetValue(), - 0, - uxlr->GetLeft(), uxlr->GetRight()); - Node* nxr = node_pool_.Allocate( - ux->GetKey(), ux->GetValue(), - 1, - nxrl, nxrr); - Node* nx = node_pool_.Allocate( - uxl->GetKey(), uxl->GetValue(), - ux->GetWeight(), - uxl->GetLeft(), nxr); - - if (nxrr == NULL || - nxrl == NULL || - nxr == NULL || - nx == NULL) { +embb_errors_t W2_R(HazardNodePtr& u, HazardOperationPtr& u_op, + HazardNodePtr& ux, HazardOperationPtr& ux_op, + HazardNodePtr& uxl, HazardOperationPtr& uxl_op, + HazardNodePtr& uxr, HazardOperationPtr& uxr_op, + HazardNodePtr& uxlr, HazardOperationPtr& uxlr_op) { + embb_errors_t result = EMBB_NOMEM; + Node* nxrr; + Node* nxrl; + Node* nxr; + Node* nx; + + while (result != EMBB_SUCCESS) { + nxrr = node_pool_.Allocate( + uxr->GetKey(), uxr->GetValue(), uxr->GetWeight() - 1, + uxr->GetLeft(), uxr->GetRight(), Operation::INITIAL_DUMMY); + if (nxrr == NULL) break; + nxrl = node_pool_.Allocate( + uxlr->GetKey(), uxlr->GetValue(), 0, + uxlr->GetLeft(), uxlr->GetRight(), Operation::INITIAL_DUMMY); + if (nxrl == NULL) break; + nxr = node_pool_.Allocate( + ux->GetKey(), ux->GetValue(), 1, + nxrl, nxrr, Operation::INITIAL_DUMMY); + if (nxr == NULL) break; + nx = node_pool_.Allocate( + uxl->GetKey(), uxl->GetValue(), ux->GetWeight(), + uxl->GetLeft(), nxr, Operation::INITIAL_DUMMY); + if (nx == NULL) break; + + HazardOperationPtr op(GetOperationGuard(HIDX_CURRENT_OP)); + op.ProtectSafe(operation_pool_.Allocate()); + if (op == NULL) break; + + op->SetRoot(u, u_op); + op->SetNewChild(nx); + op->SetOldNodes(ux, ux_op, + uxl, uxl_op, + uxr, uxr_op, + uxlr, uxlr_op); + + bool succeeded = op->Help(GetNodeGuard(HIDX_HELPING), + GetOperationGuard(HIDX_HELPING)); + op->CleanUp(); + + if (!succeeded) { + RetireOperation(op); + result = EMBB_BUSY; + break; + } + + RetireOperation(u_op); + RetireNode(ux); RetireOperation(ux_op); + RetireNode(uxl); RetireOperation(uxl_op); + RetireNode(uxr); RetireOperation(uxr_op); + RetireNode(uxlr); RetireOperation(uxlr_op); + + result = EMBB_SUCCESS; + } + + if (result != EMBB_SUCCESS) { if (nxrr) FreeNode(nxrr); if (nxrl) FreeNode(nxrl); if (nxr) FreeNode(nxr); if (nx) FreeNode(nx); - return EMBB_NOMEM; } - bool rotation_succeeded = u->ReplaceChild(ux, nx); - assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail - if (!rotation_succeeded) return EMBB_BUSY; - - RetireHazardousNode(ux, ux_lock); - RetireHazardousNode(uxl, uxl_lock); - RetireHazardousNode(uxr, uxr_lock); - RetireHazardousNode(uxlr, uxlr_lock); - (void)u_lock; // For now (FGL tree) u_lock is not used here - - return EMBB_SUCCESS; + return result; } -embb_errors_t W3_L( - HazardNodePtr& u, UniqueLock& u_lock, - HazardNodePtr& ux, UniqueLock& ux_lock, - HazardNodePtr& uxl, UniqueLock& uxl_lock, - HazardNodePtr& uxr, UniqueLock& uxr_lock, - HazardNodePtr& uxrl, UniqueLock& uxrl_lock, - HazardNodePtr& uxrll, UniqueLock& uxrll_lock) { - Node* nxlll = node_pool_.Allocate( - uxl->GetKey(), uxl->GetValue(), - uxl->GetWeight() - 1, - uxl->GetLeft(), uxl->GetRight()); - Node* nxll = node_pool_.Allocate( - ux->GetKey(), ux->GetValue(), - 1, - nxlll, uxrll->GetLeft()); - Node* nxlr = node_pool_.Allocate( - uxrl->GetKey(), uxrl->GetValue(), - 1, - uxrll->GetRight(), uxrl->GetRight()); - Node* nxl = node_pool_.Allocate( - uxrll->GetKey(), uxrll->GetValue(), - 0, - nxll, nxlr); - Node* nx = node_pool_.Allocate( - uxr->GetKey(), uxr->GetValue(), - ux->GetWeight(), - nxl, uxr->GetRight()); - - if (nxlll == NULL || - nxll == NULL || - nxlr == NULL || - nxl == NULL || - nx == NULL) { +embb_errors_t W3_L(HazardNodePtr& u, HazardOperationPtr& u_op, + HazardNodePtr& ux, HazardOperationPtr& ux_op, + HazardNodePtr& uxl, HazardOperationPtr& uxl_op, + HazardNodePtr& uxr, HazardOperationPtr& uxr_op, + HazardNodePtr& uxrl, HazardOperationPtr& uxrl_op, + HazardNodePtr& uxrll, HazardOperationPtr& uxrll_op) { + embb_errors_t result = EMBB_NOMEM; + Node* nxlll; + Node* nxll; + Node* nxlr; + Node* nxl; + Node* nx; + + while (result != EMBB_SUCCESS) { + nxlll = node_pool_.Allocate( + uxl->GetKey(), uxl->GetValue(), uxl->GetWeight() - 1, + uxl->GetLeft(), uxl->GetRight(), Operation::INITIAL_DUMMY); + if (nxlll == NULL) break; + nxll = node_pool_.Allocate( + ux->GetKey(), ux->GetValue(), 1, + nxlll, uxrll->GetLeft(), Operation::INITIAL_DUMMY); + if (nxll == NULL) break; + nxlr = node_pool_.Allocate( + uxrl->GetKey(), uxrl->GetValue(), 1, + uxrll->GetRight(), uxrl->GetRight(), Operation::INITIAL_DUMMY); + if (nxlr == NULL) break; + nxl = node_pool_.Allocate( + uxrll->GetKey(), uxrll->GetValue(), 0, + nxll, nxlr, Operation::INITIAL_DUMMY); + if (nxl == NULL) break; + nx = node_pool_.Allocate( + uxr->GetKey(), uxr->GetValue(), ux->GetWeight(), + nxl, uxr->GetRight(), Operation::INITIAL_DUMMY); + if (nx == NULL) break; + + HazardOperationPtr op(GetOperationGuard(HIDX_CURRENT_OP)); + op.ProtectSafe(operation_pool_.Allocate()); + if (op == NULL) break; + + op->SetRoot(u, u_op); + op->SetNewChild(nx); + op->SetOldNodes(ux, ux_op, + uxl, uxl_op, + uxr, uxr_op, + uxrl, uxrl_op, + uxrll, uxrll_op); + + bool succeeded = op->Help(GetNodeGuard(HIDX_HELPING), + GetOperationGuard(HIDX_HELPING)); + op->CleanUp(); + + if (!succeeded) { + RetireOperation(op); + result = EMBB_BUSY; + break; + } + + RetireOperation(u_op); + RetireNode(ux); RetireOperation(ux_op); + RetireNode(uxl); RetireOperation(uxl_op); + RetireNode(uxr); RetireOperation(uxr_op); + RetireNode(uxrl); RetireOperation(uxrl_op); + RetireNode(uxrll); RetireOperation(uxrll_op); + + result = EMBB_SUCCESS; + } + + if (result != EMBB_SUCCESS) { if (nxlll) FreeNode(nxlll); if (nxll) FreeNode(nxll); if (nxlr) FreeNode(nxlr); if (nxl) FreeNode(nxl); if (nx) FreeNode(nx); - return EMBB_NOMEM; } - bool rotation_succeeded = u->ReplaceChild(ux, nx); - assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail - if (!rotation_succeeded) return EMBB_BUSY; - - RetireHazardousNode(ux, ux_lock); - RetireHazardousNode(uxl, uxl_lock); - RetireHazardousNode(uxr, uxr_lock); - RetireHazardousNode(uxrl, uxrl_lock); - RetireHazardousNode(uxrll, uxrll_lock); - (void)u_lock; // For now (FGL tree) u_lock is not used here - - return EMBB_SUCCESS; + return result; } -embb_errors_t W3_R( - HazardNodePtr& u, UniqueLock& u_lock, - HazardNodePtr& ux, UniqueLock& ux_lock, - HazardNodePtr& uxl, UniqueLock& uxl_lock, - HazardNodePtr& uxr, UniqueLock& uxr_lock, - HazardNodePtr& uxlr, UniqueLock& uxlr_lock, - HazardNodePtr& uxlrr, UniqueLock& uxlrr_lock) { - Node* nxrrr = node_pool_.Allocate( - uxr->GetKey(), uxr->GetValue(), - uxr->GetWeight() - 1, - uxr->GetLeft(), uxr->GetRight()); - Node* nxrr = node_pool_.Allocate( - ux->GetKey(), ux->GetValue(), - 1, - uxlrr->GetRight(), nxrrr); - Node* nxrl = node_pool_.Allocate( - uxlr->GetKey(), uxlr->GetValue(), - 1, - uxlr->GetLeft(), uxlrr->GetLeft()); - Node* nxr = node_pool_.Allocate( - uxlrr->GetKey(), uxlrr->GetValue(), - 0, - nxrl, nxrr); - Node* nx = node_pool_.Allocate( - uxl->GetKey(), uxl->GetValue(), - ux->GetWeight(), - uxl->GetLeft(), nxr); - - if (nxrrr == NULL || - nxrr == NULL || - nxrl == NULL || - nxr == NULL || - nx == NULL) { +embb_errors_t W3_R(HazardNodePtr& u, HazardOperationPtr& u_op, + HazardNodePtr& ux, HazardOperationPtr& ux_op, + HazardNodePtr& uxl, HazardOperationPtr& uxl_op, + HazardNodePtr& uxr, HazardOperationPtr& uxr_op, + HazardNodePtr& uxlr, HazardOperationPtr& uxlr_op, + HazardNodePtr& uxlrr, HazardOperationPtr& uxlrr_op) { + embb_errors_t result = EMBB_NOMEM; + Node* nxrrr; + Node* nxrr; + Node* nxrl; + Node* nxr; + Node* nx; + + while (result != EMBB_SUCCESS) { + nxrrr = node_pool_.Allocate( + uxr->GetKey(), uxr->GetValue(), uxr->GetWeight() - 1, + uxr->GetLeft(), uxr->GetRight(), Operation::INITIAL_DUMMY); + if (nxrrr == NULL) break; + nxrr = node_pool_.Allocate( + ux->GetKey(), ux->GetValue(), 1, + uxlrr->GetRight(), nxrrr, Operation::INITIAL_DUMMY); + if (nxrr == NULL) break; + nxrl = node_pool_.Allocate( + uxlr->GetKey(), uxlr->GetValue(), 1, + uxlr->GetLeft(), uxlrr->GetLeft(), Operation::INITIAL_DUMMY); + if (nxrl == NULL) break; + nxr = node_pool_.Allocate( + uxlrr->GetKey(), uxlrr->GetValue(), 0, + nxrl, nxrr, Operation::INITIAL_DUMMY); + if (nxr == NULL) break; + nx = node_pool_.Allocate( + uxl->GetKey(), uxl->GetValue(), ux->GetWeight(), + uxl->GetLeft(), nxr, Operation::INITIAL_DUMMY); + if (nx == NULL) break; + + HazardOperationPtr op(GetOperationGuard(HIDX_CURRENT_OP)); + op.ProtectSafe(operation_pool_.Allocate()); + if (op == NULL) break; + + op->SetRoot(u, u_op); + op->SetNewChild(nx); + op->SetOldNodes(ux, ux_op, + uxl, uxl_op, + uxr, uxr_op, + uxlr, uxlr_op, + uxlrr, uxlrr_op); + + bool succeeded = op->Help(GetNodeGuard(HIDX_HELPING), + GetOperationGuard(HIDX_HELPING)); + op->CleanUp(); + + if (!succeeded) { + RetireOperation(op); + result = EMBB_BUSY; + break; + } + + RetireOperation(u_op); + RetireNode(ux); RetireOperation(ux_op); + RetireNode(uxl); RetireOperation(uxl_op); + RetireNode(uxr); RetireOperation(uxr_op); + RetireNode(uxlr); RetireOperation(uxlr_op); + RetireNode(uxlrr); RetireOperation(uxlrr_op); + + result = EMBB_SUCCESS; + } + + if (result != EMBB_SUCCESS) { if (nxrrr) FreeNode(nxrrr); if (nxrr) FreeNode(nxrr); if (nxrl) FreeNode(nxrl); if (nxr) FreeNode(nxr); if (nx) FreeNode(nx); - return EMBB_NOMEM; } - bool rotation_succeeded = u->ReplaceChild(ux, nx); - assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail - if (!rotation_succeeded) return EMBB_BUSY; - - RetireHazardousNode(ux, ux_lock); - RetireHazardousNode(uxl, uxl_lock); - RetireHazardousNode(uxr, uxr_lock); - RetireHazardousNode(uxlr, uxlr_lock); - RetireHazardousNode(uxlrr, uxlrr_lock); - (void)u_lock; // For now (FGL tree) u_lock is not used here - - return EMBB_SUCCESS; + return result; } -embb_errors_t W4_L( - HazardNodePtr& u, UniqueLock& u_lock, - HazardNodePtr& ux, UniqueLock& ux_lock, - HazardNodePtr& uxl, UniqueLock& uxl_lock, - HazardNodePtr& uxr, UniqueLock& uxr_lock, - HazardNodePtr& uxrl, UniqueLock& uxrl_lock, - HazardNodePtr& uxrlr, UniqueLock& uxrlr_lock) { - Node* nxll = node_pool_.Allocate( - uxl->GetKey(), uxl->GetValue(), - uxl->GetWeight() - 1, - uxl->GetLeft(), uxl->GetRight()); - Node* nxrl = node_pool_.Allocate( - uxrlr->GetKey(), uxrlr->GetValue(), - 1, - uxrlr->GetLeft(), uxrlr->GetRight()); - Node* nxl = node_pool_.Allocate( - ux->GetKey(), ux->GetValue(), - 1, - nxll, uxrl->GetLeft()); - Node* nxr = node_pool_.Allocate( - uxr->GetKey(), uxr->GetValue(), - 0, - nxrl, uxr->GetRight()); - Node* nx = node_pool_.Allocate( - uxrl->GetKey(), uxrl->GetValue(), - ux->GetWeight(), - nxl, nxr); - - if (nxll == NULL || - nxrl == NULL || - nxl == NULL || - nxr == NULL || - nx == NULL) { +embb_errors_t W4_L(HazardNodePtr& u, HazardOperationPtr& u_op, + HazardNodePtr& ux, HazardOperationPtr& ux_op, + HazardNodePtr& uxl, HazardOperationPtr& uxl_op, + HazardNodePtr& uxr, HazardOperationPtr& uxr_op, + HazardNodePtr& uxrl, HazardOperationPtr& uxrl_op, + HazardNodePtr& uxrlr, HazardOperationPtr& uxrlr_op) { + embb_errors_t result = EMBB_NOMEM; + Node* nxll; + Node* nxrl; + Node* nxl; + Node* nxr; + Node* nx; + + while (result != EMBB_SUCCESS) { + nxll = node_pool_.Allocate( + uxl->GetKey(), uxl->GetValue(), uxl->GetWeight() - 1, + uxl->GetLeft(), uxl->GetRight(), Operation::INITIAL_DUMMY); + if (nxll == NULL) break; + nxrl = node_pool_.Allocate( + uxrlr->GetKey(), uxrlr->GetValue(), 1, + uxrlr->GetLeft(), uxrlr->GetRight(), Operation::INITIAL_DUMMY); + if (nxrl == NULL) break; + nxl = node_pool_.Allocate( + ux->GetKey(), ux->GetValue(), 1, + nxll, uxrl->GetLeft(), Operation::INITIAL_DUMMY); + if (nxl == NULL) break; + nxr = node_pool_.Allocate( + uxr->GetKey(), uxr->GetValue(), 0, + nxrl, uxr->GetRight(), Operation::INITIAL_DUMMY); + if (nxr == NULL) break; + nx = node_pool_.Allocate( + uxrl->GetKey(), uxrl->GetValue(), ux->GetWeight(), + nxl, nxr, Operation::INITIAL_DUMMY); + if (nx == NULL) break; + + HazardOperationPtr op(GetOperationGuard(HIDX_CURRENT_OP)); + op.ProtectSafe(operation_pool_.Allocate()); + if (op == NULL) break; + + op->SetRoot(u, u_op); + op->SetNewChild(nx); + op->SetOldNodes(ux, ux_op, + uxl, uxl_op, + uxr, uxr_op, + uxrl, uxrl_op, + uxrlr, uxrlr_op); + + bool succeeded = op->Help(GetNodeGuard(HIDX_HELPING), + GetOperationGuard(HIDX_HELPING)); + op->CleanUp(); + + if (!succeeded) { + RetireOperation(op); + result = EMBB_BUSY; + break; + } + + RetireOperation(u_op); + RetireNode(ux); RetireOperation(ux_op); + RetireNode(uxl); RetireOperation(uxl_op); + RetireNode(uxr); RetireOperation(uxr_op); + RetireNode(uxrl); RetireOperation(uxrl_op); + RetireNode(uxrlr); RetireOperation(uxrlr_op); + + result = EMBB_SUCCESS; + } + + if (result != EMBB_SUCCESS) { if (nxll) FreeNode(nxll); if (nxrl) FreeNode(nxrl); if (nxl) FreeNode(nxl); if (nxr) FreeNode(nxr); if (nx) FreeNode(nx); - return EMBB_NOMEM; } - bool rotation_succeeded = u->ReplaceChild(ux, nx); - assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail - if (!rotation_succeeded) return EMBB_BUSY; - - RetireHazardousNode(ux, ux_lock); - RetireHazardousNode(uxl, uxl_lock); - RetireHazardousNode(uxr, uxr_lock); - RetireHazardousNode(uxrl, uxrl_lock); - RetireHazardousNode(uxrlr, uxrlr_lock); - (void)u_lock; // For now (FGL tree) u_lock is not used here - - return EMBB_SUCCESS; + return result; } -embb_errors_t W4_R( - HazardNodePtr& u, UniqueLock& u_lock, - HazardNodePtr& ux, UniqueLock& ux_lock, - HazardNodePtr& uxl, UniqueLock& uxl_lock, - HazardNodePtr& uxr, UniqueLock& uxr_lock, - HazardNodePtr& uxlr, UniqueLock& uxlr_lock, - HazardNodePtr& uxlrl, UniqueLock& uxlrl_lock) { - Node* nxrr = node_pool_.Allocate( - uxr->GetKey(), uxr->GetValue(), - uxr->GetWeight() - 1, - uxr->GetLeft(), uxr->GetRight()); - Node* nxlr = node_pool_.Allocate( - uxlrl->GetKey(), uxlrl->GetValue(), - 1, - uxlrl->GetLeft(), uxlrl->GetRight()); - Node* nxr = node_pool_.Allocate( - ux->GetKey(), ux->GetValue(), - 1, - uxlr->GetRight(), nxrr); - Node* nxl = node_pool_.Allocate( - uxl->GetKey(), uxl->GetValue(), - 0, - uxl->GetLeft(), nxlr); - Node* nx = node_pool_.Allocate( - uxlr->GetKey(), uxlr->GetValue(), - ux->GetWeight(), - nxl, nxr); - - if (nxrr == NULL || - nxlr == NULL || - nxr == NULL || - nxl == NULL || - nx == NULL) { +embb_errors_t W4_R(HazardNodePtr& u, HazardOperationPtr& u_op, + HazardNodePtr& ux, HazardOperationPtr& ux_op, + HazardNodePtr& uxl, HazardOperationPtr& uxl_op, + HazardNodePtr& uxr, HazardOperationPtr& uxr_op, + HazardNodePtr& uxlr, HazardOperationPtr& uxlr_op, + HazardNodePtr& uxlrl, HazardOperationPtr& uxlrl_op) { + embb_errors_t result = EMBB_NOMEM; + Node* nxrr; + Node* nxlr; + Node* nxr; + Node* nxl; + Node* nx; + + while (result != EMBB_SUCCESS) { + nxrr = node_pool_.Allocate( + uxr->GetKey(), uxr->GetValue(), uxr->GetWeight() - 1, + uxr->GetLeft(), uxr->GetRight(), Operation::INITIAL_DUMMY); + if (nxrr == NULL) break; + nxlr = node_pool_.Allocate( + uxlrl->GetKey(), uxlrl->GetValue(), 1, + uxlrl->GetLeft(), uxlrl->GetRight(), Operation::INITIAL_DUMMY); + if (nxlr == NULL) break; + nxr = node_pool_.Allocate( + ux->GetKey(), ux->GetValue(), 1, + uxlr->GetRight(), nxrr, Operation::INITIAL_DUMMY); + if (nxr == NULL) break; + nxl = node_pool_.Allocate( + uxl->GetKey(), uxl->GetValue(), 0, + uxl->GetLeft(), nxlr, Operation::INITIAL_DUMMY); + if (nxl == NULL) break; + nx = node_pool_.Allocate( + uxlr->GetKey(), uxlr->GetValue(), ux->GetWeight(), + nxl, nxr, Operation::INITIAL_DUMMY); + if (nx == NULL) break; + + HazardOperationPtr op(GetOperationGuard(HIDX_CURRENT_OP)); + op.ProtectSafe(operation_pool_.Allocate()); + if (op == NULL) break; + + op->SetRoot(u, u_op); + op->SetNewChild(nx); + op->SetOldNodes(ux, ux_op, + uxl, uxl_op, + uxr, uxr_op, + uxlr, uxlr_op, + uxlrl, uxlrl_op); + + bool succeeded = op->Help(GetNodeGuard(HIDX_HELPING), + GetOperationGuard(HIDX_HELPING)); + op->CleanUp(); + + if (!succeeded) { + RetireOperation(op); + result = EMBB_BUSY; + break; + } + + RetireOperation(u_op); + RetireNode(ux); RetireOperation(ux_op); + RetireNode(uxl); RetireOperation(uxl_op); + RetireNode(uxr); RetireOperation(uxr_op); + RetireNode(uxlr); RetireOperation(uxlr_op); + RetireNode(uxlrl); RetireOperation(uxlrl_op); + + result = EMBB_SUCCESS; + } + + if (result != EMBB_SUCCESS) { if (nxrr) FreeNode(nxrr); if (nxlr) FreeNode(nxlr); if (nxr) FreeNode(nxr); if (nxl) FreeNode(nxl); if (nx) FreeNode(nx); - return EMBB_NOMEM; } - bool rotation_succeeded = u->ReplaceChild(ux, nx); - assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail - if (!rotation_succeeded) return EMBB_BUSY; - - RetireHazardousNode(ux, ux_lock); - RetireHazardousNode(uxl, uxl_lock); - RetireHazardousNode(uxr, uxr_lock); - RetireHazardousNode(uxlr, uxlr_lock); - RetireHazardousNode(uxlrl, uxlrl_lock); - (void)u_lock; // For now (FGL tree) u_lock is not used here - - return EMBB_SUCCESS; + return result; } -embb_errors_t W5_L( - HazardNodePtr& u, UniqueLock& u_lock, - HazardNodePtr& ux, UniqueLock& ux_lock, - HazardNodePtr& uxl, UniqueLock& uxl_lock, - HazardNodePtr& uxr, UniqueLock& uxr_lock, - HazardNodePtr& uxrr, UniqueLock& uxrr_lock) { - Node* nxll = node_pool_.Allocate( - uxl->GetKey(), uxl->GetValue(), - uxl->GetWeight() - 1, - uxl->GetLeft(), uxl->GetRight()); - Node* nxl = node_pool_.Allocate( - ux->GetKey(), ux->GetValue(), - 1, - nxll, uxr->GetLeft()); - Node* nxr = node_pool_.Allocate( - uxrr->GetKey(), uxrr->GetValue(), - 1, - uxrr->GetLeft(), uxrr->GetRight()); - Node* nx = node_pool_.Allocate( - uxr->GetKey(), uxr->GetValue(), - ux->GetWeight(), - nxl, nxr); - - if (nxll == NULL || - nxl == NULL || - nxr == NULL || - nx == NULL) { +embb_errors_t W5_L(HazardNodePtr& u, HazardOperationPtr& u_op, + HazardNodePtr& ux, HazardOperationPtr& ux_op, + HazardNodePtr& uxl, HazardOperationPtr& uxl_op, + HazardNodePtr& uxr, HazardOperationPtr& uxr_op, + HazardNodePtr& uxrr, HazardOperationPtr& uxrr_op) { + embb_errors_t result = EMBB_NOMEM; + Node* nxll; + Node* nxl; + Node* nxr; + Node* nx; + + while (result != EMBB_SUCCESS) { + nxll = node_pool_.Allocate( + uxl->GetKey(), uxl->GetValue(), uxl->GetWeight() - 1, + uxl->GetLeft(), uxl->GetRight(), Operation::INITIAL_DUMMY); + if (nxll == NULL) break; + nxl = node_pool_.Allocate( + ux->GetKey(), ux->GetValue(), 1, + nxll, uxr->GetLeft(), Operation::INITIAL_DUMMY); + if (nxl == NULL) break; + nxr = node_pool_.Allocate( + uxrr->GetKey(), uxrr->GetValue(), 1, + uxrr->GetLeft(), uxrr->GetRight(), Operation::INITIAL_DUMMY); + if (nxr == NULL) break; + nx = node_pool_.Allocate( + uxr->GetKey(), uxr->GetValue(), ux->GetWeight(), + nxl, nxr, Operation::INITIAL_DUMMY); + if (nx == NULL) break; + + HazardOperationPtr op(GetOperationGuard(HIDX_CURRENT_OP)); + op.ProtectSafe(operation_pool_.Allocate()); + if (op == NULL) break; + + op->SetRoot(u, u_op); + op->SetNewChild(nx); + op->SetOldNodes(ux, ux_op, + uxl, uxl_op, + uxr, uxr_op, + uxrr, uxrr_op); + + bool succeeded = op->Help(GetNodeGuard(HIDX_HELPING), + GetOperationGuard(HIDX_HELPING)); + op->CleanUp(); + + if (!succeeded) { + RetireOperation(op); + result = EMBB_BUSY; + break; + } + + RetireOperation(u_op); + RetireNode(ux); RetireOperation(ux_op); + RetireNode(uxl); RetireOperation(uxl_op); + RetireNode(uxr); RetireOperation(uxr_op); + RetireNode(uxrr); RetireOperation(uxrr_op); + + result = EMBB_SUCCESS; + } + + if (result != EMBB_SUCCESS) { if (nxll) FreeNode(nxll); if (nxl) FreeNode(nxl); if (nxr) FreeNode(nxr); if (nx) FreeNode(nx); - return EMBB_NOMEM; } - bool rotation_succeeded = u->ReplaceChild(ux, nx); - assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail - if (!rotation_succeeded) return EMBB_BUSY; - - RetireHazardousNode(ux, ux_lock); - RetireHazardousNode(uxl, uxl_lock); - RetireHazardousNode(uxr, uxr_lock); - RetireHazardousNode(uxrr, uxrr_lock); - (void)u_lock; // For now (FGL tree) u_lock is not used here - - return EMBB_SUCCESS; + return result; } -embb_errors_t W5_R( - HazardNodePtr& u, UniqueLock& u_lock, - HazardNodePtr& ux, UniqueLock& ux_lock, - HazardNodePtr& uxl, UniqueLock& uxl_lock, - HazardNodePtr& uxr, UniqueLock& uxr_lock, - HazardNodePtr& uxll, UniqueLock& uxll_lock) { - Node* nxrr = node_pool_.Allocate( - uxr->GetKey(), uxr->GetValue(), - uxr->GetWeight() - 1, - uxr->GetLeft(), uxr->GetRight()); - Node* nxr = node_pool_.Allocate( - ux->GetKey(), ux->GetValue(), - 1, - uxl->GetRight(), nxrr); - Node* nxl = node_pool_.Allocate( - uxll->GetKey(), uxll->GetValue(), - 1, - uxll->GetLeft(), uxll->GetRight()); - Node* nx = node_pool_.Allocate( - uxl->GetKey(), uxl->GetValue(), - ux->GetWeight(), - nxl, nxr); - - if (nxrr == NULL || - nxr == NULL || - nxl == NULL || - nx == NULL) { +embb_errors_t W5_R(HazardNodePtr& u, HazardOperationPtr& u_op, + HazardNodePtr& ux, HazardOperationPtr& ux_op, + HazardNodePtr& uxl, HazardOperationPtr& uxl_op, + HazardNodePtr& uxr, HazardOperationPtr& uxr_op, + HazardNodePtr& uxll, HazardOperationPtr& uxll_op) { + embb_errors_t result = EMBB_NOMEM; + Node* nxrr; + Node* nxr; + Node* nxl; + Node* nx; + + while (result != EMBB_SUCCESS) { + nxrr = node_pool_.Allocate( + uxr->GetKey(), uxr->GetValue(), uxr->GetWeight() - 1, + uxr->GetLeft(), uxr->GetRight(), Operation::INITIAL_DUMMY); + if (nxrr == NULL) break; + nxr = node_pool_.Allocate( + ux->GetKey(), ux->GetValue(), 1, + uxl->GetRight(), nxrr, Operation::INITIAL_DUMMY); + if (nxr == NULL) break; + nxl = node_pool_.Allocate( + uxll->GetKey(), uxll->GetValue(), 1, + uxll->GetLeft(), uxll->GetRight(), Operation::INITIAL_DUMMY); + if (nxl == NULL) break; + nx = node_pool_.Allocate( + uxl->GetKey(), uxl->GetValue(), ux->GetWeight(), + nxl, nxr, Operation::INITIAL_DUMMY); + if (nx == NULL) break; + + HazardOperationPtr op(GetOperationGuard(HIDX_CURRENT_OP)); + op.ProtectSafe(operation_pool_.Allocate()); + if (op == NULL) break; + + op->SetRoot(u, u_op); + op->SetNewChild(nx); + op->SetOldNodes(ux, ux_op, + uxl, uxl_op, + uxr, uxr_op, + uxll, uxll_op); + + bool succeeded = op->Help(GetNodeGuard(HIDX_HELPING), + GetOperationGuard(HIDX_HELPING)); + op->CleanUp(); + + if (!succeeded) { + RetireOperation(op); + result = EMBB_BUSY; + break; + } + + RetireOperation(u_op); + RetireNode(ux); RetireOperation(ux_op); + RetireNode(uxl); RetireOperation(uxl_op); + RetireNode(uxr); RetireOperation(uxr_op); + RetireNode(uxll); RetireOperation(uxll_op); + + result = EMBB_SUCCESS; + } + + if (result != EMBB_SUCCESS) { if (nxrr) FreeNode(nxrr); if (nxr) FreeNode(nxr); if (nxl) FreeNode(nxl); if (nx) FreeNode(nx); - return EMBB_NOMEM; } - bool rotation_succeeded = u->ReplaceChild(ux, nx); - assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail - if (!rotation_succeeded) return EMBB_BUSY; - - RetireHazardousNode(ux, ux_lock); - RetireHazardousNode(uxl, uxl_lock); - RetireHazardousNode(uxr, uxr_lock); - RetireHazardousNode(uxll, uxll_lock); - (void)u_lock; // For now (FGL tree) u_lock is not used here - - return EMBB_SUCCESS; + return result; } -embb_errors_t W6_L( - HazardNodePtr& u, UniqueLock& u_lock, - HazardNodePtr& ux, UniqueLock& ux_lock, - HazardNodePtr& uxl, UniqueLock& uxl_lock, - HazardNodePtr& uxr, UniqueLock& uxr_lock, - HazardNodePtr& uxrl, UniqueLock& uxrl_lock) { - Node* nxll = node_pool_.Allocate( - uxl->GetKey(), uxl->GetValue(), - uxl->GetWeight() - 1, - uxl->GetLeft(), uxl->GetRight()); - Node* nxl = node_pool_.Allocate( - ux->GetKey(), ux->GetValue(), - 1, - nxll, uxrl->GetLeft()); - Node* nxr = node_pool_.Allocate( - uxr->GetKey(), uxr->GetValue(), - 1, - uxrl->GetRight(), uxr->GetRight()); - Node* nx = node_pool_.Allocate( - uxrl->GetKey(), uxrl->GetValue(), - ux->GetWeight(), - nxl, nxr); - - if (nxll == NULL || - nxl == NULL || - nxr == NULL || - nx == NULL) { +embb_errors_t W6_L(HazardNodePtr& u, HazardOperationPtr& u_op, + HazardNodePtr& ux, HazardOperationPtr& ux_op, + HazardNodePtr& uxl, HazardOperationPtr& uxl_op, + HazardNodePtr& uxr, HazardOperationPtr& uxr_op, + HazardNodePtr& uxrl, HazardOperationPtr& uxrl_op) { + embb_errors_t result = EMBB_NOMEM; + Node* nxll; + Node* nxl; + Node* nxr; + Node* nx; + + while (result != EMBB_SUCCESS) { + nxll = node_pool_.Allocate( + uxl->GetKey(), uxl->GetValue(), uxl->GetWeight() - 1, + uxl->GetLeft(), uxl->GetRight(), Operation::INITIAL_DUMMY); + if (nxll == NULL) break; + nxl = node_pool_.Allocate( + ux->GetKey(), ux->GetValue(), 1, + nxll, uxrl->GetLeft(), Operation::INITIAL_DUMMY); + if (nxl == NULL) break; + nxr = node_pool_.Allocate( + uxr->GetKey(), uxr->GetValue(), 1, + uxrl->GetRight(), uxr->GetRight(), Operation::INITIAL_DUMMY); + if (nxr == NULL) break; + nx = node_pool_.Allocate( + uxrl->GetKey(), uxrl->GetValue(), ux->GetWeight(), + nxl, nxr, Operation::INITIAL_DUMMY); + if (nx == NULL) break; + + HazardOperationPtr op(GetOperationGuard(HIDX_CURRENT_OP)); + op.ProtectSafe(operation_pool_.Allocate()); + if (op == NULL) break; + + op->SetRoot(u, u_op); + op->SetNewChild(nx); + op->SetOldNodes(ux, ux_op, + uxl, uxl_op, + uxr, uxr_op, + uxrl, uxrl_op); + + bool succeeded = op->Help(GetNodeGuard(HIDX_HELPING), + GetOperationGuard(HIDX_HELPING)); + op->CleanUp(); + + if (!succeeded) { + RetireOperation(op); + result = EMBB_BUSY; + break; + } + + RetireOperation(u_op); + RetireNode(ux); RetireOperation(ux_op); + RetireNode(uxl); RetireOperation(uxl_op); + RetireNode(uxr); RetireOperation(uxr_op); + RetireNode(uxrl); RetireOperation(uxrl_op); + + result = EMBB_SUCCESS; + } + + if (result != EMBB_SUCCESS) { if (nxll) FreeNode(nxll); if (nxl) FreeNode(nxl); if (nxr) FreeNode(nxr); if (nx) FreeNode(nx); - return EMBB_NOMEM; } - bool rotation_succeeded = u->ReplaceChild(ux, nx); - assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail - if (!rotation_succeeded) return EMBB_BUSY; - - RetireHazardousNode(ux, ux_lock); - RetireHazardousNode(uxl, uxl_lock); - RetireHazardousNode(uxr, uxr_lock); - RetireHazardousNode(uxrl, uxrl_lock); - (void)u_lock; // For now (FGL tree) u_lock is not used here - - return EMBB_SUCCESS; + return result; } -embb_errors_t W6_R( - HazardNodePtr& u, UniqueLock& u_lock, - HazardNodePtr& ux, UniqueLock& ux_lock, - HazardNodePtr& uxl, UniqueLock& uxl_lock, - HazardNodePtr& uxr, UniqueLock& uxr_lock, - HazardNodePtr& uxlr, UniqueLock& uxlr_lock) { - Node* nxrr = node_pool_.Allocate( - uxr->GetKey(), uxr->GetValue(), - uxr->GetWeight() - 1, - uxr->GetLeft(), uxr->GetRight()); - Node* nxr = node_pool_.Allocate( - ux->GetKey(), ux->GetValue(), - 1, - uxlr->GetRight(), nxrr); - Node* nxl = node_pool_.Allocate( - uxl->GetKey(), uxl->GetValue(), - 1, - uxl->GetLeft(), uxlr->GetLeft()); - Node* nx = node_pool_.Allocate( - uxlr->GetKey(), uxlr->GetValue(), - ux->GetWeight(), - nxl, nxr); - - if (nxrr == NULL || - nxr == NULL || - nxl == NULL || - nx == NULL) { +embb_errors_t W6_R(HazardNodePtr& u, HazardOperationPtr& u_op, + HazardNodePtr& ux, HazardOperationPtr& ux_op, + HazardNodePtr& uxl, HazardOperationPtr& uxl_op, + HazardNodePtr& uxr, HazardOperationPtr& uxr_op, + HazardNodePtr& uxlr, HazardOperationPtr& uxlr_op) { + embb_errors_t result = EMBB_NOMEM; + Node* nxrr; + Node* nxr; + Node* nxl; + Node* nx; + + while (result != EMBB_SUCCESS) { + nxrr = node_pool_.Allocate( + uxr->GetKey(), uxr->GetValue(), uxr->GetWeight() - 1, + uxr->GetLeft(), uxr->GetRight(), Operation::INITIAL_DUMMY); + if (nxrr == NULL) break; + nxr = node_pool_.Allocate( + ux->GetKey(), ux->GetValue(), 1, + uxlr->GetRight(), nxrr, Operation::INITIAL_DUMMY); + if (nxr == NULL) break; + nxl = node_pool_.Allocate( + uxl->GetKey(), uxl->GetValue(), 1, + uxl->GetLeft(), uxlr->GetLeft(), Operation::INITIAL_DUMMY); + if (nxl == NULL) break; + nx = node_pool_.Allocate( + uxlr->GetKey(), uxlr->GetValue(), ux->GetWeight(), + nxl, nxr, Operation::INITIAL_DUMMY); + if (nx == NULL) break; + + HazardOperationPtr op(GetOperationGuard(HIDX_CURRENT_OP)); + op.ProtectSafe(operation_pool_.Allocate()); + if (op == NULL) break; + + op->SetRoot(u, u_op); + op->SetNewChild(nx); + op->SetOldNodes(ux, ux_op, + uxl, uxl_op, + uxr, uxr_op, + uxlr, uxlr_op); + + bool succeeded = op->Help(GetNodeGuard(HIDX_HELPING), + GetOperationGuard(HIDX_HELPING)); + op->CleanUp(); + + if (!succeeded) { + RetireOperation(op); + result = EMBB_BUSY; + break; + } + + RetireOperation(u_op); + RetireNode(ux); RetireOperation(ux_op); + RetireNode(uxl); RetireOperation(uxl_op); + RetireNode(uxr); RetireOperation(uxr_op); + RetireNode(uxlr); RetireOperation(uxlr_op); + + result = EMBB_SUCCESS; + } + + if (result != EMBB_SUCCESS) { if (nxrr) FreeNode(nxrr); if (nxr) FreeNode(nxr); if (nxl) FreeNode(nxl); if (nx) FreeNode(nx); - return EMBB_NOMEM; } - bool rotation_succeeded = u->ReplaceChild(ux, nx); - assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail - if (!rotation_succeeded) return EMBB_BUSY; - - RetireHazardousNode(ux, ux_lock); - RetireHazardousNode(uxl, uxl_lock); - RetireHazardousNode(uxr, uxr_lock); - RetireHazardousNode(uxlr, uxlr_lock); - (void)u_lock; // For now (FGL tree) u_lock is not used here - - return EMBB_SUCCESS; + return result; } -embb_errors_t W7( - HazardNodePtr& u, UniqueLock& u_lock, - HazardNodePtr& ux, UniqueLock& ux_lock, - HazardNodePtr& uxl, UniqueLock& uxl_lock, - HazardNodePtr& uxr, UniqueLock& uxr_lock) { - Node* nxl = node_pool_.Allocate( - uxl->GetKey(), uxl->GetValue(), - uxl->GetWeight() - 1, - uxl->GetLeft(), uxl->GetRight()); - Node* nxr = node_pool_.Allocate( - uxr->GetKey(), uxr->GetValue(), - uxr->GetWeight() - 1, - uxr->GetLeft(), uxr->GetRight()); - Node* nx = node_pool_.Allocate( - ux->GetKey(), ux->GetValue(), - IsSentinel(u) ? 1 : ux->GetWeight() + 1, - nxl, nxr); - - if (nxl == NULL || - nxr == NULL || - nx == NULL) { +embb_errors_t W7(HazardNodePtr& u, HazardOperationPtr& u_op, + HazardNodePtr& ux, HazardOperationPtr& ux_op, + HazardNodePtr& uxl, HazardOperationPtr& uxl_op, + HazardNodePtr& uxr, HazardOperationPtr& uxr_op) { + embb_errors_t result = EMBB_NOMEM; + Node* nxl; + Node* nxr; + Node* nx; + + while (result != EMBB_SUCCESS) { + nxl = node_pool_.Allocate( + uxl->GetKey(), uxl->GetValue(), uxl->GetWeight() - 1, + uxl->GetLeft(), uxl->GetRight(), Operation::INITIAL_DUMMY); + if (nxl == NULL) break; + nxr = node_pool_.Allocate( + uxr->GetKey(), uxr->GetValue(), uxr->GetWeight() - 1, + uxr->GetLeft(), uxr->GetRight(), Operation::INITIAL_DUMMY); + if (nxr == NULL) break; + nx = node_pool_.Allocate( + ux->GetKey(), ux->GetValue(), IsSentinel(u) ? 1 : ux->GetWeight() + 1, + nxl, nxr, Operation::INITIAL_DUMMY); + if (nx == NULL) break; + + HazardOperationPtr op(GetOperationGuard(HIDX_CURRENT_OP)); + op.ProtectSafe(operation_pool_.Allocate()); + if (op == NULL) break; + + op->SetRoot(u, u_op); + op->SetNewChild(nx); + op->SetOldNodes(ux, ux_op, + uxl, uxl_op, + uxr, uxr_op); + + bool succeeded = op->Help(GetNodeGuard(HIDX_HELPING), + GetOperationGuard(HIDX_HELPING)); + op->CleanUp(); + + if (!succeeded) { + RetireOperation(op); + result = EMBB_BUSY; + break; + } + + RetireOperation(u_op); + RetireNode(ux); RetireOperation(ux_op); + RetireNode(uxl); RetireOperation(uxl_op); + RetireNode(uxr); RetireOperation(uxr_op); + + result = EMBB_SUCCESS; + } + + if (result != EMBB_SUCCESS) { if (nxl) FreeNode(nxl); if (nxr) FreeNode(nxr); if (nx) FreeNode(nx); - return EMBB_NOMEM; } - bool rotation_succeeded = u->ReplaceChild(ux, nx); - assert(rotation_succeeded); // For now (FGL tree) this CAS may not fail - if (!rotation_succeeded) return EMBB_BUSY; - - RetireHazardousNode(ux, ux_lock); - RetireHazardousNode(uxl, uxl_lock); - RetireHazardousNode(uxr, uxr_lock); - (void)u_lock; // For now (FGL tree) u_lock is not used here - - return EMBB_SUCCESS; + return result; } #endif // EMBB_CONTAINERS_INTERNAL_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_ diff --git a/containers_cpp/include/embb/containers/lock_free_chromatic_tree.h b/containers_cpp/include/embb/containers/lock_free_chromatic_tree.h index a6c59e7..75a8646 100644 --- a/containers_cpp/include/embb/containers/lock_free_chromatic_tree.h +++ b/containers_cpp/include/embb/containers/lock_free_chromatic_tree.h @@ -201,10 +201,19 @@ class ChromaticTreeOperation { root_operation_ = root_operation; } - void SetOldNodes(Node* node, Operation* operation) { + void SetOldNodes(Node* node1, Operation* operation1) { num_old_nodes_ = 1; - old_nodes_[0] = node; - old_operations_[0] = operation; + old_nodes_[0] = node1; + old_operations_[0] = operation1; + } + + void SetOldNodes(Node* node1, Operation* operation1, + Node* node2, Operation* operation2) { + num_old_nodes_ = 2; + old_nodes_[0] = node1; + old_operations_[0] = operation1; + old_nodes_[1] = node2; + old_operations_[1] = operation2; } void SetOldNodes(Node* node1, Operation* operation1, @@ -219,6 +228,39 @@ class ChromaticTreeOperation { old_operations_[2] = operation3; } + void SetOldNodes(Node* node1, Operation* operation1, + Node* node2, Operation* operation2, + Node* node3, Operation* operation3, + Node* node4, Operation* operation4) { + num_old_nodes_ = 4; + old_nodes_[0] = node1; + old_operations_[0] = operation1; + old_nodes_[1] = node2; + old_operations_[1] = operation2; + old_nodes_[2] = node3; + old_operations_[2] = operation3; + old_nodes_[3] = node4; + old_operations_[3] = operation4; + } + + void SetOldNodes(Node* node1, Operation* operation1, + Node* node2, Operation* operation2, + Node* node3, Operation* operation3, + Node* node4, Operation* operation4, + Node* node5, Operation* operation5) { + num_old_nodes_ = 5; + old_nodes_[0] = node1; + old_operations_[0] = operation1; + old_nodes_[1] = node2; + old_operations_[1] = operation2; + old_nodes_[2] = node3; + old_operations_[2] = operation3; + old_nodes_[3] = node4; + old_operations_[3] = operation4; + old_nodes_[4] = node5; + old_operations_[4] = operation5; + } + void SetNewChild(Node* new_child) { new_child_ = new_child; } @@ -639,8 +681,6 @@ class ChromaticTree { typedef embb::base::Atomic AtomicOperationPtr; /** Typedef for an pointer to a node protected by a Hazard Pointer. */ typedef internal::UniqueHazardPointer HazardOperationPtr; - /** Typedef for the UniqueLock class. */ - typedef embb::base::UniqueLock UniqueLock; /** Typedef for an object pool for tree nodes. */ typedef ObjectPool NodePool; /** Typedef for an object pool for tree operations. */ @@ -648,11 +688,33 @@ class ChromaticTree { typedef enum { HIDX_HELPING = 0, - HIDX_LEAF, - HIDX_PARENT, + // Common shared nodes + HIDX_GRANDGRANDPARENT, HIDX_GRANDPARENT, - HIDX_SIBLING, - HIDX_CURRENT_OP, + HIDX_PARENT, + HIDX_LEAF, + HIDX_SIBLING = HIDX_GRANDGRANDPARENT, // Never occur in the same scope + // Rebalancing nodes + HIDX_U = HIDX_GRANDGRANDPARENT, // Renamed when passed to "Rebalance" + HIDX_UX = HIDX_GRANDPARENT, // Renamed when passed to "Rebalance" + HIDX_UXX = HIDX_PARENT, // Renamed when passed to "Rebalance" + HIDX_UXXX = HIDX_LEAF, // Renamed when passed to "Rebalance" + HIDX_UXL = HIDX_LEAF + 1, // Restoring sequence + HIDX_UXR, + HIDX_UXXL, + HIDX_UXXR, + // Left overweight + HIDX_UXXRL = HIDX_U, // Reusing hazard guard that is no longer used + HIDX_UXXRR = HIDX_UXR, // Reusing hazard guard that is no longer used + HIDX_UXXRLR = HIDX_UXR, // Reusing hazard guard that is no longer used + HIDX_UXXRLL = HIDX_UXL, // Reusing hazard guard that is no longer used + // Right overweight + HIDX_UXXLR = HIDX_UXXRL, // Symmetric rotation + HIDX_UXXLL = HIDX_UXXRR, // Symmetric rotation + HIDX_UXXLRL = HIDX_UXXRLR, // Symmetric rotation + HIDX_UXXLRR = HIDX_UXXRLL, // Symmetric rotation + // Current operation object + HIDX_CURRENT_OP = HIDX_UXXR + 1, // Restoring sequence HIDX_MAX } HazardIndex; @@ -773,19 +835,19 @@ class ChromaticTree { embb_errors_t Rebalance(HazardNodePtr& u, HazardNodePtr& ux, HazardNodePtr& uxx, HazardNodePtr& uxxx); - embb_errors_t OverweightLeft(HazardNodePtr& u, UniqueLock& u_lock, - HazardNodePtr& ux, UniqueLock& ux_lock, - HazardNodePtr& uxx, UniqueLock& uxx_lock, + embb_errors_t OverweightLeft(HazardNodePtr& u, HazardOperationPtr& u_op, + HazardNodePtr& ux, HazardOperationPtr& ux_op, + HazardNodePtr& uxx, HazardOperationPtr& uxx_op, HazardNodePtr& uxl, HazardNodePtr& uxr, - HazardNodePtr& uxxl, UniqueLock& uxxl_lock, + HazardNodePtr& uxxl, HazardOperationPtr& uxxl_op, HazardNodePtr& uxxr, bool uxx_is_left); - embb_errors_t OverweightRight(HazardNodePtr& u, UniqueLock& u_lock, - HazardNodePtr& ux, UniqueLock& ux_lock, - HazardNodePtr& uxx, UniqueLock& uxx_lock, + embb_errors_t OverweightRight(HazardNodePtr& u, HazardOperationPtr& u_op, + HazardNodePtr& ux, HazardOperationPtr& ux_op, + HazardNodePtr& uxx, HazardOperationPtr& uxx_op, HazardNodePtr& uxl, HazardNodePtr& uxr, HazardNodePtr& uxxl, HazardNodePtr& uxxr, - UniqueLock& uxxr_lock, bool uxx_is_right); + HazardOperationPtr& uxxr_op, bool uxx_is_right); // The following included header contains the class methods implementing // tree rotations. It is generated automatically and must be included diff --git a/containers_cpp/test/tree_test-inl.h b/containers_cpp/test/tree_test-inl.h index 9d417ab..78913c4 100644 --- a/containers_cpp/test/tree_test-inl.h +++ b/containers_cpp/test/tree_test-inl.h @@ -66,11 +66,11 @@ TreeTest::TreeTest() Add(&TreeTest::TreeTestConcurrentGet_ReaderMethod, this, NUM_TEST_THREADS / 2, NUM_ITERATIONS). Post(&TreeTest::TreeTestConcurrentGet_Post, this); -// CreateUnit("TreeTestBalance"). -// Pre(&TreeTest::TreeTestBalance_Pre, this). -// Add(&TreeTest::TreeTestBalance_ThreadMethod, this, -// NUM_TEST_THREADS, 1). -// Post(&TreeTest::TreeTestBalance_Post, this); + CreateUnit("TreeTestBalance"). + Pre(&TreeTest::TreeTestBalance_Pre, this). + Add(&TreeTest::TreeTestBalance_ThreadMethod, this, + NUM_TEST_THREADS, 1). + Post(&TreeTest::TreeTestBalance_Post, this); } template -- libgit2 0.26.0