Reference documentation for deal.II version GIT relicensing-464-g14f7274e4d 2024-04-22 15:40: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\}}\)
Loading...
Searching...
No Matches
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;
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 92 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 250 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 284 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 296 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 271 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 259 of file smartpointer.h.

◆ ~SmartPointer()

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

Destructor, removing the subscription.

Definition at line 308 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 333 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 353 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 373 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 318 of file smartpointer.h.

◆ operator T*()

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

Conversion to normal pointer.

Definition at line 392 of file smartpointer.h.

◆ operator*()

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

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

Definition at line 401 of file smartpointer.h.

◆ get()

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

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

Definition at line 413 of file smartpointer.h.

◆ operator->()

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

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

Definition at line 425 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 435 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 450 of file smartpointer.h.

◆ memory_consumption()

template<typename T , typename P >
std::size_t SmartPointer< T, P >::memory_consumption ( ) const
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 465 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 231 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 236 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 242 of file smartpointer.h.


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