- Notifications
You must be signed in to change notification settings - Fork4
Proposal for std::intrusive_ptr
License
NotificationsYou must be signed in to change notification settings
lhmouse/intrusive_ptr
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
#include<memory>namespacestd {template<typename T,typename D = default_delete<T>>classintrusive_base;template<typename T>classintrusive_ptr;template<typename T>classintrusive_weak_ptr;template<typename T,classD>classintrusive_base {public:constexprintrusive_base()noexcept;constexprintrusive_base(const intrusive_base & rhs)noexcept; intrusive_base &operator=(const intrusive_base & rhs)noexcept;~intrusive_base();public:const deleter_type &get_deleter()constnoexcept; deleter_type &get_deleter()noexcept;boolunique()const volatilenoexcept;longuse_count()const volatilenoexcept;longweak_count()constnoexcept;voidreserve_weak()const volatile;template<typename U = T> intrusive_ptr<constvolatile U>shared_from_this()const volatilenoexcept;template<typename U = T> intrusive_ptr<const U>shared_from_this()constnoexcept;template<typename U = T> intrusive_ptr<volatile U>shared_from_this() volatilenoexcept;template<typename U = T> intrusive_ptr<U>shared_from_this()noexcept;template<typename U = T> intrusive_weak_ptr<constvolatile U>weak_from_this()const volatile;template<typename U = T> intrusive_weak_ptr<const U>weak_from_this()const;template<typename U = T> intrusive_weak_ptr<volatile U>weak_from_this() volatile;template<typename U = T> intrusive_weak_ptr<U>weak_from_this();};template<typename T>classintrusive_ptr {public:using pointer = T *;using element_type = T;using deleter_type =/* see below*/;constexprintrusive_ptr(nullptr_t =nullptr)noexcept;explicitconstexprintrusive_ptr(element_type * rhs)noexcept;template<typename U,typename E>intrusive_ptr(unique_ptr<U, E> && rhs)noexcept;template<typename U>intrusive_ptr(const intrusive_ptr<U> & rhs)noexcept;template<typename U>intrusive_ptr(intrusive_ptr<U> && rhs)noexcept;intrusive_ptr(const intrusive_ptr & rhs)noexcept;intrusive_ptr(intrusive_ptr && rhs)noexcept; intrusive_ptr &operator=(const intrusive_ptr & rhs)noexcept; intrusive_ptr &operator=(intrusive_ptr && rhs)noexcept;~intrusive_ptr(); element_type *get()constnoexcept; element_type *release()noexcept;longuse_count()constnoexcept;longweak_count()constnoexcept;voidreset(nullptr_t =nullptr)noexcept;voidreset(element_type * rhs)noexcept;voidswap(intrusive_ptr & rhs)noexcept;explicitconstexproperatorbool()constnoexcept; element_type &operator*()const; element_type *operator->()const;};template<typename T1,typename T2>booloperator==(const intrusive_ptr<T1> & lhs,const intrusive_ptr<T2> & rhs)noexcept;template<typename T1,typename T2>booloperator==(const intrusive_ptr<T1> & lhs, T2 * rhs)noexcept;template<typename T1,typename T2>booloperator==(T1 * lhs,const intrusive_ptr<T2> & rhs)noexcept;template<typename T1,typename T2>booloperator!=(const intrusive_ptr<T1> & lhs,const intrusive_ptr<T2> & rhs)noexcept;template<typename T1,typename T2>booloperator!=(const intrusive_ptr<T1> & lhs, T2 * rhs)noexcept;template<typename T1,typename T2>booloperator!=(T1 * lhs,const intrusive_ptr<T2> & rhs)noexcept;template<typename T1,typename T2>booloperator< (const intrusive_ptr<T1> & lhs,const intrusive_ptr<T2> & rhs)noexcept;template<typename T1,typename T2>booloperator< (const intrusive_ptr<T1> & lhs, T2 * rhs)noexcept;template<typename T1,typename T2>booloperator< (T1 * lhs,const intrusive_ptr<T2> & rhs)noexcept;template<typename T1,typename T2>booloperator> (const intrusive_ptr<T1> & lhs,const intrusive_ptr<T2> & rhs)noexcept;template<typename T1,typename T2>booloperator> (const intrusive_ptr<T1> & lhs, T2 * rhs)noexcept;template<typename T1,typename T2>booloperator> (T1 * lhs,const intrusive_ptr<T2> & rhs)noexcept;template<typename T1,typename T2>booloperator<=(const intrusive_ptr<T1> & lhs,const intrusive_ptr<T2> & rhs)noexcept;template<typename T1,typename T2>booloperator<=(const intrusive_ptr<T1> & lhs, T2 * rhs)noexcept;template<typename T1,typename T2>booloperator<=(T1 * lhs,const intrusive_ptr<T2> & rhs)noexcept;template<typename T1,typename T2>booloperator>=(const intrusive_ptr<T1> & lhs,const intrusive_ptr<T2> & rhs)noexcept;template<typename T1,typename T2>booloperator>=(const intrusive_ptr<T1> & lhs, T2 * rhs)noexcept;template<typename T1,typename T2>booloperator>=(T1 * lhs,const intrusive_ptr<T2> & rhs)noexcept;template<typename T>voidswap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs)noexcept;template<typename T,typename ... Args> intrusive_ptr<T>make_intrusive(Args &&... args);template<typename U,typename T> intrusive_ptr<U>static_pointer_cast(intrusive_ptr<T> src)noexcept;template<typename U,typename T> intrusive_ptr<U>dynamic_pointer_cast(intrusive_ptr<T> src)noexcept;template<typename U,typename T> intrusive_ptr<U>const_pointer_cast(intrusive_ptr<T> src)noexcept;template<typename T>classintrusive_weak_ptr {public:using pointer =typename intrusive_ptr<T>::pointer;using element_type =typename intrusive_ptr<T>::element_type;using deleter_type =typename intrusive_ptr<T>::deleter_type;constexprintrusive_weak_ptr(nullptr_t =nullptr)noexcept;explicitintrusive_weak_ptr(element_type * rhs);intrusive_weak_ptr(const intrusive_ptr<T> & rhs);template<typename U>intrusive_weak_ptr(const intrusive_weak_ptr<U> & rhs)noexcept;template<typename U>intrusive_weak_ptr(intrusive_weak_ptr<U> && rhs)noexcept;intrusive_weak_ptr(const intrusive_weak_ptr & rhs)noexcept;intrusive_weak_ptr(intrusive_weak_ptr && rhs)noexcept; intrusive_weak_ptr &operator=(const intrusive_weak_ptr & rhs)noexcept; intrusive_weak_ptr &operator=(intrusive_weak_ptr && rhs)noexcept;~intrusive_weak_ptr();boolexpired()constnoexcept;longweak_count()constnoexcept;template<typename U = T> intrusive_ptr<U>lock()constnoexcept;voidreset(nullptr_t =nullptr)noexcept;voidreset(element_type * rhs);voidswap(intrusive_weak_ptr & rhs)noexcept;};template<typename T>booloperator==(const intrusive_weak_ptr<T> & lhs,const intrusive_weak_ptr<T> & rhs)constnoexcept;template<typename T>booloperator!=(const intrusive_weak_ptr<T> & lhs,const intrusive_weak_ptr<T> & rhs)constnoexcept;template<typename T>booloperator< (const intrusive_weak_ptr<T> & lhs,const intrusive_weak_ptr<T> & rhs)constnoexcept;template<typename T>booloperator> (const intrusive_weak_ptr<T> & lhs,const intrusive_weak_ptr<T> & rhs)constnoexcept;template<typename T>booloperator<=(const intrusive_weak_ptr<T> & lhs,const intrusive_weak_ptr<T> & rhs)constnoexcept;template<typename T>booloperator>=(const intrusive_weak_ptr<T> & lhs,const intrusive_weak_ptr<T> & rhs)constnoexcept;template<typename T>voidswap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs)noexcept;}
T
andD
shall be complete types.intrusive_base<T, D>
shall be a public, non-ambiguous base ofT
.D
shall satisfy the requirements ofDefaultConstructible. None of the default constructor, the copy/move constructor, the copy/move assignment operator ofD
shall throw exceptions.
- Post-condition:
use_count() == 1
.
- Effects:
intrusive_base()
.
- Effects: No operation.
- Returns:
*this
.
- Effects: If
use_count() > 1
callsterminate()
.
- Returns: A reference to the stored deleter.
- Returns:
use_count() == 1
.
- Returns: The reference count of this object.
- Returns: The weak reference count of this object.
- Effects: Satisifies any allocation requests for resources that would be required if an
intrusive_weak_ptr
was to be constructed. Construction ofintrusive_weak_ptr
referring this object shall not throw any exceptions hereafter. - Throws:
bad_alloc
, or an implementation-defined exception when a resource other than memory could not be obtained.
template<typename U = T> intrusive_ptr<const volatile U> shared_from_this() const volatile noexcept;
- Effects: Let
pu
be the result of conversion fromthis
to typecv U *
. Ifpu
is not null, increments the reference count ofpu
. - Returns:
intrusive_ptr<cv U>(pu)
. - Post-condition: If
pu
is not null,use_count()
is one greater than the value before the call.
- Returns:
intrusive_weak_ptr<cv U>(shared_from_this())
, as ifshared_from_this()
had never returned a null pointer. - Throws: Any exceptions that might be thrown by
reserve_weak()
. - Post-condition:
weak_count()
is one greater than the value before the call.
T
shall be a complete type.- Let
intrusive_base<T, D>
be a public, non-ambiguous base ofT
.deleter_type
is the template parameterD
. If no such base can be found, the program is ill-formed.
- Post-condition:
get() == nullptr
anduse_count() == 0
andweak_count() == 0
.
- Effects: If
rhs
is not null, increments the reference count of*rhs
. - Post-condition:
get() == rhs
. Ifrhs
is not null,rhs->use_count()
is one greater than the value before the call.
- Remarks: This constructor shall not participate in overload resolution unless
U *
is implicitly convertible toT *
andE
is implicitly convertible toD
. - Effects:
intrusive_ptr(rhs.release())
.
- Remarks: This constructor shall not participate in overload resolution unless
U *
is implicitly convertible toT *
. - Effects: If
rhs
is not null, increments the reference count of*rhs
. - Post-condition:
get() == rhs.get()
anduse_count() == rhs.use_count()
. Ifrhs.use_count()
is greater than zero before the call,use_count()
is one greater than that value.
- Remarks: This constructor shall not participate in overload resolution unless
U *
is implicitly convertible toT *
. - Post-condition:
get()
equals the value ofrhs.get()
before the call andrhs.get() == nullptr
.use_count()
equals the value ofrhs.use_count()
before the call andrhs.use_count() == 0
.
- Effects:
intrusive_ptr(rhs.get())
- Effects:
intrusive_ptr(rhs.release())
- Effects:
intrusive_ptr(rhs).swap(*this)
.
- Effects:
reset()
followed byrhs.swap(*this)
.
Effects: If
get()
is not null, decrements the reference count of*get()
, and if the result is zero, deletes the object as follows:using base = intrusive_base<T, D>;auto d = move(get()->base::get_deleter());move(d)(get());
- Returns: The stored pointer.
- Effects: Sets the stored pointer to
nullptr
without deleting any objects. - Returns: The value of
get()
before the call. - Post-condition:
get() == nullptr
.
- Returns: If
get()
is null,0
. Otherwise,get()->intrusive_base<T, D>::use_count()
.
- Returns: If
get()
is null,0
. Otherwise,get()->intrusive_base<T, D>::weak_count()
.
- Effects:
intrusive_ptr().swap(*this)
.
- Effects:
intrusive_ptr(rhs).swap(*this)
.
- Post-condition:
get()
equals the value ofrhs.get()
before the call andrhs.get()
equals the value ofget()
before the call.use_count()
equals the value ofrhs.use_count()
before the call andrhs.use_count()
equals the value ofuse_count()
before the call.
- Returns:
get() != nullptr
.
- Pre-condition:
get()
shall not be null. - Returns:
*get()
.
- Pre-condition:
get()
shall not be null. - Returns:
get()
.
template<typename T1, typename T2> bool operator==(const intrusive_ptr<T1> & lhs, const intrusive_ptr<T2> & rhs) noexcept;
template<typename T1, typename T2> bool operator==(const intrusive_ptr<T1> & lhs, T2 * rhs) noexcept;
template<typename T1, typename T2> bool operator==(T1 * lhs, const intrusive_ptr<T2> & rhs) noexcept;
- Returns:
lhs.get() == rhs.get()
,lhs.get() == rhs
andlhs == rhs.get()
, respectively.
template<typename T1, typename T2> bool operator!=(const intrusive_ptr<T1> & lhs, const intrusive_ptr<T2> & rhs) noexcept;
template<typename T1, typename T2> bool operator!=(const intrusive_ptr<T1> & lhs, T2 * rhs) noexcept;
template<typename T1, typename T2> bool operator!=(T1 * lhs, const intrusive_ptr<T2> & rhs) noexcept;
- Returns:
lhs.get() != rhs.get()
,lhs.get() != rhs
andlhs != rhs.get()
, respectively.
template<typename T1, typename T2> bool operator<(const intrusive_ptr<T1> & lhs, const intrusive_ptr<T2> & rhs) noexcept;
template<typename T1, typename T2> bool operator<(const intrusive_ptr<T1> & lhs, T2 * rhs) noexcept;
template<typename T1, typename T2> bool operator<(T1 * lhs, const intrusive_ptr<T2> & rhs) noexcept;
- Returns:
lhs.get() < rhs.get()
,lhs.get() < rhs
andlhs < rhs.get()
, respectively.
template<typename T1, typename T2> bool operator>(const intrusive_ptr<T1> & lhs, const intrusive_ptr<T2> & rhs) noexcept;
template<typename T1, typename T2> bool operator>(const intrusive_ptr<T1> & lhs, T2 * rhs) noexcept;
template<typename T1, typename T2> bool operator>(T1 * lhs, const intrusive_ptr<T2> & rhs) noexcept;
- Returns:
lhs.get() > rhs.get()
,lhs.get() > rhs
andlhs > rhs.get()
, respectively.
template<typename T1, typename T2> bool operator<=(const intrusive_ptr<T1> & lhs, const intrusive_ptr<T2> & rhs) noexcept;
template<typename T1, typename T2> bool operator<=(const intrusive_ptr<T1> & lhs, T2 * rhs) noexcept;
template<typename T1, typename T2> bool operator<=(T1 * lhs, const intrusive_ptr<T2> & rhs) noexcept;
- Returns:
lhs.get() <= rhs.get()
,lhs.get() <= rhs
andlhs <= rhs.get()
, respectively.
template<typename T1, typename T2> bool operator>=(const intrusive_ptr<T1> & lhs, const intrusive_ptr<T2> & rhs) noexcept;
template<typename T1, typename T2> bool operator>=(const intrusive_ptr<T1> & lhs, T2 * rhs) noexcept;
template<typename T1, typename T2> bool operator>=(T1 * lhs, const intrusive_ptr<T2> & rhs) noexcept;
- Returns:
lhs.get() >= rhs.get()
,lhs.get() >= rhs
andlhs >= rhs.get()
, respectively.
- Effects:
lhs.swap(rhs)
.
- Returns:
intrusive_ptr<T>(new T(forward<Args>(args)...))
.
template<typename U, typename T> intrusive_ptr<U> static_pointer_cast(intrusive_ptr<T> src) noexcept;
- Effects: Let
u
be the result ofstatic_cast<U *>(src.get())
. Callssrc.release()
. - Returns:
intrusive_ptr<U>(u)
.
template<typename U, typename T> intrusive_ptr<U> dynamic_pointer_cast(intrusive_ptr<T> src) noexcept;
- Effects: Let
u
be the result ofdynamic_cast<U *>(src.get())
. Ifu
is not null, callssrc.release()
. - Returns:
intrusive_ptr<U>(u)
.
template<typename U, typename T> intrusive_ptr<U> const_pointer_cast(intrusive_ptr<T> src) noexcept;
- Effects: Let
u
be the result ofconst_cast<U *>(src.get())
. Callssrc.release()
. - Returns:
intrusive_ptr<U>(u)
.
T
shall be a complete type.- Let
intrusive_base<T, D>
be a public, non-ambiguous base ofT
.deleter_type
is the template parameterD
. If no such base can be found, the program is ill-formed.
- Post-condition:
expired()
andweak_count() == 0
.
- Effects: If
rhs
is not null, increments the weak reference count of*rhs
. - Throws: Any exceptions that might be thrown by
rhs->reserve_weak()
. - Post-condition:
lock().get() == rhs
. Ifrhs
is not null,rhs->weak_count()
is one greater than the value before the call.
- Effects:
intrusive_weak_ptr(rhs.get())
.
- Remarks: This constructor shall not participate in overload resolution unless
U *
is implicitly convertible toT *
. - Effects: If
rhs.weak_count()
is greater than zero, increments the weak reference count of the object refered byrhs
, as if it had never expired. - Post-condition:
weak_count() == rhs.weak_count()
. Ifrhs.weak_count()
is greater than zero before the call,weak_count()
is one greater than that value.
- Remarks: This constructor shall not participate in overload resolution unless
U *
is implicitly convertible toT *
. - Post-condition:
weak_count()
equals the value ofrhs.weak_count()
before the call andrhs.weak_count() == 0
.
- Effects:
intrusive_weak_ptr(rhs.lock().get())
, as if the object referred byrhs
had never expired, if any.
- Effects:
intrusive_weak_ptr(rhs.lock().get())
thenrhs.reset()
, as if the object referred byrhs
had never expired, if any.
- Effects:
intrusive_weak_ptr(rhs).swap(*this)
.
- Effects:
reset()
followed byrhs.swap(*this)
.
- Effects: Let
pt
be a pointer to the object that*this
is referring as if that object had never expired, or a null pointer if no such object exists. Ifpt
is not null, decrements the weak reference count of*pt
.
- Effects: Let
pt
be a pointer to the object that*this
is referring as if that object had never expired, or a null pointer if no such object exists. - Returns: If
pt
is null,true
. Otherwise,pt->use_count() > 0
.
- Effects: Let
pt
be a pointer to the object that*this
is referring as if that object had never expired, or a null pointer if no such object exists. - Returns: If
pt
is null,0
. Otherwise,pt->weak_count()
.
- Effects: Atomically executes: Let
pt
be a pointer to the object that*this
is referring as if that object had never expired, or a null pointer if no such object exists. Letpu
be the result of conversion frompu
to typeU *
. Ifpu
is not null, increments the reference count ofpu
. - Returns:
intrusive_ptr<U>(pu)
. - Post-condition: If
pu
is not null,use_count()
is one greater thanpt->intrusive_base<T, D>::use_count()
before the call.
- Effects:
intrusive_weak_ptr().swap(*this)
.
- Effects:
intrusive_weak_ptr(rhs).swap(*this)
.
- Post-condition:
lock()
equals the value ofrhs.lock()
before the call andrhs.lock()
equals the value oflock()
before the call.weak_count()
equals the value ofrhs.weak_count()
before the call andrhs.weak_count()
equals the value ofweak_count()
before the call.
template<typename T> bool operator==(const intrusive_weak_ptr<T> & lhs, const intrusive_weak_ptr<T> & rhs) const noexcept;
template<typename T> bool operator!=(const intrusive_weak_ptr<T> & lhs, const intrusive_weak_ptr<T> & rhs) const noexcept;
template<typename T> bool operator< (const intrusive_weak_ptr<T> & lhs, const intrusive_weak_ptr<T> & rhs) const noexcept;
template<typename T> bool operator> (const intrusive_weak_ptr<T> & lhs, const intrusive_weak_ptr<T> & rhs) const noexcept;
template<typename T> bool operator<=(const intrusive_weak_ptr<T> & lhs, const intrusive_weak_ptr<T> & rhs) const noexcept;
template<typename T> bool operator>=(const intrusive_weak_ptr<T> & lhs, const intrusive_weak_ptr<T> & rhs) const noexcept;
- Remarks: These functions define an otherwise unspecified strick weak ordering of
intrusive_weak_ptr
, enabling use ofintrusive_weak_ptr
in associative containers.
- Effects:
lhs.swap(rhs)
.