[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