#include #include #include #include #include #include #include #include #include #include #include #include #include class A { friend class boost::serialization::access; private: template void serialize(Archive & ar, const unsigned int version); public: A(); virtual ~A(); virtual size_t size() const = 0; virtual A* clone() const = 0; }; class B { friend class boost::serialization::access; private: template void serialize(Archive & ar, const unsigned int version); public: B(); virtual ~B(); virtual size_t size() const = 0; virtual B* clone() const = 0; }; class C; typedef boost::shared_ptr CP; class C { friend class boost::serialization::access; private: A* a; B* b; std::string s; std::string d; template void serialize(Archive & ar, const unsigned int version); public: C(); C(const C & c); C(A* const a, B* const b, const std::string & s, const std::string & d); ~C(); A* getA() const; B* getB() const; std::string getS() const; std::string getD() const; size_t size() const; }; #define KVPI_EXPAND_PROT(KV) \ template void KV::serialize(boost::mpi::packed_oarchive & ar, \ const unsigned int version); \ template void KV::serialize(boost::mpi::packed_iarchive & ar, \ const unsigned int version); \ template void KV::serialize(boost::mpi::detail::mpi_datatype_oarchive & ar, \ const unsigned int version); \ template void KV::serialize(boost::archive::text_oarchive & ar, \ const unsigned int version); \ template void KV::serialize(boost::archive::text_iarchive & ar, \ const unsigned int version); A::A() {} A::~A() {} template void A::serialize(Archive & ar, const unsigned int version) {} B::B() {} B::~B() {} template void B::serialize(Archive & ar, const unsigned int version) {} C::C() : a(), b(), s(""), d("") {} C::C(const C & c) { if(c.a != NULL) { a = (c.a)->clone(); } else { a = NULL; } if(c.b != NULL) { b = (c.b)->clone(); } else { b = NULL; } s = c.s; d = c.d; } C::C(A* const aa, B* const bb, const std::string & ss, const std::string & dd) { if(aa != NULL) { a = aa->clone(); } else { a = NULL; } if(bb != NULL) { b = bb->clone(); } else { b = NULL; } s = ss; d = dd; } C::~C() { if(a != NULL) { delete a; } if(b != NULL) { delete b; } } template void C::serialize(Archive & ar, const unsigned int version) { ar & a; ar & b; ar & s; ar & d; } A* C::getA() const { return a; } B* C::getB() const { return b; } std::string C::getS() const { return s; } std::string C::getD() const { return d; } size_t C::size() const { if(a != 0 && b != 0) { return a->size() + b->size(); } else { return 0; } } class D : public A { private: friend class boost::serialization::access; double* values; template void serialize(Archive & ar, const unsigned int version); public: D(); ~D(); D(const D & d); double& operator[](int i); double operator[](int i) const; virtual size_t size() const; virtual A* clone() const; }; class E : public B { private: friend class boost::serialization::access; double* values; int n; template void serialize(Archive & ar, const unsigned int version); public: E(); E(int n); ~E(); E(const E & e); double& operator()(int i, int j); double operator()(int i, int j) const; int getN() const { return n; } virtual size_t size() const; virtual B* clone() const; }; template void D::serialize(Archive & ar, const unsigned int version) { ar & boost::serialization::base_object(*this); for(int i = 0; i < 3; i++) { ar & values[i]; } } D::D() { values = new double[3]; for(int i = 0; i < 3; i++) { values[i] = 0.0; } } D::~D() { delete [] values; } D::D(const D & v) { values = new double[3]; for(int i = 0; i < 3; i++) { values[i] = v.values[i]; } } double& D::operator[](int i) { return values[i]; } double D::operator[](int i) const { return values[i]; } size_t D::size() const { return 3 * sizeof(double); } A* D::clone() const { return new D(*this); } template void E::serialize(Archive & ar, const unsigned int version) { ar & boost::serialization::base_object(*this); ar & n; for(int i = 0; i < n*n; i++) { ar & values[i]; } } E::E() { this->n = 1024; values = new double[n*n]; for(int i = 0; i < n*n; i++) { values[i] = 0.0; } } E::E(int n) { this->n = n; values = new double[n*n]; for(int i = 0; i < n*n; i++) { values[i] = 0.0; } } E::~E() { delete [] values; } E::E(const E & e) { n = e.n; values = new double[n*n]; for(int i = 0; i < n*n; i++) { values[i] = e.values[i]; } } double& E::operator()(int i, int j) { return values[i * n + j]; } double E::operator()(int i, int j) const { return values[i * n + j]; } size_t E::size() const { return n*n * sizeof(double); } B* E::clone() const { return new E(*this); } BOOST_CLASS_EXPORT(A) BOOST_CLASS_EXPORT(B) BOOST_CLASS_EXPORT(C) BOOST_CLASS_EXPORT(D) BOOST_CLASS_EXPORT(E) BOOST_SERIALIZATION_ASSUME_ABSTRACT(A) BOOST_SERIALIZATION_ASSUME_ABSTRACT(B) BOOST_SERIALIZATION_SHARED_PTR(C) double randDouble(int max) { return (2.0 * (static_cast(rand()) / (static_cast(RAND_MAX) + 1.0) * (max+1)) - (max+1)); } int main(int argc, char* argv[]) { int n = 2000; E e(n); D d; std::string myself("myself"); boost::mpi::environment env(argc, argv); boost::mpi::communicator world; srand(time(0) + world.rank()); rand(); for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) { e(i,j) = randDouble(100); } } d[0] = randDouble(10); d[1] = randDouble(10); d[2] = randDouble(10); CP c1(new C(&d, &e, myself, myself)); CP c2(new C); if(world.rank() == 0) { world.send(1, 0, c1); std::cout << "Sent " << c1->size() << " bytes" << std::endl; } else { world.recv(0, 0, c2); std::cout << "Received " << c2->size() << " bytes" << std::endl; } return 0; }