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
2f75565c
authored
May 12, 2015
by
Danila Klimenko
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chromatic_tree: Fine-grained locking implementation (complete with rebalancing)
parent
871b5391
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
812 additions
and
563 deletions
+812
-563
containers_cpp/include/embb/containers/internal/hazard_pointer-inl.h
+9
-1
containers_cpp/include/embb/containers/internal/hazard_pointer.h
+8
-1
containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-inl.h
+287
-224
containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-rebalance.h
+406
-306
containers_cpp/include/embb/containers/lock_free_chromatic_tree.h
+97
-26
containers_cpp/test/tree_test-inl.h
+5
-5
No files found.
containers_cpp/include/embb/containers/internal/hazard_pointer-inl.h
View file @
2f75565c
...
...
@@ -182,7 +182,9 @@ HazardPointerThreadEntry<GuardType>::~HazardPointerThreadEntry() {
}
template
<
typename
GuardType
>
GuardType
HazardPointerThreadEntry
<
GuardType
>::
GetGuard
(
int
pos
)
const
{
typename
HazardPointerThreadEntry
<
GuardType
>::
AtomicGuard
&
HazardPointerThreadEntry
<
GuardType
>::
GetGuard
(
int
pos
)
const
{
assert
(
pos
>=
0
&&
pos
<
guards_per_thread
);
return
guarded_pointers
[
pos
];
}
...
...
@@ -393,6 +395,12 @@ void HazardPointer< GuardType >::GuardPointer(int guardPosition,
}
template
<
typename
GuardType
>
typename
HazardPointer
<
GuardType
>::
AtomicGuard
&
HazardPointer
<
GuardType
>::
GetGuardedPointer
(
int
guardPosition
)
{
return
GetHazardPointerElementForCurrentThread
().
GetGuard
(
guardPosition
);
}
template
<
typename
GuardType
>
void
HazardPointer
<
GuardType
>::
EnqueuePointerForDeletion
(
GuardType
guardedElement
)
{
GetHazardPointerElementForCurrentThread
().
AddRetired
(
guardedElement
);
...
...
containers_cpp/include/embb/containers/internal/hazard_pointer.h
View file @
2f75565c
...
...
@@ -238,6 +238,8 @@ class HazardPointerThreadEntry {
HazardPointerThreadEntry
&
operator
=
(
const
HazardPointerThreadEntry
&
);
public
:
typedef
embb
::
base
::
Atomic
<
GuardType
>
AtomicGuard
;
/**
* Checks if current thread is active (with respect to participating in hazard
* pointer management)
...
...
@@ -318,7 +320,7 @@ class HazardPointerThreadEntry {
* Gets the guard at the specified position.
* Positions are numbered, beginning with 0.
*/
GuardType
GetGuard
(
AtomicGuard
&
GetGuard
(
int
pos
/**< [IN] Position of the guard */
)
const
;
...
...
@@ -467,6 +469,8 @@ class HazardPointer {
can be deleted*/
);
public
:
typedef
typename
HazardPointerThreadEntry_t
::
AtomicGuard
AtomicGuard
;
/**
* Gets the capacity of one retired list
*
...
...
@@ -516,6 +520,9 @@ class HazardPointer {
* Guards \c guardedElement with the guard at position \c guardPosition
*/
void
GuardPointer
(
int
guardPosition
,
GuardType
guardedElement
);
AtomicGuard
&
GetGuardedPointer
(
int
guardPosition
);
/**
* Enqueue a pointer for deletion. It is added to the retired list and
* deleted when no thread accesses it anymore.
...
...
containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-inl.h
View file @
2f75565c
...
...
@@ -105,7 +105,7 @@ ChromaticTree(size_t capacity, Key undefined_key, Value undefined_value,
#ifdef EMBB_PLATFORM_COMPILER_MSVC
#pragma warning(pop)
#endif
node_hazard_manager_
(
free_node_callback_
,
NULL
,
8
),
node_hazard_manager_
(
free_node_callback_
,
NULL
,
10
),
undefined_key_
(
undefined_key
),
undefined_value_
(
undefined_value
),
compare_
(
compare
),
...
...
@@ -128,8 +128,9 @@ ChromaticTree<Key, Value, Compare, NodePool>::
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
bool
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
Get
(
const
Key
&
key
,
Value
&
value
)
{
NodePtr
leaf
;
Search
(
key
,
leaf
);
HazardNodePtr
parent
(
node_hazard_manager_
.
GetGuardedPointer
(
0
),
NULL
);
HazardNodePtr
leaf
(
node_hazard_manager_
.
GetGuardedPointer
(
1
),
NULL
);
Search
(
key
,
leaf
,
parent
);
bool
keys_are_equal
=
!
IsSentinel
(
leaf
)
&&
!
(
compare_
(
key
,
leaf
->
GetKey
())
||
...
...
@@ -139,8 +140,6 @@ Get(const Key& key, Value& value) {
value
=
leaf
->
GetValue
();
}
node_hazard_manager_
.
GuardPointer
(
0
,
NULL
);
return
keys_are_equal
;
}
...
...
@@ -158,9 +157,11 @@ TryInsert(const Key& key, const Value& value, Value& old_value) {
NodePtr
new_sibling
=
NULL
;
NodePtr
new_parent
=
NULL
;
bool
insertion_succeeded
=
false
;
bool
added_violation
=
false
;
while
(
!
insertion_succeeded
)
{
NodePtr
leaf
,
parent
;
HazardNodePtr
parent
(
node_hazard_manager_
.
GetGuardedPointer
(
0
),
NULL
);
HazardNodePtr
leaf
(
node_hazard_manager_
.
GetGuardedPointer
(
1
),
NULL
);
Search
(
key
,
leaf
,
parent
);
// Try to lock the parent
...
...
@@ -200,23 +201,21 @@ TryInsert(const Key& key, const Value& value, Value& old_value) {
if
(
new_parent
==
NULL
)
break
;
}
GetPointerToChild
(
parent
,
leaf
).
CompareAndSwap
(
leaf
,
new_parent
);
insertion_succeeded
=
true
;
NodePtr
expected
=
leaf
;
insertion_succeeded
=
GetPointerToChild
(
parent
,
leaf
)
.
CompareAndSwap
(
expected
,
new_parent
);
assert
(
insertion_succeeded
);
// For now (FGL tree) this CAS may not fail
if
(
!
insertion_succeeded
)
continue
;
leaf
->
Retire
();
leaf_lock
.
Unlock
();
node_hazard_manager_
.
GuardPointer
(
1
,
NULL
);
RemoveNode
(
leaf
);
RetireHazardousNode
(
leaf
,
leaf_lock
);
// if (parent->GetWeight() == 0 && new_parent->GetWeight() == 0) {
// CleanUp(key);
// }
added_violation
=
(
parent
->
GetWeight
()
==
0
&&
new_parent
->
GetWeight
()
==
0
);
}
node_hazard_manager_
.
GuardPointer
(
0
,
NULL
);
node_hazard_manager_
.
GuardPointer
(
1
,
NULL
);
if
(
!
insertion_succeeded
)
{
if
(
insertion_succeeded
)
{
if
(
added_violation
)
CleanUp
(
key
);
}
else
{
if
(
new_leaf
!=
NULL
)
FreeNode
(
new_leaf
);
if
(
new_sibling
!=
NULL
)
FreeNode
(
new_sibling
);
if
(
new_parent
!=
NULL
)
FreeNode
(
new_parent
);
...
...
@@ -237,9 +236,12 @@ bool ChromaticTree<Key, Value, Compare, NodePool>::
TryDelete
(
const
Key
&
key
,
Value
&
old_value
)
{
NodePtr
new_leaf
=
NULL
;
bool
deletion_succeeded
=
false
;
bool
added_violation
=
false
;
while
(
!
deletion_succeeded
)
{
NodePtr
leaf
,
parent
,
grandparent
;
HazardNodePtr
grandparent
(
node_hazard_manager_
.
GetGuardedPointer
(
0
),
NULL
);
HazardNodePtr
parent
(
node_hazard_manager_
.
GetGuardedPointer
(
1
),
NULL
);
HazardNodePtr
leaf
(
node_hazard_manager_
.
GetGuardedPointer
(
2
),
NULL
);
Search
(
key
,
leaf
,
parent
,
grandparent
);
// Reached leaf has a different key - nothing to delete
...
...
@@ -259,16 +261,17 @@ TryDelete(const Key& key, Value& old_value) {
// Try to lock the parent
UniqueLock
parent_lock
(
parent
->
GetMutex
(),
embb
::
base
::
try_lock
);
if
(
!
parent_lock
.
OwnsLock
()
||
parent
->
IsRetired
())
continue
;
// Get the sibling (and protect it with hazard pointer)
HazardNodePtr
sibling
(
node_hazard_manager_
.
GetGuardedPointer
(
3
),
NULL
);
sibling
.
ProtectHazard
((
parent
->
GetLeft
()
==
leaf
)
?
parent
->
GetRight
()
:
parent
->
GetLeft
());
if
(
parent
->
IsRetired
()
||
!
sibling
.
IsActive
())
continue
;
VERIFY_ADDRESS
(
static_cast
<
NodePtr
>
(
sibling
));
// Verify that the leaf is still the parent's child
if
(
!
HasChild
(
parent
,
leaf
))
continue
;
AtomicNodePtr
&
other_child
=
((
parent
->
GetLeft
()
==
leaf
)
?
parent
->
GetRight
()
:
parent
->
GetLeft
());
NodePtr
sibling
=
other_child
;
node_hazard_manager_
.
GuardPointer
(
3
,
sibling
);
if
(
sibling
!=
other_child
)
continue
;
VERIFY_ADDRESS
(
sibling
);
// Try to lock the sibling
UniqueLock
sibling_lock
(
sibling
->
GetMutex
(),
embb
::
base
::
try_lock
);
if
(
!
sibling_lock
.
OwnsLock
()
||
sibling
->
IsRetired
())
continue
;
...
...
@@ -287,33 +290,22 @@ TryDelete(const Key& key, Value& old_value) {
old_value
=
leaf
->
GetValue
();
GetPointerToChild
(
grandparent
,
parent
).
CompareAndSwap
(
parent
,
new_leaf
);
deletion_succeeded
=
true
;
parent
->
Retire
();
parent_lock
.
Unlock
();
node_hazard_manager_
.
GuardPointer
(
1
,
NULL
);
RemoveNode
(
parent
);
leaf
->
Retire
();
leaf_lock
.
Unlock
();
node_hazard_manager_
.
GuardPointer
(
2
,
NULL
);
RemoveNode
(
leaf
);
sibling
->
Retire
();
sibling_lock
.
Unlock
();
node_hazard_manager_
.
GuardPointer
(
3
,
NULL
);
RemoveNode
(
sibling
);
// if (new_weight > 1) {
// CleanUp(key);
// }
NodePtr
expected
=
parent
;
deletion_succeeded
=
GetPointerToChild
(
grandparent
,
parent
)
.
CompareAndSwap
(
expected
,
new_leaf
);
assert
(
deletion_succeeded
);
// For now (FGL tree) this CAS may not fail
if
(
!
deletion_succeeded
)
continue
;
RetireHazardousNode
(
parent
,
parent_lock
);
RetireHazardousNode
(
leaf
,
leaf_lock
);
RetireHazardousNode
(
sibling
,
sibling_lock
);
added_violation
=
(
new_weight
>
1
);
}
node_hazard_manager_
.
GuardPointer
(
0
,
NULL
);
node_hazard_manager_
.
GuardPointer
(
1
,
NULL
);
node_hazard_manager_
.
GuardPointer
(
2
,
NULL
);
node_hazard_manager_
.
GuardPointer
(
3
,
NULL
);
if
(
!
deletion_succeeded
)
{
if
(
deletion_succeeded
)
{
if
(
added_violation
)
CleanUp
(
key
);
}
else
{
if
(
new_leaf
!=
NULL
)
FreeNode
(
new_leaf
);
}
...
...
@@ -340,39 +332,22 @@ IsEmpty() {
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
void
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
Search
(
const
Key
&
key
,
NodePtr
&
leaf
)
{
NodePtr
parent
;
Search
(
key
,
leaf
,
parent
);
node_hazard_manager_
.
GuardPointer
(
0
,
leaf
);
node_hazard_manager_
.
GuardPointer
(
1
,
NULL
);
}
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
void
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
Search
(
const
Key
&
key
,
NodePtr
&
leaf
,
NodePtr
&
parent
)
{
Search
(
const
Key
&
key
,
HazardNodePtr
&
leaf
,
HazardNodePtr
&
parent
)
{
bool
reached_leaf
=
false
;
while
(
!
reached_leaf
)
{
parent
=
entry_
;
node_hazard_manager_
.
GuardPointer
(
0
,
parent
);
leaf
=
entry_
->
GetLeft
();
node_hazard_manager_
.
GuardPointer
(
1
,
leaf
);
if
(
leaf
!=
entry_
->
GetLeft
())
continue
;
parent
.
ProtectHazard
(
entry_
);
leaf
.
ProtectHazard
(
entry_
->
GetLeft
());
if
(
parent
->
IsRetired
()
||
!
leaf
.
IsActive
())
continue
;
reached_leaf
=
IsLeaf
(
leaf
);
while
(
!
reached_leaf
)
{
parent
=
leaf
;
node_hazard_manager_
.
GuardPointer
(
0
,
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
<
NodePtr
>
(
leaf
));
AtomicNodePtr
&
next_leaf
=
(
IsSentinel
(
leaf
)
||
compare_
(
key
,
leaf
->
GetKey
()))
?
leaf
->
GetLeft
()
:
leaf
->
GetRight
();
leaf
=
next_leaf
;
node_hazard_manager_
.
GuardPointer
(
1
,
leaf
);
if
(
leaf
!=
next_leaf
||
parent
->
IsRetired
())
break
;
VERIFY_ADDRESS
(
leaf
);
reached_leaf
=
IsLeaf
(
leaf
);
}
}
...
...
@@ -380,35 +355,25 @@ Search(const Key& key, NodePtr& leaf, NodePtr& parent) {
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
void
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
Search
(
const
Key
&
key
,
NodePtr
&
leaf
,
NodePtr
&
parent
,
NodePtr
&
grandparent
)
{
Search
(
const
Key
&
key
,
HazardNodePtr
&
leaf
,
HazardNodePtr
&
parent
,
HazardNodePtr
&
grandparent
)
{
bool
reached_leaf
=
false
;
while
(
!
reached_leaf
)
{
grandparent
=
NULL
;
parent
=
entry_
;
node_hazard_manager_
.
GuardPointer
(
1
,
parent
);
leaf
=
entry_
->
GetLeft
();
node_hazard_manager_
.
GuardPointer
(
2
,
leaf
);
if
(
leaf
!=
entry_
->
GetLeft
())
continue
;
grandparent
.
ProtectHazard
(
entry_
);
parent
.
ProtectHazard
(
entry_
);
leaf
.
ProtectHazard
(
entry_
->
GetLeft
());
if
(
parent
->
IsRetired
()
||
!
leaf
.
IsActive
())
continue
;
reached_leaf
=
IsLeaf
(
leaf
);
while
(
!
reached_leaf
)
{
grandparent
=
parent
;
node_hazard_manager_
.
GuardPointer
(
0
,
grandparent
);
parent
=
leaf
;
node_hazard_manager_
.
GuardPointer
(
1
,
parent
);
AtomicNodePtr
&
next_leaf
=
(
IsSentinel
(
leaf
)
||
compare_
(
key
,
leaf
->
GetKey
()))
?
leaf
->
GetLeft
()
:
leaf
->
GetRight
();
leaf
=
next_leaf
;
node_hazard_manager_
.
GuardPointer
(
2
,
leaf
);
if
(
leaf
!=
next_leaf
||
parent
->
IsRetired
())
break
;
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
<
NodePtr
>
(
leaf
));
VERIFY_ADDRESS
(
leaf
);
reached_leaf
=
IsLeaf
(
leaf
);
}
}
...
...
@@ -423,13 +388,15 @@ IsLeaf(const NodePtr& node) const {
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
bool
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
IsSentinel
(
const
NodePtr
&
node
)
const
{
return
(
node
==
entry_
)
||
(
node
==
entry_
->
GetLeft
());
NodePtr
entry
=
entry_
;
//Bug: "operator->()" is not const in AtomicPointer<>
return
(
node
==
entry
)
||
(
node
==
entry
->
GetLeft
());
}
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
bool
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
HasFixedWeight
(
const
NodePtr
&
node
)
const
{
return
(
IsSentinel
(
node
))
||
(
node
==
entry_
->
GetLeft
()
->
GetLeft
());
NodePtr
entry
=
entry_
;
//Bug: "operator->()" is not const in AtomicPointer<>
return
(
IsSentinel
(
node
))
||
(
node
==
entry
->
GetLeft
()
->
GetLeft
());
}
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
...
...
@@ -470,7 +437,8 @@ GetHeight(const NodePtr& node) const {
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
bool
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
IsBalanced
()
const
{
return
IsBalanced
(
entry_
->
GetLeft
());
NodePtr
entry
=
entry_
;
//Bug: "operator->()" is not const in AtomicPointer<>
return
IsBalanced
(
entry
->
GetLeft
());
}
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
...
...
@@ -509,92 +477,137 @@ FreeNode(NodePtr node) {
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
bool
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
CleanUp
(
const
Key
&
key
)
{
for
(;;)
{
NodePtr
grandgrandparent
=
NULL
;
NodePtr
grandparent
=
NULL
;
NodePtr
parent
=
entry_
;
NodePtr
leaf
=
entry_
->
GetLeft
();
while
(
!
IsLeaf
(
leaf
)
&&
(
leaf
->
GetWeight
()
<=
1
)
&&
(
leaf
->
GetWeight
()
!=
0
||
parent
->
GetWeight
()
!=
0
))
{
grandgrandparent
=
grandparent
;
grandparent
=
parent
;
parent
=
leaf
;
leaf
=
(
IsSentinel
(
leaf
)
||
compare_
(
key
,
leaf
->
GetKey
()))
?
leaf
->
GetLeft
()
:
leaf
->
GetRight
();
VERIFY_ADDRESS
(
leaf
);
}
HazardNodePtr
grangranparent
(
node_hazard_manager_
.
GetGuardedPointer
(
0
),
NULL
);
HazardNodePtr
grandparent
(
node_hazard_manager_
.
GetGuardedPointer
(
1
),
NULL
);
HazardNodePtr
parent
(
node_hazard_manager_
.
GetGuardedPointer
(
2
),
NULL
);
HazardNodePtr
leaf
(
node_hazard_manager_
.
GetGuardedPointer
(
3
),
NULL
);
bool
reached_leaf
=
false
;
if
(
leaf
->
GetWeight
()
==
1
)
{
break
;
while
(
!
reached_leaf
)
{
bool
found_violation
=
false
;
grangranparent
.
ProtectHazard
(
entry_
);
grandparent
.
ProtectHazard
(
entry_
);
parent
.
ProtectHazard
(
entry_
);
leaf
.
ProtectHazard
(
entry_
->
GetLeft
());
if
(
parent
->
IsRetired
()
||
!
leaf
.
IsActive
())
continue
;
reached_leaf
=
IsLeaf
(
leaf
);
while
(
!
reached_leaf
&&
!
found_violation
)
{
grangranparent
.
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
<
NodePtr
>
(
leaf
));
found_violation
=
(
leaf
->
GetWeight
()
>
1
)
||
(
leaf
->
GetWeight
()
==
0
&&
parent
->
GetWeight
()
==
0
);
reached_leaf
=
IsLeaf
(
leaf
);
}
if
(
!
Rebalance
(
grandgrandparent
,
grandparent
,
parent
,
leaf
))
{
return
false
;
if
(
found_violation
)
{
reached_leaf
=
false
;
if
(
Rebalance
(
grangranparent
,
grandparent
,
parent
,
leaf
)
==
EMBB_NOMEM
)
{
assert
(
false
&&
"No memory for rebalancing!"
);
return
false
;
}
}
}
return
true
;
}
#define PROTECT_NODE_WITH_LOCK(node, lock_name) \
UniqueLock lock_name(node->GetMutex(), embb::base::try_lock); \
if (!lock_name.OwnsLock() || node->IsRetired()) return EMBB_BUSY;
#define DEFINE_NODE_WITH_HAZARD(h_num, node, parent, method) \
HazardNodePtr node(node_hazard_manager_.GetGuardedPointer(h_num), NULL); \
node.ProtectHazard(parent->method()); \
if (parent->IsRetired() || !node.IsActive()) return EMBB_BUSY; \
VERIFY_ADDRESS(static_cast<NodePtr>(node))
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
bool
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
Rebalance
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxx
,
const
NodePtr
&
uxxx
)
{
//TODO: weakLLX(u);
if
(
!
HasChild
(
u
,
ux
))
return
false
;
//TODO: weakLLX(ux);
NodePtr
uxl
=
ux
->
GetLeft
();
VERIFY_ADDRESS
(
uxl
);
NodePtr
uxr
=
ux
->
GetRight
();
VERIFY_ADDRESS
(
uxr
);
bool
uxx_is_left
=
(
uxx
==
uxl
);
if
(
!
HasChild
(
ux
,
uxx
))
return
false
;
//TODO: weakLLX(uxx);
NodePtr
uxxl
=
uxx
->
GetLeft
();
VERIFY_ADDRESS
(
uxxl
);
NodePtr
uxxr
=
uxx
->
GetRight
();
VERIFY_ADDRESS
(
uxxr
);
embb_errors_t
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
Rebalance
(
HazardNodePtr
&
u
,
HazardNodePtr
&
ux
,
HazardNodePtr
&
uxx
,
HazardNodePtr
&
uxxx
)
{
// Protect node 'u'
PROTECT_NODE_WITH_LOCK
(
u
,
u_lock
);
// Verify that ux is still a child of u
if
(
!
HasChild
(
u
,
ux
))
return
EMBB_BUSY
;
// Protect node 'ux'
PROTECT_NODE_WITH_LOCK
(
ux
,
ux_lock
);
// Get children of 'ux'
DEFINE_NODE_WITH_HAZARD
(
4
,
uxl
,
ux
,
GetLeft
);
DEFINE_NODE_WITH_HAZARD
(
5
,
uxr
,
ux
,
GetRight
);
// Verify that 'uxx' is still a child of 'ux'
bool
uxx_is_left
=
(
uxx
==
uxl
);
(
void
)
uxx_is_left
;
if
(
!
HasChild
(
ux
,
uxx
))
return
EMBB_BUSY
;
// Protect node 'uxx'
PROTECT_NODE_WITH_LOCK
(
uxx
,
uxx_lock
);
// Get children of 'uxx'
DEFINE_NODE_WITH_HAZARD
(
6
,
uxxl
,
uxx
,
GetLeft
);
DEFINE_NODE_WITH_HAZARD
(
7
,
uxxr
,
uxx
,
GetRight
);
// Verify that 'uxxx' is still a child of 'uxx'
bool
uxxx_is_left
=
(
uxxx
==
uxxl
);
if
(
!
HasChild
(
uxx
,
uxxx
))
return
false
;
if
(
!
HasChild
(
uxx
,
uxxx
))
return
EMBB_BUSY
;
if
(
uxxx
->
GetWeight
()
>
1
)
{
if
(
uxxx_is_left
)
{
//TODO: weakLLX(uxxl);
return
OverweightLeft
(
u
,
ux
,
uxx
,
uxl
,
uxr
,
uxxl
,
uxxr
,
uxx_is_left
);
// Protect node 'uxxl'
PROTECT_NODE_WITH_LOCK
(
uxxl
,
uxxl_lock
);
return
OverweightLeft
(
u
,
u_lock
,
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxl
,
uxr
,
uxxl
,
uxxl_lock
,
uxxr
,
uxx_is_left
);
}
else
{
//TODO: weakLLX(uxxr);
return
OverweightRight
(
u
,
ux
,
uxx
,
uxl
,
uxr
,
uxxl
,
uxxr
,
!
uxx_is_left
);
// Protect node 'uxxr'
PROTECT_NODE_WITH_LOCK
(
uxxr
,
uxxr_lock
);
return
OverweightRight
(
u
,
u_lock
,
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxl
,
uxr
,
uxxl
,
uxxr
,
uxxr_lock
,
!
uxx_is_left
);
}
}
else
{
assert
(
uxxx
->
GetWeight
()
==
0
&&
uxx
->
GetWeight
()
==
0
);
//Red-red violation
if
(
uxx_is_left
)
{
if
(
uxr
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxr);
return
BLK
(
u
,
ux
,
uxx
,
uxr
);
// Protect node 'uxr'
PROTECT_NODE_WITH_LOCK
(
uxr
,
uxr_lock
);
return
BLK
(
u
,
u_lock
,
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxr
,
uxr_lock
);
}
else
if
(
uxxx_is_left
)
{
return
RB1_L
(
u
,
u
x
,
uxx
);
return
RB1_L
(
u
,
u
_lock
,
ux
,
ux_lock
,
uxx
,
uxx_lock
);
}
else
{
//TODO: weakLLX(uxxr);
return
RB2_L
(
u
,
ux
,
uxx
,
uxxr
);
// Protect node 'uxxr'
PROTECT_NODE_WITH_LOCK
(
uxxr
,
uxxr_lock
);
return
RB2_L
(
u
,
u_lock
,
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxxr
,
uxxr_lock
);
}
}
else
{
if
(
uxl
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxl);
return
BLK
(
u
,
ux
,
uxl
,
uxx
);
// Protect node 'uxl'
PROTECT_NODE_WITH_LOCK
(
uxl
,
uxl_lock
);
return
BLK
(
u
,
u_lock
,
ux
,
ux_lock
,
uxl
,
uxl_lock
,
uxx
,
uxx_lock
);
}
else
if
(
!
uxxx_is_left
)
{
return
RB1_R
(
u
,
u
x
,
uxx
);
return
RB1_R
(
u
,
u
_lock
,
ux
,
ux_lock
,
uxx
,
uxx_lock
);
}
else
{
//TODO: weakLLX(uxxl);
return
RB2_R
(
u
,
ux
,
uxx
,
uxxl
);
// Protect node 'uxxl'
PROTECT_NODE_WITH_LOCK
(
uxxl
,
uxxl_lock
);
return
RB2_R
(
u
,
u_lock
,
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxxl
,
uxxl_lock
);
}
}
}
}
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
bool
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
OverweightLeft
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxx
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxr
,
const
NodePtr
&
uxxl
,
const
NodePtr
&
uxxr
,
const
bool
&
uxx_is_left
)
{
embb_errors_t
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
OverweightLeft
(
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
HazardNodePtr
&
uxx
,
UniqueLock
&
uxx_lock
,
HazardNodePtr
&
uxl
,
HazardNodePtr
&
uxr
,
HazardNodePtr
&
uxxl
,
UniqueLock
&
uxxl_lock
,
HazardNodePtr
&
uxxr
,
bool
uxx_is_left
)
{
// Let "Root" be the top of the overweight violation decision tree (see p.30)
// Root -> Middle
if
(
uxxr
->
GetWeight
()
==
0
)
{
...
...
@@ -604,14 +617,16 @@ OverweightLeft(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
if
(
uxx_is_left
)
{
// Root -> Middle -> Left -> Left -> Left
if
(
uxr
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxr);
return
BLK
(
u
,
ux
,
uxx
,
uxr
);
// Protect node 'uxr'
PROTECT_NODE_WITH_LOCK
(
uxr
,
uxr_lock
);
return
BLK
(
u
,
u_lock
,
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxr
,
uxr_lock
);
// Root -> Middle -> Left -> Left -> Right
}
else
{
assert
(
uxr
->
GetWeight
()
>
0
);
//TODO: weakLLX(uxxr);
return
RB2_L
(
u
,
ux
,
uxx
,
uxxr
);
// Protect node 'uxxr'
PROTECT_NODE_WITH_LOCK
(
uxxr
,
uxxr_lock
);
return
RB2_L
(
u
,
u_lock
,
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxxr
,
uxxr_lock
);
}
// Root -> Middle -> Left -> Right
...
...
@@ -619,102 +634,126 @@ OverweightLeft(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
assert
(
!
uxx_is_left
);
// Root -> Middle -> Left -> Right -> Left
if
(
uxl
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxl);
return
BLK
(
u
,
ux
,
uxl
,
uxx
);
// Protect node 'uxl'
PROTECT_NODE_WITH_LOCK
(
uxl
,
uxl_lock
);
return
BLK
(
u
,
u_lock
,
ux
,
ux_lock
,
uxl
,
uxl_lock
,
uxx
,
uxx_lock
);
// Root -> Middle -> Left -> Right -> Right
}
else
{
assert
(
uxl
->
GetWeight
()
>
0
);
return
RB1_R
(
u
,
u
x
,
uxx
);
return
RB1_R
(
u
,
u
_lock
,
ux
,
ux_lock
,
uxx
,
uxx_lock
);
}
}
// Root -> Middle -> Right
}
else
{
assert
(
uxx
->
GetWeight
()
>
0
);
//TODO: weakLLX(uxxr);
// Protect node 'uxxr'
PROTECT_NODE_WITH_LOCK
(
uxxr
,
uxxr_lock
);
// Get left child of 'uxxr'
// Note: we know that 'uxxr' is not a leaf because it has weight 0.
NodePtr
uxxrl
=
uxxr
->
GetLeft
();
VERIFY_ADDRESS
(
uxxrl
);
//TODO: weakLLX(uxxrl);
DEFINE_NODE_WITH_HAZARD
(
8
,
uxxrl
,
uxxr
,
GetLeft
);
// Protect node 'uxxrl'
PROTECT_NODE_WITH_LOCK
(
uxxrl
,
uxxrl_lock
);
// Root -> Middle -> Right -> Left
if
(
uxxrl
->
GetWeight
()
==
0
)
{
return
RB2_R
(
ux
,
uxx
,
uxxr
,
uxxrl
);
return
RB2_R
(
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxxr
,
uxxr_lock
,
uxxrl
,
uxxrl_lock
);
// Root -> Middle -> Right -> Middle
}
else
if
(
uxxrl
->
GetWeight
()
==
1
)
{
NodePtr
uxxrll
=
uxxrl
->
GetLeft
();
VERIFY_ADDRESS
(
uxxrll
);
NodePtr
uxxrlr
=
uxxrl
->
GetRight
();
VERIFY_ADDRESS
(
uxxrlr
);
if
(
uxxrlr
==
NULL
)
return
false
;
DEFINE_NODE_WITH_HAZARD
(
9
,
uxxrlr
,
uxxrl
,
GetRight
);
if
(
uxxrlr
==
NULL
)
return
EMBB_BUSY
;
// Root -> Middle -> Right -> Middle -> Left
if
(
uxxrlr
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxxrlr);
return
W4_L
(
ux
,
uxx
,
uxxl
,
uxxr
,
uxxrl
,
uxxrlr
);
// Protect node 'uxxrlr'
PROTECT_NODE_WITH_LOCK
(
uxxrlr
,
uxxrlr_lock
);
return
W4_L
(
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxxl
,
uxxl_lock
,
uxxr
,
uxxr_lock
,
uxxrl
,
uxxrl_lock
,
uxxrlr
,
uxxrlr_lock
);
// 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
);
if
(
uxxrll
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxxrll);
return
W3_L
(
ux
,
uxx
,
uxxl
,
uxxr
,
uxxrl
,
uxxrll
);
// Protect node 'uxxrll'
PROTECT_NODE_WITH_LOCK
(
uxxrll
,
uxxrll_lock
);
return
W3_L
(
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxxl
,
uxxl_lock
,
uxxr
,
uxxr_lock
,
uxxrl
,
uxxrl_lock
,
uxxrll
,
uxxrll_lock
);
// Root -> Middle -> Right -> Middle -> Right -> Right
}
else
{
assert
(
uxxrll
->
GetWeight
()
>
0
);
return
W2_L
(
ux
,
uxx
,
uxxl
,
uxxr
,
uxxrl
);
return
W2_L
(
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxxl
,
uxxl_lock
,
uxxr
,
uxxr_lock
,
uxxrl
,
uxxrl_lock
);
}
}
// Root -> Middle -> Right -> Right
}
else
{
assert
(
uxxrl
->
GetWeight
()
>
1
);
return
W1_L
(
ux
,
uxx
,
uxxl
,
uxxr
,
uxxrl
);
return
W1_L
(
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxxl
,
uxxl_lock
,
uxxr
,
uxxr_lock
,
uxxrl
,
uxxrl_lock
);
}
}
// Root -> Right
}
else
if
(
uxxr
->
GetWeight
()
==
1
)
{
//TODO: weakLLX(uxxr);
NodePtr
uxxrl
=
uxxr
->
GetLeft
();
VERIFY_ADDRESS
(
uxxrl
);
NodePtr
uxxrr
=
uxxr
->
GetRight
();
VERIFY_ADDRESS
(
uxxrr
);
if
(
uxxrl
==
NULL
)
return
false
;
// Protect node 'uxxr'
PROTECT_NODE_WITH_LOCK
(
uxxr
,
uxxr_lock
);
// Get children of 'uxxr'
DEFINE_NODE_WITH_HAZARD
(
8
,
uxxrl
,
uxxr
,
GetLeft
);
DEFINE_NODE_WITH_HAZARD
(
9
,
uxxrr
,
uxxr
,
GetRight
);
if
(
uxxrl
==
NULL
)
return
EMBB_BUSY
;
// Root -> Right -> Left
if
(
uxxrr
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxxrr);
return
W5_L
(
ux
,
uxx
,
uxxl
,
uxxr
,
uxxrr
);
// Protect node 'uxxrr'
PROTECT_NODE_WITH_LOCK
(
uxxrr
,
uxxrr_lock
);
return
W5_L
(
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxxl
,
uxxl_lock
,
uxxr
,
uxxr_lock
,
uxxrr
,
uxxrr_lock
);
// Root -> Right -> Right
}
else
{
assert
(
uxxrr
->
GetWeight
()
>
0
);
// Root -> Right -> Right -> Left
if
(
uxxrl
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxxrl);
return
W6_L
(
ux
,
uxx
,
uxxl
,
uxxr
,
uxxrl
);
// Protect node 'uxxrl'
PROTECT_NODE_WITH_LOCK
(
uxxrl
,
uxxrl_lock
);
return
W6_L
(
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxxl
,
uxxl_lock
,
uxxr
,
uxxr_lock
,
uxxrl
,
uxxrl_lock
);
// Root -> Right -> Right -> Right
}
else
{
assert
(
uxxrl
->
GetWeight
()
>
0
);
return
PUSH_L
(
ux
,
uxx
,
uxxl
,
uxxr
);
return
PUSH_L
(
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxxl
,
uxxl_lock
,
uxxr
,
uxxr_lock
);
}
}
// Root -> Left
}
else
{
assert
(
uxxr
->
GetWeight
()
>
1
);
//TODO: weakLLX(uxxr);
return
W7
(
ux
,
uxx
,
uxxl
,
uxxr
);
// Protect node 'uxxr'
PROTECT_NODE_WITH_LOCK
(
uxxr
,
uxxr_lock
);
return
W7
(
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxxl
,
uxxl_lock
,
uxxr
,
uxxr_lock
);
}
}
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
bool
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
OverweightRight
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxx
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxr
,
const
NodePtr
&
uxxl
,
const
NodePtr
&
uxxr
,
const
bool
&
uxx_is_right
)
{
embb_errors_t
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
OverweightRight
(
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
HazardNodePtr
&
uxx
,
UniqueLock
&
uxx_lock
,
HazardNodePtr
&
uxl
,
HazardNodePtr
&
uxr
,
HazardNodePtr
&
uxxl
,
HazardNodePtr
&
uxxr
,
UniqueLock
&
uxxr_lock
,
bool
uxx_is_right
)
{
// Let "Root" be the top of the overweight violation decision tree (see p.30)
// Root -> Middle
if
(
uxxl
->
GetWeight
()
==
0
)
{
...
...
@@ -724,14 +763,16 @@ OverweightRight(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
if
(
uxx_is_right
)
{
// Root -> Middle -> Left -> Left -> Left
if
(
uxl
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxl);
return
BLK
(
u
,
ux
,
uxl
,
uxx
);
// Protect node 'uxl'
PROTECT_NODE_WITH_LOCK
(
uxl
,
uxl_lock
);
return
BLK
(
u
,
u_lock
,
ux
,
ux_lock
,
uxl
,
uxl_lock
,
uxx
,
uxx_lock
);
// Root -> Middle -> Left -> Left -> Right
}
else
{
assert
(
uxl
->
GetWeight
()
>
0
);
//TODO: weakLLX(uxxl);
return
RB2_R
(
u
,
ux
,
uxx
,
uxxl
);
// Protect node 'uxxl'
PROTECT_NODE_WITH_LOCK
(
uxxl
,
uxxl_lock
);
return
RB2_R
(
u
,
u_lock
,
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxxl
,
uxxl_lock
);
}
// Root -> Middle -> Left -> Right
...
...
@@ -739,93 +780,115 @@ OverweightRight(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
assert
(
!
uxx_is_right
);
// Root -> Middle -> Left -> Right -> Left
if
(
uxr
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxr);
return
BLK
(
u
,
ux
,
uxx
,
uxr
);
// Protect node 'uxr'
PROTECT_NODE_WITH_LOCK
(
uxr
,
uxr_lock
);
return
BLK
(
u
,
u_lock
,
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxr
,
uxr_lock
);
// Root -> Middle -> Left -> Right -> Right
}
else
{
assert
(
uxr
->
GetWeight
()
>
0
);
return
RB1_L
(
u
,
u
x
,
uxx
);
return
RB1_L
(
u
,
u
_lock
,
ux
,
ux_lock
,
uxx
,
uxx_lock
);
}
}
// Root -> Middle -> Right
}
else
{
assert
(
uxx
->
GetWeight
()
>
0
);
//TODO: weakLLX(uxxl);
// Protect node 'uxxl'
PROTECT_NODE_WITH_LOCK
(
uxxl
,
uxxl_lock
);
// Get left child of 'uxxl'
// Note: we know that 'uxxl' is not a leaf because it has weight 0.
NodePtr
uxxlr
=
uxxl
->
GetRight
();
VERIFY_ADDRESS
(
uxxlr
);
//TODO: weakLLX(uxxlr);
DEFINE_NODE_WITH_HAZARD
(
8
,
uxxlr
,
uxxl
,
GetRight
);
// Protect node 'uxxlr'
PROTECT_NODE_WITH_LOCK
(
uxxlr
,
uxxlr_lock
);
// Root -> Middle -> Right -> Left
if
(
uxxlr
->
GetWeight
()
==
0
)
{
return
RB2_L
(
ux
,
uxx
,
uxxl
,
uxxlr
);
return
RB2_L
(
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxxl
,
uxxl_lock
,
uxxlr
,
uxxlr_lock
);
// Root -> Middle -> Right -> Middle
}
else
if
(
uxxlr
->
GetWeight
()
==
1
)
{
NodePtr
uxxlrl
=
uxxlr
->
GetLeft
();
VERIFY_ADDRESS
(
uxxlrl
);
NodePtr
uxxlrr
=
uxxlr
->
GetRight
();
VERIFY_ADDRESS
(
uxxlrr
);
if
(
uxxlrl
==
NULL
)
return
false
;
DEFINE_NODE_WITH_HAZARD
(
9
,
uxxlrl
,
uxxlr
,
GetLeft
);
if
(
uxxlrl
==
NULL
)
return
EMBB_BUSY
;
// Root -> Middle -> Right -> Middle -> Left
if
(
uxxlrl
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxxlrl);
return
W4_R
(
ux
,
uxx
,
uxxl
,
uxxr
,
uxxlr
,
uxxlrl
);
// Protect node 'uxxlrl'
PROTECT_NODE_WITH_LOCK
(
uxxlrl
,
uxxlrl_lock
);
return
W4_R
(
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxxl
,
uxxl_lock
,
uxxr
,
uxxr_lock
,
uxxlr
,
uxxlr_lock
,
uxxlrl
,
uxxlrl_lock
);
// 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
);
if
(
uxxlrr
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxxlrr);
return
W3_R
(
ux
,
uxx
,
uxxl
,
uxxr
,
uxxlr
,
uxxlrr
);
// Protect node 'uxxlrr'
PROTECT_NODE_WITH_LOCK
(
uxxlrr
,
uxxlrr_lock
);
return
W3_R
(
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxxl
,
uxxl_lock
,
uxxr
,
uxxr_lock
,
uxxlr
,
uxxlr_lock
,
uxxlrr
,
uxxlrr_lock
);
// Root -> Middle -> Right -> Middle -> Right -> Right
}
else
{
assert
(
uxxlrr
->
GetWeight
()
>
0
);
return
W2_R
(
ux
,
uxx
,
uxxl
,
uxxr
,
uxxlr
);
return
W2_R
(
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxxl
,
uxxl_lock
,
uxxr
,
uxxr_lock
,
uxxlr
,
uxxlr_lock
);
}
}
// Root -> Middle -> Right -> Right
}
else
{
assert
(
uxxlr
->
GetWeight
()
>
1
);
return
W1_R
(
ux
,
uxx
,
uxxl
,
uxxr
,
uxxlr
);
return
W1_R
(
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxxl
,
uxxl_lock
,
uxxr
,
uxxr_lock
,
uxxlr
,
uxxlr_lock
);
}
}
// Root -> Right
}
else
if
(
uxxl
->
GetWeight
()
==
1
)
{
//TODO: weakLLX(uxxl);
NodePtr
uxxll
=
uxxl
->
GetLeft
();
VERIFY_ADDRESS
(
uxxll
);
NodePtr
uxxlr
=
uxxl
->
GetRight
();
VERIFY_ADDRESS
(
uxxlr
);
if
(
uxxll
==
NULL
)
return
false
;
// Protect node 'uxxl'
PROTECT_NODE_WITH_LOCK
(
uxxl
,
uxxl_lock
);
// Get children of 'uxxl'
DEFINE_NODE_WITH_HAZARD
(
8
,
uxxll
,
uxxl
,
GetLeft
);
DEFINE_NODE_WITH_HAZARD
(
9
,
uxxlr
,
uxxl
,
GetRight
);
if
(
uxxll
==
NULL
)
return
EMBB_BUSY
;
// Root -> Right -> Left
if
(
uxxll
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxxll);
return
W5_R
(
ux
,
uxx
,
uxxl
,
uxxr
,
uxxll
);
// Protect node 'uxxll'
PROTECT_NODE_WITH_LOCK
(
uxxll
,
uxxll_lock
);
return
W5_R
(
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxxl
,
uxxl_lock
,
uxxr
,
uxxr_lock
,
uxxll
,
uxxll_lock
);
// Root -> Right -> Right
}
else
{
assert
(
uxxll
->
GetWeight
()
>
0
);
// Root -> Right -> Right -> Left
if
(
uxxlr
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxxlr);
return
W6_R
(
ux
,
uxx
,
uxxl
,
uxxr
,
uxxlr
);
// Protect node 'uxxlr'
PROTECT_NODE_WITH_LOCK
(
uxxlr
,
uxxlr_lock
);
return
W6_R
(
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxxl
,
uxxl_lock
,
uxxr
,
uxxr_lock
,
uxxlr
,
uxxlr_lock
);
// Root -> Right -> Right -> Right
}
else
{
assert
(
uxxlr
->
GetWeight
()
>
0
);
return
PUSH_R
(
ux
,
uxx
,
uxxl
,
uxxr
);
return
PUSH_R
(
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxxl
,
uxxl_lock
,
uxxr
,
uxxr_lock
);
}
}
// Root -> Left
}
else
{
assert
(
uxxl
->
GetWeight
()
>
1
);
//TODO: weakLLX(uxxl);
return
W7
(
ux
,
uxx
,
uxxl
,
uxxr
);
// Protect node 'uxxl'
PROTECT_NODE_WITH_LOCK
(
uxxl
,
uxxl_lock
);
return
W7
(
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxxl
,
uxxl_lock
,
uxxr
,
uxxr_lock
);
}
}
...
...
containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-rebalance.h
View file @
2f75565c
...
...
@@ -32,10 +32,11 @@
#ifndef EMBB_CONTAINERS_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_
#define EMBB_CONTAINERS_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_
bool
BLK
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxr
)
{
embb_errors_t
BLK
(
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
,
HazardNodePtr
&
uxr
,
UniqueLock
&
uxr_lock
)
{
NodePtr
nxl
=
node_pool_
.
Allocate
(
uxl
->
GetKey
(),
uxl
->
GetValue
(),
1
,
...
...
@@ -49,29 +50,34 @@ bool BLK(const NodePtr& u,
HasFixedWeight
(
ux
)
?
1
:
ux
->
GetWeight
()
-
1
,
nxl
,
nxr
);
if
(
nxl
==
NULL
||
nxr
==
NULL
||
if
(
nxl
==
NULL
||
nxr
==
NULL
||
nx
==
NULL
)
{
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
nx
);
assert
(
rotation_succeeded
);
// For now (FGL tree) this CAS may not fail
if
(
!
rotation_succeeded
)
return
EMBB_BUSY
;
RetireNode
(
ux
);
RetireNode
(
uxl
);
RetireNode
(
uxr
);
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
true
;
return
EMBB_SUCCESS
;
}
bool
PUSH_L
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxr
)
{
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
)
{
NodePtr
nxl
=
node_pool_
.
Allocate
(
uxl
->
GetKey
(),
uxl
->
GetValue
(),
uxl
->
GetWeight
()
-
1
,
...
...
@@ -85,29 +91,34 @@ bool PUSH_L(const NodePtr& u,
HasFixedWeight
(
ux
)
?
1
:
ux
->
GetWeight
()
+
1
,
nxl
,
nxr
);
if
(
nxl
==
NULL
||
nxr
==
NULL
||
if
(
nxl
==
NULL
||
nxr
==
NULL
||
nx
==
NULL
)
{
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
nx
);
assert
(
rotation_succeeded
);
// For now (FGL tree) this CAS may not fail
if
(
!
rotation_succeeded
)
return
EMBB_BUSY
;
RetireNode
(
ux
);
RetireNode
(
uxl
);
RetireNode
(
uxr
);
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
true
;
return
EMBB_SUCCESS
;
}
bool
PUSH_R
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxr
)
{
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
)
{
NodePtr
nxr
=
node_pool_
.
Allocate
(
uxr
->
GetKey
(),
uxr
->
GetValue
(),
uxr
->
GetWeight
()
-
1
,
...
...
@@ -121,28 +132,33 @@ bool PUSH_R(const NodePtr& u,
HasFixedWeight
(
ux
)
?
1
:
ux
->
GetWeight
()
+
1
,
nxl
,
nxr
);
if
(
nxr
==
NULL
||
nxl
==
NULL
||
if
(
nxr
==
NULL
||
nxl
==
NULL
||
nx
==
NULL
)
{
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
nx
);
assert
(
rotation_succeeded
);
// For now (FGL tree) this CAS may not fail
if
(
!
rotation_succeeded
)
return
EMBB_BUSY
;
RetireNode
(
ux
);
RetireNode
(
uxl
);
RetireNode
(
uxr
);
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
true
;
return
EMBB_SUCCESS
;
}
bool
RB1_L
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxl
)
{
embb_errors_t
RB1_L
(
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
)
{
NodePtr
nxr
=
node_pool_
.
Allocate
(
ux
->
GetKey
(),
ux
->
GetValue
(),
0
,
...
...
@@ -152,25 +168,30 @@ bool RB1_L(const NodePtr& u,
ux
->
GetWeight
(),
uxl
->
GetLeft
(),
nxr
);
if
(
nxr
==
NULL
||
if
(
nxr
==
NULL
||
nx
==
NULL
)
{
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
nx
);
assert
(
rotation_succeeded
);
// For now (FGL tree) this CAS may not fail
if
(
!
rotation_succeeded
)
return
EMBB_BUSY
;
RetireNode
(
ux
);
RetireNode
(
uxl
);
RetireHazardousNode
(
ux
,
ux_lock
);
RetireHazardousNode
(
uxl
,
uxl_lock
);
(
void
)
u_lock
;
// For now (FGL tree) u_lock is not used here
return
true
;
return
EMBB_SUCCESS
;
}
bool
RB1_R
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxr
)
{
embb_errors_t
RB1_R
(
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
HazardNodePtr
&
uxr
,
UniqueLock
&
uxr_lock
)
{
NodePtr
nxl
=
node_pool_
.
Allocate
(
ux
->
GetKey
(),
ux
->
GetValue
(),
0
,
...
...
@@ -180,26 +201,31 @@ bool RB1_R(const NodePtr& u,
ux
->
GetWeight
(),
nxl
,
uxr
->
GetRight
());
if
(
nxl
==
NULL
||
if
(
nxl
==
NULL
||
nx
==
NULL
)
{
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
nx
);
assert
(
rotation_succeeded
);
// For now (FGL tree) this CAS may not fail
if
(
!
rotation_succeeded
)
return
EMBB_BUSY
;
RetireNode
(
ux
);
RetireNode
(
uxr
);
RetireHazardousNode
(
ux
,
ux_lock
);
RetireHazardousNode
(
uxr
,
uxr_lock
);
(
void
)
u_lock
;
// For now (FGL tree) u_lock is not used here
return
true
;
return
EMBB_SUCCESS
;
}
bool
RB2_L
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxlr
)
{
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
)
{
NodePtr
nxl
=
node_pool_
.
Allocate
(
uxl
->
GetKey
(),
uxl
->
GetValue
(),
0
,
...
...
@@ -213,29 +239,34 @@ bool RB2_L(const NodePtr& u,
ux
->
GetWeight
(),
nxl
,
nxr
);
if
(
nxl
==
NULL
||
nxr
==
NULL
||
if
(
nxl
==
NULL
||
nxr
==
NULL
||
nx
==
NULL
)
{
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
nx
);
assert
(
rotation_succeeded
);
// For now (FGL tree) this CAS may not fail
if
(
!
rotation_succeeded
)
return
EMBB_BUSY
;
RetireNode
(
ux
);
RetireNode
(
uxl
);
RetireNode
(
uxlr
);
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
true
;
return
EMBB_SUCCESS
;
}
bool
RB2_R
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxr
,
const
NodePtr
&
uxrl
)
{
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
)
{
NodePtr
nxr
=
node_pool_
.
Allocate
(
uxr
->
GetKey
(),
uxr
->
GetValue
(),
0
,
...
...
@@ -249,30 +280,35 @@ bool RB2_R(const NodePtr& u,
ux
->
GetWeight
(),
nxl
,
nxr
);
if
(
nxr
==
NULL
||
nxl
==
NULL
||
if
(
nxr
==
NULL
||
nxl
==
NULL
||
nx
==
NULL
)
{
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
nx
);
assert
(
rotation_succeeded
);
// For now (FGL tree) this CAS may not fail
if
(
!
rotation_succeeded
)
return
EMBB_BUSY
;
RetireNode
(
ux
);
RetireNode
(
uxr
);
RetireNode
(
uxrl
);
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
true
;
return
EMBB_SUCCESS
;
}
bool
W1_L
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxr
,
const
NodePtr
&
uxrl
)
{
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
)
{
NodePtr
nxll
=
node_pool_
.
Allocate
(
uxl
->
GetKey
(),
uxl
->
GetValue
(),
uxl
->
GetWeight
()
-
1
,
...
...
@@ -290,33 +326,38 @@ bool W1_L(const NodePtr& u,
ux
->
GetWeight
(),
nxl
,
uxr
->
GetRight
());
if
(
nxll
==
NULL
||
nxlr
==
NULL
||
nxl
==
NULL
||
if
(
nxll
==
NULL
||
nxlr
==
NULL
||
nxl
==
NULL
||
nx
==
NULL
)
{
if
(
nxll
)
FreeNode
(
nxll
);
if
(
nxlr
)
FreeNode
(
nxlr
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
RetireNode
(
ux
);
RetireNode
(
uxl
);
RetireNode
(
uxr
);
RetireNode
(
uxrl
);
return
true
;
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
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
;
}
bool
W1_R
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxr
,
const
NodePtr
&
uxlr
)
{
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
)
{
NodePtr
nxrr
=
node_pool_
.
Allocate
(
uxr
->
GetKey
(),
uxr
->
GetValue
(),
uxr
->
GetWeight
()
-
1
,
...
...
@@ -334,33 +375,38 @@ bool W1_R(const NodePtr& u,
ux
->
GetWeight
(),
uxl
->
GetLeft
(),
nxr
);
if
(
nxrr
==
NULL
||
nxrl
==
NULL
||
nxr
==
NULL
||
if
(
nxrr
==
NULL
||
nxrl
==
NULL
||
nxr
==
NULL
||
nx
==
NULL
)
{
if
(
nxrr
)
FreeNode
(
nxrr
);
if
(
nxrl
)
FreeNode
(
nxrl
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
RetireNode
(
ux
);
RetireNode
(
uxl
);
RetireNode
(
uxr
);
RetireNode
(
uxlr
);
return
true
;
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
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
;
}
bool
W2_L
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxr
,
const
NodePtr
&
uxrl
)
{
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
)
{
NodePtr
nxll
=
node_pool_
.
Allocate
(
uxl
->
GetKey
(),
uxl
->
GetValue
(),
uxl
->
GetWeight
()
-
1
,
...
...
@@ -378,33 +424,38 @@ bool W2_L(const NodePtr& u,
ux
->
GetWeight
(),
nxl
,
uxr
->
GetRight
());
if
(
nxll
==
NULL
||
nxlr
==
NULL
||
nxl
==
NULL
||
if
(
nxll
==
NULL
||
nxlr
==
NULL
||
nxl
==
NULL
||
nx
==
NULL
)
{
if
(
nxll
)
FreeNode
(
nxll
);
if
(
nxlr
)
FreeNode
(
nxlr
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
RetireNode
(
ux
);
RetireNode
(
uxl
);
RetireNode
(
uxr
);
RetireNode
(
uxrl
);
return
true
;
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
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
;
}
bool
W2_R
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxr
,
const
NodePtr
&
uxlr
)
{
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
)
{
NodePtr
nxrr
=
node_pool_
.
Allocate
(
uxr
->
GetKey
(),
uxr
->
GetValue
(),
uxr
->
GetWeight
()
-
1
,
...
...
@@ -422,34 +473,39 @@ bool W2_R(const NodePtr& u,
ux
->
GetWeight
(),
uxl
->
GetLeft
(),
nxr
);
if
(
nxrr
==
NULL
||
nxrl
==
NULL
||
nxr
==
NULL
||
if
(
nxrr
==
NULL
||
nxrl
==
NULL
||
nxr
==
NULL
||
nx
==
NULL
)
{
if
(
nxrr
)
FreeNode
(
nxrr
);
if
(
nxrl
)
FreeNode
(
nxrl
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
RetireNode
(
ux
);
RetireNode
(
uxl
);
RetireNode
(
uxr
);
RetireNode
(
uxlr
);
return
true
;
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
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
;
}
bool
W3_L
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxr
,
const
NodePtr
&
uxrl
,
const
NodePtr
&
uxrll
)
{
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
)
{
NodePtr
nxlll
=
node_pool_
.
Allocate
(
uxl
->
GetKey
(),
uxl
->
GetValue
(),
uxl
->
GetWeight
()
-
1
,
...
...
@@ -471,37 +527,42 @@ bool W3_L(const NodePtr& u,
ux
->
GetWeight
(),
nxl
,
uxr
->
GetRight
());
if
(
nxlll
==
NULL
||
nxll
==
NULL
||
nxlr
==
NULL
||
nxl
==
NULL
||
if
(
nxlll
==
NULL
||
nxll
==
NULL
||
nxlr
==
NULL
||
nxl
==
NULL
||
nx
==
NULL
)
{
if
(
nxlll
)
FreeNode
(
nxlll
);
if
(
nxll
)
FreeNode
(
nxll
);
if
(
nxlr
)
FreeNode
(
nxlr
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
RetireNode
(
ux
);
RetireNode
(
uxl
);
RetireNode
(
uxr
);
RetireNode
(
uxrl
);
RetireNode
(
uxrll
);
return
true
;
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
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
;
}
bool
W3_R
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxr
,
const
NodePtr
&
uxlr
,
const
NodePtr
&
uxlrr
)
{
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
)
{
NodePtr
nxrrr
=
node_pool_
.
Allocate
(
uxr
->
GetKey
(),
uxr
->
GetValue
(),
uxr
->
GetWeight
()
-
1
,
...
...
@@ -523,37 +584,42 @@ bool W3_R(const NodePtr& u,
ux
->
GetWeight
(),
uxl
->
GetLeft
(),
nxr
);
if
(
nxrrr
==
NULL
||
nxrr
==
NULL
||
nxrl
==
NULL
||
nxr
==
NULL
||
if
(
nxrrr
==
NULL
||
nxrr
==
NULL
||
nxrl
==
NULL
||
nxr
==
NULL
||
nx
==
NULL
)
{
if
(
nxrrr
)
FreeNode
(
nxrrr
);
if
(
nxrr
)
FreeNode
(
nxrr
);
if
(
nxrl
)
FreeNode
(
nxrl
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
RetireNode
(
ux
);
RetireNode
(
uxl
);
RetireNode
(
uxr
);
RetireNode
(
uxlr
);
RetireNode
(
uxlrr
);
return
true
;
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
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
;
}
bool
W4_L
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxr
,
const
NodePtr
&
uxrl
,
const
NodePtr
&
uxrlr
)
{
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
)
{
NodePtr
nxll
=
node_pool_
.
Allocate
(
uxl
->
GetKey
(),
uxl
->
GetValue
(),
uxl
->
GetWeight
()
-
1
,
...
...
@@ -575,37 +641,42 @@ bool W4_L(const NodePtr& u,
ux
->
GetWeight
(),
nxl
,
nxr
);
if
(
nxll
==
NULL
||
nxrl
==
NULL
||
nxl
==
NULL
||
nxr
==
NULL
||
if
(
nxll
==
NULL
||
nxrl
==
NULL
||
nxl
==
NULL
||
nxr
==
NULL
||
nx
==
NULL
)
{
if
(
nxll
)
FreeNode
(
nxll
);
if
(
nxrl
)
FreeNode
(
nxrl
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
RetireNode
(
ux
);
RetireNode
(
uxl
);
RetireNode
(
uxr
);
RetireNode
(
uxrl
);
RetireNode
(
uxrlr
);
return
true
;
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
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
;
}
bool
W4_R
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxr
,
const
NodePtr
&
uxlr
,
const
NodePtr
&
uxlrl
)
{
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
)
{
NodePtr
nxrr
=
node_pool_
.
Allocate
(
uxr
->
GetKey
(),
uxr
->
GetValue
(),
uxr
->
GetWeight
()
-
1
,
...
...
@@ -627,36 +698,41 @@ bool W4_R(const NodePtr& u,
ux
->
GetWeight
(),
nxl
,
nxr
);
if
(
nxrr
==
NULL
||
nxlr
==
NULL
||
nxr
==
NULL
||
nxl
==
NULL
||
if
(
nxrr
==
NULL
||
nxlr
==
NULL
||
nxr
==
NULL
||
nxl
==
NULL
||
nx
==
NULL
)
{
if
(
nxrr
)
FreeNode
(
nxrr
);
if
(
nxlr
)
FreeNode
(
nxlr
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
RetireNode
(
ux
);
RetireNode
(
uxl
);
RetireNode
(
uxr
);
RetireNode
(
uxlr
);
RetireNode
(
uxlrl
);
return
true
;
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
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
;
}
bool
W5_L
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxr
,
const
NodePtr
&
uxrr
)
{
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
)
{
NodePtr
nxll
=
node_pool_
.
Allocate
(
uxl
->
GetKey
(),
uxl
->
GetValue
(),
uxl
->
GetWeight
()
-
1
,
...
...
@@ -674,33 +750,38 @@ bool W5_L(const NodePtr& u,
ux
->
GetWeight
(),
nxl
,
nxr
);
if
(
nxll
==
NULL
||
nxl
==
NULL
||
nxr
==
NULL
||
if
(
nxll
==
NULL
||
nxl
==
NULL
||
nxr
==
NULL
||
nx
==
NULL
)
{
if
(
nxll
)
FreeNode
(
nxll
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
RetireNode
(
ux
);
RetireNode
(
uxl
);
RetireNode
(
uxr
);
RetireNode
(
uxrr
);
return
true
;
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
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
;
}
bool
W5_R
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxr
,
const
NodePtr
&
uxll
)
{
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
)
{
NodePtr
nxrr
=
node_pool_
.
Allocate
(
uxr
->
GetKey
(),
uxr
->
GetValue
(),
uxr
->
GetWeight
()
-
1
,
...
...
@@ -718,33 +799,38 @@ bool W5_R(const NodePtr& u,
ux
->
GetWeight
(),
nxl
,
nxr
);
if
(
nxrr
==
NULL
||
nxr
==
NULL
||
nxl
==
NULL
||
if
(
nxrr
==
NULL
||
nxr
==
NULL
||
nxl
==
NULL
||
nx
==
NULL
)
{
if
(
nxrr
)
FreeNode
(
nxrr
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
RetireNode
(
ux
);
RetireNode
(
uxl
);
RetireNode
(
uxr
);
RetireNode
(
uxll
);
return
true
;
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
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
;
}
bool
W6_L
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxr
,
const
NodePtr
&
uxrl
)
{
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
)
{
NodePtr
nxll
=
node_pool_
.
Allocate
(
uxl
->
GetKey
(),
uxl
->
GetValue
(),
uxl
->
GetWeight
()
-
1
,
...
...
@@ -762,33 +848,38 @@ bool W6_L(const NodePtr& u,
ux
->
GetWeight
(),
nxl
,
nxr
);
if
(
nxll
==
NULL
||
nxl
==
NULL
||
nxr
==
NULL
||
if
(
nxll
==
NULL
||
nxl
==
NULL
||
nxr
==
NULL
||
nx
==
NULL
)
{
if
(
nxll
)
FreeNode
(
nxll
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
RetireNode
(
ux
);
RetireNode
(
uxl
);
RetireNode
(
uxr
);
RetireNode
(
uxrl
);
return
true
;
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
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
;
}
bool
W6_R
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxr
,
const
NodePtr
&
uxlr
)
{
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
)
{
NodePtr
nxrr
=
node_pool_
.
Allocate
(
uxr
->
GetKey
(),
uxr
->
GetValue
(),
uxr
->
GetWeight
()
-
1
,
...
...
@@ -806,32 +897,37 @@ bool W6_R(const NodePtr& u,
ux
->
GetWeight
(),
nxl
,
nxr
);
if
(
nxrr
==
NULL
||
nxr
==
NULL
||
nxl
==
NULL
||
if
(
nxrr
==
NULL
||
nxr
==
NULL
||
nxl
==
NULL
||
nx
==
NULL
)
{
if
(
nxrr
)
FreeNode
(
nxrr
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
RetireNode
(
ux
);
RetireNode
(
uxl
);
RetireNode
(
uxr
);
RetireNode
(
uxlr
);
return
true
;
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
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
;
}
bool
W7
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxr
)
{
embb_errors_t
W7
(
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
,
HazardNodePtr
&
uxr
,
UniqueLock
&
uxr_lock
)
{
NodePtr
nxl
=
node_pool_
.
Allocate
(
uxl
->
GetKey
(),
uxl
->
GetValue
(),
uxl
->
GetWeight
()
-
1
,
...
...
@@ -845,23 +941,27 @@ bool W7(const NodePtr& u,
HasFixedWeight
(
ux
)
?
1
:
ux
->
GetWeight
()
+
1
,
nxl
,
nxr
);
if
(
nxl
==
NULL
||
nxr
==
NULL
||
if
(
nxl
==
NULL
||
nxr
==
NULL
||
nx
==
NULL
)
{
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
nx
);
assert
(
rotation_succeeded
);
// For now (FGL tree) this CAS may not fail
if
(
!
rotation_succeeded
)
return
EMBB_BUSY
;
RetireNode
(
ux
);
RetireNode
(
uxl
);
RetireNode
(
uxr
);
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
true
;
return
EMBB_SUCCESS
;
}
#endif // EMBB_CONTAINERS_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_
containers_cpp/include/embb/containers/lock_free_chromatic_tree.h
View file @
2f75565c
...
...
@@ -30,6 +30,7 @@
#include <stddef.h>
#include <functional>
#include <embb/base/c/errors.h>
#include <embb/base/mutex.h>
#include <embb/containers/internal/hazard_pointer.h>
...
...
@@ -70,6 +71,7 @@ class ChromaticTreeNode {
*
* \param[IN] key Key of the new node
* \param[IN] value Value of the new node
* \param[IN] weight Weight of the new node
*/
ChromaticTreeNode
(
const
Key
&
key
,
const
Value
&
value
,
const
int
weight
=
1
);
...
...
@@ -126,6 +128,75 @@ class ChromaticTreeNode {
embb
::
base
::
Mutex
mutex_
;
};
template
<
typename
GuardedType
>
class
UniqueHazardGuard
{
public
:
typedef
embb
::
base
::
Atomic
<
GuardedType
>
AtomicGuard
;
UniqueHazardGuard
(
AtomicGuard
&
guard
,
const
GuardedType
&
undefined_guard
)
:
guard_
(
guard
),
undefined_guard_
(
undefined_guard
),
active_
(
guard_
.
Load
()
==
undefined_guard_
)
{}
~
UniqueHazardGuard
()
{
if
(
active_
)
SetUndefinedGuard
();
}
bool
ProtectHazard
(
const
AtomicGuard
&
hazard
)
{
// Read the hazard and store it into the guard
guard_
=
hazard
.
Load
();
// Check whether the guard is valid
active_
=
(
guard_
.
Load
()
==
hazard
.
Load
());
// Clear the guard if it is invalid
if
(
!
active_
)
SetUndefinedGuard
();
return
active_
;
}
bool
IsActive
()
const
{
return
active_
;
}
operator
GuardedType
()
const
{
assert
(
active_
==
true
);
return
guard_
.
Load
();
}
GuardedType
operator
->
()
const
{
assert
(
active_
==
true
);
return
guard_
.
Load
();
}
void
AdoptGuard
(
const
UniqueHazardGuard
<
GuardedType
>&
other
)
{
guard_
=
other
.
guard_
.
Load
();
active_
=
other
.
active_
;
}
GuardedType
ReleaseHazard
()
{
assert
(
active_
==
true
);
GuardedType
released_hazard
=
guard_
.
Load
();
SetUndefinedGuard
();
active_
=
false
;
return
released_hazard
;
}
private
:
void
SetUndefinedGuard
()
{
guard_
=
undefined_guard_
;
}
// Non-copyable
UniqueHazardGuard
(
const
UniqueHazardGuard
<
GuardedType
>&
);
UniqueHazardGuard
<
GuardedType
>&
operator
=
(
const
UniqueHazardGuard
<
GuardedType
>&
);
AtomicGuard
&
guard_
;
GuardedType
undefined_guard_
;
bool
active_
;
};
}
// namespace internal
namespace
test
{
...
...
@@ -301,29 +372,20 @@ class ChromaticTree {
*/
typedef
embb
::
base
::
Atomic
<
NodePtr
>
AtomicNodePtr
;
typedef
internal
::
UniqueHazardGuard
<
NodePtr
>
HazardNodePtr
;
typedef
embb
::
base
::
UniqueLock
<
embb
::
base
::
Mutex
>
UniqueLock
;
/**
* Follows a path from the root of the tree to some leaf searching for the
* given key (the leaf found by this method may or may not contain the given
* key). Returns the reached leaf.
*
* \param[IN] key Key to be searched for
* \param[IN,OUT] leaf Reference to the reached leaf
*/
void
Search
(
const
Key
&
key
,
NodePtr
&
leaf
);
/**
* Follows a path from the root of the tree to some leaf searching for the
* given key (the leaf found by this method may or may not contain the given
* key). Returns the reached leaf together with its ancestors.
*
* \param[IN] key Key to be searched for
* \param[IN,OUT] leaf Reference to the reached leaf
* \param[IN,OUT] parent Reference to the parent of the reached leaf
*/
void
Search
(
const
Key
&
key
,
NodePtr
&
leaf
,
NodePtr
&
parent
);
void
Search
(
const
Key
&
key
,
HazardNodePtr
&
leaf
,
Hazard
NodePtr
&
parent
);
/**
* Follows a path from the root of the tree to some leaf searching for the
...
...
@@ -335,8 +397,8 @@ class ChromaticTree {
* \param[IN,OUT] parent Reference to the parent of the reached leaf
* \param[IN,OUT] grandparent Reference to the grandparent of the reached leaf
*/
void
Search
(
const
Key
&
key
,
NodePtr
&
leaf
,
NodePtr
&
parent
,
NodePtr
&
grandparent
);
void
Search
(
const
Key
&
key
,
HazardNodePtr
&
leaf
,
Hazard
NodePtr
&
parent
,
Hazard
NodePtr
&
grandparent
);
/**
* Checks whether the given node is a leaf.
...
...
@@ -415,8 +477,11 @@ class ChromaticTree {
bool
IsBalanced
()
const
;
bool
IsBalanced
(
const
NodePtr
&
node
)
const
;
void
RemoveNode
(
const
NodePtr
&
node
)
{
node_hazard_manager_
.
EnqueuePointerForDeletion
(
node
);
void
RetireHazardousNode
(
HazardNodePtr
&
node
,
UniqueLock
&
node_lock
)
{
node
->
Retire
();
node_lock
.
Unlock
();
NodePtr
node_to_delete
=
node
.
ReleaseHazard
();
node_hazard_manager_
.
EnqueuePointerForDeletion
(
node_to_delete
);
}
/**
...
...
@@ -440,16 +505,22 @@ class ChromaticTree {
/**
* Next block of methods is used internally to keep the balance of the tree.
*/
bool
Rebalance
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxx
,
const
NodePtr
&
uxxx
);
bool
OverweightLeft
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxx
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxr
,
const
NodePtr
&
uxxl
,
const
NodePtr
&
uxxr
,
const
bool
&
uxx_is_left
);
bool
OverweightRight
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxx
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxr
,
const
NodePtr
&
uxxl
,
const
NodePtr
&
uxxr
,
const
bool
&
uxx_is_right
);
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
,
HazardNodePtr
&
uxl
,
HazardNodePtr
&
uxr
,
HazardNodePtr
&
uxxl
,
UniqueLock
&
uxxl_lock
,
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
,
HazardNodePtr
&
uxl
,
HazardNodePtr
&
uxr
,
HazardNodePtr
&
uxxl
,
HazardNodePtr
&
uxxr
,
UniqueLock
&
uxxr_lock
,
bool
uxx_is_right
);
// The following included header contains the class methods implementing
// tree rotations. It is generated automatically and must be included
...
...
@@ -466,7 +537,7 @@ class ChromaticTree {
const
Compare
compare_
;
/**< Comparator object for the keys */
size_t
capacity_
;
/**< User-requested capacity of the tree */
NodePool
node_pool_
;
/**< Comparator object for the keys */
NodePtr
entry_
;
/**< Pointer to the sentinel node used as
AtomicNodePtr
entry_
;
/**< Pointer to the sentinel node used as
* the entry point into the tree */
/**
...
...
containers_cpp/test/tree_test-inl.h
View file @
2f75565c
...
...
@@ -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
>
...
...
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