Skip to content

Commit

Permalink
Serializing collections with non-default constructible data
Browse files Browse the repository at this point in the history
  • Loading branch information
AntonBikineev committed Aug 7, 2017
1 parent 248c03c commit 1b6b227
Show file tree
Hide file tree
Showing 7 changed files with 403 additions and 88 deletions.
13 changes: 3 additions & 10 deletions hpx/runtime/serialization/deque.hpp
Expand Up @@ -7,6 +7,7 @@
#define HPX_SERIALIZATION_DEQUE_HPP

#include <hpx/runtime/serialization/serialize.hpp>
#include <hpx/runtime/serialization/detail/serialize_collection.hpp>

#include <cstdint>
#include <deque>
Expand All @@ -19,14 +20,9 @@ namespace hpx { namespace serialization
// normal load ...
std::uint64_t size;
ar >> size; //-V128

d.resize(size);
if(size == 0) return;

for(auto & e: d)
{
ar >> e;
}
detail::load_collection(ar, d, size);
}

template <typename T, typename Allocator>
Expand All @@ -37,10 +33,7 @@ namespace hpx { namespace serialization
ar << size;
if(d.empty()) return;

for(auto const & e: d)
{
ar << e;
}
detail::save_collection(ar, d);
}
}}

Expand Down
122 changes: 122 additions & 0 deletions hpx/runtime/serialization/detail/serialize_collection.hpp
@@ -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
13 changes: 3 additions & 10 deletions hpx/runtime/serialization/list.hpp
Expand Up @@ -7,6 +7,7 @@
#define HPX_SERIALIZATION_LIST_HPP

#include <hpx/runtime/serialization/serialize.hpp>
#include <hpx/runtime/serialization/detail/serialize_collection.hpp>

#include <cstdint>
#include <list>
Expand All @@ -19,14 +20,9 @@ namespace hpx { namespace serialization
// normal load ...
std::uint64_t size;
ar >> size; //-V128

ls.resize(size);
if(size == 0) return;

for(auto & li: ls)
{
ar >> li;
}
detail::load_collection(ar, ls, size);
}

template <typename T, typename Allocator>
Expand All @@ -37,10 +33,7 @@ namespace hpx { namespace serialization
ar << size;
if(ls.empty()) return;

for(auto const & li: ls)
{
ar << li;
}
detail::save_collection(ar, ls);
}
}}

Expand Down
44 changes: 17 additions & 27 deletions hpx/runtime/serialization/vector.hpp
Expand Up @@ -9,6 +9,7 @@
#include <hpx/config.hpp>
#include <hpx/runtime/serialization/array.hpp>
#include <hpx/runtime/serialization/serialize.hpp>
#include <hpx/runtime/serialization/detail/serialize_collection.hpp>
#include <hpx/traits/is_bitwise_serializable.hpp>

#include <cstddef>
Expand All @@ -30,12 +31,7 @@ namespace hpx { namespace serialization
ar >> size; //-V128
if (size == 0) return;

if (vs.size() < size)
vs.resize(size);
for(std::size_t i = 0; i != size; ++i)
{
ar >> vs[i];
}
detail::load_collection(ar, vs, size);
}

template <typename T, typename Allocator>
Expand All @@ -45,18 +41,17 @@ namespace hpx { namespace serialization
if(ar.disable_array_optimization())
{
load_impl(ar, v, std::false_type());
return;
}
else
{
// bitwise load ...
std::uint64_t size;
ar >> size; //-V128
if(size == 0) return;

if (v.size() < size)
v.resize(size);
ar >> hpx::serialization::make_array(v.data(), v.size());
}

// bitwise load ...
std::uint64_t size;
ar >> size; //-V128
if(size == 0) return;

if (v.size() < size)
v.resize(size);
ar >> hpx::serialization::make_array(v.data(), v.size());
}
}

Expand Down Expand Up @@ -101,11 +96,7 @@ namespace hpx { namespace serialization
std::false_type)
{
// normal save ...
typedef typename std::vector<T, Allocator>::value_type value_type;
for(const value_type & v : vs)
{
ar << v;
}
detail::save_collection(ar, vs);
}

template <typename T, typename Allocator>
Expand All @@ -115,12 +106,11 @@ namespace hpx { namespace serialization
if(ar.disable_array_optimization())
{
save_impl(ar, v, std::false_type());
return;
}
else
{
// bitwise (zero-copy) save ...
ar << hpx::serialization::make_array(v.data(), v.size());
}

// bitwise (zero-copy) save ...
ar << hpx::serialization::make_array(v.data(), v.size());
}
}

Expand Down

0 comments on commit 1b6b227

Please sign in to comment.