diff options
author | Jacques Lucke <jacques@blender.org> | 2021-03-07 19:51:56 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2021-03-07 19:53:05 +0300 |
commit | 74979459cbbe4ec5bf7014a511775b5274b20060 (patch) | |
tree | 14b2e0ecb04ca2a063f9ff83b192b72e405ca5cc /source/blender/blenlib | |
parent | 9c8382e6186b519429e4dee8870265351810bc99 (diff) |
Geometry Nodes: simplify allocating dynamically sized buffer on stack
Diffstat (limited to 'source/blender/blenlib')
-rw-r--r-- | source/blender/blenlib/BLI_memory_utils.hh | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/source/blender/blenlib/BLI_memory_utils.hh b/source/blender/blenlib/BLI_memory_utils.hh index b3b6855089e..bdbbda9f0c7 100644 --- a/source/blender/blenlib/BLI_memory_utils.hh +++ b/source/blender/blenlib/BLI_memory_utils.hh @@ -28,6 +28,7 @@ #include <type_traits> #include "BLI_utildefines.h" +#include "MEM_guardedalloc.h" namespace blender { @@ -402,6 +403,50 @@ template<typename T, int64_t Size = 1> class TypedBuffer { } }; +/* A dynamic stack buffer can be used instead of #alloca when wants to allocate a dynamic amount of + * memory on the stack. Using this class has some advantages: + * - It falls back to heap allocation, when the size is too large. + * - It can be used in loops safely. + * - If the buffer is heap allocated, it is free automatically in the destructor. + */ +template<size_t ReservedSize = 64, size_t ReservedAlignment = 64> +class alignas(ReservedAlignment) DynamicStackBuffer { + private: + /* Don't create an empty array. This causes problems with some compilers. */ + char reserved_buffer_[(ReservedSize > 0) ? ReservedSize : 1]; + void *buffer_; + + public: + DynamicStackBuffer(const int64_t size, const int64_t alignment) + { + BLI_assert(size >= 0); + BLI_assert(alignment >= 0); + if (size <= ReservedSize && alignment <= ReservedAlignment) { + buffer_ = reserved_buffer_; + } + else { + buffer_ = MEM_mallocN_aligned(size, alignment, __func__); + } + } + ~DynamicStackBuffer() + { + if (buffer_ != reserved_buffer_) { + MEM_freeN(buffer_); + } + } + + /* Don't allow any copying or moving of this type. */ + DynamicStackBuffer(const DynamicStackBuffer &other) = delete; + DynamicStackBuffer(DynamicStackBuffer &&other) = delete; + DynamicStackBuffer &operator=(const DynamicStackBuffer &other) = delete; + DynamicStackBuffer &operator=(DynamicStackBuffer &&other) = delete; + + void *buffer() const + { + return buffer_; + } +}; + /** * This can be used by container constructors. A parameter of this type should be used to indicate * that the constructor does not construct the elements. |