aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2022-12-16 18:41:47 -0800
committerChris Robinson <[email protected]>2022-12-16 18:41:47 -0800
commitd281ffa9ce3abd8dfd5afd72914acebe4a4a92ff (patch)
tree59612d00cc9efa076c3565a743eab93378532326
parent84cfef8513b88068e8ef66223d09b6c48d35caad (diff)
Use a bitset for the enabled event flags
-rw-r--r--al/event.cpp23
-rw-r--r--alc/alu.cpp7
-rw-r--r--core/async_event.h20
-rw-r--r--core/context.cpp7
-rw-r--r--core/context.h5
-rw-r--r--core/voice.cpp6
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);
}
}