diff options
-rw-r--r-- | al/auxeffectslot.cpp | 25 | ||||
-rw-r--r-- | al/buffer.cpp | 3 | ||||
-rw-r--r-- | al/effect.cpp | 3 | ||||
-rw-r--r-- | al/filter.cpp | 3 | ||||
-rw-r--r-- | alc/alc.cpp | 2 | ||||
-rw-r--r-- | alc/backends/wave.cpp | 78 | ||||
-rw-r--r-- | alc/context.h | 4 | ||||
-rw-r--r-- | alc/device.h | 6 | ||||
-rw-r--r-- | common/almalloc.cpp | 12 | ||||
-rw-r--r-- | common/almalloc.h | 59 | ||||
-rw-r--r-- | common/flexarray.h | 4 | ||||
-rw-r--r-- | core/context.cpp | 24 |
12 files changed, 115 insertions, 108 deletions
diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index 408b742b..ea41a842 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -155,19 +155,17 @@ void AddActiveEffectSlots(const al::span<ALeffectslot*> auxslots, ALCcontext *co */ if(newcount < newarray->size()) UNLIKELY { - curarray = newarray; + std::unique_ptr<EffectSlotArray> oldarray{newarray}; newarray = EffectSlot::CreatePtrArray(newcount); - std::copy_n(curarray->begin(), newcount, newarray->begin()); - delete curarray; - curarray = nullptr; + std::copy_n(oldarray->begin(), newcount, newarray->begin()); } std::uninitialized_fill_n(newarray->end(), newcount, nullptr); - curarray = context->mActiveAuxSlots.exchange(newarray, std::memory_order_acq_rel); + std::unique_ptr<EffectSlotArray> oldarray{context->mActiveAuxSlots.exchange(newarray, + std::memory_order_acq_rel)}; std::ignore = context->mDevice->waitForMix(); - std::destroy_n(curarray->end(), curarray->size()); - delete curarray; + std::destroy_n(oldarray->end(), oldarray->size()); } void RemoveActiveEffectSlots(const al::span<ALeffectslot*> auxslots, ALCcontext *context) @@ -193,20 +191,17 @@ void RemoveActiveEffectSlots(const al::span<ALeffectslot*> auxslots, ALCcontext auto newsize = static_cast<size_t>(std::distance(newarray->begin(), new_end)); if(newsize != newarray->size()) LIKELY { - curarray = newarray; + std::unique_ptr<EffectSlotArray> oldarray{newarray}; newarray = EffectSlot::CreatePtrArray(newsize); - std::copy_n(curarray->begin(), newsize, newarray->begin()); - - delete curarray; - curarray = nullptr; + std::copy_n(oldarray->begin(), newsize, newarray->begin()); } std::uninitialized_fill_n(newarray->end(), newsize, nullptr); - curarray = context->mActiveAuxSlots.exchange(newarray, std::memory_order_acq_rel); + std::unique_ptr<EffectSlotArray> oldarray{context->mActiveAuxSlots.exchange(newarray, + std::memory_order_acq_rel)}; std::ignore = context->mDevice->waitForMix(); std::destroy_n(curarray->end(), curarray->size()); - delete curarray; } @@ -251,7 +246,7 @@ bool EnsureEffectSlots(ALCcontext *context, size_t needed) context->mEffectSlotList.emplace_back(); auto sublist = context->mEffectSlotList.end() - 1; sublist->FreeMask = ~0_u64; - sublist->EffectSlots = static_cast<ALeffectslot*>( + sublist->EffectSlots = static_cast<gsl::owner<ALeffectslot*>>( al_calloc(alignof(ALeffectslot), sizeof(ALeffectslot)*64)); if(!sublist->EffectSlots) UNLIKELY { diff --git a/al/buffer.cpp b/al/buffer.cpp index e577e17a..c0f3f348 100644 --- a/al/buffer.cpp +++ b/al/buffer.cpp @@ -186,7 +186,8 @@ bool EnsureBuffers(ALCdevice *device, size_t needed) device->BufferList.emplace_back(); auto sublist = device->BufferList.end() - 1; sublist->FreeMask = ~0_u64; - sublist->Buffers = static_cast<ALbuffer*>(al_calloc(alignof(ALbuffer), sizeof(ALbuffer)*64)); + sublist->Buffers = static_cast<gsl::owner<ALbuffer*>>(al_calloc(alignof(ALbuffer), + sizeof(ALbuffer)*64)); if(!sublist->Buffers) UNLIKELY { device->BufferList.pop_back(); diff --git a/al/effect.cpp b/al/effect.cpp index c33faa2c..c2a2d1b1 100644 --- a/al/effect.cpp +++ b/al/effect.cpp @@ -134,7 +134,8 @@ bool EnsureEffects(ALCdevice *device, size_t needed) device->EffectList.emplace_back(); auto sublist = device->EffectList.end() - 1; sublist->FreeMask = ~0_u64; - sublist->Effects = static_cast<ALeffect*>(al_calloc(alignof(ALeffect), sizeof(ALeffect)*64)); + sublist->Effects = static_cast<gsl::owner<ALeffect*>>(al_calloc(alignof(ALeffect), + sizeof(ALeffect)*64)); if(!sublist->Effects) UNLIKELY { device->EffectList.pop_back(); diff --git a/al/filter.cpp b/al/filter.cpp index 9c8e4c62..ce37b0aa 100644 --- a/al/filter.cpp +++ b/al/filter.cpp @@ -129,7 +129,8 @@ bool EnsureFilters(ALCdevice *device, size_t needed) device->FilterList.emplace_back(); auto sublist = device->FilterList.end() - 1; sublist->FreeMask = ~0_u64; - sublist->Filters = static_cast<ALfilter*>(al_calloc(alignof(ALfilter), sizeof(ALfilter)*64)); + sublist->Filters = static_cast<gsl::owner<ALfilter*>>(al_calloc(alignof(ALfilter), + sizeof(ALfilter)*64)); if(!sublist->Filters) UNLIKELY { device->FilterList.pop_back(); diff --git a/alc/alc.cpp b/alc/alc.cpp index e9d3aed7..64b77080 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -2735,7 +2735,7 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin if(oldarray != &DeviceBase::sEmptyContextArray) { std::ignore = dev->waitForMix(); - delete oldarray; + newarray.reset(oldarray); } } statelock.unlock(); diff --git a/alc/backends/wave.cpp b/alc/backends/wave.cpp index 95064906..60cebd7f 100644 --- a/alc/backends/wave.cpp +++ b/alc/backends/wave.cpp @@ -55,6 +55,11 @@ using std::chrono::nanoseconds; using ubyte = unsigned char; using ushort = unsigned short; +struct FileDeleter { + void operator()(FILE *f) { fclose(f); } +}; +using FilePtr = std::unique_ptr<FILE,FileDeleter>; + /* NOLINTNEXTLINE(*-avoid-c-arrays) */ constexpr char waveDevice[] = "Wave File Writer"; @@ -102,7 +107,7 @@ struct WaveBackend final : public BackendBase { void start() override; void stop() override; - FILE *mFile{nullptr}; + FilePtr mFile{nullptr}; long mDataStart{-1}; std::vector<std::byte> mBuffer; @@ -111,12 +116,7 @@ struct WaveBackend final : public BackendBase { std::thread mThread; }; -WaveBackend::~WaveBackend() -{ - if(mFile) - fclose(mFile); - mFile = nullptr; -} +WaveBackend::~WaveBackend() = default; int WaveBackend::mixerProc() { @@ -168,8 +168,8 @@ int WaveBackend::mixerProc() } } - const size_t fs{fwrite(mBuffer.data(), frameSize, mDevice->UpdateSize, mFile)}; - if(fs < mDevice->UpdateSize || ferror(mFile)) + const size_t fs{fwrite(mBuffer.data(), frameSize, mDevice->UpdateSize, mFile.get())}; + if(fs < mDevice->UpdateSize || ferror(mFile.get())) { ERR("Error writing to file\n"); mDevice->handleDisconnect("Failed to write playback samples"); @@ -211,10 +211,10 @@ void WaveBackend::open(std::string_view name) #ifdef _WIN32 { std::wstring wname{utf8_to_wstr(fname.value())}; - mFile = _wfopen(wname.c_str(), L"wb"); + mFile.reset(_wfopen(wname.c_str(), L"wb")); } #else - mFile = fopen(fname->c_str(), "wb"); + mFile.reset(fopen(fname->c_str(), "wb")); #endif if(!mFile) throw al::backend_exception{al::backend_error::DeviceError, "Could not open file '%s': %s", @@ -228,8 +228,8 @@ bool WaveBackend::reset() uint channels{0}, bytes{0}, chanmask{0}; bool isbformat{false}; - fseek(mFile, 0, SEEK_SET); - clearerr(mFile); + fseek(mFile.get(), 0, SEEK_SET); + clearerr(mFile.get()); if(GetConfigValueBool({}, "wave", "bformat", false)) { @@ -280,48 +280,48 @@ bool WaveBackend::reset() bytes = mDevice->bytesFromFmt(); channels = mDevice->channelsFromFmt(); - rewind(mFile); + rewind(mFile.get()); - fputs("RIFF", mFile); - fwrite32le(0xFFFFFFFF, mFile); // 'RIFF' header len; filled in at close + fputs("RIFF", mFile.get()); + fwrite32le(0xFFFFFFFF, mFile.get()); // 'RIFF' header len; filled in at close - fputs("WAVE", mFile); + fputs("WAVE", mFile.get()); - fputs("fmt ", mFile); - fwrite32le(40, mFile); // 'fmt ' header len; 40 bytes for EXTENSIBLE + fputs("fmt ", mFile.get()); + fwrite32le(40, mFile.get()); // 'fmt ' header len; 40 bytes for EXTENSIBLE // 16-bit val, format type id (extensible: 0xFFFE) - fwrite16le(0xFFFE, mFile); + fwrite16le(0xFFFE, mFile.get()); // 16-bit val, channel count - fwrite16le(static_cast<ushort>(channels), mFile); + fwrite16le(static_cast<ushort>(channels), mFile.get()); // 32-bit val, frequency - fwrite32le(mDevice->Frequency, mFile); + fwrite32le(mDevice->Frequency, mFile.get()); // 32-bit val, bytes per second - fwrite32le(mDevice->Frequency * channels * bytes, mFile); + fwrite32le(mDevice->Frequency * channels * bytes, mFile.get()); // 16-bit val, frame size - fwrite16le(static_cast<ushort>(channels * bytes), mFile); + fwrite16le(static_cast<ushort>(channels * bytes), mFile.get()); // 16-bit val, bits per sample - fwrite16le(static_cast<ushort>(bytes * 8), mFile); + fwrite16le(static_cast<ushort>(bytes * 8), mFile.get()); // 16-bit val, extra byte count - fwrite16le(22, mFile); + fwrite16le(22, mFile.get()); // 16-bit val, valid bits per sample - fwrite16le(static_cast<ushort>(bytes * 8), mFile); + fwrite16le(static_cast<ushort>(bytes * 8), mFile.get()); // 32-bit val, channel mask - fwrite32le(chanmask, mFile); + fwrite32le(chanmask, mFile.get()); // 16 byte GUID, sub-type format std::ignore = fwrite((mDevice->FmtType == DevFmtFloat) ? (isbformat ? SUBTYPE_BFORMAT_FLOAT.data() : SUBTYPE_FLOAT.data()) : - (isbformat ? SUBTYPE_BFORMAT_PCM.data() : SUBTYPE_PCM.data()), 1, 16, mFile); + (isbformat ? SUBTYPE_BFORMAT_PCM.data() : SUBTYPE_PCM.data()), 1, 16, mFile.get()); - fputs("data", mFile); - fwrite32le(0xFFFFFFFF, mFile); // 'data' header len; filled in at close + fputs("data", mFile.get()); + fwrite32le(0xFFFFFFFF, mFile.get()); // 'data' header len; filled in at close - if(ferror(mFile)) + if(ferror(mFile.get())) { ERR("Error writing header: %s\n", strerror(errno)); return false; } - mDataStart = ftell(mFile); + mDataStart = ftell(mFile.get()); setDefaultWFXChannelOrder(); @@ -333,7 +333,7 @@ bool WaveBackend::reset() void WaveBackend::start() { - if(mDataStart > 0 && fseek(mFile, 0, SEEK_END) != 0) + if(mDataStart > 0 && fseek(mFile.get(), 0, SEEK_END) != 0) WARN("Failed to seek on output file\n"); try { mKillNow.store(false, std::memory_order_release); @@ -353,14 +353,14 @@ void WaveBackend::stop() if(mDataStart > 0) { - long size{ftell(mFile)}; + long size{ftell(mFile.get())}; if(size > 0) { long dataLen{size - mDataStart}; - if(fseek(mFile, 4, SEEK_SET) == 0) - fwrite32le(static_cast<uint>(size-8), mFile); // 'WAVE' header len - if(fseek(mFile, mDataStart-4, SEEK_SET) == 0) - fwrite32le(static_cast<uint>(dataLen), mFile); // 'data' header len + if(fseek(mFile.get(), 4, SEEK_SET) == 0) + fwrite32le(static_cast<uint>(size-8), mFile.get()); // 'WAVE' header len + if(fseek(mFile.get(), mDataStart-4, SEEK_SET) == 0) + fwrite32le(static_cast<uint>(dataLen), mFile.get()); // 'data' header len } } } diff --git a/alc/context.h b/alc/context.h index 9f49ceac..d5e5e78b 100644 --- a/alc/context.h +++ b/alc/context.h @@ -70,7 +70,7 @@ struct DebugLogEntry { struct SourceSubList { uint64_t FreeMask{~0_u64}; - ALsource *Sources{nullptr}; /* 64 */ + gsl::owner<ALsource*> Sources{nullptr}; /* 64 */ SourceSubList() noexcept = default; SourceSubList(const SourceSubList&) = delete; @@ -85,7 +85,7 @@ struct SourceSubList { struct EffectSlotSubList { uint64_t FreeMask{~0_u64}; - ALeffectslot *EffectSlots{nullptr}; /* 64 */ + gsl::owner<ALeffectslot*> EffectSlots{nullptr}; /* 64 */ EffectSlotSubList() noexcept = default; EffectSlotSubList(const EffectSlotSubList&) = delete; diff --git a/alc/device.h b/alc/device.h index 4eb693ff..e5e9b3d2 100644 --- a/alc/device.h +++ b/alc/device.h @@ -35,7 +35,7 @@ using uint = unsigned int; struct BufferSubList { uint64_t FreeMask{~0_u64}; - ALbuffer *Buffers{nullptr}; /* 64 */ + gsl::owner<ALbuffer*> Buffers{nullptr}; /* 64 */ BufferSubList() noexcept = default; BufferSubList(const BufferSubList&) = delete; @@ -50,7 +50,7 @@ struct BufferSubList { struct EffectSubList { uint64_t FreeMask{~0_u64}; - ALeffect *Effects{nullptr}; /* 64 */ + gsl::owner<ALeffect*> Effects{nullptr}; /* 64 */ EffectSubList() noexcept = default; EffectSubList(const EffectSubList&) = delete; @@ -65,7 +65,7 @@ struct EffectSubList { struct FilterSubList { uint64_t FreeMask{~0_u64}; - ALfilter *Filters{nullptr}; /* 64 */ + gsl::owner<ALfilter*> Filters{nullptr}; /* 64 */ FilterSubList() noexcept = default; FilterSubList(const FilterSubList&) = delete; diff --git a/common/almalloc.cpp b/common/almalloc.cpp index ad1dc6be..71953d8b 100644 --- a/common/almalloc.cpp +++ b/common/almalloc.cpp @@ -13,13 +13,13 @@ #endif -void *al_malloc(size_t alignment, size_t size) +gsl::owner<void*> al_malloc(size_t alignment, size_t size) { assert((alignment & (alignment-1)) == 0); alignment = std::max(alignment, alignof(std::max_align_t)); #if defined(HAVE_POSIX_MEMALIGN) - void *ret{}; + gsl::owner<void*> ret{}; if(posix_memalign(&ret, alignment, size) == 0) return ret; return nullptr; @@ -41,14 +41,14 @@ void *al_malloc(size_t alignment, size_t size) #endif } -void *al_calloc(size_t alignment, size_t size) +gsl::owner<void*> al_calloc(size_t alignment, size_t size) { - void *ret{al_malloc(alignment, size)}; + gsl::owner<void*> ret{al_malloc(alignment, size)}; if(ret) std::memset(ret, 0, size); return ret; } -void al_free(void *ptr) noexcept +void al_free(gsl::owner<void*> ptr) noexcept { #if defined(HAVE_POSIX_MEMALIGN) std::free(ptr); @@ -56,6 +56,6 @@ void al_free(void *ptr) noexcept _aligned_free(ptr); #else if(ptr != nullptr) - std::free(*(static_cast<void**>(ptr) - 1)); + std::free(*(static_cast<gsl::owner<void*>*>(ptr) - 1)); #endif } diff --git a/common/almalloc.h b/common/almalloc.h index 7ac02bf1..ac4ddfc2 100644 --- a/common/almalloc.h +++ b/common/almalloc.h @@ -13,11 +13,15 @@ #include "pragmadefs.h" -void al_free(void *ptr) noexcept; +namespace gsl { +template<typename T> using owner = T; +}; + +void al_free(gsl::owner<void*> ptr) noexcept; [[gnu::alloc_align(1), gnu::alloc_size(2), gnu::malloc]] -void *al_malloc(size_t alignment, size_t size); +gsl::owner<void*> al_malloc(size_t alignment, size_t size); [[gnu::alloc_align(1), gnu::alloc_size(2), gnu::malloc]] -void *al_calloc(size_t alignment, size_t size); +gsl::owner<void*> al_calloc(size_t alignment, size_t size); #define DISABLE_ALLOC \ @@ -29,10 +33,10 @@ void *al_calloc(size_t alignment, size_t size); #define DEF_PLACE_NEWDEL \ void *operator new(size_t) = delete; \ void *operator new[](size_t) = delete; \ - void operator delete(void *block, void*) noexcept { al_free(block); } \ - void operator delete(void *block) noexcept { al_free(block); } \ - void operator delete[](void *block, void*) noexcept { al_free(block); } \ - void operator delete[](void *block) noexcept { al_free(block); } + void operator delete(gsl::owner<void*> block, void*) noexcept { al_free(block); } \ + void operator delete(gsl::owner<void*> block) noexcept { al_free(block); } \ + void operator delete[](gsl::owner<void*> block, void*) noexcept { al_free(block); } \ + void operator delete[](gsl::owner<void*> block) noexcept { al_free(block); } enum FamCount : size_t { }; @@ -45,15 +49,22 @@ enum FamCount : size_t { }; sizeof(T)); \ } \ \ - void *operator new(size_t /*size*/, FamCount count) \ + gsl::owner<void*> operator new(size_t /*size*/, FamCount count) \ { \ - if(void *ret{al_malloc(alignof(T), T::Sizeof(count))}) \ - return ret; \ - throw std::bad_alloc(); \ + const auto align = std::align_val_t(alignof(T)); \ + return ::new(align) std::byte[T::Sizeof(count)]; \ } \ void *operator new[](size_t /*size*/) = delete; \ - void operator delete(void *block, FamCount) noexcept { al_free(block); } \ - void operator delete(void *block) noexcept { al_free(block); } \ + void operator delete(gsl::owner<void*> block, FamCount) noexcept \ + { \ + const auto align = std::align_val_t(alignof(T)); \ + ::operator delete[](static_cast<gsl::owner<std::byte*>>(block), align); \ + } \ + void operator delete(gsl::owner<void*> block) noexcept \ + { \ + const auto align = std::align_val_t(alignof(T)); \ + ::operator delete[](static_cast<gsl::owner<std::byte*>>(block), align); \ + } \ void operator delete[](void* /*block*/) = delete; @@ -61,7 +72,8 @@ namespace al { template<typename T, std::size_t Align=alignof(T)> struct allocator { - static constexpr std::size_t alignment{std::max(Align, alignof(T))}; + static constexpr auto alignment = std::max(Align, alignof(T)); + static constexpr auto AlignVal = std::align_val_t(alignment); using value_type = T; using reference = T&; @@ -81,13 +93,13 @@ struct allocator { template<typename U, std::size_t N> constexpr explicit allocator(const allocator<U,N>&) noexcept { } - T *allocate(std::size_t n) + gsl::owner<T*> allocate(std::size_t n) { if(n > std::numeric_limits<std::size_t>::max()/sizeof(T)) throw std::bad_alloc(); - if(auto p = al_malloc(alignment, n*sizeof(T))) return static_cast<T*>(p); - throw std::bad_alloc(); + return reinterpret_cast<gsl::owner<T*>>(::new(AlignVal) std::byte[n*sizeof(T)]); } - void deallocate(T *p, std::size_t) noexcept { al_free(p); } + void deallocate(gsl::owner<T*> p, std::size_t) noexcept + { ::operator delete[](reinterpret_cast<gsl::owner<std::byte*>>(p), AlignVal); } }; template<typename T, std::size_t N, typename U, std::size_t M> constexpr bool operator==(const allocator<T,N>&, const allocator<U,M>&) noexcept { return true; } @@ -111,8 +123,15 @@ constexpr auto to_address(const T &p) noexcept template<typename T, typename ...Args> constexpr T* construct_at(T *ptr, Args&& ...args) - noexcept(std::is_nothrow_constructible<T, Args...>::value) -{ return ::new(static_cast<void*>(ptr)) T{std::forward<Args>(args)...}; } + noexcept(std::is_nothrow_constructible_v<T, Args...>) +{ + /* NOLINTBEGIN(cppcoreguidelines-owning-memory) construct_at doesn't + * necessarily handle the address from an owner, while placement new + * expects to. + */ + return ::new(static_cast<void*>(ptr)) T{std::forward<Args>(args)...}; + /* NOLINTEND(cppcoreguidelines-owning-memory) */ +} } // namespace al diff --git a/common/flexarray.h b/common/flexarray.h index 9b6fcc63..7975a52a 100644 --- a/common/flexarray.h +++ b/common/flexarray.h @@ -74,7 +74,7 @@ struct FlexArray { { return Storage_t_::Sizeof(count, base); } static std::unique_ptr<FlexArray> Create(index_type count) { - if(void *ptr{al_calloc(alignof(FlexArray), Sizeof(count))}) + if(gsl::owner<void*> ptr{al_calloc(alignof(FlexArray), Sizeof(count))}) { try { return std::unique_ptr<FlexArray>{::new(ptr) FlexArray{count}}; @@ -87,7 +87,7 @@ struct FlexArray { throw std::bad_alloc(); } - FlexArray(index_type size) noexcept(std::is_nothrow_constructible_v<Storage_t_>) + FlexArray(index_type size) noexcept(std::is_nothrow_constructible_v<Storage_t_,index_type>) : mStore{size} { } ~FlexArray() = default; diff --git a/core/context.cpp b/core/context.cpp index 1415857c..b969583b 100644 --- a/core/context.cpp +++ b/core/context.cpp @@ -29,15 +29,12 @@ ContextBase::~ContextBase() { size_t count{0}; ContextProps *cprops{mParams.ContextUpdate.exchange(nullptr, std::memory_order_relaxed)}; - if(cprops) - { + if(std::unique_ptr<ContextProps> old{cprops}) ++count; - delete cprops; - } + cprops = mFreeContextProps.exchange(nullptr, std::memory_order_acquire); - while(cprops) + while(std::unique_ptr<ContextProps> old{cprops}) { - std::unique_ptr<ContextProps> old{cprops}; cprops = old->next.load(std::memory_order_relaxed); ++count; } @@ -45,21 +42,17 @@ ContextBase::~ContextBase() count = 0; EffectSlotProps *eprops{mFreeEffectslotProps.exchange(nullptr, std::memory_order_acquire)}; - while(eprops) + while(std::unique_ptr<EffectSlotProps> old{eprops}) { - std::unique_ptr<EffectSlotProps> old{eprops}; eprops = old->next.load(std::memory_order_relaxed); ++count; } TRACE("Freed %zu AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s"); - if(EffectSlotArray *curarray{mActiveAuxSlots.exchange(nullptr, std::memory_order_relaxed)}) - { + if(std::unique_ptr<EffectSlotArray> curarray{mActiveAuxSlots.exchange(nullptr, std::memory_order_relaxed)}) std::destroy_n(curarray->end(), curarray->size()); - delete curarray; - } - delete mVoices.exchange(nullptr, std::memory_order_relaxed); + std::unique_ptr<ContextBase::VoiceArray>{mVoices.exchange(nullptr, std::memory_order_relaxed)}; if(mAsyncEvents) { @@ -149,11 +142,8 @@ void ContextBase::allocVoices(size_t addcount) 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)) - { + if(std::unique_ptr<ContextBase::VoiceArray> oldvoices{mVoices.exchange(newarray.release(), std::memory_order_acq_rel)}) std::ignore = mDevice->waitForMix(); - delete oldvoices; - } } |