146 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			146 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								// (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()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								#if defined(MPI_VERSION) && MPI_VERSION >= 2
							 | 
						||
| 
								 | 
							
								      BOOST_MPI_CHECK_RESULT(MPI_Get_address,(const_cast<void*>(orig), &origin));
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								      BOOST_MPI_CHECK_RESULT(MPI_Address,(const_cast<void*>(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<class T>
							 | 
						||
| 
								 | 
							
								    void save_array(serialization::array_wrapper<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)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								#if defined(MPI_VERSION) && MPI_VERSION >= 2
							 | 
						||
| 
								 | 
							
								       BOOST_MPI_CHECK_RESULT(MPI_Type_create_struct,
							 | 
						||
| 
								 | 
							
								                    (
							 | 
						||
| 
								 | 
							
								                      addresses.size(),
							 | 
						||
| 
								 | 
							
								                      boost::serialization::detail::get_data(lengths),
							 | 
						||
| 
								 | 
							
								                      boost::serialization::detail::get_data(addresses),
							 | 
						||
| 
								 | 
							
								                      boost::serialization::detail::get_data(types),
							 | 
						||
| 
								 | 
							
								                      &datatype_
							 | 
						||
| 
								 | 
							
								                    ));
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								        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_
							 | 
						||
| 
								 | 
							
								                                ));
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								        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;
							 | 
						||
| 
								 | 
							
								#if defined(MPI_VERSION) && MPI_VERSION >= 2
							 | 
						||
| 
								 | 
							
								     BOOST_MPI_CHECK_RESULT(MPI_Get_address,(const_cast<void*>(p), &a));
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								     BOOST_MPI_CHECK_RESULT(MPI_Address,(const_cast<void*>(p), &a));
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								      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
							 |