Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/frontends/clover/util/pointer.hpp
4572 views
1
//
2
// Copyright 2013 Francisco Jerez
3
//
4
// Permission is hereby granted, free of charge, to any person obtaining a
5
// copy of this software and associated documentation files (the "Software"),
6
// to deal in the Software without restriction, including without limitation
7
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
// and/or sell copies of the Software, and to permit persons to whom the
9
// Software is furnished to do so, subject to the following conditions:
10
//
11
// The above copyright notice and this permission notice shall be included in
12
// all copies or substantial portions of the Software.
13
//
14
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20
// OTHER DEALINGS IN THE SOFTWARE.
21
//
22
23
#ifndef CLOVER_UTIL_POINTER_HPP
24
#define CLOVER_UTIL_POINTER_HPP
25
26
#include <atomic>
27
28
namespace clover {
29
///
30
/// Some helper functions for raw pointer operations
31
///
32
template <class T>
33
static bool
34
ptr_is_aligned(const T *ptr, uintptr_t a) noexcept {
35
assert(a == (a & -a));
36
uintptr_t ptr_value = reinterpret_cast<uintptr_t>(ptr);
37
return (ptr_value & (a - 1)) == 0;
38
}
39
40
///
41
/// Base class for objects that support reference counting.
42
///
43
class ref_counter {
44
public:
45
ref_counter(unsigned value = 1) : _ref_count(value) {}
46
47
unsigned
48
ref_count() const {
49
return _ref_count;
50
}
51
52
void
53
retain() {
54
_ref_count++;
55
}
56
57
bool
58
release() {
59
return (--_ref_count) == 0;
60
}
61
62
private:
63
std::atomic<unsigned> _ref_count;
64
};
65
66
///
67
/// Simple reference to a clover::ref_counter object. Unlike
68
/// clover::intrusive_ptr and clover::intrusive_ref, it does nothing
69
/// special when the reference count drops to zero.
70
///
71
class ref_holder {
72
public:
73
ref_holder(ref_counter &o) : p(&o) {
74
p->retain();
75
}
76
77
ref_holder(const ref_holder &ref) :
78
ref_holder(*ref.p) {
79
}
80
81
ref_holder(ref_holder &&ref) :
82
p(ref.p) {
83
ref.p = NULL;
84
}
85
86
~ref_holder() {
87
if (p)
88
p->release();
89
}
90
91
ref_holder &
92
operator=(ref_holder ref) {
93
std::swap(ref.p, p);
94
return *this;
95
}
96
97
bool
98
operator==(const ref_holder &ref) const {
99
return p == ref.p;
100
}
101
102
bool
103
operator!=(const ref_holder &ref) const {
104
return p != ref.p;
105
}
106
107
private:
108
ref_counter *p;
109
};
110
111
///
112
/// Intrusive smart pointer for objects that implement the
113
/// clover::ref_counter interface.
114
///
115
template<typename T>
116
class intrusive_ptr {
117
public:
118
intrusive_ptr(T *q = NULL) : p(q) {
119
if (p)
120
p->retain();
121
}
122
123
intrusive_ptr(const intrusive_ptr &ptr) :
124
intrusive_ptr(ptr.p) {
125
}
126
127
intrusive_ptr(intrusive_ptr &&ptr) :
128
p(ptr.p) {
129
ptr.p = NULL;
130
}
131
132
~intrusive_ptr() {
133
if (p && p->release())
134
delete p;
135
}
136
137
intrusive_ptr &
138
operator=(intrusive_ptr ptr) {
139
std::swap(ptr.p, p);
140
return *this;
141
}
142
143
bool
144
operator==(const intrusive_ptr &ref) const {
145
return p == ref.p;
146
}
147
148
bool
149
operator!=(const intrusive_ptr &ref) const {
150
return p != ref.p;
151
}
152
153
T &
154
operator*() const {
155
return *p;
156
}
157
158
T *
159
operator->() const {
160
return p;
161
}
162
163
T *
164
operator()() const {
165
return p;
166
}
167
168
explicit operator bool() const {
169
return p;
170
}
171
172
explicit operator T *() const {
173
return p;
174
}
175
176
private:
177
T *p;
178
};
179
180
///
181
/// Intrusive smart reference for objects that implement the
182
/// clover::ref_counter interface.
183
///
184
template<typename T>
185
class intrusive_ref {
186
public:
187
intrusive_ref(T &o) : p(&o) {
188
p->retain();
189
}
190
191
intrusive_ref(const intrusive_ref &ref) :
192
intrusive_ref(*ref.p) {
193
}
194
195
intrusive_ref(intrusive_ref &&ref) :
196
p(ref.p) {
197
ref.p = NULL;
198
}
199
200
~intrusive_ref() {
201
if (p && p->release())
202
delete p;
203
}
204
205
intrusive_ref &
206
operator=(intrusive_ref ref) {
207
std::swap(ref.p, p);
208
return *this;
209
}
210
211
bool
212
operator==(const intrusive_ref &ref) const {
213
return p == ref.p;
214
}
215
216
bool
217
operator!=(const intrusive_ref &ref) const {
218
return p != ref.p;
219
}
220
221
T &
222
operator()() const {
223
return *p;
224
}
225
226
operator T &() const {
227
return *p;
228
}
229
230
private:
231
T *p;
232
};
233
234
///
235
/// Initialize a clover::intrusive_ref from a newly created object
236
/// using the specified constructor arguments.
237
///
238
template<typename T, typename... As>
239
intrusive_ref<T>
240
create(As &&... as) {
241
intrusive_ref<T> ref { *new T(std::forward<As>(as)...) };
242
ref().release();
243
return ref;
244
}
245
246
///
247
/// Class that implements the usual pointer interface but in fact
248
/// contains the object it seems to be pointing to.
249
///
250
template<typename T>
251
class pseudo_ptr {
252
public:
253
pseudo_ptr(T x) : x(x) {
254
}
255
256
pseudo_ptr(const pseudo_ptr &p) : x(p.x) {
257
}
258
259
pseudo_ptr &
260
operator=(const pseudo_ptr &p) {
261
x = p.x;
262
return *this;
263
}
264
265
T &
266
operator*() {
267
return x;
268
}
269
270
T *
271
operator->() {
272
return &x;
273
}
274
275
explicit operator bool() const {
276
return true;
277
}
278
279
private:
280
T x;
281
};
282
}
283
284
#endif
285
286