This patch does not change the ring_spsc template in any significant way
but merely makes the counter type (of _begin and _end) a parameter. This
allows us to use smaller type - unsigned short (2 bytes) - in the unit test
tst-ring-spsc-wraparound.cc to make it execute more rapidly.

Before this change this unit test would run for almost 3 minutes on
aarch64 and almost 10 seconds on x64. Now it executes way under a second
and still verifies the same edge condition (see
1ba76eb03cba4431b557183d1001b16991cd1fa4).

Signed-off-by: Waldemar Kozaczuk <[email protected]>
---
 include/lockfree/ring.hh                 | 22 +++++++++++-----------
 include/lockfree/unordered-queue-spsc.hh |  2 +-
 include/lockfree/unordered_ring_mpsc.hh  |  2 +-
 include/osv/net_channel.hh               |  2 +-
 include/osv/percpu_xmit.hh               |  2 +-
 tests/misc-free-perf.cc                  |  2 +-
 tests/misc-lfring.cc                     |  2 +-
 tests/tst-nway-merger.cc                 |  2 +-
 tests/tst-ring-spsc-wraparound.cc        |  4 ++--
 9 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/include/lockfree/ring.hh b/include/lockfree/ring.hh
index c9fefccc..434a14b7 100644
--- a/include/lockfree/ring.hh
+++ b/include/lockfree/ring.hh
@@ -20,7 +20,7 @@
 //
 // spsc ring of fixed size
 //
-template<class T, unsigned MaxSize, unsigned MaxSizeMask = MaxSize - 1>
+template<class T, typename COUNTER_TYPE, COUNTER_TYPE MaxSize, COUNTER_TYPE 
MaxSizeMask = MaxSize - 1>
 class ring_spsc {
 public:
     ring_spsc(): _begin(0), _end(0)
@@ -31,7 +31,7 @@ public:
     template<typename... Args>
     inline bool emplace(Args&&... args)
     {
-        unsigned end = _end.load(std::memory_order_relaxed);
+        COUNTER_TYPE end = _end.load(std::memory_order_relaxed);
 
         //
         // It's ok to load _begin with relaxed ordering (in the size()) since
@@ -56,7 +56,7 @@ public:
 
     bool pop(T& element)
     {
-        unsigned beg = _begin.load(std::memory_order_relaxed);
+        COUNTER_TYPE beg = _begin.load(std::memory_order_relaxed);
 
         if (empty()) {
             return false;
@@ -83,15 +83,15 @@ public:
      * @return TRUE if there are no elements
      */
     bool empty() const {
-        unsigned beg = _begin.load(std::memory_order_relaxed);
-        unsigned end = _end.load(std::memory_order_acquire);
+        COUNTER_TYPE beg = _begin.load(std::memory_order_relaxed);
+        COUNTER_TYPE end = _end.load(std::memory_order_acquire);
         return beg == end;
     }
 
     const T& front() const {
         DEBUG_ASSERT(!empty(), "calling front() on an empty queue!");
 
-        unsigned beg = _begin.load(std::memory_order_relaxed);
+        COUNTER_TYPE beg = _begin.load(std::memory_order_relaxed);
 
         return _ring[beg & MaxSizeMask];
     }
@@ -102,16 +102,16 @@ public:
      *
      * @return the current number of the elements.
      */
-    unsigned size() const {
-        unsigned end = _end.load(std::memory_order_relaxed);
-        unsigned beg = _begin.load(std::memory_order_relaxed);
+    COUNTER_TYPE size() const {
+        COUNTER_TYPE end = _end.load(std::memory_order_relaxed);
+        COUNTER_TYPE beg = _begin.load(std::memory_order_relaxed);
 
         return (end - beg);
     }
 
 private:
-    std::atomic<unsigned> _begin CACHELINE_ALIGNED;
-    std::atomic<unsigned> _end CACHELINE_ALIGNED;
+    std::atomic<COUNTER_TYPE> _begin CACHELINE_ALIGNED;
+    std::atomic<COUNTER_TYPE> _end CACHELINE_ALIGNED;
     T _ring[MaxSize];
 };
 
diff --git a/include/lockfree/unordered-queue-spsc.hh 
b/include/lockfree/unordered-queue-spsc.hh
index 72f77790..702da681 100644
--- a/include/lockfree/unordered-queue-spsc.hh
+++ b/include/lockfree/unordered-queue-spsc.hh
@@ -26,7 +26,7 @@ namespace lockfree {
 template <typename LT, unsigned RingSize>
 class unordered_queue_spsc {
 private:
-    ring_spsc<LT*,RingSize> _ring;
+    ring_spsc<LT*,unsigned,RingSize> _ring;
     unordered_queue_mpsc<LT> _queue;
 public:
 
diff --git a/include/lockfree/unordered_ring_mpsc.hh 
b/include/lockfree/unordered_ring_mpsc.hh
index 72599bae..6c6d1165 100644
--- a/include/lockfree/unordered_ring_mpsc.hh
+++ b/include/lockfree/unordered_ring_mpsc.hh
@@ -26,7 +26,7 @@ template<class T, unsigned MaxSizePerCpu>
 class unordered_ring_mpsc
 {
 private:
-    std::vector<ring_spsc<T,MaxSizePerCpu>> rings;
+    std::vector<ring_spsc<T,unsigned,MaxSizePerCpu>> rings;
 public:
     using ring_mpsc_t = unordered_ring_mpsc<T,MaxSizePerCpu>;
 
diff --git a/include/osv/net_channel.hh b/include/osv/net_channel.hh
index 2784e9e7..11cc09cb 100644
--- a/include/osv/net_channel.hh
+++ b/include/osv/net_channel.hh
@@ -33,7 +33,7 @@ extern void* memory::alloc_page();
 class net_channel {
 private:
     std::function<void (mbuf*)> _process_packet;
-    ring_spsc<mbuf*, 256> _queue;
+    ring_spsc<mbuf*, unsigned, 256> _queue;
     sched::thread_handle _waiting_thread CACHELINE_ALIGNED;
     // extra list of threads to wake
     osv::rcu_ptr<std::vector<pollreq*>> _pollers;
diff --git a/include/osv/percpu_xmit.hh b/include/osv/percpu_xmit.hh
index 7ec6f1be..4b44bf6a 100644
--- a/include/osv/percpu_xmit.hh
+++ b/include/osv/percpu_xmit.hh
@@ -151,7 +151,7 @@ public:
 
 private:
     lockfree::queue_mpsc<wait_record> _waitq;
-    ring_spsc<value_type, CpuTxqSize> _r;
+    ring_spsc<value_type, unsigned, CpuTxqSize> _r;
 
     //
     // We don't want to wake the waiters when the Tx worker is going to sleep.
diff --git a/tests/misc-free-perf.cc b/tests/misc-free-perf.cc
index b9dc24b2..c7478adf 100644
--- a/tests/misc-free-perf.cc
+++ b/tests/misc-free-perf.cc
@@ -21,7 +21,7 @@ struct linked_object {
 };
 
 using _clock = std::chrono::high_resolution_clock;
-using queue_t = ring_spsc<void*,64*1024*1024>;
+using queue_t = ring_spsc<void*,unsigned,64*1024*1024>;
 
 // Manages threads, allocates each thread on a different CPU
 class thread_allocator
diff --git a/tests/misc-lfring.cc b/tests/misc-lfring.cc
index 83e3de84..ade201f1 100644
--- a/tests/misc-lfring.cc
+++ b/tests/misc-lfring.cc
@@ -64,7 +64,7 @@ public:
 
 private:
 
-    ring_spsc<int, 4096> _ring;
+    ring_spsc<int,unsigned,4096> _ring;
 
     int _stats[2][max_random] = {};
 
diff --git a/tests/tst-nway-merger.cc b/tests/tst-nway-merger.cc
index 5f37a16a..83a0cc7d 100644
--- a/tests/tst-nway-merger.cc
+++ b/tests/tst-nway-merger.cc
@@ -69,7 +69,7 @@ public:
     bool empty() const { return _r.empty(); }
 
 private:
-    ring_spsc<T, MaxSize> _r;
+    ring_spsc<T,unsigned,MaxSize> _r;
 };
 
 typedef my_spsc_ring<my_struct, 8> my_spsc_queue;
diff --git a/tests/tst-ring-spsc-wraparound.cc 
b/tests/tst-ring-spsc-wraparound.cc
index 2490755d..64953aed 100644
--- a/tests/tst-ring-spsc-wraparound.cc
+++ b/tests/tst-ring-spsc-wraparound.cc
@@ -17,8 +17,8 @@ using namespace std;
 
 int main(int argc, char *argv[])
 {
-    ring_spsc<int, 256> test_ring;
-    unsigned count;
+    ring_spsc<int, unsigned short, 256> test_ring;
+    unsigned short count;
     int val;
 
     for (count = 1; count != 0; count++) {
-- 
2.27.0

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/osv-dev/20220503203505.41452-1-jwkozaczuk%40gmail.com.

Reply via email to