Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenlib/BLI_memory_utils.hh')
-rw-r--r--source/blender/blenlib/BLI_memory_utils.hh45
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.