aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2020-02-20 23:53:56 -0800
committerChris Robinson <[email protected]>2020-02-20 23:53:56 -0800
commit9b43327f56649fb46ed0b939ac05ff6c95d1a998 (patch)
tree9bb10641e2ace1308f8f4a88f81e276c91e76c61
parentbdb8ef22b02fb278017d95c70d36e6b815533de9 (diff)
Asynchronously stop and rewind voices
-rw-r--r--al/source.cpp80
-rw-r--r--alc/alu.cpp5
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);