Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unique ptr serialization #1496

Closed
wants to merge 10 commits into from
72 changes: 36 additions & 36 deletions hpx/runtime/serialization/detail/pointer.hpp
Expand Up @@ -42,8 +42,7 @@ namespace hpx { namespace serialization

struct intrusive_polymorphic
{
static void call(input_archive& ar,
Pointer& ptr, boost::uint64_t pos)
static Pointer call(input_archive& ar, Pointer& ptr)
{
std::string name;
ar >> name;
Expand All @@ -53,49 +52,28 @@ namespace hpx { namespace serialization
create<referred_type>(name)
);
ar >> *t;
register_pointer(
ar
, pos
, ptr_helper_ptr(
new detail::erase_ptr_helper<Pointer>(std::move(t), ptr)
)
);
return t;
}
};

struct nonintrusive_polymorphic
{
static void call(input_archive& ar,
Pointer& ptr, boost::uint64_t pos)
static Pointer call(input_archive& ar, Pointer& ptr)
{
Pointer t (
polymorphic_nonintrusive_factory::instance().load<referred_type>(ar)
);
register_pointer(
ar
, pos
, ptr_helper_ptr(
new detail::erase_ptr_helper<Pointer>(std::move(t), ptr)
)
);
return t;
}
};

struct usual
{
static void call(input_archive& ar,
Pointer& ptr, boost::uint64_t pos)
static Pointer call(input_archive& ar, Pointer& ptr)
{
//referred_type t;
Pointer t(new referred_type);
ar >> *t;
register_pointer(
ar
, pos
, ptr_helper_ptr(
new detail::erase_ptr_helper<Pointer>(std::move(t), ptr)
)
);
return t;
}
};

Expand All @@ -118,8 +96,7 @@ namespace hpx { namespace serialization

struct intrusive_polymorphic
{
static void call(output_archive& ar,
Pointer& ptr)
static void call(output_archive& ar, const Pointer& ptr)
{
const std::string name = access::get_name(ptr.get());
ar << name;
Expand All @@ -129,8 +106,7 @@ namespace hpx { namespace serialization

struct usual
{
static void call(output_archive& ar,
Pointer& ptr)
static void call(output_archive& ar, const Pointer& ptr)
{
ar << *ptr;
}
Expand All @@ -146,7 +122,7 @@ namespace hpx { namespace serialization

// forwarded serialize pointer functions
template <typename Pointer> BOOST_FORCEINLINE
void serialize_pointer(output_archive & ar, Pointer ptr, unsigned)
void serialize_pointer_tracked(output_archive & ar, const Pointer& ptr, unsigned)
{
bool valid = static_cast<bool>(ptr);
ar << valid;
Expand All @@ -164,11 +140,10 @@ namespace hpx { namespace serialization
}

template <class Pointer> BOOST_FORCEINLINE
void serialize_pointer(input_archive& ar, Pointer& ptr, unsigned)
void serialize_pointer_tracked(input_archive& ar, Pointer& ptr, unsigned)
{
bool valid = false;
ar >> valid;

if(valid)
{
boost::uint64_t pos = 0;
Expand All @@ -177,7 +152,10 @@ namespace hpx { namespace serialization
{
pos = 0;
ar >> pos;
detail::pointer_input_dispatcher<Pointer>::type::call(ar, ptr, pos);
Pointer temp = detail::pointer_input_dispatcher<
Pointer>::type::call(ar, ptr);
register_pointer(ar, pos, ptr_helper_ptr(
new detail::erase_ptr_helper<Pointer>(std::move(temp), ptr)));
}
else
{
Expand All @@ -188,6 +166,28 @@ namespace hpx { namespace serialization
}
}

template <typename Pointer> BOOST_FORCEINLINE
void serialize_pointer_untracked(output_archive & ar, const Pointer& ptr, unsigned)
{
bool valid = static_cast<bool>(ptr);
ar << valid;
if(valid)
{
detail::pointer_output_dispatcher<Pointer>::type::call(ar, ptr);
}
}

template <class Pointer> BOOST_FORCEINLINE
void serialize_pointer_untracked(input_archive& ar, Pointer& ptr, unsigned)
{
bool valid = false;
ar >> valid;
if(valid)
{
ptr = detail::pointer_input_dispatcher<Pointer>::type::call(ar, ptr);
}
}

} // detail
}}

Expand Down
11 changes: 7 additions & 4 deletions hpx/runtime/serialization/intrusive_ptr.hpp
Expand Up @@ -13,16 +13,19 @@
namespace hpx { namespace serialization
{
template <typename T>
void serialize(input_archive & ar, boost::intrusive_ptr<T> & ptr, unsigned n)
void load(input_archive & ar, boost::intrusive_ptr<T> & ptr, unsigned n)
{
detail::serialize_pointer(ar, ptr, n);
detail::serialize_pointer_tracked(ar, ptr, n);
}

template <typename T>
void serialize(output_archive & ar, boost::intrusive_ptr<T> ptr, unsigned n)
void save(output_archive & ar, const boost::intrusive_ptr<T>& ptr, unsigned n)
{
detail::serialize_pointer(ar, ptr, n);
detail::serialize_pointer_tracked(ar, ptr, n);
}

HPX_SERIALIZATION_SPLIT_FREE_TEMPLATE((template <class T>),
(boost::intrusive_ptr<T>));
}}

#endif
4 changes: 2 additions & 2 deletions hpx/runtime/serialization/raw_ptr.hpp
Expand Up @@ -53,13 +53,13 @@ namespace hpx { namespace serialization

void serialize(output_archive& ar, unsigned n) const
{
serialize_pointer(ar, raw_ptr_type<T>(t), n);
serialize_pointer_tracked(ar, raw_ptr_type<T>(t), n);
}

void serialize(input_archive& ar, unsigned n)
{
raw_ptr_type<T> ptr(t);
serialize_pointer(ar, ptr, n);
serialize_pointer_tracked(ar, ptr, n);
t = ptr.get();
}

Expand Down
18 changes: 18 additions & 0 deletions hpx/runtime/serialization/serialization_fwd.hpp
Expand Up @@ -8,6 +8,7 @@
#define HPX_SERIALIZATION_FWD_HPP

#include <hpx/config.hpp>
#include <hpx/util/detail/pp_strip_parens.hpp>

#if defined(HPX_INTEL_VERSION) && ((__GNUC__ == 4 && __GNUC_MINOR__ == 4) || HPX_INTEL_VERSION < 1400)
#include <boost/shared_ptr.hpp>
Expand Down Expand Up @@ -75,5 +76,22 @@ namespace hpx { namespace serialization
save(ar, const_cast<boost::add_const<T>::type &>(t), 0); \
} \
/**/
#define HPX_SERIALIZATION_SPLIT_FREE_TEMPLATE(TEMPLATE, ARGS) \
HPX_UTIL_STRIP(TEMPLATE) \
BOOST_FORCEINLINE \
void serialize(hpx::serialization::input_archive & ar, \
HPX_UTIL_STRIP(ARGS) & t, unsigned) \
{ \
load(ar, t, 0); \
} \
HPX_UTIL_STRIP(TEMPLATE) \
BOOST_FORCEINLINE \
void serialize(hpx::serialization::output_archive & ar, \
HPX_UTIL_STRIP(ARGS) & t, unsigned) \
{ \
save(ar, const_cast<typename boost::add_const \
<HPX_UTIL_STRIP(ARGS)>::type &>(t), 0); \
} \
/**/

#endif // HPX_SERIALIZATION_FWD_HPP
11 changes: 7 additions & 4 deletions hpx/runtime/serialization/shared_ptr.hpp
Expand Up @@ -13,16 +13,19 @@
namespace hpx { namespace serialization
{
template <typename T>
void serialize(input_archive & ar, boost::shared_ptr<T> & ptr, unsigned n)
void load(input_archive & ar, boost::shared_ptr<T> & ptr, unsigned n)
{
detail::serialize_pointer(ar, ptr, n);
detail::serialize_pointer_tracked(ar, ptr, n);
}

template <typename T>
void serialize(output_archive & ar, boost::shared_ptr<T> ptr, unsigned n)
void save(output_archive & ar, const boost::shared_ptr<T>& ptr, unsigned n)
{
detail::serialize_pointer(ar, ptr, n);
detail::serialize_pointer_tracked(ar, ptr, n);
}

HPX_SERIALIZATION_SPLIT_FREE_TEMPLATE((template <class T>),
(boost::shared_ptr<T>));
}}

#endif
97 changes: 97 additions & 0 deletions hpx/runtime/serialization/variant.hpp
@@ -0,0 +1,97 @@
// Copyright (c) 2015 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_VARIANT_HPP
#define HPX_SERIALIZATION_VARIANT_HPP

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

#include <boost/variant.hpp>

namespace hpx { namespace serialization
{
namespace detail
{
struct variant_save_visitor: boost::static_visitor<>
{
variant_save_visitor(output_archive& ar)
: ar(ar)
{}

template <class T>
void operator()(const T& value) const
{
ar << value;
}

private:
output_archive& ar;
};

template <class... Args>
struct load_helper_t{};

// overload for non-variadic version of variant library
template <class Variant, class... Tail>
BOOST_FORCEINLINE void load_helper(input_archive&, Variant&,
int, load_helper_t<boost::detail::variant::void_, Tail...>)
{
HPX_ASSERT(false);
}

// overload for variadic version of variant library
template <class Variant>
BOOST_FORCEINLINE void load_helper(input_archive&, Variant&,
int, load_helper_t<>)
{
HPX_ASSERT(false);
}

template <class Variant, class Head, class... Tail>
BOOST_FORCEINLINE void load_helper(input_archive& ar, Variant& var,
int which, load_helper_t<Head, Tail...>)
{
if (which == 0)
{
Head value; // default ctor concept
ar >> value;
var = value;
}
else
{
load_helper(ar, var, which - 1, load_helper_t<Tail...>());
}
}
}

template <class... Args>
void save(output_archive& ar, const boost::variant<Args...>& variant, unsigned)
{
int which = variant.which();
ar << which;
detail::variant_save_visitor visitor(ar);
variant.apply_visitor(visitor);
}

template <class... Args>
void load(input_archive& ar, boost::variant<Args...>& variant, unsigned)
{
int which;
ar >> which;
if (static_cast<std::size_t>(which) >= sizeof...(Args))
{
HPX_THROW_EXCEPTION(serialization_error
, "load variant"
, "which of loaded variant is greater then saved one");
}

detail::load_helper(ar, variant, which, detail::load_helper_t<Args...>());
}

HPX_SERIALIZATION_SPLIT_FREE_TEMPLATE((template <class... Args>),
(boost::variant<Args...>));
}}

#endif
1 change: 1 addition & 0 deletions tests/unit/serialization/CMakeLists.txt
Expand Up @@ -8,6 +8,7 @@ set(tests
serialization_builtins
serialization_smart_ptr
serialization_vector
serialization_variant
serialize_buffer
zero_copy_serialization
)
Expand Down
23 changes: 23 additions & 0 deletions tests/unit/serialization/serialization_smart_ptr.cpp
Expand Up @@ -5,6 +5,7 @@

#include <hpx/runtime/serialization/serialize.hpp>
#include <hpx/runtime/serialization/shared_ptr.hpp>
#include <hpx/runtime/serialization/unique_ptr.hpp>
#include <hpx/runtime/serialization/intrusive_ptr.hpp>

#include <hpx/runtime/serialization/input_archive.hpp>
Expand Down Expand Up @@ -34,6 +35,27 @@ void test_shared()
HPX_TEST_EQ(*op2, *ip);
}

void test_unique()
{
std::unique_ptr<int> ip(new int(7));
std::unique_ptr<int> op1;
std::unique_ptr<int> op2;
{
std::vector<char> buffer;
hpx::serialization::output_archive oarchive(buffer);
oarchive << ip << ip;

hpx::serialization::input_archive iarchive(buffer);
iarchive >> op1;
iarchive >> op2;
}
HPX_TEST_NEQ(op1.get(), ip.get());
HPX_TEST_NEQ(op2.get(), ip.get());
HPX_TEST_NEQ(op1.get(), op2.get()); //untracked
HPX_TEST_EQ(*op1, *ip);
HPX_TEST_EQ(*op2, *ip);
}

struct A
{
A() : i(7), count(0) {}
Expand Down Expand Up @@ -90,6 +112,7 @@ void test_intrusive()
int main()
{
test_shared();
test_unique();
test_intrusive();

return hpx::util::report_errors();
Expand Down