From 3f79e61f97ac4372403bf73819e606b7b06a0078 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 2 Oct 2021 12:00:27 +0100 Subject: [PATCH] Add front() to locked queues --- .gitignore | 2 + include/etl/queue_lockable.h | 60 +++++++++++++++++++++++++ include/etl/queue_mpmc_mutex.h | 44 ++++++++++++++++++ include/etl/queue_spsc_atomic.h | 22 ++++++++- include/etl/queue_spsc_isr.h | 60 +++++++++++++++++++++++++ include/etl/queue_spsc_locked.h | 64 +++++++++++++++++++++++++++ test/test_queue_lockable.cpp | 38 ++++++++++++++++ test/test_queue_lockable_small.cpp | 38 ++++++++++++++++ test/test_queue_mpmc_mutex.cpp | 38 ++++++++++++++++ test/test_queue_mpmc_mutex_small.cpp | 38 ++++++++++++++++ test/test_queue_spsc_atomic.cpp | 20 +++------ test/test_queue_spsc_atomic_small.cpp | 38 ++++++++++++++++ test/test_queue_spsc_isr.cpp | 40 +++++++++++++++++ test/test_queue_spsc_isr_small.cpp | 40 +++++++++++++++++ test/test_queue_spsc_locked.cpp | 40 +++++++++++++++++ test/test_queue_spsc_locked_small.cpp | 40 +++++++++++++++++ 16 files changed, 607 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 72c021e0..ad659d89 100644 --- a/.gitignore +++ b/.gitignore @@ -325,3 +325,5 @@ test/vs2019/Test2 test/vs2019/Debug MSVC - Force C++03 test/vs2019/Debug LLVM - No STL test/vs2019/Debug - No STL +test/build-make +test/build-ninja diff --git a/include/etl/queue_lockable.h b/include/etl/queue_lockable.h index aecff728..736be720 100644 --- a/include/etl/queue_lockable.h +++ b/include/etl/queue_lockable.h @@ -475,6 +475,50 @@ namespace etl return result; } + //************************************************************************* + /// Peek a value at the front of the queue without locking. + //************************************************************************* + reference front_unlocked() + { + return front_implementation(); + } + + //************************************************************************* + /// Peek a value at the front of the queue without locking. + //************************************************************************* + const_reference front_unlocked() const + { + return front_implementation(); + } + + //************************************************************************* + /// Peek a value at the front of the queue. + //************************************************************************* + reference front() + { + this->lock(); + + reference result = front_implementation(); + + this->unlock(); + + return result; + } + + //************************************************************************* + /// Peek a value at the front of the queue. + //************************************************************************* + const_reference front() const + { + this->lock(); + + const_reference result = front_implementation(); + + this->unlock(); + + return result; + } + //************************************************************************* /// Clear the queue, unlocked. //************************************************************************* @@ -709,6 +753,22 @@ namespace etl return true; } + //************************************************************************* + /// Peek a value at the front of the queue without locking + //************************************************************************* + reference front_implementation() + { + return p_buffer[this->read_index];; + } + + //************************************************************************* + /// Peek a value at the front of the queue without locking + //************************************************************************* + const_reference front_implementation() const + { + return p_buffer[this->read_index];; + } + // Disable copy construction and assignment. iqueue_lockable(const iqueue_lockable&) ETL_DELETE; iqueue_lockable& operator =(const iqueue_lockable&) ETL_DELETE; diff --git a/include/etl/queue_mpmc_mutex.h b/include/etl/queue_mpmc_mutex.h index 0d29b28c..b3a583a3 100644 --- a/include/etl/queue_mpmc_mutex.h +++ b/include/etl/queue_mpmc_mutex.h @@ -292,6 +292,34 @@ namespace etl return result; } + //************************************************************************* + /// Peek a value at the front of the queue. + //************************************************************************* + reference front() + { + access.lock(); + + reference result = front_implementation(); + + access.unlock(); + + return result; + } + + //************************************************************************* + /// Peek a value at the front of the queue. + //************************************************************************* + const_reference front() const + { + access.lock(); + + const_reference result = front_implementation(); + + access.unlock(); + + return result; + } + //************************************************************************* /// Clear the queue. //************************************************************************* @@ -571,6 +599,22 @@ namespace etl return true; } + //************************************************************************* + /// Peek a value at the front of the queue. + //************************************************************************* + reference front_implementation() + { + return p_buffer[read_index]; + } + + //************************************************************************* + /// Peek a value at the front of the queue. + //************************************************************************* + const_reference front_implementation() const + { + return p_buffer[read_index]; + } + // Disable copy construction and assignment. iqueue_mpmc_mutex(const iqueue_mpmc_mutex&); iqueue_mpmc_mutex& operator =(const iqueue_mpmc_mutex&); diff --git a/include/etl/queue_spsc_atomic.h b/include/etl/queue_spsc_atomic.h index 3c03a75f..7718c687 100644 --- a/include/etl/queue_spsc_atomic.h +++ b/include/etl/queue_spsc_atomic.h @@ -368,7 +368,7 @@ namespace etl //************************************************************************* /// Peek the next value in the queue without removing it. //************************************************************************* - bool peek(reference value) + bool front(reference value) { size_type read_index = read.load(etl::memory_order_relaxed); @@ -433,6 +433,26 @@ namespace etl return true; } + //************************************************************************* + /// Peek a value from the front of the queue. + //************************************************************************* + reference front() + { + size_type read_index = read.load(etl::memory_order_relaxed); + + return p_buffer[read_index]; + } + + //************************************************************************* + /// Peek a value from the front of the queue. + //************************************************************************* + const_reference front() const + { + size_type read_index = read.load(etl::memory_order_relaxed); + + return p_buffer[read_index]; + } + //************************************************************************* /// Clear the queue. /// Must be called from thread that pops the queue or when there is no diff --git a/include/etl/queue_spsc_isr.h b/include/etl/queue_spsc_isr.h index 0eed51ca..0481bb55 100644 --- a/include/etl/queue_spsc_isr.h +++ b/include/etl/queue_spsc_isr.h @@ -106,6 +106,22 @@ namespace etl return pop_implementation(); } + //************************************************************************* + /// Peek a value at the front of the queue from an ISR + //************************************************************************* + reference front_from_isr() + { + return front_implementation(); + } + + //************************************************************************* + /// Peek a value at the front of the queue from an ISR + //************************************************************************* + const_reference front_from_isr() const + { + return front_implementation(); + } + //************************************************************************* /// How much free space available in the queue. /// Called from ISR. @@ -362,6 +378,22 @@ namespace etl return true; } + //************************************************************************* + /// Peek a value at the front of the queue. + //************************************************************************* + reference front_implementation() + { + return p_buffer[read_index]; + } + + //************************************************************************* + /// Peek a value at the front of the queue. + //************************************************************************* + const_reference front_implementation() const + { + return p_buffer[read_index]; + } + //************************************************************************* /// Pop a value from the queue and discard. //************************************************************************* @@ -589,6 +621,34 @@ namespace etl return result; } + //************************************************************************* + /// Peek a value at the front of the queue. + //************************************************************************* + reference front() + { + TAccess::lock(); + + reference result = this->front_implementation(); + + TAccess::unlock(); + + return result; + } + + //************************************************************************* + /// Peek a value at the front of the queue. + //************************************************************************* + const_reference front() const + { + TAccess::lock(); + + const_reference result = this->front_implementation(); + + TAccess::unlock(); + + return result; + } + //************************************************************************* /// Clear the queue. //************************************************************************* diff --git a/include/etl/queue_spsc_locked.h b/include/etl/queue_spsc_locked.h index 60d4cc54..a1a3b4da 100644 --- a/include/etl/queue_spsc_locked.h +++ b/include/etl/queue_spsc_locked.h @@ -431,6 +431,52 @@ namespace etl return result; } + //************************************************************************* + /// Peek a value from the front of the queue. + /// Unlocked + //************************************************************************* + reference front_from_unlocked() + { + return front_implementation(); + } + + //************************************************************************* + /// Peek a value from the front of the queue. + /// Unlocked + //************************************************************************* + const_reference front_from_unlocked() const + { + return front_implementation(); + } + + //************************************************************************* + /// Peek a value from the front of the queue. + //************************************************************************* + reference front() + { + lock(); + + reference result = front_implementation(); + + unlock(); + + return result; + } + + //************************************************************************* + /// Peek a value from the front of the queue. + //************************************************************************* + const_reference front() const + { + lock(); + + const_reference result = front_implementation(); + + unlock(); + + return result; + } + //************************************************************************* /// Clear the queue from the ISR. //************************************************************************* @@ -706,6 +752,24 @@ namespace etl return true; } + //************************************************************************* + /// Peek a value from the front of the queue. + /// Unlocked + //************************************************************************* + reference front_implementation() + { + return p_buffer[this->read_index]; + } + + //************************************************************************* + /// Peek a value from the front of the queue. + /// Unlocked + //************************************************************************* + const_reference front_implementation() const + { + return p_buffer[this->read_index]; + } + //************************************************************************* /// Pop a value from the queue. /// Unlocked diff --git a/test/test_queue_lockable.cpp b/test/test_queue_lockable.cpp index 2ba155f6..1de446a6 100644 --- a/test/test_queue_lockable.cpp +++ b/test/test_queue_lockable.cpp @@ -509,6 +509,44 @@ namespace CHECK(!queue.pop()); } + //************************************************************************* + TEST(test_size_push_front_pop) + { + QueueInt queue; + + CHECK_EQUAL(0U, queue.size()); + + queue.push(1); + queue.push(2); + queue.push(3); + queue.push(4); + CHECK_EQUAL(4U, queue.size()); + + CHECK_EQUAL(1, queue.front()); + CHECK_EQUAL(4U, queue.size()); + + CHECK_EQUAL(1, queue.front()); + CHECK_EQUAL(4U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(3U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(2U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(1U, queue.size()); + + CHECK_EQUAL(4, queue.front()); + CHECK_EQUAL(1U, queue.size()); + + CHECK_EQUAL(4, queue.front()); + CHECK_EQUAL(1U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(0U, queue.size()); + } + //************************************************************************* TEST(test_multiple_emplace) { diff --git a/test/test_queue_lockable_small.cpp b/test/test_queue_lockable_small.cpp index 32f1ec77..04a617c0 100644 --- a/test/test_queue_lockable_small.cpp +++ b/test/test_queue_lockable_small.cpp @@ -509,6 +509,44 @@ namespace CHECK(!queue.pop()); } + //************************************************************************* + TEST(test_size_push_front_pop) + { + QueueInt queue; + + CHECK_EQUAL(0U, queue.size()); + + queue.push(1); + queue.push(2); + queue.push(3); + queue.push(4); + CHECK_EQUAL(4U, queue.size()); + + CHECK_EQUAL(1, queue.front()); + CHECK_EQUAL(4U, queue.size()); + + CHECK_EQUAL(1, queue.front()); + CHECK_EQUAL(4U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(3U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(2U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(1U, queue.size()); + + CHECK_EQUAL(4, queue.front()); + CHECK_EQUAL(1U, queue.size()); + + CHECK_EQUAL(4, queue.front()); + CHECK_EQUAL(1U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(0U, queue.size()); + } + //************************************************************************* TEST(test_multiple_emplace) { diff --git a/test/test_queue_mpmc_mutex.cpp b/test/test_queue_mpmc_mutex.cpp index c0e272e8..6c7c354b 100644 --- a/test/test_queue_mpmc_mutex.cpp +++ b/test/test_queue_mpmc_mutex.cpp @@ -298,6 +298,44 @@ namespace CHECK(!queue.pop()); } + //************************************************************************* + TEST(test_size_push_front_pop) + { + etl::queue_mpmc_mutex queue; + + CHECK_EQUAL(0U, queue.size()); + + queue.push(1); + queue.push(2); + queue.push(3); + queue.push(4); + CHECK_EQUAL(4U, queue.size()); + + CHECK_EQUAL(1, queue.front()); + CHECK_EQUAL(4U, queue.size()); + + CHECK_EQUAL(1, queue.front()); + CHECK_EQUAL(4U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(3U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(2U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(1U, queue.size()); + + CHECK_EQUAL(4, queue.front()); + CHECK_EQUAL(1U, queue.size()); + + CHECK_EQUAL(4, queue.front()); + CHECK_EQUAL(1U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(0U, queue.size()); + } + //************************************************************************* TEST(test_clear) { diff --git a/test/test_queue_mpmc_mutex_small.cpp b/test/test_queue_mpmc_mutex_small.cpp index e8560ac1..09bd4808 100644 --- a/test/test_queue_mpmc_mutex_small.cpp +++ b/test/test_queue_mpmc_mutex_small.cpp @@ -310,6 +310,44 @@ namespace CHECK(!queue.pop()); } + //************************************************************************* + TEST(test_size_push_front_pop) + { + QueueInt queue; + + CHECK_EQUAL(0U, queue.size()); + + queue.push(1); + queue.push(2); + queue.push(3); + queue.push(4); + CHECK_EQUAL(4U, queue.size()); + + CHECK_EQUAL(1, queue.front()); + CHECK_EQUAL(4U, queue.size()); + + CHECK_EQUAL(1, queue.front()); + CHECK_EQUAL(4U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(3U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(2U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(1U, queue.size()); + + CHECK_EQUAL(4, queue.front()); + CHECK_EQUAL(1U, queue.size()); + + CHECK_EQUAL(4, queue.front()); + CHECK_EQUAL(1U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(0U, queue.size()); + } + //************************************************************************* TEST(test_push_255) { diff --git a/test/test_queue_spsc_atomic.cpp b/test/test_queue_spsc_atomic.cpp index 5e15ab7a..ae55fe60 100644 --- a/test/test_queue_spsc_atomic.cpp +++ b/test/test_queue_spsc_atomic.cpp @@ -271,7 +271,8 @@ namespace CHECK(!queue.pop()); } - TEST(test_size_push_peek_pop) + //************************************************************************* + TEST(test_size_push_front_pop) { etl::queue_spsc_atomic queue; @@ -283,14 +284,10 @@ namespace queue.push(4); CHECK_EQUAL(4U, queue.size()); - int i; - - CHECK(queue.peek(i)); - CHECK_EQUAL(1, i); + CHECK_EQUAL(1, queue.front()); CHECK_EQUAL(4U, queue.size()); - CHECK(queue.peek(i)); - CHECK_EQUAL(1, i); + CHECK_EQUAL(1, queue.front()); CHECK_EQUAL(4U, queue.size()); CHECK(queue.pop()); @@ -302,19 +299,14 @@ namespace CHECK(queue.pop()); CHECK_EQUAL(1U, queue.size()); - CHECK(queue.peek(i)); - CHECK_EQUAL(4, i); + CHECK_EQUAL(4, queue.front()); CHECK_EQUAL(1U, queue.size()); - CHECK(queue.peek(i)); - CHECK_EQUAL(4, i); + CHECK_EQUAL(4, queue.front()); CHECK_EQUAL(1U, queue.size()); CHECK(queue.pop()); CHECK_EQUAL(0U, queue.size()); - - CHECK(!queue.peek(i)); - CHECK(!queue.peek(i)); } //************************************************************************* diff --git a/test/test_queue_spsc_atomic_small.cpp b/test/test_queue_spsc_atomic_small.cpp index 96537865..1b3ecfe1 100644 --- a/test/test_queue_spsc_atomic_small.cpp +++ b/test/test_queue_spsc_atomic_small.cpp @@ -289,6 +289,44 @@ namespace CHECK_EQUAL(254U, queue.size()); } + //************************************************************************* + TEST(test_size_push_front_pop) + { + etl::queue_spsc_atomic queue; + + CHECK_EQUAL(0U, queue.size()); + + queue.push(1); + queue.push(2); + queue.push(3); + queue.push(4); + CHECK_EQUAL(4U, queue.size()); + + CHECK_EQUAL(1, queue.front()); + CHECK_EQUAL(4U, queue.size()); + + CHECK_EQUAL(1, queue.front()); + CHECK_EQUAL(4U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(3U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(2U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(1U, queue.size()); + + CHECK_EQUAL(4, queue.front()); + CHECK_EQUAL(1U, queue.size()); + + CHECK_EQUAL(4, queue.front()); + CHECK_EQUAL(1U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(0U, queue.size()); + } + //************************************************************************* TEST(test_multiple_emplace) { diff --git a/test/test_queue_spsc_isr.cpp b/test/test_queue_spsc_isr.cpp index 3f598fe2..a17e60af 100644 --- a/test/test_queue_spsc_isr.cpp +++ b/test/test_queue_spsc_isr.cpp @@ -453,6 +453,46 @@ namespace CHECK(!queue.pop_from_isr()); } + //************************************************************************* + TEST(test_size_push_front_pop) + { + Access::clear(); + + etl::queue_spsc_isr queue; + + CHECK_EQUAL(0U, queue.size()); + + queue.push(1); + queue.push(2); + queue.push(3); + queue.push(4); + CHECK_EQUAL(4U, queue.size()); + + CHECK_EQUAL(1, queue.front()); + CHECK_EQUAL(4U, queue.size()); + + CHECK_EQUAL(1, queue.front()); + CHECK_EQUAL(4U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(3U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(2U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(1U, queue.size()); + + CHECK_EQUAL(4, queue.front()); + CHECK_EQUAL(1U, queue.size()); + + CHECK_EQUAL(4, queue.front()); + CHECK_EQUAL(1U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(0U, queue.size()); + } + //************************************************************************* TEST(test_multiple_emplace) { diff --git a/test/test_queue_spsc_isr_small.cpp b/test/test_queue_spsc_isr_small.cpp index 0b10bc8b..217c0e85 100644 --- a/test/test_queue_spsc_isr_small.cpp +++ b/test/test_queue_spsc_isr_small.cpp @@ -471,6 +471,46 @@ namespace CHECK_EQUAL(255U, queue.size()); } + //************************************************************************* + TEST(test_size_push_front_pop) + { + Access::clear(); + + etl::queue_spsc_isr queue; + + CHECK_EQUAL(0U, queue.size()); + + queue.push(1); + queue.push(2); + queue.push(3); + queue.push(4); + CHECK_EQUAL(4U, queue.size()); + + CHECK_EQUAL(1, queue.front()); + CHECK_EQUAL(4U, queue.size()); + + CHECK_EQUAL(1, queue.front()); + CHECK_EQUAL(4U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(3U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(2U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(1U, queue.size()); + + CHECK_EQUAL(4, queue.front()); + CHECK_EQUAL(1U, queue.size()); + + CHECK_EQUAL(4, queue.front()); + CHECK_EQUAL(1U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(0U, queue.size()); + } + //************************************************************************* TEST(test_multiple_emplace) { diff --git a/test/test_queue_spsc_locked.cpp b/test/test_queue_spsc_locked.cpp index 9ea90bd0..58799996 100644 --- a/test/test_queue_spsc_locked.cpp +++ b/test/test_queue_spsc_locked.cpp @@ -458,6 +458,46 @@ namespace CHECK(!queue.pop_from_unlocked()); } + //************************************************************************* + TEST(test_size_push_front_pop) + { + access.clear(); + + etl::queue_spsc_locked queue(lock, unlock); + + CHECK_EQUAL(0U, queue.size()); + + queue.push(1); + queue.push(2); + queue.push(3); + queue.push(4); + CHECK_EQUAL(4U, queue.size()); + + CHECK_EQUAL(1, queue.front()); + CHECK_EQUAL(4U, queue.size()); + + CHECK_EQUAL(1, queue.front()); + CHECK_EQUAL(4U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(3U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(2U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(1U, queue.size()); + + CHECK_EQUAL(4, queue.front()); + CHECK_EQUAL(1U, queue.size()); + + CHECK_EQUAL(4, queue.front()); + CHECK_EQUAL(1U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(0U, queue.size()); + } + //************************************************************************* TEST(test_multiple_emplace) { diff --git a/test/test_queue_spsc_locked_small.cpp b/test/test_queue_spsc_locked_small.cpp index fc75a802..91236d0b 100644 --- a/test/test_queue_spsc_locked_small.cpp +++ b/test/test_queue_spsc_locked_small.cpp @@ -475,6 +475,46 @@ namespace CHECK_EQUAL(255U, queue.size()); } + //************************************************************************* + TEST(test_size_push_front_pop) + { + access.clear(); + + etl::queue_spsc_locked queue(lock, unlock); + + CHECK_EQUAL(0U, queue.size()); + + queue.push(1); + queue.push(2); + queue.push(3); + queue.push(4); + CHECK_EQUAL(4U, queue.size()); + + CHECK_EQUAL(1, queue.front()); + CHECK_EQUAL(4U, queue.size()); + + CHECK_EQUAL(1, queue.front()); + CHECK_EQUAL(4U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(3U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(2U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(1U, queue.size()); + + CHECK_EQUAL(4, queue.front()); + CHECK_EQUAL(1U, queue.size()); + + CHECK_EQUAL(4, queue.front()); + CHECK_EQUAL(1U, queue.size()); + + CHECK(queue.pop()); + CHECK_EQUAL(0U, queue.size()); + } + //************************************************************************* TEST(test_multiple_emplace) {