From e5f4eb6fb38c337c82fcc250f17a8f21eb788975 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 31 Jan 2021 12:34:49 +0000 Subject: [PATCH] Squashed commit of the following: commit 23c5f1d3f9b13ff9e46ce3de96aefeb655d5ed97 Author: John Wellbelove Date: Sun Jan 31 12:32:35 2021 +0000 Fixed rollover error for etl::queue_spsc_atomic Added 'required_alignment' parameter to 'allocate' for etl::imemeory_block_allocator. Updated QueuedMessageRouter example --- .gitignore | 1 + .../QueuedMessageRouter.cpp | 17 ++--- .../vs2017/.vs/QueuedMessageRouter.sqlite | Bin 278528 -> 0 bytes .../QueuedMessageRouter.vcxproj.filters | 27 -------- .../QueuedMessageRouter.sln | 0 .../QueuedMessageRouter.vcxproj | 10 +-- .../etl/fixed_sized_memory_block_allocator.h | 6 +- include/etl/imemory_block_allocator.h | 8 +-- include/etl/queue_spsc_atomic.h | 2 +- include/etl/reference_counted_message_pool.h | 2 +- include/etl/version.h | 2 +- library.json | 2 +- library.properties | 2 +- support/Release notes.txt | 6 ++ ...est_fixed_sized_memory_block_allocator.cpp | 58 +++++++++--------- test/test_queue_lockable.cpp | 21 +++++-- test/test_queue_lockable_small.cpp | 21 +++++-- test/test_queue_mpmc_mutex.cpp | 21 +++++-- test/test_queue_mpmc_mutex_small.cpp | 21 +++++-- test/test_queue_spsc_atomic.cpp | 21 +++++-- test/test_queue_spsc_atomic_small.cpp | 21 +++++-- test/test_queue_spsc_isr.cpp | 21 +++++-- test/test_queue_spsc_isr_small.cpp | 21 +++++-- test/test_queue_spsc_locked.cpp | 21 +++++-- test/test_queue_spsc_locked_small.cpp | 21 +++++-- test/vs2019/etl.vcxproj | 1 + test/vs2019/etl.vcxproj.filters | 3 + 27 files changed, 228 insertions(+), 129 deletions(-) delete mode 100644 examples/QueuedMessageRouter/vs2017/.vs/QueuedMessageRouter.sqlite delete mode 100644 examples/QueuedMessageRouter/vs2017/QueuedMessageRouter.vcxproj.filters rename examples/QueuedMessageRouter/{vs2017 => vs2019}/QueuedMessageRouter.sln (100%) rename examples/QueuedMessageRouter/{vs2017 => vs2019}/QueuedMessageRouter.vcxproj (96%) diff --git a/.gitignore b/.gitignore index 877c2b1d..45c37380 100644 --- a/.gitignore +++ b/.gitignore @@ -285,3 +285,4 @@ examples/FunctionInterruptSimulation-Delegates/vs2019/.vs *.db-shm test/vs2019/.vs/etl/v16/Browse.VC.db-wal examples/SharedMessage/.vs +examples/QueuedMessageRouter/vs2019/.vs diff --git a/examples/QueuedMessageRouter/QueuedMessageRouter.cpp b/examples/QueuedMessageRouter/QueuedMessageRouter.cpp index f635709e..a392db95 100644 --- a/examples/QueuedMessageRouter/QueuedMessageRouter.cpp +++ b/examples/QueuedMessageRouter/QueuedMessageRouter.cpp @@ -67,13 +67,16 @@ public: if (accepts(msg_)) { // Place in queue. + + Item item(&sender_, msg_); + queue.emplace(&sender_, msg_); - std::cout << "Queueing message " << int(msg_.message_id) << std::endl; + std::cout << "Queueing message " << int(msg_.get_message_id()) << std::endl; } else { - std::cout << "Ignoring message " << int(msg_.message_id) << std::endl; + std::cout << "Ignoring message " << int(msg_.get_message_id()) << std::endl; } } @@ -85,7 +88,7 @@ public: Item& item = queue.front(); etl::imessage& msg = item.packet.get(); etl::imessage_router& sender = *item.sender; - std::cout << "Processing message " << int(msg.message_id) << std::endl; + std::cout << "Processing message " << int(msg.get_message_id()) << std::endl; // Call the base class's receive function. // This will route it to the correct on_receive handler. @@ -98,25 +101,25 @@ public: //*************************************************************************** void on_receive(etl::imessage_router& sender, const Message1& msg) { - std::cout << " Received message " << int(msg.message_id) << " : '" << msg.i << "'" << std::endl; + std::cout << " Received message " << int(msg.get_message_id()) << " : '" << msg.i << "'" << std::endl; } //*************************************************************************** void on_receive(etl::imessage_router& sender, const Message2& msg) { - std::cout << " Received message " << int(msg.message_id) << " : '" << msg.d << "'" << std::endl; + std::cout << " Received message " << int(msg.get_message_id()) << " : '" << msg.d << "'" << std::endl; } //*************************************************************************** void on_receive(etl::imessage_router& sender, const Message3& msg) { - std::cout << " Received message " << int(msg.message_id) << " : '" << msg.s << "'" << std::endl; + std::cout << " Received message " << int(msg.get_message_id()) << " : '" << msg.s << "'" << std::endl; } //*************************************************************************** void on_receive_unknown(etl::imessage_router& sender, const etl::imessage& msg) { - std::cout << " Received unknown message " << int(msg.message_id) << std::endl; + std::cout << " Received unknown message " << int(msg.get_message_id()) << std::endl; } private: diff --git a/examples/QueuedMessageRouter/vs2017/.vs/QueuedMessageRouter.sqlite b/examples/QueuedMessageRouter/vs2017/.vs/QueuedMessageRouter.sqlite deleted file mode 100644 index 2572d76ef2a2e251849d46ab244b5419711b8b18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 278528 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 T1J@#W6U3GnI`Pn%931~YCDseX diff --git a/examples/QueuedMessageRouter/vs2017/QueuedMessageRouter.vcxproj.filters b/examples/QueuedMessageRouter/vs2017/QueuedMessageRouter.vcxproj.filters deleted file mode 100644 index 795b7698..00000000 --- a/examples/QueuedMessageRouter/vs2017/QueuedMessageRouter.vcxproj.filters +++ /dev/null @@ -1,27 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - - - Header Files - - - \ No newline at end of file diff --git a/examples/QueuedMessageRouter/vs2017/QueuedMessageRouter.sln b/examples/QueuedMessageRouter/vs2019/QueuedMessageRouter.sln similarity index 100% rename from examples/QueuedMessageRouter/vs2017/QueuedMessageRouter.sln rename to examples/QueuedMessageRouter/vs2019/QueuedMessageRouter.sln diff --git a/examples/QueuedMessageRouter/vs2017/QueuedMessageRouter.vcxproj b/examples/QueuedMessageRouter/vs2019/QueuedMessageRouter.vcxproj similarity index 96% rename from examples/QueuedMessageRouter/vs2017/QueuedMessageRouter.vcxproj rename to examples/QueuedMessageRouter/vs2019/QueuedMessageRouter.vcxproj index 2c3eba2a..65dad150 100644 --- a/examples/QueuedMessageRouter/vs2017/QueuedMessageRouter.vcxproj +++ b/examples/QueuedMessageRouter/vs2019/QueuedMessageRouter.vcxproj @@ -23,32 +23,32 @@ {2BB47D48-5EFC-4C38-B2BE-002172F00E3B} Win32Proj QueuedMessageRouter - 10.0.18362.0 + 10.0 Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode diff --git a/include/etl/fixed_sized_memory_block_allocator.h b/include/etl/fixed_sized_memory_block_allocator.h index ae3e217f..3e70641b 100644 --- a/include/etl/fixed_sized_memory_block_allocator.h +++ b/include/etl/fixed_sized_memory_block_allocator.h @@ -80,9 +80,11 @@ namespace etl //************************************************************************* /// The overridden virtual function to allocate a block. //************************************************************************* - virtual void* allocate_block(size_t required_size) ETL_OVERRIDE + virtual void* allocate_block(size_t required_size, size_t required_alignment) ETL_OVERRIDE { - if ((required_size <= Block_Size) && !pool.full()) + if ((required_alignment <= Alignment) && + (required_size <= Block_Size) && + !pool.full()) { return pool.template allocate(); } diff --git a/include/etl/imemory_block_allocator.h b/include/etl/imemory_block_allocator.h index aed1493d..5b8529a2 100644 --- a/include/etl/imemory_block_allocator.h +++ b/include/etl/imemory_block_allocator.h @@ -55,10 +55,10 @@ namespace etl /// Try to allocate a memory block of the required size. /// If this allocator cannot, then pass the request on the the successor, if configured. //***************************************************************************** - void* allocate(size_t required_size) + void* allocate(size_t required_size, size_t required_alignment) { // Call the derived implementation. - void* p = allocate_block(required_size); + void* p = allocate_block(required_size, required_alignment); // If that failed... if (p == ETL_NULLPTR) @@ -67,7 +67,7 @@ namespace etl if (has_successor()) { // Try to allocate from the next one in the chain. - return get_successor().allocate(required_size); + return get_successor().allocate(required_size, required_alignment); } } @@ -98,7 +98,7 @@ namespace etl protected: - virtual void* allocate_block(size_t required_size) = 0; + virtual void* allocate_block(size_t required_size, size_t required_alignment) = 0; virtual bool release_block(const void* const) = 0; private: diff --git a/include/etl/queue_spsc_atomic.h b/include/etl/queue_spsc_atomic.h index 3501ebdc..13e496a8 100644 --- a/include/etl/queue_spsc_atomic.h +++ b/include/etl/queue_spsc_atomic.h @@ -97,7 +97,7 @@ namespace etl } else { - n = RESERVED - read_index + write_index - 1; + n = RESERVED - read_index + write_index; } return n; diff --git a/include/etl/reference_counted_message_pool.h b/include/etl/reference_counted_message_pool.h index 2bc45e08..8003983f 100644 --- a/include/etl/reference_counted_message_pool.h +++ b/include/etl/reference_counted_message_pool.h @@ -117,7 +117,7 @@ namespace etl prcm_t p = ETL_NULLPTR; lock(); - p = static_cast(memory_block_allocator.allocate(sizeof(rcm_t))); + p = static_cast(memory_block_allocator.allocate(sizeof(rcm_t), etl::alignment_of::value)); unlock(); if (p != ETL_NULLPTR) diff --git a/include/etl/version.h b/include/etl/version.h index df94a637..f322966d 100644 --- a/include/etl/version.h +++ b/include/etl/version.h @@ -39,7 +39,7 @@ SOFTWARE. #define ETL_VERSION_MAJOR 19 #define ETL_VERSION_MINOR 5 -#define ETL_VERSION_PATCH 1 +#define ETL_VERSION_PATCH 2 #define ETL_VERSION ETL_STRINGIFY(ETL_VERSION_MAJOR) "." ETL_STRINGIFY(ETL_VERSION_MINOR) "." ETL_STRINGIFY(ETL_VERSION_PATCH) #define ETL_VERSION_W ETL_STRINGIFY(ETL_VERSION_MAJOR) L"." ETL_STRINGIFY(ETL_VERSION_MINOR) L"." ETL_STRINGIFY(ETL_VERSION_PATCH) #define ETL_VERSION_U16 ETL_STRINGIFY(ETL_VERSION_MAJOR) u"." ETL_STRINGIFY(ETL_VERSION_MINOR) u"." ETL_STRINGIFY(ETL_VERSION_PATCH) diff --git a/library.json b/library.json index c894dcd5..4d2a3654 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "ETL Embedded Template Library", - "version": "19.5.1", + "version": "19.5.2", "author s": { "name": "John Wellbelove", "email": "john.wellbelove@etlcpp.com" diff --git a/library.properties b/library.properties index 74b20470..f45cfaeb 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library ETL -version=19.5.1 +version=19.5.2 author= John Wellbelove maintainer=John Wellbelove license=MIT diff --git a/support/Release notes.txt b/support/Release notes.txt index a53ce710..21d306e3 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,3 +1,9 @@ +=============================================================================== +19.5.2 +Fixed rollover error for etl::queue_spsc_atomic +Added 'required_alignment' parameter to 'allocate' for etl::imemeory_block_allocator. +Updated QueuedMessageRouter example. + =============================================================================== 19.5.1 Exclude integral types from being considered for iterator range container constructors. diff --git a/test/test_fixed_sized_memory_block_allocator.cpp b/test/test_fixed_sized_memory_block_allocator.cpp index bbcd5f21..4767d53b 100644 --- a/test/test_fixed_sized_memory_block_allocator.cpp +++ b/test/test_fixed_sized_memory_block_allocator.cpp @@ -43,11 +43,11 @@ namespace { Allocator16 allocator16; - int16_t* p1 = static_cast(allocator16.allocate(sizeof(int16_t))); - int16_t* p2 = static_cast(allocator16.allocate(sizeof(int16_t))); - int16_t* p3 = static_cast(allocator16.allocate(sizeof(int16_t))); - int16_t* p4 = static_cast(allocator16.allocate(sizeof(int16_t))); - int16_t* p5 = static_cast(allocator16.allocate(sizeof(int16_t))); + int16_t* p1 = static_cast(allocator16.allocate(sizeof(int16_t), alignof(int16_t))); + int16_t* p2 = static_cast(allocator16.allocate(sizeof(int16_t), alignof(int16_t))); + int16_t* p3 = static_cast(allocator16.allocate(sizeof(int16_t), alignof(int16_t))); + int16_t* p4 = static_cast(allocator16.allocate(sizeof(int16_t), alignof(int16_t))); + int16_t* p5 = static_cast(allocator16.allocate(sizeof(int16_t), alignof(int16_t))); CHECK(p1 != nullptr); CHECK(p2 != nullptr); @@ -87,19 +87,19 @@ namespace allocator16.set_successor(allocator16s); allocator16s.set_successor(allocator16ss); - int16_t* p1 = static_cast(allocator16.allocate(sizeof(int16_t))); - int16_t* p2 = static_cast(allocator16.allocate(sizeof(int16_t))); - int16_t* p3 = static_cast(allocator16.allocate(sizeof(int16_t))); - int16_t* p4 = static_cast(allocator16.allocate(sizeof(int16_t))); - int16_t* p5 = static_cast(allocator16.allocate(sizeof(int16_t))); - int16_t* p6 = static_cast(allocator16.allocate(sizeof(int16_t))); - int16_t* p7 = static_cast(allocator16.allocate(sizeof(int16_t))); - int16_t* p8 = static_cast(allocator16.allocate(sizeof(int16_t))); - int16_t* p9 = static_cast(allocator16.allocate(sizeof(int16_t))); - int16_t* p10 = static_cast(allocator16.allocate(sizeof(int16_t))); - int16_t* p11 = static_cast(allocator16.allocate(sizeof(int16_t))); - int16_t* p12 = static_cast(allocator16.allocate(sizeof(int16_t))); - int16_t* p13 = static_cast(allocator16.allocate(sizeof(int16_t))); + int16_t* p1 = static_cast(allocator16.allocate(sizeof(int16_t), alignof(uint16_t))); + int16_t* p2 = static_cast(allocator16.allocate(sizeof(int16_t), alignof(uint16_t))); + int16_t* p3 = static_cast(allocator16.allocate(sizeof(int16_t), alignof(uint16_t))); + int16_t* p4 = static_cast(allocator16.allocate(sizeof(int16_t), alignof(uint16_t))); + int16_t* p5 = static_cast(allocator16.allocate(sizeof(int16_t), alignof(uint16_t))); + int16_t* p6 = static_cast(allocator16.allocate(sizeof(int16_t), alignof(uint16_t))); + int16_t* p7 = static_cast(allocator16.allocate(sizeof(int16_t), alignof(uint16_t))); + int16_t* p8 = static_cast(allocator16.allocate(sizeof(int16_t), alignof(uint16_t))); + int16_t* p9 = static_cast(allocator16.allocate(sizeof(int16_t), alignof(uint16_t))); + int16_t* p10 = static_cast(allocator16.allocate(sizeof(int16_t), alignof(uint16_t))); + int16_t* p11 = static_cast(allocator16.allocate(sizeof(int16_t), alignof(uint16_t))); + int16_t* p12 = static_cast(allocator16.allocate(sizeof(int16_t), alignof(uint16_t))); + int16_t* p13 = static_cast(allocator16.allocate(sizeof(int16_t), alignof(uint16_t))); CHECK(p1 != nullptr); CHECK(p2 != nullptr); @@ -140,17 +140,17 @@ namespace allocator8.set_successor(allocator16); allocator16.set_successor(allocator32); - int8_t* p1 = static_cast(allocator8.allocate(sizeof(int8_t))); // Take from allocator8 - int16_t* p2 = static_cast(allocator8.allocate(sizeof(int16_t))); // Take from allocator16 - int32_t* p3 = static_cast(allocator8.allocate(sizeof(int32_t))); // Take from allocator32 - int64_t* p4 = static_cast(allocator8.allocate(sizeof(int64_t))); // Unable to allocate - int8_t* p5 = static_cast(allocator8.allocate(sizeof(int8_t))); // Take from allocator8 - int8_t* p6 = static_cast(allocator8.allocate(sizeof(int8_t))); // Take from allocator8 - int8_t* p7 = static_cast(allocator8.allocate(sizeof(int8_t))); // Take from allocator8. allocator8 is full. - int8_t* p8 = static_cast(allocator8.allocate(sizeof(int8_t))); // Take from allocator16 - int8_t* p9 = static_cast(allocator8.allocate(sizeof(int8_t))); // Take from allocator16 - int8_t* p10 = static_cast(allocator8.allocate(sizeof(int8_t))); // Take from allocator16. allocator16 is full. - int8_t* p11 = static_cast(allocator8.allocate(sizeof(int8_t))); // Take from allocator32 + int8_t* p1 = static_cast(allocator8.allocate(sizeof(int8_t), alignof(uint8_t))); // Take from allocator8 + int16_t* p2 = static_cast(allocator8.allocate(sizeof(int16_t), alignof(uint16_t))); // Take from allocator16 + int32_t* p3 = static_cast(allocator8.allocate(sizeof(int32_t), alignof(uint32_t))); // Take from allocator32 + int64_t* p4 = static_cast(allocator8.allocate(sizeof(int64_t), alignof(uint64_t))); // Unable to allocate + int8_t* p5 = static_cast(allocator8.allocate(sizeof(int8_t), alignof(uint8_t))); // Take from allocator8 + int8_t* p6 = static_cast(allocator8.allocate(sizeof(int8_t), alignof(uint8_t))); // Take from allocator8 + int8_t* p7 = static_cast(allocator8.allocate(sizeof(int8_t), alignof(uint8_t))); // Take from allocator8. allocator8 is full. + int8_t* p8 = static_cast(allocator8.allocate(sizeof(int8_t), alignof(uint8_t))); // Take from allocator16 + int8_t* p9 = static_cast(allocator8.allocate(sizeof(int8_t), alignof(uint8_t))); // Take from allocator16 + int8_t* p10 = static_cast(allocator8.allocate(sizeof(int8_t), alignof(uint8_t))); // Take from allocator16. allocator16 is full. + int8_t* p11 = static_cast(allocator8.allocate(sizeof(int8_t), alignof(uint8_t))); // Take from allocator32 CHECK(p1 != nullptr); CHECK(p2 != nullptr); diff --git a/test/test_queue_lockable.cpp b/test/test_queue_lockable.cpp index b6f0b6d3..65edaa50 100644 --- a/test/test_queue_lockable.cpp +++ b/test/test_queue_lockable.cpp @@ -244,15 +244,26 @@ namespace queue.clear_test_flags(); + // Queue full. CHECK(!queue.push(5)); - CHECK(!queue.push(5)); + + queue.pop(); + // Queue not full (buffer rollover) + CHECK(queue.push(5)); + + // Queue full. + CHECK(!queue.push(6)); + + queue.pop(); + // Queue not full (buffer rollover) + CHECK(queue.push(6)); queue.clear_test_flags(); int i; CHECK(queue.pop(i)); - CHECK_EQUAL(1, i); + CHECK_EQUAL(3, i); CHECK(queue.called_lock); CHECK(queue.called_unlock); CHECK_EQUAL(3U, queue.size()); @@ -260,7 +271,7 @@ namespace queue.clear_test_flags(); CHECK(queue.pop(i)); - CHECK_EQUAL(2, i); + CHECK_EQUAL(4, i); CHECK(queue.called_lock); CHECK(queue.called_unlock); CHECK_EQUAL(2U, queue.size()); @@ -268,7 +279,7 @@ namespace queue.clear_test_flags(); CHECK(queue.pop(i)); - CHECK_EQUAL(3, i); + CHECK_EQUAL(5, i); CHECK(queue.called_lock); CHECK(queue.called_unlock); CHECK_EQUAL(1U, queue.size()); @@ -276,7 +287,7 @@ namespace queue.clear_test_flags(); CHECK(queue.pop(i)); - CHECK_EQUAL(4, i); + CHECK_EQUAL(6, i); CHECK(queue.called_lock); CHECK(queue.called_unlock); CHECK_EQUAL(0U, queue.size()); diff --git a/test/test_queue_lockable_small.cpp b/test/test_queue_lockable_small.cpp index 994dec72..d4351e06 100644 --- a/test/test_queue_lockable_small.cpp +++ b/test/test_queue_lockable_small.cpp @@ -244,15 +244,26 @@ namespace queue.clear_test_flags(); + // Queue full. CHECK(!queue.push(5)); - CHECK(!queue.push(5)); + + queue.pop(); + // Queue not full (buffer rollover) + CHECK(queue.push(5)); + + // Queue full. + CHECK(!queue.push(6)); + + queue.pop(); + // Queue not full (buffer rollover) + CHECK(queue.push(6)); queue.clear_test_flags(); int i; CHECK(queue.pop(i)); - CHECK_EQUAL(1, i); + CHECK_EQUAL(3, i); CHECK(queue.called_lock); CHECK(queue.called_unlock); CHECK_EQUAL(3U, queue.size()); @@ -260,7 +271,7 @@ namespace queue.clear_test_flags(); CHECK(queue.pop(i)); - CHECK_EQUAL(2, i); + CHECK_EQUAL(4, i); CHECK(queue.called_lock); CHECK(queue.called_unlock); CHECK_EQUAL(2U, queue.size()); @@ -268,7 +279,7 @@ namespace queue.clear_test_flags(); CHECK(queue.pop(i)); - CHECK_EQUAL(3, i); + CHECK_EQUAL(5, i); CHECK(queue.called_lock); CHECK(queue.called_unlock); CHECK_EQUAL(1U, queue.size()); @@ -276,7 +287,7 @@ namespace queue.clear_test_flags(); CHECK(queue.pop(i)); - CHECK_EQUAL(4, i); + CHECK_EQUAL(6, i); CHECK(queue.called_lock); CHECK(queue.called_unlock); CHECK_EQUAL(0U, queue.size()); diff --git a/test/test_queue_mpmc_mutex.cpp b/test/test_queue_mpmc_mutex.cpp index ebe0edbd..ee2b4a54 100644 --- a/test/test_queue_mpmc_mutex.cpp +++ b/test/test_queue_mpmc_mutex.cpp @@ -117,25 +117,36 @@ namespace CHECK_EQUAL(4U, queue.size()); CHECK_EQUAL(0U, queue.available()); + // Queue full. CHECK(!queue.push(5)); - CHECK(!queue.push(5)); + + queue.pop(); + // Queue not full (buffer rollover) + CHECK(queue.push(5)); + + // Queue full. + CHECK(!queue.push(6)); + + queue.pop(); + // Queue not full (buffer rollover) + CHECK(queue.push(6)); int i; CHECK(queue.pop(i)); - CHECK_EQUAL(1, i); + CHECK_EQUAL(3, i); CHECK_EQUAL(3U, queue.size()); CHECK(queue.pop(i)); - CHECK_EQUAL(2, i); + CHECK_EQUAL(4, i); CHECK_EQUAL(2U, queue.size()); CHECK(queue.pop(i)); - CHECK_EQUAL(3, i); + CHECK_EQUAL(5, i); CHECK_EQUAL(1U, queue.size()); CHECK(queue.pop(i)); - CHECK_EQUAL(4, i); + CHECK_EQUAL(6, i); CHECK_EQUAL(0U, queue.size()); CHECK(!queue.pop(i)); diff --git a/test/test_queue_mpmc_mutex_small.cpp b/test/test_queue_mpmc_mutex_small.cpp index 1f5ad387..fdf087ec 100644 --- a/test/test_queue_mpmc_mutex_small.cpp +++ b/test/test_queue_mpmc_mutex_small.cpp @@ -129,25 +129,36 @@ namespace CHECK_EQUAL(4U, queue.size()); CHECK_EQUAL(0U, queue.available()); + // Queue full. CHECK(!queue.push(5)); - CHECK(!queue.push(5)); + + queue.pop(); + // Queue not full (buffer rollover) + CHECK(queue.push(5)); + + // Queue full. + CHECK(!queue.push(6)); + + queue.pop(); + // Queue not full (buffer rollover) + CHECK(queue.push(6)); int i; CHECK(queue.pop(i)); - CHECK_EQUAL(1, i); + CHECK_EQUAL(3, i); CHECK_EQUAL(3U, queue.size()); CHECK(queue.pop(i)); - CHECK_EQUAL(2, i); + CHECK_EQUAL(4, i); CHECK_EQUAL(2U, queue.size()); CHECK(queue.pop(i)); - CHECK_EQUAL(3, i); + CHECK_EQUAL(5, i); CHECK_EQUAL(1U, queue.size()); CHECK(queue.pop(i)); - CHECK_EQUAL(4, i); + CHECK_EQUAL(6, i); CHECK_EQUAL(0U, queue.size()); CHECK(!queue.pop(i)); diff --git a/test/test_queue_spsc_atomic.cpp b/test/test_queue_spsc_atomic.cpp index 64a2df05..a4e20694 100644 --- a/test/test_queue_spsc_atomic.cpp +++ b/test/test_queue_spsc_atomic.cpp @@ -114,25 +114,36 @@ namespace CHECK_EQUAL(4U, queue.size()); CHECK_EQUAL(0U, queue.available()); + // Queue full. CHECK(!queue.push(5)); - CHECK(!queue.push(5)); + + queue.pop(); + // Queue not full (buffer rollover) + CHECK(queue.push(5)); + + // Queue full. + CHECK(!queue.push(6)); + + queue.pop(); + // Queue not full (buffer rollover) + CHECK(queue.push(6)); int i; CHECK(queue.pop(i)); - CHECK_EQUAL(1, i); + CHECK_EQUAL(3, i); CHECK_EQUAL(3U, queue.size()); CHECK(queue.pop(i)); - CHECK_EQUAL(2, i); + CHECK_EQUAL(4, i); CHECK_EQUAL(2U, queue.size()); CHECK(queue.pop(i)); - CHECK_EQUAL(3, i); + CHECK_EQUAL(5, i); CHECK_EQUAL(1U, queue.size()); CHECK(queue.pop(i)); - CHECK_EQUAL(4, i); + CHECK_EQUAL(6, i); CHECK_EQUAL(0U, queue.size()); CHECK(!queue.pop(i)); diff --git a/test/test_queue_spsc_atomic_small.cpp b/test/test_queue_spsc_atomic_small.cpp index ce4a5274..1a50fdad 100644 --- a/test/test_queue_spsc_atomic_small.cpp +++ b/test/test_queue_spsc_atomic_small.cpp @@ -119,25 +119,36 @@ namespace CHECK_EQUAL(4U, queue.size()); CHECK_EQUAL(0U, queue.available()); + // Queue full. CHECK(!queue.push(5)); - CHECK(!queue.push(5)); + + queue.pop(); + // Queue not full (buffer rollover) + CHECK(queue.push(5)); + + // Queue full. + CHECK(!queue.push(6)); + + queue.pop(); + // Queue not full (buffer rollover) + CHECK(queue.push(6)); int i; CHECK(queue.pop(i)); - CHECK_EQUAL(1, i); + CHECK_EQUAL(3, i); CHECK_EQUAL(3U, queue.size()); CHECK(queue.pop(i)); - CHECK_EQUAL(2, i); + CHECK_EQUAL(4, i); CHECK_EQUAL(2U, queue.size()); CHECK(queue.pop(i)); - CHECK_EQUAL(3, i); + CHECK_EQUAL(5, i); CHECK_EQUAL(1U, queue.size()); CHECK(queue.pop(i)); - CHECK_EQUAL(4, i); + CHECK_EQUAL(6, i); CHECK_EQUAL(0U, queue.size()); CHECK(!queue.pop(i)); diff --git a/test/test_queue_spsc_isr.cpp b/test/test_queue_spsc_isr.cpp index eaf559aa..286f73d1 100644 --- a/test/test_queue_spsc_isr.cpp +++ b/test/test_queue_spsc_isr.cpp @@ -184,15 +184,26 @@ namespace Access::clear(); + // Queue full. CHECK(!queue.push(5)); - CHECK(!queue.push_from_isr(5)); + + queue.pop(); + // Queue not full (buffer rollover) + CHECK(queue.push(5)); + + // Queue full. + CHECK(!queue.push(6)); + + queue.pop(); + // Queue not full (buffer rollover) + CHECK(queue.push(6)); Access::clear(); int i; CHECK(queue.pop(i)); - CHECK_EQUAL(1, i); + CHECK_EQUAL(3, i); CHECK(Access::called_lock); CHECK(Access::called_unlock); CHECK_EQUAL(3U, queue.size_from_isr()); @@ -200,7 +211,7 @@ namespace Access::clear(); CHECK(queue.pop_from_isr(i)); - CHECK_EQUAL(2, i); + CHECK_EQUAL(4, i); CHECK(!Access::called_lock); CHECK(!Access::called_unlock); CHECK_EQUAL(2U, queue.size_from_isr()); @@ -208,7 +219,7 @@ namespace Access::clear(); CHECK(queue.pop_from_isr(i)); - CHECK_EQUAL(3, i); + CHECK_EQUAL(5, i); CHECK(!Access::called_lock); CHECK(!Access::called_unlock); CHECK_EQUAL(1U, queue.size_from_isr()); @@ -216,7 +227,7 @@ namespace Access::clear(); CHECK(queue.pop_from_isr(i)); - CHECK_EQUAL(4, i); + CHECK_EQUAL(6, i); CHECK(!Access::called_lock); CHECK(!Access::called_unlock); CHECK_EQUAL(0U, queue.size_from_isr()); diff --git a/test/test_queue_spsc_isr_small.cpp b/test/test_queue_spsc_isr_small.cpp index ff19db76..1ce8e8e7 100644 --- a/test/test_queue_spsc_isr_small.cpp +++ b/test/test_queue_spsc_isr_small.cpp @@ -189,15 +189,26 @@ namespace Access::clear(); + // Queue full. CHECK(!queue.push(5)); - CHECK(!queue.push_from_isr(5)); + + queue.pop(); + // Queue not full (buffer rollover) + CHECK(queue.push(5)); + + // Queue full. + CHECK(!queue.push(6)); + + queue.pop(); + // Queue not full (buffer rollover) + CHECK(queue.push(6)); Access::clear(); int i; CHECK(queue.pop(i)); - CHECK_EQUAL(1, i); + CHECK_EQUAL(3, i); CHECK(Access::called_lock); CHECK(Access::called_unlock); CHECK_EQUAL(3U, queue.size_from_isr()); @@ -205,7 +216,7 @@ namespace Access::clear(); CHECK(queue.pop_from_isr(i)); - CHECK_EQUAL(2, i); + CHECK_EQUAL(4, i); CHECK(!Access::called_lock); CHECK(!Access::called_unlock); CHECK_EQUAL(2U, queue.size_from_isr()); @@ -213,7 +224,7 @@ namespace Access::clear(); CHECK(queue.pop_from_isr(i)); - CHECK_EQUAL(3, i); + CHECK_EQUAL(5, i); CHECK(!Access::called_lock); CHECK(!Access::called_unlock); CHECK_EQUAL(1U, queue.size_from_isr()); @@ -221,7 +232,7 @@ namespace Access::clear(); CHECK(queue.pop_from_isr(i)); - CHECK_EQUAL(4, i); + CHECK_EQUAL(6, i); CHECK(!Access::called_lock); CHECK(!Access::called_unlock); CHECK_EQUAL(0U, queue.size_from_isr()); diff --git a/test/test_queue_spsc_locked.cpp b/test/test_queue_spsc_locked.cpp index 09d53c94..6abe7c92 100644 --- a/test/test_queue_spsc_locked.cpp +++ b/test/test_queue_spsc_locked.cpp @@ -187,15 +187,26 @@ namespace access.clear(); + // Queue full. CHECK(!queue.push(5)); - CHECK(!queue.push_from_unlocked(5)); + + queue.pop(); + // Queue not full (buffer rollover) + CHECK(queue.push(5)); + + // Queue full. + CHECK(!queue.push(6)); + + queue.pop(); + // Queue not full (buffer rollover) + CHECK(queue.push(6)); access.clear(); int i; CHECK(queue.pop(i)); - CHECK_EQUAL(1, i); + CHECK_EQUAL(3, i); CHECK(access.called_lock); CHECK(access.called_unlock); CHECK_EQUAL(3U, queue.size_from_unlocked()); @@ -203,7 +214,7 @@ namespace access.clear(); CHECK(queue.pop_from_unlocked(i)); - CHECK_EQUAL(2, i); + CHECK_EQUAL(4, i); CHECK(!access.called_lock); CHECK(!access.called_unlock); CHECK_EQUAL(2U, queue.size_from_unlocked()); @@ -211,7 +222,7 @@ namespace access.clear(); CHECK(queue.pop_from_unlocked(i)); - CHECK_EQUAL(3, i); + CHECK_EQUAL(5, i); CHECK(!access.called_lock); CHECK(!access.called_unlock); CHECK_EQUAL(1U, queue.size_from_unlocked()); @@ -219,7 +230,7 @@ namespace access.clear(); CHECK(queue.pop_from_unlocked(i)); - CHECK_EQUAL(4, i); + CHECK_EQUAL(6, i); CHECK(!access.called_lock); CHECK(!access.called_unlock); CHECK_EQUAL(0U, queue.size_from_unlocked()); diff --git a/test/test_queue_spsc_locked_small.cpp b/test/test_queue_spsc_locked_small.cpp index c55784d1..93cd822f 100644 --- a/test/test_queue_spsc_locked_small.cpp +++ b/test/test_queue_spsc_locked_small.cpp @@ -191,15 +191,26 @@ namespace access.clear(); + // Queue full. CHECK(!queue.push(5)); - CHECK(!queue.push_from_unlocked(5)); + + queue.pop(); + // Queue not full (buffer rollover) + CHECK(queue.push(5)); + + // Queue full. + CHECK(!queue.push(6)); + + queue.pop(); + // Queue not full (buffer rollover) + CHECK(queue.push(6)); access.clear(); int i; CHECK(queue.pop(i)); - CHECK_EQUAL(1, i); + CHECK_EQUAL(3, i); CHECK(access.called_lock); CHECK(access.called_unlock); CHECK_EQUAL(3U, queue.size_from_unlocked()); @@ -207,7 +218,7 @@ namespace access.clear(); CHECK(queue.pop_from_unlocked(i)); - CHECK_EQUAL(2, i); + CHECK_EQUAL(4, i); CHECK(!access.called_lock); CHECK(!access.called_unlock); CHECK_EQUAL(2U, queue.size_from_unlocked()); @@ -215,7 +226,7 @@ namespace access.clear(); CHECK(queue.pop_from_unlocked(i)); - CHECK_EQUAL(3, i); + CHECK_EQUAL(5, i); CHECK(!access.called_lock); CHECK(!access.called_unlock); CHECK_EQUAL(1U, queue.size_from_unlocked()); @@ -223,7 +234,7 @@ namespace access.clear(); CHECK(queue.pop_from_unlocked(i)); - CHECK_EQUAL(4, i); + CHECK_EQUAL(6, i); CHECK(!access.called_lock); CHECK(!access.called_unlock); CHECK_EQUAL(0U, queue.size_from_unlocked()); diff --git a/test/vs2019/etl.vcxproj b/test/vs2019/etl.vcxproj index e24ebbb2..3aa2fa84 100644 --- a/test/vs2019/etl.vcxproj +++ b/test/vs2019/etl.vcxproj @@ -1288,6 +1288,7 @@ + diff --git a/test/vs2019/etl.vcxproj.filters b/test/vs2019/etl.vcxproj.filters index a8a96076..cda71eb1 100644 --- a/test/vs2019/etl.vcxproj.filters +++ b/test/vs2019/etl.vcxproj.filters @@ -945,6 +945,9 @@ ETL\Patterns + + ETL\Containers +