Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/embree/common/sys/vector.h
21337 views
1
// Copyright 2009-2021 Intel Corporation
2
// SPDX-License-Identifier: Apache-2.0
3
4
#pragma once
5
6
#include "alloc.h"
7
#include <algorithm>
8
#include <type_traits>
9
10
namespace embree
11
{
12
class Device;
13
14
template<typename T, typename allocator>
15
class vector_t
16
{
17
public:
18
typedef T value_type;
19
typedef T* iterator;
20
typedef const T* const_iterator;
21
22
__forceinline vector_t ()
23
: size_active(0), size_alloced(0), items(nullptr) {}
24
25
__forceinline explicit vector_t (size_t sz)
26
: size_active(0), size_alloced(0), items(nullptr) { internal_resize_init(sz); }
27
28
template<typename M>
29
__forceinline explicit vector_t (M alloc, size_t sz)
30
: alloc(alloc), size_active(0), size_alloced(0), items(nullptr) { internal_resize_init(sz); }
31
32
__forceinline vector_t (Device* alloc)
33
: vector_t(alloc,0) {}
34
35
__forceinline vector_t(void* data, size_t bytes)
36
: size_active(0), size_alloced(bytes/sizeof(T)), items((T*)data) {}
37
38
__forceinline ~vector_t() {
39
clear();
40
}
41
42
__forceinline vector_t (const vector_t& other)
43
{
44
size_active = other.size_active;
45
size_alloced = other.size_alloced;
46
items = alloc.allocate(size_alloced);
47
for (size_t i=0; i<size_active; i++)
48
::new (&items[i]) value_type(other.items[i]);
49
}
50
51
__forceinline vector_t (vector_t&& other)
52
: alloc(std::move(other.alloc))
53
{
54
size_active = other.size_active; other.size_active = 0;
55
size_alloced = other.size_alloced; other.size_alloced = 0;
56
items = other.items; other.items = nullptr;
57
}
58
59
__forceinline vector_t& operator=(const vector_t& other)
60
{
61
resize(other.size_active);
62
for (size_t i=0; i<size_active; i++)
63
items[i] = value_type(other.items[i]);
64
return *this;
65
}
66
67
__forceinline vector_t& operator=(vector_t&& other)
68
{
69
clear();
70
alloc = std::move(other.alloc);
71
size_active = other.size_active; other.size_active = 0;
72
size_alloced = other.size_alloced; other.size_alloced = 0;
73
items = other.items; other.items = nullptr;
74
return *this;
75
}
76
77
__forceinline allocator& getAlloc() {
78
return alloc;
79
}
80
81
/********************** Iterators ****************************/
82
83
__forceinline iterator begin() { return items; };
84
__forceinline const_iterator begin() const { return items; };
85
86
__forceinline iterator end () { return items+size_active; };
87
__forceinline const_iterator end () const { return items+size_active; };
88
89
90
/********************** Capacity ****************************/
91
92
__forceinline bool empty () const { return size_active == 0; }
93
__forceinline size_t size () const { return size_active; }
94
__forceinline size_t capacity () const { return size_alloced; }
95
96
97
__forceinline void resize(size_t new_size) {
98
internal_resize(new_size,internal_grow_size(new_size));
99
}
100
101
__forceinline void reserve(size_t new_alloced)
102
{
103
/* do nothing if container already large enough */
104
if (new_alloced <= size_alloced)
105
return;
106
107
/* resize exact otherwise */
108
internal_resize(size_active,new_alloced);
109
}
110
111
__forceinline void shrink_to_fit() {
112
internal_resize(size_active,size_active);
113
}
114
115
/******************** Element access **************************/
116
117
__forceinline T& operator[](size_t i) { assert(i < size_active); return items[i]; }
118
__forceinline const T& operator[](size_t i) const { assert(i < size_active); return items[i]; }
119
120
__forceinline T& at(size_t i) { assert(i < size_active); return items[i]; }
121
__forceinline const T& at(size_t i) const { assert(i < size_active); return items[i]; }
122
123
__forceinline T& front() const { assert(size_active > 0); return items[0]; };
124
__forceinline T& back () const { assert(size_active > 0); return items[size_active-1]; };
125
126
__forceinline T* data() { return items; };
127
__forceinline const T* data() const { return items; };
128
129
/* dangerous only use if you know what you're doing */
130
__forceinline void setDataPtr(T* data) { items = data; }
131
132
/******************** Modifiers **************************/
133
134
__forceinline void push_back(const T& nt)
135
{
136
const T v = nt; // need local copy as input reference could point to this vector
137
internal_resize(size_active,internal_grow_size(size_active+1));
138
::new (&items[size_active++]) T(v);
139
}
140
141
__forceinline void pop_back()
142
{
143
assert(!empty());
144
size_active--;
145
items[size_active].~T();
146
}
147
148
__forceinline void clear()
149
{
150
/* destroy elements */
151
for (size_t i=0; i<size_active; i++){
152
items[i].~T();
153
}
154
155
/* free memory */
156
alloc.deallocate(items,size_alloced);
157
items = nullptr;
158
size_active = size_alloced = 0;
159
}
160
161
/******************** Comparisons **************************/
162
163
friend bool operator== (const vector_t& a, const vector_t& b)
164
{
165
if (a.size() != b.size()) return false;
166
for (size_t i=0; i<a.size(); i++)
167
if (a[i] != b[i])
168
return false;
169
return true;
170
}
171
172
friend bool operator!= (const vector_t& a, const vector_t& b) {
173
return !(a==b);
174
}
175
176
private:
177
178
__forceinline void internal_resize_init(size_t new_active)
179
{
180
assert(size_active == 0);
181
assert(size_alloced == 0);
182
assert(items == nullptr);
183
if (new_active == 0) return;
184
items = alloc.allocate(new_active);
185
for (size_t i=0; i<new_active; i++) ::new (&items[i]) T();
186
size_active = new_active;
187
size_alloced = new_active;
188
}
189
190
__forceinline void internal_resize(size_t new_active, size_t new_alloced)
191
{
192
assert(new_active <= new_alloced);
193
194
/* destroy elements */
195
if (new_active < size_active)
196
{
197
for (size_t i=new_active; i<size_active; i++){
198
items[i].~T();
199
}
200
size_active = new_active;
201
}
202
203
/* only reallocate if necessary */
204
if (new_alloced == size_alloced) {
205
for (size_t i=size_active; i<new_active; i++) ::new (&items[i]) T;
206
size_active = new_active;
207
return;
208
}
209
210
/* reallocate and copy items */
211
T* old_items = items;
212
items = alloc.allocate(new_alloced);
213
for (size_t i=0; i<size_active; i++) {
214
::new (&items[i]) T(std::move(old_items[i]));
215
old_items[i].~T();
216
}
217
218
for (size_t i=size_active; i<new_active; i++) {
219
::new (&items[i]) T;
220
}
221
222
alloc.deallocate(old_items,size_alloced);
223
size_active = new_active;
224
size_alloced = new_alloced;
225
}
226
227
__forceinline size_t internal_grow_size(size_t new_alloced)
228
{
229
/* do nothing if container already large enough */
230
if (new_alloced <= size_alloced)
231
return size_alloced;
232
233
/* if current size is 0 allocate exact requested size */
234
if (size_alloced == 0)
235
return new_alloced;
236
237
/* resize to next power of 2 otherwise */
238
size_t new_size_alloced = size_alloced;
239
while (new_size_alloced < new_alloced) {
240
new_size_alloced = std::max(size_t(1),2*new_size_alloced);
241
}
242
return new_size_alloced;
243
}
244
245
private:
246
allocator alloc;
247
size_t size_active; // number of valid items
248
size_t size_alloced; // number of items allocated
249
T* items; // data array
250
};
251
252
/*! vector class that performs standard allocations */
253
template<typename T>
254
using vector = vector_t<T,std::allocator<T>>;
255
256
/*! vector class that performs aligned allocations */
257
template<typename T>
258
using avector = vector_t<T,aligned_allocator<T,std::alignment_of<T>::value> >;
259
260
/*! vector class that performs OS allocations */
261
template<typename T>
262
using ovector = vector_t<T,os_allocator<T> >;
263
264
/*! vector class with externally managed data buffer */
265
template<typename T>
266
using evector = vector_t<T,no_allocator<T>>;
267
}
268
269