Boost logo

Boost :

From: Vahan Margaryan (vahan_at_[hidden])
Date: 2002-07-19 01:39:34


Dear Robert,
See my comments under yours.

-----
> I believe the following code exhibits your point.
[snipped code]

Yes, it does.

> // case 1: I presume you have no problem with this
> void School::save(ar) const {
> ar << all_kids;
> ar << classes;
> }
> void School::load(ar, version_type){
> ar >> all_kids;
> ar >> classes;
> }

Yes, this case will work fine.

>
> // case 2: I believe this is the case that concerns you
> void School::save(ar) const {
> ar << classes;
> ar << all_kids;
> }
> void School::load(ar, version_type){
> // if an exeception occurs while loading classes
> // the structure classes may have some classes each
> // with students
> ar >> classes;
> // while all_kids will have no members.
> ar >> all_kids;
> }

Yes, this is the problematic case.

> Note that this is quite different than the case described in
> your first email which was easily addressed by the proposed
> change. Now on to this example:

Yes, in the first email I tried to put a simple example of the problem.
However, this example is still an exhibition of the same problem - owning
and non-owning pointers.

> At the heart of this situation is that pointers are used
> in one case to control storage while in another case as
> references to other structures. So we're really talking
> about to kinds of pointers - one that "owns" its storage
> while another doesn't.

> Your proposal suggests that the library user be aware of the
> distinction between the types of pointers and that he pass that
> distinction as one of the arguments to the load function.
> (I hope that is a fair characterization)

As you point out below, passing an extra argument isn't the most elegant way
of implementing it. I don't propose to use that specific way of indicating
ownership, I propose to use some way of indication.

> My response would be that if the user must be aware of this distinction,
> then he can take it into consideration when he writes the load/save
> functions. In this example, there would be several alternatives:

Yes, that's what I meant too. My point was that if the user has to know
about it anyway, then it's really part of the library interface, whether
visible in function prototypes or not. So we lose some transparency in any
case.

>
> a) Use case 1 above
>
> b) or alternatively use case 2 with the following load function.
>
> void School::load(ar, version_type){
> try{
> ar >> classes;
> }
> catch(...){
> // messy code to clean up classes variable
> ...
> throw; // rethrow exception
> }
> ar >> all_kids;
> }

This is not a valid solution, the 'messy code' may be impossible to write
(how do I access Class's private members?).

> c) use shared_ptr rather than raw pointers. This would entail
> writing a template to serialize a shared_ptr<class T>. I originally
> had such an example, but it turned out to be too complex for an
> example, so I replaced it with a template to serialize auto_ptr<class T>.
> But its definitely doable - though the implementation of shared_ptr
> would have to change slightly.

This forces to change code without valid reasons.

> d) don't use pointers for owned data. In this example, this
> would mean that School would change slightly to
>
> class School
> {
> std::list<Kid> all_kids;
> ....

This modification will be impossible to make in many cases (what if I want
all_kids to be a random-access container?).

> This serialization system would effectively enforce the usage of
> case 1 in this circumstance.
>
> To summarize, my view is that the need to explicitly keep track
> of which pointers are owners and which are not is an indicator
> of a weakness in the design that should be remedied at its source
> rather than trying to keep track of it within the serialization
> library. Should it be necessary to do this, it can be done outside
> the serialization library.

Why is it a weakness? When I design a class, I make a design decision
whether a specific pointer member is owned by the class or not. It is
trivial for me to implement serialization correctly by indicating my intent,
if the system allows me to do that..

> I recognize that the are some examples of structures that cannot
> be serialized without some sort of special gymnastics. The test
> program contains the simplest such case - a circular linked list
> of pointers. So far it hasn't occurred to me how to address these
> very unsual cases in a general way without making the library
> more (too) complex.

Unfortunately, the case isn't as unusual as it might seem. I have faced
it commonly in practice. One simple example I mentioned is when each Kid
stores a reference to its Class. How would you handle that case?

The real cases I'd been working with were more complex than that. Complex
data structures are usually highly linked.

>
> In my view this is another manisfestation of the whole pointer
> (pointless?) discussion that runs continously on this list.
> This discussion revolves around adding attributes to pointers
> to dintinguish amongst them. I believe that using the pointer type
> that supports the concept of "ownership" and creating a template
> to serialize it, would address the issues which your
> example raises. This would be much better than adding more
> arguements and code to the load functions.

I agree that more elegant implementations of the concept are possible. Our
implementation was mostly dictated by compiler limitations.

I don't know if users would agree to use special pointer types in their code
just for the sake of serialization. On the other hand, I think some nice
syntactic way of showing owning pointers could be invented.

It could be possible to let the user specify whether he needs to use
'advanced' serialization with ownership indication or simple serialization
without it. What do you think?

> So, it looks like we'll have to agree to disagree. I am disappointed
> as its clear to me you've put a lot of thought and effor into this, but
> then so have I. oh well.

In any case it's been interesting to discuss, hasn't it? :)

Best regards,
-Vahan


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk