RE:RE: [boost] seiralization of shared_ptr

template<class Archive, class T> inline void load( Archive & ar, shared_ptr<T> & t, const unsigned int /* file_version */ ){ // object tracking guarantees that pointers are not replicated // on loading. T * t_new; ar >> boost::serialization::make_nvp("px", t_new); // if its not the first time, it should be equal to the current pointer assert(0 == t.use_count() || t.get() == t_new); // assign new pointer or bump reference count as appropriate // ???? - what goes here? }
Can anybody tell me "what goes here?"
Robert Ramey
I don't see problem where you see it. I ses problem in different place.
How is it possible that t.use_count() != 0? My understanding that before loading all data is empty and you never actually load the same variable twice.
struct A { shared_ptr<user_type> member; load(...) { ar >> member; } };
A a1, a2
At this point a1.member.use_count == 0,
ar >> a1; ar >> a2; ...
Now the real problem lies IMO in a fact that you need to keep map raw ptr - corresponding shared_ptr. IOW when you got raw ptr and you need to create shared ptr for it you need to figure out somehow whether you already did it. If yes you need to make a copy to that shared_ptr. If not create new and register it.
That's the problem. There's no way I can see to create a copy of an existing shared pointer given only the copy to the shared underlying pointer. The current implementation uses object tracking to load the replicated pointer to the shared_count. At that point the loaded shared pointer is connected to any other shared_ptrs that correspond to the underlying shared object. This does not require maintenance of any other ptr/shared_ptr maps which would only replicate the what the serialization library does anyway through object tracking. However, the current method does require either privileged access to shared_ptr and shared_count or some sort of expansion of the interface. I believe this answers the original question you posed:"Why does serialization of shared_ptr require access to shared_count?" Robert Ramey

Now the real problem lies IMO in a fact that you need to keep map raw ptr - corresponding shared_ptr. IOW when you got raw ptr and you need to create shared ptr for it you need to figure out somehow whether you already did it. If yes you need to make a copy to that shared_ptr. If not create new and register it.
That's the problem. There's no way I can see to create a copy of an existing shared pointer given only the copy to the shared underlying pointer.
I wouldn't say that. You could use simple map<void*,void*> that mapr raw pointer to an address of shred_ptr, It is a bit havyweight and does partially replicate what library core is doing (that is why I called it " more complex solution" in original post). But I believe it quite unique situation that varant special treatment.
The current implementation uses object tracking to load the replicated pointer to the shared_count. At that point the loaded shared pointer is connected to any other shared_ptrs that correspond to the underlying shared object. This does not require maintenance of any other ptr/shared_ptr maps which would only replicate the what the serialization library does anyway through object tracking. However, the current method does require either privileged access to shared_ptr and shared_count or some sort of expansion of the interface.
So the question is what tradeoff you prefer: 1. You pay for an extra space to store ptr->shared_ptr map and possibly(?) exra time 2. You pay with extra space in any archive that uses shared_ptr and demand access to shared_ptr private area Actually who has time advantage it not simple question. My understanding is that in second case you still spend time on reading counter from archive searching in resistry and extr maintanence work.
I believe this answers the original question you posed:"Why does serialization of shared_ptr require access to shared_count?"
I would go with direct map.
Robert Ramey
Gennadiy.

Gennadiy Rozental wrote:
You could use simple map<void*,void*> that mapr raw pointer to an address of shred_ptr
We're using a similar approach in our current version of boost::serialization. Our solution currently stores a raw_ptr-to-shared_ptr<void> map in the input archive object. With this shared_ptr registry in the input archive our non-intrusive serialization code for shared_ptr looks like this (the code for weak_ptr is more or less the same): template<class Archive, class T> inline void save( Archive & ar, const boost::shared_ptr<T> &t, const unsigned int /* file_version */ ){ ar << boost::serialization::make_nvp("px", t.get()); } template<class Archive, class T> inline void load( Archive & ar, boost::shared_ptr<T> &t, const unsigned int /* file_version */ ){ T* r; ar >> boost::serialization::make_nvp("px", r); t = ar.get_shared_ptr_registry().lookup(r); if (!t) { t.reset(r); ar.get_shared_ptr_registry().register_shared_ptr(t); } } template<class Archive, class T> inline void serialize( Archive & ar, boost::shared_ptr<T> &t, const unsigned int file_version ){ boost::serialization::split_free(ar, t, file_version); } So, upon deserialization, when an object pointed to by a shared_ptr is loaded for the first time the shared_ptr instance is registered in the shared_ptr registry of the archive (where it is stored as shared_ptr<void> to allow shared_ptrs that only point to the base class to be retrieved correctly from the registry). In all other cases, the previously deserialized shared_ptr instance is used to create the shared_ptr instance that is currently being deserialized. Note that the lookup function uses a (hackky) reinterpret_cast to convert from the shared_ptr<void> which is stored in the registry to the actually requested shared_ptr<T> type. In practice, this seems to work and the reference count is maintained correctly, but there might be a better solution. Also note that the situation posted by Peter Dimov with multiple inheritance does not work with this solution. Single inheritance should work fine, though. Regards, Martin Ecker TAB Austria Industrie- und Unterhaltungselektronik GmbH & CoKG http://www.tab.at
participants (3)
-
Gennadiy Rozental
-
martin.ecker@tab.at
-
Robert Ramey