diff options
author | Chris Robinson <[email protected]> | 2023-12-10 12:58:18 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2023-12-10 12:58:18 -0800 |
commit | cf37d92442ccf3c7f4b979bd97282dcbe28ca64a (patch) | |
tree | 3b96251062c9c6ea97aea3190e22ea68e1377e18 | |
parent | 073d79c2047143e70bb199077fe3c8dbafe0a606 (diff) |
Refactor FlexArray
This avoids using an array of 1 as a flexible array member, and instead uses a
span to reference the memory after itself.
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | alc/alc.cpp | 1 | ||||
-rw-r--r-- | alc/context.cpp | 1 | ||||
-rw-r--r-- | common/almalloc.h | 116 | ||||
-rw-r--r-- | common/flexarray.h | 113 | ||||
-rw-r--r-- | common/ringbuffer.h | 1 | ||||
-rw-r--r-- | core/context.h | 1 | ||||
-rw-r--r-- | core/converter.h | 1 | ||||
-rw-r--r-- | core/device.h | 1 | ||||
-rw-r--r-- | core/effectslot.h | 1 | ||||
-rw-r--r-- | core/front_stablizer.h | 1 | ||||
-rw-r--r-- | core/hrtf.h | 3 |
12 files changed, 124 insertions, 117 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index f08c6aa0..ce287ba0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -628,6 +628,7 @@ set(COMMON_OBJS common/comptr.h common/dynload.cpp common/dynload.h + common/flexarray.h common/intrusive_ptr.h common/opthelpers.h common/pffft.cpp diff --git a/alc/alc.cpp b/alc/alc.cpp index 6e851b74..ebdba66d 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -99,6 +99,7 @@ #include "device.h" #include "effects/base.h" #include "export_list.h" +#include "flexarray.h" #include "inprogext.h" #include "intrusive_ptr.h" #include "opthelpers.h" diff --git a/alc/context.cpp b/alc/context.cpp index 4e962469..2e67f9ac 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -32,6 +32,7 @@ #include "core/voice.h" #include "core/voice_change.h" #include "device.h" +#include "flexarray.h" #include "ringbuffer.h" #include "vecmat.h" diff --git a/common/almalloc.h b/common/almalloc.h index 288b5075..8a976aae 100644 --- a/common/almalloc.h +++ b/common/almalloc.h @@ -127,122 +127,6 @@ 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)...}; } - -/* Storage for flexible array data. This is trivially destructible if type T is - * trivially destructible. - */ -template<typename T, size_t alignment, bool = std::is_trivially_destructible<T>::value> -struct FlexArrayStorage { - const size_t mSize; - union { - char mDummy; - alignas(alignment) T mArray[1]; - }; - - static constexpr size_t Sizeof(size_t count, size_t base=0u) noexcept - { - const size_t len{sizeof(T)*count}; - return std::max(offsetof(FlexArrayStorage,mArray)+len, sizeof(FlexArrayStorage)) + base; - } - - FlexArrayStorage(size_t size) : mSize{size} - { std::uninitialized_default_construct_n(mArray, mSize); } - ~FlexArrayStorage() = default; - - FlexArrayStorage(const FlexArrayStorage&) = delete; - FlexArrayStorage& operator=(const FlexArrayStorage&) = delete; -}; - -template<typename T, size_t alignment> -struct FlexArrayStorage<T,alignment,false> { - const size_t mSize; - union { - char mDummy; - alignas(alignment) T mArray[1]; - }; - - static constexpr size_t Sizeof(size_t count, size_t base) noexcept - { - const size_t len{sizeof(T)*count}; - return std::max(offsetof(FlexArrayStorage,mArray)+len, sizeof(FlexArrayStorage)) + base; - } - - FlexArrayStorage(size_t size) : mSize{size} - { std::uninitialized_default_construct_n(mArray, mSize); } - ~FlexArrayStorage() { std::destroy_n(mArray, mSize); } - - FlexArrayStorage(const FlexArrayStorage&) = delete; - FlexArrayStorage& operator=(const FlexArrayStorage&) = delete; -}; - -/* A flexible array type. Used either standalone or at the end of a parent - * struct, with placement new, to have a run-time-sized array that's embedded - * with its size. - */ -template<typename T, size_t alignment=alignof(T)> -struct FlexArray { - using element_type = T; - using value_type = std::remove_cv_t<T>; - using index_type = size_t; - using difference_type = ptrdiff_t; - - using pointer = T*; - using const_pointer = const T*; - using reference = T&; - using const_reference = const T&; - - using iterator = pointer; - using const_iterator = const_pointer; - using reverse_iterator = std::reverse_iterator<iterator>; - using const_reverse_iterator = std::reverse_iterator<const_iterator>; - - using Storage_t_ = FlexArrayStorage<element_type,alignment>; - - Storage_t_ mStore; - - static constexpr index_type Sizeof(index_type count, index_type base=0u) noexcept - { return Storage_t_::Sizeof(count, base); } - static std::unique_ptr<FlexArray> Create(index_type count) - { - void *ptr{al_calloc(alignof(FlexArray), Sizeof(count))}; - return std::unique_ptr<FlexArray>{al::construct_at(static_cast<FlexArray*>(ptr), count)}; - } - - FlexArray(index_type size) : mStore{size} { } - ~FlexArray() = default; - - [[nodiscard]] auto size() const noexcept -> index_type { return mStore.mSize; } - [[nodiscard]] auto empty() const noexcept -> bool { return mStore.mSize == 0; } - - [[nodiscard]] auto data() noexcept -> pointer { return mStore.mArray; } - [[nodiscard]] auto data() const noexcept -> const_pointer { return mStore.mArray; } - - [[nodiscard]] auto operator[](index_type i) noexcept -> reference { return mStore.mArray[i]; } - [[nodiscard]] auto operator[](index_type i) const noexcept -> const_reference { return mStore.mArray[i]; } - - [[nodiscard]] auto front() noexcept -> reference { return mStore.mArray[0]; } - [[nodiscard]] auto front() const noexcept -> const_reference { return mStore.mArray[0]; } - - [[nodiscard]] auto back() noexcept -> reference { return mStore.mArray[mStore.mSize-1]; } - [[nodiscard]] auto back() const noexcept -> const_reference { return mStore.mArray[mStore.mSize-1]; } - - [[nodiscard]] auto begin() noexcept -> iterator { return mStore.mArray; } - [[nodiscard]] auto begin() const noexcept -> const_iterator { return mStore.mArray; } - [[nodiscard]] auto cbegin() const noexcept -> const_iterator { return mStore.mArray; } - [[nodiscard]] auto end() noexcept -> iterator { return mStore.mArray + mStore.mSize; } - [[nodiscard]] auto end() const noexcept -> const_iterator { return mStore.mArray + mStore.mSize; } - [[nodiscard]] auto cend() const noexcept -> const_iterator { return mStore.mArray + mStore.mSize; } - - [[nodiscard]] auto rbegin() noexcept -> reverse_iterator { return end(); } - [[nodiscard]] auto rbegin() const noexcept -> const_reverse_iterator { return end(); } - [[nodiscard]] auto crbegin() const noexcept -> const_reverse_iterator { return cend(); } - [[nodiscard]] auto rend() noexcept -> reverse_iterator { return begin(); } - [[nodiscard]] auto rend() const noexcept -> const_reverse_iterator { return begin(); } - [[nodiscard]] auto crend() const noexcept -> const_reverse_iterator { return cbegin(); } - - DEF_PLACE_NEWDEL() -}; - } // namespace al #endif /* AL_MALLOC_H */ diff --git a/common/flexarray.h b/common/flexarray.h new file mode 100644 index 00000000..d02a7342 --- /dev/null +++ b/common/flexarray.h @@ -0,0 +1,113 @@ +#ifndef AL_FLEXARRAY_H +#define AL_FLEXARRAY_H + +#include <cstddef> +#include <type_traits> + +#include "almalloc.h" +#include "alspan.h" + +namespace al { + +/* Storage for flexible array data. This is trivially destructible if type T is + * trivially destructible. + */ +template<typename T, size_t alignment, bool = std::is_trivially_destructible<T>::value> +struct FlexArrayStorage { + alignas(alignment) const ::al::span<T> mData; + + static constexpr size_t Sizeof(size_t count, size_t base=0u) noexcept + { return sizeof(FlexArrayStorage) + sizeof(T)*count + base; } + + FlexArrayStorage(size_t size) : mData{::new(static_cast<void*>(this+1)) T[size], size} { } + ~FlexArrayStorage() = default; + + FlexArrayStorage(const FlexArrayStorage&) = delete; + FlexArrayStorage& operator=(const FlexArrayStorage&) = delete; +}; + +template<typename T, size_t alignment> +struct FlexArrayStorage<T,alignment,false> { + alignas(alignment) const ::al::span<T> mData; + + static constexpr size_t Sizeof(size_t count, size_t base=0u) noexcept + { return sizeof(FlexArrayStorage) + sizeof(T)*count + base; } + + FlexArrayStorage(size_t size) : mData{::new(static_cast<void*>(this+1)) T[size], size} { } + ~FlexArrayStorage() { std::destroy(mData.begin(), mData.end()); } + + FlexArrayStorage(const FlexArrayStorage&) = delete; + FlexArrayStorage& operator=(const FlexArrayStorage&) = delete; +}; + +/* A flexible array type. Used either standalone or at the end of a parent + * struct, with placement new, to have a run-time-sized array that's embedded + * with its size. + */ +template<typename T, size_t alignment=alignof(T)> +struct FlexArray { + using element_type = T; + using value_type = std::remove_cv_t<T>; + using index_type = size_t; + using difference_type = ptrdiff_t; + + using pointer = T*; + using const_pointer = const T*; + using reference = T&; + using const_reference = const T&; + + using iterator = pointer; + using const_iterator = const_pointer; + using reverse_iterator = std::reverse_iterator<iterator>; + using const_reverse_iterator = std::reverse_iterator<const_iterator>; + + using Storage_t_ = FlexArrayStorage<element_type,alignment>; + + Storage_t_ mStore; + + static constexpr index_type Sizeof(index_type count, index_type base=0u) noexcept + { return Storage_t_::Sizeof(count, base); } + static std::unique_ptr<FlexArray> Create(index_type count) + { + void *ptr{al_calloc(alignof(FlexArray), Sizeof(count))}; + return std::unique_ptr<FlexArray>{al::construct_at(static_cast<FlexArray*>(ptr), count)}; + } + + FlexArray(index_type size) : mStore{size} { } + ~FlexArray() = default; + + [[nodiscard]] auto size() const noexcept -> index_type { return mStore.mData.size(); } + [[nodiscard]] auto empty() const noexcept -> bool { return mStore.mData.empty(); } + + [[nodiscard]] auto data() noexcept -> pointer { return mStore.mData.data(); } + [[nodiscard]] auto data() const noexcept -> const_pointer { return mStore.mData.data(); } + + [[nodiscard]] auto operator[](index_type i) noexcept -> reference { return mStore.mData[i]; } + [[nodiscard]] auto operator[](index_type i) const noexcept -> const_reference { return mStore.mData[i]; } + + [[nodiscard]] auto front() noexcept -> reference { return mStore.mData.front(); } + [[nodiscard]] auto front() const noexcept -> const_reference { return mStore.mData.front(); } + + [[nodiscard]] auto back() noexcept -> reference { return mStore.mData.back(); } + [[nodiscard]] auto back() const noexcept -> const_reference { return mStore.mData.back(); } + + [[nodiscard]] auto begin() noexcept -> iterator { return mStore.mData.begin(); } + [[nodiscard]] auto begin() const noexcept -> const_iterator { return mStore.mData.begin(); } + [[nodiscard]] auto cbegin() const noexcept -> const_iterator { return mStore.mData.cbegin(); } + [[nodiscard]] auto end() noexcept -> iterator { return mStore.mData.end(); } + [[nodiscard]] auto end() const noexcept -> const_iterator { return mStore.mData.end(); } + [[nodiscard]] auto cend() const noexcept -> const_iterator { return mStore.mData.cend(); } + + [[nodiscard]] auto rbegin() noexcept -> reverse_iterator { return end(); } + [[nodiscard]] auto rbegin() const noexcept -> const_reverse_iterator { return end(); } + [[nodiscard]] auto crbegin() const noexcept -> const_reverse_iterator { return cend(); } + [[nodiscard]] auto rend() noexcept -> reverse_iterator { return begin(); } + [[nodiscard]] auto rend() const noexcept -> const_reverse_iterator { return begin(); } + [[nodiscard]] auto crend() const noexcept -> const_reverse_iterator { return cbegin(); } + + DEF_PLACE_NEWDEL() +}; + +} // namespace al + +#endif /* AL_FLEXARRAY_H */ diff --git a/common/ringbuffer.h b/common/ringbuffer.h index 718238a3..a2b820eb 100644 --- a/common/ringbuffer.h +++ b/common/ringbuffer.h @@ -7,6 +7,7 @@ #include <utility> #include "almalloc.h" +#include "flexarray.h" /* NOTE: This lockless ringbuffer implementation is copied from JACK, extended diff --git a/core/context.h b/core/context.h index e2a62a53..15897ff3 100644 --- a/core/context.h +++ b/core/context.h @@ -14,6 +14,7 @@ #include "alspan.h" #include "async_event.h" #include "atomic.h" +#include "flexarray.h" #include "opthelpers.h" #include "vecmat.h" diff --git a/core/converter.h b/core/converter.h index 49ca124d..7aeb6cad 100644 --- a/core/converter.h +++ b/core/converter.h @@ -7,6 +7,7 @@ #include "almalloc.h" #include "devformat.h" +#include "flexarray.h" #include "mixer/defs.h" using uint = unsigned int; diff --git a/core/device.h b/core/device.h index f5b5d971..e813b182 100644 --- a/core/device.h +++ b/core/device.h @@ -17,6 +17,7 @@ #include "bufferline.h" #include "devformat.h" #include "filters/nfc.h" +#include "flexarray.h" #include "intrusive_ptr.h" #include "mixer/hrtfdefs.h" #include "opthelpers.h" diff --git a/core/effectslot.h b/core/effectslot.h index 2624ae5f..3362ba85 100644 --- a/core/effectslot.h +++ b/core/effectslot.h @@ -6,6 +6,7 @@ #include "almalloc.h" #include "device.h" #include "effects/base.h" +#include "flexarray.h" #include "intrusive_ptr.h" struct EffectSlot; diff --git a/core/front_stablizer.h b/core/front_stablizer.h index 6825111a..8eeb6d74 100644 --- a/core/front_stablizer.h +++ b/core/front_stablizer.h @@ -7,6 +7,7 @@ #include "almalloc.h" #include "bufferline.h" #include "filters/splitter.h" +#include "flexarray.h" struct FrontStablizer { diff --git a/core/hrtf.h b/core/hrtf.h index 50c4f450..31168be6 100644 --- a/core/hrtf.h +++ b/core/hrtf.h @@ -13,8 +13,9 @@ #include "atomic.h" #include "ambidefs.h" #include "bufferline.h" -#include "mixer/hrtfdefs.h" +#include "flexarray.h" #include "intrusive_ptr.h" +#include "mixer/hrtfdefs.h" struct HrtfStore { |