// (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 #include // size_t #include #if defined(BOOST_NO_STDC_NAMESPACE) namespace std{ using ::size_t; } // namespace std #endif #include #include #include #include #include #include #include #include #include #include #include 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() { #if BOOST_MPI_VERSION >= 2 BOOST_MPI_CHECK_RESULT(MPI_Get_address,(const_cast(orig), &origin)); #else BOOST_MPI_CHECK_RESULT(MPI_Address,(const_cast(orig), &origin)); #endif } void save_binary(void const *address, std::size_t count) { save_impl(address,MPI_BYTE,count); } // fast saving of arrays of MPI types template void save_array(serialization::array_wrapper 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 use_array_optimization; // create and return the custom MPI data type MPI_Datatype get_mpi_datatype() { if (!is_committed) { #if BOOST_MPI_VERSION >= 2 BOOST_MPI_CHECK_RESULT(MPI_Type_create_struct, ( addresses.size(), c_data(lengths), c_data(addresses), c_data(types), &datatype_ )); #else BOOST_MPI_CHECK_RESULT(MPI_Type_struct, ( addresses.size(), c_data(lengths), c_data(addresses), c_data(types), &datatype_ )); #endif BOOST_MPI_CHECK_RESULT(MPI_Type_commit,(&datatype_)); is_committed = true; } return datatype_; } // default saving of primitives. template 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; #if BOOST_MPI_VERSION >= 2 BOOST_MPI_CHECK_RESULT(MPI_Get_address,(const_cast(p), &a)); #else BOOST_MPI_CHECK_RESULT(MPI_Address,(const_cast(p), &a)); #endif addresses.push_back(a-origin); types.push_back(t); lengths.push_back(l); } template static T* get_data(std::vector& v) { return v.empty() ? 0 : &(v[0]); } std::vector addresses; std::vector types; std::vector lengths; bool is_committed; MPI_Datatype datatype_; MPI_Aint origin; }; } } } // end namespace boost::mpi::detail #endif // BOOST_MPI_DETAIL_MPI_DATATYPE_OPRIMITIVE_HPP