diff options
author | Chris Robinson <[email protected]> | 2021-04-15 15:07:14 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2021-04-15 15:17:04 -0700 |
commit | 29cf7ebb752e00e116391a1df7a3ed0f49fdd193 (patch) | |
tree | 76b90d55cbcbae2bb3c04fc95aaef83161263ecc | |
parent | 92148a3a044389863601b8b907bcfc69ff77b869 (diff) |
Make an inverted atomic flag type and use it
The inverted atomic flag replaces test_and_set+clear with test_and_clear+set,
essentially inverting the flag status. This makes more logical sense for
flagging dirty state, which is less confusing than flagging clean state. The
one caveat is ATOMIC_FLAG_INIT (or default construction in C++20) initializes
the state to true rather than false.
-rw-r--r-- | al/auxeffectslot.cpp | 10 | ||||
-rw-r--r-- | al/auxeffectslot.h | 2 | ||||
-rw-r--r-- | al/listener.cpp | 2 | ||||
-rw-r--r-- | al/listener.h | 5 | ||||
-rw-r--r-- | al/source.cpp | 10 | ||||
-rw-r--r-- | al/source.h | 3 | ||||
-rw-r--r-- | al/state.cpp | 2 | ||||
-rw-r--r-- | alc/alc.cpp | 12 | ||||
-rw-r--r-- | alc/alcontext.h | 2 | ||||
-rw-r--r-- | common/atomic.h | 21 |
10 files changed, 46 insertions, 23 deletions
diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index 4465e54e..7e12a070 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -308,7 +308,7 @@ void FreeEffectSlot(ALCcontext *context, ALeffectslot *slot) && slot->mState == SlotState::Playing) \ slot->updateProps(context.get()); \ else \ - slot->PropsClean.clear(std::memory_order_release); \ + slot->mPropsDirty.set(std::memory_order_release); \ } while(0) } // namespace @@ -460,7 +460,7 @@ START_API_FUNC if(slot->mState == SlotState::Playing) return; - slot->PropsClean.test_and_set(std::memory_order_acq_rel); + slot->mPropsDirty.test_and_clear(std::memory_order_acq_rel); slot->updateProps(context.get()); AddActiveEffectSlots({&slot, 1}, context.get()); @@ -491,7 +491,7 @@ START_API_FUNC if(slot->mState != SlotState::Playing) { - slot->PropsClean.test_and_set(std::memory_order_acq_rel); + slot->mPropsDirty.test_and_clear(std::memory_order_acq_rel); slot->updateProps(context.get()); } slots[i] = slot; @@ -884,7 +884,7 @@ END_API_FUNC ALeffectslot::ALeffectslot() { - PropsClean.test_and_set(std::memory_order_relaxed); + mPropsDirty.test_and_clear(std::memory_order_relaxed); EffectStateFactory *factory{getFactoryByType(EffectSlotType::None)}; assert(factory != nullptr); @@ -1004,7 +1004,7 @@ void UpdateAllEffectSlotProps(ALCcontext *context) usemask &= ~(1_u64 << idx); if(slot->mState != SlotState::Stopped - && !slot->PropsClean.test_and_set(std::memory_order_acq_rel)) + && slot->mPropsDirty.test_and_clear(std::memory_order_acq_rel)) slot->updateProps(context); } } diff --git a/al/auxeffectslot.h b/al/auxeffectslot.h index c1c9703f..8d7e396b 100644 --- a/al/auxeffectslot.h +++ b/al/auxeffectslot.h @@ -40,7 +40,7 @@ struct ALeffectslot { al::intrusive_ptr<EffectState> State; } Effect; - std::atomic_flag PropsClean; + al::atomic_invflag mPropsDirty; SlotState mState{SlotState::Initial}; diff --git a/al/listener.cpp b/al/listener.cpp index 4bbc145c..edc1ed06 100644 --- a/al/listener.cpp +++ b/al/listener.cpp @@ -40,7 +40,7 @@ if(!context->mDeferUpdates.load(std::memory_order_acquire)) \ UpdateListenerProps(context.get()); \ else \ - listener.PropsClean.clear(std::memory_order_release); \ + listener.mPropsDirty.set(std::memory_order_release); \ } while(0) diff --git a/al/listener.h b/al/listener.h index 5f3ce3ec..f3332763 100644 --- a/al/listener.h +++ b/al/listener.h @@ -9,6 +9,7 @@ #include "AL/efx.h" #include "almalloc.h" +#include "atomic.h" struct ALlistener { @@ -19,9 +20,9 @@ struct ALlistener { float Gain{1.0f}; float mMetersPerUnit{AL_DEFAULT_METERS_PER_UNIT}; - std::atomic_flag PropsClean; + al::atomic_invflag mPropsDirty; - ALlistener() { PropsClean.test_and_set(std::memory_order_relaxed); } + ALlistener() { mPropsDirty.test_and_clear(std::memory_order_relaxed); } DISABLE_ALLOC() }; diff --git a/al/source.cpp b/al/source.cpp index 72337d74..218682d8 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -466,7 +466,7 @@ void InitVoice(Voice *voice, ALsource *source, ALbufferQueueItem *BufferList, AL voice->prepare(device); - source->PropsClean.test_and_set(std::memory_order_acq_rel); + source->mPropsDirty.test_and_clear(std::memory_order_acq_rel); UpdateSourceProps(source, voice, context); voice->mSourceID.store(source->id, std::memory_order_release); @@ -1057,7 +1057,7 @@ bool UpdateSourceProps(ALsource *source, ALCcontext *context) if(SourceShouldUpdate(source, context) && (voice=GetSourceVoice(source, context)) != nullptr) UpdateSourceProps(source, voice, context); else - source->PropsClean.clear(std::memory_order_release); + source->mPropsDirty.set(std::memory_order_release); return true; } @@ -1539,7 +1539,7 @@ bool SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp prop, const a */ Voice *voice{GetSourceVoice(Source, Context)}; if(voice) UpdateSourceProps(Source, voice, Context); - else Source->PropsClean.clear(std::memory_order_release); + else Source->mPropsDirty.set(std::memory_order_release); } else { @@ -3386,7 +3386,7 @@ ALsource::ALsource() send.LFReference = HIGHPASSFREQREF; } - PropsClean.test_and_set(std::memory_order_relaxed); + mPropsDirty.test_and_clear(std::memory_order_relaxed); } ALsource::~ALsource() @@ -3413,7 +3413,7 @@ void UpdateAllSourceProps(ALCcontext *context) ALsource *source = sid ? LookupSource(context, sid) : nullptr; if(source && source->VoiceIdx == vidx) { - if(!source->PropsClean.test_and_set(std::memory_order_acq_rel)) + if(!source->mPropsDirty.test_and_clear(std::memory_order_acq_rel)) UpdateSourceProps(source, voice, context); } ++vidx; diff --git a/al/source.h b/al/source.h index 6572864f..4f4832e5 100644 --- a/al/source.h +++ b/al/source.h @@ -16,6 +16,7 @@ #include "almalloc.h" #include "alnumeric.h" #include "alu.h" +#include "atomic.h" #include "math_defs.h" #include "vector.h" #include "voice.h" @@ -109,7 +110,7 @@ struct ALsource { /** Source Buffer Queue head. */ al::deque<ALbufferQueueItem> mQueue; - std::atomic_flag PropsClean; + al::atomic_invflag mPropsDirty; /* Index into the context's Voices array. Lazily updated, only checked and * reset when looking up the voice. diff --git a/al/state.cpp b/al/state.cpp index ae761fb8..e2f164ca 100644 --- a/al/state.cpp +++ b/al/state.cpp @@ -142,7 +142,7 @@ END_API_FUNC if(!context->mDeferUpdates.load(std::memory_order_acquire)) \ UpdateContextProps(context.get()); \ else \ - context->mPropsClean.clear(std::memory_order_release); \ + context->mPropsDirty.set(std::memory_order_release); \ } while(0) diff --git a/alc/alc.cpp b/alc/alc.cpp index a6a12811..267e5fef 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -1557,9 +1557,9 @@ void ALCcontext::processUpdates() /* busy-wait */ } - if(!mPropsClean.test_and_set(std::memory_order_acq_rel)) + if(mPropsDirty.test_and_clear(std::memory_order_acq_rel)) UpdateContextProps(this); - if(!mListener.PropsClean.test_and_set(std::memory_order_acq_rel)) + if(mListener.mPropsDirty.test_and_clear(std::memory_order_acq_rel)) UpdateListenerProps(this); UpdateAllEffectSlotProps(this); UpdateAllSourceProps(this); @@ -2191,7 +2191,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) auto send_begin = source->Send.begin() + static_cast<ptrdiff_t>(num_sends); std::for_each(send_begin, source->Send.end(), clear_send); - source->PropsClean.clear(std::memory_order_release); + source->mPropsDirty.set(std::memory_order_release); } } @@ -2234,9 +2234,9 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) } srclock.unlock(); - context->mPropsClean.test_and_set(std::memory_order_release); + context->mPropsDirty.test_and_clear(std::memory_order_release); UpdateContextProps(context); - context->mListener.PropsClean.test_and_set(std::memory_order_release); + context->mListener.mPropsDirty.test_and_clear(std::memory_order_release); UpdateListenerProps(context); UpdateAllSourceProps(context); } @@ -2348,7 +2348,7 @@ static DeviceRef VerifyDevice(ALCdevice *device) ALCcontext::ALCcontext(al::intrusive_ptr<ALCdevice> device) : mDevice{std::move(device)} { - mPropsClean.test_and_set(std::memory_order_relaxed); + mPropsDirty.test_and_clear(std::memory_order_relaxed); } ALCcontext::~ALCcontext() diff --git a/alc/alcontext.h b/alc/alcontext.h index b1ec0a6b..860b129b 100644 --- a/alc/alcontext.h +++ b/alc/alcontext.h @@ -202,7 +202,7 @@ struct ALCcontext : public al::intrusive_ref<ALCcontext> { al::vector<WetBufferPtr> mWetBuffers; - std::atomic_flag mPropsClean; + al::atomic_invflag mPropsDirty; std::atomic<bool> mDeferUpdates{false}; std::mutex mPropLock; diff --git a/common/atomic.h b/common/atomic.h index 5e9b04c6..d70382ce 100644 --- a/common/atomic.h +++ b/common/atomic.h @@ -2,8 +2,29 @@ #define AL_ATOMIC_H #include <atomic> +#include <utility> +namespace al { + +struct atomic_invflag : protected std::atomic_flag { + atomic_invflag() noexcept = default; + template<typename T> + atomic_invflag(T&& arg) noexcept : std::atomic_flag{std::forward<T>(arg)} { } + + inline bool test_and_clear(std::memory_order m=std::memory_order_seq_cst) noexcept + { return !test_and_set(m); } + inline bool test_and_clear(std::memory_order m=std::memory_order_seq_cst) volatile noexcept + { return !test_and_set(m); } + + inline void set(std::memory_order m=std::memory_order_seq_cst) noexcept + { clear(m); } + inline void set(std::memory_order m=std::memory_order_seq_cst) volatile noexcept + { clear(m); } +}; + +} // namespace al + using RefCount = std::atomic<unsigned int>; inline void InitRef(RefCount &ref, unsigned int value) |