Revert "Modified ISR queue to take references to etl::ifunction instances at runtime rather than static class at compile time."

This reverts commit 4aab7c017302b446f87037e25430167a80d9b749.
This commit is contained in:
John Wellbelove 2019-02-25 09:02:12 +01:00
parent 4aab7c0173
commit ab91c7af33
3 changed files with 371 additions and 382 deletions

View File

@ -39,7 +39,6 @@ SOFTWARE.
#include "parameter_type.h"
#include "memory_model.h"
#include "integral_limits.h"
#include "function.h"
#undef ETL_FILE
#define ETL_FILE "46"
@ -391,10 +390,14 @@ namespace etl
///\ingroup queue_spsc
///\brief This is the base for all queue_spsc_isrs that contain a particular type.
///\details Normally a reference to this type will be taken from a derived queue_spsc_isr.
///\code
/// etl::queue_spsc_isr_isr<int, 10> myQueue;
/// etl::iqueue_isr<int>& iQueue = myQueue;
///\endcode
/// This queue supports concurrent access by one producer and one consumer.
/// \tparam T The type of value that the queue_spsc_isr holds.
//***************************************************************************
template <typename T, const size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
template <typename T, typename TAccess, const size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
class iqueue_spsc_isr : public queue_spsc_isr_base<T, MEMORY_MODEL>
{
private:
@ -414,11 +417,11 @@ namespace etl
//*************************************************************************
bool push(parameter_t value)
{
lock();
TAccess::lock();
bool result = this->push_implementation(value);
unlock();
TAccess::unlock();
return result;
}
@ -431,11 +434,11 @@ namespace etl
template <typename ... Args>
bool emplace(Args&&... args)
{
lock();
TAccess::lock();
bool result = this->emplace_implementation(std::forward<Args>(args)...);
unlock();
TAccess::unlock();
return result;
}
@ -447,11 +450,11 @@ namespace etl
template <typename T1>
bool emplace(const T1& value1)
{
lock();
TAccess::lock();
bool result = this->emplace_implementation(value1);
unlock();
TAccess::unlock();
return result;
}
@ -463,11 +466,11 @@ namespace etl
template <typename T1, typename T2>
bool emplace(const T1& value1, const T2& value2)
{
lock();
TAccess::lock();
bool result = this->emplace_implementation(value1, value2);
unlock();
TAccess::unlock();
return result;
}
@ -479,11 +482,11 @@ namespace etl
template <typename T1, typename T2, typename T3>
bool emplace(const T1& value1, const T2& value2, const T3& value3)
{
lock();
TAccess::lock();
bool result = this->emplace_implementation(value1, value2, value3);
unlock();
TAccess::unlock();
return result;
}
@ -495,11 +498,11 @@ namespace etl
template <typename T1, typename T2, typename T3, typename T4>
bool emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4)
{
lock();
TAccess::lock();
bool result = this->emplace_implementation(value1, value2, value3, value4);
unlock();
TAccess::unlock();
return result;
}
@ -510,11 +513,11 @@ namespace etl
//*************************************************************************
bool pop(reference value)
{
lock();
TAccess::lock();
bool result = this->pop_implementation(value);
unlock();
TAccess::unlock();
return result;
}
@ -524,11 +527,11 @@ namespace etl
//*************************************************************************
bool pop()
{
lock();
TAccess::lock();
bool result = this->pop_implementation();
unlock();
TAccess::unlock();
return result;
}
@ -538,14 +541,14 @@ namespace etl
//*************************************************************************
void clear()
{
lock();
TAccess::lock();
while (this->pop_implementation())
{
// Do nothing.
}
unlock();
TAccess::unlock();
}
//*************************************************************************
@ -553,11 +556,11 @@ namespace etl
//*************************************************************************
bool empty() const
{
lock();
TAccess::lock();
size_type result = (this->current_size == 0);
unlock();
TAccess::unlock();
return result;
}
@ -567,11 +570,11 @@ namespace etl
//*************************************************************************
bool full() const
{
lock();
TAccess::lock();
size_type result = (this->current_size == this->MAX_SIZE);
unlock();
TAccess::unlock();
return result;
}
@ -581,11 +584,11 @@ namespace etl
//*************************************************************************
size_type size() const
{
lock();
TAccess::lock();
size_type result = this->current_size;
unlock();
TAccess::unlock();
return result;
}
@ -595,11 +598,11 @@ namespace etl
//*************************************************************************
size_type available() const
{
lock();
TAccess::lock();
size_type result = this->MAX_SIZE - this->current_size;
unlock();
TAccess::unlock();
return result;
}
@ -609,10 +612,8 @@ namespace etl
//*************************************************************************
/// The constructor that is called from derived classes.
//*************************************************************************
iqueue_spsc_isr(T* p_buffer_, size_type max_size_, etl::ifunction<void>& lock_, etl::ifunction<void>& unlock_)
iqueue_spsc_isr(T* p_buffer_, size_type max_size_)
: base_t(p_buffer_, max_size_)
, lock(lock_)
, unlock(unlock_)
{
}
@ -622,8 +623,7 @@ namespace etl
iqueue_spsc_isr(const iqueue_spsc_isr&);
iqueue_spsc_isr& operator =(const iqueue_spsc_isr&);
etl::ifunction<void>& lock; ///< The callback that locks interrupts.
etl::ifunction<void>& unlock; ///< The callback that unlocks interrupts.
TAccess access; ///< The object that locks/unlocks interrupts.
};
//***************************************************************************
@ -632,14 +632,15 @@ namespace etl
/// This queue supports concurrent access by one producer and one consumer.
/// \tparam T The type this queue should support.
/// \tparam SIZE The maximum capacity of the queue.
/// \tparam TAccess The type that will lock and unlock interrupts.
/// \tparam MEMORY_MODEL The memory model for the queue. Determines the type of the internal counter variables.
//***************************************************************************
template <typename T, size_t SIZE, const size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
class queue_spsc_isr : public etl::iqueue_spsc_isr<T, MEMORY_MODEL>
template <typename T, size_t SIZE, typename TAccess, const size_t MEMORY_MODEL = etl::memory_model::MEMORY_MODEL_LARGE>
class queue_spsc_isr : public etl::iqueue_spsc_isr<T, TAccess, MEMORY_MODEL>
{
private:
typedef etl::iqueue_spsc_isr<T, MEMORY_MODEL> base_t;
typedef etl::iqueue_spsc_isr<T, TAccess, MEMORY_MODEL> base_t;
public:
@ -652,9 +653,8 @@ namespace etl
//*************************************************************************
/// Default constructor.
//*************************************************************************
queue_spsc_isr(etl::ifunction<void>& lock,
etl::ifunction<void>& unlock)
: base_t(reinterpret_cast<T*>(&buffer[0]), MAX_SIZE, lock, unlock)
queue_spsc_isr()
: base_t(reinterpret_cast<T*>(&buffer[0]), MAX_SIZE)
{
}

View File

@ -29,7 +29,6 @@ SOFTWARE.
#include "UnitTest++.h"
#include "etl/queue_spsc_isr.h"
#include "etl/function.h"
#include <thread>
#include <mutex>
@ -47,46 +46,44 @@ namespace
{
public:
void clear()
static void clear()
{
called_lock = false;
called_lock = false;
called_unlock = false;
}
void lock()
static void lock()
{
called_lock = true;
}
void unlock()
static void unlock()
{
called_unlock = true;
}
bool called_lock;
bool called_unlock;
static bool called_lock;
static bool called_unlock;
};
Access access;
etl::function_imv<Access, access, &Access::lock> lock;
etl::function_imv<Access, access, &Access::unlock> unlock;
bool Access::called_lock;
bool Access::called_unlock;
struct Data
{
Data(int a_, int b_ = 2, int c_ = 3, int d_ = 4)
: a(a_),
b(b_),
c(c_),
d(d_)
b(b_),
c(c_),
d(d_)
{
}
Data()
: a(0),
b(0),
c(0),
d(0)
b(0),
c(0),
d(0)
{
}
@ -106,121 +103,121 @@ namespace
//*************************************************************************
TEST(test_constructor)
{
access.clear();
Access::clear();
etl::queue_spsc_isr<int, 4> queue(lock, unlock);
etl::queue_spsc_isr<int, 4, Access> queue;
CHECK_EQUAL(4U, queue.max_size());
CHECK_EQUAL(4U, queue.capacity());
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
}
//*************************************************************************
TEST(test_size_push_pop)
{
access.clear();
Access::clear();
etl::queue_spsc_isr<int, 4> queue(lock, unlock);
etl::queue_spsc_isr<int, 4, Access> queue;
CHECK_EQUAL(0U, queue.size_from_isr());
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
access.clear();
Access::clear();
CHECK_EQUAL(4U, queue.available_from_isr());
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
access.clear();
Access::clear();
CHECK_EQUAL(0U, queue.size());
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
access.clear();
Access::clear();
CHECK_EQUAL(4U, queue.available());
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
access.clear();
Access::clear();
queue.push_from_isr(1);
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
CHECK_EQUAL(1U, queue.size_from_isr());
CHECK_EQUAL(3U, queue.available_from_isr());
access.clear();
Access::clear();
queue.push(2);
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
CHECK_EQUAL(2U, queue.size_from_isr());
CHECK_EQUAL(2U, queue.available_from_isr());
access.clear();
Access::clear();
queue.push(3);
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
CHECK_EQUAL(3U, queue.size_from_isr());
CHECK_EQUAL(1U, queue.available_from_isr());
access.clear();
Access::clear();
queue.push(4);
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
CHECK_EQUAL(4U, queue.size_from_isr());
CHECK_EQUAL(0U, queue.available_from_isr());
access.clear();
Access::clear();
CHECK(!queue.push(5));
CHECK(!queue.push_from_isr(5));
access.clear();
Access::clear();
int i;
CHECK(queue.pop(i));
CHECK_EQUAL(1, i);
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
CHECK_EQUAL(3U, queue.size_from_isr());
access.clear();
Access::clear();
CHECK(queue.pop_from_isr(i));
CHECK_EQUAL(2, i);
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
CHECK_EQUAL(2U, queue.size_from_isr());
access.clear();
Access::clear();
CHECK(queue.pop_from_isr(i));
CHECK_EQUAL(3, i);
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
CHECK_EQUAL(1U, queue.size_from_isr());
access.clear();
Access::clear();
CHECK(queue.pop_from_isr(i));
CHECK_EQUAL(4, i);
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
CHECK_EQUAL(0U, queue.size_from_isr());
access.clear();
Access::clear();
CHECK(!queue.pop(i));
CHECK(!queue.pop_from_isr(i));
@ -229,92 +226,92 @@ namespace
//*************************************************************************
TEST(test_size_push_pop_iqueue)
{
access.clear();
Access::clear();
etl::queue_spsc_isr<int, 4> queue(lock, unlock);
etl::queue_spsc_isr<int, 4, Access> queue;
etl::iqueue_spsc_isr<int>& iqueue = queue;
etl::iqueue_spsc_isr<int, Access>& iqueue = queue;
CHECK_EQUAL(0U, iqueue.size_from_isr());
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
access.clear();
Access::clear();
CHECK_EQUAL(0U, iqueue.size());
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
access.clear();
Access::clear();
iqueue.push_from_isr(1);
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
CHECK_EQUAL(1U, iqueue.size_from_isr());
access.clear();
Access::clear();
iqueue.push(2);
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
CHECK_EQUAL(2U, iqueue.size_from_isr());
access.clear();
Access::clear();
iqueue.push(3);
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
CHECK_EQUAL(3U, iqueue.size_from_isr());
access.clear();
Access::clear();
iqueue.push(4);
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
CHECK_EQUAL(4U, iqueue.size_from_isr());
access.clear();
Access::clear();
CHECK(!iqueue.push(5));
CHECK(!iqueue.push_from_isr(5));
access.clear();
Access::clear();
int i;
CHECK(iqueue.pop(i));
CHECK_EQUAL(1, i);
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
CHECK_EQUAL(3U, iqueue.size_from_isr());
access.clear();
Access::clear();
CHECK(iqueue.pop_from_isr(i));
CHECK_EQUAL(2, i);
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
CHECK_EQUAL(2U, iqueue.size_from_isr());
access.clear();
Access::clear();
CHECK(iqueue.pop_from_isr(i));
CHECK_EQUAL(3, i);
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
CHECK_EQUAL(1U, iqueue.size_from_isr());
access.clear();
Access::clear();
CHECK(iqueue.pop_from_isr(i));
CHECK_EQUAL(4, i);
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
CHECK_EQUAL(0U, iqueue.size_from_isr());
access.clear();
Access::clear();
CHECK(!iqueue.pop(i));
CHECK(!iqueue.pop_from_isr(i));
@ -323,84 +320,84 @@ namespace
//*************************************************************************
TEST(test_size_push_pop_void)
{
access.clear();
Access::clear();
etl::queue_spsc_isr<int, 4> queue(lock, unlock);
etl::queue_spsc_isr<int, 4, Access> queue;
CHECK_EQUAL(0U, queue.size_from_isr());
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
access.clear();
Access::clear();
CHECK_EQUAL(0U, queue.size());
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
access.clear();
Access::clear();
queue.push_from_isr(1);
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
CHECK_EQUAL(1U, queue.size_from_isr());
access.clear();
Access::clear();
queue.push(2);
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
CHECK_EQUAL(2U, queue.size_from_isr());
access.clear();
Access::clear();
queue.push(3);
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
CHECK_EQUAL(3U, queue.size_from_isr());
access.clear();
Access::clear();
queue.push(4);
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
CHECK_EQUAL(4U, queue.size_from_isr());
access.clear();
Access::clear();
CHECK(!queue.push(5));
CHECK(!queue.push_from_isr(5));
access.clear();
Access::clear();
CHECK(queue.pop());
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
CHECK_EQUAL(3U, queue.size_from_isr());
access.clear();
Access::clear();
CHECK(queue.pop_from_isr());
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
CHECK_EQUAL(2U, queue.size_from_isr());
access.clear();
Access::clear();
CHECK(queue.pop_from_isr());
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
CHECK_EQUAL(1U, queue.size_from_isr());
access.clear();
Access::clear();
CHECK(queue.pop_from_isr());
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
CHECK_EQUAL(0U, queue.size_from_isr());
access.clear();
Access::clear();
CHECK(!queue.pop());
CHECK(!queue.pop_from_isr());
@ -409,7 +406,7 @@ namespace
//*************************************************************************
TEST(test_multiple_emplace)
{
etl::queue_spsc_isr<Data, 4> queue(lock, unlock);
etl::queue_spsc_isr<Data, 4, Access> queue;
queue.emplace(1);
queue.emplace(1, 2);
@ -433,20 +430,20 @@ namespace
//*************************************************************************
TEST(test_clear)
{
access.clear();
Access::clear();
etl::queue_spsc_isr<int, 4> queue(lock, unlock);
etl::queue_spsc_isr<int, 4, Access> queue;
CHECK_EQUAL(0U, queue.size());
queue.push(1);
queue.push(2);
queue.clear();
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
CHECK_EQUAL(0U, queue.size());
access.clear();
Access::clear();
// Do it again to check that clear() didn't screw up the internals.
queue.push_from_isr(1);
@ -454,84 +451,84 @@ namespace
CHECK_EQUAL(2U, queue.size_from_isr());
queue.clear_from_isr();
CHECK_EQUAL(0U, queue.size_from_isr());
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
}
//*************************************************************************
TEST(test_empty)
{
access.clear();
Access::clear();
etl::queue_spsc_isr<int, 4> queue(lock, unlock);
etl::queue_spsc_isr<int, 4, Access> queue;
CHECK(queue.empty());
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
queue.push(1);
access.clear();
Access::clear();
CHECK(!queue.empty());
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
queue.clear();
access.clear();
Access::clear();
CHECK(queue.empty_from_isr());
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
queue.push(1);
access.clear();
Access::clear();
CHECK(!queue.empty_from_isr());
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
}
//*************************************************************************
TEST(test_full)
{
access.clear();
Access::clear();
etl::queue_spsc_isr<int, 4> queue(lock, unlock);
etl::queue_spsc_isr<int, 4, Access> queue;
CHECK(!queue.full());
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
queue.push(1);
queue.push(2);
queue.push(3);
queue.push(4);
access.clear();
Access::clear();
CHECK(queue.full());
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
queue.clear();
access.clear();
Access::clear();
CHECK(!queue.full_from_isr());
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
queue.push(1);
queue.push(2);
queue.push(3);
queue.push(4);
access.clear();
Access::clear();
CHECK(queue.full_from_isr());
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
}
//=========================================================================
@ -547,25 +544,22 @@ namespace
struct ThreadLock
{
void lock()
static void lock()
{
mutex.lock();
}
void unlock()
static void unlock()
{
mutex.unlock();
}
std::mutex mutex;
static std::mutex mutex;
};
ThreadLock threadLock;
std::mutex ThreadLock::mutex;
etl::function_imv<ThreadLock, threadLock, &ThreadLock::lock> lock;
etl::function_imv<ThreadLock, threadLock, &ThreadLock::unlock> unlock;
etl::queue_spsc_isr<int, 10> queue(lock, unlock);
etl::queue_spsc_isr<int, 10, ThreadLock> queue;
const size_t LENGTH = 1000;
@ -580,14 +574,14 @@ namespace
while (ticks <= LENGTH)
{
if (threadLock.mutex.try_lock())
if (ThreadLock::mutex.try_lock())
{
if (queue.push_from_isr(ticks))
{
++ticks;
}
threadLock.mutex.unlock();
ThreadLock::mutex.unlock();
}
Sleep(0);

View File

@ -46,46 +46,44 @@ namespace
{
public:
void clear()
static void clear()
{
called_lock = false;
called_unlock = false;
}
void lock()
static void lock()
{
called_lock = true;
}
void unlock()
static void unlock()
{
called_unlock = true;
}
bool called_lock;
bool called_unlock;
static bool called_lock;
static bool called_unlock;
};
Access access;
etl::function_imv<Access, access, &Access::lock> lock;
etl::function_imv<Access, access, &Access::unlock> unlock;
bool Access::called_lock;
bool Access::called_unlock;
struct Data
{
Data(int a_, int b_ = 2, int c_ = 3, int d_ = 4)
: a(a_),
b(b_),
c(c_),
d(d_)
b(b_),
c(c_),
d(d_)
{
}
Data()
: a(0),
b(0),
c(0),
d(0)
b(0),
c(0),
d(0)
{
}
@ -100,131 +98,131 @@ namespace
return (lhs.a == rhs.a) && (lhs.b == rhs.b) && (lhs.c == rhs.c) && (lhs.d == rhs.d);
}
typedef etl::queue_spsc_isr<int, 4, etl::memory_model::MEMORY_MODEL_SMALL> QueueInt;
typedef etl::iqueue_spsc_isr<int, etl::memory_model::MEMORY_MODEL_SMALL> IQueueInt;
typedef etl::queue_spsc_isr<int, 4, Access, etl::memory_model::MEMORY_MODEL_SMALL> QueueInt;
typedef etl::iqueue_spsc_isr<int, Access, etl::memory_model::MEMORY_MODEL_SMALL> IQueueInt;
typedef etl::queue_spsc_isr<int, 255, etl::memory_model::MEMORY_MODEL_SMALL> QueueInt255;
typedef etl::queue_spsc_isr<int, 255, Access, etl::memory_model::MEMORY_MODEL_SMALL> QueueInt255;
SUITE(test_queue_isr)
{
//*************************************************************************
TEST(test_constructor)
{
access.clear();
Access::clear();
QueueInt queue(lock, unlock);
QueueInt queue;
CHECK_EQUAL(4U, queue.max_size());
CHECK_EQUAL(4U, queue.capacity());
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
}
//*************************************************************************
TEST(test_size_push_pop)
{
access.clear();
Access::clear();
QueueInt queue(lock, unlock);
QueueInt queue;
CHECK_EQUAL(0U, queue.size_from_isr());
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
access.clear();
Access::clear();
CHECK_EQUAL(4U, queue.available_from_isr());
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
access.clear();
Access::clear();
CHECK_EQUAL(0U, queue.size());
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
access.clear();
Access::clear();
CHECK_EQUAL(4U, queue.available());
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
access.clear();
Access::clear();
queue.push_from_isr(1);
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
CHECK_EQUAL(1U, queue.size_from_isr());
CHECK_EQUAL(3U, queue.available_from_isr());
access.clear();
Access::clear();
queue.push(2);
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
CHECK_EQUAL(2U, queue.size_from_isr());
CHECK_EQUAL(2U, queue.available_from_isr());
access.clear();
Access::clear();
queue.push(3);
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
CHECK_EQUAL(3U, queue.size_from_isr());
CHECK_EQUAL(1U, queue.available_from_isr());
access.clear();
Access::clear();
queue.push(4);
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
CHECK_EQUAL(4U, queue.size_from_isr());
CHECK_EQUAL(0U, queue.available_from_isr());
access.clear();
Access::clear();
CHECK(!queue.push(5));
CHECK(!queue.push_from_isr(5));
access.clear();
Access::clear();
int i;
CHECK(queue.pop(i));
CHECK_EQUAL(1, i);
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
CHECK_EQUAL(3U, queue.size_from_isr());
access.clear();
Access::clear();
CHECK(queue.pop_from_isr(i));
CHECK_EQUAL(2, i);
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
CHECK_EQUAL(2U, queue.size_from_isr());
access.clear();
Access::clear();
CHECK(queue.pop_from_isr(i));
CHECK_EQUAL(3, i);
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
CHECK_EQUAL(1U, queue.size_from_isr());
access.clear();
Access::clear();
CHECK(queue.pop_from_isr(i));
CHECK_EQUAL(4, i);
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
CHECK_EQUAL(0U, queue.size_from_isr());
access.clear();
Access::clear();
CHECK(!queue.pop(i));
CHECK(!queue.pop_from_isr(i));
@ -233,92 +231,92 @@ namespace
//*************************************************************************
TEST(test_size_push_pop_iqueue)
{
access.clear();
Access::clear();
QueueInt queue(lock, unlock);
QueueInt queue;
IQueueInt& iqueue = queue;
CHECK_EQUAL(0U, iqueue.size_from_isr());
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
access.clear();
Access::clear();
CHECK_EQUAL(0U, iqueue.size());
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
access.clear();
Access::clear();
iqueue.push_from_isr(1);
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
CHECK_EQUAL(1U, iqueue.size_from_isr());
access.clear();
Access::clear();
iqueue.push(2);
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
CHECK_EQUAL(2U, iqueue.size_from_isr());
access.clear();
Access::clear();
iqueue.push(3);
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
CHECK_EQUAL(3U, iqueue.size_from_isr());
access.clear();
Access::clear();
iqueue.push(4);
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
CHECK_EQUAL(4U, iqueue.size_from_isr());
access.clear();
Access::clear();
CHECK(!iqueue.push(5));
CHECK(!iqueue.push_from_isr(5));
access.clear();
Access::clear();
int i;
CHECK(iqueue.pop(i));
CHECK_EQUAL(1, i);
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
CHECK_EQUAL(3U, iqueue.size_from_isr());
access.clear();
Access::clear();
CHECK(iqueue.pop_from_isr(i));
CHECK_EQUAL(2, i);
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
CHECK_EQUAL(2U, iqueue.size_from_isr());
access.clear();
Access::clear();
CHECK(iqueue.pop_from_isr(i));
CHECK_EQUAL(3, i);
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
CHECK_EQUAL(1U, iqueue.size_from_isr());
access.clear();
Access::clear();
CHECK(iqueue.pop_from_isr(i));
CHECK_EQUAL(4, i);
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
CHECK_EQUAL(0U, iqueue.size_from_isr());
access.clear();
Access::clear();
CHECK(!iqueue.pop(i));
CHECK(!iqueue.pop_from_isr(i));
@ -327,84 +325,84 @@ namespace
//*************************************************************************
TEST(test_size_push_pop_void)
{
access.clear();
Access::clear();
QueueInt queue(lock, unlock);
QueueInt queue;
CHECK_EQUAL(0U, queue.size_from_isr());
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
access.clear();
Access::clear();
CHECK_EQUAL(0U, queue.size());
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
access.clear();
Access::clear();
queue.push_from_isr(1);
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
CHECK_EQUAL(1U, queue.size_from_isr());
access.clear();
Access::clear();
queue.push(2);
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
CHECK_EQUAL(2U, queue.size_from_isr());
access.clear();
Access::clear();
queue.push(3);
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
CHECK_EQUAL(3U, queue.size_from_isr());
access.clear();
Access::clear();
queue.push(4);
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
CHECK_EQUAL(4U, queue.size_from_isr());
access.clear();
Access::clear();
CHECK(!queue.push(5));
CHECK(!queue.push_from_isr(5));
access.clear();
Access::clear();
CHECK(queue.pop());
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
CHECK_EQUAL(3U, queue.size_from_isr());
access.clear();
Access::clear();
CHECK(queue.pop_from_isr());
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
CHECK_EQUAL(2U, queue.size_from_isr());
access.clear();
Access::clear();
CHECK(queue.pop_from_isr());
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
CHECK_EQUAL(1U, queue.size_from_isr());
access.clear();
Access::clear();
CHECK(queue.pop_from_isr());
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
CHECK_EQUAL(0U, queue.size_from_isr());
access.clear();
Access::clear();
CHECK(!queue.pop());
CHECK(!queue.pop_from_isr());
@ -413,7 +411,7 @@ namespace
//*************************************************************************
TEST(test_push_255)
{
QueueInt255 queue(lock, unlock);
QueueInt255 queue;
for (int i = 0; i < 255; ++i)
{
@ -426,7 +424,7 @@ namespace
//*************************************************************************
TEST(test_multiple_emplace)
{
etl::queue_spsc_isr<Data, 4, etl::memory_model::MEMORY_MODEL_SMALL> queue(lock, unlock);
etl::queue_spsc_isr<Data, 4, Access, etl::memory_model::MEMORY_MODEL_SMALL> queue;
queue.emplace(1);
queue.emplace(1, 2);
@ -450,20 +448,20 @@ namespace
//*************************************************************************
TEST(test_clear)
{
access.clear();
Access::clear();
QueueInt queue(lock, unlock);
QueueInt queue;
CHECK_EQUAL(0U, queue.size());
queue.push(1);
queue.push(2);
queue.clear();
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
CHECK_EQUAL(0U, queue.size());
access.clear();
Access::clear();
// Do it again to check that clear() didn't screw up the internals.
queue.push_from_isr(1);
@ -471,84 +469,84 @@ namespace
CHECK_EQUAL(2U, queue.size_from_isr());
queue.clear_from_isr();
CHECK_EQUAL(0U, queue.size_from_isr());
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
}
//*************************************************************************
TEST(test_empty)
{
access.clear();
Access::clear();
QueueInt queue(lock, unlock);
QueueInt queue;
CHECK(queue.empty());
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
queue.push(1);
access.clear();
Access::clear();
CHECK(!queue.empty());
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
queue.clear();
access.clear();
Access::clear();
CHECK(queue.empty_from_isr());
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
queue.push(1);
access.clear();
Access::clear();
CHECK(!queue.empty_from_isr());
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
}
//*************************************************************************
TEST(test_full)
{
access.clear();
Access::clear();
QueueInt queue(lock, unlock);
QueueInt queue;
CHECK(!queue.full());
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
queue.push(1);
queue.push(2);
queue.push(3);
queue.push(4);
access.clear();
Access::clear();
CHECK(queue.full());
CHECK(access.called_lock);
CHECK(access.called_unlock);
CHECK(Access::called_lock);
CHECK(Access::called_unlock);
queue.clear();
access.clear();
Access::clear();
CHECK(!queue.full_from_isr());
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
queue.push(1);
queue.push(2);
queue.push(3);
queue.push(4);
access.clear();
Access::clear();
CHECK(queue.full_from_isr());
CHECK(!access.called_lock);
CHECK(!access.called_unlock);
CHECK(!Access::called_lock);
CHECK(!Access::called_unlock);
}
//=========================================================================
@ -564,25 +562,22 @@ namespace
struct ThreadLock
{
void lock()
static void lock()
{
mutex.lock();
}
void unlock()
static void unlock()
{
mutex.unlock();
}
std::mutex mutex;
static std::mutex mutex;
};
ThreadLock threadLock;
std::mutex ThreadLock::mutex;
etl::function_imv<ThreadLock, threadLock, &ThreadLock::lock> lock;
etl::function_imv<ThreadLock, threadLock, &ThreadLock::unlock> unlock;
etl::queue_spsc_isr<int, 10> queue(lock, unlock);
etl::queue_spsc_isr<int, 10, ThreadLock> queue;
const size_t LENGTH = 1000;
@ -597,14 +592,14 @@ namespace
while (ticks <= LENGTH)
{
if (threadLock.mutex.try_lock())
if (ThreadLock::mutex.try_lock())
{
if (queue.push_from_isr(ticks))
{
++ticks;
}
threadLock.mutex.unlock();
ThreadLock::mutex.unlock();
}
Sleep(0);