From 8edb2222ae0c954771a9cddc2d8c02a7a4d68eae Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Mon, 2 Aug 2021 12:43:35 +0200 Subject: Cleanup: simplify subclassing CPPType `CPPType` can wrap any C++ type so that code can work with the wrapped type in a generic way. The goal of subclassing `CPPType` is to provide additional methods for some types. For example, the `CPPType` for `Array` could have a `.element_type()` method that returns the `CPPType` for `int`. --- source/blender/functions/FN_cpp_type.hh | 178 +++++++++++---------- source/blender/functions/FN_cpp_type_make.hh | 96 +++++------ .../intern/multi_function_network_optimization.cc | 2 +- 3 files changed, 133 insertions(+), 143 deletions(-) (limited to 'source/blender/functions') diff --git a/source/blender/functions/FN_cpp_type.hh b/source/blender/functions/FN_cpp_type.hh index bc3f398c8e9..7277bf99c12 100644 --- a/source/blender/functions/FN_cpp_type.hh +++ b/source/blender/functions/FN_cpp_type.hh @@ -70,64 +70,73 @@ #include "BLI_string_ref.hh" #include "BLI_utility_mixins.hh" +/** + * Different types support different features. Features like copy constructability can be detected + * automatically easily. For some features this is harder as of C++17. Those have flags in this + * enum and need to be determined by the programmer. + */ +enum class CPPTypeFlags { + None = 0, + Hashable = 1 << 0, + Printable = 1 << 1, + EqualityComparable = 1 << 2, + + BasicType = Hashable | Printable | EqualityComparable, +}; +ENUM_OPERATORS(CPPTypeFlags, CPPTypeFlags::EqualityComparable) + namespace blender::fn { -struct CPPTypeMembers { - int64_t size = 0; - int64_t alignment = 0; - uintptr_t alignment_mask = 0; - bool is_trivially_destructible = false; - bool has_special_member_functions = false; +/** Utility class to pass template parameters to constructor of `CPPType`. */ +template struct CPPTypeParam { +}; - void (*default_construct)(void *ptr) = nullptr; - void (*default_construct_indices)(void *ptr, IndexMask mask) = nullptr; +class CPPType : NonCopyable, NonMovable { + private: + int64_t size_ = 0; + int64_t alignment_ = 0; + uintptr_t alignment_mask_ = 0; + bool is_trivially_destructible_ = false; + bool has_special_member_functions_ = false; - void (*destruct)(void *ptr) = nullptr; - void (*destruct_indices)(void *ptr, IndexMask mask) = nullptr; + void (*default_construct_)(void *ptr) = nullptr; + void (*default_construct_indices_)(void *ptr, IndexMask mask) = nullptr; - void (*copy_assign)(const void *src, void *dst) = nullptr; - void (*copy_assign_indices)(const void *src, void *dst, IndexMask mask) = nullptr; + void (*destruct_)(void *ptr) = nullptr; + void (*destruct_indices_)(void *ptr, IndexMask mask) = nullptr; - void (*copy_construct)(const void *src, void *dst) = nullptr; - void (*copy_construct_indices)(const void *src, void *dst, IndexMask mask) = nullptr; + void (*copy_assign_)(const void *src, void *dst) = nullptr; + void (*copy_assign_indices_)(const void *src, void *dst, IndexMask mask) = nullptr; - void (*move_assign)(void *src, void *dst) = nullptr; - void (*move_assign_indices)(void *src, void *dst, IndexMask mask) = nullptr; + void (*copy_construct_)(const void *src, void *dst) = nullptr; + void (*copy_construct_indices_)(const void *src, void *dst, IndexMask mask) = nullptr; - void (*move_construct)(void *src, void *dst) = nullptr; - void (*move_construct_indices)(void *src, void *dst, IndexMask mask) = nullptr; + void (*move_assign_)(void *src, void *dst) = nullptr; + void (*move_assign_indices_)(void *src, void *dst, IndexMask mask) = nullptr; - void (*relocate_assign)(void *src, void *dst) = nullptr; - void (*relocate_assign_indices)(void *src, void *dst, IndexMask mask) = nullptr; + void (*move_construct_)(void *src, void *dst) = nullptr; + void (*move_construct_indices_)(void *src, void *dst, IndexMask mask) = nullptr; - void (*relocate_construct)(void *src, void *dst) = nullptr; - void (*relocate_construct_indices)(void *src, void *dst, IndexMask mask) = nullptr; + void (*relocate_assign_)(void *src, void *dst) = nullptr; + void (*relocate_assign_indices_)(void *src, void *dst, IndexMask mask) = nullptr; - void (*fill_assign_indices)(const void *value, void *dst, IndexMask mask) = nullptr; + void (*relocate_construct_)(void *src, void *dst) = nullptr; + void (*relocate_construct_indices_)(void *src, void *dst, IndexMask mask) = nullptr; - void (*fill_construct_indices)(const void *value, void *dst, IndexMask mask) = nullptr; + void (*fill_assign_indices_)(const void *value, void *dst, IndexMask mask) = nullptr; - void (*print)(const void *value, std::stringstream &ss) = nullptr; - bool (*is_equal)(const void *a, const void *b) = nullptr; - uint64_t (*hash)(const void *value) = nullptr; + void (*fill_construct_indices_)(const void *value, void *dst, IndexMask mask) = nullptr; - const void *default_value = nullptr; - std::string name; -}; + void (*print_)(const void *value, std::stringstream &ss) = nullptr; + bool (*is_equal_)(const void *a, const void *b) = nullptr; + uint64_t (*hash_)(const void *value) = nullptr; -class CPPType : NonCopyable, NonMovable { - private: - CPPTypeMembers m_; + const void *default_value_ = nullptr; + std::string debug_name_; public: - CPPType(CPPTypeMembers members) : m_(std::move(members)) - { - BLI_assert(is_power_of_2_i(m_.alignment)); - m_.alignment_mask = (uintptr_t)members.alignment - (uintptr_t)1; - m_.has_special_member_functions = (m_.default_construct && m_.copy_construct && - m_.copy_assign && m_.move_construct && m_.move_assign && - m_.destruct); - } + template CPPType(CPPTypeParam, StringRef debug_name); + virtual ~CPPType() = default; /** * Two types only compare equal when their pointer is equal. No two instances of CPPType for the @@ -148,7 +157,11 @@ class CPPType : NonCopyable, NonMovable { * This only works for types that actually implement the template specialization using * `MAKE_CPP_TYPE`. */ - template static const CPPType &get(); + template static const CPPType &get() + { + return CPPType::get_impl>(); + } + template static const CPPType &get_impl(); /** * Returns the name of the type for debugging purposes. This name should not be used as @@ -156,7 +169,7 @@ class CPPType : NonCopyable, NonMovable { */ StringRefNull name() const { - return m_.name; + return debug_name_; } /** @@ -167,7 +180,7 @@ class CPPType : NonCopyable, NonMovable { */ int64_t size() const { - return m_.size; + return size_; } /** @@ -178,7 +191,7 @@ class CPPType : NonCopyable, NonMovable { */ int64_t alignment() const { - return m_.alignment; + return alignment_; } /** @@ -190,52 +203,52 @@ class CPPType : NonCopyable, NonMovable { */ bool is_trivially_destructible() const { - return m_.is_trivially_destructible; + return is_trivially_destructible_; } bool is_default_constructible() const { - return m_.default_construct != nullptr; + return default_construct_ != nullptr; } bool is_copy_constructible() const { - return m_.copy_assign != nullptr; + return copy_assign_ != nullptr; } bool is_move_constructible() const { - return m_.move_assign != nullptr; + return move_assign_ != nullptr; } bool is_destructible() const { - return m_.destruct != nullptr; + return destruct_ != nullptr; } bool is_copy_assignable() const { - return m_.copy_assign != nullptr; + return copy_assign_ != nullptr; } bool is_move_assignable() const { - return m_.copy_construct != nullptr; + return copy_construct_ != nullptr; } bool is_printable() const { - return m_.print != nullptr; + return print_ != nullptr; } bool is_equality_comparable() const { - return m_.is_equal != nullptr; + return is_equal_ != nullptr; } bool is_hashable() const { - return m_.hash != nullptr; + return hash_ != nullptr; } /** @@ -249,7 +262,7 @@ class CPPType : NonCopyable, NonMovable { */ bool has_special_member_functions() const { - return m_.has_special_member_functions; + return has_special_member_functions_; } /** @@ -257,7 +270,7 @@ class CPPType : NonCopyable, NonMovable { */ bool pointer_has_valid_alignment(const void *ptr) const { - return ((uintptr_t)ptr & m_.alignment_mask) == 0; + return ((uintptr_t)ptr & alignment_mask_) == 0; } bool pointer_can_point_to_instance(const void *ptr) const @@ -277,7 +290,7 @@ class CPPType : NonCopyable, NonMovable { { BLI_assert(this->pointer_can_point_to_instance(ptr)); - m_.default_construct(ptr); + default_construct_(ptr); } void default_construct_n(void *ptr, int64_t n) const @@ -289,7 +302,7 @@ class CPPType : NonCopyable, NonMovable { { BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(ptr)); - m_.default_construct_indices(ptr, mask); + default_construct_indices_(ptr, mask); } /** @@ -304,7 +317,7 @@ class CPPType : NonCopyable, NonMovable { { BLI_assert(this->pointer_can_point_to_instance(ptr)); - m_.destruct(ptr); + destruct_(ptr); } void destruct_n(void *ptr, int64_t n) const @@ -316,7 +329,7 @@ class CPPType : NonCopyable, NonMovable { { BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(ptr)); - m_.destruct_indices(ptr, mask); + destruct_indices_(ptr, mask); } /** @@ -331,7 +344,7 @@ class CPPType : NonCopyable, NonMovable { BLI_assert(this->pointer_can_point_to_instance(src)); BLI_assert(this->pointer_can_point_to_instance(dst)); - m_.copy_assign(src, dst); + copy_assign_(src, dst); } void copy_assign_n(const void *src, void *dst, int64_t n) const @@ -345,7 +358,7 @@ class CPPType : NonCopyable, NonMovable { BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src)); BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst)); - m_.copy_assign_indices(src, dst, mask); + copy_assign_indices_(src, dst, mask); } /** @@ -362,7 +375,7 @@ class CPPType : NonCopyable, NonMovable { BLI_assert(this->pointer_can_point_to_instance(src)); BLI_assert(this->pointer_can_point_to_instance(dst)); - m_.copy_construct(src, dst); + copy_construct_(src, dst); } void copy_construct_n(const void *src, void *dst, int64_t n) const @@ -376,7 +389,7 @@ class CPPType : NonCopyable, NonMovable { BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src)); BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst)); - m_.copy_construct_indices(src, dst, mask); + copy_construct_indices_(src, dst, mask); } /** @@ -393,7 +406,7 @@ class CPPType : NonCopyable, NonMovable { BLI_assert(this->pointer_can_point_to_instance(src)); BLI_assert(this->pointer_can_point_to_instance(dst)); - m_.move_assign(src, dst); + move_assign_(src, dst); } void move_assign_n(void *src, void *dst, int64_t n) const @@ -407,7 +420,7 @@ class CPPType : NonCopyable, NonMovable { BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src)); BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst)); - m_.move_assign_indices(src, dst, mask); + move_assign_indices_(src, dst, mask); } /** @@ -424,7 +437,7 @@ class CPPType : NonCopyable, NonMovable { BLI_assert(this->pointer_can_point_to_instance(src)); BLI_assert(this->pointer_can_point_to_instance(dst)); - m_.move_construct(src, dst); + move_construct_(src, dst); } void move_construct_n(void *src, void *dst, int64_t n) const @@ -438,7 +451,7 @@ class CPPType : NonCopyable, NonMovable { BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src)); BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst)); - m_.move_construct_indices(src, dst, mask); + move_construct_indices_(src, dst, mask); } /** @@ -455,7 +468,7 @@ class CPPType : NonCopyable, NonMovable { BLI_assert(this->pointer_can_point_to_instance(src)); BLI_assert(this->pointer_can_point_to_instance(dst)); - m_.relocate_assign(src, dst); + relocate_assign_(src, dst); } void relocate_assign_n(void *src, void *dst, int64_t n) const @@ -469,7 +482,7 @@ class CPPType : NonCopyable, NonMovable { BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src)); BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst)); - m_.relocate_assign_indices(src, dst, mask); + relocate_assign_indices_(src, dst, mask); } /** @@ -486,7 +499,7 @@ class CPPType : NonCopyable, NonMovable { BLI_assert(this->pointer_can_point_to_instance(src)); BLI_assert(this->pointer_can_point_to_instance(dst)); - m_.relocate_construct(src, dst); + relocate_construct_(src, dst); } void relocate_construct_n(void *src, void *dst, int64_t n) const @@ -500,7 +513,7 @@ class CPPType : NonCopyable, NonMovable { BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src)); BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst)); - m_.relocate_construct_indices(src, dst, mask); + relocate_construct_indices_(src, dst, mask); } /** @@ -518,7 +531,7 @@ class CPPType : NonCopyable, NonMovable { BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(value)); BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst)); - m_.fill_assign_indices(value, dst, mask); + fill_assign_indices_(value, dst, mask); } /** @@ -536,13 +549,13 @@ class CPPType : NonCopyable, NonMovable { BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(value)); BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst)); - m_.fill_construct_indices(value, dst, mask); + fill_construct_indices_(value, dst, mask); } void print(const void *value, std::stringstream &ss) const { BLI_assert(this->pointer_can_point_to_instance(value)); - m_.print(value, ss); + print_(value, ss); } std::string to_string(const void *value) const @@ -566,7 +579,7 @@ class CPPType : NonCopyable, NonMovable { { BLI_assert(this->pointer_can_point_to_instance(a)); BLI_assert(this->pointer_can_point_to_instance(b)); - return m_.is_equal(a, b); + return is_equal_(a, b); } bool is_equal_or_false(const void *a, const void *b) const @@ -580,7 +593,7 @@ class CPPType : NonCopyable, NonMovable { uint64_t hash(const void *value) const { BLI_assert(this->pointer_can_point_to_instance(value)); - return m_.hash(value); + return hash_(value); } uint64_t hash_or_fallback(const void *value, uint64_t fallback_hash) const @@ -597,7 +610,7 @@ class CPPType : NonCopyable, NonMovable { */ const void *default_value() const { - return m_.default_value; + return default_value_; } uint64_t hash() const @@ -605,12 +618,9 @@ class CPPType : NonCopyable, NonMovable { return get_default_hash(this); } - /** - * Low level access to the callbacks for this CPPType. - */ - const CPPTypeMembers &members() const + void (*destruct_fn() const)(void *) { - return m_; + return destruct_; } template bool is() const diff --git a/source/blender/functions/FN_cpp_type_make.hh b/source/blender/functions/FN_cpp_type_make.hh index b8e5373ccf7..088f6b469f4 100644 --- a/source/blender/functions/FN_cpp_type_make.hh +++ b/source/blender/functions/FN_cpp_type_make.hh @@ -185,100 +185,80 @@ template uint64_t hash_cb(const void *value) } // namespace blender::fn::cpp_type_util -/** - * Different types support different features. Features like copy constructability can be detected - * automatically easily. For some features this is harder as of C++17. Those have flags in this - * enum and need to be determined by the programmer. - */ -enum class CPPTypeFlags { - None = 0, - Hashable = 1 << 0, - Printable = 1 << 1, - EqualityComparable = 1 << 2, - - BasicType = Hashable | Printable | EqualityComparable, -}; -ENUM_OPERATORS(CPPTypeFlags, CPPTypeFlags::EqualityComparable) - namespace blender::fn { -template -inline std::unique_ptr create_cpp_type(StringRef name) +template +CPPType::CPPType(CPPTypeParam /* unused */, StringRef debug_name) { using namespace cpp_type_util; - CPPTypeMembers m; - m.name = name; - m.size = (int64_t)sizeof(T); - m.alignment = (int64_t)alignof(T); - m.is_trivially_destructible = std::is_trivially_destructible_v; + debug_name_ = debug_name; + size_ = (int64_t)sizeof(T); + alignment_ = (int64_t)alignof(T); + is_trivially_destructible_ = std::is_trivially_destructible_v; if constexpr (std::is_default_constructible_v) { - m.default_construct = default_construct_cb; - m.default_construct_indices = default_construct_indices_cb; + default_construct_ = default_construct_cb; + default_construct_indices_ = default_construct_indices_cb; static T default_value; - m.default_value = (void *)&default_value; + default_value_ = (void *)&default_value; } if constexpr (std::is_destructible_v) { - m.destruct = destruct_cb; - m.destruct_indices = destruct_indices_cb; + destruct_ = destruct_cb; + destruct_indices_ = destruct_indices_cb; } if constexpr (std::is_copy_assignable_v) { - m.copy_assign = copy_assign_cb; - m.copy_assign_indices = copy_assign_indices_cb; + copy_assign_ = copy_assign_cb; + copy_assign_indices_ = copy_assign_indices_cb; } if constexpr (std::is_copy_constructible_v) { - m.copy_construct = copy_construct_cb; - m.copy_construct_indices = copy_construct_indices_cb; + copy_construct_ = copy_construct_cb; + copy_construct_indices_ = copy_construct_indices_cb; } if constexpr (std::is_move_assignable_v) { - m.move_assign = move_assign_cb; - m.move_assign_indices = move_assign_indices_cb; + move_assign_ = move_assign_cb; + move_assign_indices_ = move_assign_indices_cb; } if constexpr (std::is_move_constructible_v) { - m.move_construct = move_construct_cb; - m.move_construct_indices = move_construct_indices_cb; + move_construct_ = move_construct_cb; + move_construct_indices_ = move_construct_indices_cb; } if constexpr (std::is_destructible_v) { if constexpr (std::is_move_assignable_v) { - m.relocate_assign = relocate_assign_cb; - m.relocate_assign_indices = relocate_assign_indices_cb; + relocate_assign_ = relocate_assign_cb; + relocate_assign_indices_ = relocate_assign_indices_cb; } if constexpr (std::is_move_constructible_v) { - m.relocate_construct = relocate_construct_cb; - m.relocate_construct_indices = relocate_construct_indices_cb; + relocate_construct_ = relocate_construct_cb; + relocate_construct_indices_ = relocate_construct_indices_cb; } } if constexpr (std::is_copy_assignable_v) { - m.fill_assign_indices = fill_assign_indices_cb; + fill_assign_indices_ = fill_assign_indices_cb; } if constexpr (std::is_copy_constructible_v) { - m.fill_construct_indices = fill_construct_indices_cb; + fill_construct_indices_ = fill_construct_indices_cb; } - if constexpr ((bool)(flags & CPPTypeFlags::Hashable)) { - m.hash = hash_cb; + if constexpr ((bool)(Flags & CPPTypeFlags::Hashable)) { + hash_ = hash_cb; } - if constexpr ((bool)(flags & CPPTypeFlags::Printable)) { - m.print = print_cb; + if constexpr ((bool)(Flags & CPPTypeFlags::Printable)) { + print_ = print_cb; } - if constexpr ((bool)(flags & CPPTypeFlags::EqualityComparable)) { - m.is_equal = is_equal_cb; + if constexpr ((bool)(Flags & CPPTypeFlags::EqualityComparable)) { + is_equal_ = is_equal_cb; } - const CPPType *type = new CPPType(std::move(m)); - return std::unique_ptr(type); + alignment_mask_ = (uintptr_t)alignment_ - (uintptr_t)1; + has_special_member_functions_ = (default_construct_ && copy_construct_ && copy_assign_ && + move_construct_ && move_assign_ && destruct_); } } // namespace blender::fn #define MAKE_CPP_TYPE(IDENTIFIER, TYPE_NAME, FLAGS) \ - template<> const blender::fn::CPPType &blender::fn::CPPType::get() \ - { \ - static std::unique_ptr cpp_type = \ - blender::fn::create_cpp_type(STRINGIFY(IDENTIFIER)); \ - return *cpp_type; \ - } \ - /* Support using `CPPType::get()`. Otherwise the caller would have to remove const. */ \ - template<> const blender::fn::CPPType &blender::fn::CPPType::get() \ + template<> const blender::fn::CPPType &blender::fn::CPPType::get_impl() \ { \ - return blender::fn::CPPType::get(); \ + static CPPType cpp_type{blender::fn::CPPTypeParam(), \ + STRINGIFY(IDENTIFIER)}; \ + return cpp_type; \ } diff --git a/source/blender/functions/intern/multi_function_network_optimization.cc b/source/blender/functions/intern/multi_function_network_optimization.cc index 0f65d320f62..75c3583c5e5 100644 --- a/source/blender/functions/intern/multi_function_network_optimization.cc +++ b/source/blender/functions/intern/multi_function_network_optimization.cc @@ -263,7 +263,7 @@ static Array add_constant_folded_sockets(const MultiFunction & const CPPType &cpp_type = data_type.single_type(); GMutableSpan array = params.computed_array(param_index); void *buffer = array.data(); - scope.add(buffer, array.type().members().destruct, AT); + scope.add(buffer, array.type().destruct_fn(), AT); constant_fn = &scope.construct(AT, cpp_type, buffer); break; -- cgit v1.2.3