Commit 35ab98de by Danila Klimenko

chromatic_tree: lock-free implementation (with rebalancing)

parent 34f6e4f3
......@@ -626,59 +626,69 @@ FreeOperation(Operation* operation) {
template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, ValuePool>::
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<Node*>(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<Node*>(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*>(node))
......@@ -688,24 +698,24 @@ embb_errors_t ChromaticTree<Key, Value, Compare, ValuePool>::
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<typename Key, typename Value, typename Compare, typename ValuePool>
embb_errors_t ChromaticTree<Key, Value, Compare, ValuePool>::
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<typename Key, typename Value, typename Compare, typename ValuePool>
embb_errors_t ChromaticTree<Key, Value, Compare, ValuePool>::
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);
}
}
......
......@@ -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_
......@@ -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<Operation*> AtomicOperationPtr;
/** Typedef for an pointer to a node protected by a Hazard Pointer. */
typedef internal::UniqueHazardPointer<Operation> HazardOperationPtr;
/** Typedef for the UniqueLock class. */
typedef embb::base::UniqueLock<embb::base::Mutex> UniqueLock;
/** Typedef for an object pool for tree nodes. */
typedef ObjectPool<Node, ValuePool> 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
......
......@@ -66,11 +66,11 @@ TreeTest<Tree>::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<typename Tree>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment