NDDEM
Public Member Functions | Private Types | Private Attributes | List of all members
cereal::memory_detail::EnableSharedStateHelper< T > Class Template Reference

#include <memory.hpp>

Public Member Functions

 EnableSharedStateHelper (T *ptr)
 Saves the state of some type inheriting from enable_shared_from_this. More...
 
void restore ()
 Restores the state of the held pointer (can only be done once) More...
 
 ~EnableSharedStateHelper ()
 Restores the state of the held pointer if not done previously. More...
 

Private Types

using BaseType = typename ::cereal::traits::get_shared_from_this_base< T >::type
 
using ParentType = std::enable_shared_from_this< BaseType >
 
using StorageType = typename std::aligned_storage< sizeof(ParentType), CEREAL_ALIGNOF(ParentType)>::type
 

Private Attributes

ParentTypeitsPtr
 
StorageType itsState
 
bool itsRestored
 

Detailed Description

template<class T>
class cereal::memory_detail::EnableSharedStateHelper< T >

A helper struct for saving and restoring the state of types that derive from std::enable_shared_from_this

This special struct is necessary because when a user uses load_and_construct, the weak_ptr (or whatever implementation defined variant) that allows enable_shared_from_this to function correctly will not be initialized properly.

This internal weak_ptr can also be modified by the shared_ptr that is created during the serialization of a polymorphic pointer, where cereal creates a wrapper shared_ptr out of a void pointer to the real data.

In the case of load_and_construct, this happens because it is the allocation of shared_ptr that perform this initialization, which we let happen on a buffer of memory (aligned_storage). This buffer is then used for placement new later on, effectively overwriting any initialized weak_ptr with a default initialized one, eventually leading to issues when the user calls shared_from_this.

To get around these issues, we will store the memory for the enable_shared_from_this portion of the class and replace it after whatever happens to modify it (e.g. the user performing construction or the wrapper shared_ptr in saving).

Note that this goes into undefined behavior territory, but as of the initial writing of this, all standard library implementations of std::enable_shared_from_this are compatible with this memory manipulation. It is entirely possible that this may someday break or may not work with convoluted use cases.

Example usage:

T * myActualPointer;
{
EnableSharedStateHelper<T> helper( myActualPointer ); // save the state
std::shared_ptr<T> myPtr( myActualPointer ); // modifies the internal weak_ptr
// helper restores state when it goes out of scope
}

When possible, this is designed to be used in an RAII fashion - it will save state on construction and restore it on destruction. The restore can be done at an earlier time (e.g. after construct() is called in load_and_construct) in which case the destructor will do nothing. Performing the restore immediately following construct() allows a user to call shared_from_this within their load_and_construct function.

Template Parameters
TType pointed to by shared_ptr

Member Typedef Documentation

◆ BaseType

template<class T >
using cereal::memory_detail::EnableSharedStateHelper< T >::BaseType = typename ::cereal::traits::get_shared_from_this_base<T>::type
private

◆ ParentType

template<class T >
using cereal::memory_detail::EnableSharedStateHelper< T >::ParentType = std::enable_shared_from_this<BaseType>
private

◆ StorageType

template<class T >
using cereal::memory_detail::EnableSharedStateHelper< T >::StorageType = typename std::aligned_storage<sizeof(ParentType), CEREAL_ALIGNOF(ParentType)>::type
private

Constructor & Destructor Documentation

◆ EnableSharedStateHelper()

template<class T >
cereal::memory_detail::EnableSharedStateHelper< T >::EnableSharedStateHelper ( T *  ptr)
inline

Saves the state of some type inheriting from enable_shared_from_this.

Parameters
ptrThe raw pointer held by the shared_ptr

◆ ~EnableSharedStateHelper()

Restores the state of the held pointer if not done previously.

Member Function Documentation

◆ restore()

template<class T >
void cereal::memory_detail::EnableSharedStateHelper< T >::restore ( )
inline

Restores the state of the held pointer (can only be done once)

Member Data Documentation

◆ itsPtr

template<class T >
ParentType* cereal::memory_detail::EnableSharedStateHelper< T >::itsPtr
private

◆ itsRestored

template<class T >
bool cereal::memory_detail::EnableSharedStateHelper< T >::itsRestored
private

◆ itsState

template<class T >
StorageType cereal::memory_detail::EnableSharedStateHelper< T >::itsState
private

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