Commit df279e99 by Tobias Fuchs

containers_cpp: interface of IndexedObjectPool conforming to ObjectPool

parent d3a090c3
...@@ -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 Type, class IndexPool, class Allocator>
template<typename RAI> template<typename RAI>
IndexedObjectPool<T, IndexPool, Allocator>:: IndexedObjectPool<Type, 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 Type, class IndexPool, class Allocator>
IndexedObjectPool<T, IndexPool, Allocator >:: IndexedObjectPool<Type, IndexPool, Allocator >::
IndexedObjectPool(size_t size, const T & defaultInstance) : IndexedObjectPool(size_t size, const Type & 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 Type, class IndexPool, class Allocator>
IndexedObjectPool<T, IndexPool, Allocator >:: IndexedObjectPool<Type, 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].~Type();
// 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 Type, class IndexPool, class Allocator>
T & IndexedObjectPool<T, IndexPool, Allocator >:: Type & IndexedObjectPool<Type, IndexPool, Allocator >::
operator[](size_t elementIndex) { operator[](int 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
......
...@@ -38,14 +38,14 @@ namespace containers { ...@@ -38,14 +38,14 @@ namespace containers {
namespace internal { namespace internal {
template< template<
typename T, typename Type,
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; Type * 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,8 +76,9 @@ class IndexedObjectPool { ...@@ -73,8 +76,9 @@ 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
* *
* \memory dynamically allocates * \memory dynamically allocates
...@@ -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 Type & 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
......
...@@ -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;
......
...@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment