Mercurial > hg > svcore
diff base/RingBuffer.h @ 835:1d439494604c
Memory barriers in ringbuffer
author | Chris Cannam |
---|---|
date | Mon, 16 Sep 2013 15:47:27 +0100 |
parents | 2ba202c5be8d |
children | 6a94bb528e9d |
line wrap: on
line diff
--- a/base/RingBuffer.h Tue Jul 30 18:15:30 2013 +0100 +++ b/base/RingBuffer.h Mon Sep 16 15:47:27 2013 +0100 @@ -24,7 +24,6 @@ #include <sys/types.h> #include "system/System.h" -#include "Scavenger.h" #include <cstring> // memcpy, memset &c @@ -67,11 +66,15 @@ size_t getSize() const; /** - * Resize the ring buffer. This also empties it. Actually swaps - * in a new, larger buffer; the old buffer is scavenged after a - * seemly delay. Should be called from the write thread. + * 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 + * inconsistent. If this buffer's data will not fit in the new + * size, the contents are undefined. */ - void resize(size_t newSize); + RingBuffer<T, N> *resized(size_t newSize) const; /** * Lock the ring buffer into physical memory. Returns true @@ -167,17 +170,12 @@ size_t m_size; size_t m_spare; - static Scavenger<ScavengerArrayWrapper<T> > m_scavenger; - private: RingBuffer(const RingBuffer &); // not provided RingBuffer &operator=(const RingBuffer &); // not provided }; template <typename T, int N> -Scavenger<ScavengerArrayWrapper<T> > RingBuffer<T, N>::m_scavenger; - -template <typename T, int N> RingBuffer<T, N>::RingBuffer(size_t n) : m_buffer(new T[n + 1]), m_mlocked(false), @@ -200,8 +198,6 @@ */ for (int i = 0; i < N; ++i) m_readers[i] = 0; - - m_scavenger.scavenge(); } template <typename T, int N> @@ -217,8 +213,6 @@ MUNLOCK((void *)m_buffer, m_size * sizeof(T)); } delete[] m_buffer; - - m_scavenger.scavenge(); } template <typename T, int N> @@ -233,30 +227,25 @@ } template <typename T, int N> -void -RingBuffer<T, N>::resize(size_t newSize) +RingBuffer<T, N> * +RingBuffer<T, N>::resized(size_t newSize) const { #ifdef DEBUG_RINGBUFFER - std::cerr << "RingBuffer<T," << N << ">[" << this << "]::resize(" << newSize << ")" << std::endl; + std::cerr << "RingBuffer<T," << N << ">[" << this << "]::resized(" << newSize << ")" << std::endl; #endif - m_scavenger.scavenge(); + RingBuffer<T, N> *newBuffer = new RingBuffer<T, N>(newSize); - if (m_mlocked) { - MUNLOCK((void *)m_buffer, m_size * sizeof(T)); + int w = m_writer; + int r = m_readers[0]; + + while (r != w) { + T value = m_buffer[r]; + newBuffer->write(&value, 1); + if (++r == m_size) r = 0; } - m_scavenger.claim(new ScavengerArrayWrapper<T>(m_buffer)); - - reset(); - m_buffer = new T[newSize + 1]; - m_size = newSize + 1; - - if (m_mlocked) { - if (MLOCK((void *)m_buffer, m_size * sizeof(T))) { - m_mlocked = false; - } - } + return newBuffer; } template <typename T, int N> @@ -350,6 +339,7 @@ memcpy(destination + here, m_buffer, (n - here) * sizeof(T)); } + MBARRIER(); m_readers[R] = (m_readers[R] + n) % m_size; #ifdef DEBUG_RINGBUFFER @@ -392,6 +382,7 @@ } } + MBARRIER(); m_readers[R] = (m_readers[R] + n) % m_size; return n; } @@ -414,6 +405,7 @@ return t; } T value = m_buffer[m_readers[R]]; + MBARRIER(); if (++m_readers[R] == m_size) m_readers[R] = 0; return value; } @@ -520,6 +512,7 @@ memcpy(m_buffer, source + here, (n - here) * sizeof(T)); } + MBARRIER(); m_writer = (m_writer + n) % m_size; #ifdef DEBUG_RINGBUFFER @@ -554,7 +547,8 @@ memset(m_buffer + m_writer, 0, here * sizeof(T)); memset(m_buffer, 0, (n - here) * sizeof(T)); } - + + MBARRIER(); m_writer = (m_writer + n) % m_size; return n; }