KaMPIng 0.1.0
(Near) zero-overhead C++ MPI bindings.
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#include "cereal/archives/binary.hpp"
22
23namespace kamping {
24namespace internal {
25
26/// @brief Buffer holding serialized data.
27///
28/// This uses [`cereal`](https://uscilab.github.io/cereal/) to serialize and deserialize objects.
29///
30/// @tparam OutArchive Type of the archive to use for serialization.
31/// @tparam InArchive Type of the archive to use for deserialization.
32/// @tparam Allocator Type of the allocator to use for the buffer holding the serialized data.
33/// @tparam DataBufferType Type of the \ref GenericDataBuffer holding the data to serialize/deserialize into.
34template <typename OutArchive, typename InArchive, typename Allocator, typename DataBufferType>
36private:
37 std::basic_string<char, std::char_traits<char>, Allocator> _data; ///< Buffer holding the serialized data.
38 DataBufferType _object; ///< Object to de/serialize encapsulated in a \ref GenericDataBuffer.
39
40public:
41 using data_type =
42 typename DataBufferType::value_type; ///< Type of the encapsulated object to serialize/deserialize.
43
44 /// @brief Construct a serialization buffer from a \ref GenericDataBuffer containing the object to
45 /// serialize/deserialize into.
46 SerializationBuffer(DataBufferType&& object) : _data(), _object(std::move(object)) {}
47
48 /// @brief Serialize the object into the character buffer stored internally.
49 void serialize() {
50 std::basic_stringstream<char, std::char_traits<char>, Allocator> buffer;
51 {
53 archive(_object.underlying());
54 }
55 _data = buffer.str();
56 }
57
58 /// @brief Extract the \ref GenericDataBuffer containing the encapsulated object.
59 DataBufferType extract() && {
60 return std::move(_object);
61 }
62
63 /// @brief Deserialize from the character buffer stored internally into the encapsulated object.
64 void deserialize() {
65 std::istringstream buffer(std::string(_data.begin(), _data.end()));
66 {
68 archive(_object.underlying());
69 }
70 }
71
72 using value_type = char; ///< Type of the elements in the buffer.
73
74 /// @brief Access the underlying buffer.
75 char* data() noexcept {
76 return _data.data();
77 }
78
79 /// @brief Access the underlying buffer.
80 char const* data() const noexcept {
81 return _data.data();
82 }
83
84 /// @brief Resize the underlying buffer.
85 /// @param size New size of the buffer.
86 void resize(size_t size) {
87 _data.resize(size);
88 }
89
90 /// @brief Access the size of the underlying buffer.
91 size_t size() const {
92 return _data.size();
93 }
94};
95
96/// @brief Tag type to identify serialization support.
98
99/// @brief Type trait to check if a type is a serialization buffer.
100template <typename>
101constexpr bool is_serialization_buffer_v_impl = false;
102
103/// @brief Type trait to check if a type is a serialization buffer.
104template <typename... Args>
106
107/// @brief Type trait to check if a type is a serialization buffer.
108template <typename T>
111
112/// @brief If \p serialization_used is true, this takes a received serialization buffer, deserializes the data and
113/// repacks it into a new buffer only containing the deserialized data
114/// If \p serialization_used is false, the input buffer is returned unchanged.
115template <bool serialization_used, typename BufferType>
117 if constexpr (serialization_used) {
118 auto serialization_data = buffer.extract();
119 serialization_data.deserialize();
120 return std::move(serialization_data).extract();
121 } else {
122 return buffer;
123 }
124}
125} // namespace internal
126
127/// @brief Serializes an object using [`cereal`](https://uscilab.github.io/cereal/).
128/// @tparam Archive Type of the archive to use for serialization (see
129/// https://uscilab.github.io/cereal/serialization_archives.html). Default is `cereal::BinaryOutputArchive`.
130/// @tparam Allocator Type of the allocator to use for the buffer holding the serialized data. Default is
131/// `std::allocator<char>`.
132/// @tparam T Type of the object to serialize.
133template <typename Archive = cereal::BinaryOutputArchive, typename Allocator = std::allocator<char>, typename T>
134auto as_serialized(T const& data) {
135 internal::GenericDataBuffer<
136 T,
139 internal::BufferModifiability::constant,
140 internal::BufferOwnership::referencing,
141 internal::BufferType::in_buffer>
142 buffer(data);
143
144 return internal::SerializationBuffer<Archive, void, Allocator, decltype(buffer)>{std::move(buffer)};
145}
146
147/// @brief Serializes and deserializes an object using [`cereal`](https://uscilab.github.io/cereal/).
148/// If the input object is an rvalue reference, the result of deserialization is returned by the surrounding
149/// communication call. If the input object is an lvalue reference, the input object is modified in place.
150/// @tparam OutArchive Type of the archive to use for serialization (see
151/// https://uscilab.github.io/cereal/serialization_archives.html). Default is `cereal::BinaryOutputArchive`.
152/// @tparam InArchive Type of the archive to use for deserialization (see
153/// https://uscilab.github.io/cereal/serialization_archives.html). Default is `cereal::BinaryInputArchive`.
154/// @tparam Allocator Type of the allocator to use for the buffer holding the serialized data. Default is
155/// `std::allocator<char>`.
156/// @tparam T Type of the object to serialize.
157template <
158 typename OutArchive = cereal::BinaryOutputArchive,
159 typename InArchive = cereal::BinaryInputArchive,
160 typename Allocator = std::allocator<char>,
161 typename T>
162auto as_serialized(T&& data) {
163 if constexpr (std::is_rvalue_reference_v<T&&>) {
164 internal::GenericDataBuffer<
165 std::remove_reference_t<T>,
168 internal::BufferModifiability::modifiable,
169 internal::BufferOwnership::owning,
170 internal::BufferType::in_out_buffer>
171 buffer(data);
172 return internal::SerializationBuffer<OutArchive, InArchive, Allocator, decltype(buffer)>{std::move(buffer)};
173 } else {
174 internal::GenericDataBuffer<
175 std::remove_reference_t<T>,
178 internal::BufferModifiability::modifiable,
179 internal::BufferOwnership::referencing,
180 internal::BufferType::in_out_buffer>
181 buffer(data);
182 return internal::SerializationBuffer<OutArchive, InArchive, Allocator, decltype(buffer)>{std::move(buffer)};
183 }
184}
185
186/// @brief Deserializes the received data using [`cereal`](https://uscilab.github.io/cereal/) and returns it in the
187/// result of the surrounding communication call.
188/// @tparam T Type to deserialize into.
189/// @tparam Archive Type of the archive to use for deserialization (see
190/// https://uscilab.github.io/cereal/serialization_archives.html). Default is `cereal::BinaryInputArchive`.
191/// @tparam Allocator Type of the allocator to use for the buffer holding the serialized data. Default is
192/// `std::allocator<char>`.
193template <typename T, typename Archive = cereal::BinaryInputArchive, typename Allocator = std::allocator<char>>
194auto as_deserializable() {
195 internal::GenericDataBuffer<
196 T,
199 internal::BufferModifiability::modifiable,
200 internal::BufferOwnership::owning,
201 internal::BufferType::out_buffer>
202 buffer{T{}};
203 return internal::SerializationBuffer<void, Archive, Allocator, decltype(buffer)>{std::move(buffer)};
204}
205
206/// @brief Deserializes the received data using [`cereal`](https://uscilab.github.io/cereal/) into the input object.
207/// If the input object is an rvalue reference, the result of deserialization is returned by the surrounding
208/// communication call. If the input object is an lvalue reference, the input object is modified in place.
209/// @tparam Archive Type of the archive to use for deserialization (see
210/// https://uscilab.github.io/cereal/serialization_archives.html). Default is `cereal::BinaryInputArchive`.
211/// @tparam Allocator Type of the allocator to use for the buffer holding the serialized data. Default is
212/// `std::allocator<char>`.
213/// @tparam T Type to deserialize into.
214template <typename Archive = cereal::BinaryInputArchive, typename Allocator = std::allocator<char>, typename T>
215auto as_deserializable(T&& object) {
216 if constexpr (std::is_rvalue_reference_v<T&&>) {
217 internal::GenericDataBuffer<
218 std::remove_reference_t<T>,
221 internal::BufferModifiability::modifiable,
222 internal::BufferOwnership::owning,
223 internal::BufferType::out_buffer>
224 buffer(std::move(object));
225 return internal::SerializationBuffer<void, Archive, Allocator, decltype(buffer)>(std::move(buffer));
226 } else {
227 internal::GenericDataBuffer<
228 std::remove_reference_t<T>,
231 internal::BufferModifiability::modifiable,
232 internal::BufferOwnership::referencing,
233 internal::BufferType::out_buffer>
234 buffer(object);
235 return internal::SerializationBuffer<void, Archive, Allocator, decltype(buffer)>(std::move(buffer));
236 }
237}
238
239} // namespace kamping
STL-compatible allocator for requesting memory using the builtin MPI allocator.
Definition allocator.hpp:32
Buffer holding serialized data.
Definition serialization.hpp:35
SerializationBuffer(DataBufferType &&object)
Construct a serialization buffer from a GenericDataBuffer containing the object to serialize/deserial...
Definition serialization.hpp:46
void resize(size_t size)
Resize the underlying buffer.
Definition serialization.hpp:86
void deserialize()
Deserialize from the character buffer stored internally into the encapsulated object.
Definition serialization.hpp:64
char * data() noexcept
Access the underlying buffer.
Definition serialization.hpp:75
DataBufferType extract() &&
Extract the GenericDataBuffer containing the encapsulated object.
Definition serialization.hpp:59
typename DataBufferType::value_type data_type
Type of the encapsulated object to serialize/deserialize.
Definition serialization.hpp:41
char const * data() const noexcept
Access the underlying buffer.
Definition serialization.hpp:80
size_t size() const
Access the size of the underlying buffer.
Definition serialization.hpp:91
void serialize()
Serialize the object into the character buffer stored internally.
Definition serialization.hpp:49
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:109
constexpr bool is_serialization_buffer_v_impl
Type trait to check if a type is a serialization buffer.
Definition serialization.hpp:101
auto deserialization_repack(BufferType buffer)
If serialization_used is true, this takes a received serialization buffer, deserializes the data and ...
Definition serialization.hpp:116
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:258
STL namespace.
Tag type to identify serialization support.
Definition serialization.hpp:97