aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2019-01-03 15:54:18 -0800
committerChris Robinson <[email protected]>2019-01-03 15:54:18 -0800
commit21a17620e37dce28295cbc43b692d7fe910efd67 (patch)
tree871494a574020ae6f638f1d7d018a83381646267
parent88c2f11dcf697c4bac43249e1e98b34637988dbc (diff)
Fix the ringbuffer write limit
Previously it just limited the returned write space, irrespective of how much had already been written. The buffer could still be filled up by doing multiple writes. Now the size is limited by adjusting the read pointer by the real vs limited difference when calculating the writable space.
-rw-r--r--Alc/ringbuffer.cpp35
-rw-r--r--Alc/ringbuffer.h2
2 files changed, 15 insertions, 22 deletions
diff --git a/Alc/ringbuffer.cpp b/Alc/ringbuffer.cpp
index 791fff63..21884f6c 100644
--- a/Alc/ringbuffer.cpp
+++ b/Alc/ringbuffer.cpp
@@ -52,7 +52,7 @@ RingBufferPtr CreateRingBuffer(size_t sz, size_t elem_sz, int limit_writes)
if(power_of_two < sz) return nullptr;
RingBufferPtr rb{new (al_malloc(16, sizeof(*rb) + power_of_two*elem_sz)) RingBuffer{}};
- rb->mSize = limit_writes ? sz : power_of_two;
+ rb->mWriteSize = limit_writes ? sz : (power_of_two-1);
rb->mSizeMask = power_of_two - 1;
rb->mElemSize = elem_sz;
@@ -77,9 +77,8 @@ size_t RingBuffer::readSpace() const noexcept
size_t RingBuffer::writeSpace() const noexcept
{
size_t w = mWritePtr.load(std::memory_order_acquire);
- size_t r = mReadPtr.load(std::memory_order_acquire);
- w = (r-w-1) & mSizeMask;
- return std::max(w, mSize);
+ size_t r = mReadPtr.load(std::memory_order_acquire) + mWriteSize - mSizeMask;
+ return (r-w-1) & mSizeMask;
}
@@ -104,12 +103,11 @@ size_t RingBuffer::read(void *dest, size_t cnt) noexcept
n2 = 0;
}
- memcpy(dest, &mBuffer[read_ptr*mElemSize], n1*mElemSize);
+ memcpy(dest, mBuffer + read_ptr*mElemSize, n1*mElemSize);
read_ptr += n1;
- if(n2)
+ if(n2 > 0)
{
- memcpy(static_cast<char*>(dest) + n1*mElemSize, &mBuffer[(read_ptr&mSizeMask)*mElemSize],
- n2*mElemSize);
+ memcpy(static_cast<char*>(dest) + n1*mElemSize, mBuffer, n2*mElemSize);
read_ptr += n2;
}
mReadPtr.store(read_ptr, std::memory_order_release);
@@ -137,13 +135,9 @@ size_t RingBuffer::peek(void *dest, size_t cnt) const noexcept
n2 = 0;
}
- memcpy(dest, &mBuffer[read_ptr*mElemSize], n1*mElemSize);
- if(n2)
- {
- read_ptr += n1;
- memcpy(static_cast<char*>(dest) + n1*mElemSize, &mBuffer[(read_ptr&mSizeMask)*mElemSize],
- n2*mElemSize);
- }
+ memcpy(dest, mBuffer + read_ptr*mElemSize, n1*mElemSize);
+ if(n2 > 0)
+ memcpy(static_cast<char*>(dest) + n1*mElemSize, mBuffer, n2*mElemSize);
return to_read;
}
@@ -168,12 +162,11 @@ size_t RingBuffer::write(const void *src, size_t cnt) noexcept
n2 = 0;
}
- memcpy(&mBuffer[write_ptr*mElemSize], src, n1*mElemSize);
+ memcpy(mBuffer + write_ptr*mElemSize, src, n1*mElemSize);
write_ptr += n1;
- if(n2)
+ if(n2 > 0)
{
- memcpy(&mBuffer[(write_ptr&mSizeMask)*mElemSize],
- static_cast<const char*>(src) + n1*mElemSize, n2*mElemSize);
+ memcpy(mBuffer, static_cast<const char*>(src) + n1*mElemSize, n2*mElemSize);
write_ptr += n2;
}
mWritePtr.store(write_ptr, std::memory_order_release);
@@ -229,10 +222,10 @@ ll_ringbuffer_data_pair RingBuffer::getWriteVector() const noexcept
ll_ringbuffer_data_pair ret;
size_t w{mWritePtr.load(std::memory_order_acquire)};
- size_t r{mReadPtr.load(std::memory_order_acquire)};
+ size_t r{mReadPtr.load(std::memory_order_acquire) + mWriteSize - mSizeMask};
w &= mSizeMask;
r &= mSizeMask;
- const size_t free_cnt{std::min((r-w-1) & mSizeMask, mSize)};
+ const size_t free_cnt{(r-w-1) & mSizeMask};
const size_t cnt2{w + free_cnt};
if(cnt2 > mSizeMask+1)
diff --git a/Alc/ringbuffer.h b/Alc/ringbuffer.h
index 317995b0..311477c9 100644
--- a/Alc/ringbuffer.h
+++ b/Alc/ringbuffer.h
@@ -26,7 +26,7 @@ using ll_ringbuffer_data_pair = std::pair<ll_ringbuffer_data,ll_ringbuffer_data>
struct RingBuffer {
std::atomic<size_t> mWritePtr{0u};
std::atomic<size_t> mReadPtr{0u};
- size_t mSize{0u};
+ size_t mWriteSize{0u};
size_t mSizeMask{0u};
size_t mElemSize{0u};