diff options
author | Chris Robinson <[email protected]> | 2024-01-03 14:12:28 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2024-01-03 14:12:28 -0800 |
commit | ed98cbefd014a5166ec086fd276eb283cdab22aa (patch) | |
tree | 321f7efe504a010572c15277114883cc72cced34 | |
parent | f8604758bc7cc43efa52a305a578ee9cf474f0d6 (diff) |
Allocate context property updates in clusters
-rw-r--r-- | al/state.cpp | 16 | ||||
-rw-r--r-- | core/context.cpp | 36 | ||||
-rw-r--r-- | core/context.h | 7 |
3 files changed, 37 insertions, 22 deletions
diff --git a/al/state.cpp b/al/state.cpp index d9c199d5..c1e3d593 100644 --- a/al/state.cpp +++ b/al/state.cpp @@ -643,18 +643,18 @@ AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value) noexcept void UpdateContextProps(ALCcontext *context) { - /* Get an unused proprty container, or allocate a new one as needed. */ + /* Get an unused property container, or allocate a new one as needed. */ ContextProps *props{context->mFreeContextProps.load(std::memory_order_acquire)}; if(!props) - props = new ContextProps{}; - else { - ContextProps *next; - do { - next = props->next.load(std::memory_order_relaxed); - } while(context->mFreeContextProps.compare_exchange_weak(props, next, - std::memory_order_seq_cst, std::memory_order_acquire) == 0); + context->allocContextProps(); + props = context->mFreeContextProps.load(std::memory_order_acquire); } + ContextProps *next; + do { + next = props->next.load(std::memory_order_relaxed); + } while(context->mFreeContextProps.compare_exchange_weak(props, next, + std::memory_order_acq_rel, std::memory_order_acquire) == false); /* Copy in current property values. */ ALlistener &listener = context->mListener; diff --git a/core/context.cpp b/core/context.cpp index 46f703a9..0fe50d25 100644 --- a/core/context.cpp +++ b/core/context.cpp @@ -27,19 +27,6 @@ ContextBase::ContextBase(DeviceBase *device) : mDevice{device} ContextBase::~ContextBase() { - size_t count{0}; - ContextProps *cprops{mParams.ContextUpdate.exchange(nullptr, std::memory_order_relaxed)}; - if(std::unique_ptr<ContextProps> old{cprops}) - ++count; - - cprops = mFreeContextProps.exchange(nullptr, std::memory_order_acquire); - while(std::unique_ptr<ContextProps> old{cprops}) - { - cprops = old->next.load(std::memory_order_relaxed); - ++count; - } - TRACE("Freed %zu context property object%s\n", count, (count==1)?"":"s"); - if(std::unique_ptr<EffectSlotArray> curarray{mActiveAuxSlots.exchange(nullptr, std::memory_order_relaxed)}) std::destroy_n(curarray->end(), curarray->size()); @@ -47,7 +34,7 @@ ContextBase::~ContextBase() if(mAsyncEvents) { - count = 0; + size_t count{0}; auto evt_vec = mAsyncEvents->getReadVector(); if(evt_vec.first.len > 0) { @@ -177,3 +164,24 @@ EffectSlot *ContextBase::getEffectSlot() mEffectSlotClusters.emplace_back(std::move(clusterptr)); return mEffectSlotClusters.back()->data(); } + + +void ContextBase::allocContextProps() +{ + static constexpr size_t clustersize{std::tuple_size_v<ContextPropsCluster::element_type>}; + + TRACE("Increasing allocated context properties to %zu\n", + (mContextPropClusters.size()+1) * clustersize); + + auto clusterptr = std::make_unique<ContextPropsCluster::element_type>(); + auto cluster = al::span{*clusterptr}; + for(size_t i{1};i < clustersize;++i) + cluster[i-1].next.store(std::addressof(cluster[i]), std::memory_order_relaxed); + auto *newcluster = mContextPropClusters.emplace_back(std::move(clusterptr)).get(); + + ContextProps *oldhead{mFreeContextProps.load(std::memory_order_acquire)}; + do { + newcluster->back().next.store(oldhead, std::memory_order_relaxed); + } while(mFreeContextProps.compare_exchange_weak(oldhead, newcluster->data(), + std::memory_order_acq_rel, std::memory_order_acquire) == false); +} diff --git a/core/context.h b/core/context.h index 16d1b415..980514b3 100644 --- a/core/context.h +++ b/core/context.h @@ -108,6 +108,7 @@ struct ContextBase { void allocVoiceChanges(); void allocVoiceProps(); void allocEffectSlotProps(); + void allocContextProps(); ContextParams mParams; @@ -160,6 +161,12 @@ struct ContextBase { using EffectSlotPropsCluster = std::unique_ptr<std::array<EffectSlotProps,4>>; std::vector<EffectSlotPropsCluster> mEffectSlotPropClusters; + /* This could be greater than 2, but there should be no way there can be + * more than two context property updates in use simultaneously. + */ + using ContextPropsCluster = std::unique_ptr<std::array<ContextProps,2>>; + std::vector<ContextPropsCluster> mContextPropClusters; + ContextBase(DeviceBase *device); ContextBase(const ContextBase&) = delete; |