Clean up the ring buffer struct and use member functions
This commit is contained in:
+1
-1
@@ -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();
|
||||
|
||||
+2
-2
@@ -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{};
|
||||
|
||||
+10
-6
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+10
-7
@@ -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);
|
||||
|
||||
|
||||
+31
-25
@@ -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)
|
||||
{
|
||||
RingBuffer *ring{self->mRing.get()};
|
||||
|
||||
ring->reset();
|
||||
|
||||
SLAndroidSimpleBufferQueueItf bufferQueue;
|
||||
SLresult result;
|
||||
|
||||
ll_ringbuffer_reset(self->mRing.get());
|
||||
|
||||
result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
|
||||
&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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+3
-2
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
+89
-110
@@ -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;
|
||||
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)};
|
||||
|
||||
cnt2 = w + free_cnt;
|
||||
if(cnt2 > rb->size_mask+1)
|
||||
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;
|
||||
|
||||
+62
-60
@@ -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>;
|
||||
|
||||
|
||||
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;
|
||||
|
||||
DEF_PLACE_NEWDEL()
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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 */
|
||||
|
||||
@@ -691,13 +691,14 @@ void SendStateChangeEvent(ALCcontext *context, ALuint id, ALenum state)
|
||||
* and we don't want state change messages to occur out of order, so send
|
||||
* it through the async queue to ensure proper ordering.
|
||||
*/
|
||||
auto evt_data = ll_ringbuffer_get_write_vector(context->AsyncEvents).first;
|
||||
if(evt_data.len < 1) return;
|
||||
RingBuffer *ring{context->AsyncEvents};
|
||||
auto evt_vec = ring->getWriteVector();
|
||||
if(evt_vec.first.len < 1) return;
|
||||
|
||||
AsyncEvent *evt{new (evt_data.buf) AsyncEvent{EventType_SourceStateChange}};
|
||||
AsyncEvent *evt{new (evt_vec.first.buf) AsyncEvent{EventType_SourceStateChange}};
|
||||
evt->u.srcstate.id = id;
|
||||
evt->u.srcstate.state = state;
|
||||
ll_ringbuffer_write_advance(context->AsyncEvents, 1);
|
||||
ring->writeAdvance(1);
|
||||
context->EventSem.post();
|
||||
}
|
||||
|
||||
|
||||
+8
-6
@@ -17,10 +17,11 @@
|
||||
|
||||
static int EventThread(ALCcontext *context)
|
||||
{
|
||||
RingBuffer *ring{context->AsyncEvents};
|
||||
bool quitnow{false};
|
||||
while(LIKELY(!quitnow))
|
||||
{
|
||||
auto evt_data = ll_ringbuffer_get_read_vector(context->AsyncEvents).first;
|
||||
auto evt_data = ring->getReadVector().first;
|
||||
if(evt_data.len == 0)
|
||||
{
|
||||
context->EventSem.wait();
|
||||
@@ -37,11 +38,11 @@ static int EventThread(ALCcontext *context)
|
||||
*/
|
||||
const struct EventAutoDestructor {
|
||||
AsyncEvent &evt;
|
||||
ll_ringbuffer *ring;
|
||||
RingBuffer *ring;
|
||||
~EventAutoDestructor()
|
||||
{
|
||||
evt.~AsyncEvent();
|
||||
ll_ringbuffer_read_advance(ring, 1);
|
||||
ring->readAdvance(1);
|
||||
}
|
||||
} _{evt, context->AsyncEvents};
|
||||
|
||||
@@ -110,16 +111,17 @@ void StartEventThrd(ALCcontext *ctx)
|
||||
void StopEventThrd(ALCcontext *ctx)
|
||||
{
|
||||
static constexpr AsyncEvent kill_evt{EventType_KillThread};
|
||||
ll_ringbuffer_data 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)
|
||||
{
|
||||
do {
|
||||
std::this_thread::yield();
|
||||
evt_data = ll_ringbuffer_get_write_vector(ctx->AsyncEvents).first;
|
||||
evt_data = ring->getWriteVector().first;
|
||||
} while(evt_data.len == 0);
|
||||
}
|
||||
new (evt_data.buf) AsyncEvent{kill_evt};
|
||||
ll_ringbuffer_write_advance(ctx->AsyncEvents, 1);
|
||||
ring->writeAdvance(1);
|
||||
|
||||
ctx->EventSem.post();
|
||||
if(ctx->EventThread.joinable())
|
||||
|
||||
Reference in New Issue
Block a user