1 // (C) Copyright 2005-2007 Matthias Troyer 2 3 // Use, modification and distribution is subject to the Boost Software 4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 5 // http://www.boost.org/LICENSE_1_0.txt) 6 7 // Authors: Matthias Troyer 8 9 #ifndef BOOST_MPI_BINARY_BUFFER_IPRIMITIVE_HPP 10 #define BOOST_MPI_BINARY_BUFFER_IPRIMITIVE_HPP 11 12 #include <mpi.h> 13 #include <iostream> 14 #include <cstddef> // size_t 15 #include <boost/config.hpp> 16 #include <boost/mpi/exception.hpp> 17 #include <boost/assert.hpp> 18 #include <boost/mpl/assert.hpp> 19 #include <boost/serialization/array.hpp> 20 #include <boost/serialization/is_bitwise_serializable.hpp> 21 #include <vector> 22 #include <boost/mpi/allocator.hpp> 23 #include <cstring> // for memcpy 24 #include <cassert> 25 26 namespace boost { namespace mpi { 27 28 /// deserialization using MPI_Unpack 29 30 class BOOST_MPI_DECL binary_buffer_iprimitive 31 { 32 public: 33 /// the type of the buffer from which the data is unpacked upon deserialization 34 typedef std::vector<char, allocator<char> > buffer_type; 35 binary_buffer_iprimitive(buffer_type & b,MPI_Comm const &,int position=0)36 binary_buffer_iprimitive(buffer_type & b, MPI_Comm const &, int position = 0) 37 : buffer_(b), 38 position(position) 39 { 40 } 41 address()42 void* address () 43 { 44 return detail::c_data(buffer_); 45 } 46 address() const47 void const* address () const 48 { 49 return detail::c_data(buffer_); 50 } 51 size() const52 const std::size_t& size() const 53 { 54 return size_ = buffer_.size(); 55 } 56 resize(std::size_t s)57 void resize(std::size_t s) 58 { 59 buffer_.resize(s); 60 } 61 load_binary(void * address,std::size_t count)62 void load_binary(void *address, std::size_t count) 63 { 64 load_impl(address,count); 65 } 66 67 // fast saving of arrays of fundamental types 68 template<class T> load_array(serialization::array_wrapper<T> const & x,unsigned int)69 void load_array(serialization::array_wrapper<T> const& x, unsigned int /* file_version */) 70 { 71 BOOST_MPL_ASSERT((serialization::is_bitwise_serializable<BOOST_DEDUCED_TYPENAME remove_const<T>::type>)); 72 if (x.count()) 73 load_impl(x.address(), sizeof(T)*x.count()); 74 } 75 76 typedef serialization::is_bitwise_serializable<mpl::_1> use_array_optimization; 77 78 template<class T> load(serialization::array_wrapper<T> const & x)79 void load(serialization::array_wrapper<T> const& x) 80 { 81 load_array(x,0u); 82 } 83 84 // default saving of primitives. 85 template<class T> load(T & t)86 void load( T & t) 87 { 88 BOOST_MPL_ASSERT((serialization::is_bitwise_serializable<BOOST_DEDUCED_TYPENAME remove_const<T>::type>)); 89 load_impl(&t, sizeof(T)); 90 } 91 92 template<class CharType> load(std::basic_string<CharType> & s)93 void load(std::basic_string<CharType> & s) 94 { 95 unsigned int l; 96 load(l); 97 // borland de-allocator fixup 98 #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101)) 99 if(NULL != s.data()) 100 #endif 101 s.resize(l); 102 // note breaking a rule here - could be a problem on some platform 103 load_impl(const_cast<char *>(s.data()),l); 104 } 105 106 private: 107 load_impl(void * p,int l)108 void load_impl(void * p, int l) 109 { 110 assert(position+l<=static_cast<int>(buffer_.size())); 111 if (l) 112 std::memcpy(p,&buffer_[position],l); 113 position += l; 114 } 115 116 buffer_type & buffer_; 117 mutable std::size_t size_; 118 int position; 119 }; 120 121 } } // end namespace boost::mpi 122 123 #endif // BOOST_MPI_PACKED_IPRIMITIVE_HPP 124