aboutsummaryrefslogtreecommitdiffstats
path: root/OpenAL32
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2016-08-25 04:57:58 -0700
committerChris Robinson <[email protected]>2016-08-25 04:57:58 -0700
commit4e4e597fa54cc3498ae28bea9c2684e1fee05389 (patch)
tree16757d48abbc6f70ae37bd6903811dd465ff8447 /OpenAL32
parent0fbf34fb4592aa29fcbf4e725719cb253e7d3a78 (diff)
Track all references for effect states
This allows us to not have to play around with trying to avoid duplicate state pointers, since the reference count will ensure they're deleted as appropriate. The only caveat is that the mixer is not allowed to decrement references, since that can cause the object to be freed (which the mixer code is not allowed to do).
Diffstat (limited to 'OpenAL32')
-rw-r--r--OpenAL32/alAuxEffectSlot.c68
1 files changed, 47 insertions, 21 deletions
diff --git a/OpenAL32/alAuxEffectSlot.c b/OpenAL32/alAuxEffectSlot.c
index 1a20952b..85be5c6d 100644
--- a/OpenAL32/alAuxEffectSlot.c
+++ b/OpenAL32/alAuxEffectSlot.c
@@ -44,7 +44,6 @@ extern inline struct ALeffectslot *RemoveEffectSlot(ALCcontext *context, ALuint
static void RemoveEffectSlotList(ALCcontext *Context, const ALeffectslot *slot);
-
static UIntMap EffectStateFactoryMap;
static inline ALeffectStateFactory *getFactoryByType(ALenum type)
{
@@ -54,6 +53,9 @@ static inline ALeffectStateFactory *getFactoryByType(ALenum type)
return NULL;
}
+static void ALeffectState_IncRef(ALeffectState *state);
+static void ALeffectState_DecRef(ALeffectState *state);
+
AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
{
@@ -86,7 +88,9 @@ AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslo
if(err != AL_NO_ERROR)
{
FreeThunkEntry(slot->id);
- DELETE_OBJ(slot->Params.EffectState);
+ ALeffectState_DecRef(slot->Effect.State);
+ if(slot->Params.EffectState)
+ ALeffectState_DecRef(slot->Params.EffectState);
al_free(slot);
alDeleteAuxiliaryEffectSlots(cur, effectslots);
@@ -469,11 +473,12 @@ void DeinitEffectFactoryMap(void)
ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *effect)
{
ALenum newtype = (effect ? effect->type : AL_EFFECT_NULL);
- ALeffectStateFactory *factory;
+ struct ALeffectslotProps *props;
+ ALeffectState *State;
if(newtype != EffectSlot->Effect.Type)
{
- ALeffectState *State;
+ ALeffectStateFactory *factory;
FPUCtl oldMode;
factory = getFactoryByType(newtype);
@@ -493,7 +498,7 @@ ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *e
{
almtx_unlock(&Device->BackendLock);
RestoreFPUMode(&oldMode);
- DELETE_OBJ(State);
+ ALeffectState_DecRef(State);
return AL_OUT_OF_MEMORY;
}
almtx_unlock(&Device->BackendLock);
@@ -510,6 +515,7 @@ ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *e
EffectSlot->Effect.Props = effect->Props;
}
+ ALeffectState_DecRef(EffectSlot->Effect.State);
EffectSlot->Effect.State = State;
UpdateEffectSlotProps(EffectSlot);
}
@@ -519,10 +525,35 @@ ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *e
UpdateEffectSlotProps(EffectSlot);
}
+ /* Remove state references from old effect slot property updates. */
+ props = ATOMIC_LOAD(&EffectSlot->FreeList);
+ while(props)
+ {
+ State = ATOMIC_EXCHANGE(ALeffectState*, &props->State, NULL, almemory_order_relaxed);
+ if(State) ALeffectState_DecRef(State);
+ ATOMIC_LOAD(&props->next, almemory_order_relaxed);
+ }
+
return AL_NO_ERROR;
}
+static void ALeffectState_IncRef(ALeffectState *state)
+{
+ uint ref;
+ ref = IncrementRef(&state->Ref);
+ TRACEREF("%p increasing refcount to %u\n", state, ref);
+}
+
+static void ALeffectState_DecRef(ALeffectState *state)
+{
+ uint ref;
+ ref = DecrementRef(&state->Ref);
+ TRACEREF("%p decreasing refcount to %u\n", state, ref);
+ if(ref == 0) DELETE_OBJ(state);
+}
+
+
void ALeffectState_Construct(ALeffectState *state)
{
InitRef(&state->Ref, 1);
@@ -555,6 +586,7 @@ ALenum InitEffectSlot(ALeffectslot *slot)
slot->Params.Gain = 1.0f;
slot->Params.AuxSendAuto = AL_TRUE;
+ ALeffectState_IncRef(slot->Effect.State);
slot->Params.EffectState = slot->Effect.State;
slot->Params.RoomRolloff = 0.0f;
slot->Params.DecayTime = 0.0f;
@@ -575,8 +607,7 @@ void DeinitEffectSlot(ALeffectslot *slot)
if(props)
{
state = ATOMIC_LOAD(&props->State, almemory_order_relaxed);
- if(state != slot->Params.EffectState)
- DELETE_OBJ(state);
+ if(state) ALeffectState_DecRef(state);
TRACE("Freed unapplied AuxiliaryEffectSlot update %p\n", props);
al_free(props);
}
@@ -586,14 +617,16 @@ void DeinitEffectSlot(ALeffectslot *slot)
struct ALeffectslotProps *next;
state = ATOMIC_LOAD(&props->State, almemory_order_relaxed);
next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
- DELETE_OBJ(state);
+ if(state) ALeffectState_DecRef(state);
al_free(props);
props = next;
++count;
}
TRACE("Freed "SZFMT" AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
- DELETE_OBJ(slot->Params.EffectState);
+ ALeffectState_DecRef(slot->Effect.State);
+ if(slot->Params.EffectState)
+ ALeffectState_DecRef(slot->Params.EffectState);
}
void UpdateEffectSlotProps(ALeffectslot *slot)
@@ -602,17 +635,7 @@ void UpdateEffectSlotProps(ALeffectslot *slot)
ALeffectState *oldstate;
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
+ if(!props)
{
/* Get an unused property container, or allocate a new one as needed. */
props = ATOMIC_LOAD(&slot->FreeList, almemory_order_relaxed);
@@ -638,6 +661,8 @@ void UpdateEffectSlotProps(ALeffectslot *slot)
/* Swap out any stale effect state object there may be in the container, to
* delete it.
*/
+ if(slot->Effect.State)
+ ALeffectState_IncRef(slot->Effect.State);
oldstate = ATOMIC_EXCHANGE(ALeffectState*, &props->State, slot->Effect.State,
almemory_order_relaxed);
@@ -656,7 +681,8 @@ void UpdateEffectSlotProps(ALeffectslot *slot)
&slot->FreeList, &first, props) == 0);
}
- DELETE_OBJ(oldstate);
+ if(oldstate)
+ ALeffectState_DecRef(oldstate);
}
ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)