aboutsummaryrefslogtreecommitdiffstats
path: root/core/device.h
diff options
context:
space:
mode:
Diffstat (limited to 'core/device.h')
-rw-r--r--core/device.h28
1 files changed, 26 insertions, 2 deletions
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<uint> MixCount{0u};
+ std::atomic<uint> mMixCount{0u};
// Contexts created on this device
std::atomic<al::FlexArray<ContextBase*>*> 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<uint> &mCount;
+ const uint mLastVal;
+
+ MixLock(std::atomic<uint> &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;
}