2f1799a739e5207f4a3ce1bf19065bfb40233574
[blender-staging.git] / intern / cycles / util / util_stack_allocator.h
1 /*
2  * Copyright 2011-2016 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef __UTIL_STACK_ALLOCATOR_H__
18 #define __UTIL_STACK_ALLOCATOR_H__
19
20 #include <cstddef>
21 #include <memory>
22
23 #include "util/util_debug.h"
24 #include "util/util_types.h"
25
26 CCL_NAMESPACE_BEGIN
27
28 /* Stack allocator for the use with STL. */
29 template <int SIZE, typename T>
30 class ccl_try_align(16) StackAllocator {
31 public:
32         typedef size_t size_type;
33         typedef ptrdiff_t difference_type;
34         typedef T *pointer;
35         typedef const T *const_pointer;
36         typedef T& reference;
37         typedef const T& const_reference;
38         typedef T value_type;
39
40         /* Allocator construction/destruction. */
41
42         StackAllocator()
43         : pointer_(0),
44           use_stack_(true) {}
45
46         StackAllocator(const StackAllocator&)
47         : pointer_(0),
48           use_stack_(true) {}
49
50         template <class U>
51         StackAllocator(const StackAllocator<SIZE, U>&)
52         : pointer_(0),
53           use_stack_(false) {}
54
55         /* Memory allocation/deallocation. */
56
57         T *allocate(size_t n, const void *hint = 0)
58         {
59                 (void)hint;
60                 if(n == 0) {
61                         return NULL;
62                 }
63                 if(pointer_ + n >= SIZE || use_stack_ == false) {
64                         size_t size = n * sizeof(T);
65                         util_guarded_mem_alloc(size);
66                         T *mem;
67 #ifdef WITH_BLENDER_GUARDEDALLOC
68                         mem = (T*)MEM_mallocN_aligned(size, 16, "Cycles Alloc");
69 #else
70                         mem = (T*)malloc(size);
71 #endif
72                         if(mem == NULL) {
73                                 throw std::bad_alloc();
74                         }
75                         return mem;
76                 }
77                 T *mem = &data_[pointer_];
78                 pointer_ += n;
79                 return mem;
80         }
81
82         void deallocate(T *p, size_t n)
83         {
84                 if(p == NULL) {
85                         return;
86                 }
87                 if(p < data_ || p >= data_ + SIZE) {
88                         util_guarded_mem_free(n * sizeof(T));
89 #ifdef WITH_BLENDER_GUARDEDALLOC
90                         MEM_freeN(p);
91 #else
92                         free(p);
93 #endif
94                         return;
95                 }
96                 /* We don't support memory free for the stack allocator. */
97         }
98
99         /* Address of an reference. */
100
101         T *address(T& x) const
102         {
103                 return &x;
104         }
105
106         const T *address(const T& x) const
107         {
108                 return &x;
109         }
110
111         /* Object construction/destruction. */
112
113         void construct(T *p, const T& val)
114         {
115                 if(p != NULL) {
116                         new ((T *)p) T(val);
117                 }
118         }
119
120         void destroy(T *p)
121         {
122                 p->~T();
123         }
124
125         /* Maximum allocation size. */
126
127         size_t max_size() const
128         {
129                 return size_t(-1);
130         }
131
132         /* Rebind to other ype of allocator. */
133
134         template <class U>
135         struct rebind {
136                 typedef StackAllocator<SIZE, U> other;
137         };
138
139         /* Operators */
140
141         template <class U>
142         inline StackAllocator& operator=(const StackAllocator<SIZE, U>&)
143         {
144                 return *this;
145         }
146
147         StackAllocator<SIZE, T>& operator=(const StackAllocator&)
148         {
149                 return *this;
150         }
151
152         inline bool operator==(StackAllocator const& /*other*/) const
153         {
154                 return true;
155         }
156
157         inline bool operator!=(StackAllocator const& other) const
158         {
159                 return !operator==(other);
160         }
161
162 private:
163         int pointer_;
164         bool use_stack_;
165         T data_[SIZE];
166 };
167
168 CCL_NAMESPACE_END
169
170 #endif  /* __UTIL_GUARDED_ALLOCATOR_H__ */