Reference documentation for deal.II version GIT c1ddcf411d 2023-11-30 16:30:02+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Public Member Functions | Private Attributes | List of all members
SmartPointer< T, P > Class Template Reference

#include <deal.II/base/smartpointer.h>

Public Member Functions

 SmartPointer ()
 
template<class Q >
 SmartPointer (const SmartPointer< T, Q > &tt)
 
 SmartPointer (const SmartPointer< T, P > &tt)
 
 SmartPointer (T *t, const std::string &id)
 
 SmartPointer (T *t)
 
 ~SmartPointer ()
 
SmartPointer< T, P > & operator= (T *tt)
 
template<class Q >
SmartPointer< T, P > & operator= (const SmartPointer< T, Q > &tt)
 
SmartPointer< T, P > & operator= (const SmartPointer< T, P > &tt)
 
void clear ()
 
 operator T* () const
 
T & operator* () const
 
T * get () const
 
T * operator-> () const
 
template<class Q >
void swap (SmartPointer< T, Q > &tt)
 
void swap (T *&tt)
 
std::size_t memory_consumption () const
 

Private Attributes

T * t
 
const std::string id
 
std::atomic< boolpointed_to_object_is_alive
 

Detailed Description

template<typename T, typename P = void>
class SmartPointer< T, P >

The SmartPointer class avoids using dangling pointers. They can be used just like a pointer (i.e., using the * and -> operators and through casting) but make sure that the object pointed to is not deleted or moved from in the course of use of the pointer by signaling the pointee its use.

Conceptually, SmartPointer fills a gap between std::unique_ptr and std::shared_ptr. While the former makes it clear that there is a unique owner of an object (namely the scope in which the std::unique_ptr resides), it does not allow other places in a code base to point to the object. In contrast, std::shared_ptr allows many places to point to the same object, but none of them is the "owner" of the object: They all are, and the last one to stop pointing to the object is responsible for deleting it.

SmartPointer utilizes semantics in which one place owns an object and others can point to it. The owning place is responsible for destroying the object when it is no longer needed, and this will trigger an error if other places are still pointing to it via SmartPointer pointers. In other words, one should consider those places that hold a SmartPointer to an object as "observers", and an object may only be destroyed without an error if there are no observers left. With hindsight, perhaps a better name for the class would have been "ObserverPointer".

To make this scheme work, SmartPointers need to increment the "observer count" when they point to an observed object. This is facilitated by requiring that the objects pointed to, i.e., the template type T, must inherit from the Subscriptor class.

In practice, using this scheme, if you try to destroy an object to which observers still point via SmartPointer objects, you will get an error that says that there are still observers of the object and that the object can consequently not be destroyed without creating "dangling" pointers. This is often not very helpful in finding where these pointers are. As a consequence, this class also provides two ways to annotate the observer count with information about what other places still observe an object. First, when initializing a SmartPointer object with the address of the object pointed to, you can also attach a string that describes the observing location, and this string will then be shown in error messages listing all remaining observers. Second, if no such string is provided, the name second template argument P is used as the debug string. This allows to encode the observer information in the type of the SmartPointer.

Note
Unlike std::unique_ptr and std::shared_ptr, SmartPointer does NOT implement any memory handling. In particular, deleting a SmartPointer does not delete the object because the semantics of this class are that it only observes an object, but does not take over ownership. As a consequence, this is a sure way of creating a memory leak:
SmartPointer<T> dont_do_this = new T;
static const char T
This is because here, no variable "owns" the object pointed to, and the destruction of the dont_do_this pointer does not trigger the release of the memory pointed to.
This class correctly handles const-ness of an object, i.e., a SmartPointer<const T> really behaves as if it were a pointer to a constant object (disallowing write access when dereferenced), while SmartPointer<T> is a mutable pointer.

Definition at line 93 of file smartpointer.h.

Constructor & Destructor Documentation

◆ SmartPointer() [1/5]

template<typename T , typename P >
SmartPointer< T, P >::SmartPointer
inline

Standard constructor for null pointer. The id of this pointer is set to the name of the class P.

Definition at line 251 of file smartpointer.h.

◆ SmartPointer() [2/5]

template<typename T , typename P >
template<class Q >
SmartPointer< T, P >::SmartPointer ( const SmartPointer< T, Q > &  tt)
inline

Copy constructor for SmartPointer. We do not copy the object subscribed to from tt, but subscribe ourselves to it again.

Definition at line 285 of file smartpointer.h.

◆ SmartPointer() [3/5]

template<typename T , typename P >
SmartPointer< T, P >::SmartPointer ( const SmartPointer< T, P > &  tt)
inline

Copy constructor for SmartPointer. We do not copy the object subscribed to from tt, but subscribe ourselves to it again.

Definition at line 297 of file smartpointer.h.

◆ SmartPointer() [4/5]

template<typename T , typename P >
SmartPointer< T, P >::SmartPointer ( T *  t,
const std::string &  id 
)
inline

Constructor taking a normal pointer. If possible, i.e. if the pointer is not a null pointer, the constructor subscribes to the given object to lock it, i.e. to prevent its destruction before the end of its use.

The id is used in the call to Subscriptor::subscribe(id) and by ~SmartPointer() in the call to Subscriptor::unsubscribe().

Definition at line 272 of file smartpointer.h.

◆ SmartPointer() [5/5]

template<typename T , typename P >
SmartPointer< T, P >::SmartPointer ( T *  t)
inline

Constructor taking a normal pointer. If possible, i.e. if the pointer is not a null pointer, the constructor subscribes to the given object to lock it, i.e. to prevent its destruction before the end of its use. The id of this pointer is set to the name of the class P.

Definition at line 260 of file smartpointer.h.

◆ ~SmartPointer()

template<typename T , typename P >
SmartPointer< T, P >::~SmartPointer
inline

Destructor, removing the subscription.

Definition at line 309 of file smartpointer.h.

Member Function Documentation

◆ operator=() [1/3]

template<typename T , typename P >
SmartPointer< T, P > & SmartPointer< T, P >::operator= ( T *  tt)
inline

Assignment operator for normal pointers. The pointer subscribes to the new object automatically and unsubscribes to an old one if it exists. It will not try to subscribe to a null-pointer, but still delete the old subscription.

Definition at line 334 of file smartpointer.h.

◆ operator=() [2/3]

template<typename T , typename P >
template<class Q >
SmartPointer< T, P > & SmartPointer< T, P >::operator= ( const SmartPointer< T, Q > &  tt)
inline

Assignment operator for SmartPointer. The pointer subscribes to the new object automatically and unsubscribes to an old one if it exists.

Definition at line 354 of file smartpointer.h.

◆ operator=() [3/3]

template<typename T , typename P >
SmartPointer< T, P > & SmartPointer< T, P >::operator= ( const SmartPointer< T, P > &  tt)
inline

Assignment operator for SmartPointer. The pointer subscribes to the new object automatically and unsubscribes to an old one if it exists.

Definition at line 374 of file smartpointer.h.

◆ clear()

template<typename T , typename P >
void SmartPointer< T, P >::clear
inline

Delete the object pointed to and set the pointer to zero.

Definition at line 319 of file smartpointer.h.

◆ operator T*()

template<typename T , typename P >
SmartPointer< T, P >::operator T*
inline

Conversion to normal pointer.

Definition at line 393 of file smartpointer.h.

◆ operator*()

template<typename T , typename P >
T & SmartPointer< T, P >::operator*
inline

Dereferencing operator. This operator throws an ExcNotInitialized() if the pointer is a null pointer.

Definition at line 402 of file smartpointer.h.

◆ get()

template<typename T , typename P >
T * SmartPointer< T, P >::get
inline

Return underlying pointer. This operator throws an ExcNotInitialized() if the pointer is a null pointer.

Definition at line 414 of file smartpointer.h.

◆ operator->()

template<typename T , typename P >
T * SmartPointer< T, P >::operator->
inline

Operator that returns the underlying pointer. This operator throws an ExcNotInitialized() if the pointer is a null pointer.

Definition at line 426 of file smartpointer.h.

◆ swap() [1/2]

template<typename T , typename P >
template<class Q >
void SmartPointer< T, P >::swap ( SmartPointer< T, Q > &  tt)
inline

Exchange the pointers of this object and the argument. Since both the objects to which is pointed are subscribed to before and after, we do not have to change their subscription counters.

Note that this function (with two arguments) and the respective functions where one of the arguments is a pointer and the other one is a C-style pointer are implemented in global namespace.

Definition at line 436 of file smartpointer.h.

◆ swap() [2/2]

template<typename T , typename P >
void SmartPointer< T, P >::swap ( T *&  tt)
inline

Swap pointers between this object and the pointer given. As this releases the object pointed to presently, we reduce its subscription count by one, and increase it at the object which we will point to in the future.

Note that we indeed need a reference of a pointer, as we want to change the pointer variable which we are given.

Definition at line 451 of file smartpointer.h.

◆ memory_consumption()

template<typename T , typename P >
std::size_t SmartPointer< T, P >::memory_consumption
inline

Return an estimate of the amount of memory (in bytes) used by this class. Note in particular, that this only includes the amount of memory used by this object, not by the object pointed to.

Definition at line 466 of file smartpointer.h.

Member Data Documentation

◆ t

template<typename T , typename P = void>
T* SmartPointer< T, P >::t
private

Pointer to the object we want to subscribe to. Since it is often necessary to follow this pointer when debugging, we have deliberately chosen a short name.

Definition at line 232 of file smartpointer.h.

◆ id

template<typename T , typename P = void>
const std::string SmartPointer< T, P >::id
private

The identification for the subscriptor.

Definition at line 237 of file smartpointer.h.

◆ pointed_to_object_is_alive

template<typename T , typename P = void>
std::atomic<bool> SmartPointer< T, P >::pointed_to_object_is_alive
private

The Smartpointer is invalidated when the object pointed to is destroyed or moved from.

Definition at line 243 of file smartpointer.h.


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