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