diff options
author | Jacques Lucke <jacques@blender.org> | 2022-07-02 12:45:57 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2022-07-02 12:45:57 +0300 |
commit | 5d9ade27de54b6910ed32f92d20d8f692959603c (patch) | |
tree | 1dd2c2002178291273f0809284fbc6660a14ca70 /source/blender/blenlib | |
parent | 3c60d62dba1214378c3348563167385385f6a539 (diff) |
BLI: improve span access to virtual arrays
* Make the class names more consistent.
* Implement missing move-constructors and assignment-operators.
Diffstat (limited to 'source/blender/blenlib')
4 files changed, 126 insertions, 35 deletions
diff --git a/source/blender/blenlib/BLI_generic_virtual_array.hh b/source/blender/blenlib/BLI_generic_virtual_array.hh index 95305a0561d..3526925c2e2 100644 --- a/source/blender/blenlib/BLI_generic_virtual_array.hh +++ b/source/blender/blenlib/BLI_generic_virtual_array.hh @@ -257,22 +257,24 @@ class GVMutableArray : public GVArrayCommon { /** \} */ /* -------------------------------------------------------------------- */ -/** \name #GVArray_GSpan and #GVMutableArray_GSpan. +/** \name #GVArraySpan and #GMutableVArraySpan. * \{ */ -/* A generic version of VArray_Span. */ -class GVArray_GSpan : public GSpan { +/* A generic version of VArraySpan. */ +class GVArraySpan : public GSpan { private: GVArray varray_; void *owned_data_ = nullptr; public: - GVArray_GSpan(GVArray varray); - ~GVArray_GSpan(); + GVArraySpan(GVArray varray); + GVArraySpan(GVArraySpan &&other); + ~GVArraySpan(); + GVArraySpan &operator=(GVArraySpan &&other); }; -/* A generic version of VMutableArray_Span. */ -class GVMutableArray_GSpan : public GMutableSpan, NonCopyable, NonMovable { +/* A generic version of MutableVArraySpan. */ +class GMutableVArraySpan : public GMutableSpan, NonCopyable, NonMovable { private: GVMutableArray varray_; void *owned_data_ = nullptr; @@ -280,8 +282,10 @@ class GVMutableArray_GSpan : public GMutableSpan, NonCopyable, NonMovable { bool show_not_saved_warning_ = true; public: - GVMutableArray_GSpan(GVMutableArray varray, bool copy_values_to_span = true); - ~GVMutableArray_GSpan(); + GMutableVArraySpan(GVMutableArray varray, bool copy_values_to_span = true); + GMutableVArraySpan(GMutableVArraySpan &&other); + ~GMutableVArraySpan(); + GMutableVArraySpan &operator=(GMutableVArraySpan &&other); void save(); void disable_not_applied_warning(); diff --git a/source/blender/blenlib/BLI_virtual_array.hh b/source/blender/blenlib/BLI_virtual_array.hh index d0436bdc213..84f6223580a 100644 --- a/source/blender/blenlib/BLI_virtual_array.hh +++ b/source/blender/blenlib/BLI_virtual_array.hh @@ -51,7 +51,10 @@ struct CommonVArrayInfo { /** True when the #data becomes a dangling pointer when the virtual array is destructed. */ bool may_have_ownership = true; - /** Points either to nothing, a single value or array of values, depending on #type. */ + /** + * Points either to nothing, a single value or array of values, depending on #type. + * If this is a span of a mutable virtual array, it is safe to cast away const. + */ const void *data; CommonVArrayInfo() = default; @@ -1117,15 +1120,15 @@ template<typename T> static constexpr bool is_VMutableArray_v<VMutableArray<T>> * from faster access. * - An API is called, that does not accept virtual arrays, but only spans. */ -template<typename T> class VArray_Span final : public Span<T> { +template<typename T> class VArraySpan final : public Span<T> { private: VArray<T> varray_; Array<T> owned_data_; public: - VArray_Span() = default; + VArraySpan() = default; - VArray_Span(VArray<T> varray) : Span<T>(), varray_(std::move(varray)) + VArraySpan(VArray<T> varray) : Span<T>(), varray_(std::move(varray)) { this->size_ = varray_.size(); const CommonVArrayInfo info = varray_.common_info(); @@ -1140,7 +1143,7 @@ template<typename T> class VArray_Span final : public Span<T> { } } - VArray_Span(VArray_Span &&other) + VArraySpan(VArraySpan &&other) : varray_(std::move(other.varray_)), owned_data_(std::move(other.owned_data_)) { this->size_ = varray_.size(); @@ -1155,25 +1158,25 @@ template<typename T> class VArray_Span final : public Span<T> { other.size_ = 0; } - VArray_Span &operator=(VArray_Span &&other) + VArraySpan &operator=(VArraySpan &&other) { if (this == &other) { return *this; } std::destroy_at(this); - new (this) VArray_Span(std::move(other)); + new (this) VArraySpan(std::move(other)); return *this; } }; /** - * Same as #VArray_Span, but for a mutable span. + * Same as #VArraySpan, but for a mutable span. * The important thing to note is that when changing this span, the results might not be * immediately reflected in the underlying virtual array (only when the virtual array is a span * internally). The #save method can be used to write all changes to the underlying virtual array, * if necessary. */ -template<typename T> class VMutableArray_Span final : public MutableSpan<T> { +template<typename T> class MutableVArraySpan final : public MutableSpan<T> { private: VMutableArray<T> varray_; Array<T> owned_data_; @@ -1183,7 +1186,7 @@ template<typename T> class VMutableArray_Span final : public MutableSpan<T> { public: /* Create a span for any virtual array. This is cheap when the virtual array is a span itself. If * not, a new array has to be allocated as a wrapper for the underlying virtual array. */ - VMutableArray_Span(VMutableArray<T> varray, const bool copy_values_to_span = true) + MutableVArraySpan(VMutableArray<T> varray, const bool copy_values_to_span = true) : MutableSpan<T>(), varray_(std::move(varray)) { this->size_ = varray_.size(); @@ -1204,15 +1207,44 @@ template<typename T> class VMutableArray_Span final : public MutableSpan<T> { } } - ~VMutableArray_Span() + MutableVArraySpan(MutableVArraySpan &&other) + : varray_(std::move(other.varray_)), + owned_data_(std::move(owned_data_)), + show_not_saved_warning_(other.show_not_saved_warning_) + { + this->size_ = varray_.size(); + const CommonVArrayInfo info = varray_.common_info(); + if (info.type == CommonVArrayInfo::Type::Span) { + this->data_ = reinterpret_cast<T *>(info.data); + } + else { + this->data_ = owned_data_.data(); + } + other.data_ = nullptr; + other.size_ = 0; + } + + ~MutableVArraySpan() { - if (show_not_saved_warning_) { - if (!save_has_been_called_) { - std::cout << "Warning: Call `save()` to make sure that changes persist in all cases.\n"; + if (varray_) { + if (show_not_saved_warning_) { + if (!save_has_been_called_) { + std::cout << "Warning: Call `save()` to make sure that changes persist in all cases.\n"; + } } } } + MutableVArraySpan &operator=(MutableVArraySpan &&other) + { + if (this == &other) { + return *this; + } + std::destroy_at(this); + new (this) MutableVArraySpan(std::move(other)); + return *this; + } + /* Write back all values from a temporary allocated array to the underlying virtual array. */ void save() { diff --git a/source/blender/blenlib/intern/generic_virtual_array.cc b/source/blender/blenlib/intern/generic_virtual_array.cc index 624af3c6ed1..1f6e6cd6e18 100644 --- a/source/blender/blenlib/intern/generic_virtual_array.cc +++ b/source/blender/blenlib/intern/generic_virtual_array.cc @@ -284,10 +284,10 @@ template<int BufferSize> class GVArrayImpl_For_SmallTrivialSingleValue : public /** \} */ /* -------------------------------------------------------------------- */ -/** \name #GVArray_GSpan +/** \name #GVArraySpan * \{ */ -GVArray_GSpan::GVArray_GSpan(GVArray varray) : GSpan(varray.type()), varray_(std::move(varray)) +GVArraySpan::GVArraySpan(GVArray varray) : GSpan(varray.type()), varray_(std::move(varray)) { size_ = varray_.size(); const CommonVArrayInfo info = varray_.common_info(); @@ -301,7 +301,22 @@ GVArray_GSpan::GVArray_GSpan(GVArray varray) : GSpan(varray.type()), varray_(std } } -GVArray_GSpan::~GVArray_GSpan() +GVArraySpan::GVArraySpan(GVArraySpan &&other) + : GSpan(other.type()), varray_(std::move(other.varray_)), owned_data_(other.owned_data_) +{ + size_ = varray_.size(); + const CommonVArrayInfo info = varray_.common_info(); + if (info.type == CommonVArrayInfo::Type::Span) { + data_ = info.data; + } + else { + data_ = owned_data_; + } + other.data_ = nullptr; + other.size_ = 0; +} + +GVArraySpan::~GVArraySpan() { if (owned_data_ != nullptr) { type_->destruct_n(owned_data_, size_); @@ -309,13 +324,23 @@ GVArray_GSpan::~GVArray_GSpan() } } +GVArraySpan &GVArraySpan::operator=(GVArraySpan &&other) +{ + if (this == &other) { + return *this; + } + std::destroy_at(this); + new (this) GVArraySpan(std::move(other)); + return *this; +} + /** \} */ /* -------------------------------------------------------------------- */ -/** \name #GVMutableArray_GSpan +/** \name #GMutableVArraySpan * \{ */ -GVMutableArray_GSpan::GVMutableArray_GSpan(GVMutableArray varray, const bool copy_values_to_span) +GMutableVArraySpan::GMutableVArraySpan(GVMutableArray varray, const bool copy_values_to_span) : GMutableSpan(varray.type()), varray_(std::move(varray)) { size_ = varray_.size(); @@ -335,11 +360,31 @@ GVMutableArray_GSpan::GVMutableArray_GSpan(GVMutableArray varray, const bool cop } } -GVMutableArray_GSpan::~GVMutableArray_GSpan() +GMutableVArraySpan::GMutableVArraySpan(GMutableVArraySpan &&other) + : GMutableSpan(other.type()), + varray_(std::move(other.varray_)), + owned_data_(other.owned_data_), + show_not_saved_warning_(other.show_not_saved_warning_) { - if (show_not_saved_warning_) { - if (!save_has_been_called_) { - std::cout << "Warning: Call `apply()` to make sure that changes persist in all cases.\n"; + size_ = varray_.size(); + const CommonVArrayInfo info = varray_.common_info(); + if (info.type == CommonVArrayInfo::Type::Span) { + data_ = const_cast<void *>(info.data); + } + else { + data_ = owned_data_; + } + other.data_ = nullptr; + other.size_ = 0; +} + +GMutableVArraySpan::~GMutableVArraySpan() +{ + if (varray_) { + if (show_not_saved_warning_) { + if (!save_has_been_called_) { + std::cout << "Warning: Call `apply()` to make sure that changes persist in all cases.\n"; + } } } if (owned_data_ != nullptr) { @@ -348,7 +393,17 @@ GVMutableArray_GSpan::~GVMutableArray_GSpan() } } -void GVMutableArray_GSpan::save() +GMutableVArraySpan &GMutableVArraySpan::operator=(GMutableVArraySpan &&other) +{ + if (this == &other) { + return *this; + } + std::destroy_at(this); + new (this) GMutableVArraySpan(std::move(other)); + return *this; +} + +void GMutableVArraySpan::save() { save_has_been_called_ = true; if (data_ != owned_data_) { @@ -357,7 +412,7 @@ void GVMutableArray_GSpan::save() varray_.set_all(owned_data_); } -void GVMutableArray_GSpan::disable_not_applied_warning() +void GMutableVArraySpan::disable_not_applied_warning() { show_not_saved_warning_ = false; } diff --git a/source/blender/blenlib/tests/BLI_virtual_array_test.cc b/source/blender/blenlib/tests/BLI_virtual_array_test.cc index 90c7f1078a5..c3c6d84ea42 100644 --- a/source/blender/blenlib/tests/BLI_virtual_array_test.cc +++ b/source/blender/blenlib/tests/BLI_virtual_array_test.cc @@ -109,7 +109,7 @@ TEST(virtual_array, AsSpan) { auto func = [](int64_t index) { return (int)(10 * index); }; VArray<int> func_varray = VArray<int>::ForFunc(10, func); - VArray_Span span_varray{func_varray}; + VArraySpan span_varray{func_varray}; EXPECT_EQ(span_varray.size(), 10); Span<int> span = span_varray; EXPECT_EQ(span.size(), 10); |