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 'intern/cycles/util/util_guarded_allocator.h')
-rw-r--r--intern/cycles/util/util_guarded_allocator.h124
1 files changed, 100 insertions, 24 deletions
diff --git a/intern/cycles/util/util_guarded_allocator.h b/intern/cycles/util/util_guarded_allocator.h
index 2df717253e3..f6004749a13 100644
--- a/intern/cycles/util/util_guarded_allocator.h
+++ b/intern/cycles/util/util_guarded_allocator.h
@@ -17,17 +17,10 @@
#ifndef __UTIL_GUARDED_ALLOCATOR_H__
#define __UTIL_GUARDED_ALLOCATOR_H__
-/* Define this in order to use Blender's guarded allocator to keep
- * track of allocated buffers, their sizes and peak memory usage.
- *
- * This is usually a bad level call, but it's really handy to keep
- * track of overall peak memory consumption during the scene
- * synchronization step.
- */
-#undef WITH_BLENDER_GUARDEDALLOC
-
+#include <cstddef>
#include <memory>
+#include "util_debug.h"
#include "util_types.h"
#ifdef WITH_BLENDER_GUARDEDALLOC
@@ -42,39 +35,122 @@ void util_guarded_mem_free(size_t n);
/* Guarded allocator for the use with STL. */
template <typename T>
-class GuardedAllocator : public std::allocator<T> {
+class GuardedAllocator {
public:
- template<typename _Tp1>
- struct rebind {
- typedef GuardedAllocator<_Tp1> other;
- };
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T *pointer;
+ typedef const T *const_pointer;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef T value_type;
+
+ GuardedAllocator() {}
+ GuardedAllocator(const GuardedAllocator&) {}
T *allocate(size_t n, const void *hint = 0)
{
- util_guarded_mem_alloc(n * sizeof(T));
-#ifdef WITH_BLENDER_GUARDEDALLOC
+ size_t size = n * sizeof(T);
+ util_guarded_mem_alloc(size);
(void)hint;
- return (T*)MEM_mallocN_aligned(n * sizeof(T), 16, "Cycles Alloc");
+#ifdef WITH_BLENDER_GUARDEDALLOC
+ if(n == 0) {
+ return NULL;
+ }
+ /* C++ standard requires allocation functions to allocate memory suitably
+ * aligned for any standard type. This is 16 bytes for 64 bit platform as
+ * far as i concerned. We might over-align on 32bit here, but that should
+ * be all safe actually.
+ */
+ return (T*)MEM_mallocN_aligned(size, 16, "Cycles Alloc");
#else
- return std::allocator<T>::allocate(n, hint);
+ return (T*)malloc(size);
#endif
}
void deallocate(T *p, size_t n)
{
util_guarded_mem_free(n * sizeof(T));
+ if(p != NULL) {
#ifdef WITH_BLENDER_GUARDEDALLOC
- MEM_freeN((void*)p);
+ MEM_freeN(p);
#else
- std::allocator<T>::deallocate(p, n);
+ free(p);
#endif
+ }
+ }
+
+ T *address(T& x) const
+ {
+ return &x;
+ }
+
+ const T *address(const T& x) const
+ {
+ return &x;
+ }
+
+ GuardedAllocator<T>& operator=(const GuardedAllocator&)
+ {
+ return *this;
+ }
+
+ void construct(T *p, const T& val)
+ {
+ new ((T *)p) T(val);
}
- GuardedAllocator() : std::allocator<T>() { }
- GuardedAllocator(const GuardedAllocator &a) : std::allocator<T>(a) { }
+ void destroy(T *p)
+ {
+ p->~T();
+ }
+
+ size_t max_size() const
+ {
+ return size_t(-1);
+ }
+
+ template <class U>
+ struct rebind {
+ typedef GuardedAllocator<U> other;
+ };
+
template <class U>
- GuardedAllocator(const GuardedAllocator<U> &a) : std::allocator<T>(a) { }
- ~GuardedAllocator() { }
+ GuardedAllocator(const GuardedAllocator<U>&) {}
+
+ template <class U>
+ GuardedAllocator& operator=(const GuardedAllocator<U>&) { return *this; }
+
+ inline bool operator==(GuardedAllocator const& /*other*/) const { return true; }
+ inline bool operator!=(GuardedAllocator const& other) const { return !operator==(other); }
+
+#ifdef _MSC_VER
+ /* Welcome to the black magic here.
+ *
+ * The issue is that MSVC C++ allocates container proxy on any
+ * vector initialization, including static vectors which don't
+ * have any data yet. This leads to several issues:
+ *
+ * - Static objects initialization fiasco (global_stats from
+ * util_stats.h might not be initialized yet).
+ * - If main() function changes allocator type (for example,
+ * this might happen with `blender --debug-memory`) nobody
+ * will know how to convert already allocated memory to a new
+ * guarded allocator.
+ *
+ * Here we work this around by making it so container proxy does
+ * not use guarded allocation. A bit fragile, unfortunately.
+ */
+ template<>
+ struct rebind<std::_Container_proxy> {
+ typedef std::allocator<std::_Container_proxy> other;
+ };
+
+ operator std::allocator<std::_Container_proxy>() const
+ {
+ return std::allocator<std::_Container_proxy>();
+ }
+#endif
};
/* Get memory usage and peak from the guarded STL allocator. */