Clean up the ring buffer struct and use member functions

This commit is contained in:
Chris Robinson
2018-12-26 21:22:17 -08:00
parent 4f253a935a
commit 8a0295503d
18 changed files with 284 additions and 268 deletions
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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();
}
}
+7 -6
View File
@@ -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)
+8 -5
View File
@@ -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;
}
+9 -7
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
+8 -5
View File
@@ -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
+7 -4
View File
@@ -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;
}
+9 -7
View File
@@ -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();
}
+8 -5
View File
@@ -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;
}
+7 -6
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 */
+5 -4
View File
@@ -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
View File
@@ -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())