Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <jacques@blender.org>2022-04-25 12:51:22 +0300
committerJacques Lucke <jacques@blender.org>2022-04-25 12:51:34 +0300
commita2d32960b4de78f545ce52e92185eefd3c93fde1 (patch)
treed07f2c21566f223bd62731ee06e78984caaa17f5 /source/blender/blenlib
parentc63d64a2ce3e49188628d54450b751fd764b8a67 (diff)
BLI: optimize constructing new virtual array
Differential Revision: https://developer.blender.org/D14745
Diffstat (limited to 'source/blender/blenlib')
-rw-r--r--source/blender/blenlib/BLI_any.hh129
-rw-r--r--source/blender/blenlib/BLI_generic_virtual_array.hh4
-rw-r--r--source/blender/blenlib/BLI_virtual_array.hh8
-rw-r--r--source/blender/blenlib/intern/generic_virtual_array.cc3
-rw-r--r--source/blender/blenlib/tests/BLI_any_test.cc2
5 files changed, 77 insertions, 69 deletions
diff --git a/source/blender/blenlib/BLI_any.hh b/source/blender/blenlib/BLI_any.hh
index 4424ad29a21..875e7cce056 100644
--- a/source/blender/blenlib/BLI_any.hh
+++ b/source/blender/blenlib/BLI_any.hh
@@ -31,55 +31,37 @@ template<typename ExtraInfo> struct AnyTypeInfo {
void (*destruct)(void *src);
const void *(*get)(const void *src);
ExtraInfo extra_info;
+};
- /**
- * Used when #T is stored directly in the inline buffer of the #Any.
- */
- template<typename T> static const AnyTypeInfo &get_for_inline()
- {
- static AnyTypeInfo funcs = {[](void *dst, const void *src) { new (dst) T(*(const T *)src); },
- [](void *dst, void *src) { new (dst) T(std::move(*(T *)src)); },
- [](void *src) { ((T *)src)->~T(); },
- [](const void *src) { return src; },
- ExtraInfo::template get<T>()};
- return funcs;
- }
-
- /**
- * Used when #T can't be stored directly in the inline buffer and is stored in a #std::unique_ptr
- * instead. In this scenario, the #std::unique_ptr is stored in the inline buffer.
- */
- template<typename T> static const AnyTypeInfo &get_for_unique_ptr()
- {
- using Ptr = std::unique_ptr<T>;
- static AnyTypeInfo funcs = {
- [](void *dst, const void *src) { new (dst) Ptr(new T(**(const Ptr *)src)); },
- [](void *dst, void *src) { new (dst) Ptr(new T(std::move(**(Ptr *)src))); },
- [](void *src) { ((Ptr *)src)->~Ptr(); },
- [](const void *src) -> const void * { return &**(const Ptr *)src; },
- ExtraInfo::template get<T>()};
- return funcs;
- }
+/**
+ * Used when #T is stored directly in the inline buffer of the #Any.
+ */
+template<typename ExtraInfo, typename T>
+static constexpr AnyTypeInfo<ExtraInfo> info_for_inline = {
+ [](void *dst, const void *src) { new (dst) T(*(const T *)src); },
+ [](void *dst, void *src) { new (dst) T(std::move(*(T *)src)); },
+ [](void *src) { ((T *)src)->~T(); },
+ [](const void *src) { return src; },
+ ExtraInfo::template get<T>()};
- /**
- * Used when the #Any does not contain any type currently.
- */
- static const AnyTypeInfo &get_for_empty()
- {
- static AnyTypeInfo funcs = {[](void *UNUSED(dst), const void *UNUSED(src)) {},
- [](void *UNUSED(dst), void *UNUSED(src)) {},
- [](void *UNUSED(src)) {},
- [](const void *UNUSED(src)) -> const void * { return nullptr; },
- ExtraInfo{}};
- return funcs;
- }
-};
+/**
+ * Used when #T can't be stored directly in the inline buffer and is stored in a #std::unique_ptr
+ * instead. In this scenario, the #std::unique_ptr is stored in the inline buffer.
+ */
+template<typename T> using Ptr = std::unique_ptr<T>;
+template<typename ExtraInfo, typename T>
+static constexpr AnyTypeInfo<ExtraInfo> info_for_unique_ptr = {
+ [](void *dst, const void *src) { new (dst) Ptr<T>(new T(**(const Ptr<T> *)src)); },
+ [](void *dst, void *src) { new (dst) Ptr<T>(new T(std::move(**(Ptr<T> *)src))); },
+ [](void *src) { ((Ptr<T> *)src)->~Ptr<T>(); },
+ [](const void *src) -> const void * { return &**(const Ptr<T> *)src; },
+ ExtraInfo::template get<T>()};
/**
* Dummy extra info that is used when no additional type information should be stored in the #Any.
*/
struct NoExtraInfo {
- template<typename T> static NoExtraInfo get()
+ template<typename T> static constexpr NoExtraInfo get()
{
return {};
}
@@ -119,8 +101,9 @@ class Any {
/**
* Information about the type that is currently stored.
+ * This is null when the #Any does not contain a value.
*/
- const Info *info_ = &Info::get_for_empty();
+ const Info *info_ = nullptr;
public:
/** Only copy constructible types can be stored in #Any. */
@@ -148,10 +131,10 @@ class Any {
using DecayT = std::decay_t<T>;
static_assert(is_allowed_v<DecayT>);
if constexpr (is_inline_v<DecayT>) {
- return Info::template get_for_inline<DecayT>();
+ return detail::template info_for_inline<RealExtraInfo, DecayT>;
}
else {
- return Info::template get_for_unique_ptr<DecayT>();
+ return detail::template info_for_unique_ptr<RealExtraInfo, DecayT>;
}
}
@@ -160,7 +143,9 @@ class Any {
Any(const Any &other) : info_(other.info_)
{
- info_->copy_construct(&buffer_, &other.buffer_);
+ if (info_ != nullptr) {
+ info_->copy_construct(&buffer_, &other.buffer_);
+ }
}
/**
@@ -169,7 +154,9 @@ class Any {
*/
Any(Any &&other) noexcept : info_(other.info_)
{
- info_->move_construct(&buffer_, &other.buffer_);
+ if (info_ != nullptr) {
+ info_->move_construct(&buffer_, &other.buffer_);
+ }
}
/**
@@ -178,18 +165,7 @@ class Any {
*/
template<typename T, typename... Args> explicit Any(std::in_place_type_t<T>, Args &&...args)
{
- using DecayT = std::decay_t<T>;
- static_assert(is_allowed_v<DecayT>);
- info_ = &this->template get_info<DecayT>();
- if constexpr (is_inline_v<DecayT>) {
- /* Construct the value directly in the inline buffer. */
- new (&buffer_) DecayT(std::forward<Args>(args)...);
- }
- else {
- /* Construct the value in a new allocation and store a #std::unique_ptr to it in the inline
- * buffer. */
- new (&buffer_) std::unique_ptr<DecayT>(new DecayT(std::forward<Args>(args)...));
- }
+ this->emplace_on_empty<T>(std::forward<Args>(args)...);
}
/**
@@ -202,7 +178,9 @@ class Any {
~Any()
{
- info_->destruct(&buffer_);
+ if (info_ != nullptr) {
+ info_->destruct(&buffer_);
+ }
}
/**
@@ -234,8 +212,10 @@ class Any {
/** Destruct any existing value to make it empty. */
void reset()
{
- info_->destruct(&buffer_);
- info_ = &Info::get_for_empty();
+ if (info_ != nullptr) {
+ info_->destruct(&buffer_);
+ }
+ info_ = nullptr;
}
operator bool() const
@@ -245,7 +225,7 @@ class Any {
bool has_value() const
{
- return info_ != &Info::get_for_empty();
+ return info_ != nullptr;
}
template<typename T, typename... Args> std::decay_t<T> &emplace(Args &&...args)
@@ -255,6 +235,26 @@ class Any {
return this->get<T>();
}
+ template<typename T, typename... Args> std::decay_t<T> &emplace_on_empty(Args &&...args)
+ {
+ BLI_assert(!this->has_value());
+ using DecayT = std::decay_t<T>;
+ static_assert(is_allowed_v<DecayT>);
+ info_ = &this->template get_info<DecayT>();
+ if constexpr (is_inline_v<DecayT>) {
+ /* Construct the value directly in the inline buffer. */
+ DecayT *stored_value = new (&buffer_) DecayT(std::forward<Args>(args)...);
+ return *stored_value;
+ }
+ else {
+ /* Construct the value in a new allocation and store a #std::unique_ptr to it in the inline
+ * buffer. */
+ std::unique_ptr<DecayT> *stored_value = new (&buffer_)
+ std::unique_ptr<DecayT>(new DecayT(std::forward<Args>(args)...));
+ return **stored_value;
+ }
+ }
+
/** Return true when the value that is currently stored is a #T. */
template<typename T> bool is() const
{
@@ -264,12 +264,14 @@ class Any {
/** Get a pointer to the stored value. */
void *get()
{
+ BLI_assert(info_ != nullptr);
return const_cast<void *>(info_->get(&buffer_));
}
/** Get a pointer to the stored value. */
const void *get() const
{
+ BLI_assert(info_ != nullptr);
return info_->get(&buffer_);
}
@@ -298,6 +300,7 @@ class Any {
*/
const RealExtraInfo &extra_info() const
{
+ BLI_assert(info_ != nullptr);
return info_->extra_info;
}
};
diff --git a/source/blender/blenlib/BLI_generic_virtual_array.hh b/source/blender/blenlib/BLI_generic_virtual_array.hh
index 2e756e912f9..d02760d9178 100644
--- a/source/blender/blenlib/BLI_generic_virtual_array.hh
+++ b/source/blender/blenlib/BLI_generic_virtual_array.hh
@@ -83,7 +83,7 @@ struct GVArrayAnyExtraInfo {
const GVArrayImpl *(*get_varray)(const void *buffer) =
[](const void *UNUSED(buffer)) -> const GVArrayImpl * { return nullptr; };
- template<typename StorageT> static GVArrayAnyExtraInfo get();
+ template<typename StorageT> static constexpr GVArrayAnyExtraInfo get();
};
} // namespace detail
@@ -810,7 +810,7 @@ inline bool GVArrayCommon::is_empty() const
* \{ */
namespace detail {
-template<typename StorageT> inline GVArrayAnyExtraInfo GVArrayAnyExtraInfo::get()
+template<typename StorageT> constexpr GVArrayAnyExtraInfo GVArrayAnyExtraInfo::get()
{
static_assert(std::is_base_of_v<GVArrayImpl, StorageT> ||
is_same_any_v<StorageT, const GVArrayImpl *, std::shared_ptr<const GVArrayImpl>>);
diff --git a/source/blender/blenlib/BLI_virtual_array.hh b/source/blender/blenlib/BLI_virtual_array.hh
index 453ca67b1e0..41a73b45853 100644
--- a/source/blender/blenlib/BLI_virtual_array.hh
+++ b/source/blender/blenlib/BLI_virtual_array.hh
@@ -564,10 +564,9 @@ template<typename T> struct VArrayAnyExtraInfo {
/**
* Gets the virtual array that is stored at the given pointer.
*/
- const VArrayImpl<T> *(*get_varray)(const void *buffer) =
- [](const void *UNUSED(buffer)) -> const VArrayImpl<T> * { return nullptr; };
+ const VArrayImpl<T> *(*get_varray)(const void *buffer);
- template<typename StorageT> static VArrayAnyExtraInfo get()
+ template<typename StorageT> static constexpr VArrayAnyExtraInfo get()
{
/* These are the only allowed types in the #Any. */
static_assert(
@@ -711,6 +710,9 @@ template<typename T> class VArrayCommon {
* null. */
const VArrayImpl<T> *impl_from_storage() const
{
+ if (!storage_.has_value()) {
+ return nullptr;
+ }
return storage_.extra_info().get_varray(storage_.get());
}
diff --git a/source/blender/blenlib/intern/generic_virtual_array.cc b/source/blender/blenlib/intern/generic_virtual_array.cc
index e1a150c3f08..a3a17952a97 100644
--- a/source/blender/blenlib/intern/generic_virtual_array.cc
+++ b/source/blender/blenlib/intern/generic_virtual_array.cc
@@ -643,6 +643,9 @@ void GVArrayCommon::get_internal_single_to_uninitialized(void *r_value) const
const GVArrayImpl *GVArrayCommon::impl_from_storage() const
{
+ if (!storage_.has_value()) {
+ return nullptr;
+ }
return storage_.extra_info().get_varray(storage_.get());
}
diff --git a/source/blender/blenlib/tests/BLI_any_test.cc b/source/blender/blenlib/tests/BLI_any_test.cc
index 2830fe8b320..bf592e74206 100644
--- a/source/blender/blenlib/tests/BLI_any_test.cc
+++ b/source/blender/blenlib/tests/BLI_any_test.cc
@@ -90,7 +90,7 @@ TEST(any, AssignAny)
struct ExtraSizeInfo {
size_t size;
- template<typename T> static ExtraSizeInfo get()
+ template<typename T> static constexpr ExtraSizeInfo get()
{
return {sizeof(T)};
}