ttg 1.0.0
Template Task Graph (TTG): flowgraph-based programming model for high-performance distributed-memory algorithms
Loading...
Searching...
No Matches
archive.h
Go to the documentation of this file.
1// SPDX-License-Identifier: BSD-3-Clause
2//
3// Created by Eduard Valeyev on 5/17/21.
4//
5
6#ifndef TTG_SERIALIZATION_BACKENDS_BOOST_ARCHIVE_H
7#define TTG_SERIALIZATION_BACKENDS_BOOST_ARCHIVE_H
8
9#include <boost/archive/binary_iarchive.hpp>
10#include <boost/archive/binary_oarchive.hpp>
11#include <boost/iostreams/device/array.hpp>
12#include <boost/iostreams/stream.hpp>
13
14// explicitly instantiate for this type of binary stream
15#include <boost/archive/impl/basic_binary_iarchive.ipp>
16#include <boost/archive/impl/basic_binary_iprimitive.ipp>
17#include <boost/archive/impl/basic_binary_oarchive.ipp>
18#include <boost/archive/impl/basic_binary_oprimitive.ipp>
19
20namespace ttg::detail {
21
22 // used to serialize data only
23 template <typename Archive, typename T>
24 void oarchive_save_override_optimized_dispatch(Archive& ar, const T& t) {
25 if constexpr (boost::is_array<T>::value) {
26 boost::archive::detail::save_array_type<Archive>::invoke(ar, t);
27 return;
28 } else if constexpr (boost::is_enum<T>::value) {
29 boost::archive::detail::save_enum_type<Archive>::invoke(ar, t);
30 return;
31 } else {
32 std::conditional_t<boost::is_pointer<T>::value, T, std::add_pointer_t<const T>> tptr;
33 if constexpr (boost::is_pointer<T>::value) {
34 static_assert(!std::is_polymorphic_v<T>,
35 "oarchive_save_override does not support serialization of polymorphic types");
36 tptr = t;
37 } else
38 tptr = &t;
39 if constexpr (boost::mpl::equal_to<boost::serialization::implementation_level<T>,
40 boost::mpl::int_<boost::serialization::primitive_type>>::value) {
41 boost::archive::detail::save_non_pointer_type<Archive>::save_primitive::invoke(ar, *tptr);
42 } else
43 boost::archive::detail::save_non_pointer_type<Archive>::save_only::invoke(ar, *tptr);
44 }
45 }
46
47 // used to serialize data only
48 template <typename Archive, typename T>
50 if constexpr (boost::is_array<T>::value) {
51 boost::archive::detail::load_array_type<Archive>::invoke(ar, t);
52 return;
53 } else if constexpr (boost::is_enum<T>::value) {
54 boost::archive::detail::load_enum_type<Archive>::invoke(ar, t);
55 return;
56 } else {
57 std::conditional_t<boost::is_pointer<T>::value, T, std::add_pointer_t<T>> tptr;
58 if constexpr (boost::is_pointer<T>::value) {
59 static_assert(!std::is_polymorphic_v<T>,
60 "iarchive_load_override_optimized_dispatch does not support serialization of polymorphic types");
61 using Value = std::remove_pointer_t<T>;
62 std::allocator<Value> alloc; // instead use the allocator associated with the archive?
63 auto* buf = alloc.allocate(sizeof(Value));
64 t = new (buf) Value;
65 tptr = t;
66 } else
67 tptr = &t;
68 if constexpr (boost::mpl::equal_to<boost::serialization::implementation_level<T>,
69 boost::mpl::int_<boost::serialization::primitive_type>>::value) {
70 boost::archive::detail::load_non_pointer_type<Archive>::load_primitive::invoke(ar, *tptr);
71 } else
72 boost::archive::detail::load_non_pointer_type<Archive>::load_only::invoke(ar, *tptr);
73 }
74 }
75
77
91 template <typename StreamOrStreambuf>
93 : private StreamOrStreambuf,
94 public boost::archive::binary_oarchive_impl<boost_optimized_oarchive<StreamOrStreambuf>,
95 std::ostream::char_type, std::ostream::traits_type> {
96 public:
97 using pbase_type = StreamOrStreambuf;
98 using base_type = boost::archive::binary_oarchive_impl<boost_optimized_oarchive<StreamOrStreambuf>,
99 std::ostream::char_type, std::ostream::traits_type>;
100 // if pbase_type is derived from std::streambuf can use this information to avoid virtual function calls and inline
101 static constexpr bool pbase_derived_from_stdstreambuf = std::is_base_of_v<std::streambuf, pbase_type>;
102
103 private:
105 friend class boost::archive::detail::common_oarchive<StreamOrStreambuf>;
106 friend base_type;
107
108 const auto& pbase() const { return static_cast<const pbase_type&>(*this); }
109 auto& pbase() { return static_cast<pbase_type&>(*this); }
110 const auto& base() const { return static_cast<const base_type&>(*this); }
111 auto& base() { return static_cast<base_type&>(*this); }
112
113 public:
115 : pbase_type{}, base_type(this->pbase(), boost::archive::no_header | boost::archive::no_codecvt){};
116
117 boost_optimized_oarchive(StreamOrStreambuf sbuf)
118 : pbase_type(std::move(sbuf))
119 , base_type(this->pbase(), boost::archive::no_header | boost::archive::no_codecvt){};
120
121 template <typename Arg>
123 : pbase_type(std::forward<Arg>(arg))
124 , base_type(this->pbase(), boost::archive::no_header | boost::archive::no_codecvt){};
125
128
129 template <class T>
130 void save_override(const T& t) {
132 }
133
134 void save_override(const boost::archive::class_id_optional_type& /* t */) {}
135
136 void save_override(const boost::archive::version_type& t) {}
137 void save_override(const boost::serialization::item_version_type& t) {}
138
139 void save_override(const boost::archive::class_id_type& t) {}
140 void save_override(const boost::archive::class_id_reference_type& t) {}
141
143
144 void save_object(const void* x, const boost::archive::detail::basic_oserializer& bos) { abort(); }
145
148
149 // default saving of primitives.
150 template<class T>
151 void save(const T & t)
152 {
153 save_binary(& t, sizeof(T));
154 }
155
156 // trap usage of invalid uninitialized boolean which would
157 // otherwise crash on load.
158 void save(const bool t){
159 BOOST_ASSERT(0 == static_cast<int>(t) || 1 == static_cast<int>(t));
160 save_binary(& t, sizeof(t));
161 }
162
163 public:
164
165 // the optimized save_array dispatches to save_binary
166 template <class ValueType>
167 void save_array(boost::serialization::array_wrapper<ValueType> const& a, unsigned int)
168 {
169 save_binary(a.address(),a.count()*sizeof(ValueType));
170 }
171
172 void save_binary(const void *address, std::size_t count) {
173 if constexpr (pbase_derived_from_stdstreambuf) { // if we were given a streambuf use it directly ...
174 using Elem = std::ostream::char_type;
175 static_assert(sizeof(Elem) == 1);
176 count = (count + sizeof(Elem) - 1) / sizeof(Elem);
177 std::streamsize scount = static_cast<StreamOrStreambuf&>(this->pbase())
178 .sputn(static_cast<const Elem*>(address), static_cast<std::streamsize>(count));
179 assert(count == static_cast<std::size_t>(scount));
180 }
181 else { // ... else let boost::archive::basic_binary_oprimitive handle via std::stringbuf
182 // (and associated virtual function calls ... no inlining for you)
183 this->base().save_binary(address, count);
184 }
185 }
186
188
189 template <class T>
190 auto& operator<<(const T& t) {
191 this->save_override(t);
192 return *this;
193 }
194
195 // the & operator
196 template <class T>
197 auto& operator&(const T& t) {
198 return *this << t;
199 }
200
201 const auto& streambuf() const {
202 if constexpr (pbase_derived_from_stdstreambuf) {
203 return static_cast<const StreamOrStreambuf&>(this->pbase());
204 }
205 else {
206 return this->pbase();
207 }
208 }
209 const auto& stream() const { return this->pbase(); }
210 };
211
214
217
221
224
226
231 inline auto make_boost_buffer_oarchive(void* const buf, std::size_t size, std::size_t buf_offset = 0) {
232 assert(buf_offset <= size);
233 return ttg::detail::boost_byte_oarchive(ttg::detail::byte_ostreambuf(static_cast<char*>(buf) + buf_offset, size - buf_offset));
234 }
235
237
242 template <std::size_t N>
243 inline auto make_boost_buffer_oarchive(char (&buf)[N], std::size_t buf_offset = 0) {
244 assert(buf_offset <= N);
245 return ttg::detail::boost_byte_oarchive(ttg::detail::byte_ostreambuf(&(buf[buf_offset], N - buf_offset)));
246 }
247
249 template <typename StreamOrStreambuf>
251 : private StreamOrStreambuf,
252 public boost::archive::binary_iarchive_impl<boost_optimized_iarchive<StreamOrStreambuf>,
253 std::ostream::char_type, std::ostream::traits_type> {
254 public:
255 using pbase_type = StreamOrStreambuf;
256 using base_type = boost::archive::binary_iarchive_impl<boost_optimized_iarchive, std::ostream::char_type,
257 std::ostream::traits_type>;
258 // if pbase_type is derived from std::streambuf can use this information to avoid virtual function calls and inline
259 static constexpr bool pbase_derived_from_stdstreambuf = std::is_base_of_v<std::streambuf, pbase_type>;
260
261 private:
263 friend class boost::archive::detail::common_iarchive<boost_optimized_iarchive>;
264 friend base_type;
265
266 const auto& pbase() const { return static_cast<const pbase_type&>(*this); }
267 auto& pbase() { return static_cast<pbase_type&>(*this); }
268 const auto& base() const { return static_cast<const base_type&>(*this); }
269 auto& base() { return static_cast<base_type&>(*this); }
270
271 public:
273 : pbase_type{}, base_type(this->pbase(), boost::archive::no_header | boost::archive::no_codecvt){};
274
275 boost_optimized_iarchive(StreamOrStreambuf sbuf)
276 : pbase_type(std::move(sbuf))
277 , base_type(this->pbase(), boost::archive::no_header | boost::archive::no_codecvt){};
278
279 template <typename Arg>
281 : pbase_type(std::forward<Arg>(arg))
282 , base_type(this->pbase(), boost::archive::no_header | boost::archive::no_codecvt){};
283
286
287 template <class T>
291
292 void load_override(boost::archive::class_id_optional_type& /* t */) {}
293
294 void load_override(boost::archive::version_type& t) {}
295 void load_override(boost::serialization::item_version_type& t) {}
296
297 void load_override(boost::archive::class_id_type& t) {}
298 void load_override(boost::archive::class_id_reference_type& t) {}
299
301
302 void load_object(void* x, const boost::archive::detail::basic_oserializer& bos) { abort(); }
303
306
307 // main template for serialization of primitive types
308 template<class T>
309 void load(T & t){
310 load_binary(& t, sizeof(T));
311 }
312
314 // fundamental types that need special treatment
315
316 // trap usage of invalid uninitialized boolean
317 void load(bool & t){
318 load_binary(& t, sizeof(t));
319 int i = t;
320 BOOST_ASSERT(0 == i || 1 == i);
321 (void)i; // warning suppression for release builds.
322 }
323
324 public:
325
326 // the optimized load_array dispatches to load_binary
327 template <class ValueType>
328 void load_array(boost::serialization::array_wrapper<ValueType>& a, unsigned int)
329 {
330 load_binary(a.address(),a.count()*sizeof(ValueType));
331 }
332
334 void *address,
335 std::size_t count
336 ) {
337 if constexpr (pbase_derived_from_stdstreambuf) { // if we were given a streambuf use it directly ...
338 using Elem = std::ostream::char_type;
339 static_assert(sizeof(Elem) == 1);
340 std::streamsize s = static_cast<std::streamsize>(count);
341 std::streamsize scount = static_cast<StreamOrStreambuf&>(this->pbase()).sgetn(static_cast<Elem*>(address), s);
342 assert(scount == count);
343 }
344 else { // ... else let boost::archive::basic_binary_iprimitive handle via std::stringbuf
345 // (and associated virtual function calls ... no inlining for you)
346 this->base().load_binary(address, count);
347 }
348 }
349
351
352 template <class T>
353 auto& operator>>(T& t) {
354 this->load_override(t);
355 return *this;
356 }
357
358 // the & operator
359 template <class T>
360 auto& operator&(T& t) {
361 return *this >> t;
362 }
363
364 const auto& streambuf() const {
365 if constexpr (pbase_derived_from_stdstreambuf) {
366 return static_cast<const StreamOrStreambuf&>(this->pbase());
367 }
368 else {
369 return this->pbase();
370 }
371 }
372 const auto& stream() const { return this->pbase(); }
373 };
374
377
381
384
386
391 inline auto make_boost_buffer_iarchive(const void* const buf, std::size_t size, std::size_t buf_offset = 0) {
392 assert(buf_offset <= size);
393 return ttg::detail::boost_byte_iarchive(ttg::detail::byte_istreambuf(static_cast<const char*>(buf) + buf_offset, size - buf_offset));
394 }
395
397
402 template <std::size_t N>
403 inline auto make_boost_buffer_iarchive(const char (&buf)[N], std::size_t buf_offset = 0) {
404 assert(buf_offset <= N);
405 return ttg::detail::boost_byte_iarchive(ttg::detail::byte_istreambuf((&(buf[buf_offset]), N - buf_offset)));
406 }
407
408} // namespace ttg::detail
409
410// for some reason need to use array optimization for the base as well ... dispatch to optimized version in
411// array_wrapper.hpp:serializer(ar,version) for some reason uses Archive::base_type using apple clang 12.0.5.12050022
412#define BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION_FOR_THIS_AND_BASE(x) \
413 BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(x); \
414 BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(x::base_type);
415
430
431#undef BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION_FOR_THIS_AND_BASE
432
433#endif // TTG_SERIALIZATION_BACKENDS_BOOST_ARCHIVE_H
BOOST_SERIALIZATION_REGISTER_ARCHIVE(ttg::detail::boost_counting_oarchive)
#define BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION_FOR_THIS_AND_BASE(x)
Definition archive.h:412
optimized data-only deserializer for boost_optimized_oarchive
Definition archive.h:253
void load_override(boost::archive::class_id_type &t)
Definition archive.h:297
const auto & streambuf() const
Definition archive.h:364
void load_binary(void *address, std::size_t count)
Definition archive.h:333
boost::archive::binary_iarchive_impl< boost_optimized_iarchive, std::ostream::char_type, std::ostream::traits_type > base_type
Definition archive.h:257
void load_override(boost::archive::version_type &t)
Definition archive.h:294
void load_array(boost::serialization::array_wrapper< ValueType > &a, unsigned int)
Definition archive.h:328
boost_optimized_iarchive(StreamOrStreambuf sbuf)
Definition archive.h:275
void load_object(void *x, const boost::archive::detail::basic_oserializer &bos)
Definition archive.h:302
void load_override(boost::serialization::item_version_type &t)
Definition archive.h:295
void load_override(boost::archive::class_id_reference_type &t)
Definition archive.h:298
friend class boost::archive::save_access
Definition archive.h:262
void load_override(boost::archive::class_id_optional_type &)
Definition archive.h:292
static constexpr bool pbase_derived_from_stdstreambuf
Definition archive.h:259
optimized data-only serializer
Definition archive.h:95
void save_binary(const void *address, std::size_t count)
Definition archive.h:172
void save_override(const boost::archive::version_type &t)
Definition archive.h:136
static constexpr bool pbase_derived_from_stdstreambuf
Definition archive.h:101
void save_override(const boost::archive::class_id_reference_type &t)
Definition archive.h:140
void save_override(const boost::serialization::item_version_type &t)
Definition archive.h:137
void save_override(const boost::archive::class_id_type &t)
Definition archive.h:139
void save_override(const boost::archive::class_id_optional_type &)
Definition archive.h:134
boost_optimized_oarchive(StreamOrStreambuf sbuf)
Definition archive.h:117
const auto & streambuf() const
Definition archive.h:201
void save_object(const void *x, const boost::archive::detail::basic_oserializer &bos)
Definition archive.h:144
friend class boost::archive::save_access
Definition archive.h:104
boost::archive::binary_oarchive_impl< boost_optimized_oarchive< StreamOrStreambuf >, std::ostream::char_type, std::ostream::traits_type > base_type
Definition archive.h:99
void save_array(boost::serialization::array_wrapper< ValueType > const &a, unsigned int)
Definition archive.h:167
streambuf that writes bytes to a buffer in memory
Definition stream.h:102
streambuf that writes bytes to a buffer in memory
Definition stream.h:72
STL namespace.
void oarchive_save_override_optimized_dispatch(Archive &ar, const T &t)
Definition archive.h:24
auto make_boost_buffer_iarchive(const void *const buf, std::size_t size, std::size_t buf_offset=0)
constructs a boost_buffer_iarchive object
Definition archive.h:391
boost_optimized_oarchive< byte_ostreambuf > boost_byte_oarchive
an archive that constructs serialized representation of an object in a memory buffer,...
Definition archive.h:223
auto make_boost_buffer_oarchive(void *const buf, std::size_t size, std::size_t buf_offset=0)
constructs a boost_buffer_oarchive object
Definition archive.h:231
void iarchive_load_override_optimized_dispatch(Archive &ar, T &t)
Definition archive.h:49
boost_optimized_iarchive< byte_istreambuf > boost_byte_iarchive
the deserializer for boost_byte_oarchive
Definition archive.h:383
int size(World world=default_execution_context())
Definition run.h:131
void abort()
Aborts the TTG program using the default backend's ttg_abort method.
Definition run.h:104