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
May 20, 2015
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
Hide 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
());
}
...
...
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))
...
...
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_
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 */
/**
...
...
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