Commit 2bd00270 by unknown

Fixes for EMBB-446.

parent 791943da
...@@ -37,11 +37,19 @@ ...@@ -37,11 +37,19 @@
namespace embb { namespace embb {
namespace containers { namespace containers {
template<typename Type, class Allocator> template<typename Type, class Allocator>
WaitFreeSPSCQueue<Type, Allocator>::WaitFreeSPSCQueue(size_t capacity) : size_t WaitFreeSPSCQueue<Type, Allocator>::
capacity(capacity), AlignCapacityToPowerOfTwo(size_t capacity) {
head_index(0), size_t result = 1;
tail_index(0) { while (result < capacity) result <<= 1;
queue_array = allocator.allocate(capacity); return result;
}
template<typename Type, class Allocator>
WaitFreeSPSCQueue<Type, Allocator>::WaitFreeSPSCQueue(size_t capacity)
: capacity(AlignCapacityToPowerOfTwo(capacity)),
head_index(0),
tail_index(0) {
queue_array = allocator.allocate(this->capacity);
} }
template<typename Type, class Allocator> template<typename Type, class Allocator>
...@@ -51,7 +59,7 @@ size_t WaitFreeSPSCQueue<Type, Allocator>::GetCapacity() { ...@@ -51,7 +59,7 @@ size_t WaitFreeSPSCQueue<Type, Allocator>::GetCapacity() {
template<typename Type, class Allocator> template<typename Type, class Allocator>
bool WaitFreeSPSCQueue<Type, Allocator>::TryEnqueue(Type const & element) { bool WaitFreeSPSCQueue<Type, Allocator>::TryEnqueue(Type const & element) {
if (head_index - tail_index == capacity) if (tail_index - head_index == capacity)
return false; return false;
queue_array[tail_index % capacity] = element; queue_array[tail_index % capacity] = element;
......
...@@ -145,11 +145,17 @@ class WaitFreeSPSCQueue { ...@@ -145,11 +145,17 @@ class WaitFreeSPSCQueue {
*/ */
embb::base::Atomic<size_t> tail_index; embb::base::Atomic<size_t> tail_index;
/**
* Align capacity to the next smallest power of two
*/
static size_t AlignCapacityToPowerOfTwo(size_t capacity);
public: public:
/** /**
* Creates a queue with the specified capacity. * Creates a queue with at least the specified capacity.
* *
* \memory Allocates \c capacity elements of type \c Type. * \memory Allocates \c 2^k elements of type \c Type, where \k is the
* smallest number such that <tt>capacity <= 2^k</tt> holds.
* *
* \notthreadsafe * \notthreadsafe
* *
......
...@@ -276,16 +276,43 @@ QueueTestSingleProducerSingleConsumer_ThreadMethod() { ...@@ -276,16 +276,43 @@ QueueTestSingleProducerSingleConsumer_ThreadMethod() {
template<typename Queue_t, bool MultipleProducers, bool MultipleConsumers> template<typename Queue_t, bool MultipleProducers, bool MultipleConsumers>
void QueueTest<Queue_t, MultipleProducers, MultipleConsumers>:: void QueueTest<Queue_t, MultipleProducers, MultipleConsumers>::
QueueTestSingleThreadEnqueueDequeue_ThreadMethod() { QueueTestSingleThreadEnqueueDequeue_ThreadMethod() {
// Enqueue the expected amount of elements
for (int i = 0; i != n_queue_size; ++i) { for (int i = 0; i != n_queue_size; ++i) {
bool success = queue->TryEnqueue(element_t(0, i * 133)); bool success = queue->TryEnqueue(element_t(0, i * 133));
PT_ASSERT(success == true); PT_ASSERT(success == true);
} }
// Some queues may allow enqueueing more elements than their capacity
// permits, so try to enqueue additional elements until the queue is full
int oversized_count = n_queue_size;
while ( queue->TryEnqueue(element_t(0, oversized_count * 133)) ) {
++oversized_count;
}
// Oversized amount should not be larger than the original capacity
PT_ASSERT_LT(oversized_count, 2 * n_queue_size);
// Dequeue the expected amount of elements
for (int i = 0; i != n_queue_size; ++i) { for (int i = 0; i != n_queue_size; ++i) {
element_t dequ(0, -1); element_t dequ(0, -1);
bool success = queue->TryDequeue(dequ); bool success = queue->TryDequeue(dequ);
PT_ASSERT(success == true); PT_ASSERT(success == true);
PT_ASSERT(dequ.second == i * 133); PT_ASSERT(dequ.second == i * 133);
} }
// Dequeue any elements enqueued above the original capacity
for (int i = n_queue_size; i != oversized_count; ++i) {
element_t dequ(0, -1);
bool success = queue->TryDequeue(dequ);
PT_ASSERT(success == true);
PT_ASSERT(dequ.second == i * 133);
}
// Ensure the queue is now empty
{
element_t dequ;
bool success = queue->TryDequeue(dequ);
PT_ASSERT(success == false);
}
} }
template<typename Queue_t, bool MultipleProducers, bool MultipleConsumers> template<typename Queue_t, bool MultipleProducers, bool MultipleConsumers>
......
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