46 template <
typename,
bool>
47 class reference_counted;
51 template <
typename,
bool>
55 iManagedPtr{ &aManagedPtr },
66 return iManagedPtr ==
nullptr;
78 if (--iWeakUseCount <= 0 &&
expired())
84 iManagedPtr =
nullptr;
89 i_reference_counted* iManagedPtr;
90 int32_t iWeakUseCount;
93 template <
typename Base,
bool DeallocateOnRelease = true>
96 typedef Base base_type;
98 using typename base_type::release_during_destruction;
99 using typename base_type::too_many_references;
101 reference_counted() noexcept : iDestroying{
false }, iReferenceCount{ 0 }, iPinned{
false }, iControlBlock{
nullptr }
110 bool expected =
true;
111 if (iControlled.compare_exchange_strong(expected,
false))
112 iControlBlock.load()->set_expired();
126 if (--iReferenceCount <= 0 && !iPinned)
131 throw release_during_destruction();
136 return iReferenceCount;
140 if (iReferenceCount != 1)
141 throw too_many_references();
147 return const_cast<base_type*
>(
to_const(*this).release_and_take_ownership());
149 void pin() const noexcept
override
156 if (iReferenceCount <= 0)
162 bool expected =
false;
163 if (iControlled.compare_exchange_strong(expected,
true))
165 return *iControlBlock;
170 if constexpr (DeallocateOnRelease)
173 (*this).~reference_counted();
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;
183 template <
typename Interface>
193 ref_ptr(Interface* aManagedPtr =
nullptr) noexcept :
194 iPtr{ aManagedPtr }, iManagedPtr{ aManagedPtr }, iReferenceCounted{ aManagedPtr !=
nullptr }
197 iManagedPtr->add_ref();
200 iPtr{ &aManagedPtr }, iManagedPtr{ &aManagedPtr }, iReferenceCounted{ aManagedPtr.use_count() > 0 }
202 if (iReferenceCounted)
203 iManagedPtr->add_ref();
206 iPtr{ aOther.ptr() }, iManagedPtr{ aOther.managed_ptr() }, iReferenceCounted{ aOther.reference_counted() }
208 if (iManagedPtr && iReferenceCounted)
209 iManagedPtr->add_ref();
212 iPtr{ aOther.ptr() }, iManagedPtr { aOther.managed_ptr() }, iReferenceCounted{ aOther.reference_counted() }
217 iPtr{ aPtr }, iManagedPtr{ aOther.managed_ptr() }, iReferenceCounted{ aOther.reference_counted() }
219 if (iManagedPtr && iReferenceCounted)
220 iManagedPtr->add_ref();
223 iPtr{ aPtr }, iManagedPtr{ aOther.managed_ptr() }, iReferenceCounted{ aOther.reference_counted() }
228 iPtr{ aPtr }, iManagedPtr{ aOther.managed_ptr() }, iReferenceCounted{ aOther.reference_counted() }
230 if (iManagedPtr && iReferenceCounted)
231 iManagedPtr->add_ref();
234 iPtr{
static_cast<Interface*
>(aOther.ptr()) }, iManagedPtr{
static_cast<Interface*
>(aOther.managed_ptr()) }, iReferenceCounted{ aOther.reference_counted() }
236 if (iManagedPtr && iReferenceCounted)
237 iManagedPtr->add_ref();
240 iPtr{ nullptr }, iManagedPtr { nullptr }, iReferenceCounted{ true }
245 template <
typename Interface2,
typename = std::enable_if_t<std::is_base_of_v<Interface, Interface2>, sfinae>>
247 iPtr{
static_cast<Interface*
>(aOther.ptr()) }, iManagedPtr{
static_cast<Interface*
>(aOther.managed_ptr()) }, iReferenceCounted{ aOther.reference_counted() }
249 if (iManagedPtr && iReferenceCounted)
250 iManagedPtr->add_ref();
252 template <
typename Interface2,
typename = std::enable_if_t<std::is_base_of_v<Interface, Interface2>, sfinae>>
254 iPtr{
static_cast<Interface*
>(aOther.ptr()) }, iManagedPtr {
static_cast<Interface*
>(aOther.managed_ptr()) }, iReferenceCounted{ aOther.reference_counted() }
258 template <
typename Interface2,
typename = std::enable_if_t<std::is_base_of_v<Interface, Interface2>, sfinae>>
260 iPtr{
static_cast<Interface*
>(aOther.ptr()) }, iManagedPtr{
static_cast<Interface*
>(aOther.managed_ptr()) }, iReferenceCounted{ aOther.reference_counted() }
262 if (iManagedPtr && iReferenceCounted)
263 iManagedPtr->add_ref();
265 template <
typename Interface2>
267 iPtr{ aPtr }, iManagedPtr{
static_cast<Interface*
>(aOther.managed_ptr()) }, iReferenceCounted{ aOther.reference_counted() }
269 if (iManagedPtr && iReferenceCounted)
270 iManagedPtr->add_ref();
272 template <
typename Interface2>
274 iPtr{ aPtr }, iManagedPtr{
static_cast<Interface*
>(aOther.managed_ptr()) }, iReferenceCounted{ aOther.reference_counted() }
278 template <
typename Interface2>
280 iPtr{ aPtr }, iManagedPtr{
static_cast<Interface*
>(aOther.managed_ptr()) }, iReferenceCounted{ aOther.reference_counted() }
282 if (iManagedPtr && iReferenceCounted)
283 iManagedPtr->add_ref();
287 if (iManagedPtr && iReferenceCounted)
289 auto releasingObject = iManagedPtr;
290 iManagedPtr =
nullptr;
291 releasingObject->release();
305 reset(aOther.ptr(), aOther.managed_ptr(), aOther.reference_counted(),
false);
316 template <
typename Interface2,
typename = std::enable_if_t<std::is_base_of_v<Interface, Interface2>, sfinae>>
322 template <
typename Interface2,
typename = std::enable_if_t<std::is_base_of_v<Interface, Interface2>, sfinae>>
325 reset(aOther.ptr(), aOther.managed_ptr(), aOther.reference_counted(),
false);
329 template <
typename Interface2,
typename = std::enable_if_t<std::is_base_of_v<Interface, Interface2>, sfinae>>
341 template <
typename Interface2>
349 return iReferenceCounted;
353 if (iManagedPtr && iReferenceCounted)
354 return iManagedPtr->use_count();
359 reset<Interface>(
nullptr,
nullptr,
false,
false);
363 reset<abstract_t<Interface>>(aPtr, aPtr, aPtr !=
nullptr,
true);
367 reset<abstract_t<Interface>>(aPtr, aManagedPtr, aManagedPtr !=
nullptr,
true);
371 reset<abstract_t<Interface>>(aPtr, aManagedPtr, aReferenceCounted, aAddRef);
375 if (iManagedPtr ==
nullptr)
377 Interface* releasedObject =
dynamic_cast<Interface*
>(iManagedPtr->release_and_take_ownership());
379 iManagedPtr =
nullptr;
380 iReferenceCounted =
false;
381 return releasedObject;
385 auto detached = iManagedPtr;
387 iManagedPtr =
nullptr;
388 iReferenceCounted =
false;
391 bool valid() const noexcept
override
393 return iPtr !=
nullptr;
397 return iManagedPtr !=
nullptr;
399 Interface*
ptr() const noexcept
override
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)
423 if (iPtr == aPtr && iManagedPtr == aManagedPtr)
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();
433 if (iManagedPtr && iReferenceCounted)
435 auto releasingObject = iManagedPtr;
436 iManagedPtr =
nullptr;
437 releasingObject->release();
439 iPtr = compatiblePtr;
440 iManagedPtr = compatibleManagedPtr;
441 iReferenceCounted = aReferenceCounted;
442 if (iManagedPtr && iReferenceCounted && aAddRef)
443 iManagedPtr->add_ref();
447 Interface* iManagedPtr;
448 bool iReferenceCounted;
451 template <
typename Interface>
463 iControlBlock{
nullptr }
465 update_control_block(aManagedPtr);
468 iControlBlock{
nullptr }
470 update_control_block(&aManagedPtr);
473 iControlBlock{
nullptr }
475 update_control_block(aOther.ptr());
478 iControlBlock{
nullptr }
480 update_control_block(aOther.managed_ptr());
483 iControlBlock{ nullptr }
490 if (iControlBlock !=
nullptr)
500 reset(aOther.managed_ptr());
520 update_control_block(
nullptr);
525 update_control_block(aPtr);
530 update_control_block(aManagedPtr);
535 update_control_block(aManagedPtr);
547 update_control_block(
nullptr);
550 bool valid() const noexcept
override
552 return ptr() !=
nullptr;
560 return iControlBlock ==
nullptr || iControlBlock->
expired();
562 Interface*
ptr() const noexcept
override
564 return static_cast<Interface*
>(iControlBlock !=
nullptr ? iControlBlock->
ptr() :
nullptr);
585 auto controlBlock = aManagedPtr !=
nullptr ? &(*aManagedPtr).control_block() :
nullptr;
586 if (iControlBlock != controlBlock)
588 if (iControlBlock !=
nullptr)
590 iControlBlock = controlBlock;
591 if (iControlBlock !=
nullptr)
596 i_ref_control_block* iControlBlock;
599 template <
typename Interface>
604 else if (lhs ==
nullptr)
606 else if (rhs ==
nullptr)
612 template <
typename ConcreteType,
typename... Args>
618 template <
class T,
class U>
625 template <
class T,
class U>
632 template <
class T,
class U>
639 template <
class T,
class U>
646 template <
class T,
class U>
653 template <
class T,
class U>
660 template <
class T,
class U>
669 template <
class T,
class U>
678 template <
class T,
class U>
685 template <
class T,
class U>
692 template <
class T,
class U>
699 template <
class T,
class U>
706 template <
class T,
class U>
713 template <
class T,
class U>
720 template <
class T,
class U>
729 template <
class T,
class U>
bool discover(i_ref_ptr< Interface > &aObject)
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
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 &)
reference_counted() noexcept
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
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)
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