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() {
...
@@ -182,7 +182,9 @@ HazardPointerThreadEntry<GuardType>::~HazardPointerThreadEntry() {
}
}
template
<
typename
GuardType
>
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
];
return
guarded_pointers
[
pos
];
}
}
...
@@ -393,6 +395,12 @@ void HazardPointer< GuardType >::GuardPointer(int guardPosition,
...
@@ -393,6 +395,12 @@ void HazardPointer< GuardType >::GuardPointer(int guardPosition,
}
}
template
<
typename
GuardType
>
template
<
typename
GuardType
>
typename
HazardPointer
<
GuardType
>::
AtomicGuard
&
HazardPointer
<
GuardType
>::
GetGuardedPointer
(
int
guardPosition
)
{
return
GetHazardPointerElementForCurrentThread
().
GetGuard
(
guardPosition
);
}
template
<
typename
GuardType
>
void
HazardPointer
<
GuardType
>::
EnqueuePointerForDeletion
(
void
HazardPointer
<
GuardType
>::
EnqueuePointerForDeletion
(
GuardType
guardedElement
)
{
GuardType
guardedElement
)
{
GetHazardPointerElementForCurrentThread
().
AddRetired
(
guardedElement
);
GetHazardPointerElementForCurrentThread
().
AddRetired
(
guardedElement
);
...
...
containers_cpp/include/embb/containers/internal/hazard_pointer.h
View file @
2f75565c
...
@@ -238,6 +238,8 @@ class HazardPointerThreadEntry {
...
@@ -238,6 +238,8 @@ class HazardPointerThreadEntry {
HazardPointerThreadEntry
&
operator
=
(
const
HazardPointerThreadEntry
&
);
HazardPointerThreadEntry
&
operator
=
(
const
HazardPointerThreadEntry
&
);
public
:
public
:
typedef
embb
::
base
::
Atomic
<
GuardType
>
AtomicGuard
;
/**
/**
* Checks if current thread is active (with respect to participating in hazard
* Checks if current thread is active (with respect to participating in hazard
* pointer management)
* pointer management)
...
@@ -318,7 +320,7 @@ class HazardPointerThreadEntry {
...
@@ -318,7 +320,7 @@ class HazardPointerThreadEntry {
* Gets the guard at the specified position.
* Gets the guard at the specified position.
* Positions are numbered, beginning with 0.
* Positions are numbered, beginning with 0.
*/
*/
GuardType
GetGuard
(
AtomicGuard
&
GetGuard
(
int
pos
int
pos
/**< [IN] Position of the guard */
)
const
;
/**< [IN] Position of the guard */
)
const
;
...
@@ -467,6 +469,8 @@ class HazardPointer {
...
@@ -467,6 +469,8 @@ class HazardPointer {
can be deleted*/
);
can be deleted*/
);
public
:
public
:
typedef
typename
HazardPointerThreadEntry_t
::
AtomicGuard
AtomicGuard
;
/**
/**
* Gets the capacity of one retired list
* Gets the capacity of one retired list
*
*
...
@@ -516,6 +520,9 @@ class HazardPointer {
...
@@ -516,6 +520,9 @@ class HazardPointer {
* Guards \c guardedElement with the guard at position \c guardPosition
* Guards \c guardedElement with the guard at position \c guardPosition
*/
*/
void
GuardPointer
(
int
guardPosition
,
GuardType
guardedElement
);
void
GuardPointer
(
int
guardPosition
,
GuardType
guardedElement
);
AtomicGuard
&
GetGuardedPointer
(
int
guardPosition
);
/**
/**
* Enqueue a pointer for deletion. It is added to the retired list and
* Enqueue a pointer for deletion. It is added to the retired list and
* deleted when no thread accesses it anymore.
* 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,
...
@@ -105,7 +105,7 @@ ChromaticTree(size_t capacity, Key undefined_key, Value undefined_value,
#ifdef EMBB_PLATFORM_COMPILER_MSVC
#ifdef EMBB_PLATFORM_COMPILER_MSVC
#pragma warning(pop)
#pragma warning(pop)
#endif
#endif
node_hazard_manager_
(
free_node_callback_
,
NULL
,
8
),
node_hazard_manager_
(
free_node_callback_
,
NULL
,
10
),
undefined_key_
(
undefined_key
),
undefined_key_
(
undefined_key
),
undefined_value_
(
undefined_value
),
undefined_value_
(
undefined_value
),
compare_
(
compare
),
compare_
(
compare
),
...
@@ -128,8 +128,9 @@ ChromaticTree<Key, Value, Compare, NodePool>::
...
@@ -128,8 +128,9 @@ ChromaticTree<Key, Value, Compare, NodePool>::
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
bool
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
bool
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
Get
(
const
Key
&
key
,
Value
&
value
)
{
Get
(
const
Key
&
key
,
Value
&
value
)
{
NodePtr
leaf
;
HazardNodePtr
parent
(
node_hazard_manager_
.
GetGuardedPointer
(
0
),
NULL
);
Search
(
key
,
leaf
);
HazardNodePtr
leaf
(
node_hazard_manager_
.
GetGuardedPointer
(
1
),
NULL
);
Search
(
key
,
leaf
,
parent
);
bool
keys_are_equal
=
!
IsSentinel
(
leaf
)
&&
bool
keys_are_equal
=
!
IsSentinel
(
leaf
)
&&
!
(
compare_
(
key
,
leaf
->
GetKey
())
||
!
(
compare_
(
key
,
leaf
->
GetKey
())
||
...
@@ -139,8 +140,6 @@ Get(const Key& key, Value& value) {
...
@@ -139,8 +140,6 @@ Get(const Key& key, Value& value) {
value
=
leaf
->
GetValue
();
value
=
leaf
->
GetValue
();
}
}
node_hazard_manager_
.
GuardPointer
(
0
,
NULL
);
return
keys_are_equal
;
return
keys_are_equal
;
}
}
...
@@ -158,9 +157,11 @@ TryInsert(const Key& key, const Value& value, Value& old_value) {
...
@@ -158,9 +157,11 @@ TryInsert(const Key& key, const Value& value, Value& old_value) {
NodePtr
new_sibling
=
NULL
;
NodePtr
new_sibling
=
NULL
;
NodePtr
new_parent
=
NULL
;
NodePtr
new_parent
=
NULL
;
bool
insertion_succeeded
=
false
;
bool
insertion_succeeded
=
false
;
bool
added_violation
=
false
;
while
(
!
insertion_succeeded
)
{
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
);
Search
(
key
,
leaf
,
parent
);
// Try to lock the parent
// Try to lock the parent
...
@@ -200,23 +201,21 @@ TryInsert(const Key& key, const Value& value, Value& old_value) {
...
@@ -200,23 +201,21 @@ TryInsert(const Key& key, const Value& value, Value& old_value) {
if
(
new_parent
==
NULL
)
break
;
if
(
new_parent
==
NULL
)
break
;
}
}
GetPointerToChild
(
parent
,
leaf
).
CompareAndSwap
(
leaf
,
new_parent
);
NodePtr
expected
=
leaf
;
insertion_succeeded
=
GetPointerToChild
(
parent
,
leaf
)
insertion_succeeded
=
true
;
.
CompareAndSwap
(
expected
,
new_parent
);
assert
(
insertion_succeeded
);
// For now (FGL tree) this CAS may not fail
if
(
!
insertion_succeeded
)
continue
;
leaf
->
Retire
();
RetireHazardousNode
(
leaf
,
leaf_lock
);
leaf_lock
.
Unlock
();
node_hazard_manager_
.
GuardPointer
(
1
,
NULL
);
RemoveNode
(
leaf
);
// if (parent->GetWeight() == 0 && new_parent->GetWeight() == 0) {
added_violation
=
(
parent
->
GetWeight
()
==
0
&&
// CleanUp(key);
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_leaf
!=
NULL
)
FreeNode
(
new_leaf
);
if
(
new_sibling
!=
NULL
)
FreeNode
(
new_sibling
);
if
(
new_sibling
!=
NULL
)
FreeNode
(
new_sibling
);
if
(
new_parent
!=
NULL
)
FreeNode
(
new_parent
);
if
(
new_parent
!=
NULL
)
FreeNode
(
new_parent
);
...
@@ -237,9 +236,12 @@ bool ChromaticTree<Key, Value, Compare, NodePool>::
...
@@ -237,9 +236,12 @@ bool ChromaticTree<Key, Value, Compare, NodePool>::
TryDelete
(
const
Key
&
key
,
Value
&
old_value
)
{
TryDelete
(
const
Key
&
key
,
Value
&
old_value
)
{
NodePtr
new_leaf
=
NULL
;
NodePtr
new_leaf
=
NULL
;
bool
deletion_succeeded
=
false
;
bool
deletion_succeeded
=
false
;
bool
added_violation
=
false
;
while
(
!
deletion_succeeded
)
{
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
);
Search
(
key
,
leaf
,
parent
,
grandparent
);
// Reached leaf has a different key - nothing to delete
// Reached leaf has a different key - nothing to delete
...
@@ -259,16 +261,17 @@ TryDelete(const Key& key, Value& old_value) {
...
@@ -259,16 +261,17 @@ TryDelete(const Key& key, Value& old_value) {
// Try to lock the parent
// Try to lock the parent
UniqueLock
parent_lock
(
parent
->
GetMutex
(),
embb
::
base
::
try_lock
);
UniqueLock
parent_lock
(
parent
->
GetMutex
(),
embb
::
base
::
try_lock
);
if
(
!
parent_lock
.
OwnsLock
()
||
parent
->
IsRetired
())
continue
;
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
// Verify that the leaf is still the parent's child
if
(
!
HasChild
(
parent
,
leaf
))
continue
;
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
// Try to lock the sibling
UniqueLock
sibling_lock
(
sibling
->
GetMutex
(),
embb
::
base
::
try_lock
);
UniqueLock
sibling_lock
(
sibling
->
GetMutex
(),
embb
::
base
::
try_lock
);
if
(
!
sibling_lock
.
OwnsLock
()
||
sibling
->
IsRetired
())
continue
;
if
(
!
sibling_lock
.
OwnsLock
()
||
sibling
->
IsRetired
())
continue
;
...
@@ -287,33 +290,22 @@ TryDelete(const Key& key, Value& old_value) {
...
@@ -287,33 +290,22 @@ TryDelete(const Key& key, Value& old_value) {
old_value
=
leaf
->
GetValue
();
old_value
=
leaf
->
GetValue
();
GetPointerToChild
(
grandparent
,
parent
).
CompareAndSwap
(
parent
,
new_leaf
);
NodePtr
expected
=
parent
;
deletion_succeeded
=
GetPointerToChild
(
grandparent
,
parent
)
deletion_succeeded
=
true
;
.
CompareAndSwap
(
expected
,
new_leaf
);
assert
(
deletion_succeeded
);
// For now (FGL tree) this CAS may not fail
parent
->
Retire
();
if
(
!
deletion_succeeded
)
continue
;
parent_lock
.
Unlock
();
node_hazard_manager_
.
GuardPointer
(
1
,
NULL
);
RetireHazardousNode
(
parent
,
parent_lock
);
RemoveNode
(
parent
);
RetireHazardousNode
(
leaf
,
leaf_lock
);
leaf
->
Retire
();
RetireHazardousNode
(
sibling
,
sibling_lock
);
leaf_lock
.
Unlock
();
node_hazard_manager_
.
GuardPointer
(
2
,
NULL
);
added_violation
=
(
new_weight
>
1
);
RemoveNode
(
leaf
);
sibling
->
Retire
();
sibling_lock
.
Unlock
();
node_hazard_manager_
.
GuardPointer
(
3
,
NULL
);
RemoveNode
(
sibling
);
// if (new_weight > 1) {
// CleanUp(key);
// }
}
}
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
);
if
(
new_leaf
!=
NULL
)
FreeNode
(
new_leaf
);
}
}
...
@@ -340,39 +332,22 @@ IsEmpty() {
...
@@ -340,39 +332,22 @@ IsEmpty() {
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
void
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
void
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
Search
(
const
Key
&
key
,
NodePtr
&
leaf
)
{
Search
(
const
Key
&
key
,
HazardNodePtr
&
leaf
,
HazardNodePtr
&
parent
)
{
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
)
{
bool
reached_leaf
=
false
;
bool
reached_leaf
=
false
;
while
(
!
reached_leaf
)
{
while
(
!
reached_leaf
)
{
parent
=
entry_
;
parent
.
ProtectHazard
(
entry_
);
node_hazard_manager_
.
GuardPointer
(
0
,
parent
);
leaf
.
ProtectHazard
(
entry_
->
GetLeft
());
if
(
parent
->
IsRetired
()
||
!
leaf
.
IsActive
())
continue
;
leaf
=
entry_
->
GetLeft
();
node_hazard_manager_
.
GuardPointer
(
1
,
leaf
);
if
(
leaf
!=
entry_
->
GetLeft
())
continue
;
reached_leaf
=
IsLeaf
(
leaf
);
reached_leaf
=
IsLeaf
(
leaf
);
while
(
!
reached_leaf
)
{
while
(
!
reached_leaf
)
{
parent
=
leaf
;
parent
.
AdoptGuard
(
leaf
);
node_hazard_manager_
.
GuardPointer
(
0
,
parent
);
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
);
reached_leaf
=
IsLeaf
(
leaf
);
}
}
}
}
...
@@ -380,35 +355,25 @@ Search(const Key& key, NodePtr& leaf, NodePtr& parent) {
...
@@ -380,35 +355,25 @@ Search(const Key& key, NodePtr& leaf, NodePtr& parent) {
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
void
ChromaticTree
<
Key
,
Value
,
Compare
,
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
;
bool
reached_leaf
=
false
;
while
(
!
reached_leaf
)
{
while
(
!
reached_leaf
)
{
grandparent
=
NULL
;
grandparent
.
ProtectHazard
(
entry_
);
parent
.
ProtectHazard
(
entry_
);
parent
=
entry_
;
leaf
.
ProtectHazard
(
entry_
->
GetLeft
());
node_hazard_manager_
.
GuardPointer
(
1
,
parent
);
if
(
parent
->
IsRetired
()
||
!
leaf
.
IsActive
())
continue
;
leaf
=
entry_
->
GetLeft
();
node_hazard_manager_
.
GuardPointer
(
2
,
leaf
);
if
(
leaf
!=
entry_
->
GetLeft
())
continue
;
reached_leaf
=
IsLeaf
(
leaf
);
reached_leaf
=
IsLeaf
(
leaf
);
while
(
!
reached_leaf
)
{
while
(
!
reached_leaf
)
{
grandparent
=
parent
;
grandparent
.
AdoptGuard
(
parent
);
node_hazard_manager_
.
GuardPointer
(
0
,
grandparent
);
parent
.
AdoptGuard
(
leaf
);
leaf
.
ProtectHazard
((
IsSentinel
(
leaf
)
||
compare_
(
key
,
leaf
->
GetKey
()))
?
parent
=
leaf
;
leaf
->
GetLeft
()
:
leaf
->
GetRight
());
node_hazard_manager_
.
GuardPointer
(
1
,
parent
);
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
(
2
,
leaf
);
if
(
leaf
!=
next_leaf
||
parent
->
IsRetired
())
break
;
VERIFY_ADDRESS
(
leaf
);
reached_leaf
=
IsLeaf
(
leaf
);
reached_leaf
=
IsLeaf
(
leaf
);
}
}
}
}
...
@@ -423,13 +388,15 @@ IsLeaf(const NodePtr& node) const {
...
@@ -423,13 +388,15 @@ IsLeaf(const NodePtr& node) const {
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
bool
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
bool
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
IsSentinel
(
const
NodePtr
&
node
)
const
{
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
>
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
bool
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
bool
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
HasFixedWeight
(
const
NodePtr
&
node
)
const
{
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
>
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
...
@@ -470,7 +437,8 @@ GetHeight(const NodePtr& node) const {
...
@@ -470,7 +437,8 @@ GetHeight(const NodePtr& node) const {
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
bool
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
bool
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
IsBalanced
()
const
{
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
>
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
...
@@ -509,92 +477,137 @@ FreeNode(NodePtr node) {
...
@@ -509,92 +477,137 @@ FreeNode(NodePtr node) {
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
bool
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
bool
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
CleanUp
(
const
Key
&
key
)
{
CleanUp
(
const
Key
&
key
)
{
for
(;;)
{
HazardNodePtr
grangranparent
(
node_hazard_manager_
.
GetGuardedPointer
(
0
),
NULL
);
NodePtr
grandgrandparent
=
NULL
;
HazardNodePtr
grandparent
(
node_hazard_manager_
.
GetGuardedPointer
(
1
),
NULL
);
NodePtr
grandparent
=
NULL
;
HazardNodePtr
parent
(
node_hazard_manager_
.
GetGuardedPointer
(
2
),
NULL
);
NodePtr
parent
=
entry_
;
HazardNodePtr
leaf
(
node_hazard_manager_
.
GetGuardedPointer
(
3
),
NULL
);
NodePtr
leaf
=
entry_
->
GetLeft
();
bool
reached_leaf
=
false
;
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
);
}
if
(
leaf
->
GetWeight
()
==
1
)
{
while
(
!
reached_leaf
)
{
break
;
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
))
{
if
(
found_violation
)
{
return
false
;
reached_leaf
=
false
;
if
(
Rebalance
(
grangranparent
,
grandparent
,
parent
,
leaf
)
==
EMBB_NOMEM
)
{
assert
(
false
&&
"No memory for rebalancing!"
);
return
false
;
}
}
}
}
}
return
true
;
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
>
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
bool
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
embb_errors_t
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
Rebalance
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxx
,
Rebalance
(
HazardNodePtr
&
u
,
HazardNodePtr
&
ux
,
HazardNodePtr
&
uxx
,
const
NodePtr
&
uxxx
)
{
HazardNodePtr
&
uxxx
)
{
//TODO: weakLLX(u);
// Protect node 'u'
if
(
!
HasChild
(
u
,
ux
))
return
false
;
PROTECT_NODE_WITH_LOCK
(
u
,
u_lock
);
// Verify that ux is still a child of u
//TODO: weakLLX(ux);
if
(
!
HasChild
(
u
,
ux
))
return
EMBB_BUSY
;
NodePtr
uxl
=
ux
->
GetLeft
();
VERIFY_ADDRESS
(
uxl
);
NodePtr
uxr
=
ux
->
GetRight
();
VERIFY_ADDRESS
(
uxr
);
// Protect node 'ux'
bool
uxx_is_left
=
(
uxx
==
uxl
);
PROTECT_NODE_WITH_LOCK
(
ux
,
ux_lock
);
if
(
!
HasChild
(
ux
,
uxx
))
return
false
;
// Get children of 'ux'
DEFINE_NODE_WITH_HAZARD
(
4
,
uxl
,
ux
,
GetLeft
);
//TODO: weakLLX(uxx);
DEFINE_NODE_WITH_HAZARD
(
5
,
uxr
,
ux
,
GetRight
);
NodePtr
uxxl
=
uxx
->
GetLeft
();
VERIFY_ADDRESS
(
uxxl
);
// Verify that 'uxx' is still a child of 'ux'
NodePtr
uxxr
=
uxx
->
GetRight
();
VERIFY_ADDRESS
(
uxxr
);
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
);
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
->
GetWeight
()
>
1
)
{
if
(
uxxx_is_left
)
{
if
(
uxxx_is_left
)
{
//TODO: weakLLX(uxxl);
// Protect node 'uxxl'
return
OverweightLeft
(
u
,
ux
,
uxx
,
uxl
,
uxr
,
uxxl
,
uxxr
,
uxx_is_left
);
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
{
}
else
{
//TODO: weakLLX(uxxr);
// Protect node 'uxxr'
return
OverweightRight
(
u
,
ux
,
uxx
,
uxl
,
uxr
,
uxxl
,
uxxr
,
!
uxx_is_left
);
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
{
}
else
{
assert
(
uxxx
->
GetWeight
()
==
0
&&
uxx
->
GetWeight
()
==
0
);
//Red-red violation
if
(
uxx_is_left
)
{
if
(
uxx_is_left
)
{
if
(
uxr
->
GetWeight
()
==
0
)
{
if
(
uxr
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxr);
// Protect node 'uxr'
return
BLK
(
u
,
ux
,
uxx
,
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
)
{
}
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
{
}
else
{
//TODO: weakLLX(uxxr);
// Protect node 'uxxr'
return
RB2_L
(
u
,
ux
,
uxx
,
uxxr
);
PROTECT_NODE_WITH_LOCK
(
uxxr
,
uxxr_lock
);
return
RB2_L
(
u
,
u_lock
,
ux
,
ux_lock
,
uxx
,
uxx_lock
,
uxxr
,
uxxr_lock
);
}
}
}
else
{
}
else
{
if
(
uxl
->
GetWeight
()
==
0
)
{
if
(
uxl
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxl);
// Protect node 'uxl'
return
BLK
(
u
,
ux
,
uxl
,
uxx
);
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
)
{
}
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
{
}
else
{
//TODO: weakLLX(uxxl);
// Protect node 'uxxl'
return
RB2_R
(
u
,
ux
,
uxx
,
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
>
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
bool
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
embb_errors_t
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
OverweightLeft
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxx
,
OverweightLeft
(
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxr
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
const
NodePtr
&
uxxl
,
const
NodePtr
&
uxxr
,
HazardNodePtr
&
uxx
,
UniqueLock
&
uxx_lock
,
const
bool
&
uxx_is_left
)
{
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)
// Let "Root" be the top of the overweight violation decision tree (see p.30)
// Root -> Middle
// Root -> Middle
if
(
uxxr
->
GetWeight
()
==
0
)
{
if
(
uxxr
->
GetWeight
()
==
0
)
{
...
@@ -604,14 +617,16 @@ OverweightLeft(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
...
@@ -604,14 +617,16 @@ OverweightLeft(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
if
(
uxx_is_left
)
{
if
(
uxx_is_left
)
{
// Root -> Middle -> Left -> Left -> Left
// Root -> Middle -> Left -> Left -> Left
if
(
uxr
->
GetWeight
()
==
0
)
{
if
(
uxr
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxr);
// Protect node 'uxr'
return
BLK
(
u
,
ux
,
uxx
,
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
// Root -> Middle -> Left -> Left -> Right
}
else
{
}
else
{
assert
(
uxr
->
GetWeight
()
>
0
);
assert
(
uxr
->
GetWeight
()
>
0
);
//TODO: weakLLX(uxxr);
// Protect node 'uxxr'
return
RB2_L
(
u
,
ux
,
uxx
,
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
// Root -> Middle -> Left -> Right
...
@@ -619,102 +634,126 @@ OverweightLeft(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
...
@@ -619,102 +634,126 @@ OverweightLeft(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
assert
(
!
uxx_is_left
);
assert
(
!
uxx_is_left
);
// Root -> Middle -> Left -> Right -> Left
// Root -> Middle -> Left -> Right -> Left
if
(
uxl
->
GetWeight
()
==
0
)
{
if
(
uxl
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxl);
// Protect node 'uxl'
return
BLK
(
u
,
ux
,
uxl
,
uxx
);
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
// Root -> Middle -> Left -> Right -> Right
}
else
{
}
else
{
assert
(
uxl
->
GetWeight
()
>
0
);
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
// Root -> Middle -> Right
}
else
{
}
else
{
assert
(
uxx
->
GetWeight
()
>
0
);
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.
// Note: we know that 'uxxr' is not a leaf because it has weight 0.
NodePtr
uxxrl
=
uxxr
->
GetLeft
();
VERIFY_ADDRESS
(
uxxrl
);
DEFINE_NODE_WITH_HAZARD
(
8
,
uxxrl
,
uxxr
,
GetLeft
);
//TODO: weakLLX(uxxrl);
// Protect node 'uxxrl'
PROTECT_NODE_WITH_LOCK
(
uxxrl
,
uxxrl_lock
);
// Root -> Middle -> Right -> Left
// Root -> Middle -> Right -> Left
if
(
uxxrl
->
GetWeight
()
==
0
)
{
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
// Root -> Middle -> Right -> Middle
}
else
if
(
uxxrl
->
GetWeight
()
==
1
)
{
}
else
if
(
uxxrl
->
GetWeight
()
==
1
)
{
NodePtr
uxxrll
=
uxxrl
->
GetLeft
();
VERIFY_ADDRESS
(
uxxrll
);
DEFINE_NODE_WITH_HAZARD
(
9
,
uxxrlr
,
uxxrl
,
GetRight
);
NodePtr
uxxrlr
=
uxxrl
->
GetRight
();
VERIFY_ADDRESS
(
uxxrlr
);
if
(
uxxrlr
==
NULL
)
return
EMBB_BUSY
;
if
(
uxxrlr
==
NULL
)
return
false
;
// Root -> Middle -> Right -> Middle -> Left
// Root -> Middle -> Right -> Middle -> Left
if
(
uxxrlr
->
GetWeight
()
==
0
)
{
if
(
uxxrlr
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxxrlr);
// Protect node 'uxxrlr'
return
W4_L
(
ux
,
uxx
,
uxxl
,
uxxr
,
uxxrl
,
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
// Root -> Middle -> Right -> Middle -> Right
}
else
{
}
else
{
assert
(
uxxrlr
->
GetWeight
()
>
0
);
assert
(
uxxrlr
->
GetWeight
()
>
0
);
// Root -> Middle -> Right -> Middle -> Right -> Left
// Root -> Middle -> Right -> Middle -> Right -> Left
// Node: reusing hazard of node 'uxxrlr' as it is no longer used
DEFINE_NODE_WITH_HAZARD
(
9
,
uxxrll
,
uxxrl
,
GetLeft
);
if
(
uxxrll
->
GetWeight
()
==
0
)
{
if
(
uxxrll
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxxrll);
// Protect node 'uxxrll'
return
W3_L
(
ux
,
uxx
,
uxxl
,
uxxr
,
uxxrl
,
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
// Root -> Middle -> Right -> Middle -> Right -> Right
}
else
{
}
else
{
assert
(
uxxrll
->
GetWeight
()
>
0
);
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
// Root -> Middle -> Right -> Right
}
else
{
}
else
{
assert
(
uxxrl
->
GetWeight
()
>
1
);
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
// Root -> Right
}
else
if
(
uxxr
->
GetWeight
()
==
1
)
{
}
else
if
(
uxxr
->
GetWeight
()
==
1
)
{
//TODO: weakLLX(uxxr);
// Protect node 'uxxr'
NodePtr
uxxrl
=
uxxr
->
GetLeft
();
VERIFY_ADDRESS
(
uxxrl
);
PROTECT_NODE_WITH_LOCK
(
uxxr
,
uxxr_lock
);
NodePtr
uxxrr
=
uxxr
->
GetRight
();
VERIFY_ADDRESS
(
uxxrr
);
// Get children of 'uxxr'
if
(
uxxrl
==
NULL
)
return
false
;
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
// Root -> Right -> Left
if
(
uxxrr
->
GetWeight
()
==
0
)
{
if
(
uxxrr
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxxrr);
// Protect node 'uxxrr'
return
W5_L
(
ux
,
uxx
,
uxxl
,
uxxr
,
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
// Root -> Right -> Right
}
else
{
}
else
{
assert
(
uxxrr
->
GetWeight
()
>
0
);
assert
(
uxxrr
->
GetWeight
()
>
0
);
// Root -> Right -> Right -> Left
// Root -> Right -> Right -> Left
if
(
uxxrl
->
GetWeight
()
==
0
)
{
if
(
uxxrl
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxxrl);
// Protect node 'uxxrl'
return
W6_L
(
ux
,
uxx
,
uxxl
,
uxxr
,
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
// Root -> Right -> Right -> Right
}
else
{
}
else
{
assert
(
uxxrl
->
GetWeight
()
>
0
);
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
// Root -> Left
}
else
{
}
else
{
assert
(
uxxr
->
GetWeight
()
>
1
);
assert
(
uxxr
->
GetWeight
()
>
1
);
//TODO: weakLLX(uxxr);
// Protect node 'uxxr'
return
W7
(
ux
,
uxx
,
uxxl
,
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
>
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
bool
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
embb_errors_t
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
OverweightRight
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxx
,
OverweightRight
(
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxr
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
const
NodePtr
&
uxxl
,
const
NodePtr
&
uxxr
,
HazardNodePtr
&
uxx
,
UniqueLock
&
uxx_lock
,
const
bool
&
uxx_is_right
)
{
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)
// Let "Root" be the top of the overweight violation decision tree (see p.30)
// Root -> Middle
// Root -> Middle
if
(
uxxl
->
GetWeight
()
==
0
)
{
if
(
uxxl
->
GetWeight
()
==
0
)
{
...
@@ -724,14 +763,16 @@ OverweightRight(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
...
@@ -724,14 +763,16 @@ OverweightRight(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
if
(
uxx_is_right
)
{
if
(
uxx_is_right
)
{
// Root -> Middle -> Left -> Left -> Left
// Root -> Middle -> Left -> Left -> Left
if
(
uxl
->
GetWeight
()
==
0
)
{
if
(
uxl
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxl);
// Protect node 'uxl'
return
BLK
(
u
,
ux
,
uxl
,
uxx
);
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
// Root -> Middle -> Left -> Left -> Right
}
else
{
}
else
{
assert
(
uxl
->
GetWeight
()
>
0
);
assert
(
uxl
->
GetWeight
()
>
0
);
//TODO: weakLLX(uxxl);
// Protect node 'uxxl'
return
RB2_R
(
u
,
ux
,
uxx
,
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
// Root -> Middle -> Left -> Right
...
@@ -739,93 +780,115 @@ OverweightRight(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
...
@@ -739,93 +780,115 @@ OverweightRight(const NodePtr& u, const NodePtr& ux, const NodePtr& uxx,
assert
(
!
uxx_is_right
);
assert
(
!
uxx_is_right
);
// Root -> Middle -> Left -> Right -> Left
// Root -> Middle -> Left -> Right -> Left
if
(
uxr
->
GetWeight
()
==
0
)
{
if
(
uxr
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxr);
// Protect node 'uxr'
return
BLK
(
u
,
ux
,
uxx
,
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
// Root -> Middle -> Left -> Right -> Right
}
else
{
}
else
{
assert
(
uxr
->
GetWeight
()
>
0
);
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
// Root -> Middle -> Right
}
else
{
}
else
{
assert
(
uxx
->
GetWeight
()
>
0
);
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.
// Note: we know that 'uxxl' is not a leaf because it has weight 0.
NodePtr
uxxlr
=
uxxl
->
GetRight
();
VERIFY_ADDRESS
(
uxxlr
);
DEFINE_NODE_WITH_HAZARD
(
8
,
uxxlr
,
uxxl
,
GetRight
);
//TODO: weakLLX(uxxlr);
// Protect node 'uxxlr'
PROTECT_NODE_WITH_LOCK
(
uxxlr
,
uxxlr_lock
);
// Root -> Middle -> Right -> Left
// Root -> Middle -> Right -> Left
if
(
uxxlr
->
GetWeight
()
==
0
)
{
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
// Root -> Middle -> Right -> Middle
}
else
if
(
uxxlr
->
GetWeight
()
==
1
)
{
}
else
if
(
uxxlr
->
GetWeight
()
==
1
)
{
NodePtr
uxxlrl
=
uxxlr
->
GetLeft
();
VERIFY_ADDRESS
(
uxxlrl
);
DEFINE_NODE_WITH_HAZARD
(
9
,
uxxlrl
,
uxxlr
,
GetLeft
);
NodePtr
uxxlrr
=
uxxlr
->
GetRight
();
VERIFY_ADDRESS
(
uxxlrr
);
if
(
uxxlrl
==
NULL
)
return
EMBB_BUSY
;
if
(
uxxlrl
==
NULL
)
return
false
;
// Root -> Middle -> Right -> Middle -> Left
// Root -> Middle -> Right -> Middle -> Left
if
(
uxxlrl
->
GetWeight
()
==
0
)
{
if
(
uxxlrl
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxxlrl);
// Protect node 'uxxlrl'
return
W4_R
(
ux
,
uxx
,
uxxl
,
uxxr
,
uxxlr
,
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
// Root -> Middle -> Right -> Middle -> Right
}
else
{
}
else
{
assert
(
uxxlrl
->
GetWeight
()
>
0
);
assert
(
uxxlrl
->
GetWeight
()
>
0
);
// Root -> Middle -> Right -> Middle -> Right -> Left
// Root -> Middle -> Right -> Middle -> Right -> Left
// Node: reusing hazard of node 'uxxlrl' as it is no longer used
DEFINE_NODE_WITH_HAZARD
(
9
,
uxxlrr
,
uxxlr
,
GetRight
);
if
(
uxxlrr
->
GetWeight
()
==
0
)
{
if
(
uxxlrr
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxxlrr);
// Protect node 'uxxlrr'
return
W3_R
(
ux
,
uxx
,
uxxl
,
uxxr
,
uxxlr
,
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
// Root -> Middle -> Right -> Middle -> Right -> Right
}
else
{
}
else
{
assert
(
uxxlrr
->
GetWeight
()
>
0
);
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
// Root -> Middle -> Right -> Right
}
else
{
}
else
{
assert
(
uxxlr
->
GetWeight
()
>
1
);
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
// Root -> Right
}
else
if
(
uxxl
->
GetWeight
()
==
1
)
{
}
else
if
(
uxxl
->
GetWeight
()
==
1
)
{
//TODO: weakLLX(uxxl);
// Protect node 'uxxl'
NodePtr
uxxll
=
uxxl
->
GetLeft
();
VERIFY_ADDRESS
(
uxxll
);
PROTECT_NODE_WITH_LOCK
(
uxxl
,
uxxl_lock
);
NodePtr
uxxlr
=
uxxl
->
GetRight
();
VERIFY_ADDRESS
(
uxxlr
);
// Get children of 'uxxl'
if
(
uxxll
==
NULL
)
return
false
;
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
// Root -> Right -> Left
if
(
uxxll
->
GetWeight
()
==
0
)
{
if
(
uxxll
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxxll);
// Protect node 'uxxll'
return
W5_R
(
ux
,
uxx
,
uxxl
,
uxxr
,
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
// Root -> Right -> Right
}
else
{
}
else
{
assert
(
uxxll
->
GetWeight
()
>
0
);
assert
(
uxxll
->
GetWeight
()
>
0
);
// Root -> Right -> Right -> Left
// Root -> Right -> Right -> Left
if
(
uxxlr
->
GetWeight
()
==
0
)
{
if
(
uxxlr
->
GetWeight
()
==
0
)
{
//TODO: weakLLX(uxxlr);
// Protect node 'uxxlr'
return
W6_R
(
ux
,
uxx
,
uxxl
,
uxxr
,
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
// Root -> Right -> Right -> Right
}
else
{
}
else
{
assert
(
uxxlr
->
GetWeight
()
>
0
);
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
// Root -> Left
}
else
{
}
else
{
assert
(
uxxl
->
GetWeight
()
>
1
);
assert
(
uxxl
->
GetWeight
()
>
1
);
//TODO: weakLLX(uxxl);
// Protect node 'uxxl'
return
W7
(
ux
,
uxx
,
uxxl
,
uxxr
);
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 @@
...
@@ -32,10 +32,11 @@
#ifndef EMBB_CONTAINERS_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_
#ifndef EMBB_CONTAINERS_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_
#define EMBB_CONTAINERS_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_
#define EMBB_CONTAINERS_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_
bool
BLK
(
const
NodePtr
&
u
,
embb_errors_t
BLK
(
const
NodePtr
&
ux
,
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
const
NodePtr
&
uxl
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
const
NodePtr
&
uxr
)
{
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
,
HazardNodePtr
&
uxr
,
UniqueLock
&
uxr_lock
)
{
NodePtr
nxl
=
node_pool_
.
Allocate
(
NodePtr
nxl
=
node_pool_
.
Allocate
(
uxl
->
GetKey
(),
uxl
->
GetValue
(),
uxl
->
GetKey
(),
uxl
->
GetValue
(),
1
,
1
,
...
@@ -49,29 +50,34 @@ bool BLK(const NodePtr& u,
...
@@ -49,29 +50,34 @@ bool BLK(const NodePtr& u,
HasFixedWeight
(
ux
)
?
1
:
ux
->
GetWeight
()
-
1
,
HasFixedWeight
(
ux
)
?
1
:
ux
->
GetWeight
()
-
1
,
nxl
,
nxr
);
nxl
,
nxr
);
if
(
nxl
==
NULL
||
if
(
nxl
==
NULL
||
nxr
==
NULL
||
nxr
==
NULL
||
nx
==
NULL
)
{
nx
==
NULL
)
{
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nx
)
FreeNode
(
nx
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
}
NodePtr
expected
=
ux
;
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
);
RetireHazardousNode
(
ux
,
ux_lock
);
RetireNode
(
uxl
);
RetireHazardousNode
(
uxl
,
uxl_lock
);
RetireNode
(
uxr
);
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
,
embb_errors_t
PUSH_L
(
const
NodePtr
&
ux
,
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
const
NodePtr
&
uxl
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
const
NodePtr
&
uxr
)
{
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
,
HazardNodePtr
&
uxr
,
UniqueLock
&
uxr_lock
)
{
NodePtr
nxl
=
node_pool_
.
Allocate
(
NodePtr
nxl
=
node_pool_
.
Allocate
(
uxl
->
GetKey
(),
uxl
->
GetValue
(),
uxl
->
GetKey
(),
uxl
->
GetValue
(),
uxl
->
GetWeight
()
-
1
,
uxl
->
GetWeight
()
-
1
,
...
@@ -85,29 +91,34 @@ bool PUSH_L(const NodePtr& u,
...
@@ -85,29 +91,34 @@ bool PUSH_L(const NodePtr& u,
HasFixedWeight
(
ux
)
?
1
:
ux
->
GetWeight
()
+
1
,
HasFixedWeight
(
ux
)
?
1
:
ux
->
GetWeight
()
+
1
,
nxl
,
nxr
);
nxl
,
nxr
);
if
(
nxl
==
NULL
||
if
(
nxl
==
NULL
||
nxr
==
NULL
||
nxr
==
NULL
||
nx
==
NULL
)
{
nx
==
NULL
)
{
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nx
)
FreeNode
(
nx
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
}
NodePtr
expected
=
ux
;
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
);
RetireHazardousNode
(
ux
,
ux_lock
);
RetireNode
(
uxl
);
RetireHazardousNode
(
uxl
,
uxl_lock
);
RetireNode
(
uxr
);
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
,
embb_errors_t
PUSH_R
(
const
NodePtr
&
ux
,
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
const
NodePtr
&
uxl
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
const
NodePtr
&
uxr
)
{
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
,
HazardNodePtr
&
uxr
,
UniqueLock
&
uxr_lock
)
{
NodePtr
nxr
=
node_pool_
.
Allocate
(
NodePtr
nxr
=
node_pool_
.
Allocate
(
uxr
->
GetKey
(),
uxr
->
GetValue
(),
uxr
->
GetKey
(),
uxr
->
GetValue
(),
uxr
->
GetWeight
()
-
1
,
uxr
->
GetWeight
()
-
1
,
...
@@ -121,28 +132,33 @@ bool PUSH_R(const NodePtr& u,
...
@@ -121,28 +132,33 @@ bool PUSH_R(const NodePtr& u,
HasFixedWeight
(
ux
)
?
1
:
ux
->
GetWeight
()
+
1
,
HasFixedWeight
(
ux
)
?
1
:
ux
->
GetWeight
()
+
1
,
nxl
,
nxr
);
nxl
,
nxr
);
if
(
nxr
==
NULL
||
if
(
nxr
==
NULL
||
nxl
==
NULL
||
nxl
==
NULL
||
nx
==
NULL
)
{
nx
==
NULL
)
{
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nx
)
FreeNode
(
nx
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
}
NodePtr
expected
=
ux
;
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
);
RetireHazardousNode
(
ux
,
ux_lock
);
RetireNode
(
uxl
);
RetireHazardousNode
(
uxl
,
uxl_lock
);
RetireNode
(
uxr
);
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
,
embb_errors_t
RB1_L
(
const
NodePtr
&
ux
,
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
const
NodePtr
&
uxl
)
{
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
)
{
NodePtr
nxr
=
node_pool_
.
Allocate
(
NodePtr
nxr
=
node_pool_
.
Allocate
(
ux
->
GetKey
(),
ux
->
GetValue
(),
ux
->
GetKey
(),
ux
->
GetValue
(),
0
,
0
,
...
@@ -152,25 +168,30 @@ bool RB1_L(const NodePtr& u,
...
@@ -152,25 +168,30 @@ bool RB1_L(const NodePtr& u,
ux
->
GetWeight
(),
ux
->
GetWeight
(),
uxl
->
GetLeft
(),
nxr
);
uxl
->
GetLeft
(),
nxr
);
if
(
nxr
==
NULL
||
if
(
nxr
==
NULL
||
nx
==
NULL
)
{
nx
==
NULL
)
{
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nx
)
FreeNode
(
nx
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
}
NodePtr
expected
=
ux
;
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
);
RetireHazardousNode
(
ux
,
ux_lock
);
RetireNode
(
uxl
);
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
,
embb_errors_t
RB1_R
(
const
NodePtr
&
ux
,
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
const
NodePtr
&
uxr
)
{
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
HazardNodePtr
&
uxr
,
UniqueLock
&
uxr_lock
)
{
NodePtr
nxl
=
node_pool_
.
Allocate
(
NodePtr
nxl
=
node_pool_
.
Allocate
(
ux
->
GetKey
(),
ux
->
GetValue
(),
ux
->
GetKey
(),
ux
->
GetValue
(),
0
,
0
,
...
@@ -180,26 +201,31 @@ bool RB1_R(const NodePtr& u,
...
@@ -180,26 +201,31 @@ bool RB1_R(const NodePtr& u,
ux
->
GetWeight
(),
ux
->
GetWeight
(),
nxl
,
uxr
->
GetRight
());
nxl
,
uxr
->
GetRight
());
if
(
nxl
==
NULL
||
if
(
nxl
==
NULL
||
nx
==
NULL
)
{
nx
==
NULL
)
{
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nx
)
FreeNode
(
nx
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
}
NodePtr
expected
=
ux
;
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
);
RetireHazardousNode
(
ux
,
ux_lock
);
RetireNode
(
uxr
);
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
,
embb_errors_t
RB2_L
(
const
NodePtr
&
ux
,
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
const
NodePtr
&
uxl
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
const
NodePtr
&
uxlr
)
{
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
,
HazardNodePtr
&
uxlr
,
UniqueLock
&
uxlr_lock
)
{
NodePtr
nxl
=
node_pool_
.
Allocate
(
NodePtr
nxl
=
node_pool_
.
Allocate
(
uxl
->
GetKey
(),
uxl
->
GetValue
(),
uxl
->
GetKey
(),
uxl
->
GetValue
(),
0
,
0
,
...
@@ -213,29 +239,34 @@ bool RB2_L(const NodePtr& u,
...
@@ -213,29 +239,34 @@ bool RB2_L(const NodePtr& u,
ux
->
GetWeight
(),
ux
->
GetWeight
(),
nxl
,
nxr
);
nxl
,
nxr
);
if
(
nxl
==
NULL
||
if
(
nxl
==
NULL
||
nxr
==
NULL
||
nxr
==
NULL
||
nx
==
NULL
)
{
nx
==
NULL
)
{
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nx
)
FreeNode
(
nx
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
}
NodePtr
expected
=
ux
;
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
);
RetireHazardousNode
(
ux
,
ux_lock
);
RetireNode
(
uxl
);
RetireHazardousNode
(
uxl
,
uxl_lock
);
RetireNode
(
uxlr
);
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
,
embb_errors_t
RB2_R
(
const
NodePtr
&
ux
,
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
const
NodePtr
&
uxr
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
const
NodePtr
&
uxrl
)
{
HazardNodePtr
&
uxr
,
UniqueLock
&
uxr_lock
,
HazardNodePtr
&
uxrl
,
UniqueLock
&
uxrl_lock
)
{
NodePtr
nxr
=
node_pool_
.
Allocate
(
NodePtr
nxr
=
node_pool_
.
Allocate
(
uxr
->
GetKey
(),
uxr
->
GetValue
(),
uxr
->
GetKey
(),
uxr
->
GetValue
(),
0
,
0
,
...
@@ -249,30 +280,35 @@ bool RB2_R(const NodePtr& u,
...
@@ -249,30 +280,35 @@ bool RB2_R(const NodePtr& u,
ux
->
GetWeight
(),
ux
->
GetWeight
(),
nxl
,
nxr
);
nxl
,
nxr
);
if
(
nxr
==
NULL
||
if
(
nxr
==
NULL
||
nxl
==
NULL
||
nxl
==
NULL
||
nx
==
NULL
)
{
nx
==
NULL
)
{
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nx
)
FreeNode
(
nx
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
}
NodePtr
expected
=
ux
;
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
);
RetireHazardousNode
(
ux
,
ux_lock
);
RetireNode
(
uxr
);
RetireHazardousNode
(
uxr
,
uxr_lock
);
RetireNode
(
uxrl
);
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
,
embb_errors_t
W1_L
(
const
NodePtr
&
ux
,
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
const
NodePtr
&
uxl
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
const
NodePtr
&
uxr
,
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
,
const
NodePtr
&
uxrl
)
{
HazardNodePtr
&
uxr
,
UniqueLock
&
uxr_lock
,
HazardNodePtr
&
uxrl
,
UniqueLock
&
uxrl_lock
)
{
NodePtr
nxll
=
node_pool_
.
Allocate
(
NodePtr
nxll
=
node_pool_
.
Allocate
(
uxl
->
GetKey
(),
uxl
->
GetValue
(),
uxl
->
GetKey
(),
uxl
->
GetValue
(),
uxl
->
GetWeight
()
-
1
,
uxl
->
GetWeight
()
-
1
,
...
@@ -290,33 +326,38 @@ bool W1_L(const NodePtr& u,
...
@@ -290,33 +326,38 @@ bool W1_L(const NodePtr& u,
ux
->
GetWeight
(),
ux
->
GetWeight
(),
nxl
,
uxr
->
GetRight
());
nxl
,
uxr
->
GetRight
());
if
(
nxll
==
NULL
||
if
(
nxll
==
NULL
||
nxlr
==
NULL
||
nxlr
==
NULL
||
nxl
==
NULL
||
nxl
==
NULL
||
nx
==
NULL
)
{
nx
==
NULL
)
{
if
(
nxll
)
FreeNode
(
nxll
);
if
(
nxll
)
FreeNode
(
nxll
);
if
(
nxlr
)
FreeNode
(
nxlr
);
if
(
nxlr
)
FreeNode
(
nxlr
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nx
)
FreeNode
(
nx
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
}
NodePtr
expected
=
ux
;
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
nx
);
RetireNode
(
ux
);
assert
(
rotation_succeeded
);
// For now (FGL tree) this CAS may not fail
RetireNode
(
uxl
);
if
(
!
rotation_succeeded
)
return
EMBB_BUSY
;
RetireNode
(
uxr
);
RetireNode
(
uxrl
);
RetireHazardousNode
(
ux
,
ux_lock
);
RetireHazardousNode
(
uxl
,
uxl_lock
);
return
true
;
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
,
embb_errors_t
W1_R
(
const
NodePtr
&
ux
,
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
const
NodePtr
&
uxl
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
const
NodePtr
&
uxr
,
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
,
const
NodePtr
&
uxlr
)
{
HazardNodePtr
&
uxr
,
UniqueLock
&
uxr_lock
,
HazardNodePtr
&
uxlr
,
UniqueLock
&
uxlr_lock
)
{
NodePtr
nxrr
=
node_pool_
.
Allocate
(
NodePtr
nxrr
=
node_pool_
.
Allocate
(
uxr
->
GetKey
(),
uxr
->
GetValue
(),
uxr
->
GetKey
(),
uxr
->
GetValue
(),
uxr
->
GetWeight
()
-
1
,
uxr
->
GetWeight
()
-
1
,
...
@@ -334,33 +375,38 @@ bool W1_R(const NodePtr& u,
...
@@ -334,33 +375,38 @@ bool W1_R(const NodePtr& u,
ux
->
GetWeight
(),
ux
->
GetWeight
(),
uxl
->
GetLeft
(),
nxr
);
uxl
->
GetLeft
(),
nxr
);
if
(
nxrr
==
NULL
||
if
(
nxrr
==
NULL
||
nxrl
==
NULL
||
nxrl
==
NULL
||
nxr
==
NULL
||
nxr
==
NULL
||
nx
==
NULL
)
{
nx
==
NULL
)
{
if
(
nxrr
)
FreeNode
(
nxrr
);
if
(
nxrr
)
FreeNode
(
nxrr
);
if
(
nxrl
)
FreeNode
(
nxrl
);
if
(
nxrl
)
FreeNode
(
nxrl
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nx
)
FreeNode
(
nx
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
}
NodePtr
expected
=
ux
;
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
nx
);
RetireNode
(
ux
);
assert
(
rotation_succeeded
);
// For now (FGL tree) this CAS may not fail
RetireNode
(
uxl
);
if
(
!
rotation_succeeded
)
return
EMBB_BUSY
;
RetireNode
(
uxr
);
RetireNode
(
uxlr
);
RetireHazardousNode
(
ux
,
ux_lock
);
RetireHazardousNode
(
uxl
,
uxl_lock
);
return
true
;
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
,
embb_errors_t
W2_L
(
const
NodePtr
&
ux
,
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
const
NodePtr
&
uxl
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
const
NodePtr
&
uxr
,
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
,
const
NodePtr
&
uxrl
)
{
HazardNodePtr
&
uxr
,
UniqueLock
&
uxr_lock
,
HazardNodePtr
&
uxrl
,
UniqueLock
&
uxrl_lock
)
{
NodePtr
nxll
=
node_pool_
.
Allocate
(
NodePtr
nxll
=
node_pool_
.
Allocate
(
uxl
->
GetKey
(),
uxl
->
GetValue
(),
uxl
->
GetKey
(),
uxl
->
GetValue
(),
uxl
->
GetWeight
()
-
1
,
uxl
->
GetWeight
()
-
1
,
...
@@ -378,33 +424,38 @@ bool W2_L(const NodePtr& u,
...
@@ -378,33 +424,38 @@ bool W2_L(const NodePtr& u,
ux
->
GetWeight
(),
ux
->
GetWeight
(),
nxl
,
uxr
->
GetRight
());
nxl
,
uxr
->
GetRight
());
if
(
nxll
==
NULL
||
if
(
nxll
==
NULL
||
nxlr
==
NULL
||
nxlr
==
NULL
||
nxl
==
NULL
||
nxl
==
NULL
||
nx
==
NULL
)
{
nx
==
NULL
)
{
if
(
nxll
)
FreeNode
(
nxll
);
if
(
nxll
)
FreeNode
(
nxll
);
if
(
nxlr
)
FreeNode
(
nxlr
);
if
(
nxlr
)
FreeNode
(
nxlr
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nx
)
FreeNode
(
nx
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
}
NodePtr
expected
=
ux
;
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
nx
);
RetireNode
(
ux
);
assert
(
rotation_succeeded
);
// For now (FGL tree) this CAS may not fail
RetireNode
(
uxl
);
if
(
!
rotation_succeeded
)
return
EMBB_BUSY
;
RetireNode
(
uxr
);
RetireNode
(
uxrl
);
RetireHazardousNode
(
ux
,
ux_lock
);
RetireHazardousNode
(
uxl
,
uxl_lock
);
return
true
;
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
,
embb_errors_t
W2_R
(
const
NodePtr
&
ux
,
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
const
NodePtr
&
uxl
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
const
NodePtr
&
uxr
,
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
,
const
NodePtr
&
uxlr
)
{
HazardNodePtr
&
uxr
,
UniqueLock
&
uxr_lock
,
HazardNodePtr
&
uxlr
,
UniqueLock
&
uxlr_lock
)
{
NodePtr
nxrr
=
node_pool_
.
Allocate
(
NodePtr
nxrr
=
node_pool_
.
Allocate
(
uxr
->
GetKey
(),
uxr
->
GetValue
(),
uxr
->
GetKey
(),
uxr
->
GetValue
(),
uxr
->
GetWeight
()
-
1
,
uxr
->
GetWeight
()
-
1
,
...
@@ -422,34 +473,39 @@ bool W2_R(const NodePtr& u,
...
@@ -422,34 +473,39 @@ bool W2_R(const NodePtr& u,
ux
->
GetWeight
(),
ux
->
GetWeight
(),
uxl
->
GetLeft
(),
nxr
);
uxl
->
GetLeft
(),
nxr
);
if
(
nxrr
==
NULL
||
if
(
nxrr
==
NULL
||
nxrl
==
NULL
||
nxrl
==
NULL
||
nxr
==
NULL
||
nxr
==
NULL
||
nx
==
NULL
)
{
nx
==
NULL
)
{
if
(
nxrr
)
FreeNode
(
nxrr
);
if
(
nxrr
)
FreeNode
(
nxrr
);
if
(
nxrl
)
FreeNode
(
nxrl
);
if
(
nxrl
)
FreeNode
(
nxrl
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nx
)
FreeNode
(
nx
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
}
NodePtr
expected
=
ux
;
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
nx
);
RetireNode
(
ux
);
assert
(
rotation_succeeded
);
// For now (FGL tree) this CAS may not fail
RetireNode
(
uxl
);
if
(
!
rotation_succeeded
)
return
EMBB_BUSY
;
RetireNode
(
uxr
);
RetireNode
(
uxlr
);
RetireHazardousNode
(
ux
,
ux_lock
);
RetireHazardousNode
(
uxl
,
uxl_lock
);
return
true
;
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
,
embb_errors_t
W3_L
(
const
NodePtr
&
ux
,
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
const
NodePtr
&
uxl
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
const
NodePtr
&
uxr
,
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
,
const
NodePtr
&
uxrl
,
HazardNodePtr
&
uxr
,
UniqueLock
&
uxr_lock
,
const
NodePtr
&
uxrll
)
{
HazardNodePtr
&
uxrl
,
UniqueLock
&
uxrl_lock
,
HazardNodePtr
&
uxrll
,
UniqueLock
&
uxrll_lock
)
{
NodePtr
nxlll
=
node_pool_
.
Allocate
(
NodePtr
nxlll
=
node_pool_
.
Allocate
(
uxl
->
GetKey
(),
uxl
->
GetValue
(),
uxl
->
GetKey
(),
uxl
->
GetValue
(),
uxl
->
GetWeight
()
-
1
,
uxl
->
GetWeight
()
-
1
,
...
@@ -471,37 +527,42 @@ bool W3_L(const NodePtr& u,
...
@@ -471,37 +527,42 @@ bool W3_L(const NodePtr& u,
ux
->
GetWeight
(),
ux
->
GetWeight
(),
nxl
,
uxr
->
GetRight
());
nxl
,
uxr
->
GetRight
());
if
(
nxlll
==
NULL
||
if
(
nxlll
==
NULL
||
nxll
==
NULL
||
nxll
==
NULL
||
nxlr
==
NULL
||
nxlr
==
NULL
||
nxl
==
NULL
||
nxl
==
NULL
||
nx
==
NULL
)
{
nx
==
NULL
)
{
if
(
nxlll
)
FreeNode
(
nxlll
);
if
(
nxlll
)
FreeNode
(
nxlll
);
if
(
nxll
)
FreeNode
(
nxll
);
if
(
nxll
)
FreeNode
(
nxll
);
if
(
nxlr
)
FreeNode
(
nxlr
);
if
(
nxlr
)
FreeNode
(
nxlr
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nx
)
FreeNode
(
nx
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
}
NodePtr
expected
=
ux
;
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
nx
);
RetireNode
(
ux
);
assert
(
rotation_succeeded
);
// For now (FGL tree) this CAS may not fail
RetireNode
(
uxl
);
if
(
!
rotation_succeeded
)
return
EMBB_BUSY
;
RetireNode
(
uxr
);
RetireNode
(
uxrl
);
RetireHazardousNode
(
ux
,
ux_lock
);
RetireNode
(
uxrll
);
RetireHazardousNode
(
uxl
,
uxl_lock
);
RetireHazardousNode
(
uxr
,
uxr_lock
);
return
true
;
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
,
embb_errors_t
W3_R
(
const
NodePtr
&
ux
,
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
const
NodePtr
&
uxl
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
const
NodePtr
&
uxr
,
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
,
const
NodePtr
&
uxlr
,
HazardNodePtr
&
uxr
,
UniqueLock
&
uxr_lock
,
const
NodePtr
&
uxlrr
)
{
HazardNodePtr
&
uxlr
,
UniqueLock
&
uxlr_lock
,
HazardNodePtr
&
uxlrr
,
UniqueLock
&
uxlrr_lock
)
{
NodePtr
nxrrr
=
node_pool_
.
Allocate
(
NodePtr
nxrrr
=
node_pool_
.
Allocate
(
uxr
->
GetKey
(),
uxr
->
GetValue
(),
uxr
->
GetKey
(),
uxr
->
GetValue
(),
uxr
->
GetWeight
()
-
1
,
uxr
->
GetWeight
()
-
1
,
...
@@ -523,37 +584,42 @@ bool W3_R(const NodePtr& u,
...
@@ -523,37 +584,42 @@ bool W3_R(const NodePtr& u,
ux
->
GetWeight
(),
ux
->
GetWeight
(),
uxl
->
GetLeft
(),
nxr
);
uxl
->
GetLeft
(),
nxr
);
if
(
nxrrr
==
NULL
||
if
(
nxrrr
==
NULL
||
nxrr
==
NULL
||
nxrr
==
NULL
||
nxrl
==
NULL
||
nxrl
==
NULL
||
nxr
==
NULL
||
nxr
==
NULL
||
nx
==
NULL
)
{
nx
==
NULL
)
{
if
(
nxrrr
)
FreeNode
(
nxrrr
);
if
(
nxrrr
)
FreeNode
(
nxrrr
);
if
(
nxrr
)
FreeNode
(
nxrr
);
if
(
nxrr
)
FreeNode
(
nxrr
);
if
(
nxrl
)
FreeNode
(
nxrl
);
if
(
nxrl
)
FreeNode
(
nxrl
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nx
)
FreeNode
(
nx
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
}
NodePtr
expected
=
ux
;
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
nx
);
RetireNode
(
ux
);
assert
(
rotation_succeeded
);
// For now (FGL tree) this CAS may not fail
RetireNode
(
uxl
);
if
(
!
rotation_succeeded
)
return
EMBB_BUSY
;
RetireNode
(
uxr
);
RetireNode
(
uxlr
);
RetireHazardousNode
(
ux
,
ux_lock
);
RetireNode
(
uxlrr
);
RetireHazardousNode
(
uxl
,
uxl_lock
);
RetireHazardousNode
(
uxr
,
uxr_lock
);
return
true
;
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
,
embb_errors_t
W4_L
(
const
NodePtr
&
ux
,
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
const
NodePtr
&
uxl
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
const
NodePtr
&
uxr
,
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
,
const
NodePtr
&
uxrl
,
HazardNodePtr
&
uxr
,
UniqueLock
&
uxr_lock
,
const
NodePtr
&
uxrlr
)
{
HazardNodePtr
&
uxrl
,
UniqueLock
&
uxrl_lock
,
HazardNodePtr
&
uxrlr
,
UniqueLock
&
uxrlr_lock
)
{
NodePtr
nxll
=
node_pool_
.
Allocate
(
NodePtr
nxll
=
node_pool_
.
Allocate
(
uxl
->
GetKey
(),
uxl
->
GetValue
(),
uxl
->
GetKey
(),
uxl
->
GetValue
(),
uxl
->
GetWeight
()
-
1
,
uxl
->
GetWeight
()
-
1
,
...
@@ -575,37 +641,42 @@ bool W4_L(const NodePtr& u,
...
@@ -575,37 +641,42 @@ bool W4_L(const NodePtr& u,
ux
->
GetWeight
(),
ux
->
GetWeight
(),
nxl
,
nxr
);
nxl
,
nxr
);
if
(
nxll
==
NULL
||
if
(
nxll
==
NULL
||
nxrl
==
NULL
||
nxrl
==
NULL
||
nxl
==
NULL
||
nxl
==
NULL
||
nxr
==
NULL
||
nxr
==
NULL
||
nx
==
NULL
)
{
nx
==
NULL
)
{
if
(
nxll
)
FreeNode
(
nxll
);
if
(
nxll
)
FreeNode
(
nxll
);
if
(
nxrl
)
FreeNode
(
nxrl
);
if
(
nxrl
)
FreeNode
(
nxrl
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nx
)
FreeNode
(
nx
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
}
NodePtr
expected
=
ux
;
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
nx
);
RetireNode
(
ux
);
assert
(
rotation_succeeded
);
// For now (FGL tree) this CAS may not fail
RetireNode
(
uxl
);
if
(
!
rotation_succeeded
)
return
EMBB_BUSY
;
RetireNode
(
uxr
);
RetireNode
(
uxrl
);
RetireHazardousNode
(
ux
,
ux_lock
);
RetireNode
(
uxrlr
);
RetireHazardousNode
(
uxl
,
uxl_lock
);
RetireHazardousNode
(
uxr
,
uxr_lock
);
return
true
;
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
,
embb_errors_t
W4_R
(
const
NodePtr
&
ux
,
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
const
NodePtr
&
uxl
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
const
NodePtr
&
uxr
,
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
,
const
NodePtr
&
uxlr
,
HazardNodePtr
&
uxr
,
UniqueLock
&
uxr_lock
,
const
NodePtr
&
uxlrl
)
{
HazardNodePtr
&
uxlr
,
UniqueLock
&
uxlr_lock
,
HazardNodePtr
&
uxlrl
,
UniqueLock
&
uxlrl_lock
)
{
NodePtr
nxrr
=
node_pool_
.
Allocate
(
NodePtr
nxrr
=
node_pool_
.
Allocate
(
uxr
->
GetKey
(),
uxr
->
GetValue
(),
uxr
->
GetKey
(),
uxr
->
GetValue
(),
uxr
->
GetWeight
()
-
1
,
uxr
->
GetWeight
()
-
1
,
...
@@ -627,36 +698,41 @@ bool W4_R(const NodePtr& u,
...
@@ -627,36 +698,41 @@ bool W4_R(const NodePtr& u,
ux
->
GetWeight
(),
ux
->
GetWeight
(),
nxl
,
nxr
);
nxl
,
nxr
);
if
(
nxrr
==
NULL
||
if
(
nxrr
==
NULL
||
nxlr
==
NULL
||
nxlr
==
NULL
||
nxr
==
NULL
||
nxr
==
NULL
||
nxl
==
NULL
||
nxl
==
NULL
||
nx
==
NULL
)
{
nx
==
NULL
)
{
if
(
nxrr
)
FreeNode
(
nxrr
);
if
(
nxrr
)
FreeNode
(
nxrr
);
if
(
nxlr
)
FreeNode
(
nxlr
);
if
(
nxlr
)
FreeNode
(
nxlr
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nx
)
FreeNode
(
nx
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
}
NodePtr
expected
=
ux
;
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
nx
);
RetireNode
(
ux
);
assert
(
rotation_succeeded
);
// For now (FGL tree) this CAS may not fail
RetireNode
(
uxl
);
if
(
!
rotation_succeeded
)
return
EMBB_BUSY
;
RetireNode
(
uxr
);
RetireNode
(
uxlr
);
RetireHazardousNode
(
ux
,
ux_lock
);
RetireNode
(
uxlrl
);
RetireHazardousNode
(
uxl
,
uxl_lock
);
RetireHazardousNode
(
uxr
,
uxr_lock
);
return
true
;
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
,
embb_errors_t
W5_L
(
const
NodePtr
&
ux
,
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
const
NodePtr
&
uxl
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
const
NodePtr
&
uxr
,
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
,
const
NodePtr
&
uxrr
)
{
HazardNodePtr
&
uxr
,
UniqueLock
&
uxr_lock
,
HazardNodePtr
&
uxrr
,
UniqueLock
&
uxrr_lock
)
{
NodePtr
nxll
=
node_pool_
.
Allocate
(
NodePtr
nxll
=
node_pool_
.
Allocate
(
uxl
->
GetKey
(),
uxl
->
GetValue
(),
uxl
->
GetKey
(),
uxl
->
GetValue
(),
uxl
->
GetWeight
()
-
1
,
uxl
->
GetWeight
()
-
1
,
...
@@ -674,33 +750,38 @@ bool W5_L(const NodePtr& u,
...
@@ -674,33 +750,38 @@ bool W5_L(const NodePtr& u,
ux
->
GetWeight
(),
ux
->
GetWeight
(),
nxl
,
nxr
);
nxl
,
nxr
);
if
(
nxll
==
NULL
||
if
(
nxll
==
NULL
||
nxl
==
NULL
||
nxl
==
NULL
||
nxr
==
NULL
||
nxr
==
NULL
||
nx
==
NULL
)
{
nx
==
NULL
)
{
if
(
nxll
)
FreeNode
(
nxll
);
if
(
nxll
)
FreeNode
(
nxll
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nx
)
FreeNode
(
nx
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
}
NodePtr
expected
=
ux
;
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
nx
);
RetireNode
(
ux
);
assert
(
rotation_succeeded
);
// For now (FGL tree) this CAS may not fail
RetireNode
(
uxl
);
if
(
!
rotation_succeeded
)
return
EMBB_BUSY
;
RetireNode
(
uxr
);
RetireNode
(
uxrr
);
RetireHazardousNode
(
ux
,
ux_lock
);
RetireHazardousNode
(
uxl
,
uxl_lock
);
return
true
;
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
,
embb_errors_t
W5_R
(
const
NodePtr
&
ux
,
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
const
NodePtr
&
uxl
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
const
NodePtr
&
uxr
,
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
,
const
NodePtr
&
uxll
)
{
HazardNodePtr
&
uxr
,
UniqueLock
&
uxr_lock
,
HazardNodePtr
&
uxll
,
UniqueLock
&
uxll_lock
)
{
NodePtr
nxrr
=
node_pool_
.
Allocate
(
NodePtr
nxrr
=
node_pool_
.
Allocate
(
uxr
->
GetKey
(),
uxr
->
GetValue
(),
uxr
->
GetKey
(),
uxr
->
GetValue
(),
uxr
->
GetWeight
()
-
1
,
uxr
->
GetWeight
()
-
1
,
...
@@ -718,33 +799,38 @@ bool W5_R(const NodePtr& u,
...
@@ -718,33 +799,38 @@ bool W5_R(const NodePtr& u,
ux
->
GetWeight
(),
ux
->
GetWeight
(),
nxl
,
nxr
);
nxl
,
nxr
);
if
(
nxrr
==
NULL
||
if
(
nxrr
==
NULL
||
nxr
==
NULL
||
nxr
==
NULL
||
nxl
==
NULL
||
nxl
==
NULL
||
nx
==
NULL
)
{
nx
==
NULL
)
{
if
(
nxrr
)
FreeNode
(
nxrr
);
if
(
nxrr
)
FreeNode
(
nxrr
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nx
)
FreeNode
(
nx
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
}
NodePtr
expected
=
ux
;
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
nx
);
RetireNode
(
ux
);
assert
(
rotation_succeeded
);
// For now (FGL tree) this CAS may not fail
RetireNode
(
uxl
);
if
(
!
rotation_succeeded
)
return
EMBB_BUSY
;
RetireNode
(
uxr
);
RetireNode
(
uxll
);
RetireHazardousNode
(
ux
,
ux_lock
);
RetireHazardousNode
(
uxl
,
uxl_lock
);
return
true
;
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
,
embb_errors_t
W6_L
(
const
NodePtr
&
ux
,
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
const
NodePtr
&
uxl
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
const
NodePtr
&
uxr
,
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
,
const
NodePtr
&
uxrl
)
{
HazardNodePtr
&
uxr
,
UniqueLock
&
uxr_lock
,
HazardNodePtr
&
uxrl
,
UniqueLock
&
uxrl_lock
)
{
NodePtr
nxll
=
node_pool_
.
Allocate
(
NodePtr
nxll
=
node_pool_
.
Allocate
(
uxl
->
GetKey
(),
uxl
->
GetValue
(),
uxl
->
GetKey
(),
uxl
->
GetValue
(),
uxl
->
GetWeight
()
-
1
,
uxl
->
GetWeight
()
-
1
,
...
@@ -762,33 +848,38 @@ bool W6_L(const NodePtr& u,
...
@@ -762,33 +848,38 @@ bool W6_L(const NodePtr& u,
ux
->
GetWeight
(),
ux
->
GetWeight
(),
nxl
,
nxr
);
nxl
,
nxr
);
if
(
nxll
==
NULL
||
if
(
nxll
==
NULL
||
nxl
==
NULL
||
nxl
==
NULL
||
nxr
==
NULL
||
nxr
==
NULL
||
nx
==
NULL
)
{
nx
==
NULL
)
{
if
(
nxll
)
FreeNode
(
nxll
);
if
(
nxll
)
FreeNode
(
nxll
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nx
)
FreeNode
(
nx
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
}
NodePtr
expected
=
ux
;
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
nx
);
RetireNode
(
ux
);
assert
(
rotation_succeeded
);
// For now (FGL tree) this CAS may not fail
RetireNode
(
uxl
);
if
(
!
rotation_succeeded
)
return
EMBB_BUSY
;
RetireNode
(
uxr
);
RetireNode
(
uxrl
);
RetireHazardousNode
(
ux
,
ux_lock
);
RetireHazardousNode
(
uxl
,
uxl_lock
);
return
true
;
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
,
embb_errors_t
W6_R
(
const
NodePtr
&
ux
,
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
const
NodePtr
&
uxl
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
const
NodePtr
&
uxr
,
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
,
const
NodePtr
&
uxlr
)
{
HazardNodePtr
&
uxr
,
UniqueLock
&
uxr_lock
,
HazardNodePtr
&
uxlr
,
UniqueLock
&
uxlr_lock
)
{
NodePtr
nxrr
=
node_pool_
.
Allocate
(
NodePtr
nxrr
=
node_pool_
.
Allocate
(
uxr
->
GetKey
(),
uxr
->
GetValue
(),
uxr
->
GetKey
(),
uxr
->
GetValue
(),
uxr
->
GetWeight
()
-
1
,
uxr
->
GetWeight
()
-
1
,
...
@@ -806,32 +897,37 @@ bool W6_R(const NodePtr& u,
...
@@ -806,32 +897,37 @@ bool W6_R(const NodePtr& u,
ux
->
GetWeight
(),
ux
->
GetWeight
(),
nxl
,
nxr
);
nxl
,
nxr
);
if
(
nxrr
==
NULL
||
if
(
nxrr
==
NULL
||
nxr
==
NULL
||
nxr
==
NULL
||
nxl
==
NULL
||
nxl
==
NULL
||
nx
==
NULL
)
{
nx
==
NULL
)
{
if
(
nxrr
)
FreeNode
(
nxrr
);
if
(
nxrr
)
FreeNode
(
nxrr
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nx
)
FreeNode
(
nx
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
}
NodePtr
expected
=
ux
;
NodePtr
expected
=
ux
;
GetPointerToChild
(
u
,
ux
).
CompareAndSwap
(
expected
,
nx
);
bool
rotation_succeeded
=
GetPointerToChild
(
u
,
ux
)
.
CompareAndSwap
(
expected
,
nx
);
RetireNode
(
ux
);
assert
(
rotation_succeeded
);
// For now (FGL tree) this CAS may not fail
RetireNode
(
uxl
);
if
(
!
rotation_succeeded
)
return
EMBB_BUSY
;
RetireNode
(
uxr
);
RetireNode
(
uxlr
);
RetireHazardousNode
(
ux
,
ux_lock
);
RetireHazardousNode
(
uxl
,
uxl_lock
);
return
true
;
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
,
embb_errors_t
W7
(
const
NodePtr
&
ux
,
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
const
NodePtr
&
uxl
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
const
NodePtr
&
uxr
)
{
HazardNodePtr
&
uxl
,
UniqueLock
&
uxl_lock
,
HazardNodePtr
&
uxr
,
UniqueLock
&
uxr_lock
)
{
NodePtr
nxl
=
node_pool_
.
Allocate
(
NodePtr
nxl
=
node_pool_
.
Allocate
(
uxl
->
GetKey
(),
uxl
->
GetValue
(),
uxl
->
GetKey
(),
uxl
->
GetValue
(),
uxl
->
GetWeight
()
-
1
,
uxl
->
GetWeight
()
-
1
,
...
@@ -845,23 +941,27 @@ bool W7(const NodePtr& u,
...
@@ -845,23 +941,27 @@ bool W7(const NodePtr& u,
HasFixedWeight
(
ux
)
?
1
:
ux
->
GetWeight
()
+
1
,
HasFixedWeight
(
ux
)
?
1
:
ux
->
GetWeight
()
+
1
,
nxl
,
nxr
);
nxl
,
nxr
);
if
(
nxl
==
NULL
||
if
(
nxl
==
NULL
||
nxr
==
NULL
||
nxr
==
NULL
||
nx
==
NULL
)
{
nx
==
NULL
)
{
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxl
)
FreeNode
(
nxl
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nxr
)
FreeNode
(
nxr
);
if
(
nx
)
FreeNode
(
nx
);
if
(
nx
)
FreeNode
(
nx
);
return
false
;
return
EMBB_NOMEM
;
}
}
NodePtr
expected
=
ux
;
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
);
RetireHazardousNode
(
ux
,
ux_lock
);
RetireNode
(
uxl
);
RetireHazardousNode
(
uxl
,
uxl_lock
);
RetireNode
(
uxr
);
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_
#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 @@
...
@@ -30,6 +30,7 @@
#include <stddef.h>
#include <stddef.h>
#include <functional>
#include <functional>
#include <embb/base/c/errors.h>
#include <embb/base/mutex.h>
#include <embb/base/mutex.h>
#include <embb/containers/internal/hazard_pointer.h>
#include <embb/containers/internal/hazard_pointer.h>
...
@@ -70,6 +71,7 @@ class ChromaticTreeNode {
...
@@ -70,6 +71,7 @@ class ChromaticTreeNode {
*
*
* \param[IN] key Key of the new node
* \param[IN] key Key of the new node
* \param[IN] value Value 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
);
ChromaticTreeNode
(
const
Key
&
key
,
const
Value
&
value
,
const
int
weight
=
1
);
...
@@ -126,6 +128,75 @@ class ChromaticTreeNode {
...
@@ -126,6 +128,75 @@ class ChromaticTreeNode {
embb
::
base
::
Mutex
mutex_
;
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 internal
namespace
test
{
namespace
test
{
...
@@ -301,29 +372,20 @@ class ChromaticTree {
...
@@ -301,29 +372,20 @@ class ChromaticTree {
*/
*/
typedef
embb
::
base
::
Atomic
<
NodePtr
>
AtomicNodePtr
;
typedef
embb
::
base
::
Atomic
<
NodePtr
>
AtomicNodePtr
;
typedef
internal
::
UniqueHazardGuard
<
NodePtr
>
HazardNodePtr
;
typedef
embb
::
base
::
UniqueLock
<
embb
::
base
::
Mutex
>
UniqueLock
;
typedef
embb
::
base
::
UniqueLock
<
embb
::
base
::
Mutex
>
UniqueLock
;
/**
/**
* Follows a path from the root of the tree to some leaf searching for the
* 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
* 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.
* key). Returns the reached leaf together with its ancestors.
*
*
* \param[IN] key Key to be searched for
* \param[IN] key Key to be searched for
* \param[IN,OUT] leaf Reference to the reached leaf
* \param[IN,OUT] leaf Reference to the reached leaf
* \param[IN,OUT] parent Reference to the parent of 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
* Follows a path from the root of the tree to some leaf searching for the
...
@@ -335,8 +397,8 @@ class ChromaticTree {
...
@@ -335,8 +397,8 @@ class ChromaticTree {
* \param[IN,OUT] parent Reference to the parent of the reached leaf
* \param[IN,OUT] parent Reference to the parent of the reached leaf
* \param[IN,OUT] grandparent Reference to the grandparent 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
,
void
Search
(
const
Key
&
key
,
HazardNodePtr
&
leaf
,
Hazard
NodePtr
&
parent
,
NodePtr
&
grandparent
);
Hazard
NodePtr
&
grandparent
);
/**
/**
* Checks whether the given node is a leaf.
* Checks whether the given node is a leaf.
...
@@ -415,8 +477,11 @@ class ChromaticTree {
...
@@ -415,8 +477,11 @@ class ChromaticTree {
bool
IsBalanced
()
const
;
bool
IsBalanced
()
const
;
bool
IsBalanced
(
const
NodePtr
&
node
)
const
;
bool
IsBalanced
(
const
NodePtr
&
node
)
const
;
void
RemoveNode
(
const
NodePtr
&
node
)
{
void
RetireHazardousNode
(
HazardNodePtr
&
node
,
UniqueLock
&
node_lock
)
{
node_hazard_manager_
.
EnqueuePointerForDeletion
(
node
);
node
->
Retire
();
node_lock
.
Unlock
();
NodePtr
node_to_delete
=
node
.
ReleaseHazard
();
node_hazard_manager_
.
EnqueuePointerForDeletion
(
node_to_delete
);
}
}
/**
/**
...
@@ -440,16 +505,22 @@ class ChromaticTree {
...
@@ -440,16 +505,22 @@ class ChromaticTree {
/**
/**
* Next block of methods is used internally to keep the balance of the tree.
* 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
,
embb_errors_t
Rebalance
(
HazardNodePtr
&
u
,
HazardNodePtr
&
ux
,
const
NodePtr
&
uxxx
);
HazardNodePtr
&
uxx
,
HazardNodePtr
&
uxxx
);
bool
OverweightLeft
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxx
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxr
,
embb_errors_t
OverweightLeft
(
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
const
NodePtr
&
uxxl
,
const
NodePtr
&
uxxr
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
const
bool
&
uxx_is_left
);
HazardNodePtr
&
uxx
,
UniqueLock
&
uxx_lock
,
bool
OverweightRight
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxx
,
HazardNodePtr
&
uxl
,
HazardNodePtr
&
uxr
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxr
,
HazardNodePtr
&
uxxl
,
UniqueLock
&
uxxl_lock
,
const
NodePtr
&
uxxl
,
const
NodePtr
&
uxxr
,
HazardNodePtr
&
uxxr
,
bool
uxx_is_left
);
const
bool
&
uxx_is_right
);
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
// The following included header contains the class methods implementing
// tree rotations. It is generated automatically and must be included
// tree rotations. It is generated automatically and must be included
...
@@ -466,7 +537,7 @@ class ChromaticTree {
...
@@ -466,7 +537,7 @@ class ChromaticTree {
const
Compare
compare_
;
/**< Comparator object for the keys */
const
Compare
compare_
;
/**< Comparator object for the keys */
size_t
capacity_
;
/**< User-requested capacity of the tree */
size_t
capacity_
;
/**< User-requested capacity of the tree */
NodePool
node_pool_
;
/**< Comparator object for the keys */
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 */
* the entry point into the tree */
/**
/**
...
...
containers_cpp/test/tree_test-inl.h
View file @
2f75565c
...
@@ -66,11 +66,11 @@ TreeTest<Tree>::TreeTest()
...
@@ -66,11 +66,11 @@ TreeTest<Tree>::TreeTest()
Add
(
&
TreeTest
::
TreeTestConcurrentGet_ReaderMethod
,
this
,
Add
(
&
TreeTest
::
TreeTestConcurrentGet_ReaderMethod
,
this
,
NUM_TEST_THREADS
/
2
,
NUM_ITERATIONS
).
NUM_TEST_THREADS
/
2
,
NUM_ITERATIONS
).
Post
(
&
TreeTest
::
TreeTestConcurrentGet_Post
,
this
);
Post
(
&
TreeTest
::
TreeTestConcurrentGet_Post
,
this
);
//
CreateUnit("TreeTestBalance").
CreateUnit
(
"TreeTestBalance"
).
//
Pre(&TreeTest::TreeTestBalance_Pre, this).
Pre
(
&
TreeTest
::
TreeTestBalance_Pre
,
this
).
//
Add(&TreeTest::TreeTestBalance_ThreadMethod, this,
Add
(
&
TreeTest
::
TreeTestBalance_ThreadMethod
,
this
,
//
NUM_TEST_THREADS, 1).
NUM_TEST_THREADS
,
1
).
//
Post(&TreeTest::TreeTestBalance_Post, this);
Post
(
&
TreeTest
::
TreeTestBalance_Post
,
this
);
}
}
template
<
typename
Tree
>
template
<
typename
Tree
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment