[Bf-blender-cvs] [b75cdf36a88] functions-experimental-refactor: new tuple implementation
Jacques Lucke
noreply at git.blender.org
Tue Oct 15 15:56:13 CEST 2019
Commit: b75cdf36a8816e9fee66dd89380d0dadefdb8e23
Author: Jacques Lucke
Date: Tue Oct 1 22:27:46 2019 +0200
Branches: functions-experimental-refactor
https://developer.blender.org/rBb75cdf36a8816e9fee66dd89380d0dadefdb8e23
new tuple implementation
===================================================================
A source/blender/blenkernel/BKE_tuple.h
M source/blender/blenkernel/BKE_type_cpp.h
M source/blender/blenkernel/CMakeLists.txt
A source/blender/blenkernel/intern/tuple.cc
===================================================================
diff --git a/source/blender/blenkernel/BKE_tuple.h b/source/blender/blenkernel/BKE_tuple.h
new file mode 100644
index 00000000000..13ff792c654
--- /dev/null
+++ b/source/blender/blenkernel/BKE_tuple.h
@@ -0,0 +1,391 @@
+#ifndef __BKE_TUPLE_H__
+#define __BKE_TUPLE_H__
+
+#include "BLI_vector.h"
+
+#include "BKE_type_cpp.h"
+#include "BKE_types_cpp.h"
+
+namespace BKE {
+
+using BLI::ArrayRef;
+using BLI::Vector;
+
+class TupleInfo : BLI::NonCopyable, BLI::NonMovable {
+ private:
+ Vector<uint> m_offsets;
+ Vector<TypeCPP *> m_types;
+ uint m_alignment;
+ uintptr_t m_do_align_mask;
+ uint m_size__data;
+ uint m_size__data_and_init;
+ uint m_size__alignable_data_and_init;
+ bool m_all_trivially_destructible;
+
+ public:
+ TupleInfo(Vector<TypeCPP *> types);
+
+ ArrayRef<TypeCPP *> types() const
+ {
+ return m_types;
+ }
+
+ TypeCPP &type_at_index(uint index) const
+ {
+ return *m_types[index];
+ }
+
+ uint offset_of_index(uint index) const
+ {
+ return m_offsets[index];
+ }
+
+ uint size_of_data() const
+ {
+ return m_size__data;
+ }
+
+ uint size_of_init() const
+ {
+ return m_size__data_and_init - m_size__data;
+ }
+
+ uint size_of_data_and_init() const
+ {
+ return m_size__data_and_init;
+ }
+
+ uint size_of_alignable_data_and_init() const
+ {
+ return m_size__alignable_data_and_init;
+ }
+
+ void *align_data_buffer(void *ptr) const
+ {
+ uintptr_t ptr_i = (uintptr_t)ptr;
+ uintptr_t aligned_ptr_i = ptr_i & m_do_align_mask;
+ void *aligned_ptr = (void *)aligned_ptr_i;
+ return aligned_ptr;
+ }
+
+ uint size() const
+ {
+ return m_types.size();
+ }
+
+ uint alignment() const
+ {
+ return m_alignment;
+ }
+
+ bool all_trivially_destructible() const
+ {
+ return m_all_trivially_destructible;
+ }
+
+ template<typename T> bool element_has_type(uint index) const
+ {
+ TypeCPP *expected_type = m_types[index];
+ TypeCPP *actual_type == get_type_cpp<T>();
+ return expected_type == actual_type;
+ }
+};
+
+class TupleRef {
+ private:
+ TupleInfo *m_info;
+ void *m_data;
+ bool *m_init;
+
+ TupleRef(TupleInfo &info, void *data, bool *init) : m_info(&info), m_data(data), m_init(init)
+ {
+ BLI_assert(m_info != nullptr);
+ BLI_assert(m_data != nullptr);
+ BLI_assert(m_init != nullptr);
+ BLI_assert(POINTER_AS_UINT(data) % m_info->alignment() == 0);
+ }
+
+ public:
+ static TupleRef FromPreparedBuffers(TupleInfo &info, void *data, bool *init)
+ {
+ return TupleRef(info, data, init);
+ }
+
+ static TupleRef FromAlignableBuffer(TupleInfo &info, void *alignable_buffer)
+ {
+ void *data = info.align_data_buffer(alignable_buffer);
+ bool *init = (bool *)POINTER_OFFSET(data, info.size_of_data());
+ return TupleRef(info, data, init);
+ }
+
+ ~TupleRef() = default;
+
+ template<typename T> void copy_in(uint index, const T &value)
+ {
+ BLI_assert(index < m_info->size());
+ BLI_assert(m_info->element_has_type<T>(index));
+
+ T *dst = (T *)this->element_ptr<T>(index);
+ if (std::is_trivially_copyable<T>::value) {
+ std::memcpy(dst, &value, sizeof(T));
+ }
+ else {
+ if (m_init[index]) {
+ *dst = value;
+ }
+ else {
+ new (dst) T(value);
+ }
+ }
+ }
+
+ void copy_in__dynamic(uint index, void *src)
+ {
+ BLI_assert(index < m_info->size());
+ BLI_assert(src != nullptr);
+
+ void *dst = this->element_ptr(index);
+ TypeCPP &type = m_info->type_at_index(index);
+
+ if (m_init[index]) {
+ type.copy_to_initialized(src, dst);
+ }
+ else {
+ type.copy_to_uninitialized(src, dst);
+ m_init[index] = true;
+ }
+ }
+
+ template<typename T> void move_in(uint index, T &value)
+ {
+ BLI_assert(index < m_info->size());
+ BLI_assert(m_info->element_has_type<T>(index));
+
+ T *dst = (T *)this->element_ptr(index);
+
+ if (m_init[index]) {
+ *dst = std::move(value);
+ }
+ else {
+ new (dst) T(std::move(value));
+ m_init[index] = true;
+ }
+ }
+
+ void relocate_in__dynamic(uint index, void *src)
+ {
+ BLI_assert(index < m_info->size());
+ BLI_assert(src != nullptr);
+
+ void *dst = this->element_ptr(index);
+ TypeCPP &type = m_info->type_at_index(index);
+
+ if (m_init[index]) {
+ type.relocate_to_initialized(src, dst);
+ }
+ else {
+ type.relocate_to_uninitialized(src, dst);
+ m_init[index] = true;
+ }
+ }
+
+ template<typename T> void set(uint index, const T &value)
+ {
+ BLI_STATIC_ASSERT(std::is_trivial<T>::value, "can only be used with trivial types");
+ this->copy_in<T>(index, value);
+ }
+
+ template<typename T> T copy_out(uint index) const
+ {
+ BLI_assert(index < m_info->size());
+ BLI_assert(m_info->element_has_type<T>(index));
+ BLI_assert(m_init[index]);
+
+ const T *src = (const T *)this->element_ptr(index);
+ return *src;
+ }
+
+ template<typename T> T relocate_out(uint index)
+ {
+ BLI_assert(index < m_info->size());
+ BLI_assert(m_info->element_has_type<T>(index));
+ BLI_assert(m_init[index]);
+
+ T *stored_value_ptr = (T *)this->element_ptr(index);
+ T tmp = std::move(*stored_value_ptr);
+ stored_value_ptr->~T();
+ m_init[index] = false;
+
+ return tmp;
+ }
+
+ void relocate_to_initialized__dynamic(uint index, void *dst)
+ {
+ BLI_assert(index < m_info->size());
+ BLI_assert(m_init[index]);
+ BLI_assert(dst != nullptr);
+
+ void *src = this->element_ptr(index);
+ TypeCPP &type = m_info->type_at_index(index);
+
+ type.relocate_to_initialized(src, dst);
+ m_init[index] = false;
+ }
+
+ void relocate_to_uninitialized__dynamic(uint index, void *dst)
+ {
+ BLI_assert(index < m_info->size());
+ BLI_assert(m_init[index]);
+ BLI_assert(dst != nullptr);
+
+ void *src = this->element_ptr(index);
+ TypeCPP &type = m_info->type_at_index(index);
+
+ type.relocate_to_uninitialized(src, dst);
+ m_init[index] = false;
+ }
+
+ template<typename T> T get_type_cpp(uint index) const
+ {
+ BLI_STATIC_ASSERT(std::is_trivial<T>::value, "can only be used with trivial types");
+ return this->copy_out<T>(index);
+ }
+
+ static void CopyElement(const TupleRef &from, uint from_index, TupleRef &to, uint to_index)
+ {
+ BLI_assert(from.m_init[from_index]);
+ BLI_assert(&from.m_info->type_at_index(from_index) == &to.m_info->type_at_index(to_index));
+
+ void *src = from.element_ptr(from_index);
+ void *dst = to.element_ptr(to_index);
+ TypeCPP &type = from.m_info->type_at_index(from_index);
+
+ if (to.m_init[to_index]) {
+ type.copy_to_initialized(src, dst);
+ }
+ else {
+ type.copy_to_uninitialized(src, dst);
+ to.m_init[to_index] = true;
+ }
+ }
+
+ static void RelocateElement(TupleRef &from, uint from_index, TupleRef &to, uint to_index)
+ {
+ BLI_assert(from.m_init[from_index]);
+ BLI_assert(&from.m_info->type_at_index(from_index) == &to.m_info->type_at_index(to_index));
+
+ void *src = from.element_ptr(from_index);
+ void *dst = to.element_ptr(to_index);
+ TypeCPP &type = from.m_info->type_at_index(from_index);
+
+ if (to.m_init[to_index]) {
+ type.relocate_to_initialized(src, dst);
+ }
+ else {
+ type.relocate_to_uninitialized(src, dst);
+ to.m_init[to_index] = true;
+ }
+ from.m_init[from_index] = false;
+ }
+
+ bool all_initialized() const
+ {
+ for (uint i = 0; i < m_info->size(); i++) {
+ if (!m_init[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ void set_all_initialized()
+ {
+ for (uint i = 0; i < m_info->size(); i++) {
+ m_init[i] = true;
+ }
+ }
+
+ bool all_uninitialized() const
+ {
+ for (uint i = 0; i < m_info->size(); i++) {
+ if (m_init[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ void set_all_uninitialized()
+ {
+ for (uint i = 0; i < m_info->size(); i++) {
+ m_init[i] = false;
+ }
+ }
+
+ void destruct_all()
+ {
+ if (!m_info->all_trivially_destructible()) {
+ uint size = m_info->size();
+ for (uint i = 0; i < size; i++) {
+ if (m_init[i]) {
+ m_info->type_at_index(i).destruct(this->element_ptr(i));
+ }
+ }
+ }
+ this->set_all_uninitialized();
+ }
+
+ uint size() const
+ {
+ return m_info->size();
+ }
+
+ TupleInfo &info()
+ {
+ return *m_info;
+ }
+
+ void *element_ptr(uint index) const
+ {
+ uint offset = m_info->offset_of_index(index);
+ void *ptr = POINTER_OFFSET(m_data, offset);
+
+ BLI_assert(m_info->type_at_index(index).pointer_has_valid_alignment(ptr));
+ return ptr;
+ }
+};
+
+class DestructingTuple : BLI::NonCopyable, BLI::NonMovable {
+ private:
+ TupleRef m_tuple_ref;
+
+ public:
+ DestructingTuple(TupleInfo &info, void *alignable_buffer)
+ : m_tuple_ref(TupleRef::FromAlignableBuffer(info, alignable_buffer))
+ {
+ }
+
+ ~DestructingTuple()
+ {
+ m_tuple_ref.destruct_all();
+ }
+
+ operator TupleRef &()
+ {
+ return m_tuple_ref;
+ }
+
+ TupleRef *operator->()
+ {
+ return &m_tuple_ref;
+ }
+};
+
+} // namespace BKE
+
+#define BKE_TUPLE_STACK_ALLOC(NAME, INFO_EXPR) \
+ BKE::TupleInfo &NAME##_info = (INFO_EXPR); \
+ void *NAME##_buffer = alloca(NAME##_info.size_of_alignable_data_and_init()); \
+ BKE::DestructingTuple NAME(NAME##_info, NAME##_buffer)
+
+#endif /* __BKE_TUPLE_H__ */
diff --git a/source/blender/blenkernel/BKE_type_cpp.h b/source/blender/blenkernel/BKE_type_cpp.h
index f152b7a9122..def1077e2b5 100644
--- a/source/blender/blenkernel/BKE_type_cpp.h
+++ b/source/blender/blenkernel/BKE_type_cpp.h
@@ -40,6 +40,9 @@ class TypeCPP final {
m_relocate_to_uninitialized(relocate_to_uninitialized),
m_name(name)
{
+ BLI_assert(is_power_of_2_i(m_alignment));
+
+ m_alignment_mask = m_alignment - 1;
}
StringRefNull name() const
@@ -47,39 +50,76 @@ class TypeCPP final {
return m_name;
}
+ uint size() const
+ {
+ return m_size;
+ }
+
+ uint alignment() const
+ {
+ return m_alignment;
+ }
+
+ bool trivially_destructible() const
+ {
+ return m_trivially_destructible;
+ }
+
+ bool pointer_has_valid_alignm
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list