changeset 1827:6e218407f0cf audio-source-refactor

Make RingBuffer copyable, and simplify a bit
author Chris Cannam
date Thu, 19 Mar 2020 16:09:04 +0000
parents a4dce53b3353
children 618326c4ce4b
files base/RingBuffer.h
diffstat 1 files changed, 40 insertions(+), 84 deletions(-) [+]
line wrap: on
line diff
--- a/base/RingBuffer.h	Fri Mar 06 12:53:18 2020 +0000
+++ b/base/RingBuffer.h	Thu Mar 19 16:09:04 2020 +0000
@@ -26,8 +26,9 @@
 #include "system/System.h"
 
 #include <bqvec/Barrier.h>
+#include <bqvec/VectorOps.h>
 
-#include <cstring> // memcpy, memset &c
+#include <vector>
 
 //#define DEBUG_RINGBUFFER 1
 
@@ -38,10 +39,6 @@
 /**
  * RingBuffer implements a lock-free ring buffer for one writer and N
  * readers, that is to be used to store a sample type T.
- *
- * For efficiency, RingBuffer frequently initialises samples by
- * writing zeroes into their memory space, so T should normally be a
- * simple type that can safely be set to zero using memset.
  */
 
 template <typename T, int N = 1>
@@ -68,21 +65,14 @@
     int getSize() const;
 
     /**
-     * Return a new ring buffer (allocated with "new" -- caller must
-     * delete when no longer needed) of the given size, containing the
-     * same data as this one as perceived by reader 0 of this buffer.
-     * If another thread reads from or writes to this buffer during
-     * the call, the contents of the new buffer may be incomplete or
+     * Return a new ring buffer of the given size, containing the same
+     * data as this one as perceived by reader 0 of this buffer.  If
+     * another thread reads from or writes to this buffer during the
+     * call, the contents of the new buffer may be incomplete or
      * inconsistent.  If this buffer's data will not fit in the new
-     * size, the contents are undefined.
+     * size, the contents are undetermined.
      */
-    RingBuffer<T, N> *resized(int newSize) const;
-
-    /**
-     * Lock the ring buffer into physical memory.  Returns true
-     * for success.
-     */
-    bool mlock();
+    RingBuffer<T, N> resized(int newSize) const;
 
     /**
      * Reset read and write pointers, thus emptying the buffer.
@@ -164,42 +154,26 @@
      */
     int zero(int n);
 
+    RingBuffer(const RingBuffer &) =default;
+    RingBuffer &operator=(const RingBuffer &) =default;
+    
 protected:
-    T   *m_buffer;
-    bool m_mlocked;
-    int  m_writer;
-    int *m_readers;
-    int  m_size;
-    int  m_spare;
-
-private:
-    RingBuffer(const RingBuffer &); // not provided
-    RingBuffer &operator=(const RingBuffer &); // not provided
+    std::vector<T> m_buffer;
+    int m_writer;
+    std::vector<int> m_readers;
+    int m_size;
 };
 
 template <typename T, int N>
 RingBuffer<T, N>::RingBuffer(int n) :
-    m_buffer(new T[n + 1]),
-    m_mlocked(false),
+    m_buffer(n + 1, T()),
     m_writer(0),
-    m_readers(new int[N]),
+    m_readers(N, 0),
     m_size(n + 1)
 {
 #ifdef DEBUG_RINGBUFFER
     std::cerr << "RingBuffer<T," << N << ">[" << this << "]::RingBuffer(" << n << ")" << std::endl;
 #endif
-/*
-    std::cerr << "note: sizeof(RingBuffer<T,N> = " << sizeof(RingBuffer<T,N>) << ")" << std::endl;
-
-    std::cerr << "this = " << this << std::endl;
-    std::cerr << "&m_buffer = " << &m_buffer << std::endl;
-    std::cerr << "&m_mlocked = " << &m_mlocked << std::endl;
-    std::cerr << "&m_writer = " << &m_writer << std::endl;
-    std::cerr << "&m_readers = " << &m_readers << std::endl;
-    std::cerr << "&m_size = " << &m_size << std::endl;
-*/
-    
-    for (int i = 0; i < N; ++i) m_readers[i] = 0;
 }
 
 template <typename T, int N>
@@ -208,13 +182,6 @@
 #ifdef DEBUG_RINGBUFFER
     std::cerr << "RingBuffer<T," << N << ">[" << this << "]::~RingBuffer" << std::endl;
 #endif
-
-    delete[] m_readers;
-
-    if (m_mlocked) {
-        MUNLOCK((void *)m_buffer, m_size * sizeof(T));
-    }
-    delete[] m_buffer;
 }
 
 template <typename T, int N>
@@ -229,14 +196,14 @@
 }
 
 template <typename T, int N>
-RingBuffer<T, N> *
+RingBuffer<T, N>
 RingBuffer<T, N>::resized(int newSize) const
 {
 #ifdef DEBUG_RINGBUFFER
     std::cerr << "RingBuffer<T," << N << ">[" << this << "]::resized(" << newSize << ")" << std::endl;
 #endif
 
-    RingBuffer<T, N> *newBuffer = new RingBuffer<T, N>(newSize);
+    RingBuffer<T, N> newBuffer(newSize);
 
     int w = m_writer;
     int r = m_readers[0];
@@ -251,15 +218,6 @@
 }
 
 template <typename T, int N>
-bool
-RingBuffer<T, N>::mlock()
-{
-    if (MLOCK((void *)m_buffer, m_size * sizeof(T))) return false;
-    m_mlocked = true;
-    return true;
-}
-
-template <typename T, int N>
 void
 RingBuffer<T, N>::reset()
 {
@@ -268,7 +226,9 @@
 #endif
 
     m_writer = 0;
-    for (int i = 0; i < N; ++i) m_readers[i] = 0;
+    for (int i = 0; i < N; ++i) {
+        m_readers[i] = 0;
+    }
 }
 
 template <typename T, int N>
@@ -328,17 +288,17 @@
         std::cerr << "WARNING: Only " << available << " samples available"
                   << std::endl;
 #endif
-        memset(destination + available, 0, (n - available) * sizeof(T));
+        breakfastquay::v_zero(destination + available, n - available);
         n = available;
     }
     if (n == 0) return n;
 
     int here = m_size - m_readers[R];
     if (here >= n) {
-        memcpy(destination, m_buffer + m_readers[R], n * sizeof(T));
+        breakfastquay::v_copy(destination, m_buffer.data() + m_readers[R], n);
     } else {
-        memcpy(destination, m_buffer + m_readers[R], here * sizeof(T));
-        memcpy(destination + here, m_buffer, (n - here) * sizeof(T));
+        breakfastquay::v_copy(destination, m_buffer.data() + m_readers[R], here);
+        breakfastquay::v_copy(destination + here, m_buffer.data(), n - here);
     }
 
     BQ_MBARRIER();
@@ -373,11 +333,11 @@
 
     if (here >= n) {
         for (int i = 0; i < n; ++i) {
-            destination[i] += (m_buffer + m_readers[R])[i];
+            destination[i] += (m_buffer.data() + m_readers[R])[i];
         }
     } else {
         for (int i = 0; i < here; ++i) {
-            destination[i] += (m_buffer + m_readers[R])[i];
+            destination[i] += (m_buffer.data() + m_readers[R])[i];
         }
         for (int i = 0; i < (n - here); ++i) {
             destination[i + here] += m_buffer[i];
@@ -402,9 +362,7 @@
         std::cerr << "WARNING: No sample available"
                   << std::endl;
 #endif
-        T t;
-        memset(&t, 0, sizeof(T));
-        return t;
+        return T();
     }
     T value = m_buffer[m_readers[R]];
     BQ_MBARRIER();
@@ -426,17 +384,17 @@
         std::cerr << "WARNING: Only " << available << " samples available"
                   << std::endl;
 #endif
-        memset(destination + available, 0, (n - available) * sizeof(T));
+        breakfastquay::v_zero(destination + available, n - available);
         n = available;
     }
     if (n == 0) return n;
 
     int here = m_size - m_readers[R];
     if (here >= n) {
-        memcpy(destination, m_buffer + m_readers[R], n * sizeof(T));
+        breakfastquay::v_copy(destination, m_buffer.data() + m_readers[R], n);
     } else {
-        memcpy(destination, m_buffer + m_readers[R], here * sizeof(T));
-        memcpy(destination + here, m_buffer, (n - here) * sizeof(T));
+        breakfastquay::v_copy(destination, m_buffer.data() + m_readers[R], here);
+        breakfastquay::v_copy(destination + here, m_buffer.data(), n - here);
     }
 
 #ifdef DEBUG_RINGBUFFER
@@ -459,9 +417,7 @@
         std::cerr << "WARNING: No sample available"
                   << std::endl;
 #endif
-        T t;
-        memset(&t, 0, sizeof(T));
-        return t;
+        return T();
     }
     T value = m_buffer[m_readers[R]];
     return value;
@@ -508,10 +464,10 @@
 
     int here = m_size - m_writer;
     if (here >= n) {
-        memcpy(m_buffer + m_writer, source, n * sizeof(T));
+        breakfastquay::v_copy(m_buffer.data() + m_writer, source, n);
     } else {
-        memcpy(m_buffer + m_writer, source, here * sizeof(T));
-        memcpy(m_buffer, source + here, (n - here) * sizeof(T));
+        breakfastquay::v_copy(m_buffer.data() + m_writer, source, here);
+        breakfastquay::v_copy(m_buffer.data(), source + here, n - here);
     }
 
     BQ_MBARRIER();
@@ -544,10 +500,10 @@
 
     int here = m_size - m_writer;
     if (here >= n) {
-        memset(m_buffer + m_writer, 0, n * sizeof(T));
+        breakfastquay::v_zero(m_buffer.data() + m_writer, n);
     } else {
-        memset(m_buffer + m_writer, 0, here * sizeof(T));
-        memset(m_buffer, 0, (n - here) * sizeof(T));
+        breakfastquay::v_zero(m_buffer.data() + m_writer, here);
+        breakfastquay::v_zero(m_buffer.data(), n - here);
     }
     
     BQ_MBARRIER();