Search code examples
c++pointersserializationboostmemory-pool

C++ Boost binary serialization of pointer constructed from Boost object_pool


My application has a class "MyClass". It's objects are being constructed from the Boost Object_pool.

I need to serialized/de serialize this class object via Boost Binary Serialization.

For Serialization -

I take a pointer from the pool, do some operations and serialize it via Boost binary serialization. Everything is good so far.

For De-serialization -

I fetch that serialized buffer and de-serialize it with Boost binary serialization. De-serialization happens successfully, but during the process new memory is being allocated by Boost Serialization mechanism which is not constructed from the Object Pool.
If I allocate the pointer from the pool before de-serialization, the de-serialization allocates the memory on heap again and the track of the memory from the pool is being lost. Hence, I won't be able to reuse this memory allocated by the boost serialization mechanism as it cannot be given back to the object pool because it was not constructed from the pool.

#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/serialization/binary_object.hpp>
#include <boost/pool/object_pool.hpp>
#include <iostream>
#include <sstream>
#include <string>

class MyClass
{
  public :
    friend class boost::serialization::access;
    MyClass():data(9)
    {
      std::cout << std::endl << "MyClass()" << std::endl ;
    }

template<class Archive>
  void serialize(Archive & ar, const unsigned int version)
  {
    ar & data;
  }

~MyClass()
{
}

private :
  int data ;

};


int main()
{
  try
  {

    boost::object_pool<MyClass> pool ;

    // Get object from the Pool.
    MyClass *b = pool.construct();

    // Serialization

    std::stringbuf strbuf;
    boost::archive::binary_oarchive oa( strbuf ) ;
    oa << b ;

    // Deserilaiztion

    //MyClass *a = pool.construct() ;
    MyClass *a ;

    std::stringbuf strbufr(strbuf.str()) ; 
    boost::archive::binary_iarchive ia( strbufr ) ;

     // This calls the constructor and allocates memory for the pointer.
     // If we allocates this from the pool, new memory is still allocated     
     // and we loose track of the pointer fetched from the pool.   
     ia >> a;
  }
 catch ( boost::archive::archive_exception &e )
 {
   std::cout << std::endl << e.what() << std::endl ;
 }

}

What I need -

I want to de-serialize the buffer into the pointer allocated from the pool.

Gone through Boost serialization document and found the concept of Binary object wrappers, however it is resulting in compilation errors.

Main function : -

int main()
{
  try
  {

    boost::object_pool<MyClass> pool ;

    MyClass *b = pool.construct();

    std::stringbuf strbuf;
    boost::archive::binary_oarchive oa( strbuf ) ;
    oa << boost::serialization::binary_object(b, sizeof(MyClass) ) ;

    MyClass *a = pool.construct() ;

    std::stringbuf strbufr(strbuf.str()) ;
    boost::archive::binary_iarchive ia( strbufr ) ;

    ia >> boost::serialization::binary_object(b, sizeof(MyClass) );
  }
  catch ( boost::archive::archive_exception &e )
  {
    std::cout << std::endl << e.what() << std::endl ;
  }

}

It gives following compilation errors : -

serializationCpy.cpp: In function ‘int main()’:  
serializationCpy.cpp:56:8: error: no match for ‘operator>>’ (operand types are ‘boost::archive::binary_iarchive’ and ‘boost::serialization::binary_object’)
 ia >> boost::serialization::binary_object(b, sizeof(MyClass) );  
    ^
serializationCpy.cpp:56:8: note: candidate is:
In file included from /home/boost_root/include/boost/archive/detail/common_iarchive.hpp:23:0,
             from /home/boost_root/include/boost/archive/basic_binary_iarchive.hpp:30,
             from /home/boost_root/include/boost/archive/binary_iarchive_impl.hpp:21,
             from /home/boost_root/include/boost/archive/binary_iarchive.hpp:20,
             from serializationCpy.cpp:1:
/home/boost_root/include/boost/archive/detail/interface_iarchive.hpp:67:15: note: Archive& boost::archive::detail::interface_iarchive<Archive>::operator>>(T&) [with T = boost::serialization::binary_object; Archive = boost::archive::binary_iarchive]
 Archive & operator>>(T & t){
           ^
/home/boost_root/include/boost/archive/detail/interface_iarchive.hpp:67:15: note:   no known conversion for argument 1 from ‘boost::serialization::binary_object’ to ‘boost::serialization::binary_object&’  

Is it the correct way to use serialization with object pool?
Help will be highly appreciated.


Solution

  • Sourced from this answer, I think it should be

    ia >> boost::serialization::make_binary_object(a, sizeof(MyClass));
    

    or

    ia & boost::serialization::make_binary_object(a, sizeof(MyClass));
    

    instead of ia >> boost::serialization::binary_object(b, sizeof(MyClass) );

    fixing the other typo's, it'll become:

    #include <boost/archive/binary_iarchive.hpp>
    #include <boost/archive/binary_oarchive.hpp>
    #include <boost/serialization/binary_object.hpp>
    #include <boost/pool/object_pool.hpp>
    #include <iostream>
    #include <sstream>
    
    class MyClass
    {
    public:
        friend class boost::serialization::access;
        MyClass(int data) :data(data)
        {
            std::cout << "\nMyClass(" << data << ")\n";
        }
    
        MyClass()
        {
            std::cout << "\nMyClass()\n";
        }
    
        template<class Archive>
        void serialize(Archive & ar, const unsigned int version)
        {
            ar & data;
        }
    
        void printData()
        {
            std::cout << "Data = " << data << "\n";
        }
    private:
        int data;
    };
    
    int main()
    {
        try
        {
            boost::object_pool<MyClass> pool;
    
            MyClass *b = pool.construct(6);
    
            std::stringbuf strbuf;
            boost::archive::binary_oarchive oa(strbuf);
            oa << boost::serialization::binary_object(b, sizeof(MyClass));
    
            MyClass *a = pool.construct();
    
            std::stringbuf strbufr(strbuf.str());
            boost::archive::binary_iarchive ia(strbufr);
    
            ia >> boost::serialization::make_binary_object(a, sizeof(MyClass));
    
            a->printData();
        }
        catch (boost::archive::archive_exception &e)
        {
            std::cout << std::endl << e.what() << std::endl;
        }
        return 0;
    }
    

    output:

    MyClass(6)
    
    MyClass()
    Data = 6
    

    DEMO