aboutsummaryrefslogtreecommitdiffstats
path: root/Alc
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2018-12-25 09:32:38 -0800
committerChris Robinson <[email protected]>2018-12-25 09:32:38 -0800
commit63df7cd537bd43fb2548a112b051a1790ff1140e (patch)
tree99cc9c4ef001c2b3731a4768a8983d7c6f25b47f /Alc
parent3b7f668b28dbc5ef156bad9aa79f16b32efb2eb3 (diff)
Construct AsyncEvent objects directly in the ringbuffer
Diffstat (limited to 'Alc')
-rw-r--r--Alc/alc.cpp19
-rw-r--r--Alc/alu.cpp44
-rw-r--r--Alc/mixvoice.cpp12
3 files changed, 55 insertions, 20 deletions
diff --git a/Alc/alc.cpp b/Alc/alc.cpp
index b6065e97..d13cfc54 100644
--- a/Alc/alc.cpp
+++ b/Alc/alc.cpp
@@ -2465,6 +2465,25 @@ 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);
+ while(evt_vec.first.len > 0)
+ {
+ reinterpret_cast<AsyncEvent*>(evt_vec.first.buf)->~AsyncEvent();
+ evt_vec.first.buf += sizeof(AsyncEvent);
+ evt_vec.first.len -= 1;
+ ++count;
+ }
+ while(evt_vec.second.len > 0)
+ {
+ reinterpret_cast<AsyncEvent*>(evt_vec.second.buf)->~AsyncEvent();
+ evt_vec.second.buf += sizeof(AsyncEvent);
+ evt_vec.second.len -= 1;
+ ++count;
+ }
+ if(count > 0)
+ TRACE("Destructed " SZFMT " orphaned event%s\n", count, (count==1)?"":"s");
+
delete AsyncEvents;
AsyncEvents = nullptr;
diff --git a/Alc/alu.cpp b/Alc/alu.cpp
index 01b4f3c3..abe938f1 100644
--- a/Alc/alu.cpp
+++ b/Alc/alu.cpp
@@ -293,12 +293,14 @@ void SendSourceStoppedEvent(ALCcontext *context, ALuint id)
ALbitfieldSOFT enabledevt{context->EnabledEvts.load(std::memory_order_acquire)};
if(!(enabledevt&EventType_SourceStateChange)) return;
- AsyncEvent evt{EventType_SourceStateChange};
- evt.u.srcstate.id = id;
- evt.u.srcstate.state = AL_STOPPED;
-
- if(ll_ringbuffer_write(context->AsyncEvents, &evt, 1) == 1)
- context->EventSem.post();
+ auto evt_data = ll_ringbuffer_get_write_vector(context->AsyncEvents).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);
+ context->EventSem.post();
}
@@ -394,6 +396,7 @@ bool CalcEffectSlotParams(ALeffectslot *slot, ALCcontext *context, bool force)
}
state = props->State;
+ props->State = nullptr;
if(state == slot->Params.mEffectState)
{
@@ -402,21 +405,23 @@ bool CalcEffectSlotParams(ALeffectslot *slot, ALCcontext *context, bool force)
* 0 refs since the current params also hold a reference).
*/
DecrementRef(&state->mRef);
- props->State = nullptr;
}
else
{
/* Otherwise, replace it and send off the old one with a release
* event.
*/
- AsyncEvent evt{EventType_ReleaseEffectState};
- evt.u.mEffectState = slot->Params.mEffectState;
-
+ EffectState *oldstate{slot->Params.mEffectState};
slot->Params.mEffectState = state;
- props->State = nullptr;
- if(LIKELY(ll_ringbuffer_write(context->AsyncEvents, &evt, 1) != 0))
+ auto evt_data = ll_ringbuffer_get_write_vector(context->AsyncEvents).first;
+ if(LIKELY(evt_data.len > 0))
+ {
+ AsyncEvent *evt{new (evt_data.buf) AsyncEvent{EventType_ReleaseEffectState}};
+ evt->u.mEffectState = oldstate;
+ ll_ringbuffer_write_advance(context->AsyncEvents, 1);
context->EventSem.post();
+ }
else
{
/* If writing the event failed, the queue was probably full.
@@ -424,7 +429,7 @@ bool CalcEffectSlotParams(ALeffectslot *slot, ALCcontext *context, bool force)
* eventually be cleaned up sometime later (not ideal, but
* better than blocking or leaking).
*/
- props->State = evt.u.mEffectState;
+ props->State = oldstate;
}
}
@@ -1828,9 +1833,16 @@ void aluHandleDisconnect(ALCdevice *device, const char *msg, ...)
while(ctx)
{
const ALbitfieldSOFT enabledevt{ctx->EnabledEvts.load(std::memory_order_acquire)};
- if((enabledevt&EventType_Disconnected) &&
- ll_ringbuffer_write(ctx->AsyncEvents, &evt, 1) == 1)
- ctx->EventSem.post();
+ if((enabledevt&EventType_Disconnected))
+ {
+ auto evt_data = ll_ringbuffer_get_write_vector(ctx->AsyncEvents).first;
+ if(evt_data.len > 0)
+ {
+ new (evt_data.buf) AsyncEvent{evt};
+ ll_ringbuffer_write_advance(ctx->AsyncEvents, 1);
+ ctx->EventSem.post();
+ }
+ }
std::for_each(ctx->Voices, ctx->Voices+ctx->VoiceCount.load(std::memory_order_acquire),
[ctx](ALvoice *voice) -> void
diff --git a/Alc/mixvoice.cpp b/Alc/mixvoice.cpp
index 680f4a31..f68c0f0a 100644
--- a/Alc/mixvoice.cpp
+++ b/Alc/mixvoice.cpp
@@ -721,11 +721,15 @@ ALboolean MixSource(ALvoice *voice, ALuint SourceID, ALCcontext *Context, ALsize
ALbitfieldSOFT enabledevt{Context->EnabledEvts.load(std::memory_order_acquire)};
if(buffers_done > 0 && (enabledevt&EventType_BufferCompleted))
{
- AsyncEvent evt{EventType_BufferCompleted};
- evt.u.bufcomp.id = SourceID;
- evt.u.bufcomp.count = buffers_done;
- if(ll_ringbuffer_write(Context->AsyncEvents, &evt, 1) == 1)
+ auto evt_data = ll_ringbuffer_get_write_vector(Context->AsyncEvents).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);
Context->EventSem.post();
+ }
}
return isplaying;