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 @interface VirtualRingBuffer : NSObject
{ {
void *buffer; void *buffer;
void *bufferEnd;
UInt32 bufferLength; UInt32 bufferLength;
// buffer is the start of the ring buffer's address space. // buffer is the start of the ring buffer's address space.
// bufferEnd is the end of the "real" buffer (always buffer + bufferLength). // 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); bufferLength = (UInt32) round_page(length);
buffer = allocateVirtualBuffer(bufferLength); buffer = allocateVirtualBuffer(bufferLength);
if (buffer) { if (!buffer)
bufferEnd = buffer + bufferLength; {
} else {
self = nil; self = nil;
return nil; return nil;
} }
@ -100,21 +99,14 @@ static void deallocateVirtualBuffer(void *buffer, UInt32 bufferLength);
UInt32 length; UInt32 length;
// Read this pointer exactly once, so we're safe in case it is changed in another thread // 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 localReadPointer = atomic_load_explicit(&readPointer, memory_order_relaxed);
int localBufferFilled = atomic_load_explicit(&bufferFilled, 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. // 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; *returnedReadPointer = buffer + localReadPointer;
return length; return length;
@ -144,25 +136,12 @@ static void deallocateVirtualBuffer(void *buffer, UInt32 bufferLength);
UInt32 length; UInt32 length;
// Read this pointer exactly once, so we're safe in case it is changed in another thread // 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 localWritePointer = atomic_load_explicit(&writePointer, memory_order_relaxed);
int localBufferFilled = atomic_load_explicit(&bufferFilled, 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. length = bufferLength - localBufferFilled;
if (!localReadPointer && !localWritePointer && !localBufferFilled) { if (length > bufferLength - localWritePointer)
// The buffer is empty. Set it up to be written into. length = bufferLength - localWritePointer;
// 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);
}
*returnedWritePointer = buffer + localWritePointer; *returnedWritePointer = buffer + localWritePointer;
return length; return length;