aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2023-12-10 12:58:18 -0800
committerChris Robinson <[email protected]>2023-12-10 12:58:18 -0800
commitcf37d92442ccf3c7f4b979bd97282dcbe28ca64a (patch)
tree3b96251062c9c6ea97aea3190e22ea68e1377e18
parent073d79c2047143e70bb199077fe3c8dbafe0a606 (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.txt1
-rw-r--r--alc/alc.cpp1
-rw-r--r--alc/context.cpp1
-rw-r--r--common/almalloc.h116
-rw-r--r--common/flexarray.h113
-rw-r--r--common/ringbuffer.h1
-rw-r--r--core/context.h1
-rw-r--r--core/converter.h1
-rw-r--r--core/device.h1
-rw-r--r--core/effectslot.h1
-rw-r--r--core/front_stablizer.h1
-rw-r--r--core/hrtf.h3
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 {