Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Serializing collections with non-default constructible data
- Loading branch information
1 parent
248c03c
commit 1b6b227
Showing
7 changed files
with
403 additions
and
88 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
122 changes: 122 additions & 0 deletions
122
hpx/runtime/serialization/detail/serialize_collection.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
// Copyright (c) 2017 Anton Bikineev | ||
// | ||
// Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
#ifndef HPX_SERIALIZATION_DETAIL_SERIALIZE_COLLECTION_HPP | ||
#define HPX_SERIALIZATION_DETAIL_SERIALIZE_COLLECTION_HPP | ||
|
||
#include <hpx/config.hpp> | ||
|
||
#include <type_traits> | ||
|
||
namespace hpx { namespace serialization { namespace detail { | ||
|
||
// default fallbacks. in fact, they should never be called | ||
template <class Archive, class T> | ||
void save_construct_data(Archive&, T*, unsigned) | ||
{ | ||
} | ||
|
||
template <class Archive, class T> | ||
void load_construct_data(Archive&, T* t, unsigned) | ||
{ | ||
::new (t) T; | ||
} | ||
|
||
template <class Value> | ||
class save_collection_impl | ||
{ | ||
struct default_ | ||
{ | ||
template <class Archive, class Collection> | ||
static void call(Archive& ar, const Collection& collection) | ||
{ | ||
for (const auto& i: collection) | ||
ar << i; | ||
} | ||
}; | ||
|
||
struct non_default_ | ||
{ | ||
template <class Archive, class Collection> | ||
static void call(Archive& ar, const Collection& collection) | ||
{ | ||
// for non-default constructible types we also provide | ||
// a customization point to save any external data | ||
// (in the same way as Boost.Serialization does) | ||
for (const auto& i: collection) | ||
{ | ||
save_construct_data(ar, &i, 0); | ||
ar << i; | ||
} | ||
} | ||
}; | ||
|
||
public: | ||
using type = typename std::conditional< | ||
std::is_default_constructible<Value>::value, | ||
default_, non_default_>::type; | ||
}; | ||
|
||
template <class Value> | ||
class load_collection_impl | ||
{ | ||
struct default_ | ||
{ | ||
template <class Archive, class Collection> | ||
static void call(Archive& ar, Collection& collection, | ||
typename Collection::size_type size) | ||
{ | ||
collection.resize(size); | ||
for (auto& i: collection) | ||
ar >> i; | ||
} | ||
}; | ||
|
||
struct non_default_ | ||
{ | ||
template <class Archive, class Collection> | ||
static void call(Archive& ar, Collection& collection, | ||
typename Collection::size_type size) | ||
{ | ||
using value_type = typename Collection::value_type; | ||
using storage_type = std::aligned_storage< | ||
sizeof(value_type), alignof(value_type)>; | ||
|
||
collection.clear(); | ||
while (size-- > 0) | ||
{ | ||
storage_type storage; | ||
value_type& ref = reinterpret_cast<value_type&>(storage); | ||
load_construct_data(ar, &ref, 0); | ||
ar >> ref; | ||
collection.push_back(ref); | ||
} | ||
} | ||
}; | ||
|
||
public: | ||
using type = typename std::conditional< | ||
std::is_default_constructible<Value>::value, | ||
default_, non_default_>::type; | ||
}; | ||
|
||
template <class Archive, class Collection> | ||
void save_collection(Archive& ar, const Collection& collection) | ||
{ | ||
using value_type = typename Collection::value_type; | ||
save_collection_impl<value_type>::type::call(ar, collection); | ||
} | ||
|
||
template <class Archive, class Collection> | ||
void load_collection(Archive& ar, Collection& collection, | ||
typename Collection::size_type size) | ||
{ | ||
using value_type = typename Collection::value_type; | ||
load_collection_impl<value_type>::type::call(ar, collection, size); | ||
} | ||
|
||
}}} // hpx::serialization::detail | ||
|
||
#endif // HPX_SERIALIZATION_DETAIL_SERIALIZE_COLLECTION_HPP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.