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:
authorJacques Lucke <jacques@blender.org>2021-12-17 17:38:15 +0300
committerJacques Lucke <jacques@blender.org>2021-12-17 17:42:28 +0300
commita3ad5abf2fe85d623f9e78fefc34e27bdc14632e (patch)
tree6d03a62169251af084ff2e02bd0f567d92f3b826 /intern/guardedalloc
parentc0d96ca9a5dbf168348b6a6bdee2f635c0c1685c (diff)
Allocator: simplify using guarded allocator in C++ code
Using the `MEM_*` API from C++ code was a bit annoying: * When converting C to C++ code, one often has to add a type cast on returned `void *`. That leads to having the same type name three times in the same line. This patch reduces the amount to two and removes the `sizeof(...)` from the line. * The existing alternative of using `OBJECT_GUARDED_NEW` looks a out of place compared to other allocation methods. Sometimes `MEM_CXX_CLASS_ALLOC_FUNCS` can be used when structs are defined in C++ code. It doesn't look great but it's definitely better. The downside is that it makes the name of the allocation less useful. That's because the same name is used for all allocations of a type, independend of where it is allocated. This patch introduces three new functions: `MEM_new`, `MEM_cnew` and `MEM_delete`. These cover the majority of use cases (array allocation is not covered). The `OBJECT_GUARDED_*` macros are removed because they are not needed anymore. Differential Revision: https://developer.blender.org/D13502
Diffstat (limited to 'intern/guardedalloc')
-rw-r--r--intern/guardedalloc/MEM_guardedalloc.h73
1 files changed, 43 insertions, 30 deletions
diff --git a/intern/guardedalloc/MEM_guardedalloc.h b/intern/guardedalloc/MEM_guardedalloc.h
index 3c006b9a70c..043f7055ab1 100644
--- a/intern/guardedalloc/MEM_guardedalloc.h
+++ b/intern/guardedalloc/MEM_guardedalloc.h
@@ -259,6 +259,49 @@ void MEM_use_guarded_allocator(void);
#endif /* __cplusplus */
#ifdef __cplusplus
+
+# include <type_traits>
+# include <utility>
+
+/**
+ * Allocate new memory for and constructs an object of type #T.
+ * #MEM_delete should be used to delete the object. Just calling #MEM_freeN is not enough when #T
+ * is not a trivial type.
+ */
+template<typename T, typename... Args>
+inline T *MEM_new(const char *allocation_name, Args &&...args)
+{
+ void *buffer = MEM_mallocN(sizeof(T), allocation_name);
+ return new (buffer) T(std::forward<Args>(args)...);
+}
+
+/**
+ * Allocates zero-initialized memory for an object of type #T. The constructor of #T is not called,
+ * therefor this should only used with trivial types (like all C types).
+ * It's valid to call #MEM_freeN on a pointer returned by this, because a destructor call is not
+ * necessary, because the type is trivial.
+ */
+template<typename T> inline T *MEM_cnew(const char *allocation_name)
+{
+ static_assert(std::is_trivial_v<T>, "For non-trivial types, MEM_new should be used.");
+ return static_cast<T *>(MEM_callocN(sizeof(T), allocation_name));
+}
+
+/**
+ * Destructs and deallocates an object previously allocated with any `MEM_*` function.
+ * Passing in null does nothing.
+ */
+template<typename T> inline void MEM_delete(const T *ptr)
+{
+ if (ptr == nullptr) {
+ /* Support #ptr being null, because C++ `delete` supports that as well. */
+ return;
+ }
+ /* C++ allows destruction of const objects, so the pointer is allowed to be const. */
+ ptr->~T();
+ MEM_freeN(const_cast<T *>(ptr));
+}
+
/* Allocation functions (for C++ only). */
# define MEM_CXX_CLASS_ALLOC_FUNCS(_id) \
public: \
@@ -292,36 +335,6 @@ void MEM_use_guarded_allocator(void);
{ \
}
-/* Needed when type includes a namespace, then the namespace should not be
- * specified after ~, so using a macro fails. */
-template<class T> inline void OBJECT_GUARDED_DESTRUCTOR(T *what)
-{
- what->~T();
-}
-
-# if defined __GNUC__
-# define OBJECT_GUARDED_NEW(type, args...) new (MEM_mallocN(sizeof(type), __func__)) type(args)
-# else
-# define OBJECT_GUARDED_NEW(type, ...) \
- new (MEM_mallocN(sizeof(type), __FUNCTION__)) type(__VA_ARGS__)
-# endif
-# define OBJECT_GUARDED_DELETE(what, type) \
- { \
- if (what) { \
- OBJECT_GUARDED_DESTRUCTOR((type *)what); \
- MEM_freeN(what); \
- } \
- } \
- (void)0
-# define OBJECT_GUARDED_SAFE_DELETE(what, type) \
- { \
- if (what) { \
- OBJECT_GUARDED_DESTRUCTOR((type *)what); \
- MEM_freeN(what); \
- what = NULL; \
- } \
- } \
- (void)0
#endif /* __cplusplus */
#endif /* __MEM_GUARDEDALLOC_H__ */