source: mainline/uspace/lib/cpp/include/internal/memory/shared_ptr.hpp@ e13c378

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since e13c378 was 537b300, checked in by Dzejrou <dzejrou@…>, 7 years ago

cpp: added more definitions to shared_ptr and a WIP version of shared_payload

  • Property mode set to 100644
File size: 10.5 KB
Line 
1/*
2 * Copyright (c) 2018 Jaroslav Jindrak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef LIBCPP_INTERNAL_MEMORY_SHARED_PTR
30#define LIBCPP_INTERNAL_MEMORY_SHARED_PTR
31
32#include <exception>
33#include <functional>
34#include <type_traits>
35
36namespace std
37{
38 /**
39 * 20.8.2.1, class bad_weak_ptr:
40 */
41
42 class bad_weak_ptr: public exception
43 {
44 public:
45 bad_weak_ptr() noexcept = default;
46
47 const char* what() const noexcept override
48 {
49 return "std::bad_weak_ptr";
50 }
51 };
52
53 /**
54 * 20.8.2.2, class template shared_ptr:
55 */
56
57 template<class T>
58 class shared_ptr
59 {
60 public:
61 using element_type = T;
62
63 /**
64 * 20.8.2.2.1, constructors:
65 */
66
67 constexpr shared_ptr() noexcept;
68
69 template<class U>
70 explicit shared_ptr(U* ptr);
71
72 template<class U, class D>
73 shared_ptr(U* ptr, D deleter);
74
75 template<class U, class D, class A>
76 shared_ptr(U* ptr, D deleter, A alloc);
77
78 template<class D>
79 shared_ptr(nullptr_t, D deleter);
80
81 template<class D, class A>
82 shared_ptr(nullptr_t, D deleter, A alloc);
83
84 template<class U>
85 shared_ptr(const shared_ptr<U>& other, value_type* ptr);
86
87 shared_ptr(const shared_ptr& other);
88
89 template<class U>
90 shared_ptr(const shared_ptr<U>& other);
91
92 shared_ptr(shared_ptr&& other);
93
94 template<class U>
95 shared_ptr(shared_ptr<U>&& other);
96
97 template<class U>
98 explicit shared_ptr(const weak_ptr<U>& other);
99
100 template<class U, class D>
101 shared_ptr(unique_ptr<U, D>&& other);
102
103 constexpr shared_ptr(nullptr_t) noexcept
104 : shared_ptr{}
105 { /* DUMMY BODY */ }
106
107 /**
108 * 20.8.2.2.2, destructor:
109 */
110
111 ~shared_ptr();
112
113 /**
114 * 20.8.2.2.3, assignment:
115 */
116
117 shared_ptr& operator=(const shared_ptr& rhs) noexcept;
118
119 template<class U>
120 shared_ptr& operator=(const shared_ptr<U>& rhs) noexcept;
121
122 shared_ptr& operator=(shared_ptr&& rhs) noexcept;
123
124 template<class U>
125 shared_ptr& operator=(shared_ptr<U>&& rhs) noexcept;
126
127 template<class U, class D>
128 shared_ptr& operator=(unique_ptr<U, D>&& rhs);
129
130 /**
131 * 20.8.2.2.4, modifiers:
132 */
133
134 void swap(shared_ptr& other) noexcept;
135
136 void reset() noexcept;
137
138 template<class U>
139 void reset(U* ptr);
140
141 template<class U, class D>
142 void reset(U* ptr, D deleter);
143
144 template<class U, class D, class A>
145 void reset(U* ptr, D deleter, A alloc);
146
147 /**
148 * 20.8.2.2.5, observers:
149 */
150
151 element_type* get() const noexcept
152 {
153 if (payload_)
154 return payload_->get();
155 else
156 return nullptr;
157 }
158
159 T& operator*() const noexcept;
160
161 T* operator->() const noexcept
162 {
163 return get();
164 }
165
166 long use_count() const noexcept
167 {
168 if (payload_)
169 return payload_->refcount();
170 else
171 return 0L;
172 }
173
174 bool unique() const noexcept
175 {
176 return use_count() == 1L;
177 }
178
179 explicit operator bool() const noexcept
180 {
181 return get() != nullptr;
182 }
183
184 template<class U>
185 bool owner_before(const shared_ptr<U>& ptr) const
186 {
187 return payload_ < ptr.payload_;
188 }
189
190 template<class U>
191 bool owner_before(const weak_ptr<U>& ptr) const;
192
193 private:
194 aux::shared_payload<element_type>* payload_;
195
196 shared_ptr(aux::shared_payload<element_type>* payload)
197 : payload_{payload}
198 { /* DUMMY BODY */ }
199
200 template<class U, class... Args>
201 friend shared_ptr<U> make_shared(Args&&...);
202
203 template<class U, class A, class... Args>
204 friend shared_ptr<U> allocate_shared(const A&, Args&&...);
205 };
206
207 /**
208 * 20.8.2.2.6, shared_ptr creation:
209 * Note: According to the standard, these two functions
210 * should perform at most one memory allocation
211 * (should, don't have to :P). It might be better
212 * to create payloads that embed the type T to
213 * perform this optimization.
214 */
215
216 template<class T, class... Args>
217 shared_ptr<T> make_shared(Args&&... args)
218 {
219 return shared_ptr<T>{
220 new aux::shared_payload<T>{forward<Args>(args)...}
221 };
222 }
223
224 template<class T, class A, class... Args>
225 shared_ptr<T> allocate_shared(const A& alloc, Args&&... args)
226 {
227 return shared_ptr<T>{
228 new aux::shared_payload<T>{A{alloc}, forward<Args>(args)...}
229 };
230 }
231
232 /**
233 * 20.8.2.2.7, shared_ptr comparisons:
234 */
235
236 template<class T, class U>
237 bool operator==(const shared_ptr<T>& lhs, const shared_ptr<U>& rhs) noexcept
238 {
239 return lhs.get() == rhs.get();
240 }
241
242 template<class T, class U>
243 bool operator!=(const shared_ptr<T>& lhs, const shared_ptr<U>& rhs) noexcept
244 {
245 return !(lhs == rhs);
246 }
247
248 template<class T, class U>
249 bool operator<(const shared_ptr<T>& lhs, const shared_ptr<U>& rhs) noexcept
250 {
251 return less<common_type_t<T*, U*>>{}(lhs.get(), rhs.get());
252 }
253
254 template<class T, class U>
255 bool operator>(const shared_ptr<T>& lhs, const shared_ptr<U>& rhs) noexcept
256 {
257 return rhs < lhs;
258 }
259
260 template<class T, class U>
261 bool operator<=(const shared_ptr<T>& lhs, const shared_ptr<U>& rhs) noexcept
262 {
263 return !(rhs < lhs);
264 }
265
266 template<class T, class U>
267 bool operator>=(const shared_ptr<T>& lhs, const shared_ptr<U>& rhs) noexcept
268 {
269 return !(lhs < rhs);
270 }
271
272 template<class T>
273 bool operator==(const shared_ptr<T>& lhs, nullptr_t) noexcept
274 {
275 return !lhs;
276 }
277
278 template<class T>
279 bool operator==(nullptr_t, const shared_ptr<T>& rhs) noexcept
280 {
281 return !rhs;
282 }
283
284 template<class T>
285 bool operator!=(const shared_ptr<T>& lhs, nullptr_t) noexcept
286 {
287 return (bool)lhs;
288 }
289
290 template<class T>
291 bool operator!=(nullptr_t, const shared_ptr<T>& rhs) noexcept
292 {
293 return (bool)rhs;
294 }
295
296 template<class T>
297 bool operator<(const shared_ptr<T>& lhs, nullptr_t) noexcept
298 {
299 return less<T*>{}(lhs.get(), nullptr);
300 }
301
302 template<class T>
303 bool operator<(nullptr_t, const shared_ptr<T>& rhs) noexcept
304 {
305 return less<T*>{}(nullptr, rhs.get());
306 }
307
308 template<class T>
309 bool operator>(const shared_ptr<T>& lhs, nullptr_t) noexcept
310 {
311 return nullptr < lhs;
312 }
313
314 template<class T>
315 bool operator>(nullptr_t, const shared_ptr<T>& rhs) noexcept
316 {
317 return rhs < nullptr;
318 }
319
320 template<class T>
321 bool operator<=(const shared_ptr<T>& lhs, nullptr_t) noexcept
322 {
323 return !(nullptr < lhs);
324 }
325
326 template<class T>
327 bool operator<=(nullptr_t, const shared_ptr<T>& rhs) noexcept
328 {
329 return !(rhs < nullptr);
330 }
331
332 template<class T>
333 bool operator>=(const shared_ptr<T>& lhs, nullptr_t) noexcept
334 {
335 return !(lhs < nullptr);
336 }
337
338 template<class T>
339 bool operator>=(nullptr_t, const shared_ptr<T>& rhs) noexcept
340 {
341 return !(nullptr < rhs);
342 }
343
344 /**
345 * 20.8.2.2.8, shared_ptr specialized algorithms:
346 */
347
348 template<class T>
349 void swap(shared_ptr<T>& lhs, shared_ptr<T>& rhs) noexcept
350 {
351 lhs.swap(rhs);
352 }
353
354 /**
355 * 20.8.2.2.9, shared_ptr casts:
356 */
357
358 template<class T, class U>
359 shared_ptr<T> static_pointer_cast(const shared_ptr<U>& ptr) noexcept
360 {
361 if (!ptr)
362 return shared_ptr<T>{};
363
364 return shared_ptr<T>{
365 ptr, static_cast<T*>(ptr.get())
366 };
367 }
368
369 template<class T, class U>
370 shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& ptr) noexcept
371 {
372 if (auto res = dynamic_cast<T*>(ptr.get()))
373 return shared_ptr<T>{ptr, res};
374 else
375 return shared_ptr<T>{};
376 }
377
378 template<class T, class U>
379 shared_ptr<T> const_pointer_cast(const shared_ptr<U>& ptr) noexcept
380 {
381 if (!ptr)
382 return shared_ptr<T>{};
383
384 return shared_ptr<T>{
385 ptr, const_cast<T*>(ptr.get())
386 };
387 }
388
389 /**
390 * 20.8.2.2.10, shared_ptr get_deleter:
391 */
392
393 template<class D, class T>
394 D* get_deleter(const shared_ptr<T>& ptr) noexcept
395 {
396 // TODO: implement this through payload
397 }
398
399 /**
400 * 20.8.2.2.11, shared_ptr I/O:
401 */
402
403 template<class Char, class Traits, class T>
404 basic_ostream<Char, Traits>& operator<<(basic_ostream<Char, Traits>& os,
405 const shared_ptr<T>& ptr)
406 {
407 return os << ptr.get();
408 }
409}
410
411#endif
Note: See TracBrowser for help on using the repository browser.