1 #ifndef INTRUSIVE_PTR_H
2 #define INTRUSIVE_PTR_H
5 #include "opthelpers.h"
15 unsigned int add_ref() noexcept
{ return IncrementRef(mRef
); }
16 unsigned int release() noexcept
18 auto ref
= DecrementRef(mRef
);
20 delete static_cast<T
*>(this);
25 * Release only if doing so would not bring the object to 0 references and
26 * delete it. Returns false if the object could not be released.
28 * NOTE: The caller is responsible for handling a failed release, as it
29 * means the object has no other references and needs to be be deleted
32 bool releaseIfNoDelete() noexcept
34 auto val
= mRef
.load(std::memory_order_acquire
);
35 while(val
> 1 && !mRef
.compare_exchange_strong(val
, val
-1, std::memory_order_acq_rel
))
37 /* val was updated with the current value on failure, so just try
52 intrusive_ptr() noexcept
= default;
53 intrusive_ptr(const intrusive_ptr
&rhs
) noexcept
: mPtr
{rhs
.mPtr
}
54 { if(mPtr
) mPtr
->add_ref(); }
55 intrusive_ptr(intrusive_ptr
&& rhs
) noexcept
: mPtr
{rhs
.mPtr
}
56 { rhs
.mPtr
= nullptr; }
57 intrusive_ptr(std::nullptr_t
) noexcept
{ }
58 explicit intrusive_ptr(T
*ptr
) noexcept
: mPtr
{ptr
} { }
59 ~intrusive_ptr() { if(mPtr
) mPtr
->release(); }
61 intrusive_ptr
& operator=(const intrusive_ptr
&rhs
) noexcept
63 if(rhs
.mPtr
) rhs
.mPtr
->add_ref();
64 if(mPtr
) mPtr
->release();
68 intrusive_ptr
& operator=(intrusive_ptr
&& rhs
) noexcept
77 explicit operator bool() const noexcept
{ return mPtr
!= nullptr; }
79 T
& operator*() const noexcept
{ return *mPtr
; }
80 T
* operator->() const noexcept
{ return mPtr
; }
81 T
* get() const noexcept
{ return mPtr
; }
83 void reset(T
*ptr
=nullptr) noexcept
97 void swap(intrusive_ptr
&rhs
) noexcept
{ std::swap(mPtr
, rhs
.mPtr
); }
98 void swap(intrusive_ptr
&& rhs
) noexcept
{ std::swap(mPtr
, rhs
.mPtr
); }
101 #define AL_DECL_OP(op) \
102 template<typename T> \
103 inline bool operator op(const intrusive_ptr<T> &lhs, const T *rhs) noexcept \
104 { return lhs.get() op rhs; } \
105 template<typename T> \
106 inline bool operator op(const T *lhs, const intrusive_ptr<T> &rhs) noexcept \
107 { return lhs op rhs.get(); }
120 #endif /* INTRUSIVE_PTR_H */