Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
FORMUS3IC_LAS3
/
embb
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
35ab98de
authored
Jun 15, 2015
by
Danila Klimenko
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chromatic_tree: lock-free implementation (with rebalancing)
parent
34f6e4f3
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
1401 additions
and
895 deletions
+1401
-895
containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-inl.h
+164
-154
containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-rebalance.h
+1153
-719
containers_cpp/include/embb/containers/lock_free_chromatic_tree.h
+79
-17
containers_cpp/test/tree_test-inl.h
+5
-5
No files found.
containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-inl.h
View file @
35ab98de
...
@@ -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_L
OCK(node, lock
_name) \
#define PROTECT_NODE_WITH_L
LX(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_L
OCK
(
u
,
u_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
ux
,
ux_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxx
,
uxx_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxxl
,
uxxl_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxxr
,
uxxr_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxr
,
uxr_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxxr
,
uxxr_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxl
,
uxl_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxxl
,
uxxl_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxr
,
uxr_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxxr
,
uxxr_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxl
,
uxl_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxxr
,
uxxr_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxxrl
,
uxxrl_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxxrlr
,
uxxrlr_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxxrll
,
uxxrll_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxxr
,
uxxr_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxxrr
,
uxxrr_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxxrl
,
uxxrl_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxxr
,
uxxr_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxl
,
uxl_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxxl
,
uxxl_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxr
,
uxr_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxxl
,
uxxl_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxxlr
,
uxxlr_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxxlrl
,
uxxlrl_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxxlrr
,
uxxlrr_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxxl
,
uxxl_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxxll
,
uxxll_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxxlr
,
uxxlr_lock
);
PROTECT_NODE_WITH_L
LX
(
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_L
OCK
(
uxxl
,
uxxl_lock
);
PROTECT_NODE_WITH_L
LX
(
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
);
}
}
}
}
...
...
containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-rebalance.h
View file @
35ab98de
...
@@ -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
);
embb_errors_t
PUSH_L
(
HazardNodePtr
&
u
,
HazardOperationPtr
&
u_op
,
RetireHazardousNode
(
uxl
,
uxl_lock
);
HazardNodePtr
&
ux
,
HazardOperationPtr
&
ux_op
,
RetireHazardousNode
(
uxr
,
uxr_lock
);
HazardNodePtr
&
uxl
,
HazardOperationPtr
&
uxl_op
,
(
void
)
u_lock
;
// For now (FGL tree) u_lock is not used here
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
;
}
return
EMBB_SUCCESS
;
RetireOperation
(
u_op
);
}
RetireNode
(
ux
);
RetireOperation
(
ux_op
);
RetireNode
(
uxl
);
RetireOperation
(
uxl_op
);
RetireNode
(
uxr
);
RetireOperation
(
uxr_op
);
result
=
EMBB_SUCCESS
;
}
embb_errors_t
PUSH_L
(
if
(
result
!=
EMBB_SUCCESS
)
{
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
)
{
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
);
embb_errors_t
PUSH_R
(
HazardNodePtr
&
u
,
HazardOperationPtr
&
u_op
,
RetireHazardousNode
(
uxl
,
uxl_lock
);
HazardNodePtr
&
ux
,
HazardOperationPtr
&
ux_op
,
RetireHazardousNode
(
uxr
,
uxr_lock
);
HazardNodePtr
&
uxl
,
HazardOperationPtr
&
uxl_op
,
(
void
)
u_lock
;
// For now (FGL tree) u_lock is not used here
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
;
}
return
EMBB_SUCCESS
;
RetireOperation
(
u_op
);
}
RetireNode
(
ux
);
RetireOperation
(
ux_op
);
RetireNode
(
uxl
);
RetireOperation
(
uxl_op
);
RetireNode
(
uxr
);
RetireOperation
(
uxr_op
);
embb_errors_t
PUSH_R
(
result
=
EMBB_SUCCESS
;
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
}
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
,
if
(
result
!=
EMBB_SUCCESS
)
{
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
)
{
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
);
embb_errors_t
RB1_L
(
HazardNodePtr
&
u
,
HazardOperationPtr
&
u_op
,
RetireHazardousNode
(
uxl
,
uxl_lock
);
HazardNodePtr
&
ux
,
HazardOperationPtr
&
ux_op
,
RetireHazardousNode
(
uxr
,
uxr_lock
);
HazardNodePtr
&
uxl
,
HazardOperationPtr
&
uxl_op
)
{
(
void
)
u_lock
;
// For now (FGL tree) u_lock is not used here
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
;
}
return
EMBB_SUCCESS
;
RetireOperation
(
u_op
);
}
RetireNode
(
ux
);
RetireOperation
(
ux_op
);
RetireNode
(
uxl
);
RetireOperation
(
uxl_op
);
result
=
EMBB_SUCCESS
;
}
embb_errors_t
RB1_L
(
if
(
result
!=
EMBB_SUCCESS
)
{
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
)
{
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
);
embb_errors_t
RB1_R
(
HazardNodePtr
&
u
,
HazardOperationPtr
&
u_op
,
RetireHazardousNode
(
uxl
,
uxl_lock
);
HazardNodePtr
&
ux
,
HazardOperationPtr
&
ux_op
,
(
void
)
u_lock
;
// For now (FGL tree) u_lock is not used here
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
;
}
return
EMBB_SUCCESS
;
RetireOperation
(
u_op
);
}
RetireNode
(
ux
);
RetireOperation
(
ux_op
);
RetireNode
(
uxr
);
RetireOperation
(
uxr_op
);
embb_errors_t
RB1_R
(
result
=
EMBB_SUCCESS
;
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
}
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
HazardNodePtr
&
uxr
,
UniqueLock
&
uxr_lock
)
{
if
(
result
!=
EMBB_SUCCESS
)
{
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
)
{
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
);
embb_errors_t
RB2_L
(
HazardNodePtr
&
u
,
HazardOperationPtr
&
u_op
,
RetireHazardousNode
(
uxr
,
uxr_lock
);
HazardNodePtr
&
ux
,
HazardOperationPtr
&
ux_op
,
(
void
)
u_lock
;
// For now (FGL tree) u_lock is not used here
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
;
}
return
EMBB_SUCCESS
;
RetireOperation
(
u_op
);
}
RetireNode
(
ux
);
RetireOperation
(
ux_op
);
RetireNode
(
uxl
);
RetireOperation
(
uxl_op
);
RetireNode
(
uxlr
);
RetireOperation
(
uxlr_op
);
result
=
EMBB_SUCCESS
;
}
embb_errors_t
RB2_L
(
if
(
result
!=
EMBB_SUCCESS
)
{
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
)
{
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
);
embb_errors_t
RB2_R
(
HazardNodePtr
&
u
,
HazardOperationPtr
&
u_op
,
RetireHazardousNode
(
uxl
,
uxl_lock
);
HazardNodePtr
&
ux
,
HazardOperationPtr
&
ux_op
,
RetireHazardousNode
(
uxlr
,
uxlr_lock
);
HazardNodePtr
&
uxr
,
HazardOperationPtr
&
uxr_op
,
(
void
)
u_lock
;
// For now (FGL tree) u_lock is not used here
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
;
}
return
EMBB_SUCCESS
;
RetireOperation
(
u_op
);
}
RetireNode
(
ux
);
RetireOperation
(
ux_op
);
RetireNode
(
uxr
);
RetireOperation
(
uxr_op
);
RetireNode
(
uxrl
);
RetireOperation
(
uxrl_op
);
embb_errors_t
RB2_R
(
result
=
EMBB_SUCCESS
;
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
}
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
HazardNodePtr
&
uxr
,
UniqueLock
&
uxr_lock
,
if
(
result
!=
EMBB_SUCCESS
)
{
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
)
{
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
);
embb_errors_t
W1_L
(
HazardNodePtr
&
u
,
HazardOperationPtr
&
u_op
,
RetireHazardousNode
(
uxr
,
uxr_lock
);
HazardNodePtr
&
ux
,
HazardOperationPtr
&
ux_op
,
RetireHazardousNode
(
uxrl
,
uxrl_lock
);
HazardNodePtr
&
uxl
,
HazardOperationPtr
&
uxl_op
,
(
void
)
u_lock
;
// For now (FGL tree) u_lock is not used here
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
;
}
return
EMBB_SUCCESS
;
RetireOperation
(
u_op
);
}
RetireNode
(
ux
);
RetireOperation
(
ux_op
);
RetireNode
(
uxl
);
RetireOperation
(
uxl_op
);
RetireNode
(
uxr
);
RetireOperation
(
uxr_op
);
RetireNode
(
uxrl
);
RetireOperation
(
uxrl_op
);
embb_errors_t
W1_L
(
result
=
EMBB_SUCCESS
;
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
}
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
,
if
(
result
!=
EMBB_SUCCESS
)
{
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
)
{
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
;
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
;
}
RetireHazardousNode
(
ux
,
ux_lock
);
RetireOperation
(
u_op
);
RetireHazardousNode
(
uxl
,
uxl_lock
);
RetireNode
(
ux
);
RetireOperation
(
ux_op
);
RetireHazardousNode
(
uxr
,
uxr_lock
);
RetireNode
(
uxl
);
RetireOperation
(
uxl_op
);
RetireHazardousNode
(
uxrl
,
uxrl_lock
);
RetireNode
(
uxr
);
RetireOperation
(
uxr_op
);
(
void
)
u_lock
;
// For now (FGL tree) u_lock is not used here
RetireNode
(
uxlr
);
RetireOperation
(
uxlr_op
);
return
EMBB_SUCCESS
;
result
=
EMBB_SUCCESS
;
}
}
embb_errors_t
W1_R
(
if
(
result
!=
EMBB_SUCCESS
)
{
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
)
{
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
);
embb_errors_t
W2_L
(
HazardNodePtr
&
u
,
HazardOperationPtr
&
u_op
,
RetireHazardousNode
(
uxl
,
uxl_lock
);
HazardNodePtr
&
ux
,
HazardOperationPtr
&
ux_op
,
RetireHazardousNode
(
uxr
,
uxr_lock
);
HazardNodePtr
&
uxl
,
HazardOperationPtr
&
uxl_op
,
RetireHazardousNode
(
uxlr
,
uxlr_lock
);
HazardNodePtr
&
uxr
,
HazardOperationPtr
&
uxr_op
,
(
void
)
u_lock
;
// For now (FGL tree) u_lock is not used here
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
;
}
return
EMBB_SUCCESS
;
RetireOperation
(
u_op
);
}
RetireNode
(
ux
);
RetireOperation
(
ux_op
);
RetireNode
(
uxl
);
RetireOperation
(
uxl_op
);
RetireNode
(
uxr
);
RetireOperation
(
uxr_op
);
RetireNode
(
uxrl
);
RetireOperation
(
uxrl_op
);
embb_errors_t
W2_L
(
result
=
EMBB_SUCCESS
;
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
}
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
,
if
(
result
!=
EMBB_SUCCESS
)
{
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
)
{
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
;
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
;
}
RetireHazardousNode
(
ux
,
ux_lock
);
RetireOperation
(
u_op
);
RetireHazardousNode
(
uxl
,
uxl_lock
);
RetireNode
(
ux
);
RetireOperation
(
ux_op
);
RetireHazardousNode
(
uxr
,
uxr_lock
);
RetireNode
(
uxl
);
RetireOperation
(
uxl_op
);
RetireHazardousNode
(
uxrl
,
uxrl_lock
);
RetireNode
(
uxr
);
RetireOperation
(
uxr_op
);
(
void
)
u_lock
;
// For now (FGL tree) u_lock is not used here
RetireNode
(
uxlr
);
RetireOperation
(
uxlr_op
);
return
EMBB_SUCCESS
;
result
=
EMBB_SUCCESS
;
}
}
embb_errors_t
W2_R
(
if
(
result
!=
EMBB_SUCCESS
)
{
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
)
{
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
);
embb_errors_t
W3_L
(
HazardNodePtr
&
u
,
HazardOperationPtr
&
u_op
,
RetireHazardousNode
(
uxl
,
uxl_lock
);
HazardNodePtr
&
ux
,
HazardOperationPtr
&
ux_op
,
RetireHazardousNode
(
uxr
,
uxr_lock
);
HazardNodePtr
&
uxl
,
HazardOperationPtr
&
uxl_op
,
RetireHazardousNode
(
uxlr
,
uxlr_lock
);
HazardNodePtr
&
uxr
,
HazardOperationPtr
&
uxr_op
,
(
void
)
u_lock
;
// For now (FGL tree) u_lock is not used here
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
;
}
return
EMBB_SUCCESS
;
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
);
embb_errors_t
W3_L
(
result
=
EMBB_SUCCESS
;
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
}
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
,
if
(
result
!=
EMBB_SUCCESS
)
{
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
)
{
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
;
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
;
}
RetireHazardousNode
(
ux
,
ux_lock
);
RetireOperation
(
u_op
);
RetireHazardousNode
(
uxl
,
uxl_lock
);
RetireNode
(
ux
);
RetireOperation
(
ux_op
);
RetireHazardousNode
(
uxr
,
uxr_lock
);
RetireNode
(
uxl
);
RetireOperation
(
uxl_op
);
RetireHazardousNode
(
uxrl
,
uxrl_lock
);
RetireNode
(
uxr
);
RetireOperation
(
uxr_op
);
RetireHazardousNode
(
uxrll
,
uxrll_lock
);
RetireNode
(
uxlr
);
RetireOperation
(
uxlr_op
);
(
void
)
u_lock
;
// For now (FGL tree) u_lock is not used here
RetireNode
(
uxlrr
);
RetireOperation
(
uxlrr_op
);
return
EMBB_SUCCESS
;
result
=
EMBB_SUCCESS
;
}
}
embb_errors_t
W3_R
(
if
(
result
!=
EMBB_SUCCESS
)
{
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
)
{
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
);
embb_errors_t
W4_L
(
HazardNodePtr
&
u
,
HazardOperationPtr
&
u_op
,
RetireHazardousNode
(
uxl
,
uxl_lock
);
HazardNodePtr
&
ux
,
HazardOperationPtr
&
ux_op
,
RetireHazardousNode
(
uxr
,
uxr_lock
);
HazardNodePtr
&
uxl
,
HazardOperationPtr
&
uxl_op
,
RetireHazardousNode
(
uxlr
,
uxlr_lock
);
HazardNodePtr
&
uxr
,
HazardOperationPtr
&
uxr_op
,
RetireHazardousNode
(
uxlrr
,
uxlrr_lock
);
HazardNodePtr
&
uxrl
,
HazardOperationPtr
&
uxrl_op
,
(
void
)
u_lock
;
// For now (FGL tree) u_lock is not used here
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
;
}
return
EMBB_SUCCESS
;
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
);
embb_errors_t
W4_L
(
result
=
EMBB_SUCCESS
;
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
}
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
,
if
(
result
!=
EMBB_SUCCESS
)
{
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
)
{
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
);
embb_errors_t
W4_R
(
HazardNodePtr
&
u
,
HazardOperationPtr
&
u_op
,
RetireHazardousNode
(
uxl
,
uxl_lock
);
HazardNodePtr
&
ux
,
HazardOperationPtr
&
ux_op
,
RetireHazardousNode
(
uxr
,
uxr_lock
);
HazardNodePtr
&
uxl
,
HazardOperationPtr
&
uxl_op
,
RetireHazardousNode
(
uxrl
,
uxrl_lock
);
HazardNodePtr
&
uxr
,
HazardOperationPtr
&
uxr_op
,
RetireHazardousNode
(
uxrlr
,
uxrlr_lock
);
HazardNodePtr
&
uxlr
,
HazardOperationPtr
&
uxlr_op
,
(
void
)
u_lock
;
// For now (FGL tree) u_lock is not used here
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
;
}
return
EMBB_SUCCESS
;
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
;
}
embb_errors_t
W4_R
(
if
(
result
!=
EMBB_SUCCESS
)
{
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
)
{
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
);
embb_errors_t
W5_L
(
HazardNodePtr
&
u
,
HazardOperationPtr
&
u_op
,
RetireHazardousNode
(
uxl
,
uxl_lock
);
HazardNodePtr
&
ux
,
HazardOperationPtr
&
ux_op
,
RetireHazardousNode
(
uxr
,
uxr_lock
);
HazardNodePtr
&
uxl
,
HazardOperationPtr
&
uxl_op
,
RetireHazardousNode
(
uxlr
,
uxlr_lock
);
HazardNodePtr
&
uxr
,
HazardOperationPtr
&
uxr_op
,
RetireHazardousNode
(
uxlrl
,
uxlrl_lock
);
HazardNodePtr
&
uxrr
,
HazardOperationPtr
&
uxrr_op
)
{
(
void
)
u_lock
;
// For now (FGL tree) u_lock is not used here
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
;
}
return
EMBB_SUCCESS
;
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
;
}
embb_errors_t
W5_L
(
if
(
result
!=
EMBB_SUCCESS
)
{
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
)
{
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
);
embb_errors_t
W5_R
(
HazardNodePtr
&
u
,
HazardOperationPtr
&
u_op
,
RetireHazardousNode
(
uxl
,
uxl_lock
);
HazardNodePtr
&
ux
,
HazardOperationPtr
&
ux_op
,
RetireHazardousNode
(
uxr
,
uxr_lock
);
HazardNodePtr
&
uxl
,
HazardOperationPtr
&
uxl_op
,
RetireHazardousNode
(
uxrr
,
uxrr_lock
);
HazardNodePtr
&
uxr
,
HazardOperationPtr
&
uxr_op
,
(
void
)
u_lock
;
// For now (FGL tree) u_lock is not used here
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
;
}
return
EMBB_SUCCESS
;
RetireOperation
(
u_op
);
}
RetireNode
(
ux
);
RetireOperation
(
ux_op
);
RetireNode
(
uxl
);
RetireOperation
(
uxl_op
);
RetireNode
(
uxr
);
RetireOperation
(
uxr_op
);
RetireNode
(
uxll
);
RetireOperation
(
uxll_op
);
embb_errors_t
W5_R
(
result
=
EMBB_SUCCESS
;
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
}
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
,
if
(
result
!=
EMBB_SUCCESS
)
{
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
)
{
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
;
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
;
}
RetireHazardousNode
(
ux
,
ux_lock
);
RetireOperation
(
u_op
);
RetireHazardousNode
(
uxl
,
uxl_lock
);
RetireNode
(
ux
);
RetireOperation
(
ux_op
);
RetireHazardousNode
(
uxr
,
uxr_lock
);
RetireNode
(
uxl
);
RetireOperation
(
uxl_op
);
RetireHazardousNode
(
uxll
,
uxll_lock
);
RetireNode
(
uxr
);
RetireOperation
(
uxr_op
);
(
void
)
u_lock
;
// For now (FGL tree) u_lock is not used here
RetireNode
(
uxrl
);
RetireOperation
(
uxrl_op
);
return
EMBB_SUCCESS
;
result
=
EMBB_SUCCESS
;
}
}
embb_errors_t
W6_L
(
if
(
result
!=
EMBB_SUCCESS
)
{
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
)
{
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
);
embb_errors_t
W6_R
(
HazardNodePtr
&
u
,
HazardOperationPtr
&
u_op
,
RetireHazardousNode
(
uxl
,
uxl_lock
);
HazardNodePtr
&
ux
,
HazardOperationPtr
&
ux_op
,
RetireHazardousNode
(
uxr
,
uxr_lock
);
HazardNodePtr
&
uxl
,
HazardOperationPtr
&
uxl_op
,
RetireHazardousNode
(
uxrl
,
uxrl_lock
);
HazardNodePtr
&
uxr
,
HazardOperationPtr
&
uxr_op
,
(
void
)
u_lock
;
// For now (FGL tree) u_lock is not used here
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
;
}
return
EMBB_SUCCESS
;
RetireOperation
(
u_op
);
}
RetireNode
(
ux
);
RetireOperation
(
ux_op
);
RetireNode
(
uxl
);
RetireOperation
(
uxl_op
);
RetireNode
(
uxr
);
RetireOperation
(
uxr_op
);
RetireNode
(
uxlr
);
RetireOperation
(
uxlr_op
);
embb_errors_t
W6_R
(
result
=
EMBB_SUCCESS
;
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
}
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
,
if
(
result
!=
EMBB_SUCCESS
)
{
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
)
{
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
;
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
;
}
RetireHazardousNode
(
ux
,
ux_lock
);
RetireOperation
(
u_op
);
RetireHazardousNode
(
uxl
,
uxl_lock
);
RetireNode
(
ux
);
RetireOperation
(
ux_op
);
RetireHazardousNode
(
uxr
,
uxr_lock
);
RetireNode
(
uxl
);
RetireOperation
(
uxl_op
);
RetireHazardousNode
(
uxlr
,
uxlr_lock
);
RetireNode
(
uxr
);
RetireOperation
(
uxr_op
);
(
void
)
u_lock
;
// For now (FGL tree) u_lock is not used here
return
EMBB_SUCCESS
;
result
=
EMBB_SUCCESS
;
}
}
embb_errors_t
W7
(
if
(
result
!=
EMBB_SUCCESS
)
{
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
)
{
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_
containers_cpp/include/embb/containers/lock_free_chromatic_tree.h
View file @
35ab98de
...
@@ -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
*
node
1
,
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_
GRANDGRAND
PARENT
,
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
...
...
containers_cpp/test/tree_test-inl.h
View file @
35ab98de
...
@@ -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
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment