From 859319fa7864ed6a81af1f12c68627ab58bb7a7d Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 3 Dec 2023 14:31:24 -0800 Subject: Replace a global function with a member function --- alc/backends/base.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'alc/backends/base.cpp') diff --git a/alc/backends/base.cpp b/alc/backends/base.cpp index ab3ad028..675d8043 100644 --- a/alc/backends/base.cpp +++ b/alc/backends/base.cpp @@ -50,7 +50,7 @@ ClockLatency BackendBase::getClockLatency() uint refcount; do { refcount = mDevice->waitForMix(); - ret.ClockTime = GetDeviceClockTime(mDevice); + ret.ClockTime = mDevice->getClockTime(); std::atomic_thread_fence(std::memory_order_acquire); } while(refcount != ReadRef(mDevice->MixCount)); -- cgit v1.2.3 From b6a68e8d510610e181d638ff993e327059bd6018 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 3 Dec 2023 23:36:07 -0800 Subject: Remove some unnecessary atomic wrappers --- al/auxeffectslot.cpp | 7 ++++--- al/auxeffectslot.h | 2 +- al/buffer.cpp | 17 +++++++++-------- al/buffer.h | 2 +- al/source.cpp | 5 +++-- alc/alc.cpp | 3 ++- alc/backends/base.cpp | 2 +- alc/backends/pipewire.cpp | 2 +- common/atomic.h | 13 +++++-------- common/intrusive_ptr.h | 2 +- core/context.h | 2 +- core/device.h | 2 +- core/hrtf.cpp | 6 +++--- core/hrtf.h | 2 +- 14 files changed, 34 insertions(+), 33 deletions(-) (limited to 'alc/backends/base.cpp') diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index fb646389..31e9542b 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -370,7 +370,7 @@ FORCE_ALIGN void AL_APIENTRY alDeleteAuxiliaryEffectSlotsDirect(ALCcontext *cont context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslots[0]); return; } - if(ReadRef(slot->ref) != 0) UNLIKELY + if(slot->ref.load(std::memory_order_relaxed) != 0) UNLIKELY { context->setError(AL_INVALID_OPERATION, "Deleting in-use effect slot %u", effectslots[0]); @@ -390,7 +390,7 @@ FORCE_ALIGN void AL_APIENTRY alDeleteAuxiliaryEffectSlotsDirect(ALCcontext *cont context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslots[i]); return; } - if(ReadRef(slot->ref) != 0) UNLIKELY + if(slot->ref.load(std::memory_order_relaxed) != 0) UNLIKELY { context->setError(AL_INVALID_OPERATION, "Deleting in-use effect slot %u", effectslots[i]); @@ -1530,7 +1530,8 @@ void eax_delete_al_effect_slot(ALCcontext& context, ALeffectslot& effect_slot) std::lock_guard effect_slot_lock{context.mEffectSlotLock}; - if(ReadRef(effect_slot.ref) != 0) { + if(effect_slot.ref.load(std::memory_order_relaxed) != 0) + { ERR(EAX_PREFIX "Deleting in-use effect slot %u.\n", effect_slot.id); return; } diff --git a/al/auxeffectslot.h b/al/auxeffectslot.h index 1ad0ffc4..36216022 100644 --- a/al/auxeffectslot.h +++ b/al/auxeffectslot.h @@ -63,7 +63,7 @@ struct ALeffectslot { SlotState mState{SlotState::Initial}; - RefCount ref{0u}; + std::atomic ref{0u}; EffectSlot *mSlot{nullptr}; diff --git a/al/buffer.cpp b/al/buffer.cpp index 7d043036..ae41585f 100644 --- a/al/buffer.cpp +++ b/al/buffer.cpp @@ -286,7 +286,7 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size, const FmtChannels DstChannels, const FmtType DstType, const std::byte *SrcData, ALbitfieldSOFT access) { - if(ReadRef(ALBuf->ref) != 0 || ALBuf->MappedAccess != 0) UNLIKELY + if(ALBuf->ref.load(std::memory_order_relaxed) != 0 || ALBuf->MappedAccess != 0) UNLIKELY return context->setError(AL_INVALID_OPERATION, "Modifying storage for in-use buffer %u", ALBuf->id); @@ -393,7 +393,7 @@ void PrepareCallback(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, const FmtChannels DstChannels, const FmtType DstType, ALBUFFERCALLBACKTYPESOFT callback, void *userptr) { - if(ReadRef(ALBuf->ref) != 0 || ALBuf->MappedAccess != 0) UNLIKELY + if(ALBuf->ref.load(std::memory_order_relaxed) != 0 || ALBuf->MappedAccess != 0) UNLIKELY return context->setError(AL_INVALID_OPERATION, "Modifying callback for in-use buffer %u", ALBuf->id); @@ -445,7 +445,7 @@ void PrepareCallback(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, void PrepareUserPtr(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, const FmtChannels DstChannels, const FmtType DstType, std::byte *sdata, const ALuint sdatalen) { - if(ReadRef(ALBuf->ref) != 0 || ALBuf->MappedAccess != 0) UNLIKELY + if(ALBuf->ref.load(std::memory_order_relaxed) != 0 || ALBuf->MappedAccess != 0) UNLIKELY return context->setError(AL_INVALID_OPERATION, "Modifying storage for in-use buffer %u", ALBuf->id); @@ -711,7 +711,7 @@ FORCE_ALIGN void AL_APIENTRY alDeleteBuffersDirect(ALCcontext *context, ALsizei context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", bid); return false; } - if(ReadRef(ALBuf->ref) != 0) UNLIKELY + if(ALBuf->ref.load(std::memory_order_relaxed) != 0) UNLIKELY { context->setError(AL_INVALID_OPERATION, "Deleting in-use buffer %u", bid); return false; @@ -826,7 +826,8 @@ FORCE_ALIGN void* AL_APIENTRY alMapBufferDirectSOFT(ALCcontext *context, ALuint else { ALbitfieldSOFT unavailable = (albuf->Access^access) & access; - if(ReadRef(albuf->ref) != 0 && !(access&AL_MAP_PERSISTENT_BIT_SOFT)) UNLIKELY + if(albuf->ref.load(std::memory_order_relaxed) != 0 + && !(access&AL_MAP_PERSISTENT_BIT_SOFT)) UNLIKELY context->setError(AL_INVALID_OPERATION, "Mapping in-use buffer %u without persistent mapping", buffer); else if(albuf->MappedAccess != 0) UNLIKELY @@ -1042,7 +1043,7 @@ FORCE_ALIGN void AL_APIENTRY alBufferiDirect(ALCcontext *context, ALuint buffer, break; case AL_AMBISONIC_LAYOUT_SOFT: - if(ReadRef(albuf->ref) != 0) UNLIKELY + if(albuf->ref.load(std::memory_order_relaxed) != 0) UNLIKELY context->setError(AL_INVALID_OPERATION, "Modifying in-use buffer %u's ambisonic layout", buffer); else if(const auto layout = AmbiLayoutFromEnum(value)) @@ -1052,7 +1053,7 @@ FORCE_ALIGN void AL_APIENTRY alBufferiDirect(ALCcontext *context, ALuint buffer, break; case AL_AMBISONIC_SCALING_SOFT: - if(ReadRef(albuf->ref) != 0) UNLIKELY + if(albuf->ref.load(std::memory_order_relaxed) != 0) UNLIKELY context->setError(AL_INVALID_OPERATION, "Modifying in-use buffer %u's ambisonic scaling", buffer); else if(const auto scaling = AmbiScalingFromEnum(value)) @@ -1116,7 +1117,7 @@ FORCE_ALIGN void AL_APIENTRY alBufferivDirect(ALCcontext *context, ALuint buffer else switch(param) { case AL_LOOP_POINTS_SOFT: - if(ReadRef(albuf->ref) != 0) UNLIKELY + if(albuf->ref.load(std::memory_order_relaxed) != 0) UNLIKELY context->setError(AL_INVALID_OPERATION, "Modifying in-use buffer %u's loop points", buffer); else if(values[0] < 0 || values[0] >= values[1] diff --git a/al/buffer.h b/al/buffer.h index f936cf98..cb864aff 100644 --- a/al/buffer.h +++ b/al/buffer.h @@ -43,7 +43,7 @@ struct ALbuffer : public BufferStorage { ALuint mLoopEnd{0u}; /* Number of times buffer was attached to a source (deletion can only occur when 0) */ - RefCount ref{0u}; + std::atomic ref{0u}; /* Self ID */ ALuint id{0}; diff --git a/al/source.cpp b/al/source.cpp index 73a357d4..cb24c09f 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -1604,10 +1604,11 @@ NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, con if(!buffer) UNLIKELY return Context->setError(AL_INVALID_VALUE, "Invalid buffer ID %s", std::to_string(values[0]).c_str()); - if(buffer->MappedAccess && !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT)) UNLIKELY + if(buffer->MappedAccess + && !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT)) UNLIKELY return Context->setError(AL_INVALID_OPERATION, "Setting non-persistently mapped buffer %u", buffer->id); - if(buffer->mCallback && ReadRef(buffer->ref) != 0) UNLIKELY + if(buffer->mCallback && buffer->ref.load(std::memory_order_relaxed) != 0) UNLIKELY return Context->setError(AL_INVALID_OPERATION, "Setting already-set callback buffer %u", buffer->id); diff --git a/alc/alc.cpp b/alc/alc.cpp index ab4cc7ba..d974777b 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -2514,7 +2514,8 @@ ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, refcount = dev->waitForMix(); basecount = dev->mClockBase.load(std::memory_order_relaxed); samplecount = dev->mSamplesDone.load(std::memory_order_relaxed); - } while(refcount != ReadRef(dev->MixCount)); + std::atomic_thread_fence(std::memory_order_acquire); + } while(refcount != dev->MixCount.load(std::memory_order_relaxed)); basecount += nanoseconds{seconds{samplecount}} / dev->Frequency; *values = basecount.count(); } diff --git a/alc/backends/base.cpp b/alc/backends/base.cpp index 675d8043..b2b567a6 100644 --- a/alc/backends/base.cpp +++ b/alc/backends/base.cpp @@ -52,7 +52,7 @@ ClockLatency BackendBase::getClockLatency() refcount = mDevice->waitForMix(); ret.ClockTime = mDevice->getClockTime(); std::atomic_thread_fence(std::memory_order_acquire); - } while(refcount != ReadRef(mDevice->MixCount)); + } while(refcount != mDevice->MixCount.load(std::memory_order_relaxed)); /* NOTE: The device will generally have about all but one periods filled at * any given time during playback. Without a more accurate measurement from diff --git a/alc/backends/pipewire.cpp b/alc/backends/pipewire.cpp index e2f32758..754feb6c 100644 --- a/alc/backends/pipewire.cpp +++ b/alc/backends/pipewire.cpp @@ -1827,7 +1827,7 @@ ClockLatency PipeWirePlayback::getClockLatency() mixtime = mDevice->getClockTime(); clock_gettime(CLOCK_MONOTONIC, &tspec); std::atomic_thread_fence(std::memory_order_acquire); - } while(refcount != ReadRef(mDevice->MixCount)); + } while(refcount != mDevice->MixCount.load(std::memory_order_relaxed)); /* Convert the monotonic clock, stream ticks, and stream delay to * nanoseconds. diff --git a/common/atomic.h b/common/atomic.h index 5e9b04c6..a579dcab 100644 --- a/common/atomic.h +++ b/common/atomic.h @@ -4,15 +4,12 @@ #include -using RefCount = std::atomic; - -inline void InitRef(RefCount &ref, unsigned int value) -{ ref.store(value, std::memory_order_relaxed); } -inline unsigned int ReadRef(RefCount &ref) -{ return ref.load(std::memory_order_acquire); } -inline unsigned int IncrementRef(RefCount &ref) +template +auto IncrementRef(std::atomic &ref) noexcept { return ref.fetch_add(1u, std::memory_order_acq_rel)+1u; } -inline unsigned int DecrementRef(RefCount &ref) + +template +auto DecrementRef(std::atomic &ref) noexcept { return ref.fetch_sub(1u, std::memory_order_acq_rel)-1u; } diff --git a/common/intrusive_ptr.h b/common/intrusive_ptr.h index 27075347..714a5617 100644 --- a/common/intrusive_ptr.h +++ b/common/intrusive_ptr.h @@ -11,7 +11,7 @@ namespace al { template class intrusive_ref { - RefCount mRef{1u}; + std::atomic mRef{1u}; public: unsigned int add_ref() noexcept { return IncrementRef(mRef); } diff --git a/core/context.h b/core/context.h index ccb7dd3b..6f65663f 100644 --- a/core/context.h +++ b/core/context.h @@ -85,7 +85,7 @@ struct ContextBase { /* Counter for the pre-mixing updates, in 31.1 fixed point (lowest bit * indicates if updates are currently happening). */ - RefCount mUpdateCount{0u}; + std::atomic mUpdateCount{0u}; std::atomic mHoldUpdates{false}; std::atomic mStopVoicesOnDisconnect{true}; diff --git a/core/device.h b/core/device.h index 842f1d82..1f3c5105 100644 --- a/core/device.h +++ b/core/device.h @@ -284,7 +284,7 @@ struct DeviceBase { * the end, so the bottom bit indicates if the device is currently mixing * and the upper bits indicates how many mixes have been done. */ - RefCount MixCount{0u}; + std::atomic MixCount{0u}; // Contexts created on this device std::atomic*> mContexts{nullptr}; diff --git a/core/hrtf.cpp b/core/hrtf.cpp index 9a13a004..1b7da3f9 100644 --- a/core/hrtf.cpp +++ b/core/hrtf.cpp @@ -392,7 +392,7 @@ std::unique_ptr CreateHrtfStore(uint rate, uint8_t irSize, if(void *ptr{al_calloc(16, total)}) { Hrtf.reset(al::construct_at(static_cast(ptr))); - InitRef(Hrtf->mRef, 1u); + Hrtf->mRef.store(1u, std::memory_order_relaxed); Hrtf->mSampleRate = rate & 0xff'ff'ff; Hrtf->mIrSize = irSize; @@ -1459,9 +1459,9 @@ void HrtfStore::dec_ref() auto remove_unused = [](LoadedHrtf &hrtf) -> bool { HrtfStore *entry{hrtf.mEntry.get()}; - if(entry && ReadRef(entry->mRef) == 0) + if(entry && entry->mRef.load() == 0) { - TRACE("Unloading unused HRTF %s\n", hrtf.mFilename.data()); + TRACE("Unloading unused HRTF %s\n", hrtf.mFilename.c_str()); hrtf.mEntry = nullptr; return true; } diff --git a/core/hrtf.h b/core/hrtf.h index 5e6e09a8..50c4f450 100644 --- a/core/hrtf.h +++ b/core/hrtf.h @@ -18,7 +18,7 @@ struct HrtfStore { - RefCount mRef; + std::atomic mRef; uint mSampleRate : 24; uint mIrSize : 8; -- cgit v1.2.3 From e123e7bbda4330559ef03a5362bc93064eb87e4e Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 4 Dec 2023 01:18:49 -0800 Subject: Use RAII to handle writing under the mixer seqlock --- al/source.cpp | 6 +++--- alc/alc.cpp | 8 ++------ alc/alu.cpp | 28 +++++++++------------------- alc/backends/base.cpp | 2 +- alc/backends/pipewire.cpp | 2 +- core/device.h | 28 ++++++++++++++++++++++++++-- 6 files changed, 42 insertions(+), 32 deletions(-) (limited to 'alc/backends/base.cpp') diff --git a/al/source.cpp b/al/source.cpp index cb24c09f..c9ec8f21 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -212,7 +212,7 @@ int64_t GetSourceSampleOffset(ALsource *Source, ALCcontext *context, nanoseconds readPos += voice->mPositionFrac.load(std::memory_order_relaxed); } std::atomic_thread_fence(std::memory_order_acquire); - } while(refcount != device->MixCount.load(std::memory_order_relaxed)); + } while(refcount != device->mMixCount.load(std::memory_order_relaxed)); if(!voice) return 0; @@ -252,7 +252,7 @@ double GetSourceSecOffset(ALsource *Source, ALCcontext *context, nanoseconds *cl readPos += voice->mPositionFrac.load(std::memory_order_relaxed); } std::atomic_thread_fence(std::memory_order_acquire); - } while(refcount != device->MixCount.load(std::memory_order_relaxed)); + } while(refcount != device->mMixCount.load(std::memory_order_relaxed)); if(!voice) return 0.0f; @@ -302,7 +302,7 @@ NOINLINE T GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *context) readPosFrac = voice->mPositionFrac.load(std::memory_order_relaxed); } std::atomic_thread_fence(std::memory_order_acquire); - } while(refcount != device->MixCount.load(std::memory_order_relaxed)); + } while(refcount != device->mMixCount.load(std::memory_order_relaxed)); if(!voice) return T{0}; diff --git a/alc/alc.cpp b/alc/alc.cpp index d974777b..9a919032 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -976,9 +976,7 @@ std::unique_ptr CreateDeviceLimiter(const ALCdevice *device, const f */ inline void UpdateClockBase(ALCdevice *device) { - const auto mixCount = device->MixCount.load(std::memory_order_relaxed); - device->MixCount.store(mixCount+1, std::memory_order_relaxed); - std::atomic_thread_fence(std::memory_order_release); + const auto mixLock = device->getWriteMixLock(); auto samplesDone = device->mSamplesDone.load(std::memory_order_relaxed); auto clockBase = device->mClockBase.load(std::memory_order_relaxed); @@ -986,8 +984,6 @@ inline void UpdateClockBase(ALCdevice *device) clockBase += nanoseconds{seconds{samplesDone}} / device->Frequency; device->mClockBase.store(clockBase, std::memory_order_relaxed); device->mSamplesDone.store(0, std::memory_order_relaxed); - - device->MixCount.store(mixCount+2, std::memory_order_release); } /** @@ -2515,7 +2511,7 @@ ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, basecount = dev->mClockBase.load(std::memory_order_relaxed); samplecount = dev->mSamplesDone.load(std::memory_order_relaxed); std::atomic_thread_fence(std::memory_order_acquire); - } while(refcount != dev->MixCount.load(std::memory_order_relaxed)); + } while(refcount != dev->mMixCount.load(std::memory_order_relaxed)); basecount += nanoseconds{seconds{samplecount}} / dev->Frequency; *values = basecount.count(); } diff --git a/alc/alu.cpp b/alc/alu.cpp index 23518fa9..2bc648bf 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -2135,19 +2135,16 @@ uint DeviceBase::renderSamples(const uint numSamples) for(FloatBufferLine &buffer : MixBuffer) buffer.fill(0.0f); - /* Increment the mix count at the start (lsb should now be 1). */ - const auto mixCount = MixCount.load(std::memory_order_relaxed); - MixCount.store(mixCount+1, std::memory_order_relaxed); - std::atomic_thread_fence(std::memory_order_release); + { + const auto mixLock = getWriteMixLock(); - /* Process and mix each context's sources and effects. */ - ProcessContexts(this, samplesToDo); + /* Process and mix each context's sources and effects. */ + ProcessContexts(this, samplesToDo); - /* Increment the clock time. Every second's worth of samples is converted - * and added to clock base so that large sample counts don't overflow - * during conversion. This also guarantees a stable conversion. - */ - { + /* Every second's worth of samples is converted and added to clock base + * so that large sample counts don't overflow during conversion. This + * also guarantees a stable conversion. + */ auto samplesDone = mSamplesDone.load(std::memory_order_relaxed) + samplesToDo; auto clockBase = mClockBase.load(std::memory_order_relaxed) + std::chrono::seconds{samplesDone/Frequency}; @@ -2155,9 +2152,6 @@ uint DeviceBase::renderSamples(const uint numSamples) mClockBase.store(clockBase, std::memory_order_relaxed); } - /* Increment the mix count at the end (lsb should now be 0). */ - MixCount.store(mixCount+2, std::memory_order_release); - /* Apply any needed post-process for finalizing the Dry mix to the RealOut * (Ambisonic decode, UHJ encode, etc). */ @@ -2232,9 +2226,7 @@ void DeviceBase::renderSamples(void *outBuffer, const uint numSamples, const siz void DeviceBase::handleDisconnect(const char *msg, ...) { - const auto mixCount = MixCount.load(std::memory_order_relaxed); - MixCount.store(mixCount+1, std::memory_order_relaxed); - std::atomic_thread_fence(std::memory_order_release); + const auto mixLock = getWriteMixLock(); if(Connected.exchange(false, std::memory_order_acq_rel)) { @@ -2277,6 +2269,4 @@ void DeviceBase::handleDisconnect(const char *msg, ...) std::for_each(voicelist.begin(), voicelist.end(), stop_voice); } } - - MixCount.store(mixCount+2, std::memory_order_release); } diff --git a/alc/backends/base.cpp b/alc/backends/base.cpp index b2b567a6..1677ae19 100644 --- a/alc/backends/base.cpp +++ b/alc/backends/base.cpp @@ -52,7 +52,7 @@ ClockLatency BackendBase::getClockLatency() refcount = mDevice->waitForMix(); ret.ClockTime = mDevice->getClockTime(); std::atomic_thread_fence(std::memory_order_acquire); - } while(refcount != mDevice->MixCount.load(std::memory_order_relaxed)); + } while(refcount != mDevice->mMixCount.load(std::memory_order_relaxed)); /* NOTE: The device will generally have about all but one periods filled at * any given time during playback. Without a more accurate measurement from diff --git a/alc/backends/pipewire.cpp b/alc/backends/pipewire.cpp index 754feb6c..adf9d62a 100644 --- a/alc/backends/pipewire.cpp +++ b/alc/backends/pipewire.cpp @@ -1827,7 +1827,7 @@ ClockLatency PipeWirePlayback::getClockLatency() mixtime = mDevice->getClockTime(); clock_gettime(CLOCK_MONOTONIC, &tspec); std::atomic_thread_fence(std::memory_order_acquire); - } while(refcount != mDevice->MixCount.load(std::memory_order_relaxed)); + } while(refcount != mDevice->mMixCount.load(std::memory_order_relaxed)); /* Convert the monotonic clock, stream ticks, and stream delay to * nanoseconds. diff --git a/core/device.h b/core/device.h index 1f3c5105..1ac01ba6 100644 --- a/core/device.h +++ b/core/device.h @@ -284,7 +284,7 @@ struct DeviceBase { * the end, so the bottom bit indicates if the device is currently mixing * and the upper bits indicates how many mixes have been done. */ - std::atomic MixCount{0u}; + std::atomic mMixCount{0u}; // Contexts created on this device std::atomic*> mContexts{nullptr}; @@ -299,10 +299,34 @@ struct DeviceBase { uint channelsFromFmt() const noexcept { return ChannelsFromDevFmt(FmtChans, mAmbiOrder); } uint frameSizeFromFmt() const noexcept { return bytesFromFmt() * channelsFromFmt(); } + struct MixLock { + std::atomic &mCount; + const uint mLastVal; + + MixLock(std::atomic &count, const uint last_val) noexcept + : mCount{count}, mLastVal{last_val} + { } + /* Increment the mix count when the lock goes out of scope to "release" + * it (lsb should be 0). + */ + ~MixLock() { mCount.store(mLastVal+2, std::memory_order_release); } + }; + auto getWriteMixLock() noexcept + { + /* Increment the mix count at the start of mixing and writing clock + * info (lsb should be 1). + */ + const auto mixCount = mMixCount.load(std::memory_order_relaxed); + mMixCount.store(mixCount+1, std::memory_order_relaxed); + std::atomic_thread_fence(std::memory_order_release); + return MixLock{mMixCount, mixCount}; + } + + /** Waits for the mixer to not be mixing or updating the clock. */ uint waitForMix() const noexcept { uint refcount; - while((refcount=MixCount.load(std::memory_order_acquire))&1) { + while((refcount=mMixCount.load(std::memory_order_acquire))&1) { } return refcount; } -- cgit v1.2.3 From aeb53616757302bd57ce39a13d293db3374276b5 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 21 Dec 2023 22:09:34 -0800 Subject: Remove an unnecessary std::max --- alc/backends/base.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'alc/backends/base.cpp') diff --git a/alc/backends/base.cpp b/alc/backends/base.cpp index 1677ae19..b287b6d9 100644 --- a/alc/backends/base.cpp +++ b/alc/backends/base.cpp @@ -45,7 +45,7 @@ uint BackendBase::availableSamples() ClockLatency BackendBase::getClockLatency() { - ClockLatency ret; + ClockLatency ret{}; uint refcount; do { @@ -58,8 +58,7 @@ ClockLatency BackendBase::getClockLatency() * any given time during playback. Without a more accurate measurement from * the output, this is an okay approximation. */ - ret.Latency = std::max(std::chrono::seconds{mDevice->BufferSize-mDevice->UpdateSize}, - std::chrono::seconds::zero()); + ret.Latency = std::chrono::seconds{mDevice->BufferSize - mDevice->UpdateSize}; ret.Latency /= mDevice->Frequency; return ret; -- cgit v1.2.3