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
abd38fe8
authored
9 years ago
by
Danila Klimenko
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chromatic_tree: checking if node is the root is no longer hazardous
parent
acb6cf6b
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
41 additions
and
56 deletions
+41
-56
base_cpp/include/embb/base/internal/atomic/atomic_pointer.h
+4
-4
containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-inl.h
+29
-35
containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-rebalance.h
+7
-7
containers_cpp/include/embb/containers/lock_free_chromatic_tree.h
+1
-10
No files found.
base_cpp/include/embb/base/internal/atomic/atomic_pointer.h
View file @
abd38fe8
...
...
@@ -65,8 +65,8 @@ class AtomicPointer : public AtomicArithmetic<BaseType*, DifferenceType, S> {
bool
IsPointer
()
const
;
// The methods below are documented in atomic.h
BaseType
*
operator
->
();
BaseType
&
operator
*
();
BaseType
*
operator
->
()
const
;
BaseType
&
operator
*
()
const
;
};
template
<
typename
BaseType
,
typename
DifferenceType
,
size_t
S
>
...
...
@@ -93,13 +93,13 @@ inline bool AtomicPointer<BaseType, DifferenceType, S>::
template
<
typename
BaseType
,
typename
DifferenceType
,
size_t
S
>
inline
BaseType
*
AtomicPointer
<
BaseType
,
DifferenceType
,
S
>::
operator
->
()
{
operator
->
()
const
{
return
this
->
Load
();
}
template
<
typename
BaseType
,
typename
DifferenceType
,
size_t
S
>
inline
BaseType
&
AtomicPointer
<
BaseType
,
DifferenceType
,
S
>::
operator
*
()
{
operator
*
()
const
{
return
*
(
this
->
Load
());
}
...
...
This diff is collapsed.
Click to expand it.
containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-inl.h
View file @
abd38fe8
...
...
@@ -238,10 +238,13 @@ ChromaticTree(size_t capacity, Key undefined_key, Value undefined_value,
capacity_
(
capacity
),
node_pool_
(
2
+
5
+
2
*
capacity_
+
node_hazard_manager_
.
GetRetiredListMaxSize
()
*
embb
::
base
::
Thread
::
GetThreadsMaxCount
())
{
entry_
=
node_pool_
.
Allocate
(
undefined_key_
,
undefined_value_
);
NodePtr
sentinel
=
node_pool_
.
Allocate
(
undefined_key_
,
undefined_value_
);
entry_
->
GetLeft
()
=
sentinel
;
embb
::
base
::
Thread
::
GetThreadsMaxCount
()),
entry_
(
node_pool_
.
Allocate
(
undefined_key_
,
undefined_value_
,
1
,
node_pool_
.
Allocate
(
undefined_key_
,
undefined_value_
),
static_cast
<
NodePtr
>
(
NULL
)))
{
assert
(
entry_
!=
NULL
);
assert
(
entry_
->
GetLeft
().
Load
()
!=
NULL
);
}
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
...
...
@@ -254,8 +257,8 @@ 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
)
{
HazardNodePtr
parent
(
node_hazard_manager_
.
GetGuardedPointer
(
0
)
,
NULL
);
HazardNodePtr
leaf
(
node_hazard_manager_
.
GetGuardedPointer
(
1
)
,
NULL
);
HazardNodePtr
parent
(
node_hazard_manager_
.
GetGuardedPointer
(
0
));
HazardNodePtr
leaf
(
node_hazard_manager_
.
GetGuardedPointer
(
1
));
Search
(
key
,
leaf
,
parent
);
bool
keys_are_equal
=
!
IsSentinel
(
leaf
)
&&
...
...
@@ -286,8 +289,8 @@ TryInsert(const Key& key, const Value& value, Value& old_value) {
bool
added_violation
=
false
;
while
(
!
insertion_succeeded
)
{
HazardNodePtr
parent
(
node_hazard_manager_
.
GetGuardedPointer
(
0
)
,
NULL
);
HazardNodePtr
leaf
(
node_hazard_manager_
.
GetGuardedPointer
(
1
)
,
NULL
);
HazardNodePtr
parent
(
node_hazard_manager_
.
GetGuardedPointer
(
0
));
HazardNodePtr
leaf
(
node_hazard_manager_
.
GetGuardedPointer
(
1
));
Search
(
key
,
leaf
,
parent
);
// Try to lock the parent
...
...
@@ -316,7 +319,7 @@ TryInsert(const Key& key, const Value& value, Value& old_value) {
new_sibling
=
node_pool_
.
Allocate
(
leaf
->
GetKey
(),
leaf
->
GetValue
());
if
(
new_sibling
==
NULL
)
break
;
int
new_weight
=
(
HasFixedWeight
(
leaf
))
?
1
:
(
leaf
->
GetWeight
()
-
1
);
int
new_weight
=
(
IsSentinel
(
parent
))
?
1
:
(
leaf
->
GetWeight
()
-
1
);
if
(
IsSentinel
(
leaf
)
||
compare_
(
key
,
leaf
->
GetKey
()))
{
new_parent
=
node_pool_
.
Allocate
(
leaf
->
GetKey
(),
undefined_value_
,
new_weight
,
new_leaf
,
new_sibling
);
...
...
@@ -365,9 +368,9 @@ TryDelete(const Key& key, Value& old_value) {
bool
added_violation
=
false
;
while
(
!
deletion_succeeded
)
{
HazardNodePtr
grandparent
(
node_hazard_manager_
.
GetGuardedPointer
(
0
)
,
NULL
);
HazardNodePtr
parent
(
node_hazard_manager_
.
GetGuardedPointer
(
1
)
,
NULL
);
HazardNodePtr
leaf
(
node_hazard_manager_
.
GetGuardedPointer
(
2
)
,
NULL
);
HazardNodePtr
grandparent
(
node_hazard_manager_
.
GetGuardedPointer
(
0
));
HazardNodePtr
parent
(
node_hazard_manager_
.
GetGuardedPointer
(
1
));
HazardNodePtr
leaf
(
node_hazard_manager_
.
GetGuardedPointer
(
2
));
Search
(
key
,
leaf
,
parent
,
grandparent
);
// Reached leaf has a different key - nothing to delete
...
...
@@ -389,7 +392,7 @@ TryDelete(const Key& key, Value& old_value) {
if
(
!
parent_lock
.
OwnsLock
()
||
parent
->
IsRetired
())
continue
;
// Get the sibling (and protect it with hazard pointer)
HazardNodePtr
sibling
(
node_hazard_manager_
.
GetGuardedPointer
(
3
)
,
NULL
);
HazardNodePtr
sibling
(
node_hazard_manager_
.
GetGuardedPointer
(
3
));
sibling
.
ProtectHazard
((
parent
->
GetLeft
()
==
leaf
)
?
parent
->
GetRight
()
:
parent
->
GetLeft
());
if
(
parent
->
IsRetired
()
||
!
sibling
.
IsActive
())
continue
;
...
...
@@ -406,7 +409,7 @@ TryDelete(const Key& key, Value& old_value) {
UniqueLock
leaf_lock
(
leaf
->
GetMutex
(),
embb
::
base
::
try_lock
);
if
(
!
leaf_lock
.
OwnsLock
()
||
leaf
->
IsRetired
())
continue
;
int
new_weight
=
(
HasFixedWeight
(
parent
))
?
int
new_weight
=
(
IsSentinel
(
grand
parent
))
?
1
:
(
parent
->
GetWeight
()
+
sibling
->
GetWeight
());
new_leaf
=
node_pool_
.
Allocate
(
...
...
@@ -453,8 +456,7 @@ GetUndefinedValue() {
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
bool
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
IsEmpty
()
const
{
NodePtr
entry
=
entry_
;
//Bug: "operator->()" is not const in AtomicPointer<>
return
IsLeaf
(
entry
->
GetLeft
());
return
IsLeaf
(
entry_
->
GetLeft
());
}
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
...
...
@@ -515,15 +517,7 @@ 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
{
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
{
NodePtr
entry
=
entry_
;
//Bug: "operator->()" is not const in AtomicPointer<>
return
(
IsSentinel
(
node
))
||
(
node
==
entry
->
GetLeft
()
->
GetLeft
());
return
(
node
==
entry_
)
||
(
node
==
entry_
->
GetLeft
());
}
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
...
...
@@ -564,8 +558,7 @@ GetHeight(const NodePtr& node) const {
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
bool
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
IsBalanced
()
const
{
NodePtr
entry
=
entry_
;
//Bug: "operator->()" is not const in AtomicPointer<>
return
IsBalanced
(
entry
->
GetLeft
());
return
IsBalanced
(
entry_
->
GetLeft
());
}
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
...
...
@@ -613,16 +606,16 @@ FreeNode(NodePtr node) {
template
<
typename
Key
,
typename
Value
,
typename
Compare
,
typename
NodePool
>
bool
ChromaticTree
<
Key
,
Value
,
Compare
,
NodePool
>::
CleanUp
(
const
Key
&
key
)
{
HazardNodePtr
gran
granparent
(
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
);
HazardNodePtr
gran
dgrandparent
(
node_hazard_manager_
.
GetGuardedPointer
(
0
)
);
HazardNodePtr
grandparent
(
node_hazard_manager_
.
GetGuardedPointer
(
1
)
);
HazardNodePtr
parent
(
node_hazard_manager_
.
GetGuardedPointer
(
2
)
);
HazardNodePtr
leaf
(
node_hazard_manager_
.
GetGuardedPointer
(
3
)
);
bool
reached_leaf
=
false
;
while
(
!
reached_leaf
)
{
bool
found_violation
=
false
;
gran
gran
parent
.
ProtectHazard
(
entry_
);
gran
dgrand
parent
.
ProtectHazard
(
entry_
);
grandparent
.
ProtectHazard
(
entry_
);
parent
.
ProtectHazard
(
entry_
);
leaf
.
ProtectHazard
(
entry_
->
GetLeft
());
...
...
@@ -630,7 +623,7 @@ CleanUp(const Key& key) {
reached_leaf
=
IsLeaf
(
leaf
);
while
(
!
reached_leaf
&&
!
found_violation
)
{
gran
gran
parent
.
AdoptGuard
(
grandparent
);
gran
dgrand
parent
.
AdoptGuard
(
grandparent
);
grandparent
.
AdoptGuard
(
parent
);
parent
.
AdoptGuard
(
leaf
);
leaf
.
ProtectHazard
((
IsSentinel
(
leaf
)
||
compare_
(
key
,
leaf
->
GetKey
()))
?
...
...
@@ -647,7 +640,8 @@ CleanUp(const Key& key) {
if
(
found_violation
)
{
reached_leaf
=
false
;
if
(
Rebalance
(
grangranparent
,
grandparent
,
parent
,
leaf
)
==
EMBB_NOMEM
)
{
if
(
Rebalance
(
grandgrandparent
,
grandparent
,
parent
,
leaf
)
==
EMBB_NOMEM
)
{
assert
(
false
&&
"No memory for rebalancing!"
);
return
false
;
}
...
...
@@ -662,7 +656,7 @@ CleanUp(const Key& key) {
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
); \
HazardNodePtr node(node_hazard_manager_.GetGuardedPointer(h_num)); \
node.ProtectHazard(parent->method()); \
if (parent->IsRetired() || !node.IsActive()) return EMBB_BUSY; \
VERIFY_ADDRESS(static_cast<NodePtr>(node))
...
...
This diff is collapsed.
Click to expand it.
containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-rebalance.h
View file @
abd38fe8
...
...
@@ -29,8 +29,8 @@
// Any direct changes will be lost after rebuild of the project.
//
#ifndef EMBB_CONTAINERS_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_
#define EMBB_CONTAINERS_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_
#ifndef EMBB_CONTAINERS_
INTERNAL_
LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_
#define EMBB_CONTAINERS_
INTERNAL_
LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_
embb_errors_t
BLK
(
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
...
...
@@ -47,7 +47,7 @@ embb_errors_t BLK(
uxr
->
GetLeft
(),
uxr
->
GetRight
());
NodePtr
nx
=
node_pool_
.
Allocate
(
ux
->
GetKey
(),
ux
->
GetValue
(),
HasFixedWeight
(
ux
)
?
1
:
ux
->
GetWeight
()
-
1
,
IsSentinel
(
u
)
?
1
:
ux
->
GetWeight
()
-
1
,
nxl
,
nxr
);
if
(
nxl
==
NULL
||
...
...
@@ -88,7 +88,7 @@ embb_errors_t PUSH_L(
uxr
->
GetLeft
(),
uxr
->
GetRight
());
NodePtr
nx
=
node_pool_
.
Allocate
(
ux
->
GetKey
(),
ux
->
GetValue
(),
HasFixedWeight
(
ux
)
?
1
:
ux
->
GetWeight
()
+
1
,
IsSentinel
(
u
)
?
1
:
ux
->
GetWeight
()
+
1
,
nxl
,
nxr
);
if
(
nxl
==
NULL
||
...
...
@@ -129,7 +129,7 @@ embb_errors_t PUSH_R(
uxl
->
GetLeft
(),
uxl
->
GetRight
());
NodePtr
nx
=
node_pool_
.
Allocate
(
ux
->
GetKey
(),
ux
->
GetValue
(),
HasFixedWeight
(
ux
)
?
1
:
ux
->
GetWeight
()
+
1
,
IsSentinel
(
u
)
?
1
:
ux
->
GetWeight
()
+
1
,
nxl
,
nxr
);
if
(
nxr
==
NULL
||
...
...
@@ -938,7 +938,7 @@ embb_errors_t W7(
uxr
->
GetLeft
(),
uxr
->
GetRight
());
NodePtr
nx
=
node_pool_
.
Allocate
(
ux
->
GetKey
(),
ux
->
GetValue
(),
HasFixedWeight
(
ux
)
?
1
:
ux
->
GetWeight
()
+
1
,
IsSentinel
(
u
)
?
1
:
ux
->
GetWeight
()
+
1
,
nxl
,
nxr
);
if
(
nxl
==
NULL
||
...
...
@@ -964,4 +964,4 @@ embb_errors_t W7(
return
EMBB_SUCCESS
;
}
#endif // EMBB_CONTAINERS_LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_
#endif // EMBB_CONTAINERS_
INTERNAL_
LOCK_FREE_CHROMATIC_TREE_REBALANCE_H_
This diff is collapsed.
Click to expand it.
containers_cpp/include/embb/containers/lock_free_chromatic_tree.h
View file @
abd38fe8
...
...
@@ -540,15 +540,6 @@ class ChromaticTree {
bool
IsSentinel
(
const
NodePtr
&
node
)
const
;
/**
* Checks whether the given node has to maintain the constant weight of \c 1.
*
* \param[IN] node Node to be checked
*
* \return \c true if the given node has constant weight, \c false otherwise
*/
bool
HasFixedWeight
(
const
NodePtr
&
node
)
const
;
/**
* Checks whether the given node has a specified child node.
*
* \param[IN] parent Parent node
...
...
@@ -673,7 +664,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 */
AtomicNodePtr
entry_
;
/**< Pointer to the sentinel node used as
const
AtomicNodePtr
entry_
;
/**< Pointer to the sentinel node used as
* the entry point into the tree */
/**
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment