Commit 35ab98de by Danila Klimenko

chromatic_tree: lock-free implementation (with rebalancing)

parent 34f6e4f3
...@@ -626,59 +626,69 @@ FreeOperation(Operation* operation) { ...@@ -626,59 +626,69 @@ FreeOperation(Operation* operation) {
template<typename Key, typename Value, typename Compare, typename ValuePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
bool ChromaticTree<Key, Value, Compare, ValuePool>:: bool ChromaticTree<Key, Value, Compare, ValuePool>::
CleanUp(const Key& key) { 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; 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) \ #define PROTECT_NODE_WITH_LLX(h_idx, node, op_name) \
UniqueLock lock_name(node->GetMutex(), embb::base::try_lock); \ HazardOperationPtr op_name(GetOperationGuard(h_idx)); \
if (!lock_name.OwnsLock() || node->IsRetired()) return EMBB_BUSY; if (!WeakLLX(node, op_name)) return EMBB_BUSY
#define DEFINE_NODE_WITH_HAZARD(h_num, node, parent, method) \ #define DEFINE_HAZARDOUS_NODE(h_idx, node, parent, method) \
HazardNodePtr node(node_hazard_manager_.GetGuardedPointer(h_num)); \ HazardNodePtr node(GetNodeGuard(h_idx)); \
node.ProtectHazard(parent->method()); \ node.ProtectHazard(parent->method()); \
if (parent->IsRetired() || !node.IsActive()) return EMBB_BUSY; \ if (parent->IsRetired() || !node.IsActive()) return EMBB_BUSY; \
VERIFY_ADDRESS(static_cast<Node*>(node)) VERIFY_ADDRESS(static_cast<Node*>(node))
...@@ -688,24 +698,24 @@ embb_errors_t ChromaticTree<Key, Value, Compare, ValuePool>:: ...@@ -688,24 +698,24 @@ embb_errors_t ChromaticTree<Key, Value, Compare, ValuePool>::
Rebalance(HazardNodePtr& u, HazardNodePtr& ux, HazardNodePtr& uxx, Rebalance(HazardNodePtr& u, HazardNodePtr& ux, HazardNodePtr& uxx,
HazardNodePtr& uxxx) { HazardNodePtr& uxxx) {
// Protect node 'u' // 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 // Verify that ux is still a child of u
if (!HasChild(u, ux)) return EMBB_BUSY; if (!HasChild(u, ux)) return EMBB_BUSY;
// Protect node 'ux' // Protect node 'ux'
PROTECT_NODE_WITH_LOCK(ux, ux_lock); PROTECT_NODE_WITH_LLX(HIDX_UX, ux, ux_op);
// Get children of 'ux' // Get children of 'ux'
DEFINE_NODE_WITH_HAZARD(4, uxl, ux, GetLeft); DEFINE_HAZARDOUS_NODE(HIDX_UXL, uxl, ux, GetLeft);
DEFINE_NODE_WITH_HAZARD(5, uxr, ux, GetRight); DEFINE_HAZARDOUS_NODE(HIDX_UXR, uxr, ux, GetRight);
// Verify that 'uxx' is still a child of 'ux' // Verify that 'uxx' is still a child of 'ux'
bool uxx_is_left = (uxx == uxl); (void)uxx_is_left; bool uxx_is_left = (uxx == uxl); (void)uxx_is_left;
if (!HasChild(ux, uxx)) return EMBB_BUSY; if (!HasChild(ux, uxx)) return EMBB_BUSY;
// Protect node 'uxx' // Protect node 'uxx'
PROTECT_NODE_WITH_LOCK(uxx, uxx_lock); PROTECT_NODE_WITH_LLX(HIDX_UXX, uxx, uxx_op);
// Get children of 'uxx' // Get children of 'uxx'
DEFINE_NODE_WITH_HAZARD(6, uxxl, uxx, GetLeft); DEFINE_HAZARDOUS_NODE(HIDX_UXXL, uxxl, uxx, GetLeft);
DEFINE_NODE_WITH_HAZARD(7, uxxr, uxx, GetRight); DEFINE_HAZARDOUS_NODE(HIDX_UXXR, uxxr, uxx, GetRight);
// Verify that 'uxxx' is still a child of 'uxx' // Verify that 'uxxx' is still a child of 'uxx'
bool uxxx_is_left = (uxxx == uxxl); bool uxxx_is_left = (uxxx == uxxl);
if (!HasChild(uxx, uxxx)) return EMBB_BUSY; if (!HasChild(uxx, uxxx)) return EMBB_BUSY;
...@@ -713,40 +723,40 @@ Rebalance(HazardNodePtr& u, HazardNodePtr& ux, HazardNodePtr& uxx, ...@@ -713,40 +723,40 @@ Rebalance(HazardNodePtr& u, HazardNodePtr& ux, HazardNodePtr& uxx,
if (uxxx->GetWeight() > 1) { if (uxxx->GetWeight() > 1) {
if (uxxx_is_left) { if (uxxx_is_left) {
// Protect node 'uxxl' // Protect node 'uxxl'
PROTECT_NODE_WITH_LOCK(uxxl, uxxl_lock); PROTECT_NODE_WITH_LLX(HIDX_UXXL, uxxl, uxxl_op);
return OverweightLeft(u, u_lock, ux, ux_lock, uxx, uxx_lock, uxl, uxr, return OverweightLeft(u, u_op, ux, ux_op, uxx, uxx_op, uxl, uxr,
uxxl, uxxl_lock, uxxr, uxx_is_left); uxxl, uxxl_op, uxxr, uxx_is_left);
} else { } else {
// Protect node 'uxxr' // Protect node 'uxxr'
PROTECT_NODE_WITH_LOCK(uxxr, uxxr_lock); PROTECT_NODE_WITH_LLX(HIDX_UXXR, uxxr, uxxr_op);
return OverweightRight(u, u_lock, ux, ux_lock, uxx, uxx_lock, uxl, uxr, return OverweightRight(u, u_op, ux, ux_op, uxx, uxx_op, uxl, uxr,
uxxl, uxxr, uxxr_lock, !uxx_is_left); uxxl, uxxr, uxxr_op, !uxx_is_left);
} }
} else { } else {
assert(uxxx->GetWeight() == 0 && uxx->GetWeight() == 0); //Red-red violation assert(uxxx->GetWeight() == 0 && uxx->GetWeight() == 0); //Red-red violation
if (uxx_is_left) { if (uxx_is_left) {
if (uxr->GetWeight() == 0) { if (uxr->GetWeight() == 0) {
// Protect node 'uxr' // Protect node 'uxr'
PROTECT_NODE_WITH_LOCK(uxr, uxr_lock); PROTECT_NODE_WITH_LLX(HIDX_UXR, uxr, uxr_op);
return BLK(u, u_lock, ux, ux_lock, uxx, uxx_lock, uxr, uxr_lock); return BLK(u, u_op, ux, ux_op, uxx, uxx_op, uxr, uxr_op);
} else if (uxxx_is_left) { } 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 { } else {
// Protect node 'uxxr' // Protect node 'uxxr'
PROTECT_NODE_WITH_LOCK(uxxr, uxxr_lock); PROTECT_NODE_WITH_LLX(HIDX_UXXR, uxxr, uxxr_op);
return RB2_L(u, u_lock, ux, ux_lock, uxx, uxx_lock, uxxr, uxxr_lock); return RB2_L(u, u_op, ux, ux_op, uxx, uxx_op, uxxr, uxxr_op);
} }
} else { } else {
if (uxl->GetWeight() == 0) { if (uxl->GetWeight() == 0) {
// Protect node 'uxl' // Protect node 'uxl'
PROTECT_NODE_WITH_LOCK(uxl, uxl_lock); PROTECT_NODE_WITH_LLX(HIDX_UXL, uxl, uxl_op);
return BLK(u, u_lock, ux, ux_lock, uxl, uxl_lock, uxx, uxx_lock); return BLK(u, u_op, ux, ux_op, uxl, uxl_op, uxx, uxx_op);
} else if (!uxxx_is_left) { } 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 { } else {
// Protect node 'uxxl' // Protect node 'uxxl'
PROTECT_NODE_WITH_LOCK(uxxl, uxxl_lock); PROTECT_NODE_WITH_LLX(HIDX_UXXL, uxxl, uxxl_op);
return RB2_R(u, u_lock, ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock); 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, ...@@ -754,11 +764,11 @@ Rebalance(HazardNodePtr& u, HazardNodePtr& ux, HazardNodePtr& uxx,
template<typename Key, typename Value, typename Compare, typename ValuePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
embb_errors_t ChromaticTree<Key, Value, Compare, ValuePool>:: embb_errors_t ChromaticTree<Key, Value, Compare, ValuePool>::
OverweightLeft(HazardNodePtr& u, UniqueLock& u_lock, OverweightLeft(HazardNodePtr& u, HazardOperationPtr& u_op,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& ux, HazardOperationPtr& ux_op,
HazardNodePtr& uxx, UniqueLock& uxx_lock, HazardNodePtr& uxx, HazardOperationPtr& uxx_op,
HazardNodePtr& uxl, HazardNodePtr& uxr, HazardNodePtr& uxl, HazardNodePtr& uxr,
HazardNodePtr& uxxl, UniqueLock& uxxl_lock, HazardNodePtr& uxxl, HazardOperationPtr& uxxl_op,
HazardNodePtr& uxxr, bool uxx_is_left) { HazardNodePtr& uxxr, bool uxx_is_left) {
// Let "Root" be the top of the overweight violation decision tree (see p.30) // Let "Root" be the top of the overweight violation decision tree (see p.30)
// Root -> Middle // Root -> Middle
...@@ -770,15 +780,15 @@ OverweightLeft(HazardNodePtr& u, UniqueLock& u_lock, ...@@ -770,15 +780,15 @@ OverweightLeft(HazardNodePtr& u, UniqueLock& u_lock,
// Root -> Middle -> Left -> Left -> Left // Root -> Middle -> Left -> Left -> Left
if (uxr->GetWeight() == 0) { if (uxr->GetWeight() == 0) {
// Protect node 'uxr' // Protect node 'uxr'
PROTECT_NODE_WITH_LOCK(uxr, uxr_lock); PROTECT_NODE_WITH_LLX(HIDX_UXR, uxr, uxr_op);
return BLK(u, u_lock, ux, ux_lock, uxx, uxx_lock, uxr, uxr_lock); return BLK(u, u_op, ux, ux_op, uxx, uxx_op, uxr, uxr_op);
// Root -> Middle -> Left -> Left -> Right // Root -> Middle -> Left -> Left -> Right
} else { } else {
assert(uxr->GetWeight() > 0); assert(uxr->GetWeight() > 0);
// Protect node 'uxxr' // Protect node 'uxxr'
PROTECT_NODE_WITH_LOCK(uxxr, uxxr_lock); PROTECT_NODE_WITH_LLX(HIDX_UXXR, uxxr, uxxr_op);
return RB2_L(u, u_lock, ux, ux_lock, uxx, uxx_lock, uxxr, uxxr_lock); return RB2_L(u, u_op, ux, ux_op, uxx, uxx_op, uxxr, uxxr_op);
} }
// Root -> Middle -> Left -> Right // Root -> Middle -> Left -> Right
...@@ -787,13 +797,13 @@ OverweightLeft(HazardNodePtr& u, UniqueLock& u_lock, ...@@ -787,13 +797,13 @@ OverweightLeft(HazardNodePtr& u, UniqueLock& u_lock,
// Root -> Middle -> Left -> Right -> Left // Root -> Middle -> Left -> Right -> Left
if (uxl->GetWeight() == 0) { if (uxl->GetWeight() == 0) {
// Protect node 'uxl' // Protect node 'uxl'
PROTECT_NODE_WITH_LOCK(uxl, uxl_lock); PROTECT_NODE_WITH_LLX(HIDX_UXL, uxl, uxl_op);
return BLK(u, u_lock, ux, ux_lock, uxl, uxl_lock, uxx, uxx_lock); return BLK(u, u_op, ux, ux_op, uxl, uxl_op, uxx, uxx_op);
// Root -> Middle -> Left -> Right -> Right // Root -> Middle -> Left -> Right -> Right
} else { } else {
assert(uxl->GetWeight() > 0); 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, ...@@ -801,75 +811,75 @@ OverweightLeft(HazardNodePtr& u, UniqueLock& u_lock,
} else { } else {
assert(uxx->GetWeight() > 0); assert(uxx->GetWeight() > 0);
// Protect node 'uxxr' // Protect node 'uxxr'
PROTECT_NODE_WITH_LOCK(uxxr, uxxr_lock); PROTECT_NODE_WITH_LLX(HIDX_UXXR, uxxr, uxxr_op);
// Get left child of 'uxxr' // Get left child of 'uxxr'
// Note: we know that 'uxxr' is not a leaf because it has weight 0. // 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 'uxxrl'
PROTECT_NODE_WITH_LOCK(uxxrl, uxxrl_lock); PROTECT_NODE_WITH_LLX(HIDX_UXXRL, uxxrl, uxxrl_op);
// Root -> Middle -> Right -> Left // Root -> Middle -> Right -> Left
if (uxxrl->GetWeight() == 0) { if (uxxrl->GetWeight() == 0) {
return RB2_R(ux, ux_lock, uxx, uxx_lock, return RB2_R(ux, ux_op, uxx, uxx_op,
uxxr, uxxr_lock, uxxrl, uxxrl_lock); uxxr, uxxr_op, uxxrl, uxxrl_op);
// Root -> Middle -> Right -> Middle // Root -> Middle -> Right -> Middle
} else if (uxxrl->GetWeight() == 1) { } 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; if (uxxrlr == NULL) return EMBB_BUSY;
// Root -> Middle -> Right -> Middle -> Left // Root -> Middle -> Right -> Middle -> Left
if (uxxrlr->GetWeight() == 0) { if (uxxrlr->GetWeight() == 0) {
// Protect node 'uxxrlr' // Protect node 'uxxrlr'
PROTECT_NODE_WITH_LOCK(uxxrlr, uxxrlr_lock); PROTECT_NODE_WITH_LLX(HIDX_UXXRLR, uxxrlr, uxxrlr_op);
return W4_L(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, return W4_L(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op,
uxxr, uxxr_lock, uxxrl, uxxrl_lock, uxxrlr, uxxrlr_lock); uxxr, uxxr_op, uxxrl, uxxrl_op, uxxrlr, uxxrlr_op);
// Root -> Middle -> Right -> Middle -> Right // Root -> Middle -> Right -> Middle -> Right
} else { } else {
assert(uxxrlr->GetWeight() > 0); assert(uxxrlr->GetWeight() > 0);
// Root -> Middle -> Right -> Middle -> Right -> Left // Root -> Middle -> Right -> Middle -> Right -> Left
// Node: reusing hazard of node 'uxxrlr' as it is no longer used // 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) { if (uxxrll->GetWeight() == 0) {
// Protect node 'uxxrll' // Protect node 'uxxrll'
PROTECT_NODE_WITH_LOCK(uxxrll, uxxrll_lock); PROTECT_NODE_WITH_LLX(HIDX_UXXRLL, uxxrll, uxxrll_op);
return W3_L(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, uxxr, return W3_L(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op, uxxr,
uxxr_lock, uxxrl, uxxrl_lock, uxxrll, uxxrll_lock); uxxr_op, uxxrl, uxxrl_op, uxxrll, uxxrll_op);
// Root -> Middle -> Right -> Middle -> Right -> Right // Root -> Middle -> Right -> Middle -> Right -> Right
} else { } else {
assert(uxxrll->GetWeight() > 0); assert(uxxrll->GetWeight() > 0);
return W2_L(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, return W2_L(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op,
uxxr, uxxr_lock, uxxrl, uxxrl_lock); uxxr, uxxr_op, uxxrl, uxxrl_op);
} }
} }
// Root -> Middle -> Right -> Right // Root -> Middle -> Right -> Right
} else { } else {
assert(uxxrl->GetWeight() > 1); assert(uxxrl->GetWeight() > 1);
return W1_L(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, return W1_L(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op,
uxxr, uxxr_lock, uxxrl, uxxrl_lock); uxxr, uxxr_op, uxxrl, uxxrl_op);
} }
} }
// Root -> Right // Root -> Right
} else if (uxxr->GetWeight() == 1) { } else if (uxxr->GetWeight() == 1) {
// Protect node 'uxxr' // Protect node 'uxxr'
PROTECT_NODE_WITH_LOCK(uxxr, uxxr_lock); PROTECT_NODE_WITH_LLX(HIDX_UXXR, uxxr, uxxr_op);
// Get children of 'uxxr' // Get children of 'uxxr'
DEFINE_NODE_WITH_HAZARD(8, uxxrl, uxxr, GetLeft); DEFINE_HAZARDOUS_NODE(HIDX_UXXRL, uxxrl, uxxr, GetLeft);
DEFINE_NODE_WITH_HAZARD(9, uxxrr, uxxr, GetRight); DEFINE_HAZARDOUS_NODE(HIDX_UXXRR, uxxrr, uxxr, GetRight);
if (uxxrl == NULL) return EMBB_BUSY; if (uxxrl == NULL) return EMBB_BUSY;
// Root -> Right -> Left // Root -> Right -> Left
if (uxxrr->GetWeight() == 0) { if (uxxrr->GetWeight() == 0) {
// Protect node 'uxxrr' // Protect node 'uxxrr'
PROTECT_NODE_WITH_LOCK(uxxrr, uxxrr_lock); PROTECT_NODE_WITH_LLX(HIDX_UXXRR, uxxrr, uxxrr_op);
return W5_L(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, return W5_L(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op,
uxxr, uxxr_lock, uxxrr, uxxrr_lock); uxxr, uxxr_op, uxxrr, uxxrr_op);
// Root -> Right -> Right // Root -> Right -> Right
} else { } else {
...@@ -877,15 +887,15 @@ OverweightLeft(HazardNodePtr& u, UniqueLock& u_lock, ...@@ -877,15 +887,15 @@ OverweightLeft(HazardNodePtr& u, UniqueLock& u_lock,
// Root -> Right -> Right -> Left // Root -> Right -> Right -> Left
if (uxxrl->GetWeight() == 0) { if (uxxrl->GetWeight() == 0) {
// Protect node 'uxxrl' // Protect node 'uxxrl'
PROTECT_NODE_WITH_LOCK(uxxrl, uxxrl_lock); PROTECT_NODE_WITH_LLX(HIDX_UXXRL, uxxrl, uxxrl_op);
return W6_L(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, return W6_L(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op,
uxxr, uxxr_lock, uxxrl, uxxrl_lock); uxxr, uxxr_op, uxxrl, uxxrl_op);
// Root -> Right -> Right -> Right // Root -> Right -> Right -> Right
} else { } else {
assert(uxxrl->GetWeight() > 0); assert(uxxrl->GetWeight() > 0);
return PUSH_L(ux, ux_lock, uxx, uxx_lock, return PUSH_L(ux, ux_op, uxx, uxx_op,
uxxl, uxxl_lock, uxxr, uxxr_lock); uxxl, uxxl_op, uxxr, uxxr_op);
} }
} }
...@@ -893,19 +903,19 @@ OverweightLeft(HazardNodePtr& u, UniqueLock& u_lock, ...@@ -893,19 +903,19 @@ OverweightLeft(HazardNodePtr& u, UniqueLock& u_lock,
} else { } else {
assert(uxxr->GetWeight() > 1); assert(uxxr->GetWeight() > 1);
// Protect node 'uxxr' // Protect node 'uxxr'
PROTECT_NODE_WITH_LOCK(uxxr, uxxr_lock); PROTECT_NODE_WITH_LLX(HIDX_UXXR, uxxr, uxxr_op);
return W7(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, uxxr, uxxr_lock); return W7(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op, uxxr, uxxr_op);
} }
} }
template<typename Key, typename Value, typename Compare, typename ValuePool> template<typename Key, typename Value, typename Compare, typename ValuePool>
embb_errors_t ChromaticTree<Key, Value, Compare, ValuePool>:: embb_errors_t ChromaticTree<Key, Value, Compare, ValuePool>::
OverweightRight(HazardNodePtr& u, UniqueLock& u_lock, OverweightRight(HazardNodePtr& u, HazardOperationPtr& u_op,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& ux, HazardOperationPtr& ux_op,
HazardNodePtr& uxx, UniqueLock& uxx_lock, HazardNodePtr& uxx, HazardOperationPtr& uxx_op,
HazardNodePtr& uxl, HazardNodePtr& uxr, HazardNodePtr& uxl, HazardNodePtr& uxr,
HazardNodePtr& uxxl, HazardNodePtr& uxxr, 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) // Let "Root" be the top of the overweight violation decision tree (see p.30)
// Root -> Middle // Root -> Middle
if (uxxl->GetWeight() == 0) { if (uxxl->GetWeight() == 0) {
...@@ -916,15 +926,15 @@ OverweightRight(HazardNodePtr& u, UniqueLock& u_lock, ...@@ -916,15 +926,15 @@ OverweightRight(HazardNodePtr& u, UniqueLock& u_lock,
// Root -> Middle -> Left -> Left -> Left // Root -> Middle -> Left -> Left -> Left
if (uxl->GetWeight() == 0) { if (uxl->GetWeight() == 0) {
// Protect node 'uxl' // Protect node 'uxl'
PROTECT_NODE_WITH_LOCK(uxl, uxl_lock); PROTECT_NODE_WITH_LLX(HIDX_UXL, uxl, uxl_op);
return BLK(u, u_lock, ux, ux_lock, uxl, uxl_lock, uxx, uxx_lock); return BLK(u, u_op, ux, ux_op, uxl, uxl_op, uxx, uxx_op);
// Root -> Middle -> Left -> Left -> Right // Root -> Middle -> Left -> Left -> Right
} else { } else {
assert(uxl->GetWeight() > 0); assert(uxl->GetWeight() > 0);
// Protect node 'uxxl' // Protect node 'uxxl'
PROTECT_NODE_WITH_LOCK(uxxl, uxxl_lock); PROTECT_NODE_WITH_LLX(HIDX_UXXL, uxxl, uxxl_op);
return RB2_R(u, u_lock, ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock); return RB2_R(u, u_op, ux, ux_op, uxx, uxx_op, uxxl, uxxl_op);
} }
// Root -> Middle -> Left -> Right // Root -> Middle -> Left -> Right
...@@ -933,13 +943,13 @@ OverweightRight(HazardNodePtr& u, UniqueLock& u_lock, ...@@ -933,13 +943,13 @@ OverweightRight(HazardNodePtr& u, UniqueLock& u_lock,
// Root -> Middle -> Left -> Right -> Left // Root -> Middle -> Left -> Right -> Left
if (uxr->GetWeight() == 0) { if (uxr->GetWeight() == 0) {
// Protect node 'uxr' // Protect node 'uxr'
PROTECT_NODE_WITH_LOCK(uxr, uxr_lock); PROTECT_NODE_WITH_LLX(HIDX_UXR, uxr, uxr_op);
return BLK(u, u_lock, ux, ux_lock, uxx, uxx_lock, uxr, uxr_lock); return BLK(u, u_op, ux, ux_op, uxx, uxx_op, uxr, uxr_op);
// Root -> Middle -> Left -> Right -> Right // Root -> Middle -> Left -> Right -> Right
} else { } else {
assert(uxr->GetWeight() > 0); 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, ...@@ -947,75 +957,75 @@ OverweightRight(HazardNodePtr& u, UniqueLock& u_lock,
} else { } else {
assert(uxx->GetWeight() > 0); assert(uxx->GetWeight() > 0);
// Protect node 'uxxl' // Protect node 'uxxl'
PROTECT_NODE_WITH_LOCK(uxxl, uxxl_lock); PROTECT_NODE_WITH_LLX(HIDX_UXXL, uxxl, uxxl_op);
// Get left child of 'uxxl' // Get left child of 'uxxl'
// Note: we know that 'uxxl' is not a leaf because it has weight 0. // 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 'uxxlr'
PROTECT_NODE_WITH_LOCK(uxxlr, uxxlr_lock); PROTECT_NODE_WITH_LLX(HIDX_UXXLR, uxxlr, uxxlr_op);
// Root -> Middle -> Right -> Left // Root -> Middle -> Right -> Left
if (uxxlr->GetWeight() == 0) { if (uxxlr->GetWeight() == 0) {
return RB2_L(ux, ux_lock, uxx, uxx_lock, return RB2_L(ux, ux_op, uxx, uxx_op,
uxxl, uxxl_lock, uxxlr, uxxlr_lock); uxxl, uxxl_op, uxxlr, uxxlr_op);
// Root -> Middle -> Right -> Middle // Root -> Middle -> Right -> Middle
} else if (uxxlr->GetWeight() == 1) { } 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; if (uxxlrl == NULL) return EMBB_BUSY;
// Root -> Middle -> Right -> Middle -> Left // Root -> Middle -> Right -> Middle -> Left
if (uxxlrl->GetWeight() == 0) { if (uxxlrl->GetWeight() == 0) {
// Protect node 'uxxlrl' // Protect node 'uxxlrl'
PROTECT_NODE_WITH_LOCK(uxxlrl, uxxlrl_lock); PROTECT_NODE_WITH_LLX(HIDX_UXXLRL, uxxlrl, uxxlrl_op);
return W4_R(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, return W4_R(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op,
uxxr, uxxr_lock, uxxlr, uxxlr_lock, uxxlrl, uxxlrl_lock); uxxr, uxxr_op, uxxlr, uxxlr_op, uxxlrl, uxxlrl_op);
// Root -> Middle -> Right -> Middle -> Right // Root -> Middle -> Right -> Middle -> Right
} else { } else {
assert(uxxlrl->GetWeight() > 0); assert(uxxlrl->GetWeight() > 0);
// Root -> Middle -> Right -> Middle -> Right -> Left // Root -> Middle -> Right -> Middle -> Right -> Left
// Node: reusing hazard of node 'uxxlrl' as it is no longer used // 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) { if (uxxlrr->GetWeight() == 0) {
// Protect node 'uxxlrr' // Protect node 'uxxlrr'
PROTECT_NODE_WITH_LOCK(uxxlrr, uxxlrr_lock); PROTECT_NODE_WITH_LLX(HIDX_UXXLRR, uxxlrr, uxxlrr_op);
return W3_R(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, uxxr, return W3_R(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op, uxxr,
uxxr_lock, uxxlr, uxxlr_lock, uxxlrr, uxxlrr_lock); uxxr_op, uxxlr, uxxlr_op, uxxlrr, uxxlrr_op);
// Root -> Middle -> Right -> Middle -> Right -> Right // Root -> Middle -> Right -> Middle -> Right -> Right
} else { } else {
assert(uxxlrr->GetWeight() > 0); assert(uxxlrr->GetWeight() > 0);
return W2_R(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, return W2_R(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op,
uxxr, uxxr_lock, uxxlr, uxxlr_lock); uxxr, uxxr_op, uxxlr, uxxlr_op);
} }
} }
// Root -> Middle -> Right -> Right // Root -> Middle -> Right -> Right
} else { } else {
assert(uxxlr->GetWeight() > 1); assert(uxxlr->GetWeight() > 1);
return W1_R(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, return W1_R(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op,
uxxr, uxxr_lock, uxxlr, uxxlr_lock); uxxr, uxxr_op, uxxlr, uxxlr_op);
} }
} }
// Root -> Right // Root -> Right
} else if (uxxl->GetWeight() == 1) { } else if (uxxl->GetWeight() == 1) {
// Protect node 'uxxl' // Protect node 'uxxl'
PROTECT_NODE_WITH_LOCK(uxxl, uxxl_lock); PROTECT_NODE_WITH_LLX(HIDX_UXXL, uxxl, uxxl_op);
// Get children of 'uxxl' // Get children of 'uxxl'
DEFINE_NODE_WITH_HAZARD(8, uxxll, uxxl, GetLeft); DEFINE_HAZARDOUS_NODE(HIDX_UXXLL, uxxll, uxxl, GetLeft);
DEFINE_NODE_WITH_HAZARD(9, uxxlr, uxxl, GetRight); DEFINE_HAZARDOUS_NODE(HIDX_UXXLR, uxxlr, uxxl, GetRight);
if (uxxll == NULL) return EMBB_BUSY; if (uxxll == NULL) return EMBB_BUSY;
// Root -> Right -> Left // Root -> Right -> Left
if (uxxll->GetWeight() == 0) { if (uxxll->GetWeight() == 0) {
// Protect node 'uxxll' // Protect node 'uxxll'
PROTECT_NODE_WITH_LOCK(uxxll, uxxll_lock); PROTECT_NODE_WITH_LLX(HIDX_UXXLL, uxxll, uxxll_op);
return W5_R(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, return W5_R(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op,
uxxr, uxxr_lock, uxxll, uxxll_lock); uxxr, uxxr_op, uxxll, uxxll_op);
// Root -> Right -> Right // Root -> Right -> Right
} else { } else {
...@@ -1023,15 +1033,15 @@ OverweightRight(HazardNodePtr& u, UniqueLock& u_lock, ...@@ -1023,15 +1033,15 @@ OverweightRight(HazardNodePtr& u, UniqueLock& u_lock,
// Root -> Right -> Right -> Left // Root -> Right -> Right -> Left
if (uxxlr->GetWeight() == 0) { if (uxxlr->GetWeight() == 0) {
// Protect node 'uxxlr' // Protect node 'uxxlr'
PROTECT_NODE_WITH_LOCK(uxxlr, uxxlr_lock); PROTECT_NODE_WITH_LLX(HIDX_UXXLR, uxxlr, uxxlr_op);
return W6_R(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, return W6_R(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op,
uxxr, uxxr_lock, uxxlr, uxxlr_lock); uxxr, uxxr_op, uxxlr, uxxlr_op);
// Root -> Right -> Right -> Right // Root -> Right -> Right -> Right
} else { } else {
assert(uxxlr->GetWeight() > 0); assert(uxxlr->GetWeight() > 0);
return PUSH_R(ux, ux_lock, uxx, uxx_lock, return PUSH_R(ux, ux_op, uxx, uxx_op,
uxxl, uxxl_lock, uxxr, uxxr_lock); uxxl, uxxl_op, uxxr, uxxr_op);
} }
} }
...@@ -1039,8 +1049,8 @@ OverweightRight(HazardNodePtr& u, UniqueLock& u_lock, ...@@ -1039,8 +1049,8 @@ OverweightRight(HazardNodePtr& u, UniqueLock& u_lock,
} else { } else {
assert(uxxl->GetWeight() > 1); assert(uxxl->GetWeight() > 1);
// Protect node 'uxxl' // Protect node 'uxxl'
PROTECT_NODE_WITH_LOCK(uxxl, uxxl_lock); PROTECT_NODE_WITH_LLX(HIDX_UXXL, uxxl, uxxl_op);
return W7(ux, ux_lock, uxx, uxx_lock, uxxl, uxxl_lock, uxxr, uxxr_lock); return W7(ux, ux_op, uxx, uxx_op, uxxl, uxxl_op, uxxr, uxxr_op);
} }
} }
......
...@@ -32,896 +32,1330 @@ ...@@ -32,896 +32,1330 @@
#ifndef EMBB_CONTAINERS_INTERNAL_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_ #ifndef EMBB_CONTAINERS_INTERNAL_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_
#define EMBB_CONTAINERS_INTERNAL_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_ #define EMBB_CONTAINERS_INTERNAL_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_
embb_errors_t BLK( embb_errors_t BLK(HazardNodePtr& u, HazardOperationPtr& u_op,
HazardNodePtr& u, UniqueLock& u_lock, HazardNodePtr& ux, HazardOperationPtr& ux_op,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& uxl, HazardOperationPtr& uxl_op,
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxr, HazardOperationPtr& uxr_op) {
HazardNodePtr& uxr, UniqueLock& uxr_lock) { embb_errors_t result = EMBB_NOMEM;
Node* nxl = node_pool_.Allocate( Node* nxl;
uxl->GetKey(), uxl->GetValue(), Node* nxr;
1, Node* nx;
uxl->GetLeft(), uxl->GetRight());
Node* nxr = node_pool_.Allocate( while (result != EMBB_SUCCESS) {
uxr->GetKey(), uxr->GetValue(), nxl = node_pool_.Allocate(
1, uxl->GetKey(), uxl->GetValue(), 1,
uxr->GetLeft(), uxr->GetRight()); uxl->GetLeft(), uxl->GetRight(), Operation::INITIAL_DUMMY);
Node* nx = node_pool_.Allocate( if (nxl == NULL) break;
ux->GetKey(), ux->GetValue(), nxr = node_pool_.Allocate(
IsSentinel(u) ? 1 : ux->GetWeight() - 1, uxr->GetKey(), uxr->GetValue(), 1,
nxl, nxr); uxr->GetLeft(), uxr->GetRight(), Operation::INITIAL_DUMMY);
if (nxr == NULL) break;
if (nxl == NULL || nx = node_pool_.Allocate(
nxr == NULL || ux->GetKey(), ux->GetValue(), IsSentinel(u) ? 1 : ux->GetWeight() - 1,
nx == NULL) { 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 (nxl) FreeNode(nxl);
if (nxr) FreeNode(nxr); if (nxr) FreeNode(nxr);
if (nx) FreeNode(nx); if (nx) FreeNode(nx);
return EMBB_NOMEM;
} }
bool rotation_succeeded = u->ReplaceChild(ux, nx); return result;
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;
} }
embb_errors_t PUSH_L( embb_errors_t PUSH_L(HazardNodePtr& u, HazardOperationPtr& u_op,
HazardNodePtr& u, UniqueLock& u_lock, HazardNodePtr& ux, HazardOperationPtr& ux_op,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& uxl, HazardOperationPtr& uxl_op,
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxr, HazardOperationPtr& uxr_op) {
HazardNodePtr& uxr, UniqueLock& uxr_lock) { embb_errors_t result = EMBB_NOMEM;
Node* nxl = node_pool_.Allocate( Node* nxl;
uxl->GetKey(), uxl->GetValue(), Node* nxr;
uxl->GetWeight() - 1, Node* nx;
uxl->GetLeft(), uxl->GetRight());
Node* nxr = node_pool_.Allocate( while (result != EMBB_SUCCESS) {
uxr->GetKey(), uxr->GetValue(), nxl = node_pool_.Allocate(
0, uxl->GetKey(), uxl->GetValue(), uxl->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight()); uxl->GetLeft(), uxl->GetRight(), Operation::INITIAL_DUMMY);
Node* nx = node_pool_.Allocate( if (nxl == NULL) break;
ux->GetKey(), ux->GetValue(), nxr = node_pool_.Allocate(
IsSentinel(u) ? 1 : ux->GetWeight() + 1, uxr->GetKey(), uxr->GetValue(), 0,
nxl, nxr); uxr->GetLeft(), uxr->GetRight(), Operation::INITIAL_DUMMY);
if (nxr == NULL) break;
if (nxl == NULL || nx = node_pool_.Allocate(
nxr == NULL || ux->GetKey(), ux->GetValue(), IsSentinel(u) ? 1 : ux->GetWeight() + 1,
nx == NULL) { 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 (nxl) FreeNode(nxl);
if (nxr) FreeNode(nxr); if (nxr) FreeNode(nxr);
if (nx) FreeNode(nx); if (nx) FreeNode(nx);
return EMBB_NOMEM;
} }
bool rotation_succeeded = u->ReplaceChild(ux, nx); return result;
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;
} }
embb_errors_t PUSH_R( embb_errors_t PUSH_R(HazardNodePtr& u, HazardOperationPtr& u_op,
HazardNodePtr& u, UniqueLock& u_lock, HazardNodePtr& ux, HazardOperationPtr& ux_op,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& uxl, HazardOperationPtr& uxl_op,
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxr, HazardOperationPtr& uxr_op) {
HazardNodePtr& uxr, UniqueLock& uxr_lock) { embb_errors_t result = EMBB_NOMEM;
Node* nxr = node_pool_.Allocate( Node* nxr;
uxr->GetKey(), uxr->GetValue(), Node* nxl;
uxr->GetWeight() - 1, Node* nx;
uxr->GetLeft(), uxr->GetRight());
Node* nxl = node_pool_.Allocate( while (result != EMBB_SUCCESS) {
uxl->GetKey(), uxl->GetValue(), nxr = node_pool_.Allocate(
0, uxr->GetKey(), uxr->GetValue(), uxr->GetWeight() - 1,
uxl->GetLeft(), uxl->GetRight()); uxr->GetLeft(), uxr->GetRight(), Operation::INITIAL_DUMMY);
Node* nx = node_pool_.Allocate( if (nxr == NULL) break;
ux->GetKey(), ux->GetValue(), nxl = node_pool_.Allocate(
IsSentinel(u) ? 1 : ux->GetWeight() + 1, uxl->GetKey(), uxl->GetValue(), 0,
nxl, nxr); uxl->GetLeft(), uxl->GetRight(), Operation::INITIAL_DUMMY);
if (nxl == NULL) break;
if (nxr == NULL || nx = node_pool_.Allocate(
nxl == NULL || ux->GetKey(), ux->GetValue(), IsSentinel(u) ? 1 : ux->GetWeight() + 1,
nx == NULL) { 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 (nxr) FreeNode(nxr);
if (nxl) FreeNode(nxl); if (nxl) FreeNode(nxl);
if (nx) FreeNode(nx); if (nx) FreeNode(nx);
return EMBB_NOMEM;
} }
bool rotation_succeeded = u->ReplaceChild(ux, nx); return result;
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;
} }
embb_errors_t RB1_L( embb_errors_t RB1_L(HazardNodePtr& u, HazardOperationPtr& u_op,
HazardNodePtr& u, UniqueLock& u_lock, HazardNodePtr& ux, HazardOperationPtr& ux_op,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& uxl, HazardOperationPtr& uxl_op) {
HazardNodePtr& uxl, UniqueLock& uxl_lock) { embb_errors_t result = EMBB_NOMEM;
Node* nxr = node_pool_.Allocate( Node* nxr;
ux->GetKey(), ux->GetValue(), Node* nx;
0,
uxl->GetRight(), ux->GetRight()); while (result != EMBB_SUCCESS) {
Node* nx = node_pool_.Allocate( nxr = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(), ux->GetKey(), ux->GetValue(), 0,
ux->GetWeight(), uxl->GetRight(), ux->GetRight(), Operation::INITIAL_DUMMY);
uxl->GetLeft(), nxr); if (nxr == NULL) break;
nx = node_pool_.Allocate(
if (nxr == NULL || uxl->GetKey(), uxl->GetValue(), ux->GetWeight(),
nx == NULL) { 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 (nxr) FreeNode(nxr);
if (nx) FreeNode(nx); if (nx) FreeNode(nx);
return EMBB_NOMEM;
} }
bool rotation_succeeded = u->ReplaceChild(ux, nx); return result;
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;
} }
embb_errors_t RB1_R( embb_errors_t RB1_R(HazardNodePtr& u, HazardOperationPtr& u_op,
HazardNodePtr& u, UniqueLock& u_lock, HazardNodePtr& ux, HazardOperationPtr& ux_op,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& uxr, HazardOperationPtr& uxr_op) {
HazardNodePtr& uxr, UniqueLock& uxr_lock) { embb_errors_t result = EMBB_NOMEM;
Node* nxl = node_pool_.Allocate( Node* nxl;
ux->GetKey(), ux->GetValue(), Node* nx;
0,
ux->GetLeft(), uxr->GetLeft()); while (result != EMBB_SUCCESS) {
Node* nx = node_pool_.Allocate( nxl = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(), ux->GetKey(), ux->GetValue(), 0,
ux->GetWeight(), ux->GetLeft(), uxr->GetLeft(), Operation::INITIAL_DUMMY);
nxl, uxr->GetRight()); if (nxl == NULL) break;
nx = node_pool_.Allocate(
if (nxl == NULL || uxr->GetKey(), uxr->GetValue(), ux->GetWeight(),
nx == NULL) { 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 (nxl) FreeNode(nxl);
if (nx) FreeNode(nx); if (nx) FreeNode(nx);
return EMBB_NOMEM;
} }
bool rotation_succeeded = u->ReplaceChild(ux, nx); return result;
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;
} }
embb_errors_t RB2_L( embb_errors_t RB2_L(HazardNodePtr& u, HazardOperationPtr& u_op,
HazardNodePtr& u, UniqueLock& u_lock, HazardNodePtr& ux, HazardOperationPtr& ux_op,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& uxl, HazardOperationPtr& uxl_op,
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxlr, HazardOperationPtr& uxlr_op) {
HazardNodePtr& uxlr, UniqueLock& uxlr_lock) { embb_errors_t result = EMBB_NOMEM;
Node* nxl = node_pool_.Allocate( Node* nxl;
uxl->GetKey(), uxl->GetValue(), Node* nxr;
0, Node* nx;
uxl->GetLeft(), uxlr->GetLeft());
Node* nxr = node_pool_.Allocate( while (result != EMBB_SUCCESS) {
ux->GetKey(), ux->GetValue(), nxl = node_pool_.Allocate(
0, uxl->GetKey(), uxl->GetValue(), 0,
uxlr->GetRight(), ux->GetRight()); uxl->GetLeft(), uxlr->GetLeft(), Operation::INITIAL_DUMMY);
Node* nx = node_pool_.Allocate( if (nxl == NULL) break;
uxlr->GetKey(), uxlr->GetValue(), nxr = node_pool_.Allocate(
ux->GetWeight(), ux->GetKey(), ux->GetValue(), 0,
nxl, nxr); uxlr->GetRight(), ux->GetRight(), Operation::INITIAL_DUMMY);
if (nxr == NULL) break;
if (nxl == NULL || nx = node_pool_.Allocate(
nxr == NULL || uxlr->GetKey(), uxlr->GetValue(), ux->GetWeight(),
nx == NULL) { 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 (nxl) FreeNode(nxl);
if (nxr) FreeNode(nxr); if (nxr) FreeNode(nxr);
if (nx) FreeNode(nx); if (nx) FreeNode(nx);
return EMBB_NOMEM;
} }
bool rotation_succeeded = u->ReplaceChild(ux, nx); return result;
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;
} }
embb_errors_t RB2_R( embb_errors_t RB2_R(HazardNodePtr& u, HazardOperationPtr& u_op,
HazardNodePtr& u, UniqueLock& u_lock, HazardNodePtr& ux, HazardOperationPtr& ux_op,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& uxr, HazardOperationPtr& uxr_op,
HazardNodePtr& uxr, UniqueLock& uxr_lock, HazardNodePtr& uxrl, HazardOperationPtr& uxrl_op) {
HazardNodePtr& uxrl, UniqueLock& uxrl_lock) { embb_errors_t result = EMBB_NOMEM;
Node* nxr = node_pool_.Allocate( Node* nxr;
uxr->GetKey(), uxr->GetValue(), Node* nxl;
0, Node* nx;
uxrl->GetRight(), uxr->GetRight());
Node* nxl = node_pool_.Allocate( while (result != EMBB_SUCCESS) {
ux->GetKey(), ux->GetValue(), nxr = node_pool_.Allocate(
0, uxr->GetKey(), uxr->GetValue(), 0,
ux->GetLeft(), uxrl->GetLeft()); uxrl->GetRight(), uxr->GetRight(), Operation::INITIAL_DUMMY);
Node* nx = node_pool_.Allocate( if (nxr == NULL) break;
uxrl->GetKey(), uxrl->GetValue(), nxl = node_pool_.Allocate(
ux->GetWeight(), ux->GetKey(), ux->GetValue(), 0,
nxl, nxr); ux->GetLeft(), uxrl->GetLeft(), Operation::INITIAL_DUMMY);
if (nxl == NULL) break;
if (nxr == NULL || nx = node_pool_.Allocate(
nxl == NULL || uxrl->GetKey(), uxrl->GetValue(), ux->GetWeight(),
nx == NULL) { 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 (nxr) FreeNode(nxr);
if (nxl) FreeNode(nxl); if (nxl) FreeNode(nxl);
if (nx) FreeNode(nx); if (nx) FreeNode(nx);
return EMBB_NOMEM;
} }
bool rotation_succeeded = u->ReplaceChild(ux, nx); return result;
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;
} }
embb_errors_t W1_L( embb_errors_t W1_L(HazardNodePtr& u, HazardOperationPtr& u_op,
HazardNodePtr& u, UniqueLock& u_lock, HazardNodePtr& ux, HazardOperationPtr& ux_op,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& uxl, HazardOperationPtr& uxl_op,
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxr, HazardOperationPtr& uxr_op,
HazardNodePtr& uxr, UniqueLock& uxr_lock, HazardNodePtr& uxrl, HazardOperationPtr& uxrl_op) {
HazardNodePtr& uxrl, UniqueLock& uxrl_lock) { embb_errors_t result = EMBB_NOMEM;
Node* nxll = node_pool_.Allocate( Node* nxll;
uxl->GetKey(), uxl->GetValue(), Node* nxlr;
uxl->GetWeight() - 1, Node* nxl;
uxl->GetLeft(), uxl->GetRight()); Node* nx;
Node* nxlr = node_pool_.Allocate(
uxrl->GetKey(), uxrl->GetValue(), while (result != EMBB_SUCCESS) {
uxrl->GetWeight() - 1, nxll = node_pool_.Allocate(
uxrl->GetLeft(), uxrl->GetRight()); uxl->GetKey(), uxl->GetValue(), uxl->GetWeight() - 1,
Node* nxl = node_pool_.Allocate( uxl->GetLeft(), uxl->GetRight(), Operation::INITIAL_DUMMY);
ux->GetKey(), ux->GetValue(), if (nxll == NULL) break;
1, nxlr = node_pool_.Allocate(
nxll, nxlr); uxrl->GetKey(), uxrl->GetValue(), uxrl->GetWeight() - 1,
Node* nx = node_pool_.Allocate( uxrl->GetLeft(), uxrl->GetRight(), Operation::INITIAL_DUMMY);
uxr->GetKey(), uxr->GetValue(), if (nxlr == NULL) break;
ux->GetWeight(), nxl = node_pool_.Allocate(
nxl, uxr->GetRight()); ux->GetKey(), ux->GetValue(), 1,
nxll, nxlr, Operation::INITIAL_DUMMY);
if (nxll == NULL || if (nxl == NULL) break;
nxlr == NULL || nx = node_pool_.Allocate(
nxl == NULL || uxr->GetKey(), uxr->GetValue(), ux->GetWeight(),
nx == NULL) { 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 (nxll) FreeNode(nxll);
if (nxlr) FreeNode(nxlr); if (nxlr) FreeNode(nxlr);
if (nxl) FreeNode(nxl); if (nxl) FreeNode(nxl);
if (nx) FreeNode(nx); if (nx) FreeNode(nx);
return EMBB_NOMEM;
} }
bool rotation_succeeded = u->ReplaceChild(ux, nx); return result;
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;
} }
embb_errors_t W1_R( embb_errors_t W1_R(HazardNodePtr& u, HazardOperationPtr& u_op,
HazardNodePtr& u, UniqueLock& u_lock, HazardNodePtr& ux, HazardOperationPtr& ux_op,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& uxl, HazardOperationPtr& uxl_op,
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxr, HazardOperationPtr& uxr_op,
HazardNodePtr& uxr, UniqueLock& uxr_lock, HazardNodePtr& uxlr, HazardOperationPtr& uxlr_op) {
HazardNodePtr& uxlr, UniqueLock& uxlr_lock) { embb_errors_t result = EMBB_NOMEM;
Node* nxrr = node_pool_.Allocate( Node* nxrr;
uxr->GetKey(), uxr->GetValue(), Node* nxrl;
uxr->GetWeight() - 1, Node* nxr;
uxr->GetLeft(), uxr->GetRight()); Node* nx;
Node* nxrl = node_pool_.Allocate(
uxlr->GetKey(), uxlr->GetValue(), while (result != EMBB_SUCCESS) {
uxlr->GetWeight() - 1, nxrr = node_pool_.Allocate(
uxlr->GetLeft(), uxlr->GetRight()); uxr->GetKey(), uxr->GetValue(), uxr->GetWeight() - 1,
Node* nxr = node_pool_.Allocate( uxr->GetLeft(), uxr->GetRight(), Operation::INITIAL_DUMMY);
ux->GetKey(), ux->GetValue(), if (nxrr == NULL) break;
1, nxrl = node_pool_.Allocate(
nxrl, nxrr); uxlr->GetKey(), uxlr->GetValue(), uxlr->GetWeight() - 1,
Node* nx = node_pool_.Allocate( uxlr->GetLeft(), uxlr->GetRight(), Operation::INITIAL_DUMMY);
uxl->GetKey(), uxl->GetValue(), if (nxrl == NULL) break;
ux->GetWeight(), nxr = node_pool_.Allocate(
uxl->GetLeft(), nxr); ux->GetKey(), ux->GetValue(), 1,
nxrl, nxrr, Operation::INITIAL_DUMMY);
if (nxrr == NULL || if (nxr == NULL) break;
nxrl == NULL || nx = node_pool_.Allocate(
nxr == NULL || uxl->GetKey(), uxl->GetValue(), ux->GetWeight(),
nx == NULL) { 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 (nxrr) FreeNode(nxrr);
if (nxrl) FreeNode(nxrl); if (nxrl) FreeNode(nxrl);
if (nxr) FreeNode(nxr); if (nxr) FreeNode(nxr);
if (nx) FreeNode(nx); if (nx) FreeNode(nx);
return EMBB_NOMEM;
} }
bool rotation_succeeded = u->ReplaceChild(ux, nx); return result;
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;
} }
embb_errors_t W2_L( embb_errors_t W2_L(HazardNodePtr& u, HazardOperationPtr& u_op,
HazardNodePtr& u, UniqueLock& u_lock, HazardNodePtr& ux, HazardOperationPtr& ux_op,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& uxl, HazardOperationPtr& uxl_op,
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxr, HazardOperationPtr& uxr_op,
HazardNodePtr& uxr, UniqueLock& uxr_lock, HazardNodePtr& uxrl, HazardOperationPtr& uxrl_op) {
HazardNodePtr& uxrl, UniqueLock& uxrl_lock) { embb_errors_t result = EMBB_NOMEM;
Node* nxll = node_pool_.Allocate( Node* nxll;
uxl->GetKey(), uxl->GetValue(), Node* nxlr;
uxl->GetWeight() - 1, Node* nxl;
uxl->GetLeft(), uxl->GetRight()); Node* nx;
Node* nxlr = node_pool_.Allocate(
uxrl->GetKey(), uxrl->GetValue(), while (result != EMBB_SUCCESS) {
0, nxll = node_pool_.Allocate(
uxrl->GetLeft(), uxrl->GetRight()); uxl->GetKey(), uxl->GetValue(), uxl->GetWeight() - 1,
Node* nxl = node_pool_.Allocate( uxl->GetLeft(), uxl->GetRight(), Operation::INITIAL_DUMMY);
ux->GetKey(), ux->GetValue(), if (nxll == NULL) break;
1, nxlr = node_pool_.Allocate(
nxll, nxlr); uxrl->GetKey(), uxrl->GetValue(), 0,
Node* nx = node_pool_.Allocate( uxrl->GetLeft(), uxrl->GetRight(), Operation::INITIAL_DUMMY);
uxr->GetKey(), uxr->GetValue(), if (nxlr == NULL) break;
ux->GetWeight(), nxl = node_pool_.Allocate(
nxl, uxr->GetRight()); ux->GetKey(), ux->GetValue(), 1,
nxll, nxlr, Operation::INITIAL_DUMMY);
if (nxll == NULL || if (nxl == NULL) break;
nxlr == NULL || nx = node_pool_.Allocate(
nxl == NULL || uxr->GetKey(), uxr->GetValue(), ux->GetWeight(),
nx == NULL) { 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 (nxll) FreeNode(nxll);
if (nxlr) FreeNode(nxlr); if (nxlr) FreeNode(nxlr);
if (nxl) FreeNode(nxl); if (nxl) FreeNode(nxl);
if (nx) FreeNode(nx); if (nx) FreeNode(nx);
return EMBB_NOMEM;
} }
bool rotation_succeeded = u->ReplaceChild(ux, nx); return result;
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;
} }
embb_errors_t W2_R( embb_errors_t W2_R(HazardNodePtr& u, HazardOperationPtr& u_op,
HazardNodePtr& u, UniqueLock& u_lock, HazardNodePtr& ux, HazardOperationPtr& ux_op,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& uxl, HazardOperationPtr& uxl_op,
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxr, HazardOperationPtr& uxr_op,
HazardNodePtr& uxr, UniqueLock& uxr_lock, HazardNodePtr& uxlr, HazardOperationPtr& uxlr_op) {
HazardNodePtr& uxlr, UniqueLock& uxlr_lock) { embb_errors_t result = EMBB_NOMEM;
Node* nxrr = node_pool_.Allocate( Node* nxrr;
uxr->GetKey(), uxr->GetValue(), Node* nxrl;
uxr->GetWeight() - 1, Node* nxr;
uxr->GetLeft(), uxr->GetRight()); Node* nx;
Node* nxrl = node_pool_.Allocate(
uxlr->GetKey(), uxlr->GetValue(), while (result != EMBB_SUCCESS) {
0, nxrr = node_pool_.Allocate(
uxlr->GetLeft(), uxlr->GetRight()); uxr->GetKey(), uxr->GetValue(), uxr->GetWeight() - 1,
Node* nxr = node_pool_.Allocate( uxr->GetLeft(), uxr->GetRight(), Operation::INITIAL_DUMMY);
ux->GetKey(), ux->GetValue(), if (nxrr == NULL) break;
1, nxrl = node_pool_.Allocate(
nxrl, nxrr); uxlr->GetKey(), uxlr->GetValue(), 0,
Node* nx = node_pool_.Allocate( uxlr->GetLeft(), uxlr->GetRight(), Operation::INITIAL_DUMMY);
uxl->GetKey(), uxl->GetValue(), if (nxrl == NULL) break;
ux->GetWeight(), nxr = node_pool_.Allocate(
uxl->GetLeft(), nxr); ux->GetKey(), ux->GetValue(), 1,
nxrl, nxrr, Operation::INITIAL_DUMMY);
if (nxrr == NULL || if (nxr == NULL) break;
nxrl == NULL || nx = node_pool_.Allocate(
nxr == NULL || uxl->GetKey(), uxl->GetValue(), ux->GetWeight(),
nx == NULL) { 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 (nxrr) FreeNode(nxrr);
if (nxrl) FreeNode(nxrl); if (nxrl) FreeNode(nxrl);
if (nxr) FreeNode(nxr); if (nxr) FreeNode(nxr);
if (nx) FreeNode(nx); if (nx) FreeNode(nx);
return EMBB_NOMEM;
} }
bool rotation_succeeded = u->ReplaceChild(ux, nx); return result;
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;
} }
embb_errors_t W3_L( embb_errors_t W3_L(HazardNodePtr& u, HazardOperationPtr& u_op,
HazardNodePtr& u, UniqueLock& u_lock, HazardNodePtr& ux, HazardOperationPtr& ux_op,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& uxl, HazardOperationPtr& uxl_op,
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxr, HazardOperationPtr& uxr_op,
HazardNodePtr& uxr, UniqueLock& uxr_lock, HazardNodePtr& uxrl, HazardOperationPtr& uxrl_op,
HazardNodePtr& uxrl, UniqueLock& uxrl_lock, HazardNodePtr& uxrll, HazardOperationPtr& uxrll_op) {
HazardNodePtr& uxrll, UniqueLock& uxrll_lock) { embb_errors_t result = EMBB_NOMEM;
Node* nxlll = node_pool_.Allocate( Node* nxlll;
uxl->GetKey(), uxl->GetValue(), Node* nxll;
uxl->GetWeight() - 1, Node* nxlr;
uxl->GetLeft(), uxl->GetRight()); Node* nxl;
Node* nxll = node_pool_.Allocate( Node* nx;
ux->GetKey(), ux->GetValue(),
1, while (result != EMBB_SUCCESS) {
nxlll, uxrll->GetLeft()); nxlll = node_pool_.Allocate(
Node* nxlr = node_pool_.Allocate( uxl->GetKey(), uxl->GetValue(), uxl->GetWeight() - 1,
uxrl->GetKey(), uxrl->GetValue(), uxl->GetLeft(), uxl->GetRight(), Operation::INITIAL_DUMMY);
1, if (nxlll == NULL) break;
uxrll->GetRight(), uxrl->GetRight()); nxll = node_pool_.Allocate(
Node* nxl = node_pool_.Allocate( ux->GetKey(), ux->GetValue(), 1,
uxrll->GetKey(), uxrll->GetValue(), nxlll, uxrll->GetLeft(), Operation::INITIAL_DUMMY);
0, if (nxll == NULL) break;
nxll, nxlr); nxlr = node_pool_.Allocate(
Node* nx = node_pool_.Allocate( uxrl->GetKey(), uxrl->GetValue(), 1,
uxr->GetKey(), uxr->GetValue(), uxrll->GetRight(), uxrl->GetRight(), Operation::INITIAL_DUMMY);
ux->GetWeight(), if (nxlr == NULL) break;
nxl, uxr->GetRight()); nxl = node_pool_.Allocate(
uxrll->GetKey(), uxrll->GetValue(), 0,
if (nxlll == NULL || nxll, nxlr, Operation::INITIAL_DUMMY);
nxll == NULL || if (nxl == NULL) break;
nxlr == NULL || nx = node_pool_.Allocate(
nxl == NULL || uxr->GetKey(), uxr->GetValue(), ux->GetWeight(),
nx == NULL) { 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 (nxlll) FreeNode(nxlll);
if (nxll) FreeNode(nxll); if (nxll) FreeNode(nxll);
if (nxlr) FreeNode(nxlr); if (nxlr) FreeNode(nxlr);
if (nxl) FreeNode(nxl); if (nxl) FreeNode(nxl);
if (nx) FreeNode(nx); if (nx) FreeNode(nx);
return EMBB_NOMEM;
} }
bool rotation_succeeded = u->ReplaceChild(ux, nx); return result;
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;
} }
embb_errors_t W3_R( embb_errors_t W3_R(HazardNodePtr& u, HazardOperationPtr& u_op,
HazardNodePtr& u, UniqueLock& u_lock, HazardNodePtr& ux, HazardOperationPtr& ux_op,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& uxl, HazardOperationPtr& uxl_op,
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxr, HazardOperationPtr& uxr_op,
HazardNodePtr& uxr, UniqueLock& uxr_lock, HazardNodePtr& uxlr, HazardOperationPtr& uxlr_op,
HazardNodePtr& uxlr, UniqueLock& uxlr_lock, HazardNodePtr& uxlrr, HazardOperationPtr& uxlrr_op) {
HazardNodePtr& uxlrr, UniqueLock& uxlrr_lock) { embb_errors_t result = EMBB_NOMEM;
Node* nxrrr = node_pool_.Allocate( Node* nxrrr;
uxr->GetKey(), uxr->GetValue(), Node* nxrr;
uxr->GetWeight() - 1, Node* nxrl;
uxr->GetLeft(), uxr->GetRight()); Node* nxr;
Node* nxrr = node_pool_.Allocate( Node* nx;
ux->GetKey(), ux->GetValue(),
1, while (result != EMBB_SUCCESS) {
uxlrr->GetRight(), nxrrr); nxrrr = node_pool_.Allocate(
Node* nxrl = node_pool_.Allocate( uxr->GetKey(), uxr->GetValue(), uxr->GetWeight() - 1,
uxlr->GetKey(), uxlr->GetValue(), uxr->GetLeft(), uxr->GetRight(), Operation::INITIAL_DUMMY);
1, if (nxrrr == NULL) break;
uxlr->GetLeft(), uxlrr->GetLeft()); nxrr = node_pool_.Allocate(
Node* nxr = node_pool_.Allocate( ux->GetKey(), ux->GetValue(), 1,
uxlrr->GetKey(), uxlrr->GetValue(), uxlrr->GetRight(), nxrrr, Operation::INITIAL_DUMMY);
0, if (nxrr == NULL) break;
nxrl, nxrr); nxrl = node_pool_.Allocate(
Node* nx = node_pool_.Allocate( uxlr->GetKey(), uxlr->GetValue(), 1,
uxl->GetKey(), uxl->GetValue(), uxlr->GetLeft(), uxlrr->GetLeft(), Operation::INITIAL_DUMMY);
ux->GetWeight(), if (nxrl == NULL) break;
uxl->GetLeft(), nxr); nxr = node_pool_.Allocate(
uxlrr->GetKey(), uxlrr->GetValue(), 0,
if (nxrrr == NULL || nxrl, nxrr, Operation::INITIAL_DUMMY);
nxrr == NULL || if (nxr == NULL) break;
nxrl == NULL || nx = node_pool_.Allocate(
nxr == NULL || uxl->GetKey(), uxl->GetValue(), ux->GetWeight(),
nx == NULL) { 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 (nxrrr) FreeNode(nxrrr);
if (nxrr) FreeNode(nxrr); if (nxrr) FreeNode(nxrr);
if (nxrl) FreeNode(nxrl); if (nxrl) FreeNode(nxrl);
if (nxr) FreeNode(nxr); if (nxr) FreeNode(nxr);
if (nx) FreeNode(nx); if (nx) FreeNode(nx);
return EMBB_NOMEM;
} }
bool rotation_succeeded = u->ReplaceChild(ux, nx); return result;
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;
} }
embb_errors_t W4_L( embb_errors_t W4_L(HazardNodePtr& u, HazardOperationPtr& u_op,
HazardNodePtr& u, UniqueLock& u_lock, HazardNodePtr& ux, HazardOperationPtr& ux_op,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& uxl, HazardOperationPtr& uxl_op,
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxr, HazardOperationPtr& uxr_op,
HazardNodePtr& uxr, UniqueLock& uxr_lock, HazardNodePtr& uxrl, HazardOperationPtr& uxrl_op,
HazardNodePtr& uxrl, UniqueLock& uxrl_lock, HazardNodePtr& uxrlr, HazardOperationPtr& uxrlr_op) {
HazardNodePtr& uxrlr, UniqueLock& uxrlr_lock) { embb_errors_t result = EMBB_NOMEM;
Node* nxll = node_pool_.Allocate( Node* nxll;
uxl->GetKey(), uxl->GetValue(), Node* nxrl;
uxl->GetWeight() - 1, Node* nxl;
uxl->GetLeft(), uxl->GetRight()); Node* nxr;
Node* nxrl = node_pool_.Allocate( Node* nx;
uxrlr->GetKey(), uxrlr->GetValue(),
1, while (result != EMBB_SUCCESS) {
uxrlr->GetLeft(), uxrlr->GetRight()); nxll = node_pool_.Allocate(
Node* nxl = node_pool_.Allocate( uxl->GetKey(), uxl->GetValue(), uxl->GetWeight() - 1,
ux->GetKey(), ux->GetValue(), uxl->GetLeft(), uxl->GetRight(), Operation::INITIAL_DUMMY);
1, if (nxll == NULL) break;
nxll, uxrl->GetLeft()); nxrl = node_pool_.Allocate(
Node* nxr = node_pool_.Allocate( uxrlr->GetKey(), uxrlr->GetValue(), 1,
uxr->GetKey(), uxr->GetValue(), uxrlr->GetLeft(), uxrlr->GetRight(), Operation::INITIAL_DUMMY);
0, if (nxrl == NULL) break;
nxrl, uxr->GetRight()); nxl = node_pool_.Allocate(
Node* nx = node_pool_.Allocate( ux->GetKey(), ux->GetValue(), 1,
uxrl->GetKey(), uxrl->GetValue(), nxll, uxrl->GetLeft(), Operation::INITIAL_DUMMY);
ux->GetWeight(), if (nxl == NULL) break;
nxl, nxr); nxr = node_pool_.Allocate(
uxr->GetKey(), uxr->GetValue(), 0,
if (nxll == NULL || nxrl, uxr->GetRight(), Operation::INITIAL_DUMMY);
nxrl == NULL || if (nxr == NULL) break;
nxl == NULL || nx = node_pool_.Allocate(
nxr == NULL || uxrl->GetKey(), uxrl->GetValue(), ux->GetWeight(),
nx == NULL) { 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 (nxll) FreeNode(nxll);
if (nxrl) FreeNode(nxrl); if (nxrl) FreeNode(nxrl);
if (nxl) FreeNode(nxl); if (nxl) FreeNode(nxl);
if (nxr) FreeNode(nxr); if (nxr) FreeNode(nxr);
if (nx) FreeNode(nx); if (nx) FreeNode(nx);
return EMBB_NOMEM;
} }
bool rotation_succeeded = u->ReplaceChild(ux, nx); return result;
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;
} }
embb_errors_t W4_R( embb_errors_t W4_R(HazardNodePtr& u, HazardOperationPtr& u_op,
HazardNodePtr& u, UniqueLock& u_lock, HazardNodePtr& ux, HazardOperationPtr& ux_op,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& uxl, HazardOperationPtr& uxl_op,
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxr, HazardOperationPtr& uxr_op,
HazardNodePtr& uxr, UniqueLock& uxr_lock, HazardNodePtr& uxlr, HazardOperationPtr& uxlr_op,
HazardNodePtr& uxlr, UniqueLock& uxlr_lock, HazardNodePtr& uxlrl, HazardOperationPtr& uxlrl_op) {
HazardNodePtr& uxlrl, UniqueLock& uxlrl_lock) { embb_errors_t result = EMBB_NOMEM;
Node* nxrr = node_pool_.Allocate( Node* nxrr;
uxr->GetKey(), uxr->GetValue(), Node* nxlr;
uxr->GetWeight() - 1, Node* nxr;
uxr->GetLeft(), uxr->GetRight()); Node* nxl;
Node* nxlr = node_pool_.Allocate( Node* nx;
uxlrl->GetKey(), uxlrl->GetValue(),
1, while (result != EMBB_SUCCESS) {
uxlrl->GetLeft(), uxlrl->GetRight()); nxrr = node_pool_.Allocate(
Node* nxr = node_pool_.Allocate( uxr->GetKey(), uxr->GetValue(), uxr->GetWeight() - 1,
ux->GetKey(), ux->GetValue(), uxr->GetLeft(), uxr->GetRight(), Operation::INITIAL_DUMMY);
1, if (nxrr == NULL) break;
uxlr->GetRight(), nxrr); nxlr = node_pool_.Allocate(
Node* nxl = node_pool_.Allocate( uxlrl->GetKey(), uxlrl->GetValue(), 1,
uxl->GetKey(), uxl->GetValue(), uxlrl->GetLeft(), uxlrl->GetRight(), Operation::INITIAL_DUMMY);
0, if (nxlr == NULL) break;
uxl->GetLeft(), nxlr); nxr = node_pool_.Allocate(
Node* nx = node_pool_.Allocate( ux->GetKey(), ux->GetValue(), 1,
uxlr->GetKey(), uxlr->GetValue(), uxlr->GetRight(), nxrr, Operation::INITIAL_DUMMY);
ux->GetWeight(), if (nxr == NULL) break;
nxl, nxr); nxl = node_pool_.Allocate(
uxl->GetKey(), uxl->GetValue(), 0,
if (nxrr == NULL || uxl->GetLeft(), nxlr, Operation::INITIAL_DUMMY);
nxlr == NULL || if (nxl == NULL) break;
nxr == NULL || nx = node_pool_.Allocate(
nxl == NULL || uxlr->GetKey(), uxlr->GetValue(), ux->GetWeight(),
nx == NULL) { 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 (nxrr) FreeNode(nxrr);
if (nxlr) FreeNode(nxlr); if (nxlr) FreeNode(nxlr);
if (nxr) FreeNode(nxr); if (nxr) FreeNode(nxr);
if (nxl) FreeNode(nxl); if (nxl) FreeNode(nxl);
if (nx) FreeNode(nx); if (nx) FreeNode(nx);
return EMBB_NOMEM;
} }
bool rotation_succeeded = u->ReplaceChild(ux, nx); return result;
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;
} }
embb_errors_t W5_L( embb_errors_t W5_L(HazardNodePtr& u, HazardOperationPtr& u_op,
HazardNodePtr& u, UniqueLock& u_lock, HazardNodePtr& ux, HazardOperationPtr& ux_op,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& uxl, HazardOperationPtr& uxl_op,
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxr, HazardOperationPtr& uxr_op,
HazardNodePtr& uxr, UniqueLock& uxr_lock, HazardNodePtr& uxrr, HazardOperationPtr& uxrr_op) {
HazardNodePtr& uxrr, UniqueLock& uxrr_lock) { embb_errors_t result = EMBB_NOMEM;
Node* nxll = node_pool_.Allocate( Node* nxll;
uxl->GetKey(), uxl->GetValue(), Node* nxl;
uxl->GetWeight() - 1, Node* nxr;
uxl->GetLeft(), uxl->GetRight()); Node* nx;
Node* nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), while (result != EMBB_SUCCESS) {
1, nxll = node_pool_.Allocate(
nxll, uxr->GetLeft()); uxl->GetKey(), uxl->GetValue(), uxl->GetWeight() - 1,
Node* nxr = node_pool_.Allocate( uxl->GetLeft(), uxl->GetRight(), Operation::INITIAL_DUMMY);
uxrr->GetKey(), uxrr->GetValue(), if (nxll == NULL) break;
1, nxl = node_pool_.Allocate(
uxrr->GetLeft(), uxrr->GetRight()); ux->GetKey(), ux->GetValue(), 1,
Node* nx = node_pool_.Allocate( nxll, uxr->GetLeft(), Operation::INITIAL_DUMMY);
uxr->GetKey(), uxr->GetValue(), if (nxl == NULL) break;
ux->GetWeight(), nxr = node_pool_.Allocate(
nxl, nxr); uxrr->GetKey(), uxrr->GetValue(), 1,
uxrr->GetLeft(), uxrr->GetRight(), Operation::INITIAL_DUMMY);
if (nxll == NULL || if (nxr == NULL) break;
nxl == NULL || nx = node_pool_.Allocate(
nxr == NULL || uxr->GetKey(), uxr->GetValue(), ux->GetWeight(),
nx == NULL) { 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 (nxll) FreeNode(nxll);
if (nxl) FreeNode(nxl); if (nxl) FreeNode(nxl);
if (nxr) FreeNode(nxr); if (nxr) FreeNode(nxr);
if (nx) FreeNode(nx); if (nx) FreeNode(nx);
return EMBB_NOMEM;
} }
bool rotation_succeeded = u->ReplaceChild(ux, nx); return result;
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;
} }
embb_errors_t W5_R( embb_errors_t W5_R(HazardNodePtr& u, HazardOperationPtr& u_op,
HazardNodePtr& u, UniqueLock& u_lock, HazardNodePtr& ux, HazardOperationPtr& ux_op,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& uxl, HazardOperationPtr& uxl_op,
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxr, HazardOperationPtr& uxr_op,
HazardNodePtr& uxr, UniqueLock& uxr_lock, HazardNodePtr& uxll, HazardOperationPtr& uxll_op) {
HazardNodePtr& uxll, UniqueLock& uxll_lock) { embb_errors_t result = EMBB_NOMEM;
Node* nxrr = node_pool_.Allocate( Node* nxrr;
uxr->GetKey(), uxr->GetValue(), Node* nxr;
uxr->GetWeight() - 1, Node* nxl;
uxr->GetLeft(), uxr->GetRight()); Node* nx;
Node* nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), while (result != EMBB_SUCCESS) {
1, nxrr = node_pool_.Allocate(
uxl->GetRight(), nxrr); uxr->GetKey(), uxr->GetValue(), uxr->GetWeight() - 1,
Node* nxl = node_pool_.Allocate( uxr->GetLeft(), uxr->GetRight(), Operation::INITIAL_DUMMY);
uxll->GetKey(), uxll->GetValue(), if (nxrr == NULL) break;
1, nxr = node_pool_.Allocate(
uxll->GetLeft(), uxll->GetRight()); ux->GetKey(), ux->GetValue(), 1,
Node* nx = node_pool_.Allocate( uxl->GetRight(), nxrr, Operation::INITIAL_DUMMY);
uxl->GetKey(), uxl->GetValue(), if (nxr == NULL) break;
ux->GetWeight(), nxl = node_pool_.Allocate(
nxl, nxr); uxll->GetKey(), uxll->GetValue(), 1,
uxll->GetLeft(), uxll->GetRight(), Operation::INITIAL_DUMMY);
if (nxrr == NULL || if (nxl == NULL) break;
nxr == NULL || nx = node_pool_.Allocate(
nxl == NULL || uxl->GetKey(), uxl->GetValue(), ux->GetWeight(),
nx == NULL) { 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 (nxrr) FreeNode(nxrr);
if (nxr) FreeNode(nxr); if (nxr) FreeNode(nxr);
if (nxl) FreeNode(nxl); if (nxl) FreeNode(nxl);
if (nx) FreeNode(nx); if (nx) FreeNode(nx);
return EMBB_NOMEM;
} }
bool rotation_succeeded = u->ReplaceChild(ux, nx); return result;
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;
} }
embb_errors_t W6_L( embb_errors_t W6_L(HazardNodePtr& u, HazardOperationPtr& u_op,
HazardNodePtr& u, UniqueLock& u_lock, HazardNodePtr& ux, HazardOperationPtr& ux_op,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& uxl, HazardOperationPtr& uxl_op,
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxr, HazardOperationPtr& uxr_op,
HazardNodePtr& uxr, UniqueLock& uxr_lock, HazardNodePtr& uxrl, HazardOperationPtr& uxrl_op) {
HazardNodePtr& uxrl, UniqueLock& uxrl_lock) { embb_errors_t result = EMBB_NOMEM;
Node* nxll = node_pool_.Allocate( Node* nxll;
uxl->GetKey(), uxl->GetValue(), Node* nxl;
uxl->GetWeight() - 1, Node* nxr;
uxl->GetLeft(), uxl->GetRight()); Node* nx;
Node* nxl = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), while (result != EMBB_SUCCESS) {
1, nxll = node_pool_.Allocate(
nxll, uxrl->GetLeft()); uxl->GetKey(), uxl->GetValue(), uxl->GetWeight() - 1,
Node* nxr = node_pool_.Allocate( uxl->GetLeft(), uxl->GetRight(), Operation::INITIAL_DUMMY);
uxr->GetKey(), uxr->GetValue(), if (nxll == NULL) break;
1, nxl = node_pool_.Allocate(
uxrl->GetRight(), uxr->GetRight()); ux->GetKey(), ux->GetValue(), 1,
Node* nx = node_pool_.Allocate( nxll, uxrl->GetLeft(), Operation::INITIAL_DUMMY);
uxrl->GetKey(), uxrl->GetValue(), if (nxl == NULL) break;
ux->GetWeight(), nxr = node_pool_.Allocate(
nxl, nxr); uxr->GetKey(), uxr->GetValue(), 1,
uxrl->GetRight(), uxr->GetRight(), Operation::INITIAL_DUMMY);
if (nxll == NULL || if (nxr == NULL) break;
nxl == NULL || nx = node_pool_.Allocate(
nxr == NULL || uxrl->GetKey(), uxrl->GetValue(), ux->GetWeight(),
nx == NULL) { 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 (nxll) FreeNode(nxll);
if (nxl) FreeNode(nxl); if (nxl) FreeNode(nxl);
if (nxr) FreeNode(nxr); if (nxr) FreeNode(nxr);
if (nx) FreeNode(nx); if (nx) FreeNode(nx);
return EMBB_NOMEM;
} }
bool rotation_succeeded = u->ReplaceChild(ux, nx); return result;
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;
} }
embb_errors_t W6_R( embb_errors_t W6_R(HazardNodePtr& u, HazardOperationPtr& u_op,
HazardNodePtr& u, UniqueLock& u_lock, HazardNodePtr& ux, HazardOperationPtr& ux_op,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& uxl, HazardOperationPtr& uxl_op,
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxr, HazardOperationPtr& uxr_op,
HazardNodePtr& uxr, UniqueLock& uxr_lock, HazardNodePtr& uxlr, HazardOperationPtr& uxlr_op) {
HazardNodePtr& uxlr, UniqueLock& uxlr_lock) { embb_errors_t result = EMBB_NOMEM;
Node* nxrr = node_pool_.Allocate( Node* nxrr;
uxr->GetKey(), uxr->GetValue(), Node* nxr;
uxr->GetWeight() - 1, Node* nxl;
uxr->GetLeft(), uxr->GetRight()); Node* nx;
Node* nxr = node_pool_.Allocate(
ux->GetKey(), ux->GetValue(), while (result != EMBB_SUCCESS) {
1, nxrr = node_pool_.Allocate(
uxlr->GetRight(), nxrr); uxr->GetKey(), uxr->GetValue(), uxr->GetWeight() - 1,
Node* nxl = node_pool_.Allocate( uxr->GetLeft(), uxr->GetRight(), Operation::INITIAL_DUMMY);
uxl->GetKey(), uxl->GetValue(), if (nxrr == NULL) break;
1, nxr = node_pool_.Allocate(
uxl->GetLeft(), uxlr->GetLeft()); ux->GetKey(), ux->GetValue(), 1,
Node* nx = node_pool_.Allocate( uxlr->GetRight(), nxrr, Operation::INITIAL_DUMMY);
uxlr->GetKey(), uxlr->GetValue(), if (nxr == NULL) break;
ux->GetWeight(), nxl = node_pool_.Allocate(
nxl, nxr); uxl->GetKey(), uxl->GetValue(), 1,
uxl->GetLeft(), uxlr->GetLeft(), Operation::INITIAL_DUMMY);
if (nxrr == NULL || if (nxl == NULL) break;
nxr == NULL || nx = node_pool_.Allocate(
nxl == NULL || uxlr->GetKey(), uxlr->GetValue(), ux->GetWeight(),
nx == NULL) { 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 (nxrr) FreeNode(nxrr);
if (nxr) FreeNode(nxr); if (nxr) FreeNode(nxr);
if (nxl) FreeNode(nxl); if (nxl) FreeNode(nxl);
if (nx) FreeNode(nx); if (nx) FreeNode(nx);
return EMBB_NOMEM;
} }
bool rotation_succeeded = u->ReplaceChild(ux, nx); return result;
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;
} }
embb_errors_t W7( embb_errors_t W7(HazardNodePtr& u, HazardOperationPtr& u_op,
HazardNodePtr& u, UniqueLock& u_lock, HazardNodePtr& ux, HazardOperationPtr& ux_op,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& uxl, HazardOperationPtr& uxl_op,
HazardNodePtr& uxl, UniqueLock& uxl_lock, HazardNodePtr& uxr, HazardOperationPtr& uxr_op) {
HazardNodePtr& uxr, UniqueLock& uxr_lock) { embb_errors_t result = EMBB_NOMEM;
Node* nxl = node_pool_.Allocate( Node* nxl;
uxl->GetKey(), uxl->GetValue(), Node* nxr;
uxl->GetWeight() - 1, Node* nx;
uxl->GetLeft(), uxl->GetRight());
Node* nxr = node_pool_.Allocate( while (result != EMBB_SUCCESS) {
uxr->GetKey(), uxr->GetValue(), nxl = node_pool_.Allocate(
uxr->GetWeight() - 1, uxl->GetKey(), uxl->GetValue(), uxl->GetWeight() - 1,
uxr->GetLeft(), uxr->GetRight()); uxl->GetLeft(), uxl->GetRight(), Operation::INITIAL_DUMMY);
Node* nx = node_pool_.Allocate( if (nxl == NULL) break;
ux->GetKey(), ux->GetValue(), nxr = node_pool_.Allocate(
IsSentinel(u) ? 1 : ux->GetWeight() + 1, uxr->GetKey(), uxr->GetValue(), uxr->GetWeight() - 1,
nxl, nxr); uxr->GetLeft(), uxr->GetRight(), Operation::INITIAL_DUMMY);
if (nxr == NULL) break;
if (nxl == NULL || nx = node_pool_.Allocate(
nxr == NULL || ux->GetKey(), ux->GetValue(), IsSentinel(u) ? 1 : ux->GetWeight() + 1,
nx == NULL) { 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 (nxl) FreeNode(nxl);
if (nxr) FreeNode(nxr); if (nxr) FreeNode(nxr);
if (nx) FreeNode(nx); if (nx) FreeNode(nx);
return EMBB_NOMEM;
} }
bool rotation_succeeded = u->ReplaceChild(ux, nx); return result;
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;
} }
#endif // EMBB_CONTAINERS_INTERNAL_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_ #endif // EMBB_CONTAINERS_INTERNAL_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_
...@@ -201,10 +201,19 @@ class ChromaticTreeOperation { ...@@ -201,10 +201,19 @@ class ChromaticTreeOperation {
root_operation_ = root_operation; root_operation_ = root_operation;
} }
void SetOldNodes(Node* node, Operation* operation) { void SetOldNodes(Node* node1, Operation* operation1) {
num_old_nodes_ = 1; num_old_nodes_ = 1;
old_nodes_[0] = node; old_nodes_[0] = node1;
old_operations_[0] = operation; 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, void SetOldNodes(Node* node1, Operation* operation1,
...@@ -219,6 +228,39 @@ class ChromaticTreeOperation { ...@@ -219,6 +228,39 @@ class ChromaticTreeOperation {
old_operations_[2] = operation3; 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) { void SetNewChild(Node* new_child) {
new_child_ = new_child; new_child_ = new_child;
} }
...@@ -639,8 +681,6 @@ class ChromaticTree { ...@@ -639,8 +681,6 @@ class ChromaticTree {
typedef embb::base::Atomic<Operation*> AtomicOperationPtr; typedef embb::base::Atomic<Operation*> AtomicOperationPtr;
/** Typedef for an pointer to a node protected by a Hazard Pointer. */ /** Typedef for an pointer to a node protected by a Hazard Pointer. */
typedef internal::UniqueHazardPointer<Operation> HazardOperationPtr; 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 for an object pool for tree nodes. */
typedef ObjectPool<Node, ValuePool> NodePool; typedef ObjectPool<Node, ValuePool> NodePool;
/** Typedef for an object pool for tree operations. */ /** Typedef for an object pool for tree operations. */
...@@ -648,11 +688,33 @@ class ChromaticTree { ...@@ -648,11 +688,33 @@ class ChromaticTree {
typedef enum { typedef enum {
HIDX_HELPING = 0, HIDX_HELPING = 0,
HIDX_LEAF, // Common shared nodes
HIDX_PARENT, HIDX_GRANDGRANDPARENT,
HIDX_GRANDPARENT, HIDX_GRANDPARENT,
HIDX_SIBLING, HIDX_PARENT,
HIDX_CURRENT_OP, 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 HIDX_MAX
} HazardIndex; } HazardIndex;
...@@ -773,19 +835,19 @@ class ChromaticTree { ...@@ -773,19 +835,19 @@ class ChromaticTree {
embb_errors_t Rebalance(HazardNodePtr& u, HazardNodePtr& ux, embb_errors_t Rebalance(HazardNodePtr& u, HazardNodePtr& ux,
HazardNodePtr& uxx, HazardNodePtr& uxxx); HazardNodePtr& uxx, HazardNodePtr& uxxx);
embb_errors_t OverweightLeft(HazardNodePtr& u, UniqueLock& u_lock, embb_errors_t OverweightLeft(HazardNodePtr& u, HazardOperationPtr& u_op,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& ux, HazardOperationPtr& ux_op,
HazardNodePtr& uxx, UniqueLock& uxx_lock, HazardNodePtr& uxx, HazardOperationPtr& uxx_op,
HazardNodePtr& uxl, HazardNodePtr& uxr, HazardNodePtr& uxl, HazardNodePtr& uxr,
HazardNodePtr& uxxl, UniqueLock& uxxl_lock, HazardNodePtr& uxxl, HazardOperationPtr& uxxl_op,
HazardNodePtr& uxxr, bool uxx_is_left); HazardNodePtr& uxxr, bool uxx_is_left);
embb_errors_t OverweightRight(HazardNodePtr& u, UniqueLock& u_lock, embb_errors_t OverweightRight(HazardNodePtr& u, HazardOperationPtr& u_op,
HazardNodePtr& ux, UniqueLock& ux_lock, HazardNodePtr& ux, HazardOperationPtr& ux_op,
HazardNodePtr& uxx, UniqueLock& uxx_lock, HazardNodePtr& uxx, HazardOperationPtr& uxx_op,
HazardNodePtr& uxl, HazardNodePtr& uxr, HazardNodePtr& uxl, HazardNodePtr& uxr,
HazardNodePtr& uxxl, HazardNodePtr& uxxr, 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 // The following included header contains the class methods implementing
// tree rotations. It is generated automatically and must be included // tree rotations. It is generated automatically and must be included
......
...@@ -66,11 +66,11 @@ TreeTest<Tree>::TreeTest() ...@@ -66,11 +66,11 @@ TreeTest<Tree>::TreeTest()
Add(&TreeTest::TreeTestConcurrentGet_ReaderMethod, this, Add(&TreeTest::TreeTestConcurrentGet_ReaderMethod, this,
NUM_TEST_THREADS / 2, NUM_ITERATIONS). NUM_TEST_THREADS / 2, NUM_ITERATIONS).
Post(&TreeTest::TreeTestConcurrentGet_Post, this); Post(&TreeTest::TreeTestConcurrentGet_Post, this);
// CreateUnit("TreeTestBalance"). CreateUnit("TreeTestBalance").
// Pre(&TreeTest::TreeTestBalance_Pre, this). Pre(&TreeTest::TreeTestBalance_Pre, this).
// Add(&TreeTest::TreeTestBalance_ThreadMethod, this, Add(&TreeTest::TreeTestBalance_ThreadMethod, this,
// NUM_TEST_THREADS, 1). NUM_TEST_THREADS, 1).
// Post(&TreeTest::TreeTestBalance_Post, this); Post(&TreeTest::TreeTestBalance_Post, this);
} }
template<typename Tree> 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