Intrusive Smart Pointer#

#include <dplx/cncr/intrusive_ptr.hpp>
namespace dplx::cncr {}

Concepts#

template<typename RC>
concept ref_counted#

A type whose lifetime is managed by an internal reference counter and which has a reference_counted_traits specialization for controlling the reference counter.

All functions are required to be noexcept.

Notation

RC &obj#

An lvalue reference to a reference counted object.

Valid Expressions

template<typename RC>
concept inspectable_ref_counted#

Requires that a ref_counted type also provides a way to get an estimate of the current reference count. Not requiring the value to be excact allows reference counted objects shared across multiple threads to satisfy this.

The only value required to be stable is 1 in which case our thread should be the only pointee. (With the exception of insane software architectures which retain non owning across threads).

All functions are required to be noexcept.

Notation

RC &obj#

An lvalue reference to a reference counted object.

Valid Expressions

template<ref_counted RC>
concept detail::dplx_ref_counted#

Exposition Only

Describes the typical deeplex reference counting API.

All functions are required to be noexcept.

Notation

RC const &obj#

An lvalue reference to a reference counted object.

Valid Expressions

  • obj.add_reference() increments the reference counter.

  • obj.release() decrements the reference counter.

  • obj.reference_count() retrieves the current (approximate) reference count.

Customization Points#

template<typename RC>
class reference_counted_traits#

This is a customization point i.e. there is no primary template definition.

The implementation requirements are described by the ref_counted and inspectable_ref_counted concepts.

template<detail::dplx_ref_counted RC>
class reference_counted_traits<RC>#

The specialization of reference_counted_traits for types satisfying detail::dplx_ref_counted.

The specialization satisfies inspectable_ref_counted.

Factory Functions#

template<ref_counted RC>
constexpr auto intrusive_ptr_import(RC *obj) -> intrusive_ptr<RC>#

Creates a intrusive_ptr<RC> tracking obj assuming ownership of an existing reference (i.e. it doesn’t call add_reference())

It is a type deducing wrapper around intrusive_ptr<RC>::import.

template<ref_counted RC>
constexpr auto intrusive_ptr_acquire(RC *obj) -> intrusive_ptr<RC>#

Creates a intrusive_ptr<RC> tracking obj assuming ownership by acquiring a new reference (i.e. it calls add_reference()).

It is a type deducing wrapper around intrusive_ptr<RC>::acquire.

Types#

template<ref_counted RC>
class intrusive_ptr<RC, RC>#

The usual intrusive smart pointer which poses as a pointer to the object whose lifetime it manages.

The type satisfies std::regular, i.e. it is default initializable, copyable and equality comparable. It is also swappable, totally ordered and contextually convertible to bool.

Additionally the following members exist:

using element_type = RC#

Exposes the type parameter for meta programming purposes.

using handle_type = intrusive_ptr<RC>#

Exposes the type which is used for reference counting. It is exposed for compatibility with the aliasing variant intrusive_ptr<T, RC> whose element_type is not equal to RC.

constexpr intrusive_ptr(std::nullptr_t) noexcept#

Constructs an empty instance from a nullptr literal which makes the following expressions well formed:

intrusive_ptr<T> ptr{nullptr};
ptr = nullptr;
template<ref_counted U>
constexpr intrusive_ptr(intrusive_ptr<U> &&other) noexcept#

Imports ownership from a compatible intrusive_ptr<U> instance.

This constructor is only available if std::convertible_to<U*, RC*> holds.

template<ref_counted U>
constexpr intrusive_ptr(intrusive_ptr<U> const &other) noexcept#

Aquires ownership from a compatible intrusive_ptr<U> instance.

This constructor is only available if std::convertible_to<U*, RC*> holds.

static constexpr auto import(RC *ptr) noexcept -> intrusive_ptr<RC>#

Creates a intrusive_ptr<RC> tracking ptr assuming ownership of an existing reference (i.e. it doesn’t call add_reference()).

static constexpr auto acquire(RC *ptr) noexcept -> intrusive_ptr<RC>#

Creates a intrusive_ptr<RC> tracking ptr assuming ownership by acquiring a new reference (i.e. it calls add_reference()).

constexpr auto get() const noexcept -> RC*#

Retrieves the stored object pointer.

constexpr auto get_handle() const noexcept -> intrusive_ptr<RC>#

Returns a copy of this. It is exposed for compatibility with the aliasing variant intrusive_ptr<T, RC> whose element_type is not equal to RC.

constexpr auto use_count() const noexcept -> reference_counted_traits<RC>::counter_type#
constexpr auto reference_count() const noexcept -> reference_counted_traits<RC>::counter_type#

If RC satisfies inspectable_ref_counted it returns the (approximate) number of references. The only value guaranteed to be stable in multi-threaded environments is 1.

The use_count() name exists for API compatibility with std::shared_ptr.

constexpr auto release() noexcept -> RC*#

Returns the bound object after unbinding this without decrementing the reference counter.

constexpr void reset(RC *toBeBound) noexcept#

Replaces the managed object with toBeBound and increases its ref count.

template<>
class intrusive_ptr<void, void>#

A type erased intrusive pointer. It keeps a pointer to a vtable in addition to a void * referencing the bound object.

The type satisfies std::regular, i.e. it is default initializable, copyable and equality comparable. It is also swappable, totally ordered and contextually convertible to bool.

You can either (copy) assign normal intrusive pointer instances or use the static class functions import or acquire

Additionally the following members exist:

using element_type = void#

Exposes the type parameter for meta programming purposes.

using handle_type = intrusive_ptr<void, void>#

Exposes the type which is used for reference counting. It is exposed for compatibility with the aliasing variant intrusive_ptr<T, RC> whose element_type is not equal to void.

intrusive_ptr(std::nullptr_t) noexcept#

Constructs an empty instance from a nullptr literal which makes the following expressions well formed:

intrusive_ptr<void> ptr{nullptr};
ptr = nullptr;
template<ref_counted U>
intrusive_ptr(intrusive_ptr<U> &&other) noexcept#

Imports ownership from an intrusive_ptr<U> instance.

template<ref_counted U>
intrusive_ptr(intrusive_ptr<U> const &other) noexcept#

Aquires ownership from an intrusive_ptr<U> instance.

template<ref_counted RC>
static auto import(RC *ptr) noexcept -> intrusive_ptr<void, void>#

Creates a intrusive_ptr<void, void> tracking ptr assuming ownership of an existing reference (i.e. it doesn’t call add_reference()).

template<ref_counted RC>
static auto acquire(RC *ptr) noexcept -> intrusive_ptr<void, void>#

Creates a intrusive_ptr<void, void> tracking ptr assuming ownership by acquiring a new reference (i.e. it calls add_reference()).

auto get() const noexcept -> void*#

Retrieves the stored object pointer.

auto get_handle() const noexcept -> intrusive_ptr<void>#

Returns a copy of this. It is exposed for compatibility with the aliasing variant intrusive_ptr<T, RC> whose element_type is not equal to void.

template<ref_counted U>
auto release_as() noexcept -> U*#

Returns the bound object pointer after casting it to U after unbinding this without decrementing the reference counter.

template<typename T, ref_counted RC = T>
class intrusive_ptr#

The main template is an aliasing intrusive pointer which means it poses as a pointer to an object of type T while managing the reference count of (a potentially different) object of type RC.

The type satisfies std::regular, i.e. it is default initializable, copyable and equality comparable. It is also swappable, totally ordered and contextually convertible to bool.

Additionally the following members exist:

using element_type = T#

Exposes the type parameter for meta programming purposes.

using handle_type = intrusive_ptr<RC>#

Exposes the intrusive pointer type which implements reference counting.

constexpr intrusive_ptr(std::nullptr_t) noexcept#

Constructs an empty instance from a nullptr literal which makes the following expressions well formed:

intrusive_ptr<T, RC> ptr{nullptr};
ptr = nullptr;
constexpr intrusive_ptr(intrusive_ptr<RC> &&handle, T *ptr) noexcept#

Creates a intrusive_ptr<T, RC> tracking handle assuming ownership of an existing reference (i.e. it doesn’t call add_reference()).

The constructed intrusive pointer poses as ptr afterwards.

constexpr intrusive_ptr(intrusive_ptr<RC> const &handle, T *ptr) noexcept#

Creates a intrusive_ptr<T, RC> tracking handle assuming ownership by acquiring a new reference (i.e. it calls add_reference()).

The constructed intrusive pointer poses as ptr afterwards.

constexpr auto get() const noexcept -> T*#

Retrieves the stored aliased object pointer.

constexpr auto get_handle() const noexcept -> intrusive_ptr<RC>#

Returns a copy of the contained object handle.

constexpr auto use_count() const noexcept -> reference_counted_traits<RC>::counter_type#
constexpr auto reference_count() const noexcept -> reference_counted_traits<RC>::counter_type#

If RC satisfies inspectable_ref_counted it returns the (approximate) number of references. The only value guaranteed to be stable in multi-threaded environments is 1.

The use_count() name exists for API compatibility with std::shared_ptr.