Blender V4.3
cycles/util/array.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#ifndef __UTIL_ARRAY_H__
6#define __UTIL_ARRAY_H__
7
8#include <cassert>
9#include <cstring>
10
11#include "util/aligned_malloc.h"
13#include "util/types.h"
14#include "util/vector.h"
15
17
18/* Simplified version of vector, serving multiple purposes:
19 * - somewhat faster in that it does not clear memory on resize/alloc,
20 * this was actually showing up in profiles quite significantly. it
21 * also does not run any constructors/destructors
22 * - if this is used, we are not tempted to use inefficient operations
23 * - aligned allocation for CPU native data types */
24
25template<typename T, size_t alignment = MIN_ALIGNMENT_CPU_DATA_TYPES> class array {
26 public:
28
29 explicit array(size_t newsize)
30 {
31 if (newsize == 0) {
32 data_ = NULL;
33 datasize_ = 0;
34 capacity_ = 0;
35 }
36 else {
37 data_ = mem_allocate(newsize);
38 datasize_ = newsize;
40 }
41 }
42
43 array(const array &from)
44 {
45 if (from.datasize_ == 0) {
46 data_ = NULL;
47 datasize_ = 0;
48 capacity_ = 0;
49 }
50 else {
51 data_ = mem_allocate(from.datasize_);
52 if (from.datasize_ > 0) {
53 mem_copy(data_, from.data_, from.datasize_);
54 }
55 datasize_ = from.datasize_;
57 }
58 }
59
60 array &operator=(const array &from)
61 {
62 if (this != &from) {
63 resize(from.size());
64 if (datasize_ > 0) {
65 mem_copy(data_, from.data_, datasize_);
66 }
67 }
68
69 return *this;
70 }
71
73 {
74 resize(from.size());
75
76 if (from.size() > 0 && datasize_ > 0) {
77 mem_copy(data_, from.data(), datasize_);
78 }
79
80 return *this;
81 }
82
84 {
86 }
87
88 bool operator==(const array<T> &other) const
89 {
90 if (datasize_ != other.datasize_) {
91 return false;
92 }
93 if (datasize_ == 0) {
94 return true;
95 }
96
97 return memcmp(data_, other.data_, datasize_ * sizeof(T)) == 0;
98 }
99
100 bool operator!=(const array<T> &other) const
101 {
102 return !(*this == other);
103 }
104
105 void steal_data(array &from)
106 {
107 if (this != &from) {
108 clear();
109
110 data_ = from.data_;
111 datasize_ = from.datasize_;
112 capacity_ = from.capacity_;
113
114 from.data_ = NULL;
115 from.datasize_ = 0;
116 from.capacity_ = 0;
117 }
118 }
119
120 void set_data(T *ptr_, size_t datasize)
121 {
122 clear();
123 data_ = ptr_;
124 datasize_ = datasize;
125 capacity_ = datasize;
126 }
127
129 {
130 T *ptr = data_;
131 data_ = NULL;
132 clear();
133 return ptr;
134 }
135
136 T *resize(size_t newsize)
137 {
138 if (newsize == 0) {
139 clear();
140 }
141 else if (newsize != datasize_) {
142 if (newsize > capacity_) {
143 T *newdata = mem_allocate(newsize);
144 if (newdata == NULL) {
145 /* Allocation failed, likely out of memory. */
146 clear();
147 return NULL;
148 }
149 else if (data_ != NULL) {
150 mem_copy(newdata, data_, ((datasize_ < newsize) ? datasize_ : newsize));
152 }
153 data_ = newdata;
154 capacity_ = newsize;
155 }
156 datasize_ = newsize;
157 }
158 return data_;
159 }
160
161 T *resize(size_t newsize, const T &value)
162 {
163 size_t oldsize = size();
164 resize(newsize);
165
166 for (size_t i = oldsize; i < size(); i++) {
167 data_[i] = value;
168 }
169
170 return data_;
171 }
172
173 void clear()
174 {
175 if (data_ != NULL) {
177 data_ = NULL;
178 }
179 datasize_ = 0;
180 capacity_ = 0;
181 }
182
183 size_t empty() const
184 {
185 return datasize_ == 0;
186 }
187
188 size_t size() const
189 {
190 return datasize_;
191 }
192
193 T *data()
194 {
195 return data_;
196 }
197
198 const T *data() const
199 {
200 return data_;
201 }
202
203 T &operator[](size_t i) const
204 {
205 assert(i < datasize_);
206 return data_[i];
207 }
208
209 T *begin()
210 {
211 return data_;
212 }
213
214 const T *begin() const
215 {
216 return data_;
217 }
218
219 T *end()
220 {
221 return data_ + datasize_;
222 }
223
224 const T *end() const
225 {
226 return data_ + datasize_;
227 }
228
229 void reserve(size_t newcapacity)
230 {
231 if (newcapacity > capacity_) {
232 T *newdata = mem_allocate(newcapacity);
233 if (data_ != NULL) {
234 mem_copy(newdata, data_, ((datasize_ < newcapacity) ? datasize_ : newcapacity));
236 }
237 data_ = newdata;
238 capacity_ = newcapacity;
239 }
240 }
241
242 size_t capacity() const
243 {
244 return capacity_;
245 }
246
247 // do not use this method unless you are sure the code is not performance critical
248 void push_back_slow(const T &t)
249 {
250 if (capacity_ == datasize_) {
251 reserve(datasize_ == 0 ? 1 : (size_t)((datasize_ + 1) * 1.2));
252 }
253
254 data_[datasize_++] = t;
255 }
256
257 void push_back_reserved(const T &t)
258 {
259 assert(datasize_ < capacity_);
261 }
262
263 void append(const array<T> &from)
264 {
265 if (from.size()) {
266 size_t old_size = size();
267 resize(old_size + from.size());
268 mem_copy(data_ + old_size, from.data(), from.size());
269 }
270 }
271
272 protected:
273 inline T *mem_allocate(size_t N)
274 {
275 if (N == 0) {
276 return NULL;
277 }
278 T *mem = (T *)util_aligned_malloc(sizeof(T) * N, alignment);
279 if (mem != NULL) {
280 util_guarded_mem_alloc(sizeof(T) * N);
281 }
282 else {
283 throw std::bad_alloc();
284 }
285 return mem;
286 }
287
288 inline void mem_free(T *mem, size_t N)
289 {
290 if (mem != NULL) {
291 util_guarded_mem_free(sizeof(T) * N);
293 }
294 }
295
296 inline void mem_copy(T *mem_to, const T *mem_from, const size_t N)
297 {
298 memcpy((void *)mem_to, mem_from, sizeof(T) * N);
299 }
300
302 size_t datasize_;
303 size_t capacity_;
304};
305
307
308#endif /* __UTIL_ARRAY_H__ */
void util_aligned_free(void *ptr)
CCL_NAMESPACE_BEGIN void * util_aligned_malloc(size_t size, int alignment)
void append(const array< T > &from)
void steal_data(array &from)
const T * data() const
T * resize(size_t newsize)
bool operator!=(const array< T > &other) const
size_t capacity_
array & operator=(const array &from)
T * steal_pointer()
size_t size() const
array(size_t newsize)
array & operator=(const vector< T > &from)
size_t empty() const
size_t datasize_
const T * end() const
size_t capacity() const
void push_back_reserved(const T &t)
void set_data(T *ptr_, size_t datasize)
void mem_free(T *mem, size_t N)
void mem_copy(T *mem_to, const T *mem_from, const size_t N)
void reserve(size_t newcapacity)
T * resize(size_t newsize, const T &value)
T * mem_allocate(size_t N)
T & operator[](size_t i) const
void push_back_slow(const T &t)
const T * begin() const
bool operator==(const array< T > &other) const
array(const array &from)
#define CCL_NAMESPACE_END
#define NULL
void util_guarded_mem_free(size_t n)
void util_guarded_mem_alloc(size_t n)
#define N
PointerRNA * ptr
Definition wm_files.cc:4126