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
5192f502
authored
Oct 30, 2015
by
Christian Kern
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'development' into embb421_parallel_building_bug
parents
b32fd724
e71d171f
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
194 additions
and
68 deletions
+194
-68
containers_cpp/include/embb/containers/internal/lock_free_tree_value_pool-inl.h
+61
-22
containers_cpp/include/embb/containers/internal/object_pool-inl.h
+14
-11
containers_cpp/include/embb/containers/internal/wait_free_array_value_pool-inl.h
+30
-8
containers_cpp/include/embb/containers/lock_free_tree_value_pool.h
+22
-7
containers_cpp/include/embb/containers/object_pool.h
+13
-7
containers_cpp/include/embb/containers/wait_free_array_value_pool.h
+54
-13
No files found.
containers_cpp/include/embb/containers/internal/lock_free_tree_value_pool-inl.h
View file @
5192f502
...
@@ -42,7 +42,7 @@ template<typename Type, Type Undefined, class PoolAllocator,
...
@@ -42,7 +42,7 @@ template<typename Type, Type Undefined, class PoolAllocator,
class
TreeAllocator
>
class
TreeAllocator
>
bool
LockFreeTreeValuePool
<
Type
,
Undefined
,
PoolAllocator
,
TreeAllocator
>::
bool
LockFreeTreeValuePool
<
Type
,
Undefined
,
PoolAllocator
,
TreeAllocator
>::
IsLeaf
(
int
node
)
{
IsLeaf
(
int
node
)
{
if
(
node
>=
size
-
1
&&
node
<=
2
*
size
-
1
)
{
if
(
node
>=
size
_
-
1
&&
node
<=
2
*
size_
-
1
)
{
return
true
;
return
true
;
}
}
return
false
;
return
false
;
...
@@ -52,7 +52,7 @@ template<typename Type, Type Undefined, class PoolAllocator,
...
@@ -52,7 +52,7 @@ template<typename Type, Type Undefined, class PoolAllocator,
class
TreeAllocator
>
class
TreeAllocator
>
bool
LockFreeTreeValuePool
<
Type
,
Undefined
,
PoolAllocator
,
TreeAllocator
>::
bool
LockFreeTreeValuePool
<
Type
,
Undefined
,
PoolAllocator
,
TreeAllocator
>::
IsValid
(
int
node
)
{
IsValid
(
int
node
)
{
return
(
node
>=
0
&&
node
<=
2
*
size
-
1
);
return
(
node
>=
0
&&
node
<=
2
*
size
_
-
1
);
}
}
template
<
typename
Type
,
Type
Undefined
,
class
PoolAllocator
,
template
<
typename
Type
,
Type
Undefined
,
class
PoolAllocator
,
...
@@ -77,14 +77,14 @@ template<typename T, T Undefined, class PoolAllocator, class TreeAllocator >
...
@@ -77,14 +77,14 @@ template<typename T, T Undefined, class PoolAllocator, class TreeAllocator >
int
LockFreeTreeValuePool
<
T
,
Undefined
,
PoolAllocator
,
TreeAllocator
>::
int
LockFreeTreeValuePool
<
T
,
Undefined
,
PoolAllocator
,
TreeAllocator
>::
NodeIndexToPoolIndex
(
int
node
)
{
NodeIndexToPoolIndex
(
int
node
)
{
assert
(
IsLeaf
(
node
));
assert
(
IsLeaf
(
node
));
return
(
node
-
(
size
-
1
));
return
(
node
-
(
size
_
-
1
));
}
}
template
<
typename
Type
,
Type
Undefined
,
class
PoolAllocator
,
template
<
typename
Type
,
Type
Undefined
,
class
PoolAllocator
,
class
TreeAllocator
>
class
TreeAllocator
>
int
LockFreeTreeValuePool
<
Type
,
Undefined
,
PoolAllocator
,
TreeAllocator
>::
int
LockFreeTreeValuePool
<
Type
,
Undefined
,
PoolAllocator
,
TreeAllocator
>::
PoolIndexToNodeIndex
(
int
index
)
{
PoolIndexToNodeIndex
(
int
index
)
{
int
node
=
index
+
(
size
-
1
);
int
node
=
index
+
(
size
_
-
1
);
assert
(
IsLeaf
(
node
));
assert
(
IsLeaf
(
node
));
return
node
;
return
node
;
}
}
...
@@ -100,7 +100,7 @@ template<typename T, T Undefined, class PoolAllocator, class TreeAllocator >
...
@@ -100,7 +100,7 @@ template<typename T, T Undefined, class PoolAllocator, class TreeAllocator >
int
LockFreeTreeValuePool
<
T
,
Undefined
,
PoolAllocator
,
TreeAllocator
>::
int
LockFreeTreeValuePool
<
T
,
Undefined
,
PoolAllocator
,
TreeAllocator
>::
GetParentNode
(
int
node
)
{
GetParentNode
(
int
node
)
{
int
parent
=
(
node
-
1
)
/
2
;
int
parent
=
(
node
-
1
)
/
2
;
assert
(
parent
>=
0
&&
parent
<
size
-
1
);
assert
(
parent
>=
0
&&
parent
<
size
_
-
1
);
return
parent
;
return
parent
;
}
}
...
@@ -112,11 +112,11 @@ allocate_rec(int node, Type& element) {
...
@@ -112,11 +112,11 @@ allocate_rec(int node, Type& element) {
if
(
IsLeaf
(
node
))
{
if
(
IsLeaf
(
node
))
{
int
pool_index
=
NodeIndexToPoolIndex
(
node
);
int
pool_index
=
NodeIndexToPoolIndex
(
node
);
Type
expected
=
pool
[
pool_index
];
Type
expected
=
pool
_
[
pool_index
];
if
(
expected
==
Undefined
)
if
(
expected
==
Undefined
)
return
-
1
;
return
-
1
;
if
(
pool
[
pool_index
].
CompareAndSwap
(
expected
,
Undefined
))
{
if
(
pool
_
[
pool_index
].
CompareAndSwap
(
expected
,
Undefined
))
{
element
=
expected
;
element
=
expected
;
return
pool_index
;
return
pool_index
;
}
}
...
@@ -131,11 +131,11 @@ allocate_rec(int node, Type& element) {
...
@@ -131,11 +131,11 @@ allocate_rec(int node, Type& element) {
// atomically decrement the value in the node if the result is greater than
// atomically decrement the value in the node if the result is greater than
// or equal to zero. This cannot be done atomically.
// or equal to zero. This cannot be done atomically.
do
{
do
{
current
=
tree
[
node
];
current
=
tree
_
[
node
];
desired
=
current
-
1
;
desired
=
current
-
1
;
if
(
desired
<
0
)
if
(
desired
<
0
)
return
-
1
;
return
-
1
;
}
while
(
!
tree
[
node
].
CompareAndSwap
(
current
,
desired
));
}
while
(
!
tree
_
[
node
].
CompareAndSwap
(
current
,
desired
));
int
leftResult
=
allocate_rec
(
GetLeftChildIndex
(
node
),
element
);
int
leftResult
=
allocate_rec
(
GetLeftChildIndex
(
node
),
element
);
if
(
leftResult
!=
-
1
)
{
if
(
leftResult
!=
-
1
)
{
...
@@ -156,7 +156,7 @@ Fill(int node, int elementsToStore, int power2Value) {
...
@@ -156,7 +156,7 @@ Fill(int node, int elementsToStore, int power2Value) {
if
(
IsLeaf
(
node
))
if
(
IsLeaf
(
node
))
return
;
return
;
tree
[
node
]
=
elementsToStore
;
tree
_
[
node
]
=
elementsToStore
;
int
postPower2Value
=
power2Value
>>
1
;
int
postPower2Value
=
power2Value
>>
1
;
...
@@ -188,14 +188,14 @@ Free(Type element, int index) {
...
@@ -188,14 +188,14 @@ Free(Type element, int index) {
assert
(
element
!=
Undefined
);
assert
(
element
!=
Undefined
);
// Put the element back
// Put the element back
pool
[
index
].
Store
(
element
);
pool
_
[
index
].
Store
(
element
);
assert
(
index
>=
0
&&
index
<
size
);
assert
(
index
>=
0
&&
index
<
size
_
);
int
node
=
PoolIndexToNodeIndex
(
index
);
int
node
=
PoolIndexToNodeIndex
(
index
);
while
(
!
IsRoot
(
node
))
{
while
(
!
IsRoot
(
node
))
{
node
=
GetParentNode
(
node
);
node
=
GetParentNode
(
node
);
tree
[
node
].
FetchAndAdd
(
1
);
tree
_
[
node
].
FetchAndAdd
(
1
);
}
}
}
}
...
@@ -205,37 +205,76 @@ template< typename ForwardIterator >
...
@@ -205,37 +205,76 @@ template< typename ForwardIterator >
LockFreeTreeValuePool
<
Type
,
Undefined
,
PoolAllocator
,
TreeAllocator
>::
LockFreeTreeValuePool
<
Type
,
Undefined
,
PoolAllocator
,
TreeAllocator
>::
LockFreeTreeValuePool
(
ForwardIterator
first
,
ForwardIterator
last
)
{
LockFreeTreeValuePool
(
ForwardIterator
first
,
ForwardIterator
last
)
{
// Number of elements to store
// Number of elements to store
real_size
=
static_cast
<
int
>
(
::
std
::
distance
(
first
,
last
));
real_size
_
=
static_cast
<
int
>
(
::
std
::
distance
(
first
,
last
));
// Let k be smallest number so that real_size <= 2^k, size = 2^k
// Let k be smallest number so that real_size <= 2^k, size = 2^k
size
=
GetSmallestPowerByTwoValue
(
real_size
);
size
_
=
GetSmallestPowerByTwoValue
(
real_size_
);
// Size of binary tree without the leaves
// Size of binary tree without the leaves
tree_size
=
size
-
1
;
tree_size_
=
size_
-
1
;
// make sure, signed values are not negative
assert
(
tree_size_
>=
0
);
assert
(
real_size_
>=
0
);
size_t
tree_size_unsigned
=
static_cast
<
size_t
>
(
tree_size_
);
size_t
real_size_unsigned
=
static_cast
<
size_t
>
(
real_size_
);
// Pool stores elements of type T
// Pool stores elements of type T
pool
=
poolAllocator
.
allocate
(
static_cast
<
size_t
>
(
real_size
));
pool_
=
pool_allocator_
.
allocate
(
real_size_unsigned
);
// invoke inplace new for each pool element
for
(
size_t
i
=
0
;
i
!=
real_size_unsigned
;
++
i
)
{
new
(
&
pool_
[
i
])
embb
::
base
::
Atomic
<
Type
>
();
}
// Tree holds the counter of not allocated elements
// Tree holds the counter of not allocated elements
tree
=
treeAllocator
.
allocate
(
static_cast
<
size_t
>
(
tree_size
));
tree_
=
tree_allocator_
.
allocate
(
tree_size_unsigned
);
// invoke inplace new for each tree element
for
(
size_t
i
=
0
;
i
!=
tree_size_unsigned
;
++
i
)
{
new
(
&
tree_
[
i
])
embb
::
base
::
Atomic
<
int
>
();
}
int
i
=
0
;
int
i
=
0
;
// Store the elements from the range
// Store the elements from the range
for
(
ForwardIterator
curIter
(
first
);
curIter
!=
last
;
++
curIter
)
{
for
(
ForwardIterator
curIter
(
first
);
curIter
!=
last
;
++
curIter
)
{
pool
[
i
++
]
=
*
curIter
;
pool
_
[
i
++
]
=
*
curIter
;
}
}
// Initialize the binary tree without leaves (counters)
// Initialize the binary tree without leaves (counters)
Fill
(
0
,
static_cast
<
int
>
(
::
std
::
distance
(
first
,
last
)),
size
);
Fill
(
0
,
static_cast
<
int
>
(
::
std
::
distance
(
first
,
last
)),
size
_
);
}
}
template
<
typename
Type
,
Type
Undefined
,
class
PoolAllocator
,
template
<
typename
Type
,
Type
Undefined
,
class
PoolAllocator
,
class
TreeAllocator
>
class
TreeAllocator
>
LockFreeTreeValuePool
<
Type
,
Undefined
,
PoolAllocator
,
TreeAllocator
>::
LockFreeTreeValuePool
<
Type
,
Undefined
,
PoolAllocator
,
TreeAllocator
>::
~
LockFreeTreeValuePool
()
{
~
LockFreeTreeValuePool
()
{
poolAllocator
.
deallocate
(
pool
,
static_cast
<
size_t
>
(
real_size
));
size_t
tree_size_unsigned
=
static_cast
<
size_t
>
(
tree_size_
);
treeAllocator
.
deallocate
(
tree
,
static_cast
<
size_t
>
(
tree_size
));
size_t
real_size_unsigned
=
static_cast
<
size_t
>
(
real_size_
);
pool_allocator_
.
deallocate
(
pool_
,
real_size_unsigned
);
// invoke destructor for each pool element
for
(
size_t
i
=
0
;
i
!=
real_size_unsigned
;
++
i
)
{
pool_
[
i
].
~
Atomic
();
}
tree_allocator_
.
deallocate
(
tree_
,
tree_size_unsigned
);
// invoke destructor for each tree element
for
(
size_t
i
=
0
;
i
!=
tree_size_unsigned
;
++
i
)
{
tree_
[
i
].
~
Atomic
();
}
}
template
<
typename
Type
,
Type
Undefined
,
class
PoolAllocator
,
class
TreeAllocator
>
size_t
LockFreeTreeValuePool
<
Type
,
Undefined
,
PoolAllocator
,
TreeAllocator
>::
GetMinimumElementCountForGuaranteedCapacity
(
size_t
capacity
)
{
// for this value pool, this is just capacity...
return
capacity
;
}
}
}
// namespace containers
}
// namespace containers
...
...
containers_cpp/include/embb/containers/internal/object_pool-inl.h
View file @
5192f502
...
@@ -83,7 +83,8 @@ ReturningTrueIterator::operator!=(const self_type& rhs) {
...
@@ -83,7 +83,8 @@ ReturningTrueIterator::operator!=(const self_type& rhs) {
template
<
class
Type
,
typename
ValuePool
,
class
ObjectAllocator
>
template
<
class
Type
,
typename
ValuePool
,
class
ObjectAllocator
>
bool
ObjectPool
<
Type
,
ValuePool
,
ObjectAllocator
>::
bool
ObjectPool
<
Type
,
ValuePool
,
ObjectAllocator
>::
IsContained
(
const
Type
&
obj
)
const
{
IsContained
(
const
Type
&
obj
)
const
{
if
((
&
obj
<
&
objects
[
0
])
||
(
&
obj
>
&
objects
[
capacity
-
1
]))
{
if
((
&
obj
<
&
objects_array_
[
0
])
||
(
&
obj
>
&
objects_array_
[
value_pool_size_
-
1
]))
{
return
false
;
return
false
;
}
else
{
}
else
{
return
true
;
return
true
;
...
@@ -94,17 +95,17 @@ template<class Type, typename ValuePool, class ObjectAllocator>
...
@@ -94,17 +95,17 @@ template<class Type, typename ValuePool, class ObjectAllocator>
int
ObjectPool
<
Type
,
ValuePool
,
ObjectAllocator
>::
int
ObjectPool
<
Type
,
ValuePool
,
ObjectAllocator
>::
GetIndexOfObject
(
const
Type
&
obj
)
const
{
GetIndexOfObject
(
const
Type
&
obj
)
const
{
assert
(
IsContained
(
obj
));
assert
(
IsContained
(
obj
));
return
(
static_cast
<
int
>
(
&
obj
-
&
objects
[
0
]));
return
(
static_cast
<
int
>
(
&
obj
-
&
objects
_array_
[
0
]));
}
}
template
<
class
Type
,
typename
ValuePool
,
class
ObjectAllocator
>
template
<
class
Type
,
typename
ValuePool
,
class
ObjectAllocator
>
Type
*
ObjectPool
<
Type
,
ValuePool
,
ObjectAllocator
>::
AllocateRaw
()
{
Type
*
ObjectPool
<
Type
,
ValuePool
,
ObjectAllocator
>::
AllocateRaw
()
{
bool
val
;
bool
val
;
int
allocated_index
=
p
.
Allocate
(
val
);
int
allocated_index
=
value_pool_
.
Allocate
(
val
);
if
(
allocated_index
==
-
1
)
{
if
(
allocated_index
==
-
1
)
{
return
NULL
;
return
NULL
;
}
else
{
}
else
{
Type
*
ret_pointer
=
&
(
objects
[
allocated_index
]);
Type
*
ret_pointer
=
&
(
objects
_array_
[
allocated_index
]);
return
ret_pointer
;
return
ret_pointer
;
}
}
...
@@ -112,15 +113,17 @@ Type* ObjectPool<Type, ValuePool, ObjectAllocator>::AllocateRaw() {
...
@@ -112,15 +113,17 @@ Type* ObjectPool<Type, ValuePool, ObjectAllocator>::AllocateRaw() {
template
<
class
Type
,
typename
ValuePool
,
class
ObjectAllocator
>
template
<
class
Type
,
typename
ValuePool
,
class
ObjectAllocator
>
size_t
ObjectPool
<
Type
,
ValuePool
,
ObjectAllocator
>::
GetCapacity
()
{
size_t
ObjectPool
<
Type
,
ValuePool
,
ObjectAllocator
>::
GetCapacity
()
{
return
capacity
;
return
capacity
_
;
}
}
template
<
class
Type
,
typename
ValuePool
,
class
ObjectAllocator
>
template
<
class
Type
,
typename
ValuePool
,
class
ObjectAllocator
>
ObjectPool
<
Type
,
ValuePool
,
ObjectAllocator
>::
ObjectPool
(
size_t
capacity
)
:
ObjectPool
<
Type
,
ValuePool
,
ObjectAllocator
>::
ObjectPool
(
size_t
capacity
)
:
capacity
(
capacity
),
capacity_
(
capacity
),
p
(
ReturningTrueIterator
(
0
),
ReturningTrueIterator
(
capacity
))
{
value_pool_size_
(
// Allocate the objects (without construction, just get the memory)
ValuePool
::
GetMinimumElementCountForGuaranteedCapacity
(
capacity
)),
objects
=
objectAllocator
.
allocate
(
capacity
);
value_pool_
(
ReturningTrueIterator
(
0
),
ReturningTrueIterator
(
value_pool_size_
)),
objects_array_
(
object_allocator_
.
allocate
(
value_pool_size_
))
{
}
}
template
<
class
Type
,
typename
ValuePool
,
class
ObjectAllocator
>
template
<
class
Type
,
typename
ValuePool
,
class
ObjectAllocator
>
...
@@ -128,7 +131,7 @@ void ObjectPool<Type, ValuePool, ObjectAllocator>::Free(Type* obj) {
...
@@ -128,7 +131,7 @@ void ObjectPool<Type, ValuePool, ObjectAllocator>::Free(Type* obj) {
int
index
=
GetIndexOfObject
(
*
obj
);
int
index
=
GetIndexOfObject
(
*
obj
);
obj
->~
Type
();
obj
->~
Type
();
p
.
Free
(
true
,
index
);
value_pool_
.
Free
(
true
,
index
);
}
}
template
<
class
Type
,
typename
ValuePool
,
class
ObjectAllocator
>
template
<
class
Type
,
typename
ValuePool
,
class
ObjectAllocator
>
...
@@ -189,7 +192,7 @@ Type* ObjectPool<Type, ValuePool, ObjectAllocator>::Allocate(
...
@@ -189,7 +192,7 @@ Type* ObjectPool<Type, ValuePool, ObjectAllocator>::Allocate(
template
<
class
Type
,
typename
ValuePool
,
class
ObjectAllocator
>
template
<
class
Type
,
typename
ValuePool
,
class
ObjectAllocator
>
ObjectPool
<
Type
,
ValuePool
,
ObjectAllocator
>::~
ObjectPool
()
{
ObjectPool
<
Type
,
ValuePool
,
ObjectAllocator
>::~
ObjectPool
()
{
// Deallocate the objects
// Deallocate the objects
object
Allocator
.
deallocate
(
objects
,
capacity
);
object
_allocator_
.
deallocate
(
objects_array_
,
value_pool_size_
);
}
}
}
// namespace containers
}
// namespace containers
}
// namespace embb
}
// namespace embb
...
...
containers_cpp/include/embb/containers/internal/wait_free_array_value_pool-inl.h
View file @
5192f502
...
@@ -35,21 +35,21 @@ Free(Type element, int index) {
...
@@ -35,21 +35,21 @@ Free(Type element, int index) {
assert
(
element
!=
Undefined
);
assert
(
element
!=
Undefined
);
// Just put back the element
// Just put back the element
pool
[
index
].
Store
(
element
);
pool
_array_
[
index
].
Store
(
element
);
}
}
template
<
typename
Type
,
Type
Undefined
,
class
Allocator
>
template
<
typename
Type
,
Type
Undefined
,
class
Allocator
>
int
WaitFreeArrayValuePool
<
Type
,
Undefined
,
Allocator
>::
int
WaitFreeArrayValuePool
<
Type
,
Undefined
,
Allocator
>::
Allocate
(
Type
&
element
)
{
Allocate
(
Type
&
element
)
{
for
(
int
i
=
0
;
i
!=
size
;
++
i
)
{
for
(
int
i
=
0
;
i
!=
size
_
;
++
i
)
{
Type
expected
;
Type
expected
;
// If the memory cell is not available, go ahead
// If the memory cell is not available, go ahead
if
(
Undefined
==
(
expected
=
pool
[
i
].
Load
()))
if
(
Undefined
==
(
expected
=
pool
_array_
[
i
].
Load
()))
continue
;
continue
;
// Try to get the memory cell
// Try to get the memory cell
if
(
pool
[
i
].
CompareAndSwap
(
expected
,
Undefined
))
{
if
(
pool
_array_
[
i
].
CompareAndSwap
(
expected
,
Undefined
))
{
// When the CAS was successful, this element is ours
// When the CAS was successful, this element is ours
element
=
expected
;
element
=
expected
;
return
i
;
return
i
;
...
@@ -64,23 +64,45 @@ WaitFreeArrayValuePool<Type, Undefined, Allocator>::
...
@@ -64,23 +64,45 @@ WaitFreeArrayValuePool<Type, Undefined, Allocator>::
WaitFreeArrayValuePool
(
ForwardIterator
first
,
ForwardIterator
last
)
{
WaitFreeArrayValuePool
(
ForwardIterator
first
,
ForwardIterator
last
)
{
size_t
dist
=
static_cast
<
size_t
>
(
std
::
distance
(
first
,
last
));
size_t
dist
=
static_cast
<
size_t
>
(
std
::
distance
(
first
,
last
));
size
=
static_cast
<
int
>
(
dist
);
size_
=
static_cast
<
int
>
(
dist
);
// conversion may result in negative number. check!
assert
(
size_
>=
0
);
// Use the allocator to allocate an array of size dist
// Use the allocator to allocate an array of size dist
pool
=
allocator
.
allocate
(
dist
);
pool_array_
=
allocator_
.
allocate
(
dist
);
// invoke inplace new for each pool element
for
(
size_t
i
=
0
;
i
!=
dist
;
++
i
)
{
new
(
&
pool_array_
[
i
])
embb
::
base
::
Atomic
<
Type
>
();
}
int
i
=
0
;
int
i
=
0
;
// Store the elements of the range
// Store the elements of the range
for
(
ForwardIterator
curIter
(
first
);
curIter
!=
last
;
++
curIter
)
{
for
(
ForwardIterator
curIter
(
first
);
curIter
!=
last
;
++
curIter
)
{
pool
[
i
++
]
=
*
curIter
;
pool
_array_
[
i
++
]
=
*
curIter
;
}
}
}
}
template
<
typename
Type
,
Type
Undefined
,
class
Allocator
>
template
<
typename
Type
,
Type
Undefined
,
class
Allocator
>
WaitFreeArrayValuePool
<
Type
,
Undefined
,
Allocator
>::~
WaitFreeArrayValuePool
()
{
WaitFreeArrayValuePool
<
Type
,
Undefined
,
Allocator
>::~
WaitFreeArrayValuePool
()
{
allocator
.
deallocate
(
pool
,
(
size_t
)
size
);
// invoke destructor for each pool element
for
(
int
i
=
0
;
i
!=
size_
;
++
i
)
{
pool_array_
[
i
].
~
Atomic
();
}
// free memory
allocator_
.
deallocate
(
pool_array_
,
static_cast
<
size_t
>
(
size_
));
}
}
template
<
typename
Type
,
Type
Undefined
,
class
Allocator
>
size_t
WaitFreeArrayValuePool
<
Type
,
Undefined
,
Allocator
>::
GetMinimumElementCountForGuaranteedCapacity
(
size_t
capacity
)
{
// for this value pool, this is just capacity...
return
capacity
;
}
}
// namespace containers
}
// namespace containers
}
// namespace embb
}
// namespace embb
...
...
containers_cpp/include/embb/containers/lock_free_tree_value_pool.h
View file @
5192f502
...
@@ -123,22 +123,25 @@ class LockFreeTreeValuePool {
...
@@ -123,22 +123,25 @@ class LockFreeTreeValuePool {
LockFreeTreeValuePool
&
operator
=
(
const
LockFreeTreeValuePool
&
);
LockFreeTreeValuePool
&
operator
=
(
const
LockFreeTreeValuePool
&
);
// See algorithm description above
// See algorithm description above
int
size
;
int
size
_
;
// See algorithm description above
// See algorithm description above
int
tree_size
;
int
tree_size
_
;
// See algorithm description above
// See algorithm description above
int
real_size
;
int
real_size
_
;
// The tree above the pool
// The tree above the pool
embb
::
base
::
Atomic
<
int
>*
tree
;
embb
::
base
::
Atomic
<
int
>*
tree
_
;
// The actual pool
// The actual pool
embb
::
base
::
Atomic
<
Type
>*
pool
;
embb
::
base
::
Atomic
<
Type
>*
pool
_
;
PoolAllocator
poolAllocator
;
// respective allocator
TreeAllocator
treeAllocator
;
PoolAllocator
pool_allocator_
;
// respective allocator
TreeAllocator
tree_allocator_
;
/**
/**
* Computes smallest power of two fitting the specified value
* Computes smallest power of two fitting the specified value
...
@@ -278,6 +281,18 @@ class LockFreeTreeValuePool {
...
@@ -278,6 +281,18 @@ class LockFreeTreeValuePool {
);
);
/**
/**
* Due to concurrency effects, a pool might provide less elements than managed
* by it. However, usually one wants to guarantee a minimal capacity. The
* count of elements, that must be given to the pool when to guarantee \c
* capacity elements is computed using this function.
*
* \return count of indices the pool has to be initialized with
*/
static
size_t
GetMinimumElementCountForGuaranteedCapacity
(
size_t
capacity
/**< [IN] count of indices that shall be guaranteed */
);
/**
* Destructs the pool.
* Destructs the pool.
*
*
* \notthreadsafe
* \notthreadsafe
...
...
containers_cpp/include/embb/containers/object_pool.h
View file @
5192f502
...
@@ -35,7 +35,6 @@
...
@@ -35,7 +35,6 @@
namespace
embb
{
namespace
embb
{
namespace
containers
{
namespace
containers
{
/**
/**
* \defgroup CPP_CONTAINERS_POOLS Pools
* \defgroup CPP_CONTAINERS_POOLS Pools
* Concurrent pools
* Concurrent pools
...
@@ -62,22 +61,29 @@ class ObjectPool {
...
@@ -62,22 +61,29 @@ class ObjectPool {
/**
/**
* Allocator used to allocate elements of the object pool
* Allocator used to allocate elements of the object pool
*/
*/
ObjectAllocator
object
Allocator
;
ObjectAllocator
object
_allocator_
;
/**
/**
*
Array holding the allocated object
*
Capacity of the object pool
*/
*/
Type
*
objects
;
size_t
capacity_
;
/**
/**
* Capacity of the object pool
* The size of the underlying value pool. This is also the size of the object
* array in this class. It is assumed, that the valuepool manages indices in
* range [0;value_pool_size_-1].
*/
*/
size_t
capacity
;
size_t
value_pool_size_
;
/**
/**
* Underlying value pool
* Underlying value pool
*/
*/
ValuePool
p
;
ValuePool
value_pool_
;
/**
* Array holding the allocated object
*/
Type
*
objects_array_
;
/**
/**
* Helper providing a virtual iterator that just returns true in each
* Helper providing a virtual iterator that just returns true in each
...
...
containers_cpp/include/embb/containers/wait_free_array_value_pool.h
View file @
5192f502
...
@@ -39,12 +39,30 @@ namespace containers {
...
@@ -39,12 +39,30 @@ namespace containers {
* \ingroup CPP_CONCEPT
* \ingroup CPP_CONCEPT
* \{
* \{
* \par Description
* \par Description
* A value pool is a fixed-size multiset of elements, where each element has a
* A value pool is a multi-set of elements, where each element has a unique,
* unique index. The elements cannot be modified and are given at construction
* continuous (starting with 0) index. The elements cannot be modified and are
* time (by providing first/last iterators). A value pool provides two
* given at construction time by providing first/last iterators.
* operations: \c Allocate and \c Free. \c Allocate removes an element from the
*
* pool, and \c Free returns an element to the pool. It is only allowed to
* \par
* free elements that have previously been allocated.
* A value pool provides two primary operations: \c Allocate and \c Free. \c
* Allocate allocates an element/index "pair" (index via return, element via
* reference parameter) from the pool, and \c Free returns an element/index pair
* to the pool. To guarantee linearizability, \c element is not allowed to be
* modified between \c Allocate and \c Free. It is only allowed to free elements
* that have previously been allocated. The \c Allocate function does not
* guarantee an order on which indices are allocated. The count of elements that
* can be allocated with \c Allocate might be smaller than the count of
* elements, the pool is initialized with. This might be because of
* implementation details and respective concurrency effects: for example, if
* indices are managed within a queue, one has to protect queue elements from
* concurrency effects (reuse and access). As long as a thread potentially
* accesses a node (and with that an index), the respective index cannot not be
* given out to the user, even if being logically not part of the pool anymore.
* However, the user might want to guarantee a certain amount of indices to the
* user. Therefore, the static \c GetMinimumElementCountForGuaranteedCapacity
* method is used. The user passes the count of indices to this method, that
* shall be guaranteed by the pool. The method returns the count on indices, the
* pool has to be initialized with in order to guarantee this count on indices.
*
*
* \par Requirements
* \par Requirements
* - Let \c Pool be the pool class
* - Let \c Pool be the pool class
...
@@ -54,6 +72,7 @@ namespace containers {
...
@@ -54,6 +72,7 @@ namespace containers {
* - Let \c i, j be forward iterators supporting \c std::distance.
* - Let \c i, j be forward iterators supporting \c std::distance.
* - Let \c c be an object of type \c Type&
* - Let \c c be an object of type \c Type&
* - Let \c e be a value of type \c int
* - Let \c e be a value of type \c int
* - Let \c f be a value of type \c int
*
*
* \par Valid Expressions
* \par Valid Expressions
*
*
...
@@ -72,7 +91,7 @@ namespace containers {
...
@@ -72,7 +91,7 @@ namespace containers {
* the bottom element. The bottom element cannot be stored in the pool, it
* the bottom element. The bottom element cannot be stored in the pool, it
* is exclusively used to mark empty cells. The pool initially contains
* is exclusively used to mark empty cells. The pool initially contains
* \c std::distance(i, j) elements which are copied during construction from
* \c std::distance(i, j) elements which are copied during construction from
* the range \c [i, j
)
. A concrete class satisfying the value pool concept
* the range \c [i, j
]
. A concrete class satisfying the value pool concept
* might provide additional template parameters for specifying allocators.
* might provide additional template parameters for specifying allocators.
* </td>
* </td>
* </tr>
* </tr>
...
@@ -80,9 +99,10 @@ namespace containers {
...
@@ -80,9 +99,10 @@ namespace containers {
* <td>\code{.cpp} Allocate(c) \endcode</td>
* <td>\code{.cpp} Allocate(c) \endcode</td>
* <td>\c int</td>
* <td>\c int</td>
* <td>
* <td>
* Gets an element from the pool. Returns -1, if no element is available,
* Allocates an element/index "pair" from the pool. Returns -1, if no
* i.e., the pool is empty. Otherwise, returns the index of the element in
* element is available, i.e., the pool is empty. Otherwise, returns the
* the pool. The value of the pool element is written into reference \c c.
* index of the element in the pool. The value of the pool element is
* written into parameter reference \c c.
* </td>
* </td>
* </tr>
* </tr>
* <tr>
* <tr>
...
@@ -93,6 +113,15 @@ namespace containers {
...
@@ -93,6 +113,15 @@ namespace containers {
* \c Allocate. For each allocated element, \c Free must be called exactly
* \c Allocate. For each allocated element, \c Free must be called exactly
* once.</td>
* once.</td>
* </tr>
* </tr>
* <tr>
* <td>\code{.cpp} GetMinimumElementCountForGuaranteedCapacity(f)
* \endcode</td>
* <td>\c void</td>
* <td>Static method, returns the count of indices, the user has to
* initialize the pool with in order to guarantee a count of \c f elements
* (irrespective of concurrency effects).
* </td>
* </tr>
* </table>
* </table>
*
*
* \}
* \}
...
@@ -116,10 +145,10 @@ template<typename Type,
...
@@ -116,10 +145,10 @@ template<typename Type,
class
Allocator
=
embb
::
base
::
Allocator
<
embb
::
base
::
Atomic
<
Type
>
>
>
class
Allocator
=
embb
::
base
::
Allocator
<
embb
::
base
::
Atomic
<
Type
>
>
>
class
WaitFreeArrayValuePool
{
class
WaitFreeArrayValuePool
{
private
:
private
:
int
size
;
int
size
_
;
embb
::
base
::
Atomic
<
Type
>*
pool
;
embb
::
base
::
Atomic
<
Type
>*
pool
_array_
;
WaitFreeArrayValuePool
();
WaitFreeArrayValuePool
();
Allocator
allocator
;
Allocator
allocator
_
;
// Prevent copy-construction
// Prevent copy-construction
WaitFreeArrayValuePool
(
const
WaitFreeArrayValuePool
&
);
WaitFreeArrayValuePool
(
const
WaitFreeArrayValuePool
&
);
...
@@ -150,6 +179,18 @@ class WaitFreeArrayValuePool {
...
@@ -150,6 +179,18 @@ class WaitFreeArrayValuePool {
);
);
/**
/**
* Due to concurrency effects, a pool might provide less elements than managed
* by it. However, usually one wants to guarantee a minimal capacity. The
* count of elements, that must be given to the pool when to guarantee \c
* capacity elements is computed using this function.
*
* \return count of indices the pool has to be initialized with
*/
static
size_t
GetMinimumElementCountForGuaranteedCapacity
(
size_t
capacity
/**< [IN] count of indices that shall be guaranteed */
);
/**
* Destructs the pool.
* Destructs the pool.
*
*
* \notthreadsafe
* \notthreadsafe
...
...
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