neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
reference_counted.hpp
Go to the documentation of this file.
1// reference_counted.hpp
2/*
3 * Copyright (c) 2007 Leigh Johnston.
4 *
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * * Neither the name of Leigh Johnston nor the names of any
19 * other contributors to this software may be used to endorse or
20 * promote products derived from this software without specific prior
21 * written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
24 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
25 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*/
35
36#pragma once
37
38#include <neolib/neolib.hpp>
39#include <atomic>
40#include <vector>
41#include <functional>
43
44namespace neolib
45{
46 template <typename, bool>
47 class reference_counted;
48
50 {
51 template <typename, bool>
52 friend class reference_counted;
53 public:
55 iManagedPtr{ &aManagedPtr },
56 iWeakUseCount{ 0 }
57 {
58 }
59 public:
60 i_reference_counted* ptr() const noexcept override
61 {
62 return iManagedPtr;
63 }
64 bool expired() const noexcept override
65 {
66 return iManagedPtr == nullptr;
67 }
68 int32_t weak_use_count() const noexcept override
69 {
70 return iWeakUseCount;
71 }
72 void add_ref() noexcept override
73 {
74 ++iWeakUseCount;
75 }
76 void release() override
77 {
78 if (--iWeakUseCount <= 0 && expired())
79 delete this;
80 }
81 private:
82 void set_expired()
83 {
84 iManagedPtr = nullptr;
85 if (weak_use_count() <= 0)
86 delete this;
87 }
88 private:
89 i_reference_counted* iManagedPtr;
90 int32_t iWeakUseCount;
91 };
92
93 template <typename Base, bool DeallocateOnRelease = true>
94 class reference_counted : public Base
95 {
96 typedef Base base_type;
97 public:
98 using typename base_type::release_during_destruction;
99 using typename base_type::too_many_references;
100 public:
101 reference_counted() noexcept : iDestroying{ false }, iReferenceCount{ 0 }, iPinned{ false }, iControlBlock{ nullptr }
102 {
103 }
104 reference_counted(const reference_counted& aOther) noexcept : iDestroying{ false }, iReferenceCount{ 0 }, iPinned{ aOther.iPinned.load() }, iControlBlock{ nullptr }
105 {
106 }
108 {
109 iDestroying = true;
110 bool expected = true;
111 if (iControlled.compare_exchange_strong(expected, false))
112 iControlBlock.load()->set_expired();
113 }
115 {
116 // do nothing
117 return *this;
118 }
119 public:
120 void add_ref() const noexcept override
121 {
122 ++iReferenceCount;
123 }
124 void release() const override
125 {
126 if (--iReferenceCount <= 0 && !iPinned)
127 {
128 if (!iDestroying)
129 destroy();
130 else
131 throw release_during_destruction();
132 }
133 }
134 int32_t use_count() const noexcept override
135 {
136 return iReferenceCount;
137 }
138 const base_type* release_and_take_ownership() const override
139 {
140 if (iReferenceCount != 1)
141 throw too_many_references();
142 iReferenceCount = 0;
143 return this;
144 }
145 base_type* release_and_take_ownership() override
146 {
147 return const_cast<base_type*>(to_const(*this).release_and_take_ownership());
148 }
149 void pin() const noexcept override
150 {
151 iPinned = true;
152 }
153 void unpin() const override
154 {
155 iPinned = false;
156 if (iReferenceCount <= 0)
157 destroy();
158 }
159 public:
161 {
162 bool expected = false;
163 if (iControlled.compare_exchange_strong(expected, true))
164 iControlBlock = new ref_control_block{ *this };
165 return *iControlBlock;
166 }
167 private:
168 void destroy() const
169 {
170 if constexpr (DeallocateOnRelease)
171 delete this;
172 else
173 (*this).~reference_counted();
174 }
175 private:
176 std::atomic<bool> iDestroying;
177 mutable std::atomic<int32_t> iReferenceCount;
178 mutable std::atomic<bool> iPinned;
179 mutable std::atomic<bool> iControlled;
180 mutable std::atomic<ref_control_block*> iControlBlock;
181 };
182
183 template <typename Interface>
184 class ref_ptr : public i_ref_ptr<abstract_t<Interface>>
185 {
186 public:
187 typedef Interface element_type;
189 typedef typename abstract_type::no_object no_object;
190 typedef typename abstract_type::no_managed_object no_managed_object;
191 typedef typename abstract_type::interface_not_found interface_not_found;
192 public:
193 ref_ptr(Interface* aManagedPtr = nullptr) noexcept :
194 iPtr{ aManagedPtr }, iManagedPtr{ aManagedPtr }, iReferenceCounted{ aManagedPtr != nullptr }
195 {
196 if (iManagedPtr)
197 iManagedPtr->add_ref();
198 }
199 ref_ptr(Interface& aManagedPtr) noexcept :
200 iPtr{ &aManagedPtr }, iManagedPtr{ &aManagedPtr }, iReferenceCounted{ aManagedPtr.use_count() > 0 }
201 {
202 if (iReferenceCounted)
203 iManagedPtr->add_ref();
204 }
205 ref_ptr(ref_ptr const& aOther) noexcept :
206 iPtr{ aOther.ptr() }, iManagedPtr{ aOther.managed_ptr() }, iReferenceCounted{ aOther.reference_counted() }
207 {
208 if (iManagedPtr && iReferenceCounted)
209 iManagedPtr->add_ref();
210 }
211 ref_ptr(ref_ptr&& aOther) noexcept :
212 iPtr{ aOther.ptr() }, iManagedPtr { aOther.managed_ptr() }, iReferenceCounted{ aOther.reference_counted() }
213 {
214 aOther.detach();
215 }
216 ref_ptr(ref_ptr const& aOther, Interface* aPtr) noexcept :
217 iPtr{ aPtr }, iManagedPtr{ aOther.managed_ptr() }, iReferenceCounted{ aOther.reference_counted() }
218 {
219 if (iManagedPtr && iReferenceCounted)
220 iManagedPtr->add_ref();
221 }
222 ref_ptr(ref_ptr&& aOther, Interface* aPtr) noexcept :
223 iPtr{ aPtr }, iManagedPtr{ aOther.managed_ptr() }, iReferenceCounted{ aOther.reference_counted() }
224 {
225 aOther.detach();
226 }
227 ref_ptr(abstract_type const& aOther, Interface* aPtr) noexcept :
228 iPtr{ aPtr }, iManagedPtr{ aOther.managed_ptr() }, iReferenceCounted{ aOther.reference_counted() }
229 {
230 if (iManagedPtr && iReferenceCounted)
231 iManagedPtr->add_ref();
232 }
233 ref_ptr(abstract_type const& aOther) noexcept :
234 iPtr{ static_cast<Interface*>(aOther.ptr()) }, iManagedPtr{ static_cast<Interface*>(aOther.managed_ptr()) }, iReferenceCounted{ aOther.reference_counted() }
235 {
236 if (iManagedPtr && iReferenceCounted)
237 iManagedPtr->add_ref();
238 }
239 ref_ptr(i_discoverable& aDiscoverable) :
240 iPtr{ nullptr }, iManagedPtr { nullptr }, iReferenceCounted{ true }
241 {
242 if (!aDiscoverable.discover(*this))
243 throw interface_not_found();
244 }
245 template <typename Interface2, typename = std::enable_if_t<std::is_base_of_v<Interface, Interface2>, sfinae>>
246 ref_ptr(ref_ptr<Interface2> const& aOther) noexcept :
247 iPtr{ static_cast<Interface*>(aOther.ptr()) }, iManagedPtr{ static_cast<Interface*>(aOther.managed_ptr()) }, iReferenceCounted{ aOther.reference_counted() }
248 {
249 if (iManagedPtr && iReferenceCounted)
250 iManagedPtr->add_ref();
251 }
252 template <typename Interface2, typename = std::enable_if_t<std::is_base_of_v<Interface, Interface2>, sfinae>>
253 ref_ptr(ref_ptr<Interface2>&& aOther) noexcept :
254 iPtr{ static_cast<Interface*>(aOther.ptr()) }, iManagedPtr { static_cast<Interface*>(aOther.managed_ptr()) }, iReferenceCounted{ aOther.reference_counted() }
255 {
256 aOther.detach();
257 }
258 template <typename Interface2, typename = std::enable_if_t<std::is_base_of_v<Interface, Interface2>, sfinae>>
259 ref_ptr(i_ref_ptr<Interface2> const& aOther) noexcept :
260 iPtr{ static_cast<Interface*>(aOther.ptr()) }, iManagedPtr{ static_cast<Interface*>(aOther.managed_ptr()) }, iReferenceCounted{ aOther.reference_counted() }
261 {
262 if (iManagedPtr && iReferenceCounted)
263 iManagedPtr->add_ref();
264 }
265 template <typename Interface2>
266 ref_ptr(ref_ptr<Interface2> const& aOther, Interface* aPtr) noexcept :
267 iPtr{ aPtr }, iManagedPtr{ static_cast<Interface*>(aOther.managed_ptr()) }, iReferenceCounted{ aOther.reference_counted() }
268 {
269 if (iManagedPtr && iReferenceCounted)
270 iManagedPtr->add_ref();
271 }
272 template <typename Interface2>
273 ref_ptr(ref_ptr<Interface2>&& aOther, Interface* aPtr) noexcept :
274 iPtr{ aPtr }, iManagedPtr{ static_cast<Interface*>(aOther.managed_ptr()) }, iReferenceCounted{ aOther.reference_counted() }
275 {
276 aOther.detach();
277 }
278 template <typename Interface2>
279 ref_ptr(i_ref_ptr<Interface2> const& aOther, Interface* aPtr) noexcept :
280 iPtr{ aPtr }, iManagedPtr{ static_cast<Interface*>(aOther.managed_ptr()) }, iReferenceCounted{ aOther.reference_counted() }
281 {
282 if (iManagedPtr && iReferenceCounted)
283 iManagedPtr->add_ref();
284 }
286 {
287 if (iManagedPtr && iReferenceCounted)
288 {
289 auto releasingObject = iManagedPtr;
290 iManagedPtr = nullptr;
291 releasingObject->release();
292 }
293 }
294 ref_ptr& operator=(ref_ptr const& aOther)
295 {
296 if (&aOther == this)
297 return *this;
298 reset(aOther.ptr(), aOther.managed_ptr(), aOther.reference_counted(), true);
299 return *this;
300 }
302 {
303 if (&aOther == this)
304 return *this;
305 reset(aOther.ptr(), aOther.managed_ptr(), aOther.reference_counted(), false);
306 aOther.detach();
307 return *this;
308 }
310 {
311 if (&aOther == this)
312 return *this;
313 reset(aOther.ptr(), aOther.managed_ptr(), aOther.reference_counted(), true);
314 return *this;
315 }
316 template <typename Interface2, typename = std::enable_if_t<std::is_base_of_v<Interface, Interface2>, sfinae>>
318 {
319 reset(aOther.ptr(), aOther.managed_ptr(), aOther.reference_counted(), true);
320 return *this;
321 }
322 template <typename Interface2, typename = std::enable_if_t<std::is_base_of_v<Interface, Interface2>, sfinae>>
324 {
325 reset(aOther.ptr(), aOther.managed_ptr(), aOther.reference_counted(), false);
326 aOther.detach();
327 return *this;
328 }
329 template <typename Interface2, typename = std::enable_if_t<std::is_base_of_v<Interface, Interface2>, sfinae>>
331 {
332 reset(aOther.ptr(), aOther.managed_ptr(), aOther.reference_counted(), true);
333 return *this;
334 }
335 ref_ptr& operator=(std::nullptr_t)
336 {
337 reset();
338 return *this;
339 }
340 public:
341 template <typename Interface2>
343 {
344 return ref_ptr<Interface2>{ *this };
345 }
346 public:
347 bool reference_counted() const noexcept override
348 {
349 return iReferenceCounted;
350 }
351 int32_t use_count() const noexcept override
352 {
353 if (iManagedPtr && iReferenceCounted)
354 return iManagedPtr->use_count();
355 return 0;
356 }
357 void reset() override
358 {
359 reset<Interface>(nullptr, nullptr, false, false);
360 }
361 void reset(abstract_t<Interface>* aPtr) override
362 {
363 reset<abstract_t<Interface>>(aPtr, aPtr, aPtr != nullptr, true);
364 }
365 void reset(abstract_t<Interface>* aPtr, abstract_t<Interface>* aManagedPtr) override
366 {
367 reset<abstract_t<Interface>>(aPtr, aManagedPtr, aManagedPtr != nullptr, true);
368 }
369 void reset(abstract_t<Interface>* aPtr, abstract_t<Interface>* aManagedPtr, bool aReferenceCounted, bool aAddRef) override
370 {
371 reset<abstract_t<Interface>>(aPtr, aManagedPtr, aReferenceCounted, aAddRef);
372 }
373 Interface* release() override
374 {
375 if (iManagedPtr == nullptr)
376 throw no_managed_object();
377 Interface* releasedObject = dynamic_cast<Interface*>(iManagedPtr->release_and_take_ownership());
378 iPtr = nullptr;
379 iManagedPtr = nullptr;
380 iReferenceCounted = false;
381 return releasedObject;
382 }
383 Interface* detach() noexcept override
384 {
385 auto detached = iManagedPtr;
386 iPtr = nullptr;
387 iManagedPtr = nullptr;
388 iReferenceCounted = false;
389 return detached;
390 }
391 bool valid() const noexcept override
392 {
393 return iPtr != nullptr;
394 }
395 bool managing() const noexcept override
396 {
397 return iManagedPtr != nullptr;
398 }
399 Interface* ptr() const noexcept override
400 {
401 return iPtr;
402 }
403 Interface* managed_ptr() const noexcept override
404 {
405 return iManagedPtr;
406 }
407 Interface* operator->() const override
408 {
409 if (iPtr == nullptr)
410 throw no_object();
411 return iPtr;
412 }
413 Interface& operator*() const override
414 {
415 if (iPtr == nullptr)
416 throw no_object();
417 return *iPtr;
418 }
419 public:
420 template <typename Interface2 = Interface, typename = std::enable_if_t<std::is_base_of_v<Interface2, Interface>, sfinae>>
421 void reset(Interface2* aPtr, Interface2* aManagedPtr, bool aReferenceCounted, bool aAddRef)
422 {
423 if (iPtr == aPtr && iManagedPtr == aManagedPtr)
424 return;
425 Interface* compatiblePtr = dynamic_cast<Interface*>(aPtr);
426 if (aPtr != nullptr && compatiblePtr == nullptr)
427 throw std::bad_cast();
428 Interface* compatibleManagedPtr = dynamic_cast<Interface*>(aManagedPtr);
429 if (aManagedPtr != nullptr && compatibleManagedPtr == nullptr)
430 throw std::bad_cast();
431 ref_ptr copy{ *this };
432 iPtr = nullptr;
433 if (iManagedPtr && iReferenceCounted)
434 {
435 auto releasingObject = iManagedPtr;
436 iManagedPtr = nullptr;
437 releasingObject->release();
438 }
439 iPtr = compatiblePtr;
440 iManagedPtr = compatibleManagedPtr;
441 iReferenceCounted = aReferenceCounted;
442 if (iManagedPtr && iReferenceCounted && aAddRef)
443 iManagedPtr->add_ref();
444 }
445 private:
446 Interface* iPtr;
447 Interface* iManagedPtr;
448 bool iReferenceCounted;
449 };
450
451 template <typename Interface>
452 class weak_ref_ptr : public i_weak_ref_ptr<abstract_t<Interface>>
453 {
455 public:
459 typedef typename base_type::bad_release bad_release;
460 typedef typename base_type::wrong_object wrong_object;
461 public:
462 weak_ref_ptr(Interface* aManagedPtr = nullptr) noexcept :
463 iControlBlock{ nullptr }
464 {
465 update_control_block(aManagedPtr);
466 }
467 weak_ref_ptr(Interface& aManagedPtr) noexcept :
468 iControlBlock{ nullptr }
469 {
470 update_control_block(&aManagedPtr);
471 }
472 weak_ref_ptr(const weak_ref_ptr& aOther) noexcept :
473 iControlBlock{ nullptr }
474 {
475 update_control_block(aOther.ptr());
476 }
478 iControlBlock{ nullptr }
479 {
480 update_control_block(aOther.managed_ptr());
481 }
482 weak_ref_ptr(i_discoverable& aDiscoverable) :
483 iControlBlock{ nullptr }
484 {
485 if (!aDiscoverable.discover(*this))
486 throw interface_not_found();
487 }
489 {
490 if (iControlBlock != nullptr)
491 iControlBlock->release();
492 }
494 {
495 reset(aOther.ptr());
496 return *this;
497 }
499 {
500 reset(aOther.managed_ptr());
501 return *this;
502 }
503 weak_ref_ptr& operator=(std::nullptr_t)
504 {
505 reset();
506 return *this;
507 }
508 public:
509 bool reference_counted() const noexcept override
510 {
511 return false;
512 }
513 int32_t use_count() const noexcept override
514 {
515 return 0;
516 }
517 void reset() override
518 {
519 weak_ref_ptr copy(*this);
520 update_control_block(nullptr);
521 }
522 void reset(abstract_t<Interface>* aPtr) override
523 {
524 weak_ref_ptr copy(*this);
525 update_control_block(aPtr);
526 }
528 {
529 weak_ref_ptr copy(*this);
530 update_control_block(aManagedPtr);
531 }
532 void reset(abstract_t<Interface>*, abstract_t<Interface>* aManagedPtr, bool, bool) override
533 {
534 weak_ref_ptr copy(*this);
535 update_control_block(aManagedPtr);
536 }
537 Interface* release() override
538 {
539 if (expired())
540 throw no_object();
541 else
542 throw bad_release();
543 }
544 Interface* detach() override
545 {
546 weak_ref_ptr copy(*this);
547 update_control_block(nullptr);
548 return copy.ptr();
549 }
550 bool valid() const noexcept override
551 {
552 return ptr() != nullptr;
553 }
554 bool managing() const noexcept override
555 {
556 return valid();
557 }
558 bool expired() const noexcept override
559 {
560 return iControlBlock == nullptr || iControlBlock->expired();
561 }
562 Interface* ptr() const noexcept override
563 {
564 return static_cast<Interface*>(iControlBlock != nullptr ? iControlBlock->ptr() : nullptr);
565 }
566 Interface* managed_ptr() const noexcept override
567 {
568 return ptr();
569 }
570 Interface* operator->() const override
571 {
572 if (expired())
573 throw no_object();
574 return ptr();
575 }
576 Interface& operator*() const override
577 {
578 if (expired())
579 throw no_object();
580 return *ptr();
581 }
582 private:
583 void update_control_block(abstract_t<Interface>* aManagedPtr)
584 {
585 auto controlBlock = aManagedPtr != nullptr ? &(*aManagedPtr).control_block() : nullptr;
586 if (iControlBlock != controlBlock)
587 {
588 if (iControlBlock != nullptr)
589 iControlBlock->release();
590 iControlBlock = controlBlock;
591 if (iControlBlock != nullptr)
592 iControlBlock->add_ref();
593 }
594 }
595 private:
596 i_ref_control_block* iControlBlock;
597 };
598
599 template <typename Interface>
600 inline bool operator<(ref_ptr<Interface> const& lhs, ref_ptr<Interface> const& rhs) noexcept
601 {
602 if (lhs == rhs)
603 return false;
604 else if (lhs == nullptr)
605 return false;
606 else if (rhs == nullptr)
607 return true;
608 else
609 return *lhs < *rhs;
610 }
611
612 template <typename ConcreteType, typename... Args>
613 inline ref_ptr<ConcreteType> make_ref(Args&&... args)
614 {
615 return ref_ptr<ConcreteType>{ new ConcreteType{ std::forward<Args>(args)... } };
616 }
617
618 template <class T, class U>
620 {
621 auto const ptr = static_cast<typename ref_ptr<T>::element_type*>(aOther.ptr());
622 return ref_ptr<T>{ aOther, ptr };
623 }
624
625 template <class T, class U>
627 {
628 auto const ptr = static_cast<typename ref_ptr<T>::element_type*>(aOther.ptr());
629 return ref_ptr<T>{ std::move(aOther), ptr };
630 }
631
632 template <class T, class U>
633 ref_ptr<T> const_pointer_cast(ref_ptr<U> const& aOther) noexcept
634 {
635 auto const ptr = const_cast<typename ref_ptr<T>::element_type*>(aOther.ptr());
636 return ref_ptr<T>{ aOther, ptr };
637 }
638
639 template <class T, class U>
641 {
642 auto const ptr = const_cast<typename ref_ptr<T>::element_type*>(aOther.ptr());
643 return ref_ptr<T>{ std::move(aOther), ptr };
644 }
645
646 template <class T, class U>
648 {
649 auto const ptr = reinterpret_cast<typename ref_ptr<T>::element_type*>(aOther.ptr());
650 return ref_ptr<T>{ aOther, ptr };
651 }
652
653 template <class T, class U>
655 {
656 auto const ptr = reinterpret_cast<typename ref_ptr<T>::element_type*>(aOther.ptr());
657 return ref_ptr<T>{ std::move(aOther), ptr };
658 }
659
660 template <class T, class U>
662 {
663 auto const ptr = dynamic_cast<typename ref_ptr<T>::element_type*>(aOther.ptr());
664 if (ptr)
665 return ref_ptr<T>{ aOther, ptr };
666 return ref_ptr<T>{};
667 }
668
669 template <class T, class U>
671 {
672 auto const ptr = dynamic_cast<typename ref_ptr<T>::element_type*>(aOther.ptr());
673 if (ptr)
674 return ref_ptr<T>{ std::move(aOther), ptr };
675 return ref_ptr<T>{};
676 }
677
678 template <class T, class U>
680 {
681 auto const ptr = static_cast<typename ref_ptr<T>::element_type*>(aOther.ptr());
682 return ref_ptr<T>{ aOther, ptr };
683 }
684
685 template <class T, class U>
687 {
688 auto const ptr = static_cast<typename ref_ptr<T>::element_type*>(aOther.ptr());
689 return ref_ptr<T>{ std::move(aOther), ptr };
690 }
691
692 template <class T, class U>
694 {
695 auto const ptr = const_cast<typename ref_ptr<T>::element_type*>(aOther.ptr());
696 return ref_ptr<T>{ aOther, ptr };
697 }
698
699 template <class T, class U>
701 {
702 auto const ptr = const_cast<typename ref_ptr<T>::element_type*>(aOther.ptr());
703 return ref_ptr<T>{ std::move(aOther), ptr };
704 }
705
706 template <class T, class U>
708 {
709 auto const ptr = reinterpret_cast<typename ref_ptr<T>::element_type*>(aOther.ptr());
710 return ref_ptr<T>{ aOther, ptr };
711 }
712
713 template <class T, class U>
715 {
716 auto const ptr = reinterpret_cast<typename ref_ptr<T>::element_type*>(aOther.ptr());
717 return ref_ptr<T>{ std::move(aOther), ptr };
718 }
719
720 template <class T, class U>
722 {
723 auto const ptr = dynamic_cast<typename ref_ptr<T>::element_type*>(aOther.ptr());
724 if (ptr)
725 return ref_ptr<T>{ aOther, ptr };
726 return ref_ptr<T>{};
727 }
728
729 template <class T, class U>
731 {
732 auto const ptr = dynamic_cast<typename ref_ptr<T>::element_type*>(aOther.ptr());
733 if (ptr)
734 return ref_ptr<T>{ std::move(aOther), ptr };
735 return ref_ptr<T>{};
736 }
737}
bool discover(i_ref_ptr< Interface > &aObject)
virtual void release()=0
virtual bool expired() const noexcept=0
virtual void add_ref() noexcept=0
virtual i_reference_counted * ptr() const noexcept=0
virtual bool reference_counted() const noexcept=0
virtual Interface * ptr() const noexcept=0
virtual Interface * managed_ptr() const noexcept=0
int32_t weak_use_count() const noexcept override
ref_control_block(i_reference_counted &aManagedPtr)
void add_ref() noexcept override
i_reference_counted * ptr() const noexcept override
bool expired() const noexcept override
Interface * managed_ptr() const noexcept override
ref_ptr(Interface &aManagedPtr) noexcept
abstract_type::interface_not_found interface_not_found
ref_ptr(ref_ptr< Interface2 > &&aOther) noexcept
ref_ptr(ref_ptr &&aOther) noexcept
void reset(abstract_t< Interface > *aPtr, abstract_t< Interface > *aManagedPtr) override
Interface * detach() noexcept override
ref_ptr(ref_ptr< Interface2 > const &aOther, Interface *aPtr) noexcept
ref_ptr(i_ref_ptr< Interface2 > const &aOther, Interface *aPtr) noexcept
ref_ptr(ref_ptr &&aOther, Interface *aPtr) noexcept
Interface * ptr() const noexcept override
ref_ptr(ref_ptr const &aOther, Interface *aPtr) noexcept
int32_t use_count() const noexcept override
void reset(Interface2 *aPtr, Interface2 *aManagedPtr, bool aReferenceCounted, bool aAddRef)
ref_ptr & operator=(ref_ptr const &aOther)
void reset(abstract_t< Interface > *aPtr) override
i_ref_ptr< abstract_t< Interface > > abstract_type
ref_ptr< Interface2 > as()
Interface * release() override
Interface & operator*() const override
ref_ptr & operator=(ref_ptr &&aOther)
bool managing() const noexcept override
ref_ptr & operator=(i_ref_ptr< Interface2 > const &aOther)
ref_ptr(ref_ptr const &aOther) noexcept
abstract_type::no_managed_object no_managed_object
ref_ptr(abstract_type const &aOther) noexcept
void reset() override
ref_ptr(i_discoverable &aDiscoverable)
ref_ptr(Interface *aManagedPtr=nullptr) noexcept
void reset(abstract_t< Interface > *aPtr, abstract_t< Interface > *aManagedPtr, bool aReferenceCounted, bool aAddRef) override
ref_ptr(i_ref_ptr< Interface2 > const &aOther) noexcept
bool valid() const noexcept override
ref_ptr & operator=(ref_ptr< Interface2 > &&aOther)
ref_ptr(ref_ptr< Interface2 > &&aOther, Interface *aPtr) noexcept
ref_ptr & operator=(abstract_type const &aOther)
Interface * operator->() const override
ref_ptr & operator=(std::nullptr_t)
ref_ptr(ref_ptr< Interface2 > const &aOther) noexcept
bool reference_counted() const noexcept override
ref_ptr(abstract_type const &aOther, Interface *aPtr) noexcept
abstract_type::no_object no_object
ref_ptr & operator=(ref_ptr< Interface2 > const &aOther)
reference_counted(const reference_counted &aOther) noexcept
const base_type * release_and_take_ownership() const override
base_type * release_and_take_ownership() override
reference_counted & operator=(const reference_counted &)
void pin() const noexcept override
void release() const override
void add_ref() const noexcept override
int32_t use_count() const noexcept override
i_ref_control_block & control_block() override
void unpin() const override
Interface * release() override
weak_ref_ptr(Interface *aManagedPtr=nullptr) noexcept
weak_ref_ptr(const i_ref_ptr< abstract_t< Interface > > &aOther) noexcept
int32_t use_count() const noexcept override
bool reference_counted() const noexcept override
Interface * detach() override
Interface & operator*() const override
bool valid() const noexcept override
base_type::interface_not_found interface_not_found
weak_ref_ptr(Interface &aManagedPtr) noexcept
weak_ref_ptr & operator=(weak_ref_ptr const &aOther)
base_type::no_object no_object
weak_ref_ptr & operator=(i_ref_ptr< abstract_t< Interface > > const &aOther)
base_type::bad_release bad_release
weak_ref_ptr(i_discoverable &aDiscoverable)
base_type::wrong_object wrong_object
bool expired() const noexcept override
Interface * operator->() const override
void reset(abstract_t< Interface > *, abstract_t< Interface > *aManagedPtr) override
weak_ref_ptr(const weak_ref_ptr &aOther) noexcept
Interface * ptr() const noexcept override
i_weak_ref_ptr< abstract_t< Interface > > abstract_type
weak_ref_ptr & operator=(std::nullptr_t)
bool managing() const noexcept override
Interface * managed_ptr() const noexcept override
void reset(abstract_t< Interface > *aPtr) override
void reset(abstract_t< Interface > *, abstract_t< Interface > *aManagedPtr, bool, bool) override
typename detail::abstract_type< T >::type abstract_t
Definition neolib.hpp:178
ref_ptr< T > dynamic_pointer_cast(ref_ptr< U > const &aOther) noexcept
ref_ptr< ConcreteType > make_ref(Args &&... args)
to_const_reference_t< T > to_const(T &&object)
Definition neolib.hpp:113
ref_ptr< T > const_pointer_cast(ref_ptr< U > const &aOther) noexcept
ref_ptr< T > static_pointer_cast(ref_ptr< U > const &aOther) noexcept
ref_ptr< T > reinterpret_pointer_cast(ref_ptr< U > const &aOther) noexcept