// (C) Copyright 2005 Matthias Troyer | |
// Use, modification and distribution is subject to 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) | |
// Authors: Matthias Troyer | |
#ifndef BOOST_MPI_DETAIL_MPI_DATATYPE_OPRIMITIVE_HPP | |
#define BOOST_MPI_DETAIL_MPI_DATATYPE_OPRIMITIVE_HPP | |
#include <boost/mpi/config.hpp> | |
#include <cstddef> // size_t | |
#include <boost/config.hpp> | |
#if defined(BOOST_NO_STDC_NAMESPACE) | |
namespace std{ | |
using ::size_t; | |
} // namespace std | |
#endif | |
#include <boost/mpi/datatype_fwd.hpp> | |
#include <boost/mpi/exception.hpp> | |
#include <boost/throw_exception.hpp> | |
#include <boost/assert.hpp> | |
#include <boost/mpl/placeholders.hpp> | |
#include <boost/serialization/array.hpp> | |
#include <boost/serialization/detail/get_data.hpp> | |
#include <stdexcept> | |
#include <iostream> | |
#include <vector> | |
namespace boost { namespace mpi { namespace detail { | |
///////////////////////////////////////////////////////////////////////// | |
// class mpi_data_type_oprimitive - creation of custom MPI data types | |
class mpi_datatype_primitive | |
{ | |
public: | |
// trivial default constructor | |
mpi_datatype_primitive() | |
: is_committed(false), | |
origin(0) | |
{} | |
mpi_datatype_primitive(void const* orig) | |
: is_committed(false), | |
origin() | |
{ | |
BOOST_MPI_CHECK_RESULT(MPI_Address,(const_cast<void*>(orig), &origin)); | |
} | |
void save_binary(void const *address, std::size_t count) | |
{ | |
save_impl(address,MPI_BYTE,count); | |
} | |
// fast saving of arrays of MPI types | |
template<class T> | |
void save_array(serialization::array<T> const& x, unsigned int /* version */) | |
{ | |
if (x.count()) | |
save_impl(x.address(), boost::mpi::get_mpi_datatype(*x.address()), x.count()); | |
} | |
typedef is_mpi_datatype<mpl::_1> use_array_optimization; | |
// create and return the custom MPI data type | |
MPI_Datatype get_mpi_datatype() | |
{ | |
if (!is_committed) | |
{ | |
BOOST_MPI_CHECK_RESULT(MPI_Type_struct, | |
( | |
addresses.size(), | |
boost::serialization::detail::get_data(lengths), | |
boost::serialization::detail::get_data(addresses), | |
boost::serialization::detail::get_data(types), | |
&datatype_ | |
)); | |
BOOST_MPI_CHECK_RESULT(MPI_Type_commit,(&datatype_)); | |
is_committed = true; | |
} | |
return datatype_; | |
} | |
// default saving of primitives. | |
template<class T> | |
void save(const T & t) | |
{ | |
save_impl(&t, boost::mpi::get_mpi_datatype(t), 1); | |
} | |
private: | |
void save_impl(void const * p, MPI_Datatype t, int l) | |
{ | |
BOOST_ASSERT ( !is_committed ); | |
// store address, type and length | |
MPI_Aint a; | |
BOOST_MPI_CHECK_RESULT(MPI_Address,(const_cast<void*>(p), &a)); | |
addresses.push_back(a-origin); | |
types.push_back(t); | |
lengths.push_back(l); | |
} | |
std::vector<MPI_Aint> addresses; | |
std::vector<MPI_Datatype> types; | |
std::vector<int> lengths; | |
bool is_committed; | |
MPI_Datatype datatype_; | |
MPI_Aint origin; | |
}; | |
} } } // end namespace boost::mpi::detail | |
#endif // BOOST_MPI_DETAIL_MPI_DATATYPE_OPRIMITIVE_HPP |