Reference documentation for deal.II version Git 73c87d96ef 2021-11-30 22:54:44 +0100
\(\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\}}\)
Classes | Public Member Functions | Private Attributes | List of all members
AlignedVector< T >::Deleter Class Reference


class  DeleterActionBase
class  MPISharedMemDeleterAction

Public Member Functions

 Deleter (AlignedVector< T > *owning_object)
 Deleter (AlignedVector< T > *owning_object, const bool is_shmem_root, T *aligned_shmem_pointer, MPI_Comm shmem_group_communicator, MPI_Win shmem_window)
void operator() (T *ptr)
void reset_owning_object (const AlignedVector< T > *new_aligned_vector_ptr)

Private Attributes

std::unique_ptr< DeleterActionBasedeleter_action_object
const AlignedVector< T > * owning_aligned_vector

Detailed Description

template<class T>
class AlignedVector< T >::Deleter

A class that is used as the "deleter" for a std::unique_ptr object that AlignedVector uses to store the memory used for the elements.

There are two ways the AlignedVector class can handle memory:

A common idiom towards using std::unique_ptr with complex de-allocation semantics is to use std::unique_ptr<T, std::function<void (T*)> and then use a lambda function to initialize the std::function deleter object. This approach is used in numerous other places in deal.II, but this has two downsides:

The way out of this is to write a custom deleter. It stores a pointer to the owning AlignedVector object. It then also stores a std::unique_ptr to an object of a class derived from a base class that implements the concrete action necessary to facilitate the "deleter" action. Based on the arguments given to the constructor of the Deleter class, the constructor then either allocates a "regular" or an MPI-based action object, and the action is facilitated by an overloaded virtual function.

In the end, this solves both of our problems:

This scheme can be further optimized in the following way: In the most common case, memory is allocated via posix_memalign() and needs to destroyed via std::free(). Rather than derive an action class for this common case, dynamically allocate an object for this case, and call it, we can just special case this situation: If the pointer to the action object is nullptr, then we just execute the default action. This means that for the most common case, we do not need any dynamic memory allocation at all, and in that case the deleter object truly only uses 16 bytes: One pointer to the owning AlignedVector object, and a pointer to the action object that happens to be a nullptr. Only in the case of the MPI shared memory data management does the action pointer point somewhere, but this case is expensive anyway and so the extra dynamic memory allocation does little harm.

(One could in that case go even further: There is no really only one possible non-default action left, namely the MPI-based destruction of the shared-memory window. Instead of having the Deleter::DeleterActionBase class below, and the derived Deleter::MPISharedMemDeleterAction class, both with virtual functions, we could just get rid of the base class and make the member functions of the derived class non-virtual. We would then either store a pointer to an MPISharedMemDeleterAction object if the non-default action is requested, or a nullptr for the default action. Avoiding virtual functions would make these objects smaller by a few bytes, and the call to the delete_array() function marginally faster. That said, given that the Deleter::MPISharedMemDeleterAction object already stores all sorts of stuff and its execution is not cheap, these additional optimizations are probably not worth it. Instead, we kept the class hierarchy so that one could define other non-standard actions in the future through other derived classes.)

Definition at line 558 of file aligned_vector.h.

Constructor & Destructor Documentation

◆ Deleter() [1/2]

template<class T>
AlignedVector< T >::Deleter::Deleter ( AlignedVector< T > *  owning_object)

Constructor. When this constructor is called, it installs an action that corresponds to "regular" memory allocation that needs to be handled by using std::free().

◆ Deleter() [2/2]

template<class T>
AlignedVector< T >::Deleter::Deleter ( AlignedVector< T > *  owning_object,
const bool  is_shmem_root,
T *  aligned_shmem_pointer,
MPI_Comm  shmem_group_communicator,
MPI_Win  shmem_window 

Constructor. When this constructor is called, it installs an action that corresponds to MPI-based shared memory allocation that needs to be handled by letting MPI de-allocate the shared memory window, plus destroying the MPI communicator, and doing other clean-up work.

Member Function Documentation

◆ operator()()

template<class T>
void AlignedVector< T >::Deleter::operator() ( T *  ptr)

The operator called by std::unique_ptr to destroy the data it is storing. This function dispatches to the different actions that this class implements.

◆ reset_owning_object()

template<class T>
void AlignedVector< T >::Deleter::reset_owning_object ( const AlignedVector< T > *  new_aligned_vector_ptr)

Reset the pointer to the owning AlignedVector object. This function is used in move operations when the pointer to the data is transferred from one AlignedVector object – i.e., the pointer itself remains unchanged, but the deleter object needs to be updated to know who the new owner now is.

Member Data Documentation

◆ deleter_action_object

template<class T>
std::unique_ptr<DeleterActionBase> AlignedVector< T >::Deleter::deleter_action_object

A pointer to the object that facilitates the actual action of destroying the memory.

Definition at line 664 of file aligned_vector.h.

◆ owning_aligned_vector

template<class T>
const AlignedVector<T>* AlignedVector< T >::Deleter::owning_aligned_vector

A (non-owned) pointer to the surrounding AlignedVector object that owns the memory this deleter object is responsible for deleting.

Definition at line 670 of file aligned_vector.h.

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