diff options
author | Chris Robinson <[email protected]> | 2022-12-16 18:41:47 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2022-12-16 18:41:47 -0800 |
commit | d281ffa9ce3abd8dfd5afd72914acebe4a4a92ff (patch) | |
tree | 59612d00cc9efa076c3565a743eab93378532326 /core | |
parent | 84cfef8513b88068e8ef66223d09b6c48d35caad (diff) |
Use a bitset for the enabled event flags
Diffstat (limited to 'core')
-rw-r--r-- | core/async_event.h | 20 | ||||
-rw-r--r-- | core/context.cpp | 7 | ||||
-rw-r--r-- | core/context.h | 5 | ||||
-rw-r--r-- | core/voice.cpp | 6 |
4 files changed, 23 insertions, 15 deletions
diff --git a/core/async_event.h b/core/async_event.h index 750f38c9..5a2f5f91 100644 --- a/core/async_event.h +++ b/core/async_event.h @@ -10,16 +10,17 @@ using uint = unsigned int; struct AsyncEvent { enum : uint { - /* End event thread processing. */ - KillThread = 0, - /* User event types. */ - SourceStateChange = 1<<0, - BufferCompleted = 1<<1, - Disconnected = 1<<2, + SourceStateChange, + BufferCompleted, + Disconnected, + UserEventCount, - /* Internal events. */ - ReleaseEffectState = 65536, + /* Internal events, always processed. */ + ReleaseEffectState = 128, + + /* End event thread processing. */ + KillThread, }; enum class SrcState { @@ -29,7 +30,7 @@ struct AsyncEvent { Pause }; - uint EnumType{0u}; + const uint EnumType; union { char dummy; struct { @@ -46,7 +47,6 @@ struct AsyncEvent { EffectState *mEffectState; } u{}; - AsyncEvent() noexcept = default; constexpr AsyncEvent(uint type) noexcept : EnumType{type} { } DISABLE_ALLOC() diff --git a/core/context.cpp b/core/context.cpp index 111802d9..d68d8327 100644 --- a/core/context.cpp +++ b/core/context.cpp @@ -1,6 +1,7 @@ #include "config.h" +#include <cassert> #include <memory> #include "async_event.h" @@ -13,8 +14,12 @@ #include "voice_change.h" +#ifdef __cpp_lib_atomic_is_always_lock_free +static_assert(std::atomic<ContextBase::AsyncEventBitset>::is_always_lock_free, "atomic<bitset> isn't lock-free"); +#endif + ContextBase::ContextBase(DeviceBase *device) : mDevice{device} -{ } +{ assert(mEnabledEvts.is_lock_free()); } ContextBase::~ContextBase() { diff --git a/core/context.h b/core/context.h index 4e3ea195..9723eac3 100644 --- a/core/context.h +++ b/core/context.h @@ -3,12 +3,14 @@ #include <array> #include <atomic> +#include <bitset> #include <cstddef> #include <memory> #include <thread> #include "almalloc.h" #include "alspan.h" +#include "async_event.h" #include "atomic.h" #include "bufferline.h" #include "threads.h" @@ -135,7 +137,8 @@ struct ContextBase { std::thread mEventThread; al::semaphore mEventSem; std::unique_ptr<RingBuffer> mAsyncEvents; - std::atomic<uint> mEnabledEvts{0u}; + using AsyncEventBitset = std::bitset<AsyncEvent::UserEventCount>; + std::atomic<AsyncEventBitset> mEnabledEvts{0u}; /* Asynchronous voice change actions are processed as a linked list of * VoiceChange objects by the mixer, which is atomically appended to. diff --git a/core/voice.cpp b/core/voice.cpp index c8810c36..eab8f851 100644 --- a/core/voice.cpp +++ b/core/voice.cpp @@ -849,8 +849,8 @@ void Voice::mix(const State vstate, ContextBase *Context, const nanoseconds devi std::atomic_thread_fence(std::memory_order_release); /* Send any events now, after the position/buffer info was updated. */ - const uint enabledevt{Context->mEnabledEvts.load(std::memory_order_acquire)}; - if(buffers_done > 0 && (enabledevt&AsyncEvent::BufferCompleted)) + const auto enabledevt = Context->mEnabledEvts.load(std::memory_order_acquire); + if(buffers_done > 0 && enabledevt.test(AsyncEvent::BufferCompleted)) { RingBuffer *ring{Context->mAsyncEvents.get()}; auto evt_vec = ring->getWriteVector(); @@ -870,7 +870,7 @@ void Voice::mix(const State vstate, ContextBase *Context, const nanoseconds devi * ensures any residual noise fades to 0 amplitude. */ mPlayState.store(Stopping, std::memory_order_release); - if((enabledevt&AsyncEvent::SourceStateChange)) + if(enabledevt.test(AsyncEvent::SourceStateChange)) SendSourceStoppedEvent(Context, SourceID); } } |