| // (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 |