diff options
author | Jacques Lucke <jacques@blender.org> | 2020-05-07 15:21:26 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2020-05-07 15:21:48 +0300 |
commit | 850a539c903605586d0f32bd14fc3dcf63d5a89e (patch) | |
tree | ae8bc1876409719ec6ac2329ab1bcbd6724770d1 /source/blender/blenlib/BLI_linear_allocator.hh | |
parent | 45adcc51b21d626238b25428f791937148cf0a20 (diff) |
BLI: improve linear allocator documentation
Diffstat (limited to 'source/blender/blenlib/BLI_linear_allocator.hh')
-rw-r--r-- | source/blender/blenlib/BLI_linear_allocator.hh | 125 |
1 files changed, 86 insertions, 39 deletions
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: |