diff options
author | Chris Robinson <[email protected]> | 2016-05-15 13:44:32 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2016-05-15 13:50:56 -0700 |
commit | c522658d19f7e82748400731bddb4633847c2a40 (patch) | |
tree | 1f98ada849dcbe6e210c30381c94ff1295c23e25 /OpenAL32/alAuxEffectSlot.c | |
parent | 576c1116a65bd66effce6d92d1aa7e21d1dee83a (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/alAuxEffectSlot.c')
-rw-r--r-- | OpenAL32/alAuxEffectSlot.c | 37 |
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. */ |