diff options
author | Chris Robinson <[email protected]> | 2023-12-08 11:53:51 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2023-12-08 11:53:51 -0800 |
commit | 112ad405df27b5a20d7a578321b592be2d4d8eaf (patch) | |
tree | a3401c88cdcd70dee030697cec885adfc6330d57 /core | |
parent | 040c172cdf186c9ccfb0642aa9ac598f115bb46b (diff) |
Use a fixed array for fixed-size clusters
Diffstat (limited to 'core')
-rw-r--r-- | core/context.cpp | 75 | ||||
-rw-r--r-- | core/context.h | 9 |
2 files changed, 45 insertions, 39 deletions
diff --git a/core/context.cpp b/core/context.cpp index bd7bb006..1640fbdc 100644 --- a/core/context.cpp +++ b/core/context.cpp @@ -2,6 +2,7 @@ #include "config.h" #include <cassert> +#include <functional> #include <limits> #include <memory> #include <stdexcept> @@ -85,60 +86,66 @@ ContextBase::~ContextBase() void ContextBase::allocVoiceChanges() { - constexpr size_t clustersize{128}; + VoiceChangeCluster clusterptr{std::make_unique<VoiceChangeCluster::element_type>()}; + const auto cluster = al::span{*clusterptr}; - VoiceChangeCluster cluster{std::make_unique<VoiceChange[]>(clustersize)}; + const size_t clustersize{cluster.size()}; for(size_t i{1};i < clustersize;++i) cluster[i-1].mNext.store(std::addressof(cluster[i]), std::memory_order_relaxed); cluster[clustersize-1].mNext.store(mVoiceChangeTail, std::memory_order_relaxed); - mVoiceChangeClusters.emplace_back(std::move(cluster)); - mVoiceChangeTail = mVoiceChangeClusters.back().get(); + mVoiceChangeClusters.emplace_back(std::move(clusterptr)); + mVoiceChangeTail = mVoiceChangeClusters.back()->data(); } void ContextBase::allocVoiceProps() { - constexpr size_t clustersize{32}; + auto clusterptr = std::make_unique<VoicePropsCluster::element_type>(); + const size_t clustersize{clusterptr->size()}; TRACE("Increasing allocated voice properties to %zu\n", (mVoicePropClusters.size()+1) * clustersize); - VoicePropsCluster cluster{std::make_unique<VoicePropsItem[]>(clustersize)}; + 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); - mVoicePropClusters.emplace_back(std::move(cluster)); + mVoicePropClusters.emplace_back(std::move(clusterptr)); VoicePropsItem *oldhead{mFreeVoiceProps.load(std::memory_order_acquire)}; do { - mVoicePropClusters.back()[clustersize-1].next.store(oldhead, std::memory_order_relaxed); - } while(mFreeVoiceProps.compare_exchange_weak(oldhead, mVoicePropClusters.back().get(), + mVoicePropClusters.back()->back().next.store(oldhead, std::memory_order_relaxed); + } while(mFreeVoiceProps.compare_exchange_weak(oldhead, mVoicePropClusters.back()->data(), std::memory_order_acq_rel, std::memory_order_acquire) == false); } void ContextBase::allocVoices(size_t addcount) { - constexpr size_t clustersize{32}; - /* Convert element count to cluster count. */ - addcount = (addcount+(clustersize-1)) / clustersize; - - if(addcount >= std::numeric_limits<int>::max()/clustersize - mVoiceClusters.size()) - throw std::runtime_error{"Allocating too many voices"}; - const size_t totalcount{(mVoiceClusters.size()+addcount) * clustersize}; - TRACE("Increasing allocated voices to %zu\n", totalcount); + if(!addcount) + { + if(!mVoiceClusters.empty()) + return; + ++addcount; + } - auto newarray = VoiceArray::Create(totalcount); while(addcount) { - mVoiceClusters.emplace_back(std::make_unique<Voice[]>(clustersize)); - --addcount; + auto voicesptr = std::make_unique<VoiceCluster::element_type>(); + const size_t clustersize{voicesptr->size()}; + if(1u >= std::numeric_limits<int>::max()/clustersize - mVoiceClusters.size()) + throw std::runtime_error{"Allocating too many voices"}; + + mVoiceClusters.emplace_back(std::move(voicesptr)); + addcount -= std::min(addcount, clustersize);; } + const size_t totalcount{mVoiceClusters.size() * mVoiceClusters.front()->size()}; + TRACE("Increasing allocated voices to %zu\n", totalcount); + + auto newarray = VoiceArray::Create(totalcount); auto voice_iter = newarray->begin(); for(VoiceCluster &cluster : mVoiceClusters) - { - for(size_t i{0};i < clustersize;++i) - *(voice_iter++) = &cluster[i]; - } + voice_iter = std::transform(cluster->begin(), cluster->end(), voice_iter, + [](Voice &voice) noexcept -> Voice* { return &voice; }); if(auto *oldvoices = mVoices.exchange(newarray.release(), std::memory_order_acq_rel)) { @@ -150,20 +157,20 @@ void ContextBase::allocVoices(size_t addcount) EffectSlot *ContextBase::getEffectSlot() { - for(auto& cluster : mEffectSlotClusters) + for(auto& clusterptr : mEffectSlotClusters) { - for(size_t i{0};i < EffectSlotClusterSize;++i) - { - if(!cluster[i].InUse) - return &cluster[i]; - } + const auto cluster = al::span{*clusterptr}; + auto iter = std::find_if_not(cluster.begin(), cluster.end(), + std::mem_fn(&EffectSlot::InUse)); + if(iter != cluster.end()) return al::to_address(iter); } - if(1 >= std::numeric_limits<int>::max()/EffectSlotClusterSize - mEffectSlotClusters.size()) + auto clusterptr = std::make_unique<EffectSlotCluster::element_type>(); + if(1 >= std::numeric_limits<int>::max()/clusterptr->size() - mEffectSlotClusters.size()) throw std::runtime_error{"Allocating too many effect slots"}; - const size_t totalcount{(mEffectSlotClusters.size()+1) * EffectSlotClusterSize}; + const size_t totalcount{(mEffectSlotClusters.size()+1) * clusterptr->size()}; TRACE("Increasing allocated effect slots to %zu\n", totalcount); - mEffectSlotClusters.emplace_back(std::make_unique<EffectSlot[]>(EffectSlotClusterSize)); - return getEffectSlot(); + mEffectSlotClusters.emplace_back(std::move(clusterptr)); + return mEffectSlotClusters.back()->data(); } diff --git a/core/context.h b/core/context.h index fded0902..e2a62a53 100644 --- a/core/context.h +++ b/core/context.h @@ -143,20 +143,19 @@ struct ContextBase { * However, to avoid allocating each object individually, they're allocated * in clusters that are stored in a vector for easy automatic cleanup. */ - using VoiceChangeCluster = std::unique_ptr<VoiceChange[]>; + using VoiceChangeCluster = std::unique_ptr<std::array<VoiceChange,128>>; std::vector<VoiceChangeCluster> mVoiceChangeClusters; - using VoiceCluster = std::unique_ptr<Voice[]>; + using VoiceCluster = std::unique_ptr<std::array<Voice,32>>; std::vector<VoiceCluster> mVoiceClusters; - using VoicePropsCluster = std::unique_ptr<VoicePropsItem[]>; + using VoicePropsCluster = std::unique_ptr<std::array<VoicePropsItem,32>>; std::vector<VoicePropsCluster> mVoicePropClusters; - static constexpr size_t EffectSlotClusterSize{4}; EffectSlot *getEffectSlot(); - using EffectSlotCluster = std::unique_ptr<EffectSlot[]>; + using EffectSlotCluster = std::unique_ptr<std::array<EffectSlot,4>>; std::vector<EffectSlotCluster> mEffectSlotClusters; |