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