[Bf-blender-cvs] [850a539c903] master: BLI: improve linear allocator documentation

Jacques Lucke noreply at git.blender.org
Thu May 7 14:22:02 CEST 2020


Commit: 850a539c903605586d0f32bd14fc3dcf63d5a89e
Author: Jacques Lucke
Date:   Thu May 7 14:21:26 2020 +0200
Branches: master
https://developer.blender.org/rB850a539c903605586d0f32bd14fc3dcf63d5a89e

BLI: improve linear allocator documentation

===================================================================

M	source/blender/blenlib/BLI_array_ref.hh
M	source/blender/blenlib/BLI_linear_allocator.hh

===================================================================

diff --git a/source/blender/blenlib/BLI_array_ref.hh b/source/blender/blenlib/BLI_array_ref.hh
index dd9421d289c..c0484493bda 100644
--- a/source/blender/blenlib/BLI_array_ref.hh
+++ b/source/blender/blenlib/BLI_array_ref.hh
@@ -508,6 +508,16 @@ template<typename T> class MutableArrayRef {
     BLI_assert(m_size > 0);
     return m_start[m_size - 1];
   }
+
+  /**
+   * Get a new array ref to the same underlying memory buffer. No conversions are done.
+   */
+  template<typename NewT> MutableArrayRef<NewT> cast() const
+  {
+    BLI_assert((m_size * sizeof(T)) % sizeof(NewT) == 0);
+    uint new_size = m_size * sizeof(T) / sizeof(NewT);
+    return MutableArrayRef<NewT>(reinterpret_cast<NewT *>(m_start), new_size);
+  }
 };
 
 /**
diff --git a/source/blender/blenlib/BLI_linear_allocator.hh b/source/blender/blenlib/BLI_linear_allocator.hh
index cebf878580c..ffa81b3ac6b 100644
--- a/source/blender/blenlib/BLI_linear_allocator.hh
+++ b/source/blender/blenlib/BLI_linear_allocator.hh
@@ -60,28 +60,13 @@ template<typename Allocator = GuardedAllocator> class LinearAllocator : NonCopya
     }
   }
 
-  void provide_buffer(void *buffer, uint size)
-  {
-    m_unused_borrowed_buffers.append(ArrayRef<char>((char *)buffer, size));
-  }
-
-  template<uint Size, uint Alignment>
-  void provide_buffer(AlignedBuffer<Size, Alignment> &aligned_buffer)
-  {
-    this->provide_buffer(aligned_buffer.ptr(), Size);
-  }
-
-  template<typename T> T *allocate()
-  {
-    return (T *)this->allocate(sizeof(T), alignof(T));
-  }
-
-  template<typename T> MutableArrayRef<T> allocate_array(uint length)
-  {
-    return MutableArrayRef<T>((T *)this->allocate(sizeof(T) * length), length);
-  }
-
-  void *allocate(uint size, uint alignment = 4)
+  /**
+   * Get a pointer to a memory buffer with the given size an alignment. The memory buffer will be
+   * freed when this LinearAllocator is destructed.
+   *
+   * The alignment has to be a power of 2.
+   */
+  void *allocate(uint size, uint alignment)
   {
     BLI_assert(alignment >= 1);
     BLI_assert(is_power_of_2_i(alignment));
@@ -104,6 +89,55 @@ template<typename Allocator = GuardedAllocator> class LinearAllocator : NonCopya
     }
   };
 
+  /**
+   * Allocate a memory buffer that can hold an instance of T.
+   *
+   * This method only allocates memory and does not construct the instance.
+   */
+  template<typename T> T *allocate()
+  {
+    return (T *)this->allocate(sizeof(T), alignof(T));
+  }
+
+  /**
+   * Allocate a memory buffer that can hold T array with the given size.
+   *
+   * This method only allocates memory and does not construct the instance.
+   */
+  template<typename T> MutableArrayRef<T> allocate_array(uint size)
+  {
+    return MutableArrayRef<T>((T *)this->allocate(sizeof(T) * size, alignof(T)), size);
+  }
+
+  /**
+   * Construct an instance of T in memory provided by this allocator.
+   *
+   * Arguments passed to this method will be forwarded to the constructor of T.
+   *
+   * You must not call `delete` on the returned pointer. Instead, the destructor has to be called
+   * explicitely.
+   */
+  template<typename T, typename... Args> T *construct(Args &&... args)
+  {
+    void *buffer = this->allocate(sizeof(T), alignof(T));
+    T *value = new (buffer) T(std::forward<Args>(args)...);
+    return value;
+  }
+
+  /**
+   * Copy the given array into a memory buffer provided by this allocator.
+   */
+  template<typename T> MutableArrayRef<T> construct_array_copy(ArrayRef<T> src)
+  {
+    MutableArrayRef<T> dst = this->allocate_array<T>(src.size());
+    uninitialized_copy_n(src.begin(), src.size(), dst.begin());
+    return dst;
+  }
+
+  /**
+   * Copy the given string into a memory buffer provided by this allocator. The returned string is
+   * always null terminated.
+   */
   StringRefNull copy_string(StringRef str)
   {
     uint alloc_size = str.size() + 1;
@@ -112,37 +146,50 @@ template<typename Allocator = GuardedAllocator> class LinearAllocator : NonCopya
     return StringRefNull((const char *)buffer);
   }
 
-  template<typename T, typename... Args> T *construct(Args &&... args)
+  MutableArrayRef<void *> allocate_elements_and_pointer_array(uint element_amount,
+                                                              uint element_size,
+                                                              uint element_alignment)
   {
-    void *buffer = this->allocate(sizeof(T), alignof(T));
-    T *value = new (buffer) T(std::forward<Args>(args)...);
-    return value;
+    void *pointer_buffer = this->allocate(element_amount * sizeof(void *), alignof(void *));
+    void *elements_buffer = this->allocate(element_amount * element_size, element_alignment);
+
+    MutableArrayRef<void *> pointers((void **)pointer_buffer, element_amount);
+    void *next_element_buffer = elements_buffer;
+    for (uint i : IndexRange(element_amount)) {
+      pointers[i] = next_element_buffer;
+      next_element_buffer = POINTER_OFFSET(next_element_buffer, element_size);
+    }
+
+    return pointers;
   }
 
   template<typename T, typename... Args>
   ArrayRef<T *> construct_elements_and_pointer_array(uint n, Args &&... args)
   {
-    void *pointer_buffer = this->allocate(n * sizeof(T *), alignof(T *));
-    void *element_buffer = this->allocate(n * sizeof(T), alignof(T));
-
-    MutableArrayRef<T *> pointers((T **)pointer_buffer, n);
-    T *elements = (T *)element_buffer;
+    MutableArrayRef<void *> void_pointers = this->allocate_elements_and_pointer_array(
+        n, sizeof(T), alignof(T));
+    MutableArrayRef<T *> pointers = void_pointers.cast<T *>();
 
     for (uint i : IndexRange(n)) {
-      pointers[i] = elements + i;
-    }
-    for (uint i : IndexRange(n)) {
-      new (elements + i) T(std::forward<Args>(args)...);
+      new (pointers[i]) T(std::forward<Args>(args)...);
     }
 
     return pointers;
   }
 
-  template<typename T> MutableArrayRef<T> construct_array_copy(ArrayRef<T> source)
+  /**
+   * Tell the allocator to use up the given memory buffer, before allocating new memory from the
+   * system.
+   */
+  void provide_buffer(void *buffer, uint size)
   {
-    T *buffer = (T *)this->allocate(source.byte_size(), alignof(T));
-    uninitialized_copy_n(source.begin(), source.size(), buffer);
-    return MutableArrayRef<T>(buffer, source.size());
+    m_unused_borrowed_buffers.append(ArrayRef<char>((char *)buffer, size));
+  }
+
+  template<uint Size, uint Alignment>
+  void provide_buffer(AlignedBuffer<Size, Alignment> &aligned_buffer)
+  {
+    this->provide_buffer(aligned_buffer.ptr(), Size);
   }
 
  private:



More information about the Bf-blender-cvs mailing list