Cog Audio: Improve ring buffer

CQTexperiment
Christopher Snowhill 2022-01-14 10:17:08 -08:00
parent 3ce3edde88
commit cb3782d0b1
2 changed files with 10 additions and 32 deletions

View File

@ -49,7 +49,6 @@
@interface VirtualRingBuffer : NSObject
{
void *buffer;
void *bufferEnd;
UInt32 bufferLength;
// buffer is the start of the ring buffer's address space.
// bufferEnd is the end of the "real" buffer (always buffer + bufferLength).

View File

@ -37,9 +37,8 @@ static void deallocateVirtualBuffer(void *buffer, UInt32 bufferLength);
bufferLength = (UInt32) round_page(length);
buffer = allocateVirtualBuffer(bufferLength);
if (buffer) {
bufferEnd = buffer + bufferLength;
} else {
if (!buffer)
{
self = nil;
return nil;
}
@ -100,21 +99,14 @@ static void deallocateVirtualBuffer(void *buffer, UInt32 bufferLength);
UInt32 length;
// Read this pointer exactly once, so we're safe in case it is changed in another thread
int localWritePointer = atomic_load_explicit(&writePointer, memory_order_relaxed);
int localReadPointer = atomic_load_explicit(&readPointer, memory_order_relaxed);
int localBufferFilled = atomic_load_explicit(&bufferFilled, memory_order_relaxed);
length = bufferLength - localReadPointer;
if (length > localBufferFilled)
length = localBufferFilled;
// Depending on out-of-order execution and memory storage, either one of these may be NULL when the buffer is empty. So we must check both.
if (localReadPointer == localWritePointer && !localBufferFilled) {
// The buffer is empty
length = 0;
} else if (localWritePointer > localReadPointer) {
// Write is ahead of read in the buffer
length = (UInt32)(localWritePointer - localReadPointer);
} else {
// Write has wrapped around past read, OR write == read (the buffer is full)
length = (UInt32)(bufferLength - localReadPointer);
}
*returnedReadPointer = buffer + localReadPointer;
return length;
@ -144,25 +136,12 @@ static void deallocateVirtualBuffer(void *buffer, UInt32 bufferLength);
UInt32 length;
// Read this pointer exactly once, so we're safe in case it is changed in another thread
int localReadPointer = atomic_load_explicit(&readPointer, memory_order_relaxed);
int localWritePointer = atomic_load_explicit(&writePointer, memory_order_relaxed);
int localBufferFilled = atomic_load_explicit(&bufferFilled, memory_order_relaxed);
// Either one of these may be NULL when the buffer is empty. So we must check both.
if (!localReadPointer && !localWritePointer && !localBufferFilled) {
// The buffer is empty. Set it up to be written into.
// This is one of the two places the write pointer can change; both are in the write thread.
length = bufferLength;
} else if (localWritePointer <= localReadPointer) {
// Write is before read in the buffer, OR write == read (meaning that the buffer is full).
length = (UInt32)(localReadPointer - localWritePointer);
if (!length && !localBufferFilled) {
length = (UInt32)(bufferLength - localWritePointer);
}
} else {
// Write is behind read in the buffer. The available space wraps around.
length = (UInt32)(bufferLength - localWritePointer);
}
length = bufferLength - localBufferFilled;
if (length > bufferLength - localWritePointer)
length = bufferLength - localWritePointer;
*returnedWritePointer = buffer + localWritePointer;
return length;