diff options
author | Chris Robinson <[email protected]> | 2017-02-13 21:18:18 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2017-02-13 21:18:18 -0800 |
commit | 0d19a209014582f1e77ab3b927dfb1af6c307d66 (patch) | |
tree | 38d5b06d2003a23175522411bfeeffb8fc252f7a | |
parent | 0324712540f88d18f1fa8f18f7a72da06af00d75 (diff) |
Make the source state atomic
Since it's modified by the mixer when playback is ended, a plain struct member
isn't safe.
-rw-r--r-- | Alc/ALc.c | 3 | ||||
-rw-r--r-- | Alc/ALu.c | 10 | ||||
-rw-r--r-- | Alc/mixer.c | 2 | ||||
-rw-r--r-- | OpenAL32/Include/alSource.h | 9 | ||||
-rw-r--r-- | OpenAL32/alSource.c | 46 |
5 files changed, 36 insertions, 34 deletions
@@ -1697,8 +1697,7 @@ void ALCcontext_ProcessUpdates(ALCcontext *context) ALsource *Source = context->SourceMap.values[pos]; ALenum new_state; - if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) && - Source->OffsetType != AL_NONE) + if(Source->OffsetType != AL_NONE && IsPlayingOrPaused(Source)) { WriteLock(&Source->queue_lock); ApplyOffset(Source); @@ -1326,7 +1326,7 @@ static void UpdateContextSources(ALCcontext *ctx, ALeffectslot *slot) for(;voice != voice_end;++voice) { if(!(source=voice->Source)) continue; - if(source->state != AL_PLAYING && source->state != AL_PAUSED) + if(!IsPlayingOrPaused(source)) voice->Source = NULL; else CalcSourceParams(voice, ctx, force); @@ -1449,7 +1449,8 @@ void aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size) { ALboolean IsVoiceInit = (voice->Step > 0); source = voice->Source; - if(source && source->state == AL_PLAYING && IsVoiceInit) + if(IsVoiceInit && source && + ATOMIC_LOAD(&source->state, almemory_order_relaxed) == AL_PLAYING) MixSource(voice, source, device, SamplesToDo); } @@ -1614,12 +1615,13 @@ void aluHandleDisconnect(ALCdevice *device) voice_end = voice + Context->VoiceCount; while(voice != voice_end) { + ALenum playing = AL_PLAYING; ALsource *source = voice->Source; voice->Source = NULL; - if(source && source->state == AL_PLAYING) + if(source && + ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALenum, &source->state, &playing, AL_STOPPED)) { - source->state = AL_STOPPED; ATOMIC_STORE(&source->current_buffer, NULL, almemory_order_relaxed); ATOMIC_STORE(&source->position, 0, almemory_order_relaxed); ATOMIC_STORE(&source->position_fraction, 0, almemory_order_release); diff --git a/Alc/mixer.c b/Alc/mixer.c index 592d51d4..179c028e 100644 --- a/Alc/mixer.c +++ b/Alc/mixer.c @@ -711,7 +711,7 @@ void MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei Samp voice->Moving = AL_TRUE; /* Update source info */ - Source->state = State; + ATOMIC_STORE(&Source->state, State, almemory_order_relaxed); ATOMIC_STORE(&Source->current_buffer, BufferListItem, almemory_order_relaxed); ATOMIC_STORE(&Source->position, DataPosInt, almemory_order_relaxed); ATOMIC_STORE(&Source->position_fraction, DataPosFrac, almemory_order_release); diff --git a/OpenAL32/Include/alSource.h b/OpenAL32/Include/alSource.h index 3111a48a..b9479905 100644 --- a/OpenAL32/Include/alSource.h +++ b/OpenAL32/Include/alSource.h @@ -175,7 +175,7 @@ typedef struct ALsource { ALint SourceType; /** Source state (initial, playing, paused, or stopped) */ - ALenum state; + ATOMIC(ALenum) state; ALenum new_state; /** Source Buffer Queue info. */ @@ -224,6 +224,13 @@ void UpdateAllSourceProps(ALCcontext *context); ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state); ALboolean ApplyOffset(ALsource *Source); +inline ALboolean IsPlayingOrPaused(ALsource *source) +{ + ALenum state = ATOMIC_LOAD_SEQ(&source->state); + return state == AL_PLAYING || state == AL_PAUSED; +} + + ALvoid ReleaseALSources(ALCcontext *Context); #ifdef __cplusplus diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c index c60cd790..edcb49cd 100644 --- a/OpenAL32/alSource.c +++ b/OpenAL32/alSource.c @@ -46,6 +46,7 @@ extern inline void LockSourcesWrite(ALCcontext *context); extern inline void UnlockSourcesWrite(ALCcontext *context); extern inline struct ALsource *LookupSource(ALCcontext *context, ALuint id); extern inline struct ALsource *RemoveSource(ALCcontext *context, ALuint id); +extern inline ALboolean IsPlayingOrPaused(ALsource *source); static void InitSourceParams(ALsource *Source); static void DeinitSource(ALsource *source); @@ -524,7 +525,7 @@ static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SourceProp p Source->OffsetType = prop; Source->Offset = *values; - if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) && + if(IsPlayingOrPaused(Source) && !ATOMIC_LOAD(&Context->DeferUpdates, almemory_order_acquire)) { ALCdevice_Lock(Context->Device); @@ -671,7 +672,7 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p } WriteLock(&Source->queue_lock); - if(!(Source->state == AL_STOPPED || Source->state == AL_INITIAL)) + if(IsPlayingOrPaused(Source)) { WriteUnlock(&Source->queue_lock); UnlockBuffersRead(device); @@ -725,7 +726,7 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p Source->OffsetType = prop; Source->Offset = *values; - if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) && + if(IsPlayingOrPaused(Source) && !ATOMIC_LOAD(&Context->DeferUpdates, almemory_order_acquire)) { ALCdevice_Lock(Context->Device); @@ -843,8 +844,7 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p } UnlockFiltersRead(device); - if(slot != Source->Send[values[1]].Slot && - (Source->state == AL_PLAYING || Source->state == AL_PAUSED)) + if(slot != Source->Send[values[1]].Slot && IsPlayingOrPaused(Source)) { /* Add refcount on the new slot, and release the previous slot */ if(slot) IncrementRef(&slot->ref); @@ -1227,7 +1227,7 @@ static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p return AL_TRUE; case AL_SOURCE_STATE: - *values = Source->state; + *values = ATOMIC_LOAD_SEQ(&Source->state); return AL_TRUE; case AL_BYTE_LENGTH_SOFT: @@ -2767,7 +2767,7 @@ static void InitSourceParams(ALsource *Source) Source->Offset = 0.0; Source->OffsetType = AL_NONE; Source->SourceType = AL_UNDETERMINED; - Source->state = AL_INITIAL; + ATOMIC_INIT(&Source->state, AL_INITIAL); Source->new_state = AL_NONE; ATOMIC_INIT(&Source->queue, NULL); @@ -2926,9 +2926,7 @@ void UpdateAllSourceProps(ALCcontext *context) { ALvoice *voice = &context->Voices[pos]; ALsource *source = voice->Source; - if(source != NULL && (source->state == AL_PLAYING || - source->state == AL_PAUSED) && - source->NeedsUpdate) + if(source != NULL && source->NeedsUpdate && IsPlayingOrPaused(source)) { source->NeedsUpdate = AL_FALSE; UpdateSourceProps(source, num_sends); @@ -2963,19 +2961,15 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) BufferList = BufferList->next; } - if(Source->state != AL_PAUSED) + if(ATOMIC_EXCHANGE(ALenum, &Source->state, AL_PLAYING, almemory_order_acq_rel) == AL_PAUSED) + discontinuity = AL_FALSE; + else { - Source->state = AL_PLAYING; ATOMIC_STORE(&Source->current_buffer, BufferList, almemory_order_relaxed); ATOMIC_STORE(&Source->position, 0, almemory_order_relaxed); ATOMIC_STORE(&Source->position_fraction, 0, almemory_order_release); discontinuity = AL_TRUE; } - else - { - Source->state = AL_PLAYING; - discontinuity = AL_FALSE; - } // Check if an Offset has been set if(Source->OffsetType != AL_NONE) @@ -3041,15 +3035,15 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) } else if(state == AL_PAUSED) { - if(Source->state == AL_PLAYING) - Source->state = AL_PAUSED; + ALenum playing = AL_PLAYING; + ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALenum, &Source->state, &playing, AL_PAUSED); } else if(state == AL_STOPPED) { do_stop: - if(Source->state != AL_INITIAL) + if(ATOMIC_LOAD(&Source->state, almemory_order_acquire) != AL_INITIAL) { - Source->state = AL_STOPPED; + ATOMIC_STORE(&Source->state, AL_STOPPED, almemory_order_relaxed); ATOMIC_STORE_SEQ(&Source->current_buffer, NULL); } Source->OffsetType = AL_NONE; @@ -3057,9 +3051,9 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) } else if(state == AL_INITIAL) { - if(Source->state != AL_INITIAL) + if(ATOMIC_LOAD(&Source->state, almemory_order_acquire) != AL_INITIAL) { - Source->state = AL_INITIAL; + ATOMIC_STORE(&Source->state, AL_INITIAL, almemory_order_relaxed); ATOMIC_STORE(&Source->current_buffer, ATOMIC_LOAD_SEQ(&Source->queue), almemory_order_relaxed); ATOMIC_STORE(&Source->position, 0, almemory_order_relaxed); @@ -3085,7 +3079,7 @@ static ALint64 GetSourceSampleOffset(ALsource *Source, ALCdevice *device, ALuint ALuint refcount; ReadLock(&Source->queue_lock); - if(Source->state != AL_PLAYING && Source->state != AL_PAUSED) + if(!IsPlayingOrPaused(Source)) { ReadUnlock(&Source->queue_lock); do { @@ -3135,7 +3129,7 @@ static ALdouble GetSourceSecOffset(ALsource *Source, ALCdevice *device, ALuint64 ALuint refcount; ReadLock(&Source->queue_lock); - if(Source->state != AL_PLAYING && Source->state != AL_PAUSED) + if(!IsPlayingOrPaused(Source)) { ReadUnlock(&Source->queue_lock); do { @@ -3200,7 +3194,7 @@ static ALdouble GetSourceOffset(ALsource *Source, ALenum name, ALCdevice *device ALuint refcount; ReadLock(&Source->queue_lock); - if(Source->state != AL_PLAYING && Source->state != AL_PAUSED) + if(!IsPlayingOrPaused(Source)) { ReadUnlock(&Source->queue_lock); return 0.0; |