Skip to content

Commit

Permalink
Improve documentation of deferment
Browse files Browse the repository at this point in the history
relates #185
  • Loading branch information
AzothAmmo committed Oct 17, 2019
1 parent 3529f59 commit a8f633d
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 13 deletions.
79 changes: 66 additions & 13 deletions include/cereal/cereal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,50 @@ namespace cereal

// ######################################################################
//! Marks data for deferred serialization
/*! @relates DeferredData
/*! cereal performs a recursive depth-first traversal of data it serializes. When
serializing smart pointers to large, nested, or cyclical data structures, it
is possible to encounter a stack overflow from excessive recursion when following
a chain of pointers.
Deferment can help in these situations if the data can be serialized separately from
the pointers used to traverse the structure. For example, a graph structure can have its
nodes serialized before its edges:
@code{.cpp}
struct MyEdge
{
std::shared_ptr<MyNode> connection;
int some_value;
template<class Archive>
void serialize(Archive & archive)
{
// when we serialize an edge, we'll defer serializing the associated node
archive( cereal::defer( connection ),
some_value );
}
};
struct MyGraphStructure
{
std::vector<MyEdge> edges;
std::vector<MyNodes> nodes;
template<class Archive>
void serialize(Archive & archive)
{
// because of the deferment, we ensure all nodes are fully serialized
// before any connection pointers to those nodes are serialized
archive( edges, nodes );
// we have to explicitly inform the archive when it is safe to serialize
// the deferred data
archive.serializeDeferments();
}
};
@endcode
@relates DeferredData
@ingroup Utility */
template <class T> inline
DeferredData<T> defer( T && value )
Expand Down Expand Up @@ -269,6 +312,15 @@ namespace cereal
return *self;
}

//! Serializes any data marked for deferment
/*! This will cause any data wrapped in DeferredData to be immediately serialized
@relates defer */
void serializeDeferments()
{
for( auto & deferment : itsDeferments )
deferment();
}

/*! @name Boost Transition Layer
Functionality that mirrors the syntax for Boost. This is useful if you are transitioning
a large project from Boost to cereal. The preferred interface for cereal is using operator(). */
Expand Down Expand Up @@ -357,12 +409,6 @@ namespace cereal
return id->second;
}

void serializeDeferments()
{
for( auto & deferment : itsDeferments )
deferment();
}

private:
//! Serializes data after calling prologue, then calls epilogue
template <class T> inline
Expand Down Expand Up @@ -655,6 +701,15 @@ namespace cereal
return *self;
}

//! Serializes any data marked for deferment
/*! This will cause any data wrapped in DeferredData to be immediately serialized
@relates defer */
void serializeDeferments()
{
for( auto & deferment : itsDeferments )
deferment();
}

/*! @name Boost Transition Layer
Functionality that mirrors the syntax for Boost. This is useful if you are transitioning
a large project from Boost to cereal. The preferred interface for cereal is using operator(). */
Expand Down Expand Up @@ -702,6 +757,7 @@ namespace cereal
/*! This is used to retrieve a previously registered shared_ptr
which has already been loaded.
@internal
@param id The unique id that was serialized for the pointer
@return A shared pointer to the data
@throw Exception if the id does not exist */
Expand All @@ -720,6 +776,7 @@ namespace cereal
/*! After a shared pointer has been allocated for the first time, it should
be registered with its loaded id for future references to it.
@internal
@param id The unique identifier for the shared pointer
@param ptr The actual shared pointer */
inline void registerSharedPointer(std::uint32_t const id, std::shared_ptr<void> ptr)
Expand All @@ -732,6 +789,7 @@ namespace cereal
/*! This is used to retrieve a string previously registered during
a polymorphic load.
@internal
@param id The unique id that was serialized for the polymorphic type
@return The string identifier for the tyep */
inline std::string getPolymorphicName(std::uint32_t const id)
Expand All @@ -748,6 +806,7 @@ namespace cereal
/*! After a polymorphic type has been loaded for the first time, it should
be registered with its loaded id for future references to it.
@internal
@param id The unique identifier for the polymorphic type
@param name The name associated with the tyep */
inline void registerPolymorphicName(std::uint32_t const id, std::string const & name)
Expand All @@ -756,12 +815,6 @@ namespace cereal
itsPolymorphicTypeMap.insert( {stripped_id, name} );
}

void serializeDeferments()
{
for( auto & deferment : itsDeferments )
deferment();
}

private:
//! Serializes data after calling prologue, then calls epilogue
template <class T> inline
Expand Down
5 changes: 5 additions & 0 deletions include/cereal/details/helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,11 @@ namespace cereal
};

// ######################################################################
//! A wrapper around data that should be serialized after all non-deferred data
/*! This class is used to demarcate data that can only be safely serialized after
any data not wrapped in this class.
@internal */
template <class T>
class DeferredData : detail::DeferredDataCore
{
Expand Down

0 comments on commit a8f633d

Please sign in to comment.