Boost logo

Boost Users :

Subject: Re: [Boost-users] Usingboost::serializationinreal-timewithoutallocating memory
From: Peter Soetens (peter.soetens_at_[hidden])
Date: 2009-09-21 18:11:33


On Mon, Sep 21, 2009 at 23:44, Peter Soetens <peter.soetens_at_[hidden]> wrote:
> On Mon, Sep 21, 2009 at 21:25, Robert Ramey <ramey_at_[hidden]> wrote:
>> Stefan Strasser wrote:
>>> Am Monday 21 September 2009 20:27:59 schrieb Robert Ramey:
>>>> Stefan Strasser wrote:
>>>>> I think to support this an other use cases like it common_archive
>>>>> would have to be moved outside of the linked library into a header
>>>>> and be made more generic.
>>>>
>>>> common_archive is a template - it's not in the linked library.
>>>
>>> ok, I must have mixed up some types. the point was that the ultimate
>>> base class, that handles the type registration and object tracking
>>> etc., is
>>> linked .cpp and not very configurable.
>>> the optimum case imho would be that you could pass a traits class to
>>> that archive base class, that gets called whenever there is an object
>>> or type to be registered and is queried for existing objects and
>>> types later on.
>>> that way you could disable registration, save type registration
>>> outside of the archive itself, let type registration span multiple
>>> archives etc, make sure type registration doesn't allocate etc.
>>
>> as I alluded to before - what I would like to know is why I derived
>> trivial_archive from common_archive.  I don't remember what
>> made me do this.  It seems that if this isn't done then save/load_object
>> is necessary.  So the question is - why is this?  It is an oversight
>> somewhere? or does the archive concept have to be changed.
>>
>> Personally, I generally don't like the "traits class" as an argument.
>> It sort of implies that that the template has a lot of "if -" code
>> which navigates the traits. A "policy class" is better but can
>> still make things complex.  Personally I prefer composition
>> of funtionality through inheritance. This can be seen in
>> the class diagram for the serialization library. And your example
>> makes me more convinced than ever that this is basically
>> right.  Now the only loose end it investigate why save/load
>> object is required.
>
> I found a lead to that. When the archive calls archive::save, a chain
> of 'invoke' calls is done to select the right serialization method for
> type T. When I pass std::vector<double> as T, it encounters a branch
> in oserializer.hpp:245, in  struct 'save_conditional::invoke' .
>
> <code>
>    // adds class information to the archive. This includes
>    // serialization level and class version
>    struct save_conditional {
>        static void invoke(Archive &ar, const T &t){
>            //if(0 == (ar.get_flags() & no_tracking))
>                save_standard::invoke(ar, t);
>            //else
>            //   save_only::invoke(ar, t);
>        }
>    };
> </code>
>
>  The alternative branch is commented out, but let that be the path
> that needs to be taken by my code. Current code calls save_standard,
> which calls directly ' ar.save_object'. save_object in turn depends on
> basic_oarchive to do its job. If save_only was taken, the
> 'non-basic_oarchive' serialization code path would have been taken.
>
> For some reason (I've spent an hour staring at it), my unit test did
> not discover this flaw in my code and does as if serialisation of the
> std::vector was fine. I'm overlooking something stupid clearly...
>
> Anyway, as it seems now, the code path taken by archive::save/load
> mandates derivation of basic_?archive. Maybe I should have called
> another 'selection' function ? like archive::save_only directly ?

I tried using this instead of archive::save() :
<code>
  boost::archive::detail::load_non_pointer_type<binary_data_iarchive,T>::load_only::invoke(*this,t);
</code>

But the compiler (gcc 4.3.3-5ubuntu4) refuses to compile this when the
nvt types are in use. Basically, this is not fine:
<code>
int count;
ar >> BOOST_SERIALIZATION_NVP(count);
</code>
While this is:
<code>
int count;
nvp<int> n = BOOST_SERIALIZATION_NVP(count);
ar >> n
</code>

You can try this out in plain user code. Beats me. The errors I get
for the first case are in the line of:

usr/include/boost/serialization/access.hpp: In static member function
‘static void boost::serialization::access::serialize(Archive&, T&,
unsigned int) [with Archive = RTT::marsh::binary_data_iarchive, T =
const boost::serialization::nvp<int>]’:
/usr/include/boost/serialization/serialization.hpp:74: instantiated
from ‘void boost::serialization::serialize(Archive&, T&, unsigned int)
[with Archive = RTT::marsh::binary_data_iarchive, T = const
boost::serialization::nvp<int>]’
/usr/include/boost/serialization/serialization.hpp:133: instantiated
from ‘void boost::serialization::serialize_adl(Archive&, T&, unsigned
int) [with Archive = RTT::marsh::binary_data_iarchive, T = const
boost::serialization::nvp<int>]’
/usr/include/boost/archive/detail/iserializer.hpp:316: instantiated
from ‘static void
boost::archive::detail::load_non_pointer_type<Archive,
T>::load_only::invoke(Archive&, T&) [with Archive =
RTT::marsh::binary_data_iarchive, T = const
boost::serialization::nvp<int>]’
/home/kaltan/src/git/orocos-rtt/src/marsh/binary_data_archive.hpp:198:
  instantiated from ‘RTT::marsh::binary_data_iarchive&
RTT::marsh::binary_data_iarchive::load_a_type(T&, mpl_::false_) [with
T = const boost::serialization::nvp<int>]’
/home/kaltan/src/git/orocos-rtt/src/marsh/binary_data_archive.hpp:131:
  instantiated from ‘RTT::marsh::binary_data_iarchive&
RTT::marsh::binary_data_iarchive::operator>>(T&) [with T = const
boost::serialization::nvp<int>]’
/home/kaltan/src/git/orocos-rtt/tests/mqueue_archive_test.cpp:71:
instantiated from here
/usr/include/boost/serialization/access.hpp:109: error: passing ‘const
boost::serialization::nvp<int>’ as ‘this’ argument of ‘void
boost::serialization::nvp<T>::serialize(Archive&, unsigned int) [with
Archive = RTT::marsh::binary_data_iarchive, T = int]’ discards
qualifiers

Passing to operator>> the nvt struct as a return value of make_nvt()
makes gcc add a const qualifier, which gets propagated all the way...I
have no idea why the other archive implementations don't suffer this.

Peter


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net