aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2023-12-08 11:53:51 -0800
committerChris Robinson <[email protected]>2023-12-08 11:53:51 -0800
commit112ad405df27b5a20d7a578321b592be2d4d8eaf (patch)
treea3401c88cdcd70dee030697cec885adfc6330d57 /core
parent040c172cdf186c9ccfb0642aa9ac598f115bb46b (diff)
Use a fixed array for fixed-size clusters
Diffstat (limited to 'core')
-rw-r--r--core/context.cpp75
-rw-r--r--core/context.h9
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;