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
df279e99
authored
Apr 14, 2015
by
Tobias Fuchs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
containers_cpp: interface of IndexedObjectPool conforming to ObjectPool
parent
d3a090c3
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
183 additions
and
100 deletions
+183
-100
containers_cpp/include/embb/containers/internal/indexed_object_pool-inl.h
+89
-28
containers_cpp/include/embb/containers/internal/indexed_object_pool.h
+41
-16
containers_cpp/include/embb/containers/internal/wait_free_mpmc_queue-inl.h
+48
-51
containers_cpp/include/embb/containers/wait_free_mpmc_queue.h
+5
-5
No files found.
containers_cpp/include/embb/containers/internal/indexed_object_pool-inl.h
View file @
df279e99
...
@@ -33,9 +33,9 @@ namespace embb {
...
@@ -33,9 +33,9 @@ namespace embb {
namespace
containers
{
namespace
containers
{
namespace
internal
{
namespace
internal
{
template
<
typename
T
,
class
IndexPool
,
class
Allocator
>
template
<
typename
T
ype
,
class
IndexPool
,
class
Allocator
>
template
<
typename
RAI
>
template
<
typename
RAI
>
IndexedObjectPool
<
T
,
IndexPool
,
Allocator
>::
IndexedObjectPool
<
T
ype
,
IndexPool
,
Allocator
>::
IndexedObjectPool
(
RAI
first
,
RAI
last
)
:
IndexedObjectPool
(
RAI
first
,
RAI
last
)
:
size_
(
static_cast
<
size_t
>
(
std
::
distance
(
first
,
last
))),
size_
(
static_cast
<
size_t
>
(
std
::
distance
(
first
,
last
))),
indexPool
(
internal
::
ReturningTrueIterator
(
0
),
indexPool
(
internal
::
ReturningTrueIterator
(
0
),
...
@@ -50,9 +50,9 @@ IndexedObjectPool(RAI first, RAI last) :
...
@@ -50,9 +50,9 @@ IndexedObjectPool(RAI first, RAI last) :
}
}
}
}
template
<
typename
T
,
class
IndexPool
,
class
Allocator
>
template
<
typename
T
ype
,
class
IndexPool
,
class
Allocator
>
IndexedObjectPool
<
T
,
IndexPool
,
Allocator
>::
IndexedObjectPool
<
T
ype
,
IndexPool
,
Allocator
>::
IndexedObjectPool
(
size_t
size
,
const
T
&
defaultInstance
)
:
IndexedObjectPool
(
size_t
size
,
const
T
ype
&
defaultInstance
)
:
size_
(
size
),
size_
(
size
),
indexPool
(
internal
::
ReturningTrueIterator
(
0
),
indexPool
(
internal
::
ReturningTrueIterator
(
0
),
internal
::
ReturningTrueIterator
(
size_
))
{
internal
::
ReturningTrueIterator
(
size_
))
{
...
@@ -66,42 +66,103 @@ IndexedObjectPool(size_t size, const T & defaultInstance) :
...
@@ -66,42 +66,103 @@ IndexedObjectPool(size_t size, const T & defaultInstance) :
}
}
}
}
template
<
typename
T
,
class
IndexPool
,
class
Allocator
>
template
<
typename
T
ype
,
class
IndexPool
,
class
Allocator
>
IndexedObjectPool
<
T
,
IndexPool
,
Allocator
>::
IndexedObjectPool
<
T
ype
,
IndexPool
,
Allocator
>::
~
IndexedObjectPool
()
{
~
IndexedObjectPool
()
{
allocator
.
deallocate
(
elements
,
size_
);
allocator
.
deallocate
(
elements
,
size_
);
}
}
template
<
typename
T
,
class
IndexPool
,
class
Allocator
>
template
<
typename
Type
,
class
IndexPool
,
class
Allocator
>
int
IndexedObjectPool
<
T
,
IndexPool
,
Allocator
>::
void
IndexedObjectPool
<
Type
,
IndexPool
,
Allocator
>::
Allocate
(
T
&
element
)
{
// Reserve a pool index:
bool
reservedFlag
;
int
index
=
indexPool
.
Allocate
(
reservedFlag
);
// Assign element to be allocated at pool index.
// Index returned from index pool is -1 if no index
// is available.
if
(
index
>=
0
)
{
element
=
elements
[
index
];
}
return
index
;
}
template
<
typename
T
,
class
IndexPool
,
class
Allocator
>
void
IndexedObjectPool
<
T
,
IndexPool
,
Allocator
>::
Free
(
int
elementIndex
)
{
Free
(
int
elementIndex
)
{
// Call the referenced element's destructor:
// Call the referenced element's destructor:
elements
[
elementIndex
].
~
T
();
elements
[
elementIndex
].
~
T
ype
();
// Release index of the element for reuse:
// Release index of the element for reuse:
indexPool
.
Free
(
true
,
elementIndex
);
indexPool
.
Free
(
true
,
elementIndex
);
}
}
template
<
typename
T
,
class
IndexPool
,
class
Allocator
>
template
<
typename
T
ype
,
class
IndexPool
,
class
Allocator
>
T
&
IndexedObjectPool
<
T
,
IndexPool
,
Allocator
>::
T
ype
&
IndexedObjectPool
<
Type
,
IndexPool
,
Allocator
>::
operator
[](
size_
t
elementIndex
)
{
operator
[](
in
t
elementIndex
)
{
return
elements
[
elementIndex
];
return
elements
[
elementIndex
];
}
}
template
<
class
Type
,
typename
ValuePool
,
class
ObjectAllocator
>
int
IndexedObjectPool
<
Type
,
ValuePool
,
ObjectAllocator
>::
AllocateRaw
(
Type
*
&
newElement
)
{
newElement
=
NULL
;
// Reserve a pool index:
bool
val
;
int
allocated_index
=
indexPool
.
Allocate
(
val
);
if
(
allocated_index
>=
0
)
{
// Return pointer to reserved element:
Type
*
ret_pointer
=
&
(
elements
[
allocated_index
]);
newElement
=
ret_pointer
;
}
return
allocated_index
;
}
template
<
typename
Type
,
class
IndexPool
,
class
Allocator
>
int
IndexedObjectPool
<
Type
,
IndexPool
,
Allocator
>::
Allocate
()
{
Type
*
raw_object
=
NULL
;
int
element_index
=
AllocateRaw
(
raw_object
);
if
(
element_index
>=
0
&&
raw_object
!=
NULL
)
{
new
(
raw_object
)
Type
();
}
return
element_index
;
}
template
<
typename
Type
,
class
IndexPool
,
class
Allocator
>
template
<
typename
Param1
>
int
IndexedObjectPool
<
Type
,
IndexPool
,
Allocator
>::
Allocate
(
Param1
const
&
param1
)
{
Type
*
raw_object
=
NULL
;
int
element_index
=
AllocateRaw
(
raw_object
);
if
(
element_index
>=
0
&&
raw_object
!=
NULL
)
{
new
(
raw_object
)
Type
(
param1
);
}
return
element_index
;
}
template
<
typename
Type
,
class
IndexPool
,
class
Allocator
>
template
<
typename
Param1
,
typename
Param2
>
int
IndexedObjectPool
<
Type
,
IndexPool
,
Allocator
>::
Allocate
(
Param1
const
&
param1
,
Param2
const
&
param2
)
{
Type
*
raw_object
=
NULL
;
int
element_index
=
AllocateRaw
(
raw_object
);
if
(
element_index
>=
0
&&
raw_object
!=
NULL
)
{
new
(
raw_object
)
Type
(
param1
,
param2
);
}
return
element_index
;
}
template
<
typename
Type
,
class
IndexPool
,
class
Allocator
>
template
<
typename
Param1
,
typename
Param2
,
typename
Param3
>
int
IndexedObjectPool
<
Type
,
IndexPool
,
Allocator
>::
Allocate
(
Param1
const
&
param1
,
Param2
const
&
param2
,
Param3
const
&
param3
)
{
Type
*
raw_object
=
NULL
;
int
element_index
=
AllocateRaw
(
raw_object
);
if
(
element_index
>=
0
&&
raw_object
!=
NULL
)
{
new
(
raw_object
)
Type
(
param1
,
param2
,
param3
);
}
return
element_index
;
}
template
<
typename
Type
,
class
IndexPool
,
class
Allocator
>
template
<
typename
Param1
,
typename
Param2
,
typename
Param3
,
typename
Param4
>
int
IndexedObjectPool
<
Type
,
IndexPool
,
Allocator
>::
Allocate
(
Param1
const
&
param1
,
Param2
const
&
param2
,
Param3
const
&
param3
,
Param4
const
&
param4
)
{
Type
*
raw_object
=
NULL
;
int
element_index
=
AllocateRaw
(
raw_object
);
if
(
element_index
>=
0
&&
raw_object
!=
NULL
)
{
new
(
raw_object
)
Type
(
param1
,
param2
,
param3
,
param4
);
}
return
element_index
;
}
}
// namespace internal
}
// namespace internal
}
// namespace containers
}
// namespace containers
}
// namespace embb
}
// namespace embb
...
...
containers_cpp/include/embb/containers/internal/indexed_object_pool.h
View file @
df279e99
...
@@ -38,14 +38,14 @@ namespace containers {
...
@@ -38,14 +38,14 @@ namespace containers {
namespace
internal
{
namespace
internal
{
template
<
template
<
typename
T
,
typename
T
ype
,
class
IndexPool
=
LockFreeTreeValuePool
<
bool
,
false
>
,
class
IndexPool
=
LockFreeTreeValuePool
<
bool
,
false
>
,
class
Allocator
=
embb
::
base
::
Allocator
<
T
>
class
Allocator
=
embb
::
base
::
Allocator
<
T
>
>
>
class
IndexedObjectPool
{
class
IndexedObjectPool
{
private
:
private
:
const
size_t
size_
;
const
size_t
size_
;
T
*
elements
;
T
ype
*
elements
;
Allocator
allocator
;
Allocator
allocator
;
IndexPool
indexPool
;
IndexPool
indexPool
;
IndexedObjectPool
();
IndexedObjectPool
();
...
@@ -53,10 +53,13 @@ class IndexedObjectPool {
...
@@ -53,10 +53,13 @@ class IndexedObjectPool {
IndexedObjectPool
(
const
IndexedObjectPool
&
);
IndexedObjectPool
(
const
IndexedObjectPool
&
);
// Prevent assignment
// Prevent assignment
IndexedObjectPool
&
operator
=
(
const
IndexedObjectPool
&
);
IndexedObjectPool
&
operator
=
(
const
IndexedObjectPool
&
);
// Allocates pool index and resolves pointer to reserved element
int
AllocateRaw
(
Type
*
&
newElement
);
public
:
public
:
/**
/**
* \see value_pool_concept
* Creates an indexed object pool, initializing all pool elements
* with elements from given range.
*
*
* \notthreadsafe
* \notthreadsafe
*
*
...
@@ -73,7 +76,8 @@ class IndexedObjectPool {
...
@@ -73,7 +76,8 @@ class IndexedObjectPool {
);
);
/**
/**
* \see value_pool_concept
* Creates an indexed object pool of size \c capacity, initializing
* all pool elements with given default instance.
*
*
* \notthreadsafe
* \notthreadsafe
*
*
...
@@ -84,7 +88,7 @@ class IndexedObjectPool {
...
@@ -84,7 +88,7 @@ class IndexedObjectPool {
IndexedObjectPool
(
IndexedObjectPool
(
size_t
size
,
size_t
size
,
/**< [IN] Number of elements the pool is filled with */
/**< [IN] Number of elements the pool is filled with */
const
T
&
defaultInstance
const
T
ype
&
defaultInstance
/**< [IN] Default instance to initialize pool elements with */
/**< [IN] Default instance to initialize pool elements with */
);
);
...
@@ -94,16 +98,6 @@ class IndexedObjectPool {
...
@@ -94,16 +98,6 @@ class IndexedObjectPool {
~
IndexedObjectPool
();
~
IndexedObjectPool
();
/**
/**
* Request element and index from pool.
*
* \return index of element
*
* \see object_pool_concept
*
*/
int
Allocate
(
T
&
element
);
/**
* Return element and index to the pool.
* Return element and index to the pool.
*
*
* \see value_pool_concept
* \see value_pool_concept
...
@@ -117,7 +111,38 @@ class IndexedObjectPool {
...
@@ -117,7 +111,38 @@ class IndexedObjectPool {
* \see object_pool_concept
* \see object_pool_concept
*
*
*/
*/
T
&
operator
[](
size_t
elementIndex
);
Type
&
operator
[](
int
elementIndex
);
#ifdef DOXYGEN
/**
* Allocates an element from the pool.
*
* If the underlying value pool is wait-free/lock-free, this operation is
* also wait-free/lock-free, respectively.
*
* \return Index of the allocated object if successful, otherwise \c -1.
*
* \param ... Arguments of arbitrary type, passed to the object's constructor
*/
int
Allocate
(...);
#else
int
Allocate
();
template
<
typename
Param1
>
int
Allocate
(
Param1
const
&
param1
);
template
<
typename
Param1
,
typename
Param2
>
int
Allocate
(
Param1
const
&
param1
,
Param2
const
&
param2
);
template
<
typename
Param1
,
typename
Param2
,
typename
Param3
>
int
Allocate
(
Param1
const
&
param1
,
Param2
const
&
param2
,
Param3
const
&
param3
);
template
<
typename
Param1
,
typename
Param2
,
typename
Param3
,
typename
Param4
>
int
Allocate
(
Param1
const
&
param1
,
Param2
const
&
param2
,
Param3
const
&
param3
,
Param4
const
&
param4
);
#endif
};
};
}
// namespace internal
}
// namespace internal
...
...
containers_cpp/include/embb/containers/internal/wait_free_mpmc_queue-inl.h
View file @
df279e99
...
@@ -90,7 +90,7 @@ bool WaitFreeMPMCQueueNode<Type>::CASNext(
...
@@ -90,7 +90,7 @@ bool WaitFreeMPMCQueueNode<Type>::CASNext(
}
}
template
<
typename
Type
>
template
<
typename
Type
>
bool
WaitFreeMPMCQueueNode
<
Type
>::
Next
_
IsNull
()
const
{
bool
WaitFreeMPMCQueueNode
<
Type
>::
NextIsNull
()
const
{
return
next_idx
.
Load
()
==
UndefinedIndex
;
return
next_idx
.
Load
()
==
UndefinedIndex
;
}
}
...
@@ -112,8 +112,8 @@ const uint32_t WaitFreeMPMCQueueNode<Type>::UndefinedIndex = 0x3fffffff;
...
@@ -112,8 +112,8 @@ const uint32_t WaitFreeMPMCQueueNode<Type>::UndefinedIndex = 0x3fffffff;
}
// namespace internal
}
// namespace internal
template
<
template
<
typename
Type
,
class
NodeAllocator
,
class
OpAllocator
,
class
ValuePool
>
typename
Type
,
class
ValuePool
,
class
NodeAllocator
,
class
OpAllocator
>
WaitFreeMPMCQueue
<
Type
,
NodeAllocator
,
OpAllocator
,
ValuePool
>::
OperationDesc
::
WaitFreeMPMCQueue
<
Type
,
ValuePool
,
NodeAllocator
,
OpAllocator
>::
OperationDesc
::
OperationDesc
(
OperationDesc
(
bool
pending
,
bool
pending
,
bool
enqueue
,
bool
enqueue
,
...
@@ -133,8 +133,8 @@ OperationDesc(
...
@@ -133,8 +133,8 @@ OperationDesc(
}
}
template
<
template
<
typename
Type
,
class
NodeAllocator
,
class
OpAllocator
,
class
ValuePool
>
typename
Type
,
class
ValuePool
,
class
NodeAllocator
,
class
OpAllocator
>
WaitFreeMPMCQueue
<
Type
,
NodeAllocator
,
OpAllocator
,
ValuePool
>::
OperationDesc
::
WaitFreeMPMCQueue
<
Type
,
ValuePool
,
NodeAllocator
,
OpAllocator
>::
OperationDesc
::
OperationDesc
(
index_t
raw
)
:
Raw
(
raw
)
{
OperationDesc
(
index_t
raw
)
:
Raw
(
raw
)
{
Pending
=
(
raw
&
PENDING_FLAG_MASK
)
?
true
:
false
;
Pending
=
(
raw
&
PENDING_FLAG_MASK
)
?
true
:
false
;
Enqueue
=
(
raw
&
ENQUEUE_FLAG_MASK
)
?
true
:
false
;
Enqueue
=
(
raw
&
ENQUEUE_FLAG_MASK
)
?
true
:
false
;
...
@@ -142,8 +142,8 @@ OperationDesc(index_t raw) : Raw(raw) {
...
@@ -142,8 +142,8 @@ OperationDesc(index_t raw) : Raw(raw) {
}
}
template
<
template
<
typename
Type
,
class
NodeAllocator
,
class
OpAllocator
,
class
ValuePool
>
typename
Type
,
class
ValuePool
,
class
NodeAllocator
,
class
OpAllocator
>
WaitFreeMPMCQueue
<
Type
,
NodeAllocator
,
OpAllocator
,
ValuePool
>::
WaitFreeMPMCQueue
<
Type
,
ValuePool
,
NodeAllocator
,
OpAllocator
>::
WaitFreeMPMCQueue
(
size_t
capacity
)
WaitFreeMPMCQueue
(
size_t
capacity
)
:
max_size_
(
capacity
),
:
max_size_
(
capacity
),
// Disable "this is used in base member initializer" warning.
// Disable "this is used in base member initializer" warning.
...
@@ -178,9 +178,10 @@ WaitFreeMPMCQueue(size_t capacity)
...
@@ -178,9 +178,10 @@ WaitFreeMPMCQueue(size_t capacity)
"Maximum size of queue exceeded"
);
"Maximum size of queue exceeded"
);
}
}
// Allocate sentinel node:
// Allocate sentinel node:
Node_t
sentinelNode
;
int
sentinelNodePoolIndex
=
nodePool
.
Allocate
();
assert
(
sentinelNode
.
NextPoolIdx
()
==
Node_t
::
UndefinedIndex
);
assert
(
int
sentinelNodePoolIndex
=
nodePool
.
Allocate
(
sentinelNode
);
nodePool
[
sentinelNodePoolIndex
].
NextPoolIdx
()
==
Node_t
::
UndefinedIndex
);
if
(
sentinelNodePoolIndex
<
0
)
{
if
(
sentinelNodePoolIndex
<
0
)
{
EMBB_THROW
(
embb
::
base
::
NoMemoryException
,
EMBB_THROW
(
embb
::
base
::
NoMemoryException
,
"Allocation of sentinel node failed"
);
"Allocation of sentinel node failed"
);
...
@@ -209,8 +210,8 @@ WaitFreeMPMCQueue(size_t capacity)
...
@@ -209,8 +210,8 @@ WaitFreeMPMCQueue(size_t capacity)
}
}
template
<
template
<
typename
Type
,
class
NodeAllocator
,
class
OpAllocator
,
class
ValuePool
>
typename
Type
,
class
ValuePool
,
class
NodeAllocator
,
class
OpAllocator
>
WaitFreeMPMCQueue
<
Type
,
NodeAllocator
,
OpAllocator
,
ValuePool
>::
WaitFreeMPMCQueue
<
Type
,
ValuePool
,
NodeAllocator
,
OpAllocator
>::
~
WaitFreeMPMCQueue
()
{
~
WaitFreeMPMCQueue
()
{
// Dequeue until queue is empty:
// Dequeue until queue is empty:
Type
val
;
Type
val
;
...
@@ -221,8 +222,8 @@ WaitFreeMPMCQueue<Type, NodeAllocator, OpAllocator, ValuePool>::
...
@@ -221,8 +222,8 @@ WaitFreeMPMCQueue<Type, NodeAllocator, OpAllocator, ValuePool>::
}
}
template
<
template
<
typename
Type
,
class
NodeAllocator
,
class
OpAllocator
,
class
ValuePool
>
typename
Type
,
class
ValuePool
,
class
NodeAllocator
,
class
OpAllocator
>
inline
bool
WaitFreeMPMCQueue
<
Type
,
NodeAllocator
,
OpAllocator
,
ValuePool
>::
inline
bool
WaitFreeMPMCQueue
<
Type
,
ValuePool
,
NodeAllocator
,
OpAllocator
>::
LoadAccessorThreadIndex
(
index_t
&
retIndexValue
)
{
LoadAccessorThreadIndex
(
index_t
&
retIndexValue
)
{
unsigned
int
tmpIndexValue
;
// For conversion size32_t <-> unsigned int
unsigned
int
tmpIndexValue
;
// For conversion size32_t <-> unsigned int
if
(
embb_internal_thread_index
(
&
tmpIndexValue
)
==
EMBB_SUCCESS
)
{
if
(
embb_internal_thread_index
(
&
tmpIndexValue
)
==
EMBB_SUCCESS
)
{
...
@@ -238,8 +239,8 @@ LoadAccessorThreadIndex(index_t & retIndexValue) {
...
@@ -238,8 +239,8 @@ LoadAccessorThreadIndex(index_t & retIndexValue) {
}
}
template
<
template
<
typename
Type
,
class
NodeAllocator
,
class
OpAllocator
,
class
ValuePool
>
typename
Type
,
class
ValuePool
,
class
NodeAllocator
,
class
OpAllocator
>
inline
size_t
WaitFreeMPMCQueue
<
Type
,
NodeAllocator
,
OpAllocator
,
ValuePool
>::
inline
size_t
WaitFreeMPMCQueue
<
Type
,
ValuePool
,
NodeAllocator
,
OpAllocator
>::
RetiredListMaxSize
(
size_t
nThreads
)
{
RetiredListMaxSize
(
size_t
nThreads
)
{
return
static_cast
<
size_t
>
(
return
static_cast
<
size_t
>
(
1
.
25
*
1
.
25
*
...
@@ -247,8 +248,8 @@ RetiredListMaxSize(size_t nThreads) {
...
@@ -247,8 +248,8 @@ RetiredListMaxSize(size_t nThreads) {
}
}
template
<
template
<
typename
Type
,
class
NodeAllocator
,
class
OpAllocator
,
class
ValuePool
>
typename
Type
,
class
ValuePool
,
class
NodeAllocator
,
class
OpAllocator
>
bool
WaitFreeMPMCQueue
<
Type
,
NodeAllocator
,
OpAllocator
,
ValuePool
>::
bool
WaitFreeMPMCQueue
<
Type
,
ValuePool
,
NodeAllocator
,
OpAllocator
>::
TryEnqueue
(
Type
const
&
element
)
{
TryEnqueue
(
Type
const
&
element
)
{
index_t
accessorId
=
Node_t
::
UndefinedIndex
;
index_t
accessorId
=
Node_t
::
UndefinedIndex
;
if
(
!
LoadAccessorThreadIndex
(
accessorId
))
{
if
(
!
LoadAccessorThreadIndex
(
accessorId
))
{
...
@@ -256,14 +257,10 @@ TryEnqueue(Type const & element) {
...
@@ -256,14 +257,10 @@ TryEnqueue(Type const & element) {
"Invalid thread ID."
);
"Invalid thread ID."
);
}
}
// Register new node in pool:
// Register new node in pool:
Node_t
poolNode
;
int
nodeIndex
=
nodePool
.
Allocate
(
element
,
accessorId
);
int
nodeIndex
=
nodePool
.
Allocate
(
poolNode
);
if
(
nodeIndex
<
0
)
{
if
(
nodeIndex
<
0
)
{
return
false
;
// Queue is at capacity
return
false
;
// Queue is at capacity
}
}
// Initialize node in pool:
Node_t
newNode
(
element
,
accessorId
);
nodePool
[
static_cast
<
index_t
>
(
nodeIndex
)]
=
newNode
;
OperationDesc
enqOp
(
OperationDesc
enqOp
(
true
,
// pending
true
,
// pending
true
,
// enqueue
true
,
// enqueue
...
@@ -276,8 +273,8 @@ TryEnqueue(Type const & element) {
...
@@ -276,8 +273,8 @@ TryEnqueue(Type const & element) {
}
}
template
<
template
<
typename
Type
,
class
NodeAllocator
,
class
OpAllocator
,
class
ValuePool
>
typename
Type
,
class
ValuePool
,
class
NodeAllocator
,
class
OpAllocator
>
bool
WaitFreeMPMCQueue
<
Type
,
NodeAllocator
,
OpAllocator
,
ValuePool
>::
bool
WaitFreeMPMCQueue
<
Type
,
ValuePool
,
NodeAllocator
,
OpAllocator
>::
TryDequeue
(
Type
&
retElement
)
{
TryDequeue
(
Type
&
retElement
)
{
index_t
accessorId
=
static_cast
<
index_t
>
(
-
1
);
index_t
accessorId
=
static_cast
<
index_t
>
(
-
1
);
if
(
!
LoadAccessorThreadIndex
(
accessorId
))
{
if
(
!
LoadAccessorThreadIndex
(
accessorId
))
{
...
@@ -313,11 +310,11 @@ TryDequeue(Type & retElement) {
...
@@ -313,11 +310,11 @@ TryDequeue(Type & retElement) {
retElement
=
Type
();
retElement
=
Type
();
return
false
;
return
false
;
}
}
Node_t
&
node
=
nodePool
[
nodeIdx
];
Node_t
&
node
=
nodePool
[
static_cast
<
int
>
(
nodeIdx
)
];
assert
(
node
.
DequeueAID
().
Load
()
==
accessorId
);
assert
(
node
.
DequeueAID
().
Load
()
==
accessorId
);
// Return value of node next to node dequeued in this operation:
// Return value of node next to node dequeued in this operation:
index_t
nextNodeIdx
=
node
.
NextPoolIdx
();
index_t
nextNodeIdx
=
node
.
NextPoolIdx
();
retElement
=
nodePool
[
nextNodeIdx
].
Value
();
retElement
=
nodePool
[
static_cast
<
int
>
(
nextNodeIdx
)
].
Value
();
// Value is safe. Mark node as non-pending and available for reclamation by
// Value is safe. Mark node as non-pending and available for reclamation by
// setting this operation's node index to UndefinedIndex:
// setting this operation's node index to UndefinedIndex:
OperationDesc
noOp
(
OperationDesc
noOp
(
...
@@ -338,14 +335,14 @@ TryDequeue(Type & retElement) {
...
@@ -338,14 +335,14 @@ TryDequeue(Type & retElement) {
}
}
template
<
template
<
typename
Type
,
class
NodeAllocator
,
class
OpAllocator
,
class
ValuePool
>
typename
Type
,
class
ValuePool
,
class
NodeAllocator
,
class
OpAllocator
>
void
WaitFreeMPMCQueue
<
Type
,
NodeAllocator
,
OpAllocator
,
ValuePool
>::
void
WaitFreeMPMCQueue
<
Type
,
ValuePool
,
NodeAllocator
,
OpAllocator
>::
HelpEnqueue
(
unsigned
int
accessorId
)
{
HelpEnqueue
(
unsigned
int
accessorId
)
{
while
(
IsPending
(
accessorId
))
{
while
(
IsPending
(
accessorId
))
{
index_t
lastIdx
=
tailIdx
.
Load
();
index_t
lastIdx
=
tailIdx
.
Load
();
// Guard tail:
// Guard tail:
hp
.
GuardPointer
(
0
,
lastIdx
);
hp
.
GuardPointer
(
0
,
lastIdx
);
Node_t
&
lastNode
=
nodePool
[
lastIdx
];
Node_t
&
lastNode
=
nodePool
[
static_cast
<
int
>
(
lastIdx
)
];
index_t
nextIdx
=
lastNode
.
NextPoolIdx
();
index_t
nextIdx
=
lastNode
.
NextPoolIdx
();
if
(
lastIdx
==
tailIdx
.
Load
())
{
if
(
lastIdx
==
tailIdx
.
Load
())
{
// Last node still is tail
// Last node still is tail
...
@@ -369,17 +366,17 @@ HelpEnqueue(unsigned int accessorId) {
...
@@ -369,17 +366,17 @@ HelpEnqueue(unsigned int accessorId) {
}
}
template
<
template
<
typename
Type
,
class
NodeAllocator
,
class
OpAllocator
,
class
ValuePool
>
typename
Type
,
class
ValuePool
,
class
NodeAllocator
,
class
OpAllocator
>
void
WaitFreeMPMCQueue
<
Type
,
NodeAllocator
,
OpAllocator
,
ValuePool
>::
void
WaitFreeMPMCQueue
<
Type
,
ValuePool
,
NodeAllocator
,
OpAllocator
>::
HelpFinishEnqueue
()
{
HelpFinishEnqueue
()
{
// Load node pointed at by tail:
// Load node pointed at by tail:
index_t
lastIdx
=
tailIdx
.
Load
();
index_t
lastIdx
=
tailIdx
.
Load
();
// Guard tail:
// Guard tail:
hp
.
GuardPointer
(
0
,
lastIdx
);
hp
.
GuardPointer
(
0
,
lastIdx
);
// Load tail->next:
// Load tail->next:
Node_t
&
lastNode
=
nodePool
[
lastIdx
];
Node_t
&
lastNode
=
nodePool
[
static_cast
<
int
>
(
lastIdx
)
];
index_t
nextIdx
=
lastNode
.
NextPoolIdx
();
index_t
nextIdx
=
lastNode
.
NextPoolIdx
();
Node_t
&
nextNode
=
nodePool
[
nextIdx
];
Node_t
&
nextNode
=
nodePool
[
static_cast
<
int
>
(
nextIdx
)
];
// tail->next not undefined => unfinished ENQ
// tail->next not undefined => unfinished ENQ
if
(
nextIdx
!=
Node_t
::
UndefinedIndex
)
{
if
(
nextIdx
!=
Node_t
::
UndefinedIndex
)
{
// Load accessor id from last (non-tail) element in list:
// Load accessor id from last (non-tail) element in list:
...
@@ -408,15 +405,15 @@ HelpFinishEnqueue() {
...
@@ -408,15 +405,15 @@ HelpFinishEnqueue() {
}
}
template
<
template
<
typename
Type
,
class
NodeAllocator
,
class
OpAllocator
,
class
ValuePool
>
typename
Type
,
class
ValuePool
,
class
NodeAllocator
,
class
OpAllocator
>
void
WaitFreeMPMCQueue
<
Type
,
NodeAllocator
,
OpAllocator
,
ValuePool
>::
void
WaitFreeMPMCQueue
<
Type
,
ValuePool
,
NodeAllocator
,
OpAllocator
>::
HelpDequeue
(
index_t
accessorId
)
{
HelpDequeue
(
index_t
accessorId
)
{
while
(
IsPending
(
accessorId
))
{
while
(
IsPending
(
accessorId
))
{
index_t
firstIdx
=
headIdx
.
Load
();
index_t
firstIdx
=
headIdx
.
Load
();
// Guard head:
// Guard head:
hp
.
GuardPointer
(
0
,
firstIdx
);
hp
.
GuardPointer
(
0
,
firstIdx
);
// Order matters for these assignments:
// Order matters for these assignments:
Node_t
&
first
=
nodePool
[
firstIdx
];
Node_t
&
first
=
nodePool
[
static_cast
<
int
>
(
firstIdx
)
];
index_t
lastIdx
=
tailIdx
.
Load
();
index_t
lastIdx
=
tailIdx
.
Load
();
index_t
nextIdx
=
first
.
NextPoolIdx
();
index_t
nextIdx
=
first
.
NextPoolIdx
();
// Guard head->next:
// Guard head->next:
...
@@ -499,19 +496,19 @@ HelpDequeue(index_t accessorId) {
...
@@ -499,19 +496,19 @@ HelpDequeue(index_t accessorId) {
}
}
template
<
template
<
typename
Type
,
class
NodeAllocator
,
class
OpAllocator
,
class
ValuePool
>
typename
Type
,
class
ValuePool
,
class
NodeAllocator
,
class
OpAllocator
>
void
WaitFreeMPMCQueue
<
Type
,
NodeAllocator
,
OpAllocator
,
ValuePool
>::
void
WaitFreeMPMCQueue
<
Type
,
ValuePool
,
NodeAllocator
,
OpAllocator
>::
HelpFinishDequeue
()
{
HelpFinishDequeue
()
{
index_t
firstIdx
=
headIdx
.
Load
();
index_t
firstIdx
=
headIdx
.
Load
();
// Guard head:
// Guard head:
hp
.
GuardPointer
(
0
,
firstIdx
);
hp
.
GuardPointer
(
0
,
firstIdx
);
Node_t
&
first
=
nodePool
[
firstIdx
];
Node_t
&
first
=
nodePool
[
static_cast
<
int
>
(
firstIdx
)
];
index_t
nextIdx
=
first
.
NextPoolIdx
();
index_t
nextIdx
=
first
.
NextPoolIdx
();
// Guard and head->next
// Guard and head->next
// Actually not necessary, as head->next will only change from Undefined
// Actually not necessary, as head->next will only change from Undefined
// to a node index value, but not back to Undefined.
// to a node index value, but not back to Undefined.
hp
.
GuardPointer
(
1
,
nextIdx
);
hp
.
GuardPointer
(
1
,
nextIdx
);
if
(
nextIdx
!=
nodePool
[
firstIdx
].
NextPoolIdx
())
{
if
(
nextIdx
!=
nodePool
[
static_cast
<
int
>
(
firstIdx
)
].
NextPoolIdx
())
{
return
;
return
;
}
}
index_t
accessorId
=
first
.
DequeueAID
().
Load
();
index_t
accessorId
=
first
.
DequeueAID
().
Load
();
...
@@ -542,8 +539,8 @@ HelpFinishDequeue() {
...
@@ -542,8 +539,8 @@ HelpFinishDequeue() {
}
}
template
<
template
<
typename
Type
,
class
NodeAllocator
,
class
OpAllocator
,
class
ValuePool
>
typename
Type
,
class
ValuePool
,
class
NodeAllocator
,
class
OpAllocator
>
void
WaitFreeMPMCQueue
<
Type
,
NodeAllocator
,
OpAllocator
,
ValuePool
>::
void
WaitFreeMPMCQueue
<
Type
,
ValuePool
,
NodeAllocator
,
OpAllocator
>::
Help
()
{
Help
()
{
// Fairness guarantee in every thread:
// Fairness guarantee in every thread:
// "Every other thread will help my operation before helping its
// "Every other thread will help my operation before helping its
...
@@ -572,8 +569,8 @@ Help() {
...
@@ -572,8 +569,8 @@ Help() {
}
}
template
<
template
<
typename
Type
,
class
NodeAllocator
,
class
OpAllocator
,
class
ValuePool
>
typename
Type
,
class
ValuePool
,
class
NodeAllocator
,
class
OpAllocator
>
void
WaitFreeMPMCQueue
<
Type
,
NodeAllocator
,
OpAllocator
,
ValuePool
>::
void
WaitFreeMPMCQueue
<
Type
,
ValuePool
,
NodeAllocator
,
OpAllocator
>::
DeleteNodeCallback
(
index_t
releasedNodeIndex
)
{
DeleteNodeCallback
(
index_t
releasedNodeIndex
)
{
if
(
!
NodeIsPending
(
releasedNodeIndex
))
{
if
(
!
NodeIsPending
(
releasedNodeIndex
))
{
nodePool
.
Free
(
static_cast
<
int
>
(
releasedNodeIndex
));
nodePool
.
Free
(
static_cast
<
int
>
(
releasedNodeIndex
));
...
@@ -581,16 +578,16 @@ DeleteNodeCallback(index_t releasedNodeIndex) {
...
@@ -581,16 +578,16 @@ DeleteNodeCallback(index_t releasedNodeIndex) {
}
}
template
<
template
<
typename
Type
,
class
NodeAllocator
,
class
OpAllocator
,
class
ValuePool
>
typename
Type
,
class
ValuePool
,
class
NodeAllocator
,
class
OpAllocator
>
inline
size_t
WaitFreeMPMCQueue
<
Type
,
NodeAllocator
,
OpAllocator
,
ValuePool
>::
inline
size_t
WaitFreeMPMCQueue
<
Type
,
ValuePool
,
NodeAllocator
,
OpAllocator
>::
GetCapacity
()
{
GetCapacity
()
{
return
max_size_
;
return
max_size_
;
}
}
template
<
template
<
typename
Type
,
class
NodeAllocator
,
class
OpAllocator
,
class
ValuePool
>
typename
Type
,
class
ValuePool
,
class
NodeAllocator
,
class
OpAllocator
>
inline
bool
WaitFreeMPMCQueue
<
Type
,
NodeAllocator
,
OpAllocator
,
ValuePool
>::
inline
bool
WaitFreeMPMCQueue
<
Type
,
ValuePool
,
NodeAllocator
,
OpAllocator
>::
NodeIsPending
(
index_t
nodeIdx
)
{
NodeIsPending
(
index_t
nodeIdx
)
{
for
(
unsigned
int
accessorId
=
0
;
accessorId
<
num_states
;
++
accessorId
)
{
for
(
unsigned
int
accessorId
=
0
;
accessorId
<
num_states
;
++
accessorId
)
{
if
(
OperationDesc
(
operationDescriptions
[
accessorId
].
Load
()).
NodeIndex
==
if
(
OperationDesc
(
operationDescriptions
[
accessorId
].
Load
()).
NodeIndex
==
...
@@ -602,8 +599,8 @@ NodeIsPending(index_t nodeIdx) {
...
@@ -602,8 +599,8 @@ NodeIsPending(index_t nodeIdx) {
}
}
template
<
template
<
typename
Type
,
class
NodeAllocator
,
class
OpAllocator
,
class
ValuePool
>
typename
Type
,
class
ValuePool
,
class
NodeAllocator
,
class
OpAllocator
>
inline
bool
WaitFreeMPMCQueue
<
Type
,
NodeAllocator
,
OpAllocator
,
ValuePool
>::
inline
bool
WaitFreeMPMCQueue
<
Type
,
ValuePool
,
NodeAllocator
,
OpAllocator
>::
IsPending
(
unsigned
int
accessorId
)
{
IsPending
(
unsigned
int
accessorId
)
{
OperationDesc
opDesc
(
operationDescriptions
[
accessorId
].
Load
());
OperationDesc
opDesc
(
operationDescriptions
[
accessorId
].
Load
());
return
opDesc
.
Pending
;
return
opDesc
.
Pending
;
...
...
containers_cpp/include/embb/containers/wait_free_mpmc_queue.h
View file @
df279e99
...
@@ -127,7 +127,7 @@ class WaitFreeMPMCQueueNode {
...
@@ -127,7 +127,7 @@ class WaitFreeMPMCQueueNode {
/**< [IN] New pointer value to set */
/**< [IN] New pointer value to set */
);
);
inline
bool
Next
_
IsNull
()
const
;
inline
bool
NextIsNull
()
const
;
inline
uint32_t
EnqueueAID
()
const
;
inline
uint32_t
EnqueueAID
()
const
;
...
@@ -155,18 +155,18 @@ class WaitFreeMPMCQueueNode {
...
@@ -155,18 +155,18 @@ class WaitFreeMPMCQueueNode {
*/
*/
template
<
template
<
typename
Type
,
typename
Type
,
class
ValuePool
=
WaitFreeArrayValuePool
<
bool
,
false
>
,
class
NodeAllocator
=
class
NodeAllocator
=
embb
::
base
::
AllocatorCacheAligned
<
internal
::
WaitFreeMPMCQueueNode
<
Type
>
>
,
embb
::
base
::
AllocatorCacheAligned
<
internal
::
WaitFreeMPMCQueueNode
<
Type
>
>
,
class
OpAllocator
=
class
OpAllocator
=
embb
::
base
::
AllocatorCacheAligned
<
embb
::
base
::
Atomic
<
uint32_t
>
>
,
embb
::
base
::
AllocatorCacheAligned
<
embb
::
base
::
Atomic
<
uint32_t
>
>
class
ValuePool
=
WaitFreeArrayValuePool
<
bool
,
false
>
>
>
class
WaitFreeMPMCQueue
{
class
WaitFreeMPMCQueue
{
private
:
private
:
typedef
internal
::
WaitFreeMPMCQueueNode
<
Type
>
Node_t
;
typedef
internal
::
WaitFreeMPMCQueueNode
<
Type
>
Node_t
;
typedef
typename
internal
::
WaitFreeMPMCQueueNode
<
Type
>::
index_t
index_t
;
typedef
typename
internal
::
WaitFreeMPMCQueueNode
<
Type
>::
index_t
index_t
;
typedef
WaitFreeMPMCQueue
<
Type
,
NodeAllocator
,
OpAllocator
,
ValuePool
>
self_t
;
typedef
WaitFreeMPMCQueue
<
Type
,
ValuePool
,
NodeAllocator
,
OpAllocator
>
self_t
;
typedef
internal
::
IndexedObjectPool
<
typedef
internal
::
IndexedObjectPool
<
internal
::
WaitFreeMPMCQueueNode
<
Type
>
,
ValuePool
,
NodeAllocator
>
NodePool_t
;
internal
::
WaitFreeMPMCQueueNode
<
Type
>
,
ValuePool
,
NodeAllocator
>
NodePool_t
;
...
...
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