MOS Source Code
Loading...
Searching...
No Matches
shared_ptr.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2#pragma once
3
4#include <cstddef>
5#include <mos/allocator.hpp>
6#include <mos/type_utils.hpp>
7#include <mos/types.hpp>
8#include <type_traits>
9
10namespace mos
11{
12 // Forward declaration for shared_ptr
13 template<typename T>
14 class shared_ptr;
15
16 // Forward declaration for weak_ptr
17 template<typename T>
18 class weak_ptr;
19
20 template<typename T, typename... Args>
21 T *create(Args &&...args);
22
23 template<typename T>
24 struct __shared_ptr_core : mos::NamedType<"shared_ptr.core">
25 {
26 explicit __shared_ptr_core(T *ptr, size_t own, size_t weak) : _ptr(ptr), _n_own(own), _n_weak(weak) {};
28 {
29 delete _ptr;
30 }
31
32 // clang-format off
33 void _dec_weak() { _n_weak--; }
34 void _inc_weak() { _n_weak++; }
35 void _inc_use() { _n_own++; }
36 void _dec_use() { _n_own--; }
37 // clang-format on
38
39 bool _can_delete() const
40 {
41 return _n_own == 0;
42 }
43
44 size_t _use_count() const
45 {
46 return _n_own;
47 }
48
49 size_t _weak_count() const
50 {
51 return _n_weak;
52 }
53
54 friend bool operator==(const __shared_ptr_core &lhs, const __shared_ptr_core &rhs)
55 {
56 return lhs._ptr == rhs._ptr;
57 }
58
59 public:
60 T *_ptr;
61
62 private:
63 size_t _n_own; // number of shared_ptr instances owning the object
64 size_t _n_weak; // number of weak_ptr instances owning the object
65 };
66
67 template<typename T>
69 {
70 friend class shared_ptr<T>;
71
72 public:
73 using element_type = std::remove_extent_t<T>;
74
75 public:
76 constexpr weak_ptr() : _c(nullptr) {};
77 constexpr weak_ptr(std::nullptr_t) : _c(nullptr) {};
78
79 weak_ptr(const weak_ptr &r) noexcept : _c(r._c)
80 {
81 _c->_inc_weak();
82 }
83
84 template<class Y>
85 weak_ptr(const weak_ptr<Y> &r) noexcept : _c(r._c)
86 {
87 _c->_inc_weak();
88 }
89
90 template<class Y>
91 weak_ptr(const shared_ptr<Y> &r) noexcept : _c(r._c)
92 {
93 _c->_inc_weak();
94 }
95
96 weak_ptr(weak_ptr &&r) noexcept : _c(r._c)
97 {
98 r._c = nullptr;
99 }
100
101 template<class Y>
102 weak_ptr(weak_ptr<Y> &&r) noexcept : _c(r._c)
103 {
104 r._c = nullptr;
105 }
106
107 public:
108 long use_count() const
109 {
110 if (_c == nullptr)
111 return 0;
112 return _c->_n_own;
113 }
114
115 bool expired() const
116 {
117 return use_count() == 0;
118 }
119
121 {
122 if (_c->_use_count() == 0)
123 return nullptr;
124 return shared_ptr<T>(_c);
125 }
126
128 {
129 _c->_dec_weak();
130 if (_c->_can_delete())
131 delete _c;
132 }
133
134 private:
136 };
137
138 template<typename T>
140 {
141 friend class weak_ptr<T>;
142
143 public:
144 using element_type = std::remove_extent_t<T>;
145
146 public:
147 constexpr shared_ptr() noexcept : _c(nullptr) {};
148 constexpr shared_ptr(std::nullptr_t) noexcept : _c(nullptr) {};
149
150 template<typename Y>
151 explicit shared_ptr(Y *ptr) : _c(mos::create<__shared_ptr_core<T>>(ptr, 1, 0)){};
152
154 {
155 if (_c)
156 _c->_inc_use();
157 }
158
159 shared_ptr(const shared_ptr &r) noexcept : _c(r._c)
160 {
161 if (_c)
162 _c->_inc_use();
163 }
164
165 template<typename Y>
166 shared_ptr(shared_ptr<Y> &other) : _c(other._c)
167 {
168 if (_c)
169 _c->_inc_use();
170 }
171
172 shared_ptr(shared_ptr &&r) noexcept : _c(r._c)
173 {
174 r._c = nullptr;
175 }
176
177 template<typename Y>
178 shared_ptr(shared_ptr<Y> &&other) : _c(other._c)
179 {
180 other._c = nullptr;
181 }
182
183 public:
184 shared_ptr &operator=(const shared_ptr &r) noexcept
185 {
186 if (_c == r._c)
187 return *this;
188
189 if (_c)
190 {
191 _c->_dec_use();
192 if (_c->_can_delete())
193 delete _c;
194 }
195
196 _c = r._c;
197 if (_c)
198 _c->_inc_use();
199
200 return *this;
201 }
202
203 template<class Y>
205 {
206 if (_c == r._c)
207 return *this;
208
209 if (_c)
210 {
211 _c->_dec_use();
212 if (_c->_can_delete())
213 delete _c;
214 }
215
216 _c = r._c;
217 if (_c)
218 _c->_inc_use();
219
220 return *this;
221 }
222
224 {
225 if (_c == r._c)
226 return *this;
227
228 if (_c)
229 {
230 _c->_dec_use();
231 if (_c->_can_delete())
232 delete _c;
233 }
234
235 _c = r._c;
236 r._c = nullptr;
237
238 return *this;
239 }
240
241 template<class Y>
243 {
244 if (_c == r._c)
245 return *this;
246
247 if (_c)
248 {
249 _c->_dec_use();
250 if (_c->_can_delete())
251 delete _c;
252 }
253
254 _c = r._c;
255 r._c = nullptr;
256
257 return *this;
258 }
259
260 public:
262 {
263 if (_c == nullptr)
264 return; // nothing to do, we represents nullptr
265
266 _c->_dec_use();
267 if (_c->_can_delete())
268 delete _c;
269 }
270
271 public:
272 long use_count() const
273 {
274 if (_c == nullptr)
275 return 0;
276 return _c->_use_count();
277 }
278
279 void reset()
280 {
281 if (_c == nullptr)
282 return;
283 _c->_dec_use();
284 if (_c->_can_delete())
285 delete _c;
286 _c = nullptr;
287 }
288
290 {
291 if (_c == nullptr)
292 return nullptr;
293 T *ptr = _c->_ptr;
294 _c->_dec_use();
295 if (_c->_can_delete())
296 delete _c;
297 _c = nullptr;
298 return ptr;
299 }
300
301 public:
303 {
304 if (_c == nullptr)
305 return nullptr;
306 return _c->_ptr;
307 }
308
310 {
311 return *_c->_ptr;
312 }
313
315 {
316 if (_c == nullptr)
317 return nullptr;
318 return _c->_ptr;
319 }
320
321 public:
322 friend void swap(shared_ptr &lhs, shared_ptr &rhs)
323 {
324 std::swap(lhs._c, rhs._c);
325 }
326
327 friend bool operator==(const shared_ptr &lhs, const shared_ptr &rhs)
328 {
329 return lhs._c == rhs._c && *lhs._c == *rhs._c;
330 }
331
332 friend bool operator==(const shared_ptr &lhs, std::nullptr_t)
333 {
334 return lhs._c == nullptr;
335 }
336
337 operator bool() const
338 {
339 return _c != nullptr;
340 }
341
342 private:
344 };
345
346 template<typename T, typename... Args>
348 {
349 return shared_ptr<T>(mos::create<T>(std::forward<Args>(args)...));
350 }
351} // namespace mos
352
353template<typename T>
355
356template<typename T>
357struct PtrResult<mos::shared_ptr<T>>
358{
359 private:
361 const int errorCode;
362
363 public:
364 PtrResult() : value(nullptr) {};
366 PtrResult(const mos::shared_ptr<T> &&value) : value(std::move(value)), errorCode(0) {};
368
369 public:
371 {
372 return value;
373 }
374
375 bool isErr() const
376 {
377 return errorCode != 0;
378 }
379
380 long getErr() const
381 {
382 return errorCode;
383 }
384};
char args[3][16]
Definition avr_io.c:16
element_type & operator*() const
shared_ptr(shared_ptr &&r) noexcept
shared_ptr & operator=(const shared_ptr &r) noexcept
__shared_ptr_core< T > * _c
shared_ptr(shared_ptr< Y > &&other)
shared_ptr(__shared_ptr_core< T > *cb)
friend bool operator==(const shared_ptr &lhs, const shared_ptr &rhs)
shared_ptr & operator=(shared_ptr< Y > &&r) noexcept
shared_ptr(shared_ptr< Y > &other)
friend bool operator==(const shared_ptr &lhs, std::nullptr_t)
shared_ptr & operator=(shared_ptr &&r) noexcept
element_type * get() const
friend void swap(shared_ptr &lhs, shared_ptr &rhs)
constexpr shared_ptr() noexcept
shared_ptr(const shared_ptr &r) noexcept
constexpr shared_ptr(std::nullptr_t) noexcept
std::remove_extent_t< T > element_type
element_type * operator->() const
shared_ptr & operator=(const shared_ptr< Y > &r) noexcept
long use_count() const
weak_ptr(weak_ptr &&r) noexcept
__shared_ptr_core< T > * _c
constexpr weak_ptr()
friend class shared_ptr< T >
shared_ptr< T > lock()
weak_ptr(const shared_ptr< Y > &r) noexcept
weak_ptr(const weak_ptr &r) noexcept
constexpr weak_ptr(std::nullptr_t)
bool expired() const
weak_ptr(const weak_ptr< Y > &r) noexcept
std::remove_extent_t< T > element_type
weak_ptr(weak_ptr< Y > &&r) noexcept
long use_count() const
T * create(Args &&...args)
Definition allocator.hpp:10
shared_ptr< T > make_shared(Args &&...args)
int bool
Definition pb_syshdr.h:57
mos::shared_ptr< T > ptr
PtrResult(const mos::shared_ptr< T > &value)
PtrResult(const mos::shared_ptr< T > &&value)
mos::shared_ptr< T > get() const
const mos::shared_ptr< T > value
__shared_ptr_core(T *ptr, size_t own, size_t weak)
size_t _weak_count() const
friend bool operator==(const __shared_ptr_core &lhs, const __shared_ptr_core &rhs)
size_t _use_count() const
bool _can_delete() const