diff options
-rw-r--r-- | al/event.cpp | 23 | ||||
-rw-r--r-- | alc/alu.cpp | 7 | ||||
-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 |
6 files changed, 35 insertions, 33 deletions
diff --git a/al/event.cpp b/al/event.cpp index 8765e79b..19509d2f 100644 --- a/al/event.cpp +++ b/al/event.cpp @@ -63,13 +63,12 @@ static int EventThread(ALCcontext *context) continue; } - uint enabledevts{context->mEnabledEvts.load(std::memory_order_acquire)}; - if(!context->mEventCb) continue; + auto enabledevts = context->mEnabledEvts.load(std::memory_order_acquire); + if(!context->mEventCb || !enabledevts.test(evt.EnumType)) + continue; if(evt.EnumType == AsyncEvent::SourceStateChange) { - if(!(enabledevts&AsyncEvent::SourceStateChange)) - continue; ALuint state{}; std::string msg{"Source ID " + std::to_string(evt.u.srcstate.id)}; msg += " state has changed to "; @@ -97,8 +96,6 @@ static int EventThread(ALCcontext *context) } else if(evt.EnumType == AsyncEvent::BufferCompleted) { - if(!(enabledevts&AsyncEvent::BufferCompleted)) - continue; std::string msg{std::to_string(evt.u.bufcomp.count)}; if(evt.u.bufcomp.count == 1) msg += " buffer completed"; else msg += " buffers completed"; @@ -108,8 +105,6 @@ static int EventThread(ALCcontext *context) } else if(evt.EnumType == AsyncEvent::Disconnected) { - if(!(enabledevts&AsyncEvent::Disconnected)) - continue; context->mEventCb(AL_EVENT_TYPE_DISCONNECTED_SOFT, 0, 0, static_cast<ALsizei>(strlen(evt.u.disconnect.msg)), evt.u.disconnect.msg, context->mEventParam); @@ -161,17 +156,17 @@ START_API_FUNC if(count <= 0) return; if(!types) SETERR_RETURN(context, AL_INVALID_VALUE,, "NULL pointer"); - uint flags{0}; + ContextBase::AsyncEventBitset flags{}; const ALenum *types_end = types+count; auto bad_type = std::find_if_not(types, types_end, [&flags](ALenum type) noexcept -> bool { if(type == AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT) - flags |= AsyncEvent::BufferCompleted; + flags.set(AsyncEvent::BufferCompleted); else if(type == AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT) - flags |= AsyncEvent::SourceStateChange; + flags.set(AsyncEvent::SourceStateChange); else if(type == AL_EVENT_TYPE_DISCONNECTED_SOFT) - flags |= AsyncEvent::Disconnected; + flags.set(AsyncEvent::Disconnected); else return false; return true; @@ -182,7 +177,7 @@ START_API_FUNC if(enable) { - uint enabledevts{context->mEnabledEvts.load(std::memory_order_relaxed)}; + auto enabledevts = context->mEnabledEvts.load(std::memory_order_relaxed); while(context->mEnabledEvts.compare_exchange_weak(enabledevts, enabledevts|flags, std::memory_order_acq_rel, std::memory_order_acquire) == 0) { @@ -193,7 +188,7 @@ START_API_FUNC } else { - uint enabledevts{context->mEnabledEvts.load(std::memory_order_relaxed)}; + auto enabledevts = context->mEnabledEvts.load(std::memory_order_relaxed); while(context->mEnabledEvts.compare_exchange_weak(enabledevts, enabledevts&~flags, std::memory_order_acq_rel, std::memory_order_acquire) == 0) { diff --git a/alc/alu.cpp b/alc/alu.cpp index fdb51f78..a9bb5298 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -1726,7 +1726,7 @@ void ProcessVoiceChanges(ContextBase *ctx) VoiceChange *next{cur->mNext.load(std::memory_order_acquire)}; if(!next) return; - const uint enabledevt{ctx->mEnabledEvts.load(std::memory_order_acquire)}; + const auto enabledevt = ctx->mEnabledEvts.load(std::memory_order_acquire); do { cur = next; @@ -1807,7 +1807,7 @@ void ProcessVoiceChanges(ContextBase *ctx) } oldvoice->mPendingChange.store(false, std::memory_order_release); } - if(sendevt && (enabledevt&AsyncEvent::SourceStateChange)) + if(sendevt && enabledevt.test(AsyncEvent::SourceStateChange)) SendSourceStateEvent(ctx, cur->mSourceID, cur->mState); next = cur->mNext.load(std::memory_order_acquire); @@ -2172,8 +2172,7 @@ void DeviceBase::handleDisconnect(const char *msg, ...) for(ContextBase *ctx : *mContexts.load()) { - const uint enabledevt{ctx->mEnabledEvts.load(std::memory_order_acquire)}; - if((enabledevt&AsyncEvent::Disconnected)) + if(ctx->mEnabledEvts.load(std::memory_order_acquire).test(AsyncEvent::Disconnected)) { RingBuffer *ring{ctx->mAsyncEvents.get()}; auto evt_data = ring->getWriteVector().first; 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); } } |