diff options
author | Chris Robinson <[email protected]> | 2020-02-20 23:53:56 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2020-02-20 23:53:56 -0800 |
commit | 9b43327f56649fb46ed0b939ac05ff6c95d1a998 (patch) | |
tree | 9bb10641e2ace1308f8f4a88f81e276c91e76c61 | |
parent | bdb8ef22b02fb278017d95c70d36e6b815533de9 (diff) |
Asynchronously stop and rewind voices
-rw-r--r-- | al/source.cpp | 80 | ||||
-rw-r--r-- | alc/alu.cpp | 5 |
2 files changed, 46 insertions, 39 deletions
diff --git a/al/source.cpp b/al/source.cpp index 60a9a782..2b474e89 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -523,10 +523,16 @@ VoiceChange *GetVoiceChangers(ALCcontext *ctx, size_t count) void SendVoiceChangers(ALCcontext *ctx, VoiceChange *tail) { + ALCdevice *device{ctx->mDevice.get()}; + VoiceChange *oldhead{ctx->mCurrentVoiceChange.load(std::memory_order_acquire)}; while(VoiceChange *next{oldhead->mNext.load(std::memory_order_relaxed)}) oldhead = next; oldhead->mNext.store(tail, std::memory_order_release); + + ALuint refcount; + while(((refcount=device->MixCount.load(std::memory_order_acquire))&1)) + std::this_thread::yield(); } @@ -3009,35 +3015,33 @@ START_API_FUNC ++sources; } - ALCdevice *device{context->mDevice.get()}; - BackendLockGuard __{*device->Backend}; - auto stop_source = [&context](ALsource *source) -> void + VoiceChange *tail{GetVoiceChangers(context.get(), srchandles.size())}; + VoiceChange *cur{tail}; + auto stop_source = [&context,&cur](ALsource *source) -> void { - /* Get the source state before clearing from the voice, so we know what - * state the source+voice was actually in. - */ - ALvoice *voice{GetSourceVoice(source, context.get())}; - const ALenum oldstate{GetSourceState(source, voice)}; - if(voice != nullptr) - { - voice->mCurrentBuffer.store(nullptr, std::memory_order_relaxed); - voice->mLoopBuffer.store(nullptr, std::memory_order_relaxed); - voice->mSourceID.store(0u, std::memory_order_relaxed); - std::atomic_thread_fence(std::memory_order_release); - ALvoice::State oldvstate{ALvoice::Playing}; - voice->mPlayState.compare_exchange_strong(oldvstate, ALvoice::Stopping, - std::memory_order_acq_rel, std::memory_order_acquire); - voice = nullptr; - } - if(oldstate != AL_INITIAL && oldstate != AL_STOPPED) + if(ALvoice *voice{GetSourceVoice(source, context.get())}) { + voice->mPendingStop.store(true, std::memory_order_relaxed); + cur->mVoice = voice; + cur->mSourceID = source->id; + cur->mState = AL_STOPPED; + cur = cur->mNext.load(std::memory_order_relaxed); source->state = AL_STOPPED; - SendStateChangeEvent(context.get(), source->id, AL_STOPPED); } source->OffsetType = AL_NONE; source->Offset = 0.0; + source->VoiceIdx = INVALID_VOICE_IDX; }; std::for_each(srchandles.begin(), srchandles.end(), stop_source); + + while(cur) + { + cur->mVoice = nullptr; + cur->mSourceID = 0; + cur->mState = AL_NONE; + cur = cur->mNext.load(std::memory_order_relaxed); + } + SendVoiceChangers(context.get(), tail); } END_API_FUNC @@ -3077,31 +3081,35 @@ START_API_FUNC ++sources; } - ALCdevice *device{context->mDevice.get()}; - BackendLockGuard __{*device->Backend}; - auto rewind_source = [&context](ALsource *source) -> void + VoiceChange *tail{GetVoiceChangers(context.get(), srchandles.size())}; + VoiceChange *cur{tail}; + auto rewind_source = [&context,&cur](ALsource *source) -> void { ALvoice *voice{GetSourceVoice(source, context.get())}; - if(voice != nullptr) - { - voice->mCurrentBuffer.store(nullptr, std::memory_order_relaxed); - voice->mLoopBuffer.store(nullptr, std::memory_order_relaxed); - voice->mSourceID.store(0u, std::memory_order_relaxed); - std::atomic_thread_fence(std::memory_order_release); - ALvoice::State oldvstate{ALvoice::Playing}; - voice->mPlayState.compare_exchange_strong(oldvstate, ALvoice::Stopping, - std::memory_order_acq_rel, std::memory_order_acquire); - voice = nullptr; - } if(source->state != AL_INITIAL) { + if(voice != nullptr) + voice->mPendingStop.store(true, std::memory_order_relaxed); + cur->mVoice = voice; + cur->mSourceID = source->id; + cur->mState = AL_INITIAL; + cur = cur->mNext.load(std::memory_order_relaxed); source->state = AL_INITIAL; - SendStateChangeEvent(context.get(), source->id, AL_INITIAL); } source->OffsetType = AL_NONE; source->Offset = 0.0; + source->VoiceIdx = INVALID_VOICE_IDX; }; std::for_each(srchandles.begin(), srchandles.end(), rewind_source); + + while(cur) + { + cur->mVoice = nullptr; + cur->mSourceID = 0; + cur->mState = AL_NONE; + cur = cur->mNext.load(std::memory_order_relaxed); + } + SendVoiceChangers(context.get(), tail); } END_API_FUNC diff --git a/alc/alu.cpp b/alc/alu.cpp index 748338ab..6d67756c 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -1629,10 +1629,9 @@ void ProcessVoiceChanges(ALCcontext *ctx) cur = next; bool success{false}; - ALvoice *voice{cur->mVoice}; if(cur->mState == AL_INITIAL || cur->mState == AL_STOPPED) { - if(voice) + if(ALvoice *voice{cur->mVoice}) { voice->mCurrentBuffer.store(nullptr, std::memory_order_relaxed); voice->mLoopBuffer.store(nullptr, std::memory_order_relaxed); @@ -1644,7 +1643,7 @@ void ProcessVoiceChanges(ALCcontext *ctx) } success |= (cur->mState == AL_INITIAL); } - if(success && (enabledevt&EventType_SourceStateChange)) + if(success && (enabledevt&EventType_SourceStateChange) && cur->mSourceID != 0) SendSourceStateEvent(ctx, cur->mSourceID, cur->mState); } while((next=cur->mNext.load(std::memory_order_acquire))); ctx->mCurrentVoiceChange.store(cur, std::memory_order_release); |