blob: d59d7533c0235d1b21f8f8dbf885b998711e4d16 [file] [log] [blame]
// (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