aboutsummaryrefslogtreecommitdiffstats
path: root/OpenAL32
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2016-05-15 13:44:32 -0700
committerChris Robinson <[email protected]>2016-05-15 13:50:56 -0700
commitc522658d19f7e82748400731bddb4633847c2a40 (patch)
tree1f98ada849dcbe6e210c30381c94ff1295c23e25 /OpenAL32
parent576c1116a65bd66effce6d92d1aa7e21d1dee83a (diff)
Avoid duplicate effect state objects in the freelist
If an unapplied update was superceded, it would be placed in the freelist with its effect state object intact. This would cause another update with the same effect state object to be placed into the freelist as well, or worse, cause it to get deleted while in use when the container had its effect state cleared.
Diffstat (limited to 'OpenAL32')
-rw-r--r--OpenAL32/alAuxEffectSlot.c37
1 files changed, 25 insertions, 12 deletions
diff --git a/OpenAL32/alAuxEffectSlot.c b/OpenAL32/alAuxEffectSlot.c
index 0dd6a53f..9cc86563 100644
--- a/OpenAL32/alAuxEffectSlot.c
+++ b/OpenAL32/alAuxEffectSlot.c
@@ -549,12 +549,12 @@ ALenum InitEffectSlot(ALeffectslot *slot)
void DeinitEffectSlot(ALeffectslot *slot)
{
struct ALeffectslotProps *props;
+ ALeffectState *state;
size_t count = 0;
props = ATOMIC_LOAD(&slot->Update);
if(props)
{
- ALeffectState *state;
state = ATOMIC_LOAD(&props->State, almemory_order_relaxed);
if(state != slot->Params.EffectState)
DELETE_OBJ(state);
@@ -565,7 +565,6 @@ void DeinitEffectSlot(ALeffectslot *slot)
while(props)
{
struct ALeffectslotProps *next;
- ALeffectState *state;
state = ATOMIC_LOAD(&props->State, almemory_order_relaxed);
next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
DELETE_OBJ(state);
@@ -583,18 +582,32 @@ void UpdateEffectSlotProps(ALeffectslot *slot)
struct ALeffectslotProps *props;
ALeffectState *oldstate;
- /* Get an unused property container, or allocate a new one as needed. */
- props = ATOMIC_LOAD(&slot->FreeList, almemory_order_acquire);
- if(!props)
- props = al_calloc(16, sizeof(*props));
+ props = ATOMIC_EXCHANGE(struct ALeffectslotProps*, &slot->Update, NULL);
+ if(props)
+ {
+ /* If there was an unapplied update, check if its state object is the
+ * same as the current in-use one, or the one that will be set. If
+ * neither, delete it.
+ */
+ oldstate = ATOMIC_EXCHANGE(ALeffectState*, &props->State, NULL, almemory_order_relaxed);
+ if(oldstate != slot->Params.EffectState && oldstate != slot->Effect.State)
+ DELETE_OBJ(oldstate);
+ }
else
{
- struct ALeffectslotProps *next;
- do {
- next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
- } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALeffectslotProps*,
- &slot->FreeList, &props, next, almemory_order_seq_cst,
- almemory_order_consume) == 0);
+ /* Get an unused property container, or allocate a new one as needed. */
+ props = ATOMIC_LOAD(&slot->FreeList, almemory_order_relaxed);
+ if(!props)
+ props = al_calloc(16, sizeof(*props));
+ else
+ {
+ struct ALeffectslotProps *next;
+ do {
+ next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
+ } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALeffectslotProps*,
+ &slot->FreeList, &props, next, almemory_order_seq_cst,
+ almemory_order_consume) == 0);
+ }
}
/* Copy in current property values. */