Giter Site home page Giter Site logo

intrusive_ptr's Introduction

Proposal for std::intrusive_ptr

Synopsis

#include <memory>

namespace std {

template<typename T, typename D = default_delete<T>>
class intrusive_base;

template<typename T>
class intrusive_ptr;
template<typename T>
class intrusive_weak_ptr;

template<typename T, class D>
class intrusive_base {
public:
    constexpr intrusive_base() noexcept;
    constexpr intrusive_base(const intrusive_base & rhs) noexcept;
    intrusive_base & operator=(const intrusive_base & rhs) noexcept;
    ~intrusive_base();

public:
    const deleter_type & get_deleter() const noexcept;
    deleter_type & get_deleter() noexcept;

    bool unique() const volatile noexcept;
    long use_count() const volatile noexcept;
    long weak_count() const noexcept;
    void reserve_weak() const volatile;

    template<typename U = T> intrusive_ptr<const volatile U> shared_from_this() const volatile noexcept;
    template<typename U = T> intrusive_ptr<const U> shared_from_this() const noexcept;
    template<typename U = T> intrusive_ptr<volatile U> shared_from_this() volatile noexcept;
    template<typename U = T> intrusive_ptr<U> shared_from_this() noexcept;

    template<typename U = T> intrusive_weak_ptr<const volatile 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>
class intrusive_ptr {
public:
    using pointer      = T *;
    using element_type = T;
    using deleter_type = /* see below */;

    constexpr intrusive_ptr(nullptr_t = nullptr) noexcept;
    explicit constexpr intrusive_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() const noexcept;
    element_type * release() noexcept;
    long use_count() const noexcept;
    long weak_count() const noexcept;

    void reset(nullptr_t = nullptr) noexcept;
    void reset(element_type * rhs) noexcept;

    void swap(intrusive_ptr & rhs) noexcept;

    explicit constexpr operator bool() const noexcept;

    element_type & operator*() const;
    element_type * operator->() const;
};

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;

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;

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;

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;

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;

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;

template<typename T> void swap(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>
class intrusive_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;

    constexpr intrusive_weak_ptr(nullptr_t = nullptr) noexcept;
    explicit intrusive_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();

    bool expired() const noexcept;
    long weak_count() const noexcept;
    template<typename U = T> intrusive_ptr<U> lock() const noexcept;

    void reset(nullptr_t = nullptr) noexcept;
    void reset(element_type * rhs);

    void swap(intrusive_weak_ptr & rhs) 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;
template<typename T> bool operator>=(const intrusive_weak_ptr<T> & lhs, const intrusive_weak_ptr<T> & rhs) const noexcept;

template<typename T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs) noexcept;

}

template<typename T, class D> class intrusive_base

In general
  • T and D shall be complete types.
  • intrusive_base<T, D> shall be a public, non-ambiguous base of T.
  • D shall satisfy the requirements of DefaultConstructible. None of the default constructor, the copy/move constructor, the copy/move assignment operator of D shall throw exceptions.
constexpr intrusive_base() noexcept;
  • Post-condition: use_count() == 1.
constexpr intrusive_base(const intrusive_base & rhs) noexcept;
  • Effects: intrusive_base().
intrusive_base & operator=(const intrusive_base & rhs) noexcept;
  • Effects: No operation.
  • Returns: *this.
~intrusive_base();
  • Effects: If use_count() > 1 calls terminate().
const deleter_type & get_deleter() const noexcept;
deleter_type & get_deleter() noexcept;
  • Returns: A reference to the stored deleter.
bool unique() const volatile noexcept;
  • Returns: use_count() == 1.
long use_count() const volatile noexcept;
  • Returns: The reference count of this object.
long weak_count() const volatile noexcept;
  • Returns: The weak reference count of this object.
void reserve_weak() const volatile;
  • Effects: Satisifies any allocation requests for resources that would be required if an intrusive_weak_ptr was to be constructed. Construction of intrusive_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;
template<typename U = T> intrusive_ptr<const U> shared_from_this() const noexcept;
template<typename U = T> intrusive_ptr<volatile U> shared_from_this() volatile noexcept;
template<typename U = T> intrusive_ptr<U> shared_from_this() noexcept;
  • Effects: Let pu be the result of conversion from this to type cv U *. If pu is not null, increments the reference count of pu.
  • Returns: intrusive_ptr<cv U>(pu).
  • Post-condition: If pu is not null, use_count() is one greater than the value before the call.
template<typename U = T> intrusive_weak_ptr<const volatile 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();
  • Returns: intrusive_weak_ptr<cv U>(shared_from_this()), as if shared_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.

template<typename T> class intrusive_ptr

In general
  • T shall be a complete type.
  • Let intrusive_base<T, D> be a public, non-ambiguous base of T. deleter_type is the template parameter D. If no such base can be found, the program is ill-formed.
constexpr intrusive_ptr(nullptr_t = nullptr) noexcept;
  • Post-condition: get() == nullptr and use_count() == 0 and weak_count() == 0.
explicit constexpr intrusive_ptr(element_type * rhs) noexcept;
  • Effects: If rhs is not null, increments the reference count of *rhs.
  • Post-condition: get() == rhs. If rhs is not null, rhs->use_count() is one greater than the value before the call.
template<typename U, typename E> intrusive_ptr(unique_ptr<U, E> && rhs) noexcept;
  • Remarks: This constructor shall not participate in overload resolution unless U * is implicitly convertible to T * and E is implicitly convertible to D.
  • Effects: intrusive_ptr(rhs.release()).
template<typename U> intrusive_ptr(const intrusive_ptr<U> & rhs) noexcept;
  • Remarks: This constructor shall not participate in overload resolution unless U * is implicitly convertible to T *.
  • Effects: If rhs is not null, increments the reference count of *rhs.
  • Post-condition: get() == rhs.get()and use_count() == rhs.use_count(). If rhs.use_count() is greater than zero before the call, use_count() is one greater than that value.
template<typename U> intrusive_ptr(intrusive_ptr<U> && rhs) noexcept;
  • Remarks: This constructor shall not participate in overload resolution unless U * is implicitly convertible to T *.
  • Post-condition: get() equals the value of rhs.get() before the call and rhs.get() == nullptr. use_count() equals the value of rhs.use_count() before the call and rhs.use_count() == 0.
intrusive_ptr(const intrusive_ptr & rhs) noexcept;
  • Effects: intrusive_ptr(rhs.get())
intrusive_ptr(intrusive_ptr && rhs) noexcept;
  • Effects: intrusive_ptr(rhs.release())
intrusive_ptr & operator=(const intrusive_ptr & rhs) noexcept;
  • Effects: intrusive_ptr(rhs).swap(*this).
intrusive_ptr & operator=(intrusive_ptr && rhs) noexcept;
  • Effects: reset() followed by rhs.swap(*this).
~intrusive_ptr();
  • 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());
element_type * get() const noexcept;
  • Returns: The stored pointer.
element_type * release() noexcept;
  • Effects: Sets the stored pointer to nullptr without deleting any objects.
  • Returns: The value of get() before the call.
  • Post-condition: get() == nullptr.
long use_count() const noexcept;
  • Returns: If get() is null, 0. Otherwise, get()->intrusive_base<T, D>::use_count().
long weak_count() const noexcept;
  • Returns: If get() is null, 0. Otherwise, get()->intrusive_base<T, D>::weak_count().
void reset(nullptr_t = nullptr) noexcept;
  • Effects: intrusive_ptr().swap(*this).
void reset(element_type * rhs) noexcept;
  • Effects: intrusive_ptr(rhs).swap(*this).
void swap(intrusive_ptr & rhs) noexcept;
  • Post-condition: get() equals the value of rhs.get() before the call and rhs.get() equals the value of get() before the call. use_count() equals the value of rhs.use_count() before the call and rhs.use_count() equals the value of use_count() before the call.
explicit constexpr operator bool() const noexcept;
  • Returns: get() != nullptr.
element_type & operator*() const;
  • Pre-condition: get() shall not be null.
  • Returns: *get().
element_type * operator->() const;
  • 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 and lhs == 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 and lhs != 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 and lhs < 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 and lhs > 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 and lhs <= 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 and lhs >= rhs.get(), respectively.
template<typename T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs) noexcept;
  • Effects: lhs.swap(rhs).
template<typename T, typename ... Args> intrusive_ptr<T> make_intrusive(Args &&... args);
  • 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 of static_cast<U *>(src.get()). Calls src.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 of dynamic_cast<U *>(src.get()). If u is not null, calls src.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 of const_cast<U *>(src.get()). Calls src.release().
  • Returns: intrusive_ptr<U>(u).

template<typename T> class intrusive_weak_ptr

In general
  • T shall be a complete type.
  • Let intrusive_base<T, D> be a public, non-ambiguous base of T. deleter_type is the template parameter D. If no such base can be found, the program is ill-formed.
constexpr intrusive_weak_ptr(nullptr_t = nullptr) noexcept;
  • Post-condition: expired() and weak_count() == 0.
explicit intrusive_weak_ptr(element_type * rhs);
  • 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. If rhs is not null, rhs->weak_count() is one greater than the value before the call.
intrusive_weak_ptr(const intrusive_ptr<T> & rhs);
  • Effects: intrusive_weak_ptr(rhs.get()).
template<typename U> intrusive_weak_ptr(const intrusive_weak_ptr<U> & rhs) noexcept;
  • Remarks: This constructor shall not participate in overload resolution unless U * is implicitly convertible to T *.
  • Effects: If rhs.weak_count() is greater than zero, increments the weak reference count of the object refered by rhs, as if it had never expired.
  • Post-condition: weak_count() == rhs.weak_count(). If rhs.weak_count() is greater than zero before the call, weak_count() is one greater than that value.
template<typename U> intrusive_weak_ptr(intrusive_weak_ptr<U> && rhs) noexcept;
  • Remarks: This constructor shall not participate in overload resolution unless U * is implicitly convertible to T *.
  • Post-condition: weak_count() equals the value of rhs.weak_count() before the call and rhs.weak_count() == 0.
intrusive_weak_ptr(const intrusive_weak_ptr & rhs) noexcept;
  • Effects: intrusive_weak_ptr(rhs.lock().get()), as if the object referred by rhs had never expired, if any.
intrusive_weak_ptr(intrusive_weak_ptr && rhs) noexcept;
  • Effects: intrusive_weak_ptr(rhs.lock().get()) then rhs.reset(), as if the object referred by rhs had never expired, if any.
intrusive_weak_ptr & operator=(const intrusive_weak_ptr & rhs) noexcept;
  • Effects: intrusive_weak_ptr(rhs).swap(*this).
intrusive_weak_ptr & operator=(intrusive_weak_ptr && rhs) noexcept;
  • Effects: reset() followed by rhs.swap(*this).
~intrusive_weak_ptr();
  • 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. If pt is not null, decrements the weak reference count of *pt.
bool expired() const noexcept;
  • 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.
long weak_count() const noexcept;
  • 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().
template<typename U = T> intrusive_ptr<U> lock() const noexcept;
  • 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. Let pu be the result of conversion from pu to type U *. If pu is not null, increments the reference count of pu.
  • Returns: intrusive_ptr<U>(pu).
  • Post-condition: If pu is not null, use_count() is one greater than pt->intrusive_base<T, D>::use_count() before the call.
void reset(nullptr_t = nullptr) noexcept;
  • Effects: intrusive_weak_ptr().swap(*this).
void reset(element_type * rhs);
  • Effects: intrusive_weak_ptr(rhs).swap(*this).
void swap(intrusive_weak_ptr & rhs) noexcept;
  • Post-condition: lock() equals the value of rhs.lock() before the call and rhs.lock() equals the value of lock() before the call. weak_count() equals the value of rhs.weak_count() before the call and rhs.weak_count() equals the value of weak_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 of intrusive_weak_ptr in associative containers.
template<typename T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs) noexcept;
  • Effects: lhs.swap(rhs).

intrusive_ptr's People

Contributors

lhmouse avatar lyp951018 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

intrusive_ptr's Issues

version without weak pointers

Hello,
i was digging for "intrusive_ptr" implementations in the web and i found very promising your library.
What is the memory cost of each of your intrusive ptrs?
Your implementation gives the same thread safety guarantees as smart_ptrs, right?

On my side, i would be interested in using intrusive_ptrs instead of smart_ptr to reduce memory occupation of my program (as well as ideally to improve efficiency). For this reason i was looking for a lightweight version, without weak counters (i would use raw pointers instead of weak ones)

what would it take to achieve that?

Can this support boost::intrusive_ptr like usage?

Get pointer from a intrusive_ptr to another intrusive_ptr like below, the reference count is not right

boost::intrusive_ptr<ProcessData> ptr(new ProcessData(1, "a"));
{
        // get from another intrusive_ptr
        boost::intrusive_ptr<ProcessData> ptrCopy(ptr.get());
}
    explicit constexpr intrusive_ptr(_T * __t) noexcept
            : __x_t(__t)
    {
        if (__x_t->_Impl_intrusive_ptr::_Ref_count_base::__get_ref() > 1)
        __x_t->_Impl_intrusive_ptr::_Ref_count_base::__add_ref();
    }

I __add_ref when old __x_t is not 1. Is this right?

possible problem with dynamic_pointer_cast

Hello,

could it be that the implementation of dynamic pointer_cast is wrong?

i believe it should be:

 template<typename _U, typename _T>
  intrusive_ptr<_U> my_dynamic_pointer_cast(intrusive_ptr<_T> __r) noexcept {
    const auto __u = dynamic_cast<_U*>(__r.get());
    if(__u){
      __r.release();
    }
    return intrusive_ptr<_U>(__u);
  }

with $dynamic_cast&lt;_U*&gt;$ as in the code i post instead of $dynamic_cast&lt;_U&gt;$ as in the repository

[WISH] non-atomic version, documentation of intrusive_weak_ptr

Hello,
it's a nice template you created but I have trouble understanding a few things.

a) the implementation basically requires atomic variables. However, there are usecases where one wants intrusive_ptr but not including atomic operations, for example because they pull in extra library dependencies on some embedded architectures or because they make the operation slower (memory barriers) although in the specific design the MT-safety might be not required.

Would it be possible to add an inline variant (controlled by traits or prepr. defines) that work without atomic variables?

b) I don't see the point of intrusive_weak_ptr. Maybe it's just missing documentation?

From my point of view, intrusive_weak_ptr does not make any sense. I mean, the basic idea of normal weak_ptr is to a) avoid ref-counted dependency and there allow the object to be deleted and b) giving the user of weak_ptr means to reliable detect whether object was deleted and atomically create a reliable shared_ptr from it.
I cannot see how your current implementation would satisfy such demands, i.e. the point of __lock is to enforce/guarantee... what exactly?

Relaxing constraints on complete types?

Right now the spec requires that T is a complete type, I feel like this is a tough requirement since neither shared_ptr nor unique_ptr have this requirement. Is there a way to work around the restrictions? The other pointer types have some specific places where completeness is required and other places where it's not. Maybe some detailed rules could be fleshed out here as well.

unit test coverage

First of all, thank you for writing this very neat proposal!

I thought I'd make a suggestion to include unit tests with more code coverage. That way it would be easier to check that everything in the implementation works for a given compiler environment.

Cheers!

-Wfree-nonheap-object when using intrusive objects on the stack

GCC warns of -Wfree-nonheap-object when stack-allocating objects that derive from intrusive_base. The compiler thinks it's weird that there are potentially calls to "delete" on a stack object. Not sure how this warning could be avoided so I personally recommend to silence it at this point if you're ok with being careful of your allocations.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.