wxMaxima
Public Types | Public Member Functions | Static Public Member Functions | 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
 

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. Currently, this is the m_nextToDraw - it uses up 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.


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