[Bf-blender-cvs] [c365ec7c611] functions-experimental-refactor: initial GenericVectorArray
Jacques Lucke
noreply at git.blender.org
Tue Oct 15 15:56:43 CEST 2019
Commit: c365ec7c611d71bbe729fbed30e91ff4bd19d397
Author: Jacques Lucke
Date: Thu Oct 10 10:51:51 2019 +0200
Branches: functions-experimental-refactor
https://developer.blender.org/rBc365ec7c611d71bbe729fbed30e91ff4bd19d397
initial GenericVectorArray
===================================================================
M source/blender/blenkernel/BKE_cpp_type.h
M source/blender/blenkernel/BKE_generic_array_ref.h
A source/blender/blenkernel/BKE_generic_vector_array.h
M source/blender/blenkernel/intern/cpp_types.cc
M source/blender/blenlib/BLI_monotonic_allocator.h
===================================================================
diff --git a/source/blender/blenkernel/BKE_cpp_type.h b/source/blender/blenkernel/BKE_cpp_type.h
index 8e94652f88b..b9dd946f9bc 100644
--- a/source/blender/blenkernel/BKE_cpp_type.h
+++ b/source/blender/blenkernel/BKE_cpp_type.h
@@ -14,8 +14,8 @@ class CPPType {
public:
using ConstructDefaultF = void (*)(const CPPType *self, void *ptr);
using DestructF = void (*)(void *ptr);
- using CopyToInitializedF = void (*)(void *src, void *dst);
- using CopyToUninitializedF = void (*)(void *src, void *dst);
+ using CopyToInitializedF = void (*)(const void *src, void *dst);
+ using CopyToUninitializedF = void (*)(const void *src, void *dst);
using RelocateToInitializedF = void (*)(void *src, void *dst);
using RelocateToUninitializedF = void (*)(void *src, void *dst);
@@ -91,7 +91,7 @@ class CPPType {
return m_trivially_destructible;
}
- bool pointer_has_valid_alignment(void *ptr) const
+ bool pointer_has_valid_alignment(const void *ptr) const
{
return (POINTER_AS_UINT(ptr) & m_alignment_mask) == 0;
}
@@ -110,7 +110,7 @@ class CPPType {
m_destruct(ptr);
}
- void copy_to_initialized(void *src, void *dst) const
+ void copy_to_initialized(const void *src, void *dst) const
{
BLI_assert(this->pointer_has_valid_alignment(src));
BLI_assert(this->pointer_has_valid_alignment(dst));
@@ -118,7 +118,7 @@ class CPPType {
m_copy_to_initialized(src, dst);
}
- void copy_to_uninitialized(void *src, void *dst) const
+ void copy_to_uninitialized(const void *src, void *dst) const
{
BLI_assert(this->pointer_has_valid_alignment(src));
BLI_assert(this->pointer_has_valid_alignment(dst));
diff --git a/source/blender/blenkernel/BKE_generic_array_ref.h b/source/blender/blenkernel/BKE_generic_array_ref.h
index e24614d16a1..7005cdac7a4 100644
--- a/source/blender/blenkernel/BKE_generic_array_ref.h
+++ b/source/blender/blenkernel/BKE_generic_array_ref.h
@@ -14,7 +14,7 @@ using BLI::MutableArrayRef;
class GenericArrayRef {
private:
const CPPType *m_type;
- void *m_buffer;
+ const void *m_buffer;
uint m_size;
public:
@@ -22,7 +22,7 @@ class GenericArrayRef {
{
}
- GenericArrayRef(const CPPType *type, void *buffer, uint size)
+ GenericArrayRef(const CPPType *type, const void *buffer, uint size)
: m_type(type), m_buffer(buffer), m_size(size)
{
BLI_assert(type != nullptr);
@@ -35,6 +35,17 @@ class GenericArrayRef {
return m_size;
}
+ const void *buffer() const
+ {
+ return m_buffer;
+ }
+
+ const void *operator[](uint index) const
+ {
+ BLI_assert(index < m_size);
+ return POINTER_OFFSET(m_buffer, m_type->size() * index);
+ }
+
template<typename T> ArrayRef<T> get_ref() const
{
BLI_assert(GET_TYPE<T>().is_same_or_generalization(m_type));
diff --git a/source/blender/blenkernel/BKE_generic_vector_array.h b/source/blender/blenkernel/BKE_generic_vector_array.h
new file mode 100644
index 00000000000..4f8e43f076e
--- /dev/null
+++ b/source/blender/blenkernel/BKE_generic_vector_array.h
@@ -0,0 +1,139 @@
+#ifndef __BKE_GENERIC_MULTI_VECTOR_H__
+#define __BKE_GENERIC_MULTI_VECTOR_H__
+
+#include "BKE_cpp_type.h"
+#include "BKE_cpp_types.h"
+#include "BKE_generic_array_ref.h"
+
+#include "BLI_array_ref.h"
+#include "BLI_index_range.h"
+#include "BLI_monotonic_allocator.h"
+
+namespace BKE {
+
+using BLI::ArrayRef;
+using BLI::IndexRange;
+using BLI::MonotonicAllocator;
+using BLI::MutableArrayRef;
+
+class GenericVectorArray : BLI::NonCopyable, BLI::NonMovable {
+ private:
+ struct BufferSlice {
+ void *start;
+ uint length;
+ uint capacity;
+ };
+
+ BLI::GuardedAllocator m_slices_allocator;
+ MonotonicAllocator<> m_elements_allocator;
+ CPPType &m_type;
+ BufferSlice *m_slices;
+ uint m_array_size;
+ uint m_element_size;
+
+ public:
+ GenericVectorArray() = delete;
+
+ GenericVectorArray(CPPType &type, uint array_size)
+ : m_slices_allocator({}),
+ m_elements_allocator({}),
+ m_type(type),
+ m_array_size(array_size),
+ m_element_size(type.size())
+ {
+ uint slices_size_in_bytes = sizeof(BufferSlice) * array_size;
+ m_slices = (BufferSlice *)m_slices_allocator.allocate(slices_size_in_bytes, __func__);
+ memset((void *)m_slices, 0, slices_size_in_bytes);
+ }
+
+ ~GenericVectorArray()
+ {
+ this->destruct_all_elements();
+ m_slices_allocator.deallocate((void *)m_slices);
+ }
+
+ template<typename T> ArrayRef<T> as_ref(uint index) const
+ {
+ BLI_assert(GET_TYPE<T>().is_same_or_generalization(m_type));
+ const BufferSlice &slice = this->slices()[index];
+ return ArrayRef<T>((const T *)slice.start, slice.length);
+ }
+
+ void append_single__copy(uint index, void *src)
+ {
+ MutableArrayRef<BufferSlice> slices = this->slices();
+ BufferSlice &slice = slices[index];
+ if (slice.length == slice.capacity) {
+ this->grow_single(slice, slice.length + 1);
+ }
+
+ void *dst = POINTER_OFFSET(slice.start, m_element_size * slice.length);
+ m_type.copy_to_uninitialized(src, dst);
+ slice.length++;
+ }
+
+ void append_all__copy(const GenericArrayRef &array)
+ {
+ BLI_assert(m_array_size == array.size());
+
+ for (BufferSlice &slice : this->slices()) {
+ if (slice.length == slice.capacity) {
+ this->grow_single(slice, slice.length + 1);
+ }
+ }
+
+ const void *src_buffer = array.buffer();
+ for (BufferSlice &slice : this->slices()) {
+ void *dst = POINTER_OFFSET(slice.start, m_element_size * slice.length);
+ m_type.copy_to_uninitialized(src_buffer, dst);
+ slice.length++;
+
+ src_buffer = POINTER_OFFSET(src_buffer, m_element_size);
+ }
+ }
+
+ private:
+ void grow_single(BufferSlice &slice, uint min_capacity)
+ {
+ BLI_assert(slice.capacity < min_capacity);
+ min_capacity = power_of_2_max_u(min_capacity);
+ void *new_buffer = m_elements_allocator.allocate_aligned(m_element_size * min_capacity,
+ m_type.alignment());
+
+ for (uint i = 0; i < slice.length; i++) {
+ void *src = POINTER_OFFSET(slice.start, m_element_size * i);
+ void *dst = POINTER_OFFSET(new_buffer, m_element_size * i);
+ m_type.relocate_to_uninitialized(src, dst);
+ }
+
+ slice.start = new_buffer;
+ }
+
+ void destruct_all_elements()
+ {
+ if (m_type.trivially_destructible()) {
+ return;
+ }
+
+ for (const BufferSlice &slice : this->slices()) {
+ for (uint i = 0; i < slice.length; i++) {
+ void *ptr = POINTER_OFFSET(slice.start, m_element_size * i);
+ m_type.destruct(ptr);
+ }
+ }
+ }
+
+ ArrayRef<BufferSlice> slices() const
+ {
+ return ArrayRef<BufferSlice>(m_slices, m_array_size);
+ }
+
+ MutableArrayRef<BufferSlice> slices()
+ {
+ return MutableArrayRef<BufferSlice>(m_slices, m_array_size);
+ }
+};
+
+}; // namespace BKE
+
+#endif /* __BKE_GENERIC_MULTI_VECTOR_H__ */
\ No newline at end of file
diff --git a/source/blender/blenkernel/intern/cpp_types.cc b/source/blender/blenkernel/intern/cpp_types.cc
index 27ceb72e884..7e1f212f596 100644
--- a/source/blender/blenkernel/intern/cpp_types.cc
+++ b/source/blender/blenkernel/intern/cpp_types.cc
@@ -42,11 +42,11 @@ template<typename T> void Destruct_CB(void *ptr)
{
BLI::destruct((T *)ptr);
}
-template<typename T> void CopyToInitialized_CB(void *src, void *dst)
+template<typename T> void CopyToInitialized_CB(const void *src, void *dst)
{
- *(T *)src = *(T *)dst;
+ *(T *)dst = *(T *)src;
}
-template<typename T> void CopyToUninitialized_CB(void *src, void *dst)
+template<typename T> void CopyToUninitialized_CB(const void *src, void *dst)
{
BLI::uninitialized_copy_n((T *)src, 1, (T *)dst);
}
diff --git a/source/blender/blenlib/BLI_monotonic_allocator.h b/source/blender/blenlib/BLI_monotonic_allocator.h
index 15169d397fc..b700aa413bd 100644
--- a/source/blender/blenlib/BLI_monotonic_allocator.h
+++ b/source/blender/blenlib/BLI_monotonic_allocator.h
@@ -86,6 +86,7 @@ class MonotonicAllocator : NonCopyable, NonMovable {
void *allocate_aligned(uint size, uint alignment)
{
+ /* TODO: Don't overallocate when not necessary. */
BLI_assert(is_power_of_2_i(alignment));
size_t space = size + alignment - 1;
void *ptr = this->allocate(space);
More information about the Bf-blender-cvs
mailing list