diff options
author | Chris Robinson <[email protected]> | 2018-12-26 21:22:17 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2018-12-26 21:22:17 -0800 |
commit | 8a0295503db394ea895bfa079d1f3eda0d758e61 (patch) | |
tree | 21a1a1e63fe148dc087ad2c35ce94a49418ef900 /Alc | |
parent | 4f253a935a14e49a77516a56e0d4c6d6177a56b6 (diff) |
Clean up the ring buffer struct and use member functions
Diffstat (limited to 'Alc')
-rw-r--r-- | Alc/alc.cpp | 2 | ||||
-rw-r--r-- | Alc/alcontext.h | 4 | ||||
-rw-r--r-- | Alc/alu.cpp | 16 | ||||
-rw-r--r-- | Alc/backends/alsa.cpp | 13 | ||||
-rw-r--r-- | Alc/backends/coreaudio.cpp | 13 | ||||
-rw-r--r-- | Alc/backends/dsound.cpp | 16 | ||||
-rw-r--r-- | Alc/backends/jack.cpp | 17 | ||||
-rw-r--r-- | Alc/backends/opensl.cpp | 54 | ||||
-rw-r--r-- | Alc/backends/oss.cpp | 13 | ||||
-rw-r--r-- | Alc/backends/portaudio.cpp | 11 | ||||
-rw-r--r-- | Alc/backends/sndio.cpp | 16 | ||||
-rw-r--r-- | Alc/backends/wasapi.cpp | 13 | ||||
-rw-r--r-- | Alc/backends/winmm.cpp | 13 | ||||
-rw-r--r-- | Alc/mixvoice.cpp | 5 | ||||
-rw-r--r-- | Alc/ringbuffer.cpp | 203 | ||||
-rw-r--r-- | Alc/ringbuffer.h | 122 |
16 files changed, 272 insertions, 259 deletions
diff --git a/Alc/alc.cpp b/Alc/alc.cpp index d13cfc54..294ba394 100644 --- a/Alc/alc.cpp +++ b/Alc/alc.cpp @@ -2466,7 +2466,7 @@ ALCcontext_struct::~ALCcontext_struct() TRACE("Freed " SZFMT " listener property object%s\n", count, (count==1)?"":"s"); count = 0; - auto evt_vec = ll_ringbuffer_get_read_vector(AsyncEvents); + auto evt_vec = AsyncEvents->getReadVector(); while(evt_vec.first.len > 0) { reinterpret_cast<AsyncEvent*>(evt_vec.first.buf)->~AsyncEvent(); diff --git a/Alc/alcontext.h b/Alc/alcontext.h index 7b7688ac..dadb4f8f 100644 --- a/Alc/alcontext.h +++ b/Alc/alcontext.h @@ -27,7 +27,7 @@ struct ALvoiceProps; struct ALeffectslotProps; struct ALvoice; struct ALeffectslotArray; -struct ll_ringbuffer; +struct RingBuffer; enum class DistanceModel { InverseClamped = AL_INVERSE_DISTANCE_CLAMPED, @@ -112,7 +112,7 @@ struct ALCcontext_struct { std::thread EventThread; al::semaphore EventSem; - ll_ringbuffer *AsyncEvents{nullptr}; + RingBuffer *AsyncEvents{nullptr}; std::atomic<ALbitfieldSOFT> EnabledEvts{0u}; std::mutex EventCbLock; ALEVENTPROCSOFT EventCb{}; diff --git a/Alc/alu.cpp b/Alc/alu.cpp index 6655bd81..1ebf3adc 100644 --- a/Alc/alu.cpp +++ b/Alc/alu.cpp @@ -289,13 +289,15 @@ void SendSourceStoppedEvent(ALCcontext *context, ALuint id) ALbitfieldSOFT enabledevt{context->EnabledEvts.load(std::memory_order_acquire)}; if(!(enabledevt&EventType_SourceStateChange)) return; - auto evt_data = ll_ringbuffer_get_write_vector(context->AsyncEvents).first; + RingBuffer *ring{context->AsyncEvents}; + auto evt_data = ring->getWriteVector().first; if(evt_data.len < 1) return; AsyncEvent *evt{new (evt_data.buf) AsyncEvent{EventType_SourceStateChange}}; evt->u.srcstate.id = id; evt->u.srcstate.state = AL_STOPPED; - ll_ringbuffer_write_advance(context->AsyncEvents, 1); + + ring->writeAdvance(1); context->EventSem.post(); } @@ -414,12 +416,13 @@ bool CalcEffectSlotParams(ALeffectslot *slot, ALCcontext *context, bool force) /* Otherwise, if it would be deleted, send it off with a release * event. */ - auto evt_vec = ll_ringbuffer_get_write_vector(context->AsyncEvents); + RingBuffer *ring{context->AsyncEvents}; + auto evt_vec = ring->getWriteVector(); if(LIKELY(evt_vec.first.len > 0)) { AsyncEvent *evt{new (evt_vec.first.buf) AsyncEvent{EventType_ReleaseEffectState}}; evt->u.mEffectState = oldstate; - ll_ringbuffer_write_advance(context->AsyncEvents, 1); + ring->writeAdvance(1); context->EventSem.post(); } else @@ -1837,11 +1840,12 @@ void aluHandleDisconnect(ALCdevice *device, const char *msg, ...) const ALbitfieldSOFT enabledevt{ctx->EnabledEvts.load(std::memory_order_acquire)}; if((enabledevt&EventType_Disconnected)) { - auto evt_data = ll_ringbuffer_get_write_vector(ctx->AsyncEvents).first; + RingBuffer *ring{ctx->AsyncEvents}; + auto evt_data = ring->getWriteVector().first; if(evt_data.len > 0) { new (evt_data.buf) AsyncEvent{evt}; - ll_ringbuffer_write_advance(ctx->AsyncEvents, 1); + ring->writeAdvance(1); ctx->EventSem.post(); } } diff --git a/Alc/backends/alsa.cpp b/Alc/backends/alsa.cpp index cf3f7fff..fd6981f8 100644 --- a/Alc/backends/alsa.cpp +++ b/Alc/backends/alsa.cpp @@ -1136,9 +1136,9 @@ ALCenum ALCcaptureAlsa_captureSamples(ALCcaptureAlsa *self, ALCvoid *buffer, ALC { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - if(self->Ring) + if(RingBuffer *ring{self->Ring.get()}) { - ll_ringbuffer_read(self->Ring.get(), static_cast<char*>(buffer), samples); + ring->read(static_cast<char*>(buffer), samples); return ALC_NO_ERROR; } @@ -1221,7 +1221,8 @@ ALCuint ALCcaptureAlsa_availableSamples(ALCcaptureAlsa *self) } } - if(!self->Ring) + RingBuffer *ring{self->Ring.get()}; + if(!ring) { if(avail < 0) avail = 0; avail += snd_pcm_bytes_to_frames(self->PcmHandle, self->Buffer.size()); @@ -1231,7 +1232,7 @@ ALCuint ALCcaptureAlsa_availableSamples(ALCcaptureAlsa *self) while(avail > 0) { - auto vec = ll_ringbuffer_get_write_vector(self->Ring.get()); + auto vec = ring->getWriteVector(); if(vec.first.len == 0) break; snd_pcm_sframes_t amt{std::min<snd_pcm_sframes_t>(vec.first.len, avail)}; @@ -1259,11 +1260,11 @@ ALCuint ALCcaptureAlsa_availableSamples(ALCcaptureAlsa *self) continue; } - ll_ringbuffer_write_advance(self->Ring.get(), amt); + ring->writeAdvance(amt); avail -= amt; } - return ll_ringbuffer_read_space(self->Ring.get()); + return ring->readSpace(); } ClockLatency ALCcaptureAlsa_getClockLatency(ALCcaptureAlsa *self) diff --git a/Alc/backends/coreaudio.cpp b/Alc/backends/coreaudio.cpp index c73a67f9..808e7cb8 100644 --- a/Alc/backends/coreaudio.cpp +++ b/Alc/backends/coreaudio.cpp @@ -404,7 +404,8 @@ static OSStatus ALCcoreAudioCapture_RecordProc(void *inRefCon, const AudioTimeStamp *inTimeStamp, UInt32 UNUSED(inBusNumber), UInt32 inNumberFrames, AudioBufferList* UNUSED(ioData)) { - ALCcoreAudioCapture *self = static_cast<ALCcoreAudioCapture*>(inRefCon); + auto self = static_cast<ALCcoreAudioCapture*>(inRefCon); + RingBuffer *ring{self->Ring.get()}; AudioUnitRenderActionFlags flags = 0; OSStatus err; @@ -416,7 +417,7 @@ static OSStatus ALCcoreAudioCapture_RecordProc(void *inRefCon, return err; } - ll_ringbuffer_write(self->Ring.get(), self->BufferList->mBuffers[0].mData, inNumberFrames); + ring->write(self->BufferList->mBuffers[0].mData, inNumberFrames); return noErr; } @@ -425,10 +426,11 @@ static OSStatus ALCcoreAudioCapture_ConvertCallback(AudioConverterRef UNUSED(inA AudioStreamPacketDescription** UNUSED(outDataPacketDescription), void *inUserData) { - ALCcoreAudioCapture *self = reinterpret_cast<ALCcoreAudioCapture*>(inUserData); + auto self = reinterpret_cast<ALCcoreAudioCapture*>(inUserData); + RingBuffer *ring{self->Ring.get()}; // Read from the ring buffer and store temporarily in a large buffer - ll_ringbuffer_read(self->Ring.get(), self->ResampleBuffer, *ioNumberDataPackets); + ring->read(self->ResampleBuffer, *ioNumberDataPackets); // Set the input data ioData->mNumberBuffers = 1; @@ -739,7 +741,8 @@ static ALCenum ALCcoreAudioCapture_captureSamples(ALCcoreAudioCapture *self, ALC static ALCuint ALCcoreAudioCapture_availableSamples(ALCcoreAudioCapture *self) { - return ll_ringbuffer_read_space(self->Ring.get()) / self->SampleRateRatio; + RingBuffer *ring{self->Ring.get()}; + return ring->readSpace() / self->SampleRateRatio; } diff --git a/Alc/backends/dsound.cpp b/Alc/backends/dsound.cpp index 4ada7419..516a7770 100644 --- a/Alc/backends/dsound.cpp +++ b/Alc/backends/dsound.cpp @@ -889,16 +889,18 @@ void ALCdsoundCapture_stop(ALCdsoundCapture *self) ALCenum ALCdsoundCapture_captureSamples(ALCdsoundCapture *self, ALCvoid *buffer, ALCuint samples) { - ll_ringbuffer_read(self->Ring.get(), buffer, samples); + RingBuffer *ring{self->Ring.get()}; + ring->read(buffer, samples); return ALC_NO_ERROR; } ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self) { - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + ALCdevice *device{self->mDevice}; + RingBuffer *ring{self->Ring.get()}; if(!device->Connected.load(std::memory_order_acquire)) - return static_cast<ALCuint>(ll_ringbuffer_read_space(self->Ring.get())); + return static_cast<ALCuint>(ring->readSpace()); ALsizei FrameSize{device->frameSizeFromFmt()}; DWORD BufferBytes{self->BufferBytes}; @@ -911,15 +913,15 @@ ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self) if(SUCCEEDED(hr)) { DWORD NumBytes{(ReadCursor-LastCursor + BufferBytes) % BufferBytes}; - if(!NumBytes) return static_cast<ALCubyte>(ll_ringbuffer_read_space(self->Ring.get())); + if(!NumBytes) return static_cast<ALCubyte>(ring->readSpace()); hr = self->DSCbuffer->Lock(LastCursor, NumBytes, &ReadPtr1, &ReadCnt1, &ReadPtr2, &ReadCnt2, 0); } if(SUCCEEDED(hr)) { - ll_ringbuffer_write(self->Ring.get(), ReadPtr1, ReadCnt1/FrameSize); + ring->write(ReadPtr1, ReadCnt1/FrameSize); if(ReadPtr2 != nullptr) - ll_ringbuffer_write(self->Ring.get(), ReadPtr2, ReadCnt2/FrameSize); + ring->write(ReadPtr2, ReadCnt2/FrameSize); hr = self->DSCbuffer->Unlock(ReadPtr1, ReadCnt1, ReadPtr2, ReadCnt2); self->Cursor = (LastCursor+ReadCnt1+ReadCnt2) % BufferBytes; } @@ -930,7 +932,7 @@ ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self) aluHandleDisconnect(device, "Failure retrieving capture data: 0x%lx", hr); } - return static_cast<ALCuint>(ll_ringbuffer_read_space(self->Ring.get())); + return static_cast<ALCuint>(ring->readSpace()); } } // namespace diff --git a/Alc/backends/jack.cpp b/Alc/backends/jack.cpp index c768983d..02e29973 100644 --- a/Alc/backends/jack.cpp +++ b/Alc/backends/jack.cpp @@ -245,7 +245,8 @@ int ALCjackPlayback_process(jack_nframes_t numframes, void *arg) out[numchans++] = static_cast<float*>(jack_port_get_buffer(port, numframes)); } - auto data = ll_ringbuffer_get_read_vector(self->mRing.get()); + RingBuffer *ring{self->mRing.get()}; + auto data = ring->getReadVector(); jack_nframes_t todo{minu(numframes, data.first.len)}; std::transform(out, out+numchans, out, [&data,numchans,todo](ALfloat *outbuf) -> ALfloat* @@ -287,7 +288,7 @@ int ALCjackPlayback_process(jack_nframes_t numframes, void *arg) total += todo; } - ll_ringbuffer_read_advance(self->mRing.get(), total); + ring->readAdvance(total); self->mSem.post(); if(numframes > total) @@ -307,7 +308,8 @@ int ALCjackPlayback_process(jack_nframes_t numframes, void *arg) int ALCjackPlayback_mixerProc(ALCjackPlayback *self) { - ALCdevice *device{STATIC_CAST(ALCbackend,self)->mDevice}; + ALCdevice *device{self->mDevice}; + RingBuffer *ring{self->mRing.get()}; SetRTPriority(); althrd_setname(MIXER_THREAD_NAME); @@ -316,7 +318,7 @@ int ALCjackPlayback_mixerProc(ALCjackPlayback *self) while(!self->mKillNow.load(std::memory_order_acquire) && device->Connected.load(std::memory_order_acquire)) { - if(ll_ringbuffer_write_space(self->mRing.get()) < device->UpdateSize) + if(ring->writeSpace() < device->UpdateSize) { ALCjackPlayback_unlock(self); self->mSem.wait(); @@ -324,7 +326,7 @@ int ALCjackPlayback_mixerProc(ALCjackPlayback *self) continue; } - auto data = ll_ringbuffer_get_write_vector(self->mRing.get()); + auto data = ring->getWriteVector(); auto todo = static_cast<ALuint>(data.first.len + data.second.len); todo -= todo%device->UpdateSize; @@ -334,7 +336,7 @@ int ALCjackPlayback_mixerProc(ALCjackPlayback *self) aluMixData(device, data.first.buf, len1); if(len2 > 0) aluMixData(device, data.second.buf, len2); - ll_ringbuffer_write_advance(self->mRing.get(), todo); + ring->writeAdvance(todo); } ALCjackPlayback_unlock(self); @@ -506,8 +508,9 @@ ClockLatency ALCjackPlayback_getClockLatency(ALCjackPlayback *self) ALCjackPlayback_lock(self); ALCdevice *device{self->mDevice}; + RingBuffer *ring{self->mRing.get()}; ret.ClockTime = GetDeviceClockTime(device); - ret.Latency = std::chrono::seconds{ll_ringbuffer_read_space(self->mRing.get())}; + ret.Latency = std::chrono::seconds{ring->readSpace()}; ret.Latency /= device->Frequency; ALCjackPlayback_unlock(self); diff --git a/Alc/backends/opensl.cpp b/Alc/backends/opensl.cpp index 9213919b..872fbc91 100644 --- a/Alc/backends/opensl.cpp +++ b/Alc/backends/opensl.cpp @@ -203,7 +203,8 @@ static void ALCopenslPlayback_Destruct(ALCopenslPlayback* self) /* this callback handler is called every time a buffer finishes playing */ static void ALCopenslPlayback_process(SLAndroidSimpleBufferQueueItf UNUSED(bq), void *context) { - ALCopenslPlayback *self = static_cast<ALCopenslPlayback*>(context); + auto self = static_cast<ALCopenslPlayback*>(context); + RingBuffer *ring{self->mRing.get()}; /* A note on the ringbuffer usage: The buffer queue seems to hold on to the * pointer passed to the Enqueue method, rather than copying the audio. @@ -213,7 +214,7 @@ static void ALCopenslPlayback_process(SLAndroidSimpleBufferQueueItf UNUSED(bq), * available for writing again, and wake up the mixer thread to mix and * queue more audio. */ - ll_ringbuffer_read_advance(self->mRing.get(), 1); + ring->readAdvance(1); self->mSem.post(); } @@ -221,7 +222,8 @@ static void ALCopenslPlayback_process(SLAndroidSimpleBufferQueueItf UNUSED(bq), static int ALCopenslPlayback_mixerProc(ALCopenslPlayback *self) { - ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; + ALCdevice *device{self->mDevice}; + RingBuffer *ring{self->mRing.get()}; SLAndroidSimpleBufferQueueItf bufferQueue; SLPlayItf player; SLresult result; @@ -247,7 +249,7 @@ static int ALCopenslPlayback_mixerProc(ALCopenslPlayback *self) { size_t todo; - if(ll_ringbuffer_write_space(self->mRing.get()) == 0) + if(ring->writeSpace() == 0) { SLuint32 state = 0; @@ -264,7 +266,7 @@ static int ALCopenslPlayback_mixerProc(ALCopenslPlayback *self) break; } - if(ll_ringbuffer_write_space(self->mRing.get()) == 0) + if(ring->writeSpace() == 0) { ALCopenslPlayback_unlock(self); self->mSem.wait(); @@ -273,15 +275,15 @@ static int ALCopenslPlayback_mixerProc(ALCopenslPlayback *self) } } - auto data = ll_ringbuffer_get_write_vector(self->mRing.get()); + auto data = ring->getWriteVector(); aluMixData(device, data.first.buf, data.first.len*device->UpdateSize); if(data.second.len > 0) aluMixData(device, data.second.buf, data.second.len*device->UpdateSize); todo = data.first.len+data.second.len; - ll_ringbuffer_write_advance(self->mRing.get(), todo); + ring->writeAdvance(todo); - for(size_t i = 0;i < todo;i++) + for(size_t i{0};i < todo;i++) { if(!data.first.len) { @@ -556,13 +558,13 @@ static ALCboolean ALCopenslPlayback_reset(ALCopenslPlayback *self) static ALCboolean ALCopenslPlayback_start(ALCopenslPlayback *self) { - SLAndroidSimpleBufferQueueItf bufferQueue; - SLresult result; + RingBuffer *ring{self->mRing.get()}; - ll_ringbuffer_reset(self->mRing.get()); + ring->reset(); - result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, - &bufferQueue); + SLAndroidSimpleBufferQueueItf bufferQueue; + SLresult result{VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, + &bufferQueue)}; PRINTERR(result, "bufferQueue->GetInterface"); if(SL_RESULT_SUCCESS != result) return ALC_FALSE; @@ -632,13 +634,13 @@ static void ALCopenslPlayback_stop(ALCopenslPlayback *self) static ClockLatency ALCopenslPlayback_getClockLatency(ALCopenslPlayback *self) { - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + ALCdevice *device{self->mDevice}; + RingBuffer *ring{self->mRing.get()}; ClockLatency ret; ALCopenslPlayback_lock(self); ret.ClockTime = GetDeviceClockTime(device); - ret.Latency = std::chrono::seconds{ll_ringbuffer_read_space(self->mRing.get()) * - device->UpdateSize}; + ret.Latency = std::chrono::seconds{ring->readSpace() * device->UpdateSize}; ret.Latency /= device->Frequency; ALCopenslPlayback_unlock(self); @@ -702,9 +704,10 @@ static void ALCopenslCapture_Destruct(ALCopenslCapture *self) static void ALCopenslCapture_process(SLAndroidSimpleBufferQueueItf UNUSED(bq), void *context) { - ALCopenslCapture *self = static_cast<ALCopenslCapture*>(context); + auto *self = static_cast<ALCopenslCapture*>(context); + RingBuffer *ring{self->mRing.get()}; /* A new chunk has been written into the ring buffer, advance it. */ - ll_ringbuffer_write_advance(self->mRing.get(), 1); + ring->writeAdvance(1); } @@ -837,10 +840,11 @@ static ALCenum ALCopenslCapture_open(ALCopenslCapture *self, const ALCchar *name } if(SL_RESULT_SUCCESS == result) { + RingBuffer *ring{self->mRing.get()}; ALsizei chunk_size = device->UpdateSize * self->mFrameSize; size_t i; - auto data = ll_ringbuffer_get_write_vector(self->mRing.get()); + auto data = ring->getWriteVector(); for(i = 0;i < data.first.len && SL_RESULT_SUCCESS == result;i++) { result = VCALL(bufferQueue,Enqueue)(data.first.buf + chunk_size*i, chunk_size); @@ -914,7 +918,8 @@ static void ALCopenslCapture_stop(ALCopenslCapture *self) static ALCenum ALCopenslCapture_captureSamples(ALCopenslCapture *self, ALCvoid *buffer, ALCuint samples) { - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + ALCdevice *device{self->mDevice}; + RingBuffer *ring{self->mRing.get()}; ALsizei chunk_size = device->UpdateSize * self->mFrameSize; SLAndroidSimpleBufferQueueItf bufferQueue; SLresult result; @@ -927,7 +932,7 @@ static ALCenum ALCopenslCapture_captureSamples(ALCopenslCapture *self, ALCvoid * /* Read the desired samples from the ring buffer then advance its read * pointer. */ - auto data = ll_ringbuffer_get_read_vector(self->mRing.get()); + auto data = ring->getReadVector(); for(i = 0;i < samples;) { ALCuint rem = minu(samples - i, device->UpdateSize - self->mSplOffset); @@ -941,7 +946,7 @@ static ALCenum ALCopenslCapture_captureSamples(ALCopenslCapture *self, ALCvoid * /* Finished a chunk, reset the offset and advance the read pointer. */ self->mSplOffset = 0; - ll_ringbuffer_read_advance(self->mRing.get(), 1); + ring->readAdvance(1); result = VCALL(bufferQueue,Enqueue)(data.first.buf, chunk_size); PRINTERR(result, "bufferQueue->Enqueue"); if(SL_RESULT_SUCCESS != result) break; @@ -969,8 +974,9 @@ static ALCenum ALCopenslCapture_captureSamples(ALCopenslCapture *self, ALCvoid * static ALCuint ALCopenslCapture_availableSamples(ALCopenslCapture *self) { - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return ll_ringbuffer_read_space(self->mRing.get()) * device->UpdateSize; + ALCdevice *device{self->mDevice}; + RingBuffer *ring{self->mRing.get()}; + return ring->readSpace() * device->UpdateSize; } diff --git a/Alc/backends/oss.cpp b/Alc/backends/oss.cpp index e338c40d..f6a75d12 100644 --- a/Alc/backends/oss.cpp +++ b/Alc/backends/oss.cpp @@ -537,7 +537,8 @@ void ALCcaptureOSS_Destruct(ALCcaptureOSS *self) int ALCcaptureOSS_recordProc(ALCcaptureOSS *self) { - ALCdevice *device{STATIC_CAST(ALCbackend, self)->mDevice}; + ALCdevice *device{self->mDevice}; + RingBuffer *ring{self->mRing.get()}; SetRTPriority(); althrd_setname(RECORD_THREAD_NAME); @@ -564,7 +565,7 @@ int ALCcaptureOSS_recordProc(ALCcaptureOSS *self) continue; } - auto vec = ll_ringbuffer_get_write_vector(self->mRing.get()); + auto vec = ring->getWriteVector(); if(vec.first.len > 0) { ssize_t amt{read(self->fd, vec.first.buf, vec.first.len*frame_size)}; @@ -576,7 +577,7 @@ int ALCcaptureOSS_recordProc(ALCcaptureOSS *self) ALCcaptureOSS_unlock(self); break; } - ll_ringbuffer_write_advance(self->mRing.get(), amt/frame_size); + ring->writeAdvance(amt/frame_size); } } @@ -724,13 +725,15 @@ void ALCcaptureOSS_stop(ALCcaptureOSS *self) ALCenum ALCcaptureOSS_captureSamples(ALCcaptureOSS *self, ALCvoid *buffer, ALCuint samples) { - ll_ringbuffer_read(self->mRing.get(), static_cast<char*>(buffer), samples); + RingBuffer *ring{self->mRing.get()}; + ring->read(buffer, samples); return ALC_NO_ERROR; } ALCuint ALCcaptureOSS_availableSamples(ALCcaptureOSS *self) { - return ll_ringbuffer_read_space(self->mRing.get()); + RingBuffer *ring{self->mRing.get()}; + return ring->readSpace(); } } // namespace diff --git a/Alc/backends/portaudio.cpp b/Alc/backends/portaudio.cpp index 59b357b5..f39661a7 100644 --- a/Alc/backends/portaudio.cpp +++ b/Alc/backends/portaudio.cpp @@ -365,8 +365,9 @@ int ALCportCapture_ReadCallback(const void *inputBuffer, void *UNUSED(outputBuff unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *UNUSED(timeInfo), const PaStreamCallbackFlags UNUSED(statusFlags), void *userData) { - ALCportCapture *self = static_cast<ALCportCapture*>(userData); - ll_ringbuffer_write(self->Ring.get(), inputBuffer, framesPerBuffer); + auto self = static_cast<ALCportCapture*>(userData); + RingBuffer *ring{self->Ring.get()}; + ring->write(inputBuffer, framesPerBuffer); return 0; } @@ -456,12 +457,14 @@ void ALCportCapture_stop(ALCportCapture *self) ALCuint ALCportCapture_availableSamples(ALCportCapture *self) { - return ll_ringbuffer_read_space(self->Ring.get()); + RingBuffer *ring{self->Ring.get()}; + return ring->readSpace(); } ALCenum ALCportCapture_captureSamples(ALCportCapture *self, ALCvoid *buffer, ALCuint samples) { - ll_ringbuffer_read(self->Ring.get(), buffer, samples); + RingBuffer *ring{self->Ring.get()}; + ring->read(buffer, samples); return ALC_NO_ERROR; } diff --git a/Alc/backends/sndio.cpp b/Alc/backends/sndio.cpp index 2be1d26c..887b5703 100644 --- a/Alc/backends/sndio.cpp +++ b/Alc/backends/sndio.cpp @@ -323,20 +323,20 @@ static void SndioCapture_Destruct(SndioCapture *self) static int SndioCapture_recordProc(SndioCapture *self) { - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - ALsizei frameSize; + ALCdevice *device{self->mDevice}; + RingBuffer *ring{self->ring.get()}; SetRTPriority(); althrd_setname(RECORD_THREAD_NAME); - frameSize = device->frameSizeFromFmt(); + const ALsizei frameSize{device->frameSizeFromFmt()}; while(!self->mKillNow.load(std::memory_order_acquire) && device->Connected.load(std::memory_order_acquire)) { size_t total, todo; - auto data = ll_ringbuffer_get_write_vector(self->ring.get()); + auto data = ring->getWriteVector(); todo = data.first.len + data.second.len; if(todo == 0) { @@ -369,7 +369,7 @@ static int SndioCapture_recordProc(SndioCapture *self) data.first.len -= got; total += got; } - ll_ringbuffer_write_advance(self->ring.get(), total / frameSize); + ring->writeAdvance(total / frameSize); } return 0; @@ -514,13 +514,15 @@ static void SndioCapture_stop(SndioCapture *self) static ALCenum SndioCapture_captureSamples(SndioCapture *self, void *buffer, ALCuint samples) { - ll_ringbuffer_read(self->ring.get(), static_cast<char*>(buffer), samples); + RingBuffer *ring{self->ring.get()}; + ring->read(buffer, samples); return ALC_NO_ERROR; } static ALCuint SndioCapture_availableSamples(SndioCapture *self) { - return ll_ringbuffer_read_space(self->ring.get()); + RingBuffer *ring{self->ring.get()}; + return ring->readSpace(); } diff --git a/Alc/backends/wasapi.cpp b/Alc/backends/wasapi.cpp index c1b4bddb..e1783ef9 100644 --- a/Alc/backends/wasapi.cpp +++ b/Alc/backends/wasapi.cpp @@ -1230,7 +1230,8 @@ void ALCwasapiCapture_Destruct(ALCwasapiCapture *self) FORCE_ALIGN int ALCwasapiCapture_recordProc(ALCwasapiCapture *self) { - ALCdevice *device{STATIC_CAST(ALCbackend, self)->mDevice}; + ALCdevice *device{self->mDevice}; + RingBuffer *ring{self->mRing.get()}; IAudioCaptureClient *capture{self->mCapture}; HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); @@ -1272,7 +1273,7 @@ FORCE_ALIGN int ALCwasapiCapture_recordProc(ALCwasapiCapture *self) rdata = reinterpret_cast<BYTE*>(samples.data()); } - auto data = ll_ringbuffer_get_write_vector(self->mRing.get()); + auto data = ring->getWriteVector(); size_t dstframes; if(self->mSampleConv) @@ -1308,7 +1309,7 @@ FORCE_ALIGN int ALCwasapiCapture_recordProc(ALCwasapiCapture *self) dstframes = len1 + len2; } - ll_ringbuffer_write_advance(self->mRing.get(), dstframes); + ring->writeAdvance(dstframes); hr = capture->ReleaseBuffer(numsamples); if(FAILED(hr)) ERR("Failed to release capture buffer: 0x%08lx\n", hr); @@ -1786,12 +1787,14 @@ void ALCwasapiCapture::stopProxy() ALuint ALCwasapiCapture_availableSamples(ALCwasapiCapture *self) { - return (ALuint)ll_ringbuffer_read_space(self->mRing.get()); + RingBuffer *ring{self->mRing.get()}; + return (ALuint)ring->readSpace(); } ALCenum ALCwasapiCapture_captureSamples(ALCwasapiCapture *self, ALCvoid *buffer, ALCuint samples) { - ll_ringbuffer_read(self->mRing.get(), reinterpret_cast<char*>(buffer), samples); + RingBuffer *ring{self->mRing.get()}; + ring->read(buffer, samples); return ALC_NO_ERROR; } diff --git a/Alc/backends/winmm.cpp b/Alc/backends/winmm.cpp index 0ebba81c..7bfb7f6c 100644 --- a/Alc/backends/winmm.cpp +++ b/Alc/backends/winmm.cpp @@ -472,7 +472,8 @@ void CALLBACK ALCwinmmCapture_waveInProc(HWAVEIN UNUSED(device), UINT msg, int ALCwinmmCapture_captureProc(ALCwinmmCapture *self) { - ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + ALCdevice *device{self->mDevice}; + RingBuffer *ring{self->Ring.get()}; althrd_setname(RECORD_THREAD_NAME); @@ -494,9 +495,7 @@ int ALCwinmmCapture_captureProc(ALCwinmmCapture *self) WAVEHDR &waveHdr = self->WaveBuffer[widx]; widx = (widx+1) % self->WaveBuffer.size(); - ll_ringbuffer_write(self->Ring.get(), waveHdr.lpData, - waveHdr.dwBytesRecorded / self->Format.nBlockAlign - ); + ring->write(waveHdr.lpData, waveHdr.dwBytesRecorded / self->Format.nBlockAlign); self->Readable.fetch_sub(1, std::memory_order_acq_rel); waveInAddBuffer(self->InHdl, &waveHdr, sizeof(WAVEHDR)); } while(--todo); @@ -645,13 +644,15 @@ void ALCwinmmCapture_stop(ALCwinmmCapture *self) ALCenum ALCwinmmCapture_captureSamples(ALCwinmmCapture *self, ALCvoid *buffer, ALCuint samples) { - ll_ringbuffer_read(self->Ring.get(), buffer, samples); + RingBuffer *ring{self->Ring.get()}; + ring->read(buffer, samples); return ALC_NO_ERROR; } ALCuint ALCwinmmCapture_availableSamples(ALCwinmmCapture *self) { - return (ALCuint)ll_ringbuffer_read_space(self->Ring.get()); + RingBuffer *ring{self->Ring.get()}; + return (ALCuint)ring->readSpace(); } } // namespace diff --git a/Alc/mixvoice.cpp b/Alc/mixvoice.cpp index b94f26be..48844219 100644 --- a/Alc/mixvoice.cpp +++ b/Alc/mixvoice.cpp @@ -736,13 +736,14 @@ ALboolean MixSource(ALvoice *voice, const ALuint SourceID, ALCcontext *Context, ALbitfieldSOFT enabledevt{Context->EnabledEvts.load(std::memory_order_acquire)}; if(buffers_done > 0 && (enabledevt&EventType_BufferCompleted)) { - auto evt_data = ll_ringbuffer_get_write_vector(Context->AsyncEvents).first; + RingBuffer *ring{Context->AsyncEvents}; + auto evt_data = ring->getWriteVector().first; if(evt_data.len > 0) { AsyncEvent *evt{new (evt_data.buf) AsyncEvent{EventType_BufferCompleted}}; evt->u.bufcomp.id = SourceID; evt->u.bufcomp.count = buffers_done; - ll_ringbuffer_write_advance(Context->AsyncEvents, 1); + ring->writeAdvance(1); Context->EventSem.post(); } } diff --git a/Alc/ringbuffer.cpp b/Alc/ringbuffer.cpp index a298ff43..9e531316 100644 --- a/Alc/ringbuffer.cpp +++ b/Alc/ringbuffer.cpp @@ -24,6 +24,8 @@ #include <stdlib.h> #include <limits.h> +#include <algorithm> + #include "ringbuffer.h" #include "atomic.h" #include "threads.h" @@ -31,9 +33,9 @@ #include "compat.h" -ll_ringbuffer *ll_ringbuffer_create(size_t sz, size_t elem_sz, int limit_writes) +RingBuffer *ll_ringbuffer_create(size_t sz, size_t elem_sz, int limit_writes) { - ll_ringbuffer *rb; + RingBuffer *rb; size_t power_of_two = 0; if(sz > 0) @@ -51,57 +53,52 @@ ll_ringbuffer *ll_ringbuffer_create(size_t sz, size_t elem_sz, int limit_writes) power_of_two++; if(power_of_two < sz) return NULL; - rb = new (al_malloc(16, sizeof(*rb) + power_of_two*elem_sz)) ll_ringbuffer{}; + rb = new (al_malloc(16, sizeof(*rb) + power_of_two*elem_sz)) RingBuffer{}; - rb->size = limit_writes ? sz : power_of_two; - rb->size_mask = power_of_two - 1; - rb->elem_size = elem_sz; + rb->mSize = limit_writes ? sz : power_of_two; + rb->mSizeMask = power_of_two - 1; + rb->mElemSize = elem_sz; return rb; } -void ll_ringbuffer_reset(ll_ringbuffer *rb) +void RingBuffer::reset() noexcept { - rb->write_ptr.store(0, std::memory_order_relaxed); - rb->read_ptr.store(0, std::memory_order_relaxed); - std::fill_n(rb->buf+0, (rb->size_mask+1)*rb->elem_size, 0); + mWritePtr.store(0, std::memory_order_relaxed); + mReadPtr.store(0, std::memory_order_relaxed); + std::fill_n(mBuffer, (mSizeMask+1)*mElemSize, 0); } -size_t ll_ringbuffer_read_space(const ll_ringbuffer *rb) +size_t RingBuffer::readSpace() const noexcept { - size_t w = rb->write_ptr.load(std::memory_order_acquire); - size_t r = rb->read_ptr.load(std::memory_order_acquire); - return (w-r) & rb->size_mask; + size_t w = mWritePtr.load(std::memory_order_acquire); + size_t r = mReadPtr.load(std::memory_order_acquire); + return (w-r) & mSizeMask; } -size_t ll_ringbuffer_write_space(const ll_ringbuffer *rb) +size_t RingBuffer::writeSpace() const noexcept { - size_t w = rb->write_ptr.load(std::memory_order_acquire); - size_t r = rb->read_ptr.load(std::memory_order_acquire); - w = (r-w-1) & rb->size_mask; - return (w > rb->size) ? rb->size : w; + 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 ll_ringbuffer_read(ll_ringbuffer *rb, void *dest, size_t cnt) +size_t RingBuffer::read(void *dest, size_t cnt) noexcept { - size_t read_ptr; - size_t free_cnt; - size_t cnt2; - size_t to_read; - size_t n1, n2; - - free_cnt = ll_ringbuffer_read_space(rb); + const size_t free_cnt{readSpace()}; if(free_cnt == 0) return 0; - to_read = (cnt > free_cnt) ? free_cnt : cnt; - read_ptr = rb->read_ptr.load(std::memory_order_relaxed) & rb->size_mask; + const size_t to_read{std::min(cnt, free_cnt)}; + size_t read_ptr{mReadPtr.load(std::memory_order_relaxed) & mSizeMask}; - cnt2 = read_ptr + to_read; - if(cnt2 > rb->size_mask+1) + size_t n1, n2; + const size_t cnt2{read_ptr + to_read}; + if(cnt2 > mSizeMask+1) { - n1 = rb->size_mask+1 - read_ptr; - n2 = cnt2 & rb->size_mask; + n1 = mSizeMask+1 - read_ptr; + n2 = cnt2 & mSizeMask; } else { @@ -109,38 +106,32 @@ size_t ll_ringbuffer_read(ll_ringbuffer *rb, void *dest, size_t cnt) n2 = 0; } - memcpy(dest, &rb->buf[read_ptr*rb->elem_size], n1*rb->elem_size); + memcpy(dest, &mBuffer[read_ptr*mElemSize], n1*mElemSize); read_ptr += n1; if(n2) { - memcpy(static_cast<char*>(dest) + n1*rb->elem_size, - &rb->buf[(read_ptr&rb->size_mask)*rb->elem_size], - n2*rb->elem_size); + memcpy(static_cast<char*>(dest) + n1*mElemSize, &mBuffer[(read_ptr&mSizeMask)*mElemSize], + n2*mElemSize); read_ptr += n2; } - rb->read_ptr.store(read_ptr, std::memory_order_release); + mReadPtr.store(read_ptr, std::memory_order_release); return to_read; } -size_t ll_ringbuffer_peek(ll_ringbuffer *rb, void *dest, size_t cnt) +size_t RingBuffer::peek(void *dest, size_t cnt) const noexcept { - size_t free_cnt; - size_t cnt2; - size_t to_read; - size_t n1, n2; - size_t read_ptr; - - free_cnt = ll_ringbuffer_read_space(rb); + const size_t free_cnt{readSpace()}; if(free_cnt == 0) return 0; - to_read = (cnt > free_cnt) ? free_cnt : cnt; - read_ptr = rb->read_ptr.load(std::memory_order_relaxed) & rb->size_mask; + const size_t to_read{std::min(cnt, free_cnt)}; + size_t read_ptr{mReadPtr.load(std::memory_order_relaxed) & mSizeMask}; - cnt2 = read_ptr + to_read; - if(cnt2 > rb->size_mask+1) + size_t n1, n2; + const size_t cnt2{read_ptr + to_read}; + if(cnt2 > mSizeMask+1) { - n1 = rb->size_mask+1 - read_ptr; - n2 = cnt2 & rb->size_mask; + n1 = mSizeMask+1 - read_ptr; + n2 = cnt2 & mSizeMask; } else { @@ -148,36 +139,30 @@ size_t ll_ringbuffer_peek(ll_ringbuffer *rb, void *dest, size_t cnt) n2 = 0; } - memcpy(dest, &rb->buf[read_ptr*rb->elem_size], n1*rb->elem_size); + memcpy(dest, &mBuffer[read_ptr*mElemSize], n1*mElemSize); if(n2) { read_ptr += n1; - memcpy(static_cast<char*>(dest) + n1*rb->elem_size, - &rb->buf[(read_ptr&rb->size_mask)*rb->elem_size], - n2*rb->elem_size); + memcpy(static_cast<char*>(dest) + n1*mElemSize, &mBuffer[(read_ptr&mSizeMask)*mElemSize], + n2*mElemSize); } return to_read; } -size_t ll_ringbuffer_write(ll_ringbuffer *rb, const void *src, size_t cnt) +size_t RingBuffer::write(const void *src, size_t cnt) noexcept { - size_t write_ptr; - size_t free_cnt; - size_t cnt2; - size_t to_write; - size_t n1, n2; - - free_cnt = ll_ringbuffer_write_space(rb); + const size_t free_cnt{writeSpace()}; if(free_cnt == 0) return 0; - to_write = (cnt > free_cnt) ? free_cnt : cnt; - write_ptr = rb->write_ptr.load(std::memory_order_relaxed) & rb->size_mask; + const size_t to_write{std::min(cnt, free_cnt)}; + size_t write_ptr{mWritePtr.load(std::memory_order_relaxed) & mSizeMask}; - cnt2 = write_ptr + to_write; - if(cnt2 > rb->size_mask+1) + size_t n1, n2; + const size_t cnt2{write_ptr + to_write}; + if(cnt2 > mSizeMask+1) { - n1 = rb->size_mask+1 - write_ptr; - n2 = cnt2 & rb->size_mask; + n1 = mSizeMask+1 - write_ptr; + n2 = cnt2 & mSizeMask; } else { @@ -185,57 +170,54 @@ size_t ll_ringbuffer_write(ll_ringbuffer *rb, const void *src, size_t cnt) n2 = 0; } - memcpy(&rb->buf[write_ptr*rb->elem_size], src, n1*rb->elem_size); + memcpy(&mBuffer[write_ptr*mElemSize], src, n1*mElemSize); write_ptr += n1; if(n2) { - memcpy(&rb->buf[(write_ptr&rb->size_mask)*rb->elem_size], - static_cast<const char*>(src) + n1*rb->elem_size, - n2*rb->elem_size); + memcpy(&mBuffer[(write_ptr&mSizeMask)*mElemSize], + static_cast<const char*>(src) + n1*mElemSize, n2*mElemSize); write_ptr += n2; } - rb->write_ptr.store(write_ptr, std::memory_order_release); + mWritePtr.store(write_ptr, std::memory_order_release); return to_write; } -void ll_ringbuffer_read_advance(ll_ringbuffer *rb, size_t cnt) +void RingBuffer::readAdvance(size_t cnt) noexcept { - rb->read_ptr.fetch_add(cnt, std::memory_order_acq_rel); + mReadPtr.fetch_add(cnt, std::memory_order_acq_rel); } -void ll_ringbuffer_write_advance(ll_ringbuffer *rb, size_t cnt) +void RingBuffer::writeAdvance(size_t cnt) noexcept { - rb->write_ptr.fetch_add(cnt, std::memory_order_acq_rel); + mWritePtr.fetch_add(cnt, std::memory_order_acq_rel); } -ll_ringbuffer_data_pair ll_ringbuffer_get_read_vector(const ll_ringbuffer *rb) +ll_ringbuffer_data_pair RingBuffer::getWriteVector() const noexcept { ll_ringbuffer_data_pair ret; - size_t free_cnt; - size_t cnt2; - size_t w = rb->write_ptr.load(std::memory_order_acquire); - size_t r = rb->read_ptr.load(std::memory_order_acquire); - w &= rb->size_mask; - r &= rb->size_mask; - free_cnt = (w-r) & rb->size_mask; + size_t w{mWritePtr.load(std::memory_order_acquire)}; + size_t r{mReadPtr.load(std::memory_order_acquire)}; + w &= mSizeMask; + r &= mSizeMask; + const size_t free_cnt{(w-r) & mSizeMask}; - cnt2 = r + free_cnt; - if(cnt2 > rb->size_mask+1) + const size_t cnt2{r + free_cnt}; + if(cnt2 > mSizeMask+1) { /* Two part vector: the rest of the buffer after the current write ptr, * plus some from the start of the buffer. */ - ret.first.buf = const_cast<char*>(&rb->buf[r*rb->elem_size]); - ret.first.len = rb->size_mask+1 - r; - ret.second.buf = const_cast<char*>(rb->buf); - ret.second.len = cnt2 & rb->size_mask; + ret.first.buf = const_cast<char*>(&mBuffer[r*mElemSize]); + ret.first.len = mSizeMask+1 - r; + ret.second.buf = const_cast<char*>(mBuffer); + ret.second.len = cnt2 & mSizeMask; } else { /* Single part vector: just the rest of the buffer */ - ret.first.buf = const_cast<char*>(&rb->buf[r*rb->elem_size]); + ret.first.buf = const_cast<char*>(&mBuffer[r*mElemSize]); ret.first.len = free_cnt; ret.second.buf = nullptr; ret.second.len = 0; @@ -244,32 +226,29 @@ ll_ringbuffer_data_pair ll_ringbuffer_get_read_vector(const ll_ringbuffer *rb) return ret; } -ll_ringbuffer_data_pair ll_ringbuffer_get_write_vector(const ll_ringbuffer *rb) +ll_ringbuffer_data_pair RingBuffer::getReadVector() const noexcept { ll_ringbuffer_data_pair ret; - size_t free_cnt; - size_t cnt2; - - size_t w = rb->write_ptr.load(std::memory_order_acquire); - size_t r = rb->read_ptr.load(std::memory_order_acquire); - w &= rb->size_mask; - r &= rb->size_mask; - free_cnt = (r-w-1) & rb->size_mask; - if(free_cnt > rb->size) free_cnt = rb->size; - - cnt2 = w + free_cnt; - if(cnt2 > rb->size_mask+1) + + size_t w{mWritePtr.load(std::memory_order_acquire)}; + size_t r{mReadPtr.load(std::memory_order_acquire)}; + w &= mSizeMask; + r &= mSizeMask; + const size_t free_cnt{std::min((r-w-1) & mSizeMask, mSize)}; + + const size_t cnt2{w + free_cnt}; + if(cnt2 > mSizeMask+1) { /* Two part vector: the rest of the buffer after the current write ptr, * plus some from the start of the buffer. */ - ret.first.buf = const_cast<char*>(&rb->buf[w*rb->elem_size]); - ret.first.len = rb->size_mask+1 - w; - ret.second.buf = const_cast<char*>(rb->buf); - ret.second.len = cnt2 & rb->size_mask; + ret.first.buf = const_cast<char*>(&mBuffer[w*mElemSize]); + ret.first.len = mSizeMask+1 - w; + ret.second.buf = const_cast<char*>(mBuffer); + ret.second.len = cnt2 & mSizeMask; } else { - ret.first.buf = const_cast<char*>(&rb->buf[w*rb->elem_size]); + ret.first.buf = const_cast<char*>(&mBuffer[w*mElemSize]); ret.first.len = free_cnt; ret.second.buf = nullptr; ret.second.len = 0; diff --git a/Alc/ringbuffer.h b/Alc/ringbuffer.h index 5111023e..a2871859 100644 --- a/Alc/ringbuffer.h +++ b/Alc/ringbuffer.h @@ -15,18 +15,6 @@ * size or count is in 'elements', not bytes. Additionally, it only supports * single-consumer/single-provider operation. */ -struct ll_ringbuffer { - std::atomic<size_t> write_ptr{0u}; - std::atomic<size_t> read_ptr{0u}; - size_t size{0u}; - size_t size_mask{0u}; - size_t elem_size{0u}; - - alignas(16) char buf[]; - - DEF_PLACE_NEWDEL() -}; - struct ll_ringbuffer_data { char *buf; @@ -35,60 +23,74 @@ struct ll_ringbuffer_data { using ll_ringbuffer_data_pair = std::pair<ll_ringbuffer_data,ll_ringbuffer_data>; -/** - * Create a new ringbuffer to hold at least `sz' elements of `elem_sz' bytes. - * The number of elements is rounded up to the next power of two (even if it is - * already a power of two, to ensure the requested amount can be written). - */ -ll_ringbuffer *ll_ringbuffer_create(size_t sz, size_t elem_sz, int limit_writes); -/** Reset the read and write pointers to zero. This is not thread safe. */ -void ll_ringbuffer_reset(ll_ringbuffer *rb); +struct RingBuffer { + std::atomic<size_t> mWritePtr{0u}; + std::atomic<size_t> mReadPtr{0u}; + size_t mSize{0u}; + size_t mSizeMask{0u}; + size_t mElemSize{0u}; + + alignas(16) char mBuffer[]; + + /** Reset the read and write pointers to zero. This is not thread safe. */ + void reset() noexcept; + + /** + * The non-copying data reader. Returns two ringbuffer data pointers that + * hold the current readable data. If the readable data is in one segment + * the second segment has zero length. + */ + ll_ringbuffer_data_pair getReadVector() const noexcept; + /** + * The non-copying data writer. Returns two ringbuffer data pointers that + * hold the current writeable data. If the writeable data is in one segment + * the second segment has zero length. + */ + ll_ringbuffer_data_pair getWriteVector() const noexcept; + + /** + * Return the number of elements available for reading. This is the number + * of elements in front of the read pointer and behind the write pointer. + */ + size_t readSpace() const noexcept; + /** + * The copying data reader. Copy at most `cnt' elements into `dest'. + * Returns the actual number of elements copied. + */ + size_t read(void *dest, size_t cnt) noexcept; + /** + * The copying data reader w/o read pointer advance. Copy at most `cnt' + * elements into `dest'. Returns the actual number of elements copied. + */ + size_t peek(void *dest, size_t cnt) const noexcept; + /** Advance the read pointer `cnt' places. */ + void readAdvance(size_t cnt) noexcept; + + /** + * Return the number of elements available for writing. This is the number + * of elements in front of the write pointer and behind the read pointer. + */ + size_t writeSpace() const noexcept; + /** + * The copying data writer. Copy at most `cnt' elements from `src'. Returns + * the actual number of elements copied. + */ + size_t write(const void *src, size_t cnt) noexcept; + /** Advance the write pointer `cnt' places. */ + void writeAdvance(size_t cnt) noexcept; -/** - * The non-copying data reader. Returns two ringbuffer data pointers that hold - * the current readable data at `rb'. If the readable data is in one segment - * the second segment has zero length. - */ -ll_ringbuffer_data_pair ll_ringbuffer_get_read_vector(const ll_ringbuffer *rb); -/** - * The non-copying data writer. Returns two ringbuffer data pointers that hold - * the current writeable data at `rb'. If the writeable data is in one segment - * the second segment has zero length. - */ -ll_ringbuffer_data_pair ll_ringbuffer_get_write_vector(const ll_ringbuffer *rb); + DEF_PLACE_NEWDEL() +}; -/** - * Return the number of elements available for reading. This is the number of - * elements in front of the read pointer and behind the write pointer. - */ -size_t ll_ringbuffer_read_space(const ll_ringbuffer *rb); -/** - * The copying data reader. Copy at most `cnt' elements from `rb' to `dest'. - * Returns the actual number of elements copied. - */ -size_t ll_ringbuffer_read(ll_ringbuffer *rb, void *dest, size_t cnt); -/** - * The copying data reader w/o read pointer advance. Copy at most `cnt' - * elements from `rb' to `dest'. Returns the actual number of elements copied. - */ -size_t ll_ringbuffer_peek(ll_ringbuffer *rb, void *dest, size_t cnt); -/** Advance the read pointer `cnt' places. */ -void ll_ringbuffer_read_advance(ll_ringbuffer *rb, size_t cnt); /** - * Return the number of elements available for writing. This is the number of - * elements in front of the write pointer and behind the read pointer. - */ -size_t ll_ringbuffer_write_space(const ll_ringbuffer *rb); -/** - * The copying data writer. Copy at most `cnt' elements to `rb' from `src'. - * Returns the actual number of elements copied. + * Create a new ringbuffer to hold at least `sz' elements of `elem_sz' bytes. + * The number of elements is rounded up to the next power of two (even if it is + * already a power of two, to ensure the requested amount can be written). */ -size_t ll_ringbuffer_write(ll_ringbuffer *rb, const void *src, size_t cnt); -/** Advance the write pointer `cnt' places. */ -void ll_ringbuffer_write_advance(ll_ringbuffer *rb, size_t cnt); +RingBuffer *ll_ringbuffer_create(size_t sz, size_t elem_sz, int limit_writes); -using RingBufferPtr = std::unique_ptr<ll_ringbuffer>; +using RingBufferPtr = std::unique_ptr<RingBuffer>; #endif /* RINGBUFFER_H */ |