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