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-06-25 20:27:33 +0300
committerJacques Lucke <jacques@blender.org>2022-06-25 20:27:33 +0300
commit22fc0cbd6966c1e46a28038fca8ef59e8ce50660 (patch)
tree0f6bf65b27f60f7f313fa14daefa662eb3e4678e /source/blender/blenlib/BLI_any.hh
parent3237c6dbe877db1cfbe15e92f6cb267d8a6031ea (diff)
BLI: improve support for trivial virtual arrays
This commits reduces the number of function calls through function pointers in `blender::Any` when the stored type is trivial. Furthermore, this implements marks some classes as trivial, which we know are trivial but the compiler does not (the standard currently says that any class with a virtual destructor is non-trivial). Under some circumstances we know that final child classes are trivial though. This allows for some optimizations. Also see https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1077r0.html.
Diffstat (limited to 'source/blender/blenlib/BLI_any.hh')
-rw-r--r--source/blender/blenlib/BLI_any.hh51
1 files changed, 40 insertions, 11 deletions
diff --git a/source/blender/blenlib/BLI_any.hh b/source/blender/blenlib/BLI_any.hh
index e80dad82d01..a20239f214f 100644
--- a/source/blender/blenlib/BLI_any.hh
+++ b/source/blender/blenlib/BLI_any.hh
@@ -13,6 +13,7 @@
*/
#include <algorithm>
+#include <cstring>
#include <utility>
#include "BLI_memory_utils.hh"
@@ -26,6 +27,7 @@ namespace detail {
* Additional type specific #ExtraInfo can be embedded here as well.
*/
template<typename ExtraInfo> struct AnyTypeInfo {
+ /* The pointers are allowed to be null, which means that the implementation is trivial. */
void (*copy_construct)(void *dst, const void *src);
void (*move_construct)(void *dst, void *src);
void (*destruct)(void *src);
@@ -38,10 +40,15 @@ template<typename ExtraInfo> struct AnyTypeInfo {
*/
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) { std::destroy_at(((T *)src)); },
- [](const void *src) { return src; },
+ is_trivially_copy_constructible_extended_v<T> ?
+ nullptr :
+ +[](void *dst, const void *src) { new (dst) T(*(const T *)src); },
+ is_trivially_move_constructible_extended_v<T> ?
+ nullptr :
+ +[](void *dst, void *src) { new (dst) T(std::move(*(T *)src)); },
+ is_trivially_destructible_extended_v<T> ? nullptr :
+ +[](void *src) { std::destroy_at(((T *)src)); },
+ nullptr,
ExtraInfo::template get<T>()};
/**
@@ -92,12 +99,14 @@ class Any {
using RealExtraInfo =
std::conditional_t<std::is_void_v<ExtraInfo>, detail::NoExtraInfo, ExtraInfo>;
using Info = detail::AnyTypeInfo<RealExtraInfo>;
+ static constexpr size_t RealInlineBufferCapacity = std::max(InlineBufferCapacity,
+ sizeof(std::unique_ptr<int>));
/**
* Inline buffer that either contains nothing, the stored value directly, or a #std::unique_ptr
* to the value.
*/
- AlignedBuffer<std::max(InlineBufferCapacity, sizeof(std::unique_ptr<int>)), Alignment> buffer_{};
+ AlignedBuffer<RealInlineBufferCapacity, Alignment> buffer_{};
/**
* Information about the type that is currently stored.
@@ -144,7 +153,12 @@ class Any {
Any(const Any &other) : info_(other.info_)
{
if (info_ != nullptr) {
- info_->copy_construct(&buffer_, &other.buffer_);
+ if (info_->copy_construct != nullptr) {
+ info_->copy_construct(&buffer_, &other.buffer_);
+ }
+ else {
+ memcpy(&buffer_, &other.buffer_, RealInlineBufferCapacity);
+ }
}
}
@@ -155,7 +169,12 @@ class Any {
Any(Any &&other) noexcept : info_(other.info_)
{
if (info_ != nullptr) {
- info_->move_construct(&buffer_, &other.buffer_);
+ if (info_->move_construct != nullptr) {
+ info_->move_construct(&buffer_, &other.buffer_);
+ }
+ else {
+ memcpy(&buffer_, &other.buffer_, RealInlineBufferCapacity);
+ }
}
}
@@ -179,7 +198,9 @@ class Any {
~Any()
{
if (info_ != nullptr) {
- info_->destruct(&buffer_);
+ if (info_->destruct != nullptr) {
+ info_->destruct(&buffer_);
+ }
}
}
@@ -213,7 +234,9 @@ class Any {
void reset()
{
if (info_ != nullptr) {
- info_->destruct(&buffer_);
+ if (info_->destruct != nullptr) {
+ info_->destruct(&buffer_);
+ }
}
info_ = nullptr;
}
@@ -265,14 +288,20 @@ class Any {
void *get()
{
BLI_assert(info_ != nullptr);
- return const_cast<void *>(info_->get(&buffer_));
+ if (info_->get != nullptr) {
+ return const_cast<void *>(info_->get(&buffer_));
+ }
+ return &buffer_;
}
/** Get a pointer to the stored value. */
const void *get() const
{
BLI_assert(info_ != nullptr);
- return info_->get(&buffer_);
+ if (info_->get != nullptr) {
+ return info_->get(&buffer_);
+ }
+ return &buffer_;
}
/**