diff options
author | Chris Robinson <[email protected]> | 2018-11-23 16:16:31 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2018-11-23 16:16:31 -0800 |
commit | df057d41181b8acc83cb8f64a7dc118b771f9198 (patch) | |
tree | 2ebe7f93f083b065977549547913fd331d08c6e7 | |
parent | 73528c9f550c7df6b1e0f2b54e61c02bf7eac00a (diff) |
Make the context VoiceCount atomic
-rw-r--r-- | Alc/alc.cpp | 98 | ||||
-rw-r--r-- | Alc/alcontext.h | 2 | ||||
-rw-r--r-- | Alc/alu.cpp | 6 | ||||
-rw-r--r-- | OpenAL32/alSource.cpp | 59 |
4 files changed, 79 insertions, 86 deletions
diff --git a/Alc/alc.cpp b/Alc/alc.cpp index a8ea1c53..9fcf028a 100644 --- a/Alc/alc.cpp +++ b/Alc/alc.cpp @@ -1711,7 +1711,6 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) ALCsizei hrtf_id = -1; ALCcontext *context; ALCuint oldFreq; - ALCsizei i; int val; // Check for attributes @@ -2248,9 +2247,6 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) context = device->ContextList.load(); while(context) { - struct ALvoiceProps *vprops; - ALsizei pos; - if(context->DefaultSlot) { ALeffectslot *slot = context->DefaultSlot.get(); @@ -2320,7 +2316,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) * auxiliary sends is changing. Active sources will have updates * respecified in UpdateAllSourceProps. */ - vprops = context->FreeVoiceProps.exchange(nullptr, std::memory_order_acq_rel); + ALvoiceProps *vprops{context->FreeVoiceProps.exchange(nullptr, std::memory_order_acq_rel)}; while(vprops) { struct ALvoiceProps *next = vprops->next.load(std::memory_order_relaxed); @@ -2329,24 +2325,27 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) } AllocateVoices(context, context->MaxVoices, old_sends); - for(pos = 0;pos < context->VoiceCount;pos++) - { - ALvoice *voice = context->Voices[pos]; - - al_free(voice->Update.exchange(nullptr, std::memory_order_acq_rel)); + auto voices_end = context->Voices + context->VoiceCount.load(std::memory_order_relaxed); + std::for_each(context->Voices, voices_end, + [device](ALvoice *voice) -> void + { + al_free(voice->Update.exchange(nullptr, std::memory_order_acq_rel)); - if(voice->Source.load(std::memory_order_acquire) == nullptr) - continue; + if(voice->Source.load(std::memory_order_acquire) == nullptr) + return; - if(device->AvgSpeakerDist > 0.0f) - { - /* Reinitialize the NFC filters for new parameters. */ - ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC / - (device->AvgSpeakerDist * device->Frequency); - for(i = 0;i < voice->NumChannels;i++) - NfcFilterCreate(&voice->Direct.Params[i].NFCtrlFilter, 0.0f, w1); + if(device->AvgSpeakerDist > 0.0f) + { + /* Reinitialize the NFC filters for new parameters. */ + ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC / + (device->AvgSpeakerDist * device->Frequency); + std::for_each(voice->Direct.Params, voice->Direct.Params+voice->NumChannels, + [w1](DirectParams ¶ms) -> void + { NfcFilterCreate(¶ms.NFCtrlFilter, 0.0f, w1); } + ); + } } - } + ); srclock.unlock(); context->PropsClean.test_and_set(std::memory_order_release); @@ -2592,11 +2591,12 @@ ALCcontext_struct::~ALCcontext_struct() } TRACE("Freed " SZFMT " voice property object%s\n", count, (count==1)?"":"s"); - for(ALsizei i{0};i < VoiceCount;i++) - DeinitVoice(Voices[i]); + std::for_each(Voices, Voices + VoiceCount.load(std::memory_order_relaxed), + [](ALvoice *voice) -> void { DeinitVoice(voice); } + ); al_free(Voices); Voices = nullptr; - VoiceCount = 0; + VoiceCount.store(0, std::memory_order_relaxed); MaxVoices = 0; struct ALlistenerProps *lprops{Listener.Update.load(std::memory_order_relaxed)}; @@ -2747,15 +2747,8 @@ ALCcontext *GetContextRef(void) void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends) { - ALCdevice *device = context->Device; - ALsizei num_sends = device->NumAuxSends; - struct ALvoiceProps *props; - size_t sizeof_props; - size_t sizeof_voice; - ALvoice **voices; - ALvoice *voice; - ALsizei v = 0; - size_t size; + ALCdevice *device{context->Device}; + ALsizei num_sends{device->NumAuxSends}; if(num_voices == context->MaxVoices && num_sends == old_sends) return; @@ -2764,53 +2757,54 @@ void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends) * property set (including the dynamically-sized Send[] array) in one * chunk. */ - sizeof_voice = RoundUp(FAM_SIZE(ALvoice, Send, num_sends), 16); - sizeof_props = RoundUp(FAM_SIZE(struct ALvoiceProps, Send, num_sends), 16); - size = sizeof(ALvoice*) + sizeof_voice + sizeof_props; + size_t sizeof_voice{RoundUp(FAM_SIZE(ALvoice, Send, num_sends), 16)}; + size_t sizeof_props{RoundUp(FAM_SIZE(struct ALvoiceProps, Send, num_sends), 16)}; + size_t size{sizeof(ALvoice*) + sizeof_voice + sizeof_props}; - voices = static_cast<ALvoice**>(al_calloc(16, RoundUp(size*num_voices, 16))); + auto voices = static_cast<ALvoice**>(al_calloc(16, RoundUp(size*num_voices, 16))); /* The voice and property objects are stored interleaved since they're * paired together. */ - voice = (ALvoice*)((char*)voices + RoundUp(num_voices*sizeof(ALvoice*), 16)); - props = (struct ALvoiceProps*)((char*)voice + sizeof_voice); + auto voice = reinterpret_cast<ALvoice*>((char*)voices + RoundUp(num_voices*sizeof(ALvoice*), 16)); + auto props = reinterpret_cast<ALvoiceProps*>((char*)voice + sizeof_voice); + ALsizei v{0}; if(context->Voices) { - const ALsizei v_count = mini(context->VoiceCount, num_voices); + const ALsizei v_count = mini(context->VoiceCount.load(std::memory_order_relaxed), + num_voices); const ALsizei s_count = mini(old_sends, num_sends); for(;v < v_count;v++) { - ALvoice *old_voice = context->Voices[v]; - ALsizei i; + ALvoice *old_voice{context->Voices[v]}; /* Copy the old voice data and source property set to the new * storage. */ memcpy(voice, old_voice, sizeof(*voice)); - for(i = 0;i < s_count;i++) - voice->Send[i] = old_voice->Send[i]; + std::copy_n(old_voice->Send, s_count, voice->Send); memcpy(props, old_voice->Props, sizeof(*props)); - for(i = 0;i < s_count;i++) - props->Send[i] = old_voice->Props->Send[i]; + std::copy_n(old_voice->Props->Send, s_count, props->Send); /* Set this voice's property set pointer and voice reference. */ voice->Props = props; voices[v] = voice; /* Increment pointers to the next storage space. */ - voice = (ALvoice*)((char*)props + sizeof_props); - props = (struct ALvoiceProps*)((char*)voice + sizeof_voice); + voice = reinterpret_cast<ALvoice*>((char*)props + sizeof_props); + props = reinterpret_cast<ALvoiceProps*>((char*)voice + sizeof_voice); } /* Deinit any left over voices that weren't copied over to the new * array. NOTE: If this does anything, v equals num_voices and * num_voices is less than VoiceCount, so the following loop won't do * anything. */ - for(;v < context->VoiceCount;v++) - DeinitVoice(context->Voices[v]); + auto voices_end = context->Voices + context->VoiceCount.load(std::memory_order_relaxed); + std::for_each(context->Voices + v, voices_end, + [](ALvoice *voice) -> void { DeinitVoice(voice); } + ); } /* Finish setting the voices' property set pointers and references. */ for(;v < num_voices;v++) @@ -2820,14 +2814,14 @@ void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends) voice->Props = props; voices[v] = voice; - voice = (ALvoice*)((char*)props + sizeof_props); - props = (struct ALvoiceProps*)((char*)voice + sizeof_voice); + voice = reinterpret_cast<ALvoice*>((char*)props + sizeof_props); + props = reinterpret_cast<ALvoiceProps*>((char*)voice + sizeof_voice); } al_free(context->Voices); context->Voices = voices; context->MaxVoices = num_voices; - context->VoiceCount = mini(context->VoiceCount, num_voices); + context->VoiceCount = mini(context->VoiceCount.load(std::memory_order_relaxed), num_voices); } diff --git a/Alc/alcontext.h b/Alc/alcontext.h index c9cfa985..9845b686 100644 --- a/Alc/alcontext.h +++ b/Alc/alcontext.h @@ -95,7 +95,7 @@ struct ALCcontext_struct { ATOMIC(ALeffectslotProps*) FreeEffectslotProps{nullptr}; ALvoice **Voices{nullptr}; - ALsizei VoiceCount{0}; + std::atomic<ALsizei> VoiceCount{0}; ALsizei MaxVoices{0}; ATOMIC(ALeffectslotArray*) ActiveAuxSlots{nullptr}; diff --git a/Alc/alu.cpp b/Alc/alu.cpp index 71823bf7..5036ae24 100644 --- a/Alc/alu.cpp +++ b/Alc/alu.cpp @@ -1503,7 +1503,7 @@ void ProcessParamUpdates(ALCcontext *ctx, const ALeffectslotArray *slots) { force |= CalcEffectSlotParams(slot, ctx, cforce); } ); - std::for_each(ctx->Voices, ctx->Voices+ctx->VoiceCount, + std::for_each(ctx->Voices, ctx->Voices+ctx->VoiceCount.load(std::memory_order_acquire), [ctx,force](ALvoice *voice) -> void { ALsource *source{voice->Source.load(std::memory_order_acquire)}; @@ -1533,7 +1533,7 @@ void ProcessContext(ALCcontext *ctx, ALsizei SamplesToDo) ); /* Process voices that have a playing source. */ - std::for_each(ctx->Voices, ctx->Voices+ctx->VoiceCount, + std::for_each(ctx->Voices, ctx->Voices+ctx->VoiceCount.load(std::memory_order_acquire), [SamplesToDo,ctx](ALvoice *voice) -> void { ALsource *source{voice->Source.load(std::memory_order_acquire)}; @@ -1859,7 +1859,7 @@ void aluHandleDisconnect(ALCdevice *device, const char *msg, ...) ll_ringbuffer_write(ctx->AsyncEvents, &evt, 1) == 1) alsem_post(&ctx->EventSem); - std::for_each(ctx->Voices, ctx->Voices+ctx->VoiceCount, + std::for_each(ctx->Voices, ctx->Voices+ctx->VoiceCount.load(std::memory_order_acquire), [ctx](ALvoice *voice) -> void { ALsource *source{voice->Source.exchange(nullptr, std::memory_order_relaxed)}; diff --git a/OpenAL32/alSource.cpp b/OpenAL32/alSource.cpp index 30629c29..8ee94600 100644 --- a/OpenAL32/alSource.cpp +++ b/OpenAL32/alSource.cpp @@ -51,7 +51,7 @@ namespace { inline ALvoice *GetSourceVoice(ALsource *source, ALCcontext *context) { ALint idx{source->VoiceIdx}; - if(idx >= 0 && idx < context->VoiceCount) + if(idx >= 0 && idx < context->VoiceCount.load(std::memory_order_relaxed)) { ALvoice *voice{context->Voices[idx]}; if(voice->Source.load(std::memory_order_acquire) == source) @@ -2725,7 +2725,7 @@ AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources) return; } - while(n > context->MaxVoices-context->VoiceCount) + while(n > context->MaxVoices-context->VoiceCount.load(std::memory_order_relaxed)) { ALsizei newcount = context->MaxVoices << 1; if(context->MaxVoices >= newcount) @@ -2790,19 +2790,15 @@ AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources) /* Look for an unused voice to play this source with. */ assert(voice == nullptr); - ALint vidx{-1}; - for(ALsizei j{0};j < context->VoiceCount;j++) - { - if(context->Voices[j]->Source.load(std::memory_order_acquire) == nullptr) - { - vidx = j; - break; - } - } - if(vidx == -1) - vidx = context->VoiceCount++; - voice = context->Voices[vidx]; + auto voices_end = context->Voices + context->VoiceCount.load(std::memory_order_relaxed); + auto voice_iter = std::find_if(context->Voices, voices_end, + [](const ALvoice *voice) noexcept -> bool + { return voice->Source.load(std::memory_order_relaxed) == nullptr; } + ); + auto vidx = static_cast<ALint>(std::distance(context->Voices, voice_iter)); + voice = *voice_iter; voice->Playing.store(false, std::memory_order_release); + if(voice_iter == voices_end) context->VoiceCount.fetch_add(1, std::memory_order_acq_rel); source->PropsClean.test_and_set(std::memory_order_acquire); UpdateSourceProps(source, voice, context.get()); @@ -2823,19 +2819,20 @@ AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources) voice->position_fraction.load(std::memory_order_relaxed) != 0 || voice->current_buffer.load(std::memory_order_relaxed) != BufferList; - for(ALsizei j{0};j < BufferList->num_buffers;j++) + auto buffers_end = BufferList->buffers + BufferList->num_buffers; + auto buffer = std::find_if(BufferList->buffers, buffers_end, + [](const ALbuffer *buffer) noexcept -> bool + { return buffer != nullptr; } + ); + if(buffer != buffers_end) { - ALbuffer *buffer = BufferList->buffers[j]; - if(buffer) - { - voice->NumChannels = ChannelsFromFmt(buffer->FmtChannels); - voice->SampleSize = BytesFromFmt(buffer->FmtType); - break; - } + voice->NumChannels = ChannelsFromFmt((*buffer)->FmtChannels); + voice->SampleSize = BytesFromFmt((*buffer)->FmtType); } /* Clear previous samples. */ - memset(voice->PrevSamples, 0, sizeof(voice->PrevSamples)); + for(auto &samples : voice->PrevSamples) + std::fill(std::begin(samples), std::end(samples), 0.0f); /* Clear the stepping value so the mixer knows not to mix this until * the update gets applied. @@ -3399,13 +3396,15 @@ ALsource::~ALsource() void UpdateAllSourceProps(ALCcontext *context) { - for(ALsizei i{0};i < context->VoiceCount;++i) - { - ALvoice *voice{context->Voices[i]}; - ALsource *source{voice->Source.load(std::memory_order_acquire)}; - if(source && !source->PropsClean.test_and_set(std::memory_order_acq_rel)) - UpdateSourceProps(source, voice, context); - } + auto voices_end = context->Voices + context->VoiceCount.load(std::memory_order_relaxed); + std::for_each(context->Voices, voices_end, + [context](ALvoice *voice) -> void + { + ALsource *source{voice->Source.load(std::memory_order_acquire)}; + if(source && !source->PropsClean.test_and_set(std::memory_order_acq_rel)) + UpdateSourceProps(source, voice, context); + } + ); } /* ReleaseALSources |