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
9 years ago
by
Danila Klimenko
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chromatic_tree: Fine-grained locking implementation (complete with rebalancing)
parent
871b5391
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
119 additions
and
33 deletions
+119
-33
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
+0
-0
containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-rebalance.h
+0
-0
containers_cpp/include/embb/containers/lock_free_chromatic_tree.h
+97
-26
containers_cpp/test/tree_test-inl.h
+5
-5
No files found.
containers_cpp/include/embb/containers/internal/hazard_pointer-inl.h
View file @
2f75565c
...
...
@@ -182,7 +182,9 @@ HazardPointerThreadEntry<GuardType>::~HazardPointerThreadEntry() {
}
template
<
typename
GuardType
>
GuardType
HazardPointerThreadEntry
<
GuardType
>::
GetGuard
(
int
pos
)
const
{
typename
HazardPointerThreadEntry
<
GuardType
>::
AtomicGuard
&
HazardPointerThreadEntry
<
GuardType
>::
GetGuard
(
int
pos
)
const
{
assert
(
pos
>=
0
&&
pos
<
guards_per_thread
);
return
guarded_pointers
[
pos
];
}
...
...
@@ -393,6 +395,12 @@ void HazardPointer< GuardType >::GuardPointer(int guardPosition,
}
template
<
typename
GuardType
>
typename
HazardPointer
<
GuardType
>::
AtomicGuard
&
HazardPointer
<
GuardType
>::
GetGuardedPointer
(
int
guardPosition
)
{
return
GetHazardPointerElementForCurrentThread
().
GetGuard
(
guardPosition
);
}
template
<
typename
GuardType
>
void
HazardPointer
<
GuardType
>::
EnqueuePointerForDeletion
(
GuardType
guardedElement
)
{
GetHazardPointerElementForCurrentThread
().
AddRetired
(
guardedElement
);
...
...
This diff is collapsed.
Click to expand it.
containers_cpp/include/embb/containers/internal/hazard_pointer.h
View file @
2f75565c
...
...
@@ -238,6 +238,8 @@ class HazardPointerThreadEntry {
HazardPointerThreadEntry
&
operator
=
(
const
HazardPointerThreadEntry
&
);
public
:
typedef
embb
::
base
::
Atomic
<
GuardType
>
AtomicGuard
;
/**
* Checks if current thread is active (with respect to participating in hazard
* pointer management)
...
...
@@ -318,7 +320,7 @@ class HazardPointerThreadEntry {
* Gets the guard at the specified position.
* Positions are numbered, beginning with 0.
*/
GuardType
GetGuard
(
AtomicGuard
&
GetGuard
(
int
pos
/**< [IN] Position of the guard */
)
const
;
...
...
@@ -467,6 +469,8 @@ class HazardPointer {
can be deleted*/
);
public
:
typedef
typename
HazardPointerThreadEntry_t
::
AtomicGuard
AtomicGuard
;
/**
* Gets the capacity of one retired list
*
...
...
@@ -516,6 +520,9 @@ class HazardPointer {
* Guards \c guardedElement with the guard at position \c guardPosition
*/
void
GuardPointer
(
int
guardPosition
,
GuardType
guardedElement
);
AtomicGuard
&
GetGuardedPointer
(
int
guardPosition
);
/**
* Enqueue a pointer for deletion. It is added to the retired list and
* deleted when no thread accesses it anymore.
...
...
This diff is collapsed.
Click to expand it.
containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-inl.h
View file @
2f75565c
This diff is collapsed.
Click to expand it.
containers_cpp/include/embb/containers/internal/lock_free_chromatic_tree-rebalance.h
View file @
2f75565c
This diff is collapsed.
Click to expand it.
containers_cpp/include/embb/containers/lock_free_chromatic_tree.h
View file @
2f75565c
...
...
@@ -30,6 +30,7 @@
#include <stddef.h>
#include <functional>
#include <embb/base/c/errors.h>
#include <embb/base/mutex.h>
#include <embb/containers/internal/hazard_pointer.h>
...
...
@@ -70,6 +71,7 @@ class ChromaticTreeNode {
*
* \param[IN] key Key of the new node
* \param[IN] value Value of the new node
* \param[IN] weight Weight of the new node
*/
ChromaticTreeNode
(
const
Key
&
key
,
const
Value
&
value
,
const
int
weight
=
1
);
...
...
@@ -126,6 +128,75 @@ class ChromaticTreeNode {
embb
::
base
::
Mutex
mutex_
;
};
template
<
typename
GuardedType
>
class
UniqueHazardGuard
{
public
:
typedef
embb
::
base
::
Atomic
<
GuardedType
>
AtomicGuard
;
UniqueHazardGuard
(
AtomicGuard
&
guard
,
const
GuardedType
&
undefined_guard
)
:
guard_
(
guard
),
undefined_guard_
(
undefined_guard
),
active_
(
guard_
.
Load
()
==
undefined_guard_
)
{}
~
UniqueHazardGuard
()
{
if
(
active_
)
SetUndefinedGuard
();
}
bool
ProtectHazard
(
const
AtomicGuard
&
hazard
)
{
// Read the hazard and store it into the guard
guard_
=
hazard
.
Load
();
// Check whether the guard is valid
active_
=
(
guard_
.
Load
()
==
hazard
.
Load
());
// Clear the guard if it is invalid
if
(
!
active_
)
SetUndefinedGuard
();
return
active_
;
}
bool
IsActive
()
const
{
return
active_
;
}
operator
GuardedType
()
const
{
assert
(
active_
==
true
);
return
guard_
.
Load
();
}
GuardedType
operator
->
()
const
{
assert
(
active_
==
true
);
return
guard_
.
Load
();
}
void
AdoptGuard
(
const
UniqueHazardGuard
<
GuardedType
>&
other
)
{
guard_
=
other
.
guard_
.
Load
();
active_
=
other
.
active_
;
}
GuardedType
ReleaseHazard
()
{
assert
(
active_
==
true
);
GuardedType
released_hazard
=
guard_
.
Load
();
SetUndefinedGuard
();
active_
=
false
;
return
released_hazard
;
}
private
:
void
SetUndefinedGuard
()
{
guard_
=
undefined_guard_
;
}
// Non-copyable
UniqueHazardGuard
(
const
UniqueHazardGuard
<
GuardedType
>&
);
UniqueHazardGuard
<
GuardedType
>&
operator
=
(
const
UniqueHazardGuard
<
GuardedType
>&
);
AtomicGuard
&
guard_
;
GuardedType
undefined_guard_
;
bool
active_
;
};
}
// namespace internal
namespace
test
{
...
...
@@ -301,29 +372,20 @@ class ChromaticTree {
*/
typedef
embb
::
base
::
Atomic
<
NodePtr
>
AtomicNodePtr
;
typedef
internal
::
UniqueHazardGuard
<
NodePtr
>
HazardNodePtr
;
typedef
embb
::
base
::
UniqueLock
<
embb
::
base
::
Mutex
>
UniqueLock
;
/**
* Follows a path from the root of the tree to some leaf searching for the
* given key (the leaf found by this method may or may not contain the given
* key). Returns the reached leaf.
*
* \param[IN] key Key to be searched for
* \param[IN,OUT] leaf Reference to the reached leaf
*/
void
Search
(
const
Key
&
key
,
NodePtr
&
leaf
);
/**
* Follows a path from the root of the tree to some leaf searching for the
* given key (the leaf found by this method may or may not contain the given
* key). Returns the reached leaf together with its ancestors.
*
* \param[IN] key Key to be searched for
* \param[IN,OUT] leaf Reference to the reached leaf
* \param[IN,OUT] parent Reference to the parent of the reached leaf
*/
void
Search
(
const
Key
&
key
,
NodePtr
&
leaf
,
NodePtr
&
parent
);
void
Search
(
const
Key
&
key
,
HazardNodePtr
&
leaf
,
Hazard
NodePtr
&
parent
);
/**
* Follows a path from the root of the tree to some leaf searching for the
...
...
@@ -335,8 +397,8 @@ class ChromaticTree {
* \param[IN,OUT] parent Reference to the parent of the reached leaf
* \param[IN,OUT] grandparent Reference to the grandparent of the reached leaf
*/
void
Search
(
const
Key
&
key
,
NodePtr
&
leaf
,
NodePtr
&
parent
,
NodePtr
&
grandparent
);
void
Search
(
const
Key
&
key
,
HazardNodePtr
&
leaf
,
Hazard
NodePtr
&
parent
,
Hazard
NodePtr
&
grandparent
);
/**
* Checks whether the given node is a leaf.
...
...
@@ -415,8 +477,11 @@ class ChromaticTree {
bool
IsBalanced
()
const
;
bool
IsBalanced
(
const
NodePtr
&
node
)
const
;
void
RemoveNode
(
const
NodePtr
&
node
)
{
node_hazard_manager_
.
EnqueuePointerForDeletion
(
node
);
void
RetireHazardousNode
(
HazardNodePtr
&
node
,
UniqueLock
&
node_lock
)
{
node
->
Retire
();
node_lock
.
Unlock
();
NodePtr
node_to_delete
=
node
.
ReleaseHazard
();
node_hazard_manager_
.
EnqueuePointerForDeletion
(
node_to_delete
);
}
/**
...
...
@@ -440,16 +505,22 @@ class ChromaticTree {
/**
* Next block of methods is used internally to keep the balance of the tree.
*/
bool
Rebalance
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxx
,
const
NodePtr
&
uxxx
);
bool
OverweightLeft
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxx
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxr
,
const
NodePtr
&
uxxl
,
const
NodePtr
&
uxxr
,
const
bool
&
uxx_is_left
);
bool
OverweightRight
(
const
NodePtr
&
u
,
const
NodePtr
&
ux
,
const
NodePtr
&
uxx
,
const
NodePtr
&
uxl
,
const
NodePtr
&
uxr
,
const
NodePtr
&
uxxl
,
const
NodePtr
&
uxxr
,
const
bool
&
uxx_is_right
);
embb_errors_t
Rebalance
(
HazardNodePtr
&
u
,
HazardNodePtr
&
ux
,
HazardNodePtr
&
uxx
,
HazardNodePtr
&
uxxx
);
embb_errors_t
OverweightLeft
(
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
HazardNodePtr
&
uxx
,
UniqueLock
&
uxx_lock
,
HazardNodePtr
&
uxl
,
HazardNodePtr
&
uxr
,
HazardNodePtr
&
uxxl
,
UniqueLock
&
uxxl_lock
,
HazardNodePtr
&
uxxr
,
bool
uxx_is_left
);
embb_errors_t
OverweightRight
(
HazardNodePtr
&
u
,
UniqueLock
&
u_lock
,
HazardNodePtr
&
ux
,
UniqueLock
&
ux_lock
,
HazardNodePtr
&
uxx
,
UniqueLock
&
uxx_lock
,
HazardNodePtr
&
uxl
,
HazardNodePtr
&
uxr
,
HazardNodePtr
&
uxxl
,
HazardNodePtr
&
uxxr
,
UniqueLock
&
uxxr_lock
,
bool
uxx_is_right
);
// The following included header contains the class methods implementing
// tree rotations. It is generated automatically and must be included
...
...
@@ -466,7 +537,7 @@ class ChromaticTree {
const
Compare
compare_
;
/**< Comparator object for the keys */
size_t
capacity_
;
/**< User-requested capacity of the tree */
NodePool
node_pool_
;
/**< Comparator object for the keys */
NodePtr
entry_
;
/**< Pointer to the sentinel node used as
AtomicNodePtr
entry_
;
/**< Pointer to the sentinel node used as
* the entry point into the tree */
/**
...
...
This diff is collapsed.
Click to expand it.
containers_cpp/test/tree_test-inl.h
View file @
2f75565c
...
...
@@ -66,11 +66,11 @@ TreeTest<Tree>::TreeTest()
Add
(
&
TreeTest
::
TreeTestConcurrentGet_ReaderMethod
,
this
,
NUM_TEST_THREADS
/
2
,
NUM_ITERATIONS
).
Post
(
&
TreeTest
::
TreeTestConcurrentGet_Post
,
this
);
//
CreateUnit("TreeTestBalance").
//
Pre(&TreeTest::TreeTestBalance_Pre, this).
//
Add(&TreeTest::TreeTestBalance_ThreadMethod, this,
//
NUM_TEST_THREADS, 1).
//
Post(&TreeTest::TreeTestBalance_Post, this);
CreateUnit
(
"TreeTestBalance"
).
Pre
(
&
TreeTest
::
TreeTestBalance_Pre
,
this
).
Add
(
&
TreeTest
::
TreeTestBalance_ThreadMethod
,
this
,
NUM_TEST_THREADS
,
1
).
Post
(
&
TreeTest
::
TreeTestBalance_Post
,
this
);
}
template
<
typename
Tree
>
...
...
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