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