wxMaxima
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Static Public Member Functions | Protected Member Functions | Static Protected Member Functions
CellPtr< T > Class Template Referencefinal

A weak non-owning pointer that becomes null whenever the observed object is destroyed. More...

#include <CellPtr.h>

Inheritance diagram for CellPtr< T >:
[legend]
Collaboration diagram for CellPtr< T >:
[legend]

Public Types

using value_type = T
 
using pointer = T *
 
using const_pointer = const T *
 
using reference = T &
 

Public Member Functions

pointer get () const noexcept
 
reference operator* () const noexcept
 
pointer operator-> () const noexcept
 
 operator pointer () const noexcept
 
template<typename PtrT , typename std::enable_if< std::is_pointer< PtrT >::value, bool >::type = true>
PtrT CastAs () const noexcept
 
 CellPtr (int)=delete
 
 CellPtr (void *)=delete
 
void reset () noexcept
 
 CellPtr (decltype(nullptr)) noexcept
 
CellPtroperator= (decltype(nullptr)) noexcept
 
bool operator== (decltype(nullptr)) const noexcept
 
bool operator!= (decltype(nullptr)) const noexcept
 
template<typename U , typename std::enable_if< is_pointer< U >(), bool >::type = true>
 CellPtr (U obj) noexcept
 
template<typename U , typename std::enable_if< is_pointer< U >(), bool >::type = true>
CellPtroperator= (U obj) noexcept
 
template<typename U , typename std::enable_if< is_pointer< U >(), bool >::type = true>
void reset (U obj) noexcept
 
 CellPtr (CellPtr &o) noexcept
 
 CellPtr (CellPtr &&o) noexcept
 
CellPtroperator= (const CellPtr &o) noexcept
 
CellPtroperator= (CellPtr &&o) noexcept
 
template<typename U , typename std::enable_if< std::is_convertible< typename std::add_pointer< U >::type, pointer >::value, bool >::type = true>
 CellPtr (CellPtr< U > &&o) noexcept
 
template<typename U , typename std::enable_if< std::is_convertible< typename std::add_pointer< U >::type, pointer >::value, bool >::type = true>
 CellPtr (const CellPtr< U > &o) noexcept
 
template<typename U , typename std::enable_if< std::is_convertible< typename std::add_pointer< U >::type, pointer >::value, bool >::type = true>
CellPtroperator= (CellPtr< U > &&o) noexcept
 
template<typename U , typename std::enable_if< std::is_convertible< typename std::add_pointer< U >::type, pointer >::value, bool >::type = true>
CellPtroperator= (const CellPtr< U > &o) noexcept
 
template<typename U , typename Del >
 CellPtr (std::unique_ptr< U, Del > &&)=delete
 
template<typename U , typename Del , typename std::enable_if< std::is_convertible< typename std::add_pointer< U >::type, pointer >::value, bool >::type = true>
 CellPtr (const std::unique_ptr< U, Del > &ptr) noexcept
 
template<typename U , typename Del >
CellPtroperator= (std::unique_ptr< U, Del > &&)=delete
 
template<typename U , typename Del , typename std::enable_if< std::is_convertible< typename std::add_pointer< U >::type, pointer >::value, bool >::type = true>
CellPtroperator= (const std::unique_ptr< U, Del > &o) noexcept
 
 operator bool () const noexcept
 
auto cmpPointers (const CellPtrBase &o) const noexcept
 This is exactly like the spaceship operator in C++20.
 
auto cmpObjects (const CellPtrBase &o) const noexcept
 This is the spaceship operator acting on pointed-to objects.
 
auto cmpObjects (const Observed *o) const noexcept
 This is the spaceship operator acting on pointed-to objects.
 
bool IsNull () const
 
bool HasOneObserved () const
 
bool HasControlBlock () const
 

Static Public Member Functions

static size_t GetLiveInstanceCount () noexcept
 

Protected Member Functions

Observedbase_get () const noexcept
 
void base_reset (Observed *obj=nullptr) noexcept
 

Static Protected Member Functions

static int CmpAddresses (const void *a, const void *b) noexcept
 A total order over two (possibly unrelated) addresses, usable with < 0 / == 0 / > 0. Compares them as unsigned integers rather than via pointer subtraction: see the GH #2208 comment on cmpObjects() below.
 

Detailed Description

template<typename T>
class CellPtr< T >

A weak non-owning pointer that becomes null whenever the observed object is destroyed.

The use of this pointer type has performance implications. It is not a "free" abstraction!

Warning: To maintain performance, most cells should have at most one CellPtr pointing at them. This is m_group - every Cell has one. (The draw list used to be a second CellPtr, m_nextToDraw, present on every cell; it's computed on the fly now instead - see CellIterators.h - so it no longer spends any of our "CellPtr budget".) The remaining CellPtrs are in CellPointers, and there is very few cells at any given time that are pointed-to by those pointers, and thus the performance impact is minimal.

In the common case of being null, or of being the only CellPtr to a given cell, the performance is similar to a raw pointer: it stores the cell pointer directly. The pointed-to cell points back to this sole pointer, so that it can reset it to null when it gets destroyed. A CellPtr is exactly the size of an Observed *.

When the second CellPtr is made to point to a cell, a shared control block is allocated on behalf of the cell, and both the CellPtr and the cell point to it. The control block is greedily dereferenced whenever the CellPtr notices that the cell it pointed to has vanished. But, once a cell has a ControlBlock, it doesn't get rid of it until no pointers point to it. So, if there are two+ pointers pointing to a cell, then only one is left, there still is a control block, and the pointers still "pointer chase" through that control block. Getting rid of the control block in this case is a low-priority TODO at the moment, since there's no performance impact seen from this.

The observed type must be derived from Observed, and this fact is checked at the point of instantiation. The pointer's instance can be declared with forward-defined classes.

Member Function Documentation

◆ base_reset()

void CellPtrBase::base_reset ( Observed obj = nullptr)
protectednoexceptinherited

Different objects must have control blocks that are either null or non-null but different.

◆ cmpObjects()

auto CellPtrBase::cmpObjects ( const CellPtrBase o) const
inlinenoexceptinherited

This is the spaceship operator acting on pointed-to objects.

GH #2208: this used to be a plain base_get() - o.base_get() pointer subtraction. That is undefined behavior for two pointers into unrelated objects, and in practice, on 32-bit architectures, it can silently produce the wrong sign: a signed ptrdiff_t subtraction of two addresses spread widely across the (much smaller) 32-bit address space can overflow and wrap around, which a 64-bit build's much sparser address space essentially never triggers. Comparing the two addresses as unsigned integers instead is well-defined on any architecture and gives the total order operator< (used via cmpObjects() < 0) actually needs.


The documentation for this class was generated from the following files: