aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2021-04-15 15:07:14 -0700
committerChris Robinson <[email protected]>2021-04-15 15:17:04 -0700
commit29cf7ebb752e00e116391a1df7a3ed0f49fdd193 (patch)
tree76b90d55cbcbae2bb3c04fc95aaef83161263ecc
parent92148a3a044389863601b8b907bcfc69ff77b869 (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.cpp10
-rw-r--r--al/auxeffectslot.h2
-rw-r--r--al/listener.cpp2
-rw-r--r--al/listener.h5
-rw-r--r--al/source.cpp10
-rw-r--r--al/source.h3
-rw-r--r--al/state.cpp2
-rw-r--r--alc/alc.cpp12
-rw-r--r--alc/alcontext.h2
-rw-r--r--common/atomic.h21
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)