L4Re Operating System Framework
Interface and Usage Documentation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
ref_ptr
1// vim:set ft=cpp: -*- Mode: C++ -*-
2/*
3 * (c) 2008-2009 Alexander Warg <warg@os.inf.tu-dresden.de>
4 * economic rights: Technische Universität Dresden (Germany)
5 *
6 * License: see LICENSE.spdx (in this directory or the directories above)
7 */
8
9#pragma once
10
11#include "type_traits"
12#include <stddef.h>
13#include <l4/sys/compiler.h>
14
15namespace cxx {
16
17template< typename T >
18struct Default_ref_counter
19{
20 void h_drop_ref(T *p) noexcept
21 {
22 if (p->remove_ref() == 0)
23 delete p;
24 }
25
26 void h_take_ref(T *p) noexcept
27 {
28 p->add_ref();
29 }
30};
31
32struct Ref_ptr_base
33{
34 enum Default_value
35 { Nil = 0 };
36};
37
38template<typename T, template< typename X > class CNT = Default_ref_counter>
39class Weak_ptr;
40
66template <
67 typename T = void,
68 template< typename X > class CNT = Default_ref_counter
69>
70class Ref_ptr : public Ref_ptr_base, private CNT<T>
71{
72private:
73 typedef decltype(nullptr) Null_type;
74 typedef Weak_ptr<T, CNT> Wp;
75
76public:
78 Ref_ptr() noexcept : _p(0) {}
79
80 Ref_ptr(Ref_ptr_base::Default_value v)
81 : _p(reinterpret_cast<T*>(static_cast<unsigned long>(v))) {}
82
88 Ref_ptr(Wp const &o) noexcept : _p(o.ptr())
89 { __take_ref(); }
90
92 Ref_ptr(decltype(nullptr) n) noexcept : _p(n) {}
93
100 template<typename X>
101 explicit Ref_ptr(X *o) noexcept : _p(o)
102 { __take_ref(); }
103
114 Ref_ptr(T *o, [[maybe_unused]] bool d) noexcept : _p(o) { }
115
121 T *get() const noexcept
122 {
123 return _p;
124 }
125
127 T *ptr() const noexcept
128 {
129 return _p;
130 }
131
138 T *release() noexcept
139 {
140 T *p = _p;
141 _p = 0;
142 return p;
143 }
144
145 ~Ref_ptr() noexcept
146 { __drop_ref(); }
147
148 template<typename OT>
149 Ref_ptr(Ref_ptr<OT, CNT> const &o) noexcept
150 {
151 _p = o.ptr();
152 __take_ref();
153 }
154
155 Ref_ptr(Ref_ptr<T> const &o) noexcept
156 {
157 _p = o._p;
158 __take_ref();
159 }
160
161 template< typename OT >
162 void operator = (Ref_ptr<OT> const &o) noexcept
163 {
164 __drop_ref();
165 _p = o.ptr();
166 __take_ref();
167 }
168
169 void operator = (Ref_ptr<T> const &o) noexcept
170 {
171 if (&o == this)
172 return;
173
174 __drop_ref();
175 _p = o._p;
176 __take_ref();
177 }
178
179 void operator = (Null_type) noexcept
180 {
181 __drop_ref();
182 _p = 0;
183 }
184
185 template<typename OT>
186 Ref_ptr(Ref_ptr<OT, CNT> &&o) noexcept
187 { _p = o.release(); }
188
189 Ref_ptr(Ref_ptr<T> &&o) noexcept
190 { _p = o.release(); }
191
192 template< typename OT >
193 void operator = (Ref_ptr<OT> &&o) noexcept
194 {
195 __drop_ref();
196 _p = o.release();
197 }
198
199 void operator = (Ref_ptr<T> &&o) noexcept
200 {
201 if (&o == this)
202 return;
203
204 __drop_ref();
205 _p = o.release();
206 }
207
208 [[nodiscard]] explicit operator bool () const noexcept { return _p; }
209
210 T *operator -> () const noexcept
211 { return _p; }
212
213 [[nodiscard]] bool operator == (Ref_ptr const &o) const noexcept
214 { return _p == o._p; }
215
216 [[nodiscard]] bool operator != (Ref_ptr const &o) const noexcept
217 { return _p != o._p; }
218
219 [[nodiscard]] bool operator < (Ref_ptr const &o) const noexcept
220 { return _p < o._p; }
221
222 [[nodiscard]] bool operator <= (Ref_ptr const &o) const noexcept
223 { return _p <= o._p; }
224
225 [[nodiscard]] bool operator > (Ref_ptr const &o) const noexcept
226 { return _p > o._p; }
227
228 [[nodiscard]] bool operator >= (Ref_ptr const &o) const noexcept
229 { return _p >= o._p; }
230
231 [[nodiscard]] bool operator == (T const *o) const noexcept
232 { return _p == o; }
233
234 [[nodiscard]] bool operator < (T const *o) const noexcept
235 { return _p < o; }
236
237 [[nodiscard]] bool operator <= (T const *o) const noexcept
238 { return _p <= o; }
239
240 [[nodiscard]] bool operator > (T const *o) const noexcept
241 { return _p > o; }
242
243 [[nodiscard]] bool operator >= (T const *o) const noexcept
244 { return _p >= o; }
245
246private:
247 void __drop_ref() noexcept
248 {
249 if (_p)
250 static_cast<CNT<T>*>(this)->h_drop_ref(_p);
251 }
252
253 void __take_ref() noexcept
254 {
255 if (_p)
256 static_cast<CNT<T>*>(this)->h_take_ref(_p);
257 }
258
259 T *_p;
260};
261
262
263template<typename T, template< typename X > class CNT>
264class Weak_ptr
265{
266private:
267 struct Null_type;
268 typedef Ref_ptr<T, CNT> Rp;
269
270public:
271 Weak_ptr() = default;
272 Weak_ptr(decltype(nullptr)) : _p(nullptr) {}
273 // backwards 0 ctor
274 explicit Weak_ptr(int x) noexcept
275 L4_DEPRECATED("Use initialization from 'nullptr'")
276 : _p(nullptr)
277 { if (x != 0) __builtin_trap(); }
278
279 Weak_ptr(Rp const &o) noexcept : _p(o.ptr()) {}
280 explicit Weak_ptr(T *o) noexcept : _p(o) {}
281
282 template<typename OT>
283 Weak_ptr(Weak_ptr<OT, CNT> const &o) noexcept : _p(o.ptr()) {}
284
285 Weak_ptr(Weak_ptr<T, CNT> const &o) noexcept : _p(o._p) {}
286
287 Weak_ptr<T, CNT> &operator = (const Weak_ptr<T, CNT> &o) = default;
288
289 T *get() const noexcept { return _p; }
290 T *ptr() const noexcept { return _p; }
291
292 T *operator -> () const noexcept { return _p; }
293 operator Null_type const * () const noexcept
294 { return reinterpret_cast<Null_type const*>(_p); }
295
296private:
297 T *_p;
298};
299
300template<typename OT, typename T> inline
301Ref_ptr<OT> ref_ptr_static_cast(Ref_ptr<T> const &o)
302{ return ref_ptr(static_cast<OT*>(o.ptr())); }
303
304template< typename T >
305inline Ref_ptr<T> ref_ptr(T *t)
306{ return Ref_ptr<T>(t); }
307
308template< typename T >
309inline Weak_ptr<T> weak_ptr(T *t)
310{ return Weak_ptr<T>(t); }
311
312
313class Ref_obj
314{
315private:
316 mutable int _ref_cnt;
317
318public:
319 Ref_obj() : _ref_cnt(0) {}
320 void add_ref() const noexcept { ++_ref_cnt; }
321 int remove_ref() const noexcept { return --_ref_cnt; }
322};
323
324template< typename T, typename... Args >
325Ref_ptr<T>
326make_ref_obj(Args &&... args)
327{ return cxx::Ref_ptr<T>(new T(cxx::forward<Args>(args)...)); }
328
329template<typename T, typename U>
330Ref_ptr<T>
331dynamic_pointer_cast(Ref_ptr<U> const &p) noexcept
332{
333 // our constructor from a naked pointer increments the counter
334 return Ref_ptr<T>(dynamic_cast<T *>(p.get()));
335}
336
337template<typename T, typename U>
338Ref_ptr<T>
339static_pointer_cast(Ref_ptr<U> const &p) noexcept
340{
341 // our constructor from a naked pointer increments the counter
342 return Ref_ptr<T>(static_cast<T *>(p.get()));
343}
344
345}
A reference-counting pointer with automatic cleanup.
Definition ref_ptr:71
Ref_ptr(Wp const &o) noexcept
Create a shared pointer from a weak pointer.
Definition ref_ptr:88
Ref_ptr() noexcept
Default constructor creates a pointer with no managed object.
Definition ref_ptr:78
Ref_ptr(decltype(nullptr) n) noexcept
allow creation from nullptr
Definition ref_ptr:92
T * get() const noexcept
Return a raw pointer to the object this shared pointer points to.
Definition ref_ptr:121
T * release() noexcept
Release the shared pointer without removing the reference.
Definition ref_ptr:138
Ref_ptr(X *o) noexcept
Create a shared pointer from a raw pointer.
Definition ref_ptr:101
Ref_ptr(T *o, bool d) noexcept
Create a shared pointer from a raw pointer without creating a new reference.
Definition ref_ptr:114
T * ptr() const noexcept
Return a raw pointer to the object this shared pointer points to.
Definition ref_ptr:127
L4 compiler related defines.
#define L4_DEPRECATED(s)
Mark symbol deprecated.
Definition compiler.h:280
Our C++ library.
Definition arith:11