aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2018-09-21 02:37:37 -0700
committerChris Robinson <[email protected]>2018-09-21 04:14:15 -0700
commitb6d0ff02c2ec52d2c12a58f2be83b4c3eaa93afe (patch)
treef0d8d0d56589b38d623dd746ff7435d3a63026b6
parentf21e2df4cf0d51fda31f5607e1bf966459d9bf9d (diff)
Use an internal event to more timely release old effect states
-rw-r--r--Alc/ALu.c38
-rw-r--r--OpenAL32/Include/alMain.h4
-rw-r--r--OpenAL32/alAuxEffectSlot.c3
-rw-r--r--OpenAL32/event.c7
4 files changed, 47 insertions, 5 deletions
diff --git a/Alc/ALu.c b/Alc/ALu.c
index c8c583ef..3f61338f 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -462,12 +462,40 @@ static bool CalcEffectSlotParams(ALeffectslot *slot, ALCcontext *context, bool f
slot->Params.AirAbsorptionGainHF = 1.0f;
}
- /* Swap effect states. No need to play with the ref counts since they
- * keep the same number of refs.
- */
state = props->State;
- props->State = slot->Params.EffectState;
- slot->Params.EffectState = state;
+
+ if(state == slot->Params.EffectState)
+ {
+ /* If the effect state is the same as current, we can decrement its
+ * count safely to remove it from the update object (it can't reach
+ * 0 refs since the current params also hold a reference).
+ */
+ DecrementRef(&state->Ref);
+ props->State = NULL;
+ }
+ else
+ {
+ /* Otherwise, replace it and send off the old one with a release
+ * event.
+ */
+ AsyncEvent evt = ASYNC_EVENT(EventType_ReleaseEffectState);
+ evt.u.EffectState = slot->Params.EffectState;
+
+ slot->Params.EffectState = state;
+ props->State = NULL;
+
+ if(LIKELY(ll_ringbuffer_write(context->AsyncEvents, (const char*)&evt, 1) != 0))
+ alsem_post(&context->EventSem);
+ else
+ {
+ /* If writing the event failed, the queue was probably full.
+ * Store the old state in the property object where it can
+ * eventually be cleaned up sometime later (not ideal, but
+ * better than blocking or leaking).
+ */
+ props->State = evt.u.EffectState;
+ }
+ }
ATOMIC_REPLACE_HEAD(struct ALeffectslotProps*, &context->FreeEffectslotProps, props);
}
diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h
index 3a08e8c1..3e328157 100644
--- a/OpenAL32/Include/alMain.h
+++ b/OpenAL32/Include/alMain.h
@@ -760,6 +760,9 @@ enum {
EventType_Performance = 1<<3,
EventType_Deprecated = 1<<4,
EventType_Disconnected = 1<<5,
+
+ /* Internal events. */
+ EventType_ReleaseEffectState = 65536,
};
typedef struct AsyncEvent {
@@ -772,6 +775,7 @@ typedef struct AsyncEvent {
ALuint param;
ALchar msg[1008];
} user;
+ struct ALeffectState *EffectState;
} u;
} AsyncEvent;
#define ASYNC_EVENT(t) { t, { 0 } }
diff --git a/OpenAL32/alAuxEffectSlot.c b/OpenAL32/alAuxEffectSlot.c
index b293b6a5..8141e0f6 100644
--- a/OpenAL32/alAuxEffectSlot.c
+++ b/OpenAL32/alAuxEffectSlot.c
@@ -753,6 +753,9 @@ void UpdateEffectSlotProps(ALeffectslot *slot, ALCcontext *context)
/* If there was an unused update container, put it back in the
* freelist.
*/
+ if(props->State)
+ ALeffectState_DecRef(props->State);
+ props->State = NULL;
ATOMIC_REPLACE_HEAD(struct ALeffectslotProps*, &context->FreeEffectslotProps, props);
}
diff --git a/OpenAL32/event.c b/OpenAL32/event.c
index c0bf4204..4c9c0be2 100644
--- a/OpenAL32/event.c
+++ b/OpenAL32/event.c
@@ -6,6 +6,7 @@
#include "AL/alext.h"
#include "alMain.h"
#include "alError.h"
+#include "alAuxEffectSlot.h"
#include "ringbuffer.h"
@@ -30,6 +31,12 @@ int EventThread(void *arg)
quitnow = evt.EnumType == EventType_KillThread;
if(quitnow) break;
+ if(evt.EnumType == EventType_ReleaseEffectState)
+ {
+ ALeffectState_DecRef(evt.u.EffectState);
+ continue;
+ }
+
enabledevts = ATOMIC_LOAD(&context->EnabledEvts, almemory_order_acquire);
if(context->EventCb && (enabledevts&evt.EnumType) == evt.EnumType)
context->EventCb(evt.u.user.type, evt.u.user.id, evt.u.user.param,