diff options
author | Chris Robinson <[email protected]> | 2018-12-26 12:25:34 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2018-12-26 12:25:34 -0800 |
commit | 5cc545f157877d5ae6911c9778a90e9400e3fbd2 (patch) | |
tree | 13551725174bce1988f39712f1297b8be774a3d6 /Alc | |
parent | 38537a35ccc2ad713a31943bb699d013b004d075 (diff) |
More aggressively try to decrement an effect's refcount in-place
Diffstat (limited to 'Alc')
-rw-r--r-- | Alc/alu.cpp | 30 |
1 files changed, 17 insertions, 13 deletions
diff --git a/Alc/alu.cpp b/Alc/alu.cpp index fec574d8..07ad540d 100644 --- a/Alc/alu.cpp +++ b/Alc/alu.cpp @@ -397,27 +397,31 @@ bool CalcEffectSlotParams(ALeffectslot *slot, ALCcontext *context, bool force) state = props->State; props->State = nullptr; + EffectState *oldstate{slot->Params.mEffectState}; + slot->Params.mEffectState = state; - if(state == slot->Params.mEffectState) + /* Manually decrement the old effect state's refcount if it's greater + * than 1. We need to be a bit clever here to avoid the refcount + * reaching 0 since it can't be deleted in the mixer. + */ + ALuint oldval{oldstate->mRef.load(std::memory_order_acquire)}; + while(oldval > 1 && !oldstate->mRef.compare_exchange_weak(oldval, oldval-1, + std::memory_order_acq_rel, std::memory_order_acquire)) { - /* 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). + /* oldval was updated with the current value on failure, so just + * try again. */ - DecrementRef(&state->mRef); } - else + + if(oldval < 2) { - /* Otherwise, replace it and send off the old one with a release + /* Otherwise, if it would be deleted, send it off with a release * event. */ - EffectState *oldstate{slot->Params.mEffectState}; - slot->Params.mEffectState = state; - - auto evt_data = ll_ringbuffer_get_write_vector(context->AsyncEvents).first; - if(LIKELY(evt_data.len > 0)) + auto evt_vec = ll_ringbuffer_get_write_vector(context->AsyncEvents); + if(LIKELY(evt_vec.first.len > 0)) { - AsyncEvent *evt{new (evt_data.buf) AsyncEvent{EventType_ReleaseEffectState}}; + AsyncEvent *evt{new (evt_vec.first.buf) AsyncEvent{EventType_ReleaseEffectState}}; evt->u.mEffectState = oldstate; ll_ringbuffer_write_advance(context->AsyncEvents, 1); context->EventSem.post(); |