Commit 2bd00270 by unknown

Fixes for EMBB-446.

parent 791943da
......@@ -37,11 +37,19 @@
namespace embb {
namespace containers {
template<typename Type, class Allocator>
WaitFreeSPSCQueue<Type, Allocator>::WaitFreeSPSCQueue(size_t capacity) :
capacity(capacity),
head_index(0),
tail_index(0) {
queue_array = allocator.allocate(capacity);
size_t WaitFreeSPSCQueue<Type, Allocator>::
AlignCapacityToPowerOfTwo(size_t capacity) {
size_t result = 1;
while (result < capacity) result <<= 1;
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>
......@@ -51,7 +59,7 @@ size_t WaitFreeSPSCQueue<Type, Allocator>::GetCapacity() {
template<typename Type, class Allocator>
bool WaitFreeSPSCQueue<Type, Allocator>::TryEnqueue(Type const & element) {
if (head_index - tail_index == capacity)
if (tail_index - head_index == capacity)
return false;
queue_array[tail_index % capacity] = element;
......
......@@ -145,11 +145,17 @@ class WaitFreeSPSCQueue {
*/
embb::base::Atomic<size_t> tail_index;
/**
* Align capacity to the next smallest power of two
*/
static size_t AlignCapacityToPowerOfTwo(size_t capacity);
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
*
......
......@@ -276,16 +276,43 @@ QueueTestSingleProducerSingleConsumer_ThreadMethod() {
template<typename Queue_t, bool MultipleProducers, bool MultipleConsumers>
void QueueTest<Queue_t, MultipleProducers, MultipleConsumers>::
QueueTestSingleThreadEnqueueDequeue_ThreadMethod() {
// Enqueue the expected amount of elements
for (int i = 0; i != n_queue_size; ++i) {
bool success = queue->TryEnqueue(element_t(0, i * 133));
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) {
element_t dequ(0, -1);
bool success = queue->TryDequeue(dequ);
PT_ASSERT(success == true);
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>
......
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