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

Adding MPark's variant (V1.4.0) to HPX #4038

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions hpx/runtime/serialization/boost_variant.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// copyright (c) 2005
// troy d. straszheim <[email protected]>
// http://www.resophonic.com
// 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_BOOST_VARIANT_HPP
#define HPX_SERIALIZATION_BOOST_VARIANT_HPP

#include <hpx/config.hpp>
#include <hpx/runtime/serialization/serialization_fwd.hpp>
#include <hpx/errors.hpp>

#include <boost/variant.hpp>

#include <utility>

namespace hpx { namespace serialization
{
namespace detail {

struct variant_save_visitor : boost::static_visitor<>
{
variant_save_visitor(output_archive& ar)
: m_ar(ar)
{}

template <typename T>
void operator()(T const& value) const
{
m_ar << value;
}

private:
output_archive & m_ar;
};

template <typename ... Ts>
struct variant_impl;

template <typename T, typename ... Ts>
struct variant_impl<T, Ts...>
{
template <typename V>
static void load(input_archive& ar, std::size_t which, V& v)
{
if (which == 0)
{
// note: A non-intrusive implementation (such as this one)
// necessary has to copy the value. This wouldn't be necessary
// with an implementation that de-serialized to the address of the
// aligned storage included in the variant.
T value;
ar >> value;
v = std::move(value);
return;
}
variant_impl<Ts...>::load(ar, which - 1, v);
}
};

template <>
struct variant_impl<>
{
template <typename V>
static void load(
input_archive& /*ar*/, std::size_t /*which*/, V& /*v*/)
{
}
};
}

template <typename ... T>
void save(output_archive& ar, boost::variant<T...> const& v, unsigned)
{
std::size_t which = static_cast<std::size_t>(v.which());
ar << which;
detail::variant_save_visitor visitor(ar);
v.apply_visitor(visitor);
}

template <typename ... T>
void load(input_archive& ar, boost::variant<T...>& v, unsigned)
{
std::size_t which;
ar >> which;
if (which >= static_cast<int>(sizeof...(T)))
{
// this might happen if a type was removed from the list of variant
// types
HPX_THROW_EXCEPTION(serialization_error
, "load<Archive, Variant, version>"
, "type was removed from the list of variant types");
}
detail::variant_impl<T...>::load(ar, which, v);
}

HPX_SERIALIZATION_SPLIT_FREE_TEMPLATE(
(template<typename ... T>), (boost::variant<T...>));
}}

#endif // HPX_SERIALIZATION_BOOST_VARIANT_HPP
90 changes: 21 additions & 69 deletions hpx/runtime/serialization/variant.hpp
Original file line number Diff line number Diff line change
@@ -1,100 +1,52 @@
// copyright (c) 2005
// troy d. straszheim <[email protected]>
// http://www.resophonic.com
// Copyright (c) 2015 Anton Bikineev
// Copyright (c) 2017-2019 Hartmut Kaiser
//
// 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
#if !defined(HPX_DATASTRUCTURES_VARIANT_SERIALIZATION_HPP)
#define HPX_DATASTRUCTURES_VARIANT_SERIALIZATION_HPP

#include <hpx/config.hpp>
#include <hpx/runtime/serialization/serialization_fwd.hpp>
#include <hpx/errors.hpp>
#include <hpx/datastructures/variant.hpp>

#include <boost/variant.hpp>
#include <hpx/runtime/serialization/serialization_fwd.hpp>
#include <hpx/runtime/serialization/boost_variant.hpp>
#include <hpx/errors/throw_exception.hpp>

#include <cstddef>
#include <utility>

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

template <typename T>
void operator()(T const& value) const
{
m_ar << value;
}

private:
output_archive & m_ar;
};

template <typename ... Ts>
struct variant_impl;

template <typename T, typename ... Ts>
struct variant_impl<T, Ts...>
{
template <typename V>
static void load(input_archive& ar, int which, V& v)
{
if (which == 0)
{
// note: A non-intrusive implementation (such as this one)
// necessary has to copy the value. This wouldn't be necessary
// with an implementation that de-serialized to the address of the
// aligned storage included in the variant.
T value;
ar >> value;
v = std::move(value);
return;
}
variant_impl<Ts...>::load(ar, which - 1, v);
}
};

template <>
struct variant_impl<>
{
template <typename V>
static void load(input_archive& /*ar*/, int /*which*/, V& /*v*/)
{
}
};

template <typename ... T>
void save(output_archive& ar, boost::variant<T...> const& v, unsigned)
///////////////////////////////////////////////////////////////////////////
template <typename... Ts>
void save(output_archive& ar, hpx::util::variant<Ts...> const& v, unsigned)
{
int which = v.which();
std::size_t which = v.index();
ar << which;
variant_save_visitor visitor(ar);
v.apply_visitor(visitor);
detail::variant_save_visitor visitor(ar);
hpx::util::visit(visitor, v);
}

template <typename ... T>
void load(input_archive& ar, boost::variant<T...>& v, unsigned)
template <typename... Ts>
void load(input_archive& ar, hpx::util::variant<Ts...>& v, unsigned)
{
int which;
std::size_t which;
ar >> which;
if (which >= static_cast<int>(sizeof...(T)))
if (which >= sizeof...(Ts))
{
// this might happen if a type was removed from the list of variant
// types
HPX_THROW_EXCEPTION(serialization_error
, "load<Archive, Variant, version>"
, "type was removed from the list of variant types");
}
variant_impl<T...>::load(ar, which, v);
detail::variant_impl<Ts...>::load(ar, which, v);
}

HPX_SERIALIZATION_SPLIT_FREE_TEMPLATE(
(template<typename ... T>), (boost::variant<T...>));
(template <typename ... Ts>), (hpx::util::variant<Ts...>));
}}

#endif //HPX_SERIALIZATION_VARIANT_HPP
#endif
3 changes: 3 additions & 0 deletions libs/datastructures/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ cmake_minimum_required(VERSION 3.3.2 FATAL_ERROR)
set(datastructures_headers
hpx/datastructures/tuple.hpp
hpx/datastructures/optional.hpp
hpx/datastructures/variant.hpp
hpx/datastructures/detail/pack.hpp
hpx/datastructures/detail/variant.hpp
)

set(datastructures_compat_headers
Expand All @@ -27,6 +29,7 @@ add_hpx_module(datastructures
GLOBAL_HEADER_GEN ON
EXCLUDE_FROM_GLOBAL_HEADER
"hpx/datastructures/detail/pack.hpp"
"hpx/datastructures/detail/variant.hpp"
SOURCES ${datastructures_sources}
HEADERS ${datastructures_headers}
COMPAT_HEADERS ${datastructures_compat_headers}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
variant.hpp
Loading