Boost logo

Boost :

From: Nicola Santi (nicola.santi_at_[hidden])
Date: 2003-04-16 09:03:14


Hi,

First of all thank you, thank you very much for your interesting
feedbacks. I will try to answer beginning with your questions, then talk
about documentation, then implementation problem and finally design notes:

>4. I don't understand how serialization of base classes should be done.

In derive class serialization method remember to call the serialization
method of base class.

void Derived::serialize( bin_archive &stream) {
        // first base class serialization
        Abase::serialize(stream);

        // following by derived class serialization
        if (stream.is_loading()) {
                …
        } else {
                ..
        }
}

In this way you respect base class encapsulation over base class members.

> 5. .. Then, if you use put_object for storing … if you store a
several different pointers to the same class, you'll have type name
stored many times, and it's likely it will be longer that the class data!

put_object() stores the class conventional name than call the method
serialze(). get_object() retrieves the conventional name, create the
object, call the method serialize.

If you do not need dynamic creation (because you know it’s type or
because it is allocated on the stack, etc.) create the object and call
its serialize() method instead of get_object().

void serialize( BinArchive &stream)
{
        if (stream.IsLoading()) {
                //read the size
                size_t len;
                stream >> len;
                        
                for (size_t i=0; i<len; ++i) {
                        KnownClass* pObj = new KnownClass;
                        pObj->serialize(stream);
                        push_back( pObj);
                        
                }
                } else {
                //store size
                size_t len = size();
                stream << len;

                for (size_t i=0; i<size(); ++i) {
                        (*this)[i]->serialize(stream);
                }
        }

}

Xml persistence has an apposite method to correctly indent this kind of
object ( put/get_stack_object() ).

7. (thinking aloud) ..

>- The space is important. A single class may be 4-ints big, and
writing class name will double the size of data.
>- The speed is important. In one case, the type of data is known
during writing, and just raw bytes are added to a buffer. Adding
"typeid" call and a search for conventional name (you do it with linear
search now, but map is not O(1) as well), will not be acceptable.

Same as previous point, if you know the type don’t store it. Otherwise
if you need dynamic creation assistance the name of the class should
necessarily has been stored in the archive: in this situation could be
of some help register the class with short name only for the duration of
storing and retrieving.

> I recalled that someone suggested to Robert to separate class
registration to a separate component (possibly replacable). That would
be very good here. I could create custom class which will return id for
a type at compile-time. What do you think?

I think could be interesting, please let me know more details about the
API you are suggesting and we could try to implement it.

DOCUMENTATION

> 1. The documentation on the web page could be better.
    - I don't see "overview" anywhere. I see such document in the
distribution, but if you don't have overview instantly accessible, some
folks will not even bother to download the library.
    - The "examples" web page does not contain examples, but just
mentions the ones from distribution. Having examples on the web would
be much better.

I agree: I’ve change eternity web site this morning to follow your
suggestions.

8. The reference docs are not complete.

Yes, your are right: I think I’m the laziest documenter in the whole
Italy. I’ll try to improve references this week-end…

6. I believe there's not enough tests for your library.
Again, your are right. Could you help me in writing more tests? I will
appreciate it…

DESIGN CONSIDERATION

2. (DP) Binary serialization and XML serialization are entirely separate.

Storing a primitive type in xml archive required an additional field
(the tag label) then storing the same field in binary archive. Moreover
retrieve that field required one other parameter (the position) that is
not needed in binary persistence.
One year ago a developer from French write me if it could be possible to
have only one serialize() method to store both xml and binary way. I
wrote the modification to eternity (moving a lot of methods from
xml_archive to archive ) and having serialization method like this:

template <class archive>
void Derived::serialize( archive &stream) {
        

        // following by derived class serialization
        if (stream.is_loading()) {
                stream.read(“label”, m_nField, 0 );
        } else {
                stream.write(“label”, m_nField);
        }
}

When this method is called for binary persistence it passes a lot of
parameters that are not using and loose the random access facility over
XML archive. Do you really things it is a good idea? With two methods
(serialize and xml_serialize) the class has more control over the
persistence engine and could choice to implement only one of the two ways.

Ok, excuse me for this long reply (and my english). I have really
appreciate your notes and I will be very happy if could help me again,
as you wish. Let me know…

See you
N.


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