aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--al/source.cpp14
-rw-r--r--alc/alc.cpp21
-rw-r--r--alc/context.cpp29
-rw-r--r--core/context.h4
-rw-r--r--core/voice.h2
5 files changed, 39 insertions, 31 deletions
diff --git a/al/source.cpp b/al/source.cpp
index 4a2aaf35..cf95f7a4 100644
--- a/al/source.cpp
+++ b/al/source.cpp
@@ -100,15 +100,15 @@ void UpdateSourceProps(const ALsource *source, Voice *voice, ALCcontext *context
/* Get an unused property container, or allocate a new one as needed. */
VoicePropsItem *props{context->mFreeVoiceProps.load(std::memory_order_acquire)};
if(!props)
- props = new VoicePropsItem{};
- else
{
- VoicePropsItem *next;
- do {
- next = props->next.load(std::memory_order_relaxed);
- } while(context->mFreeVoiceProps.compare_exchange_weak(props, next,
- std::memory_order_acq_rel, std::memory_order_acquire) == 0);
+ context->allocVoiceProps();
+ props = context->mFreeVoiceProps.load(std::memory_order_acquire);
}
+ VoicePropsItem *next;
+ do {
+ next = props->next.load(std::memory_order_relaxed);
+ } while(unlikely(context->mFreeVoiceProps.compare_exchange_weak(props, next,
+ std::memory_order_acq_rel, std::memory_order_acquire) == false));
props->Pitch = source->Pitch;
props->Gain = source->Gain;
diff --git a/alc/alc.cpp b/alc/alc.cpp
index 54162d14..89c836d0 100644
--- a/alc/alc.cpp
+++ b/alc/alc.cpp
@@ -2082,18 +2082,6 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList)
}
}
- /* Clear any pre-existing voice property structs, in case the number of
- * auxiliary sends is changing. Active sources will have updates
- * respecified in UpdateAllSourceProps.
- */
- VoicePropsItem *vprops{context->mFreeVoiceProps.exchange(nullptr, std::memory_order_acq_rel)};
- while(vprops)
- {
- VoicePropsItem *next = vprops->next.load(std::memory_order_relaxed);
- delete vprops;
- vprops = next;
- }
-
auto voicelist = context->getVoicesSpan();
for(Voice *voice : voicelist)
{
@@ -2108,7 +2096,8 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList)
SendParams{});
}
- delete voice->mUpdate.exchange(nullptr, std::memory_order_acq_rel);
+ if(VoicePropsItem *props{voice->mUpdate.exchange(nullptr, std::memory_order_relaxed)})
+ AtomicReplaceHead(context->mFreeVoiceProps, props);
/* Force the voice to stopped if it was stopping. */
Voice::State vstate{Voice::Stopping};
@@ -2119,6 +2108,9 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList)
voice->prepare(device);
}
+ /* Clear all voice props to let them get allocated again. */
+ context->mVoicePropClusters.clear();
+ context->mFreeVoiceProps.store(nullptr, std::memory_order_relaxed);
srclock.unlock();
context->mPropsDirty.test_and_clear(std::memory_order_release);
@@ -2173,6 +2165,9 @@ bool ResetDeviceParams(ALCdevice *device, const int *attrList)
vchg = next;
ctx->mCurrentVoiceChange.store(vchg, std::memory_order_release);
+ ctx->mVoicePropClusters.clear();
+ ctx->mFreeVoiceProps.store(nullptr, std::memory_order_relaxed);
+
ctx->mVoiceClusters.clear();
ctx->allocVoices(std::max<size_t>(256,
ctx->mActiveVoiceCount.load(std::memory_order_relaxed)));
diff --git a/alc/context.cpp b/alc/context.cpp
index a97c2a68..297d24a6 100644
--- a/alc/context.cpp
+++ b/alc/context.cpp
@@ -133,16 +133,6 @@ ContextBase::~ContextBase()
delete curarray;
}
- count = 0;
- VoicePropsItem *vprops{mFreeVoiceProps.exchange(nullptr, std::memory_order_acquire)};
- while(vprops)
- {
- std::unique_ptr<VoicePropsItem> old{vprops};
- vprops = old->next.load(std::memory_order_relaxed);
- ++count;
- }
- TRACE("Freed %zu voice property object%s\n", count, (count==1)?"":"s");
-
delete mVoices.exchange(nullptr, std::memory_order_relaxed);
count = 0;
@@ -198,6 +188,25 @@ void ContextBase::allocVoiceChanges(size_t addcount)
}
}
+void ContextBase::allocVoiceProps()
+{
+ constexpr size_t clustersize{32};
+
+ TRACE("Increasing allocated voice properties to %zu\n",
+ (mVoicePropClusters.size()+1) * clustersize);
+
+ VoicePropsCluster cluster{std::make_unique<VoicePropsItem[]>(clustersize)};
+ 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));
+
+ 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(),
+ std::memory_order_acq_rel, std::memory_order_acquire) == false);
+}
+
void ContextBase::allocVoices(size_t addcount)
{
constexpr size_t clustersize{32};
diff --git a/core/context.h b/core/context.h
index 155ee167..0e531db0 100644
--- a/core/context.h
+++ b/core/context.h
@@ -122,6 +122,7 @@ struct ContextBase {
std::atomic<VoiceChange*> mCurrentVoiceChange{};
void allocVoiceChanges(size_t addcount);
+ void allocVoiceProps();
ContextParams mParams;
@@ -162,6 +163,9 @@ struct ContextBase {
using VoiceCluster = std::unique_ptr<Voice[]>;
al::vector<VoiceCluster> mVoiceClusters;
+ using VoicePropsCluster = std::unique_ptr<VoicePropsItem[]>;
+ al::vector<VoicePropsCluster> mVoicePropClusters;
+
ContextBase(DeviceBase *device);
ContextBase(const ContextBase&) = delete;
diff --git a/core/voice.h b/core/voice.h
index 8b5ae37f..d7168fb9 100644
--- a/core/voice.h
+++ b/core/voice.h
@@ -252,7 +252,7 @@ struct Voice {
al::vector<ChannelData> mChans{2};
Voice() = default;
- ~Voice() { delete mUpdate.exchange(nullptr, std::memory_order_acq_rel); }
+ ~Voice() = default;
Voice(const Voice&) = delete;
Voice& operator=(const Voice&) = delete;