Use a vector for ALeffectslotArray

This commit is contained in:
Chris Robinson 2019-01-09 18:29:22 -08:00
parent 30184613a5
commit e7d77f5caa
5 changed files with 40 additions and 48 deletions

View File

@ -2324,22 +2324,16 @@ static ALvoid InitContext(ALCcontext *Context)
ALeffectslotArray *auxslots;
//Validate Context
if(Context->DefaultSlot)
if(!Context->DefaultSlot)
auxslots = new ALeffectslotArray{};
else
{
static constexpr int count{1};
/* Allocate twice as much space for effect slots so the mixer has a
* place to sort them.
*/
auxslots = static_cast<ALeffectslotArray*>(al_calloc(DEF_ALIGN,
FAM_SIZE(ALeffectslotArray, slot, count*2)));
auxslots->count = count;
auxslots->slot[0] = Context->DefaultSlot.get();
}
else
{
auxslots = static_cast<ALeffectslotArray*>(al_calloc(DEF_ALIGN,
sizeof(ALeffectslotArray)));
auxslots->count = 0;
auxslots = new ALeffectslotArray{};
auxslots->reserve(2);
auxslots->push_back(Context->DefaultSlot.get());
}
Context->ActiveAuxSlots.store(auxslots, std::memory_order_relaxed);
@ -2418,7 +2412,7 @@ ALCcontext::~ALCcontext()
}
TRACE("Freed " SZFMT " AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
al_free(ActiveAuxSlots.exchange(nullptr, std::memory_order_relaxed));
delete ActiveAuxSlots.exchange(nullptr, std::memory_order_relaxed);
DefaultSlot = nullptr;
count = std::count_if(EffectSlotList.cbegin(), EffectSlotList.cend(),

View File

@ -26,7 +26,6 @@ struct ALlistenerProps;
struct ALvoiceProps;
struct ALeffectslotProps;
struct ALvoice;
struct ALeffectslotArray;
struct RingBuffer;
enum class DistanceModel {
@ -108,6 +107,7 @@ struct ALCcontext {
std::atomic<ALsizei> VoiceCount{0};
ALsizei MaxVoices{0};
using ALeffectslotArray = al::vector<ALeffectslot*>;
std::atomic<ALeffectslotArray*> ActiveAuxSlots{nullptr};
std::thread EventThread;

View File

@ -28,6 +28,7 @@
#include <cmath>
#include <limits>
#include <numeric>
#include <algorithm>
#include <functional>
@ -1437,9 +1438,9 @@ void ProcessParamUpdates(ALCcontext *ctx, const ALeffectslotArray *slots)
{
bool cforce{CalcContextParams(ctx)};
bool force{CalcListenerParams(ctx) || cforce};
std::for_each(slots->slot, slots->slot+slots->count,
[ctx,cforce,&force](ALeffectslot *slot) -> void
{ force |= CalcEffectSlotParams(slot, ctx, cforce); }
force = std::accumulate(slots->begin(), slots->end(), force,
[ctx,cforce](bool force, ALeffectslot *slot) -> bool
{ return CalcEffectSlotParams(slot, ctx, cforce) | force; }
);
std::for_each(ctx->Voices, ctx->Voices+ctx->VoiceCount.load(std::memory_order_acquire),
@ -1463,7 +1464,7 @@ void ProcessContext(ALCcontext *ctx, const ALsizei SamplesToDo)
ProcessParamUpdates(ctx, auxslots);
/* Clear auxiliary effect slot mixing buffers. */
std::for_each(auxslots->slot, auxslots->slot+auxslots->count,
std::for_each(auxslots->begin(), auxslots->end(),
[SamplesToDo](ALeffectslot *slot) -> void
{
std::for_each(slot->WetBuffer, slot->WetBuffer+slot->NumChannels,
@ -1491,9 +1492,9 @@ void ProcessContext(ALCcontext *ctx, const ALsizei SamplesToDo)
);
/* Process effects. */
if(auxslots->count < 1) return;
auto slots = auxslots->slot;
auto slots_end = slots + auxslots->count;
if(auxslots->size() < 1) return;
auto slots = auxslots->data();
auto slots_end = slots + auxslots->size();
/* First sort the slots into scratch storage, so that effects come before
* their effect target (or their targets' target).

View File

@ -44,10 +44,7 @@ struct EffectStateFactory {
#define MAX_EFFECT_CHANNELS (4)
struct ALeffectslotArray {
ALsizei count;
ALeffectslot *slot[];
};
using ALeffectslotArray = al::vector<ALeffectslot*>;
struct ALeffectslotProps {

View File

@ -68,42 +68,42 @@ void AddActiveEffectSlots(const ALuint *slotids, ALsizei count, ALCcontext *cont
{
if(count < 1) return;
ALeffectslotArray *curarray{context->ActiveAuxSlots.load(std::memory_order_acquire)};
ALsizei newcount{curarray->count + count};
size_t newcount{curarray->size() + count};
/* Insert the new effect slots into the head of the array, followed by the
* existing ones. Allocate twice as much space for effect slots so the
* mixer has a place to sort them.
*/
auto newarray = static_cast<ALeffectslotArray*>(al_calloc(DEF_ALIGN,
FAM_SIZE(ALeffectslotArray, slot, newcount*2)));
newarray->count = newcount;
auto slotiter = std::transform(slotids, slotids+count, newarray->slot,
auto newarray = new ALeffectslotArray{};
newarray->reserve(newcount * 2);
newarray->resize(newcount);
auto slotiter = std::transform(slotids, slotids+count, newarray->begin(),
[context](ALuint id) noexcept -> ALeffectslot*
{ return LookupEffectSlot(context, id); }
);
std::copy_n(curarray->slot, curarray->count, slotiter);
std::copy(curarray->begin(), curarray->end(), slotiter);
/* Remove any duplicates (first instance of each will be kept). */
ALeffectslot **last = newarray->slot + newarray->count;
for(ALeffectslot **start=newarray->slot+1;;)
auto last = newarray->end();
for(auto start=newarray->begin()+1;;)
{
last = std::remove(start, last, *(start-1));
if(start == last) break;
++start;
}
newcount = static_cast<ALsizei>(std::distance(newarray->slot, last));
newcount = static_cast<size_t>(std::distance(newarray->begin(), last));
/* Reallocate newarray if the new size ended up smaller from duplicate
* removal.
*/
if(UNLIKELY(newcount < newarray->count))
if(UNLIKELY(newcount < newarray->size()))
{
curarray = newarray;
newarray = static_cast<ALeffectslotArray*>(al_calloc(DEF_ALIGN,
FAM_SIZE(ALeffectslotArray, slot, newcount*2)));
newarray->count = newcount;
std::copy_n(curarray->slot, newcount, newarray->slot);
al_free(curarray);
newarray = new ALeffectslotArray{};
newarray->reserve(newcount * 2);
newarray->resize(newcount);
std::copy_n(curarray->begin(), newcount, newarray->begin());
delete curarray;
curarray = nullptr;
}
@ -111,7 +111,7 @@ void AddActiveEffectSlots(const ALuint *slotids, ALsizei count, ALCcontext *cont
ALCdevice *device{context->Device};
while((device->MixCount.load(std::memory_order_acquire)&1))
std::this_thread::yield();
al_free(curarray);
delete curarray;
}
void RemoveActiveEffectSlots(const ALuint *slotids, ALsizei count, ALCcontext *context)
@ -122,16 +122,17 @@ void RemoveActiveEffectSlots(const ALuint *slotids, ALsizei count, ALCcontext *c
/* Don't shrink the allocated array size since we don't know how many (if
* any) of the effect slots to remove are in the array.
*/
auto newarray = static_cast<ALeffectslotArray*>(al_calloc(DEF_ALIGN,
FAM_SIZE(ALeffectslotArray, slot, curarray->count*2)));
auto newarray = new ALeffectslotArray{};
newarray->reserve(curarray->size() * 2);
newarray->resize(curarray->size());
/* Copy each element in curarray to newarray whose ID is not in slotids. */
const ALuint *slotids_end{slotids + count};
auto slotiter = std::copy_if(curarray->slot, curarray->slot+curarray->count, newarray->slot,
auto slotiter = std::copy_if(curarray->begin(), curarray->end(), newarray->begin(),
[slotids, slotids_end](const ALeffectslot *slot) -> bool
{ return std::find(slotids, slotids_end, slot->id) == slotids_end; }
);
newarray->count = static_cast<ALsizei>(std::distance(newarray->slot, slotiter));
newarray->resize(std::distance(newarray->begin(), slotiter));
/* TODO: Could reallocate newarray now that we know it's needed size. */
@ -139,7 +140,7 @@ void RemoveActiveEffectSlots(const ALuint *slotids, ALsizei count, ALCcontext *c
ALCdevice *device{context->Device};
while((device->MixCount.load(std::memory_order_acquire)&1))
std::this_thread::yield();
al_free(curarray);
delete curarray;
}
constexpr struct FactoryItem {
@ -695,9 +696,8 @@ void UpdateAllEffectSlotProps(ALCcontext *context)
{
std::lock_guard<std::mutex> _{context->EffectSlotLock};
ALeffectslotArray *auxslots{context->ActiveAuxSlots.load(std::memory_order_acquire)};
for(ALsizei i{0};i < auxslots->count;i++)
for(ALeffectslot *slot : *auxslots)
{
ALeffectslot *slot = auxslots->slot[i];
if(!slot->PropsClean.test_and_set(std::memory_order_acq_rel))
UpdateEffectSlotProps(slot, context);
}