KaMPIng 0.1.1
Flexible and (near) zero-overhead C++ bindings for MPI
Loading...
Searching...
No Matches
serialization.hpp
1// This file is part of KaMPIng.
2//
3// Copyright 2024 The KaMPIng Authors
4//
5// KaMPIng is free software : you can redistribute it and/or modify it under the
6// terms of the GNU Lesser General Public License as published by the Free
7// Software Foundation, either version 3 of the License, or (at your option) any
8// later version. KaMPIng is distributed in the hope that it will be useful, but
9// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
11// for more details.
12//
13// You should have received a copy of the GNU Lesser General Public License
14// along with KaMPIng. If not, see <https://www.gnu.org/licenses/>.
15
16#pragma once
17
18#include <type_traits>
19
20#ifdef KAMPING_ENABLE_SERIALIZATION
21 #include "cereal/archives/binary.hpp"
22#endif
24
25namespace kamping {
26namespace internal {
27#ifdef KAMPING_ENABLE_SERIALIZATION
28
29/// @brief Buffer holding serialized data.
30///
31/// This uses [`cereal`](https://uscilab.github.io/cereal/) to serialize and deserialize objects.
32///
33/// @tparam OutArchive Type of the archive to use for serialization.
34/// @tparam InArchive Type of the archive to use for deserialization.
35/// @tparam Allocator Type of the allocator to use for the buffer holding the serialized data.
36/// @tparam DataBufferType Type of the \ref GenericDataBuffer holding the data to serialize/deserialize into.
37template <typename OutArchive, typename InArchive, typename Allocator, typename DataBufferType>
38class SerializationBuffer {
39private:
40 std::basic_string<char, std::char_traits<char>, Allocator> _data; ///< Buffer holding the serialized data.
41 DataBufferType _object; ///< Object to de/serialize encapsulated in a \ref GenericDataBuffer.
42
43public:
44 using data_type =
45 typename DataBufferType::value_type; ///< Type of the encapsulated object to serialize/deserialize.
46
47 /// @brief Construct a serialization buffer from a \ref GenericDataBuffer containing the object to
48 /// serialize/deserialize into.
49 SerializationBuffer(DataBufferType&& object) : _data(), _object(std::move(object)) {}
50
51 /// @brief Serialize the object into the character buffer stored internally.
52 void serialize() {
53 std::basic_stringstream<char, std::char_traits<char>, Allocator> buffer;
54 {
55 OutArchive archive(buffer);
56 archive(_object.underlying());
57 }
58 _data = buffer.str();
59 }
60
61 /// @brief Extract the \ref GenericDataBuffer containing the encapsulated object.
62 DataBufferType extract() && {
63 return std::move(_object);
64 }
65
66 /// @brief Deserialize from the character buffer stored internally into the encapsulated object.
67 void deserialize() {
68 std::istringstream buffer(std::string(_data.begin(), _data.end()));
69 {
70 InArchive archive(buffer);
71 archive(_object.underlying());
72 }
73 }
74
75 using value_type = char; ///< Type of the elements in the buffer.
76
77 /// @brief Access the underlying buffer.
78 char* data() noexcept {
79 return _data.data();
80 }
81
82 /// @brief Access the underlying buffer.
83 char const* data() const noexcept {
84 return _data.data();
85 }
86
87 /// @brief Resize the underlying buffer.
88 /// @param size New size of the buffer.
89 void resize(size_t size) {
90 _data.resize(size);
91 }
92
93 /// @brief Access the size of the underlying buffer.
94 size_t size() const {
95 return _data.size();
96 }
97};
98#endif
99
100/// @brief Tag type to identify serialization support.
102
103/// @brief Type trait to check if a type is a serialization buffer.
104template <typename>
105constexpr bool is_serialization_buffer_v_impl = false;
106#ifdef KAMPING_ENABLE_SERIALIZATION
107/// @brief Type trait to check if a type is a serialization buffer.
108template <typename... Args>
110#endif
111
112/// @brief Type trait to check if a type is a serialization buffer.
113template <typename T>
116
117/// @brief If \p serialization_used is true, this takes a received serialization buffer, deserializes the data and
118/// repacks it into a new buffer only containing the deserialized data
119/// If \p serialization_used is false, the input buffer is returned unchanged.
120template <bool serialization_used, typename BufferType>
122 if constexpr (serialization_used) {
123 auto serialization_data = buffer.extract();
124 serialization_data.deserialize();
125 return std::move(serialization_data).extract();
126 } else {
127 return buffer;
128 }
129}
130} // namespace internal
131#ifdef KAMPING_ENABLE_SERIALIZATION
132/// @brief Serializes an object using [`cereal`](https://uscilab.github.io/cereal/).
133/// @tparam Archive Type of the archive to use for serialization (see
134/// https://uscilab.github.io/cereal/serialization_archives.html). Default is `cereal::BinaryOutputArchive`.
135/// @tparam Allocator Type of the allocator to use for the buffer holding the serialized data. Default is
136/// `std::allocator<char>`.
137/// @tparam T Type of the object to serialize.
138template <typename Archive = cereal::BinaryOutputArchive, typename Allocator = std::allocator<char>, typename T>
139auto as_serialized(T const& data) {
140 internal::GenericDataBuffer<
141 T,
144 internal::BufferModifiability::constant,
145 internal::BufferOwnership::referencing,
146 internal::BufferType::in_buffer>
147 buffer(data);
148
149 return internal::SerializationBuffer<Archive, void, Allocator, decltype(buffer)>{std::move(buffer)};
150}
151
152/// @brief Serializes and deserializes an object using [`cereal`](https://uscilab.github.io/cereal/).
153/// If the input object is an rvalue reference, the result of deserialization is returned by the surrounding
154/// communication call. If the input object is an lvalue reference, the input object is modified in place.
155/// @tparam OutArchive Type of the archive to use for serialization (see
156/// https://uscilab.github.io/cereal/serialization_archives.html). Default is `cereal::BinaryOutputArchive`.
157/// @tparam InArchive Type of the archive to use for deserialization (see
158/// https://uscilab.github.io/cereal/serialization_archives.html). Default is `cereal::BinaryInputArchive`.
159/// @tparam Allocator Type of the allocator to use for the buffer holding the serialized data. Default is
160/// `std::allocator<char>`.
161/// @tparam T Type of the object to serialize.
162template <
163 typename OutArchive = cereal::BinaryOutputArchive,
164 typename InArchive = cereal::BinaryInputArchive,
165 typename Allocator = std::allocator<char>,
166 typename T>
167auto as_serialized(T&& data) {
168 if constexpr (std::is_rvalue_reference_v<T&&>) {
169 internal::GenericDataBuffer<
170 std::remove_reference_t<T>,
173 internal::BufferModifiability::modifiable,
174 internal::BufferOwnership::owning,
175 internal::BufferType::in_out_buffer>
176 buffer(data);
177 return internal::SerializationBuffer<OutArchive, InArchive, Allocator, decltype(buffer)>{std::move(buffer)};
178 } else {
179 internal::GenericDataBuffer<
180 std::remove_reference_t<T>,
183 internal::BufferModifiability::modifiable,
184 internal::BufferOwnership::referencing,
185 internal::BufferType::in_out_buffer>
186 buffer(data);
187 return internal::SerializationBuffer<OutArchive, InArchive, Allocator, decltype(buffer)>{std::move(buffer)};
188 }
189}
190
191/// @brief Deserializes the received data using [`cereal`](https://uscilab.github.io/cereal/) and returns it in the
192/// result of the surrounding communication call.
193/// @tparam T Type to deserialize into.
194/// @tparam Archive Type of the archive to use for deserialization (see
195/// https://uscilab.github.io/cereal/serialization_archives.html). Default is `cereal::BinaryInputArchive`.
196/// @tparam Allocator Type of the allocator to use for the buffer holding the serialized data. Default is
197/// `std::allocator<char>`.
198template <typename T, typename Archive = cereal::BinaryInputArchive, typename Allocator = std::allocator<char>>
199auto as_deserializable() {
200 internal::GenericDataBuffer<
201 T,
204 internal::BufferModifiability::modifiable,
205 internal::BufferOwnership::owning,
206 internal::BufferType::out_buffer>
207 buffer{T{}};
208 return internal::SerializationBuffer<void, Archive, Allocator, decltype(buffer)>{std::move(buffer)};
209}
210
211/// @brief Deserializes the received data using [`cereal`](https://uscilab.github.io/cereal/) into the input object.
212/// If the input object is an rvalue reference, the result of deserialization is returned by the surrounding
213/// communication call. If the input object is an lvalue reference, the input object is modified in place.
214/// @tparam Archive Type of the archive to use for deserialization (see
215/// https://uscilab.github.io/cereal/serialization_archives.html). Default is `cereal::BinaryInputArchive`.
216/// @tparam Allocator Type of the allocator to use for the buffer holding the serialized data. Default is
217/// `std::allocator<char>`.
218/// @tparam T Type to deserialize into.
219template <typename Archive = cereal::BinaryInputArchive, typename Allocator = std::allocator<char>, typename T>
220auto as_deserializable(T&& object) {
221 if constexpr (std::is_rvalue_reference_v<T&&>) {
222 internal::GenericDataBuffer<
223 std::remove_reference_t<T>,
226 internal::BufferModifiability::modifiable,
227 internal::BufferOwnership::owning,
228 internal::BufferType::out_buffer>
229 buffer(std::move(object));
230 return internal::SerializationBuffer<void, Archive, Allocator, decltype(buffer)>(std::move(buffer));
231 } else {
232 internal::GenericDataBuffer<
233 std::remove_reference_t<T>,
236 internal::BufferModifiability::modifiable,
237 internal::BufferOwnership::referencing,
238 internal::BufferType::out_buffer>
239 buffer(object);
240 return internal::SerializationBuffer<void, Archive, Allocator, decltype(buffer)>(std::move(buffer));
241 }
242}
243#endif
244
245} // namespace kamping
STL-compatible allocator for requesting memory using the builtin MPI allocator.
Definition allocator.hpp:32
ParameterType
Each input parameter to one of the MPI calls wrapped by KaMPIng needs to has one of the following tag...
Definition named_parameter_types.hpp:33
constexpr bool is_serialization_buffer_v
Type trait to check if a type is a serialization buffer.
Definition serialization.hpp:114
constexpr bool is_serialization_buffer_v_impl
Type trait to check if a type is a serialization buffer.
Definition serialization.hpp:105
auto deserialization_repack(BufferType buffer)
If serialization_used is true, this takes a received serialization buffer, deserializes the data and ...
Definition serialization.hpp:121
BufferType
Enum to specify whether a buffer is an in buffer of an out buffer. Out buffer will be used to directl...
Definition data_buffer.hpp:287
STL namespace.
Tag type to identify serialization support.
Definition serialization.hpp:101