From: Luca Heltai Date: Sat, 18 Nov 2017 19:18:09 +0000 (+0100) Subject: Added pack/unpack to Utilities. X-Git-Tag: v9.0.0-rc1~754^2~1 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3b60cd3ad1427d5cc20330fd8e6f856cd485aee7;p=dealii.git Added pack/unpack to Utilities. --- diff --git a/doc/news/changes/minor/20171118LucaHeltai b/doc/news/changes/minor/20171118LucaHeltai new file mode 100644 index 0000000000..cf4bae39d3 --- /dev/null +++ b/doc/news/changes/minor/20171118LucaHeltai @@ -0,0 +1,4 @@ +New:Added Utilities::pack and Utilities::unpack, to serialize and unserialize arbitrary +objects that support boost::serialization/deserialization. +
+(Luca Heltai, 2017/11/18) diff --git a/include/deal.II/base/utilities.h b/include/deal.II/base/utilities.h index 14785abf25..4c44c34643 100644 --- a/include/deal.II/base/utilities.h +++ b/include/deal.II/base/utilities.h @@ -34,6 +34,19 @@ # endif #endif +DEAL_II_DISABLE_EXTRA_DIAGNOSTICS +#include +#include +#include +#include + +#ifdef DEAL_II_WITH_ZLIB +# include +# include +# include +# include +#endif + DEAL_II_NAMESPACE_OPEN @@ -377,6 +390,32 @@ namespace Utilities std::vector invert_permutation (const std::vector &permutation); + /** + * Given an arbitrary object of type T, use boost::serialization utilities + * to pack the object into a vector of characters. The object can be unpacked + * using the Utilities::unpack function below. + * + * If the library has been compiled with ZLIB enabled, then the output buffer + * is compressed. + * + * @author Timo Heister, Wolfgang Bangerth, 2017. + */ + template + std::vector pack(const T &object); + + /** + * Given a vector of characters, obtained through a call to the function + * Utilities::pack, restore its content in an object of type T. + * + * This function uses boost::serialization utilities to unpack the object + * from a vector of characters, and it is the inverse of the function + * Utilities::pack + * + * @author Timo Heister, Wolfgang Bangerth, 2017. + */ + template + T unpack(const std::vector &buffer); + /** * A namespace for utility functions that probe system properties. * @@ -730,6 +769,65 @@ namespace Utilities len = half; } } + + + + template + std::vector pack(const T &object) + { + // set up a buffer and then use it as the target of a compressing + // stream into which we serialize the current object + std::vector buffer; + { +#ifdef DEAL_II_WITH_ZLIB + boost::iostreams::filtering_ostream out; + out.push(boost::iostreams::gzip_compressor + (boost::iostreams::gzip_params + (boost::iostreams::gzip::best_compression))); + out.push(boost::iostreams::back_inserter(buffer)); + + boost::archive::binary_oarchive archive(out); + archive << object; + out.flush(); +#else + std::ostringstream out; + boost::archive::binary_oarchive archive(out); + archive << object; + const std::string &s = out.str(); + buffer.reserve(s.size()); + buffer.assign(s.begin(), s.end()); +#endif + } + return buffer; + } + + + + template + T unpack(const std::vector &buffer) + { + std::string decompressed_buffer; + T object; + + // first decompress the buffer + { +#ifdef DEAL_II_WITH_ZLIB + boost::iostreams::filtering_ostream decompressing_stream; + decompressing_stream.push(boost::iostreams::gzip_decompressor()); + decompressing_stream.push(boost::iostreams::back_inserter(decompressed_buffer)); + decompressing_stream.write (buffer.data(), buffer.size()); +#else + decompressed_buffer.assign (buffer.begin(), buffer.end()); +#endif + } + + // then restore the object from the buffer + std::istringstream in(decompressed_buffer); + boost::archive::binary_iarchive archive(in); + + archive >> object; + return object; + } } diff --git a/include/deal.II/grid/grid_tools.h b/include/deal.II/grid/grid_tools.h index e222295f85..3662641b3d 100644 --- a/include/deal.II/grid/grid_tools.h +++ b/include/deal.II/grid/grid_tools.h @@ -2316,20 +2316,6 @@ namespace GridTools const unsigned int version); BOOST_SERIALIZATION_SPLIT_MEMBER() - - /** - * Pack the data that corresponds to this object into a buffer in - * the form of a vector of chars and return it. - */ - std::vector pack_data () const; - - /** - * Given a buffer in the form of an array of chars, unpack it and - * restore the current object to the state that it was when - * it was packed into said buffer by the pack_data() function. - */ - void unpack_data (const std::vector &buffer); - }; /** @@ -3110,66 +3096,6 @@ namespace GridTools - template - std::vector - CellDataTransferBuffer::pack_data () const - { - // set up a buffer and then use it as the target of a compressing - // stream into which we serialize the current object - std::vector buffer; - { -#ifdef DEAL_II_WITH_ZLIB - boost::iostreams::filtering_ostream out; - out.push(boost::iostreams::gzip_compressor - (boost::iostreams::gzip_params - (boost::iostreams::gzip::best_compression))); - out.push(boost::iostreams::back_inserter(buffer)); - - boost::archive::binary_oarchive archive(out); - archive << *this; - out.flush(); -#else - std::ostringstream out; - boost::archive::binary_oarchive archive(out); - archive << *this; - const std::string &s = out.str(); - buffer.reserve(s.size()); - buffer.assign(s.begin(), s.end()); -#endif - } - - return buffer; - } - - - - template - void - CellDataTransferBuffer::unpack_data (const std::vector &buffer) - { - std::string decompressed_buffer; - - // first decompress the buffer - { -#ifdef DEAL_II_WITH_ZLIB - boost::iostreams::filtering_ostream decompressing_stream; - decompressing_stream.push(boost::iostreams::gzip_decompressor()); - decompressing_stream.push(boost::iostreams::back_inserter(decompressed_buffer)); - decompressing_stream.write (buffer.data(), buffer.size()); -#else - decompressed_buffer.assign (buffer.begin(), buffer.end()); -#endif - } - - // then restore the object from the buffer - std::istringstream in(decompressed_buffer); - boost::archive::binary_iarchive archive(in); - - archive >> *this; - } - - - template void exchange_cell_data_to_ghosts (const MeshType &mesh, @@ -3265,7 +3191,7 @@ namespace GridTools // pack all the data into the buffer for this recipient and send it. // keep data around till we can make sure that the packet has been // received - sendbuffers[idx] = data.pack_data (); + sendbuffers[idx] = Utilities::pack(data); const int ierr = MPI_Isend(sendbuffers[idx].data(), sendbuffers[idx].size(), MPI_BYTE, *it, 786, tria->get_communicator(), &requests[idx]); @@ -3290,8 +3216,7 @@ namespace GridTools tria->get_communicator(), &status); AssertThrowMPI(ierr); - CellDataTransferBuffer cellinfo; - cellinfo.unpack_data(receive); + auto cellinfo = Utilities::unpack >(receive); DataType *data = cellinfo.data.data(); for (unsigned int c=0; c +#include + +template +void test(const unsigned int &size) +{ + std::vector > points(size); + + for (auto &p : points) + for (unsigned int i=0; i > >(buffer); + + unsigned int i=0; + bool ok = true; + for (const auto &p : points) + if (p.distance(unpacked[i++]) > 1e-12) + { + deallog << "NOT OK: " + << p << " != " << unpacked[i-1] << std::endl; + ok = false; + } + + if (ok) + deallog << "OK!" << std::endl; +} + +int main() +{ + initlog(); + + test<1>(10); + test<2>(10); + test<3>(10); +} diff --git a/tests/base/utilities_pack_unpack_01.output b/tests/base/utilities_pack_unpack_01.output new file mode 100644 index 0000000000..7ca52c43a9 --- /dev/null +++ b/tests/base/utilities_pack_unpack_01.output @@ -0,0 +1,4 @@ + +DEAL::OK! +DEAL::OK! +DEAL::OK!