xrpld
Loading...
Searching...
No Matches
xrpl::IntrusiveRefCounts Struct Reference

Implement the strong count, weak count, and bit flags for an intrusive pointer. More...

#include <IntrusiveRefCounts.h>

Inheritance diagram for xrpl::IntrusiveRefCounts:
Collaboration diagram for xrpl::IntrusiveRefCounts:

Classes

struct  RefCountPair
 Unpack the count and tag fields from the packed atomic integer form. More...

Public Member Functions

virtual ~IntrusiveRefCounts () noexcept
void addStrongRef () const noexcept
void addWeakRef () const noexcept
ReleaseStrongRefAction releaseStrongRef () const
ReleaseStrongRefAction addWeakReleaseStrongRef () const
ReleaseWeakRefAction releaseWeakRef () const
bool checkoutStrongRefFromWeak () const noexcept
bool expired () const noexcept
std::size_t useCount () const noexcept

Private Types

using CountType = std::uint16_t
using FieldType = std::uint32_t

Private Attributes

std::atomic< FieldTyperefCounts_ {kStrongDelta}
 refCounts consists of four fields that are treated atomically:

Static Private Attributes

static constexpr size_t kStrongCountNumBits = sizeof(CountType) * 8
static constexpr size_t kWeakCountNumBits = kStrongCountNumBits - 2
static constexpr size_t kFieldTypeBits = sizeof(FieldType) * 8
static constexpr FieldType kOne = 1
static constexpr FieldType kStrongDelta = 1
 Amount to change the strong count when adding or releasing a reference.
static constexpr FieldType kWeakDelta = (kOne << kStrongCountNumBits)
 Amount to change the weak count when adding or releasing a reference.
static constexpr FieldType kPartialDestroyStartedMask = (kOne << (kFieldTypeBits - 1))
 Flag that is set when the partialDestroy function has started running (or is about to start running).
static constexpr FieldType kPartialDestroyFinishedMask = (kOne << (kFieldTypeBits - 2))
 Flag that is set when the partialDestroy function has finished running.
static constexpr FieldType kTagMask = kPartialDestroyStartedMask | kPartialDestroyFinishedMask
 Mask that will zero out all the count bits and leave the tag bits unchanged.
static constexpr FieldType kValueMask = ~kTagMask
 Mask that will zero out the tag bits and leave the count bits unchanged.
static constexpr FieldType kStrongMask = ((kOne << kStrongCountNumBits) - 1) & kValueMask
 Mask that will zero out everything except the strong count.
static constexpr FieldType kWeakMask
 Mask that will zero out everything except the weak count.

Friends

template<class T>
void partialDestructorFinished (T **o)

Detailed Description

Implement the strong count, weak count, and bit flags for an intrusive pointer.

A class can satisfy the requirements of an xrpl::IntrusivePointer by inheriting from this class.

Definition at line 39 of file IntrusiveRefCounts.h.

Member Typedef Documentation

◆ CountType

Definition at line 100 of file IntrusiveRefCounts.h.

◆ FieldType

Definition at line 103 of file IntrusiveRefCounts.h.

Constructor & Destructor Documentation

◆ ~IntrusiveRefCounts()

xrpl::IntrusiveRefCounts::~IntrusiveRefCounts ( )
virtualnoexcept

Definition at line 397 of file IntrusiveRefCounts.h.

Member Function Documentation

◆ addStrongRef()

void xrpl::IntrusiveRefCounts::addStrongRef ( ) const
noexcept

Definition at line 227 of file IntrusiveRefCounts.h.

◆ addWeakRef()

void xrpl::IntrusiveRefCounts::addWeakRef ( ) const
noexcept

Definition at line 233 of file IntrusiveRefCounts.h.

◆ releaseStrongRef()

ReleaseStrongRefAction xrpl::IntrusiveRefCounts::releaseStrongRef ( ) const

Definition at line 239 of file IntrusiveRefCounts.h.

◆ addWeakReleaseStrongRef()

ReleaseStrongRefAction xrpl::IntrusiveRefCounts::addWeakReleaseStrongRef ( ) const

Definition at line 287 of file IntrusiveRefCounts.h.

◆ releaseWeakRef()

ReleaseWeakRefAction xrpl::IntrusiveRefCounts::releaseWeakRef ( ) const

Definition at line 340 of file IntrusiveRefCounts.h.

◆ checkoutStrongRefFromWeak()

bool xrpl::IntrusiveRefCounts::checkoutStrongRefFromWeak ( ) const
noexcept

Definition at line 367 of file IntrusiveRefCounts.h.

◆ expired()

bool xrpl::IntrusiveRefCounts::expired ( ) const
noexcept

Definition at line 384 of file IntrusiveRefCounts.h.

◆ useCount()

std::size_t xrpl::IntrusiveRefCounts::useCount ( ) const
noexcept

Definition at line 391 of file IntrusiveRefCounts.h.

◆ partialDestructorFinished

template<class T>
void partialDestructorFinished ( T ** o)
friend

Definition at line 448 of file IntrusiveRefCounts.h.

Member Data Documentation

◆ kStrongCountNumBits

size_t xrpl::IntrusiveRefCounts::kStrongCountNumBits = sizeof(CountType) * 8
staticconstexprprivate

Definition at line 101 of file IntrusiveRefCounts.h.

◆ kWeakCountNumBits

size_t xrpl::IntrusiveRefCounts::kWeakCountNumBits = kStrongCountNumBits - 2
staticconstexprprivate

Definition at line 102 of file IntrusiveRefCounts.h.

◆ kFieldTypeBits

size_t xrpl::IntrusiveRefCounts::kFieldTypeBits = sizeof(FieldType) * 8
staticconstexprprivate

Definition at line 104 of file IntrusiveRefCounts.h.

◆ kOne

FieldType xrpl::IntrusiveRefCounts::kOne = 1
staticconstexprprivate

Definition at line 105 of file IntrusiveRefCounts.h.

◆ refCounts_

std::atomic<FieldType> xrpl::IntrusiveRefCounts::refCounts_ {kStrongDelta}
mutableprivate

refCounts consists of four fields that are treated atomically:

  1. Strong count. This is a count of the number of shared pointers that hold a reference to this object. When the strong counts goes to zero, if the weak count is zero, the destructor is run. If the weak count is non-zero when the strong count goes to zero then the partialDestructor is run.
  2. Weak count. This is a count of the number of weak pointer that hold a reference to this object. When the weak count goes to zero and the strong count is also zero, then the destructor is run.
  3. Partial destroy started bit. This bit is set if the partialDestructor function has been started (or is about to be started). This is used to prevent the destructor from running concurrently with the partial destructor. This can easily happen when the last strong pointer release its reference in one thread and starts the partialDestructor, while in another thread the last weak pointer goes out of scope and starts the destructor while the partialDestructor is still running. Both a start and finished bit is needed to handle a corner-case where the last strong pointer goes out of scope, then then last weakPointer goes out of scope, but this happens before the partialDestructor bit is set. It would be possible to use a single bit if it could also be set atomically when the strong count goes to zero and the weak count is non-zero, but that would add complexity (and likely slow down common cases as well).
  4. Partial destroy finished bit. This bit is set when the partialDestructor has finished running. See (3) above for more information.

Definition at line 140 of file IntrusiveRefCounts.h.

◆ kStrongDelta

FieldType xrpl::IntrusiveRefCounts::kStrongDelta = 1
staticconstexprprivate

Amount to change the strong count when adding or releasing a reference.

Note: The strong count is stored in the low StrongCountNumBits bits of refCounts

Definition at line 147 of file IntrusiveRefCounts.h.

◆ kWeakDelta

FieldType xrpl::IntrusiveRefCounts::kWeakDelta = (kOne << kStrongCountNumBits)
staticconstexprprivate

Amount to change the weak count when adding or releasing a reference.

Note: The weak count is stored in the high WeakCountNumBits bits of refCounts

Definition at line 154 of file IntrusiveRefCounts.h.

◆ kPartialDestroyStartedMask

FieldType xrpl::IntrusiveRefCounts::kPartialDestroyStartedMask = (kOne << (kFieldTypeBits - 1))
staticconstexprprivate

Flag that is set when the partialDestroy function has started running (or is about to start running).

See description of the refCounts field for a fuller description of this field.

Definition at line 162 of file IntrusiveRefCounts.h.

◆ kPartialDestroyFinishedMask

FieldType xrpl::IntrusiveRefCounts::kPartialDestroyFinishedMask = (kOne << (kFieldTypeBits - 2))
staticconstexprprivate

Flag that is set when the partialDestroy function has finished running.

See description of the refCounts field for a fuller description of this field.

Definition at line 169 of file IntrusiveRefCounts.h.

◆ kTagMask

FieldType xrpl::IntrusiveRefCounts::kTagMask = kPartialDestroyStartedMask | kPartialDestroyFinishedMask
staticconstexprprivate

Mask that will zero out all the count bits and leave the tag bits unchanged.

Definition at line 174 of file IntrusiveRefCounts.h.

◆ kValueMask

FieldType xrpl::IntrusiveRefCounts::kValueMask = ~kTagMask
staticconstexprprivate

Mask that will zero out the tag bits and leave the count bits unchanged.

Definition at line 179 of file IntrusiveRefCounts.h.

◆ kStrongMask

FieldType xrpl::IntrusiveRefCounts::kStrongMask = ((kOne << kStrongCountNumBits) - 1) & kValueMask
staticconstexprprivate

Mask that will zero out everything except the strong count.

Definition at line 183 of file IntrusiveRefCounts.h.

◆ kWeakMask

FieldType xrpl::IntrusiveRefCounts::kWeakMask
staticconstexprprivate
Initial value:
=
static constexpr size_t kWeakCountNumBits
static constexpr FieldType kValueMask
Mask that will zero out the tag bits and leave the count bits unchanged.
static constexpr FieldType kOne
static constexpr size_t kStrongCountNumBits

Mask that will zero out everything except the weak count.

Definition at line 187 of file IntrusiveRefCounts.h.