diff --git a/examples/checkpoint_example_traversal_nonintrusive.cc b/examples/checkpoint_example_traversal_nonintrusive.cc index 7b22157b..2585fd8f 100644 --- a/examples/checkpoint_example_traversal_nonintrusive.cc +++ b/examples/checkpoint_example_traversal_nonintrusive.cc @@ -136,7 +136,7 @@ struct CustomDispatch> { } }; -/// Custom traverser for printing typed ranges +/// Custom traverser for printing typed range<>s struct TypedTraverse : checkpoint::Serializer { template using DispatcherType = CustomDispatch; diff --git a/examples/checkpoint_example_user_traits.cc b/examples/checkpoint_example_user_traits.cc new file mode 100644 index 00000000..4c97933c --- /dev/null +++ b/examples/checkpoint_example_user_traits.cc @@ -0,0 +1,17 @@ +#include "checkpoint/checkpoint.h" + +#include "checkpoint_example_user_traits.hpp" + +int main(int argc, char *argv[]){ + test::TestObj obj; + + auto s_info = checkpoint::serialize(obj); + s_info = checkpoint::serialize(obj); + s_info = checkpoint::serialize(obj); + s_info = checkpoint::serialize(obj); + s_info = checkpoint::serialize(obj); + s_info = checkpoint::serialize(obj); + s_info = checkpoint::serialize(obj); + s_info = checkpoint::serialize(obj); + s_info = checkpoint::serialize(obj); +} diff --git a/examples/checkpoint_example_user_traits.hpp b/examples/checkpoint_example_user_traits.hpp new file mode 100644 index 00000000..259c0e78 --- /dev/null +++ b/examples/checkpoint_example_user_traits.hpp @@ -0,0 +1,66 @@ +#include "checkpoint/checkpoint.h" + +const struct checkpoint_trait {} CheckpointTrait; +const struct shallow_trait {} ShallowTrait; + +namespace test { + const struct random_trait {} RandomTrait; + + struct TestObj { + int a = 1; + + TestObj() {} + + template* = nullptr> + void serialize(SerT& s){ + if (s.hasTraits(CheckpointTrait)){ + if(s.isSizing()) printf("Customizing serialization for checkpoint\n"); + s | a; + } else { + if(s.isSizing()) printf("Default serializing testObj\n"); + } + + static_assert(not s.hasTraits(ShallowTrait), "ShallowTrait should have been removed!\n"); + } + }; +} + + +namespace test { + template* = nullptr> + void serialize(SerT& s, TestObj& myObj){ + if(s.isSizing()) printf("Inserting random extra object serialization step! "); + myObj.serialize(s); + } + + template* = nullptr> + void serialize(SerT& s, TestObj& myObj){ + if(s.isSizing()) printf("Removing shallow trait before passing along!\n"); + + myObj.serialize(s.withoutTraits(ShallowTrait)); + } +} + +namespace misc { + template* = nullptr> + void serialize(SerT& s, test::TestObj& myObj){ + if(s.isSizing()) printf("Serializers in other namespaces don't usually get found "); + myObj.serialize(s); + } + + + const struct namespace_trait {} NamespaceTrait; + template* = nullptr> + void serialize(SerT& s, test::TestObj& myObj){ + if(s.isSizing()) printf("A misc:: trait means we can serialize from misc:: too: "); + myObj.serialize(s); + } + + + const struct hook_all_trait {} HookAllTrait; + template* = nullptr> + void serialize(SerT& s, T& myObj){ + if(s.isSizing()) printf("We can even add on a generic pre-serialize hook: "); + myObj.serialize(s.withoutTraits(HookAllTrait)); + } +} diff --git a/src/checkpoint/checkpoint.h b/src/checkpoint/checkpoint.h index 72692288..97f20b51 100644 --- a/src/checkpoint/checkpoint.h +++ b/src/checkpoint/checkpoint.h @@ -47,6 +47,7 @@ #include "checkpoint/serializers/serializers_headers.h" #include "checkpoint/dispatch/dispatch.h" #include "checkpoint/traits/serializable_traits.h" +#include "checkpoint/traits/user_traits.h" #include "checkpoint/container/array_serialize.h" #include "checkpoint/container/atomic_serialize.h" diff --git a/src/checkpoint/checkpoint_api.h b/src/checkpoint/checkpoint_api.h index 4198d587..012f8779 100644 --- a/src/checkpoint/checkpoint_api.h +++ b/src/checkpoint/checkpoint_api.h @@ -78,7 +78,7 @@ using SerializedReturnType = std::unique_ptr; * \return a \c std::unique_ptr to a \c SerializedInfo containing the buffer * with serialized data and the size of the buffer */ -template +template SerializedReturnType serialize(T& target, BufferCallbackType fn = nullptr); /** @@ -101,7 +101,7 @@ SerializedReturnType serialize(T& target, BufferCallbackType fn = nullptr); * * \return a pointer to the newly reified \c T based on bytes in \c buf */ -template +template T* deserialize(char* buf, char* object_buf); /** @@ -118,7 +118,7 @@ T* deserialize(char* buf, char* object_buf); * * \return a unique pointer to the newly reified \c T based on bytes in \c buf */ -template +template std::unique_ptr deserialize(char* buf); /** @@ -132,7 +132,7 @@ std::unique_ptr deserialize(char* buf); * \param[in] t a valid pointer to a \c T that has been user-allocated and * constructed */ -template +template void deserializeInPlace(char* buf, T* t); /** @@ -143,7 +143,7 @@ void deserializeInPlace(char* buf, T* t); * * \return a unique pointer to \c T that must be deallocated */ -template +template std::unique_ptr deserialize(SerializedReturnType&& in); /** @@ -153,7 +153,7 @@ std::unique_ptr deserialize(SerializedReturnType&& in); * * \return number of bytes for the \c target */ -template +template std::size_t getSize(T& target); /** @@ -170,7 +170,7 @@ std::size_t getSize(T& target); * * \return memory footprint of the \c target */ -template +template std::size_t getMemoryFootprint(T& target, std::size_t size_offset = 0); /** @@ -184,7 +184,7 @@ std::size_t getMemoryFootprint(T& target, std::size_t size_offset = 0); * \param[in] target the \c T to serialize * \param[in] file name of the file to create */ -template +template void serializeToFile(T& target, std::string const& file); /** @@ -200,7 +200,7 @@ void serializeToFile(T& target, std::string const& file); * * \return unique pointer to the new object \c T */ -template +template std::unique_ptr deserializeFromFile(std::string const& file); /** @@ -214,9 +214,52 @@ std::unique_ptr deserializeFromFile(std::string const& file); * \param[in] file the filename to read with bytes for \c T * \param[in] t a valid, constructed \c T to deserialize into */ -template +template void deserializeInPlaceFromFile(std::string const& file, T* buf); +/** + * \brief Serialize \c T to a stream + * + * Byte-serializes \c T to stream. Handling of any errors during writing + * to the stream will be handled by the stream itself, e.g. any exceptions + * or status bits to check will depend on stream type. + * + * \param[in] target the \c T to serialize + * \param[in] stream to serialize into, with tellp and write functions. + */ +template +void serializeToStream(T& target, StreamT& stream); + +/** + * \brief De-serialize and reify \c T from a stream + * + * De-serializes an object recursively by first invoking the reconstruction + * strategy and then \c serialize functions/methods recursively to rebuild the + * state of the object as serialized. During reconstruction, based on trait + * detection, \c T will either be default constructed or reconstructed based on + * a user-defined reconstruct method. + * + * \param[in] stream the stream to read with bytes for \c T, with tellg and read functions + * + * \return unique pointer to the new object \c T + */ +template +std::unique_ptr deserializeFromStream(StreamT& stream); + +/** + * \brief De-serialize and reify \c T from a stream in place on an existing + * pointer to \c T + * + * De-serializes an object recursively by invoking the \c serialize + * functions/methods recursively to rebuild the state of the object as + * serialized. + * + * \param[in] stream the stream to read with bytes for \c T, with tellg and read functions + * \param[in] t a valid, constructed \c T to deserialize into + */ +template +void deserializeInPlaceFromStream(StreamT& stream, T* t); + } /* end namespace checkpoint */ #endif /*INCLUDED_CHECKPOINT_CHECKPOINT_API_H*/ diff --git a/src/checkpoint/checkpoint_api.impl.h b/src/checkpoint/checkpoint_api.impl.h index e649c5dd..6738677c 100644 --- a/src/checkpoint/checkpoint_api.impl.h +++ b/src/checkpoint/checkpoint_api.impl.h @@ -48,14 +48,15 @@ #include #include "checkpoint/checkpoint_api.h" #include "buffer/buffer.h" +#include "traits/user_traits.h" #include namespace checkpoint { -template +template SerializedReturnType serialize(T& target, BufferCallbackType fn) { - auto ret = dispatch::serializeType(target, fn); + auto ret = dispatch::serializeType>(target, fn); auto& buf = std::get<0>(ret); std::unique_ptr base_ptr( static_cast(buf.release()) @@ -63,66 +64,91 @@ SerializedReturnType serialize(T& target, BufferCallbackType fn) { return base_ptr; } -template +template T* deserialize(char* buf, char* object_buf) { - return dispatch::deserializeType(buf, object_buf); + return dispatch::deserializeType>(buf, object_buf); } -template +template std::unique_ptr deserialize(char* buf) { - auto t = dispatch::deserializeType(buf); + auto t = dispatch::deserializeType>(buf); return std::unique_ptr(t); } -template +template std::unique_ptr deserialize(SerializedReturnType&& in) { - auto t = dispatch::deserializeType(in->getBuffer()); + auto t = dispatch::deserializeType>(in->getBuffer()); return std::unique_ptr(t); } -template +template void deserializeInPlace(char* buf, T* t) { - return dispatch::deserializeType(dispatch::InPlaceTag{}, buf, t); + return dispatch::deserializeType>(dispatch::InPlaceTag{}, buf, t); } -template +template std::size_t getSize(T& target) { - return dispatch::Standard::size(target); + return dispatch::Standard::size>>(target); } -template +template std::size_t getMemoryFootprint(T& target, std::size_t size_offset) { return size_offset + std::max( - dispatch::Standard::footprint(target), + dispatch::Standard::footprint>>(target), sizeof(target) ); } -template +template void serializeToFile(T& target, std::string const& file) { - auto len = getSize(target); - dispatch::Standard::pack>( + auto len = getSize(target); + dispatch::Standard::pack>>( target, len, buffer::IOBuffer::WriteToFileTag{}, len, file ); } -template +template std::unique_ptr deserializeFromFile(std::string const& file) { auto mem = dispatch::Standard::allocate(); T* t_buf = dispatch::Standard::construct(mem); - auto t = dispatch::Standard::unpack>( + auto t = dispatch::Standard::unpack>>( t_buf, buffer::IOBuffer::ReadFromFileTag{}, file ); return std::unique_ptr(t); } -template +template void deserializeInPlaceFromFile(std::string const& file, T* t) { - dispatch::Standard::unpack>( + dispatch::Standard::unpack>>( t, buffer::IOBuffer::ReadFromFileTag{}, file ); } +template +void serializeToStream(T& target, StreamT& stream) { + auto len = getSize(target); + dispatch::Standard::pack>>( + target, len, eSerializationMode::Packing, stream + ); +} + +template +std::unique_ptr deserializeFromStream(StreamT& stream) { + auto mem = dispatch::Standard::allocate(); + T* t_buf = dispatch::Standard::construct(mem); + auto t = dispatch::Standard::unpack>>( + t_buf, eSerializationMode::Unpacking, stream + ); + return std::unique_ptr(t); +} + +template +void deserializeInPlaceFromStream(StreamT& stream, T* t) { + dispatch::Standard::unpack>>( + t, eSerializationMode::Unpacking, stream + ); +} + } /* end namespace checkpoint */ #endif /*INCLUDED_CHECKPOINT_CHECKPOINT_API_IMPL_H*/ diff --git a/src/checkpoint/container/atomic_serialize.h b/src/checkpoint/container/atomic_serialize.h index b639712d..53b8b97b 100644 --- a/src/checkpoint/container/atomic_serialize.h +++ b/src/checkpoint/container/atomic_serialize.h @@ -54,7 +54,7 @@ template < typename SerializerT, typename T, typename = std::enable_if_t< - std::is_same::value + checkpoint::is_footprinter::value > > void serialize(SerializerT& s, const std::atomic& atomic) { diff --git a/src/checkpoint/container/function_serialize.h b/src/checkpoint/container/function_serialize.h index aac19ab5..168e447f 100644 --- a/src/checkpoint/container/function_serialize.h +++ b/src/checkpoint/container/function_serialize.h @@ -68,9 +68,8 @@ template < typename Res, typename... ArgTypes, typename = std::enable_if_t< - std::is_same< - SerializerT, - checkpoint::Footprinter + checkpoint::is_footprinter< + SerializerT >::value > > diff --git a/src/checkpoint/container/kokkos_unordered_map_serialize.h b/src/checkpoint/container/kokkos_unordered_map_serialize.h index 6d230872..d2b72751 100644 --- a/src/checkpoint/container/kokkos_unordered_map_serialize.h +++ b/src/checkpoint/container/kokkos_unordered_map_serialize.h @@ -117,7 +117,7 @@ template < typename Hasher, typename EqualTo > typename std::enable_if_t< - not std::is_same::value, void + not checkpoint::is_footprinter::value, void > serialize( SerializerT& s, Kokkos::UnorderedMap& map @@ -140,7 +140,7 @@ template < typename Hasher, typename EqualTo > typename std::enable_if_t< - std::is_same::value, void + checkpoint::is_footprinter::value, void > serialize( SerializerT& s, Kokkos::UnorderedMap& map diff --git a/src/checkpoint/container/list_serialize.h b/src/checkpoint/container/list_serialize.h index c1bda13d..5855ce82 100644 --- a/src/checkpoint/container/list_serialize.h +++ b/src/checkpoint/container/list_serialize.h @@ -56,7 +56,7 @@ namespace checkpoint { template inline typename std::enable_if_t< - not std::is_same::value, void + not checkpoint::is_footprinter::value, void > deserializeOrderedElems( Serializer& s, ContainerT& cont, typename ContainerT::size_type size, @@ -76,7 +76,7 @@ deserializeOrderedElems( template inline typename std::enable_if_t< - not std::is_same::value, void + not checkpoint::is_footprinter::value, void > deserializeOrderedElems( Serializer& s, ContainerT& cont, typename ContainerT::size_type size, @@ -96,7 +96,7 @@ deserializeOrderedElems( template inline typename std::enable_if_t< - std::is_same::value, void + checkpoint::is_footprinter::value, void > deserializeOrderedElems( Serializer& s, ContainerT& cont, typename ContainerT::size_type size diff --git a/src/checkpoint/container/map_serialize.h b/src/checkpoint/container/map_serialize.h index 8ace2172..f663567e 100644 --- a/src/checkpoint/container/map_serialize.h +++ b/src/checkpoint/container/map_serialize.h @@ -58,7 +58,7 @@ namespace checkpoint { template inline typename std::enable_if_t< - not std::is_same::value, + not checkpoint::is_footprinter::value, void > deserializeEmplaceElems( Serializer& s, ContainerT& cont, typename ContainerT::size_type size @@ -77,7 +77,7 @@ inline typename std::enable_if_t< template inline typename std::enable_if_t< - std::is_same::value, + checkpoint::is_footprinter::value, void > deserializeEmplaceElems( Serializer& s, ContainerT& cont, typename ContainerT::size_type size diff --git a/src/checkpoint/container/queue_serialize.h b/src/checkpoint/container/queue_serialize.h index a1e88db2..3088b48c 100644 --- a/src/checkpoint/container/queue_serialize.h +++ b/src/checkpoint/container/queue_serialize.h @@ -70,9 +70,8 @@ template < typename SerializerT, typename Q, typename = std::enable_if_t< - std::is_same< - SerializerT, - checkpoint::Footprinter + checkpoint::is_footprinter< + SerializerT >::value > > diff --git a/src/checkpoint/container/raw_ptr_serialize.h b/src/checkpoint/container/raw_ptr_serialize.h index be83cfb5..3e096069 100644 --- a/src/checkpoint/container/raw_ptr_serialize.h +++ b/src/checkpoint/container/raw_ptr_serialize.h @@ -62,8 +62,8 @@ template < typename T, typename = std::enable_if_t< std::is_same< - SerializerT, - checkpoint::Footprinter + checkpoint::Footprinter<>, + SerializerT >::value > > @@ -95,7 +95,7 @@ void serializeRawPtr(SerializerT& s, void* ptr) { #define CHECKPOINT_FOOTPRINT_PIMPL_WITH_SIZEOF_PTR(PIMPL_TYPE) \ template < \ typename SerializerT, \ - typename = std::enable_if_t< std::is_same::value > \ + typename = std::enable_if_t< checkpoint::is_footprinter::value > \ > \ void serialize(SerializerT &s, PIMPL_TYPE *t) { \ s.countBytes(t); \ diff --git a/src/checkpoint/container/shared_ptr_serialize.h b/src/checkpoint/container/shared_ptr_serialize.h index a2554f02..31efd331 100644 --- a/src/checkpoint/container/shared_ptr_serialize.h +++ b/src/checkpoint/container/shared_ptr_serialize.h @@ -53,8 +53,8 @@ template < typename T, typename = std::enable_if_t< std::is_same< - SerializerT, - checkpoint::Footprinter + checkpoint::Footprinter<>, + SerializerT >::value > > diff --git a/src/checkpoint/container/thread_serialize.h b/src/checkpoint/container/thread_serialize.h index 5ecefc85..87765906 100644 --- a/src/checkpoint/container/thread_serialize.h +++ b/src/checkpoint/container/thread_serialize.h @@ -53,7 +53,7 @@ namespace checkpoint { template < typename SerializerT, typename = std::enable_if_t< - std::is_same::value + checkpoint::is_footprinter::value > > void serialize(SerializerT& s, const std::thread& t) { diff --git a/src/checkpoint/container/vector_serialize.h b/src/checkpoint/container/vector_serialize.h index 238e793d..ed8f109b 100644 --- a/src/checkpoint/container/vector_serialize.h +++ b/src/checkpoint/container/vector_serialize.h @@ -56,7 +56,7 @@ namespace checkpoint { template typename std::enable_if_t< - not std::is_same::value, SerialSizeType + not checkpoint::is_footprinter::value, SerialSizeType > serializeVectorMeta(SerializerT& s, std::vector& vec) { SerialSizeType vec_capacity = vec.capacity(); @@ -108,7 +108,7 @@ void constructVectorData( template typename std::enable_if_t< - not std::is_same::value, void + not checkpoint::is_footprinter::value, void > serialize(SerializerT& s, std::vector& vec) { auto const vec_size = serializeVectorMeta(s, vec); @@ -122,7 +122,7 @@ serialize(SerializerT& s, std::vector& vec) { template typename std::enable_if_t< - not std::is_same::value, void + not checkpoint::is_footprinter::value, void > serialize(SerializerT& s, std::vector& vec) { auto const vec_size = serializeVectorMeta(s, vec); @@ -146,7 +146,7 @@ serialize(SerializerT& s, std::vector& vec) { template typename std::enable_if_t< - std::is_same::value, void + checkpoint::is_footprinter::value, void > serialize(SerializerT& s, std::vector& vec) { s.countBytes(vec); @@ -156,7 +156,7 @@ serialize(SerializerT& s, std::vector& vec) { template typename std::enable_if_t< - std::is_same::value, void + checkpoint::is_footprinter::value, void > serialize(SerializerT& s, std::vector& vec) { s.countBytes(vec); diff --git a/src/checkpoint/dispatch/dispatch.h b/src/checkpoint/dispatch/dispatch.h index 3bf10e55..78b47874 100644 --- a/src/checkpoint/dispatch/dispatch.h +++ b/src/checkpoint/dispatch/dispatch.h @@ -188,7 +188,7 @@ struct Standard { static SerialByteType* allocate(); }; -template +template buffer::ImplReturnType packBuffer( T& target, SerialSizeType size, BufferObtainFnType fn ); @@ -196,13 +196,13 @@ buffer::ImplReturnType packBuffer( template inline void serializeArray(Serializer& s, T* array, SerialSizeType const len); -template +template buffer::ImplReturnType serializeType(T& target, BufferObtainFnType fn = nullptr); -template +template T* deserializeType(SerialByteType* data, SerialByteType* allocBuf = nullptr); -template +template void deserializeType(InPlaceTag, SerialByteType* data, T* t); template diff --git a/src/checkpoint/dispatch/dispatch.impl.h b/src/checkpoint/dispatch/dispatch.impl.h index 420d0577..ddb0e776 100644 --- a/src/checkpoint/dispatch/dispatch.impl.h +++ b/src/checkpoint/dispatch/dispatch.impl.h @@ -247,17 +247,17 @@ validatePackerBufferSize(PackerT const& p, SerialSizeType bufferSize) { } } -template +template buffer::ImplReturnType packBuffer(T& target, SerialSizeType size, BufferObtainFnType fn) { SerialByteType* user_buf = fn ? fn(size) : nullptr; if (user_buf == nullptr) { auto p = - Standard::pack>(target, size); + Standard::pack>(target, size); validatePackerBufferSize(p, size); return std::make_tuple(std::move(p.extractPackedBuffer()), size); } else { - auto p = Standard::pack>( + auto p = Standard::pack>( target, size, std::make_unique(user_buf, size) ); validatePackerBufferSize(p, size); @@ -265,26 +265,26 @@ packBuffer(T& target, SerialSizeType size, BufferObtainFnType fn) { } } -template +template buffer::ImplReturnType serializeType(T& target, BufferObtainFnType fn) { - auto len = Standard::size(target); + auto len = Standard::size>(target); debug_checkpoint("serializeType: len=%ld\n", len); - return packBuffer(target, len, fn); + return packBuffer(target, len, fn); } -template +template T* deserializeType(SerialByteType* data, SerialByteType* allocBuf) { auto mem = allocBuf ? allocBuf : Standard::allocate(); auto t_buf = std::unique_ptr(Standard::construct(mem)); T* traverser = - Standard::unpack>(t_buf.get(), data); + Standard::unpack>(t_buf.get(), data); t_buf.release(); return traverser; } -template +template void deserializeType(InPlaceTag, SerialByteType* data, T* t) { - Standard::unpack>(t, data); + Standard::unpack>(t, data); } }} /* end namespace checkpoint::dispatch */ diff --git a/src/checkpoint/dispatch/dispatch_serializer_nonbyte.h b/src/checkpoint/dispatch/dispatch_serializer_nonbyte.h index 5da80f9b..1739e4c9 100644 --- a/src/checkpoint/dispatch/dispatch_serializer_nonbyte.h +++ b/src/checkpoint/dispatch/dispatch_serializer_nonbyte.h @@ -91,7 +91,7 @@ struct SerializerDispatchNonByte { template using hasInSerialize = - typename std::enable_if::has_serialize_instrusive, T>::type; + typename std::enable_if::has_serialize_instrusive && !SerializableTraits::has_serialize_noninstrusive, T>::type; template using hasNoninSerialize = @@ -112,7 +112,7 @@ struct SerializerDispatchNonByte { template using justFootprint = typename std::enable_if< - std::is_same::value and + checkpoint::is_footprinter::value and not SerializableTraits::is_traversable and not std::is_enum::value, T diff --git a/src/checkpoint/dispatch/vrt/serializer_registry.h b/src/checkpoint/dispatch/vrt/serializer_registry.h index e0772411..93372556 100644 --- a/src/checkpoint/dispatch/vrt/serializer_registry.h +++ b/src/checkpoint/dispatch/vrt/serializer_registry.h @@ -94,7 +94,7 @@ inline RegistryType& getRegistry() { template inline TypeIdx makeObjIdx() { - return Type::idx; + return Type::idx; } template diff --git a/src/checkpoint/dispatch/vrt/virtual_serialize.h b/src/checkpoint/dispatch/vrt/virtual_serialize.h index 426352e9..147ce096 100644 --- a/src/checkpoint/dispatch/vrt/virtual_serialize.h +++ b/src/checkpoint/dispatch/vrt/virtual_serialize.h @@ -62,6 +62,15 @@ void virtualSerialize(T*& base, SerializerT& s) { // Get the real base in case this is called on a derived type using BaseT = ::checkpoint::dispatch::vrt::checkpoint_base_type_t; auto serializer_idx = serializer_registry::makeObjIdx(); + + if constexpr (not std::is_same_v){ + static bool warned_once = false; + if(!warned_once){ + fprintf(stderr, "Warning: Magistrate cannot support UserTraits being visible to virtually serialized objects.\n"); + warned_once = true; + } + } + base->_checkpointDynamicSerialize(&s, serializer_idx, no_type_idx); } @@ -146,7 +155,7 @@ struct ReconstructAsVirtualIfNeeded< SerializerT, typename std::enable_if_t< dispatch::vrt::VirtualSerializeTraits::has_not_virtual_serialize and - not std::is_same::value + not checkpoint::is_footprinter::value > > { static T* apply(SerializerT& s, dispatch::vrt::TypeIdx entry) { @@ -162,7 +171,7 @@ struct ReconstructAsVirtualIfNeeded< SerializerT, typename std::enable_if_t< dispatch::vrt::VirtualSerializeTraits::has_not_virtual_serialize and - std::is_same::value + checkpoint::is_footprinter::value > > { static T* apply(SerializerT& s, dispatch::vrt::TypeIdx entry) { return nullptr; } diff --git a/src/checkpoint/serializers/base_serializer.h b/src/checkpoint/serializers/base_serializer.h index 723c0bde..77ba82c9 100644 --- a/src/checkpoint/serializers/base_serializer.h +++ b/src/checkpoint/serializers/base_serializer.h @@ -45,6 +45,7 @@ #define INCLUDED_CHECKPOINT_SERIALIZERS_BASE_SERIALIZER_H #include "checkpoint/common.h" +#include "checkpoint/traits/user_traits.h" #include #include @@ -208,6 +209,7 @@ struct Serializer { bool virtual_disabled_ = false; /**< Virtual serialization disabled */ }; + } /* end namespace checkpoint */ #endif /*INCLUDED_CHECKPOINT_SERIALIZERS_BASE_SERIALIZER_H*/ diff --git a/src/checkpoint/serializers/footprinter.h b/src/checkpoint/serializers/footprinter.h index 334f7b9f..283bd7f8 100644 --- a/src/checkpoint/serializers/footprinter.h +++ b/src/checkpoint/serializers/footprinter.h @@ -49,7 +49,10 @@ namespace checkpoint { -struct Footprinter : Serializer { +template> +struct Footprinter : Serializer, UserTraitedType { + using Serializer::ModeType; + Footprinter() : Serializer(ModeType::Footprinting) { } SerialSizeType getMemoryFootprint() const { @@ -72,6 +75,20 @@ struct Footprinter : Serializer { SerialSizeType num_bytes_ = 0; }; +namespace { + template + struct is_footprinter_impl : public std::false_type {}; + + template + struct is_footprinter_impl> : std::true_type {}; + + template <> + struct is_footprinter_impl> : std::true_type {}; +} + +template +using is_footprinter = is_footprinter_impl>; + } /* end namespace checkpoint */ #endif /*INCLUDED_CHECKPOINT_SERIALIZERS_FOOTPRINTER_H*/ diff --git a/src/checkpoint/serializers/memory_serializer.h b/src/checkpoint/serializers/memory_serializer.h index 284da449..3e7366c9 100644 --- a/src/checkpoint/serializers/memory_serializer.h +++ b/src/checkpoint/serializers/memory_serializer.h @@ -50,6 +50,8 @@ namespace checkpoint { struct MemorySerializer : Serializer { + using Serializer::ModeType; + MemorySerializer(ModeType const& in_mode, SerialByteType* in_start) : Serializer(in_mode), start_(in_start), cur_(in_start) { } diff --git a/src/checkpoint/serializers/packer.h b/src/checkpoint/serializers/packer.h index 0502c64f..3d628ca6 100644 --- a/src/checkpoint/serializers/packer.h +++ b/src/checkpoint/serializers/packer.h @@ -52,9 +52,8 @@ #include "checkpoint/buffer/io_buffer.h" namespace checkpoint { - -template -struct PackerBuffer : MemorySerializer { +template > +struct PackerBuffer : MemorySerializer, public UserTraitedType { using BufferTPtrType = std::unique_ptr; using PackerReturnType = std::tuple; diff --git a/src/checkpoint/serializers/packer.impl.h b/src/checkpoint/serializers/packer.impl.h index dfffaf15..93a2ce87 100644 --- a/src/checkpoint/serializers/packer.impl.h +++ b/src/checkpoint/serializers/packer.impl.h @@ -52,9 +52,9 @@ namespace checkpoint { -template -PackerBuffer::PackerBuffer(SerialSizeType const& in_size) - : MemorySerializer(ModeType::Packing), size_(in_size), +template +PackerBuffer::PackerBuffer(SerialSizeType const& in_size) + : MemorySerializer(Serializer::ModeType::Packing), size_(in_size), buffer_(std::make_unique(size_)) { MemorySerializer::initializeBuffer(buffer_->getBuffer()); @@ -67,10 +67,10 @@ PackerBuffer::PackerBuffer(SerialSizeType const& in_size) ); } -template -PackerBuffer::PackerBuffer( +template +PackerBuffer::PackerBuffer( SerialSizeType const& in_size, BufferTPtrType buf_ptr -) : MemorySerializer(ModeType::Packing), size_(in_size), +) : MemorySerializer(Serializer::ModeType::Packing), size_(in_size), buffer_(std::move(buf_ptr)) { MemorySerializer::initializeBuffer(buffer_->getBuffer()); @@ -83,11 +83,11 @@ PackerBuffer::PackerBuffer( ); } -template +template template -PackerBuffer::PackerBuffer( +PackerBuffer::PackerBuffer( SerialSizeType const& in_size, Args&&... args -) : MemorySerializer(ModeType::Packing), +) : MemorySerializer(Serializer::ModeType::Packing), size_(in_size), buffer_(std::make_unique(std::forward(args)...)) { @@ -101,16 +101,16 @@ PackerBuffer::PackerBuffer( ); } -template -typename PackerBuffer::BufferTPtrType -PackerBuffer::extractPackedBuffer() { +template +typename PackerBuffer::BufferTPtrType +PackerBuffer::extractPackedBuffer() { auto ret = std::move(buffer_); buffer_ = nullptr; return ret; } -template -void PackerBuffer::contiguousBytes( +template +void PackerBuffer::contiguousBytes( void* ptr, SerialSizeType size, SerialSizeType num_elms ) { debug_checkpoint( @@ -132,8 +132,8 @@ void PackerBuffer::contiguousBytes( usedSize_ += len; } -template -SerialSizeType PackerBuffer::usedBufferSize() const { +template +SerialSizeType PackerBuffer::usedBufferSize() const { return usedSize_; } diff --git a/src/checkpoint/serializers/serializers_headers.h b/src/checkpoint/serializers/serializers_headers.h index bc6fda64..e01a9e3f 100644 --- a/src/checkpoint/serializers/serializers_headers.h +++ b/src/checkpoint/serializers/serializers_headers.h @@ -50,14 +50,17 @@ #include "checkpoint/serializers/sizer.h" #include "checkpoint/serializers/packer.h" #include "checkpoint/serializers/unpacker.h" +#include "checkpoint/serializers/stream_serializer.h" #define checkpoint_serializer_variadic_args() \ - checkpoint::Footprinter, \ + checkpoint::Footprinter<>, \ checkpoint::Packer, \ checkpoint::PackerUserBuf, \ checkpoint::PackerIO, \ checkpoint::Unpacker, \ checkpoint::UnpackerIO, \ - checkpoint::Sizer \ + checkpoint::Sizer<>, \ + checkpoint::StreamPacker<>, \ + checkpoint::StreamUnpacker<> \ #endif /*INCLUDED_CHECKPOINT_SERIALIZERS_SERIALIZERS_HEADERS_H*/ diff --git a/src/checkpoint/serializers/sizer.cc b/src/checkpoint/serializers/sizer.cc index 43257212..92f4a3eb 100644 --- a/src/checkpoint/serializers/sizer.cc +++ b/src/checkpoint/serializers/sizer.cc @@ -47,14 +47,4 @@ namespace checkpoint { -Sizer::Sizer() : Serializer(ModeType::Sizing) { } - -SerialSizeType Sizer::getSize() const { - return num_bytes_; -} - -void Sizer::contiguousBytes(void*, SerialSizeType size, SerialSizeType num_elms) { - num_bytes_ += size * num_elms; -} - } /* end namespace checkpoint */ diff --git a/src/checkpoint/serializers/sizer.h b/src/checkpoint/serializers/sizer.h index 447319d7..82d2c4d9 100644 --- a/src/checkpoint/serializers/sizer.h +++ b/src/checkpoint/serializers/sizer.h @@ -56,18 +56,24 @@ namespace checkpoint { * preprocessing pass before packing content so a properly sized buffer can be * allocated. */ -struct Sizer : Serializer { +template> +struct Sizer : Serializer, public UserTraitedType { + using ModeType = eSerializationMode; /** * \internal \brief Construct a sizer */ - Sizer(); + Sizer() : Serializer(ModeType::Sizing){ + + } /** * \brief Get the current size * * \return The current size */ - SerialSizeType getSize() const; + SerialSizeType getSize() const{ + return num_bytes_; + } /** * \brief Add contiguous bytes to the sizer @@ -76,7 +82,9 @@ struct Sizer : Serializer { * \param[in] size the number of bytes for each element * \param[in] num_elms the number of elements */ - void contiguousBytes(void* ptr, SerialSizeType size, SerialSizeType num_elms); + void contiguousBytes(void* ptr, SerialSizeType size, SerialSizeType num_elms){ + num_bytes_ += size*num_elms; + }; private: SerialSizeType num_bytes_ = 0; /**< Count of bytes */ diff --git a/src/checkpoint/serializers/stream_serializer.h b/src/checkpoint/serializers/stream_serializer.h new file mode 100644 index 00000000..665ba429 --- /dev/null +++ b/src/checkpoint/serializers/stream_serializer.h @@ -0,0 +1,120 @@ +/* +//@HEADER +// ***************************************************************************** +// +// stream_serializer.h +// DARMA/checkpoint => Serialization Library +// +// Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact darma@sandia.gov +// +// ***************************************************************************** +//@HEADER +*/ + +#if !defined INCLUDED_CHECKPOINT_SERIALIZERS_STREAM_SERIALIZER_H +#define INCLUDED_CHECKPOINT_SERIALIZERS_STREAM_SERIALIZER_H + +#include "checkpoint/common.h" +#include "checkpoint/serializers/base_serializer.h" + +namespace checkpoint { + +namespace { + template + struct StreamHolder {}; + + template + struct StreamHolder { + StreamT& stream; + + StreamHolder(StreamT& stream) : stream(stream) {}; + + void copy(char* ptr, SerialSizeType len){ + stream.write(ptr, len); + } + + SerialSizeType position(){ + return stream.tellp(); + } + }; + + template + struct StreamHolder { + StreamT& stream; + + StreamHolder(StreamT& stream) : stream(stream) {}; + + void copy(char* ptr, SerialSizeType len){ + stream.read(ptr, len); + } + + SerialSizeType position(){ + return stream.tellg(); + } + }; +} + +template > +struct StreamSerializerImpl : Serializer, public UserTraitedType { + using Serializer::ModeType; + + StreamSerializerImpl(ModeType const& in_mode, StreamT& in_stream) + : Serializer(in_mode), stream(in_stream), stream_start_position(stream.position()) { + assert(( IsPacking::value && (in_mode == ModeType::Packing)) || + (!IsPacking::value && (in_mode == ModeType::Unpacking))); + } + + StreamSerializerImpl(SerialSizeType size, ModeType const& in_mode, StreamT& in_stream) + : StreamSerializerImpl(in_mode, in_stream) {} + + void contiguousBytes(void* ptr, SerialSizeType size, SerialSizeType num_elms) { + stream.copy(static_cast(ptr), size*num_elms); + } + + SerialSizeType usedBufferSize() { + return stream.position() - stream_start_position; + } + +private: + StreamHolder stream; + const SerialSizeType stream_start_position; +}; + +template +using StreamPacker = StreamSerializerImpl; +template +using StreamUnpacker = StreamSerializerImpl; + +} /* end namespace checkpoint */ + +#endif /*INCLUDED_CHECKPOINT_SERIALIZERS_STREAM_SERIALIZER_H*/ diff --git a/src/checkpoint/serializers/unpacker.h b/src/checkpoint/serializers/unpacker.h index 77d34439..02279695 100644 --- a/src/checkpoint/serializers/unpacker.h +++ b/src/checkpoint/serializers/unpacker.h @@ -50,8 +50,8 @@ namespace checkpoint { -template -struct UnpackerBuffer : MemorySerializer { +template > +struct UnpackerBuffer : MemorySerializer, public UserTraitedType { using BufferPtrType = std::unique_ptr; explicit UnpackerBuffer(SerialByteType* buf); diff --git a/src/checkpoint/serializers/unpacker.impl.h b/src/checkpoint/serializers/unpacker.impl.h index c6c835c1..e3521153 100644 --- a/src/checkpoint/serializers/unpacker.impl.h +++ b/src/checkpoint/serializers/unpacker.impl.h @@ -53,9 +53,9 @@ namespace checkpoint { -template -UnpackerBuffer::UnpackerBuffer(SerialByteType* buf) - : MemorySerializer(ModeType::Unpacking), +template +UnpackerBuffer::UnpackerBuffer(SerialByteType* buf) + : MemorySerializer(Serializer::ModeType::Unpacking), buffer_(std::make_unique(buf, 0)) { MemorySerializer::initializeBuffer(buffer_->getBuffer()); @@ -67,10 +67,10 @@ UnpackerBuffer::UnpackerBuffer(SerialByteType* buf) ); } -template +template template -UnpackerBuffer::UnpackerBuffer(Args&&... args) - : MemorySerializer(ModeType::Unpacking), +UnpackerBuffer::UnpackerBuffer(Args&&... args) + : MemorySerializer(Serializer::ModeType::Unpacking), buffer_(std::make_unique(std::forward(args)...)) { MemorySerializer::initializeBuffer(buffer_->getBuffer()); @@ -82,8 +82,8 @@ UnpackerBuffer::UnpackerBuffer(Args&&... args) ); } -template -void UnpackerBuffer::contiguousBytes( +template +void UnpackerBuffer::contiguousBytes( void* ptr, SerialSizeType size, SerialSizeType num_elms ) { debug_checkpoint( @@ -98,8 +98,8 @@ void UnpackerBuffer::contiguousBytes( usedSize_ += len; } -template -SerialSizeType UnpackerBuffer::usedBufferSize() const { +template +SerialSizeType UnpackerBuffer::usedBufferSize() const { return usedSize_; } diff --git a/src/checkpoint/traits/user_traits.h b/src/checkpoint/traits/user_traits.h new file mode 100644 index 00000000..62ec637e --- /dev/null +++ b/src/checkpoint/traits/user_traits.h @@ -0,0 +1,252 @@ +/* +//@HEADER +// ***************************************************************************** +// +// user_traits.h +// DARMA/checkpoint => Serialization Library +// +// Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact darma@sandia.gov +// +// ***************************************************************************** +//@HEADER +*/ + +#if !defined INCLUDED_USER_TRAITS_CHECKPOINT_TRAITS_H +#define INCLUDED_USER_TRAITS_CHECKPOINT_TRAITS_H + +namespace { + struct NoTrait; + + template + struct without_helper { + using type = typename without_helper, U...>::type; + }; + template + struct without_helper { + using type = typename Traits::_without_trait; + }; +} + +namespace checkpoint { +namespace SerializerUserTraits { + + template + struct is_base_or_derived + : std::disjunction, std::is_base_of> {}; + + template + struct is_same_template + : std::false_type {}; + template