
"Robert Ramey" <ramey@rrsd.com> writes:
David Abrahams [mailto:dave@boost-consulting.com] wrote:
The following message is a courtesy copy of an article that has been posted to gmane.comp.lib.boost.devel as well.
Hi Robert,
Are you going to reply to
http://article.gmane.org/gmane.comp.lib.boost.devel/131257
??
Thanks,
I considered your comments and re-wrote the section Archive Concept and it's checked into RC_1_33_0.
It's an improvement, but either you missed or intentionally discarded some of my more important remarks. The most important question was: **** Isn't something in an Archive required to call "serialize?" **** If not, how does an Archive work with Serializable types?
There are two Archive concepts. Given a set of C++ data structures consisting of Serializable types, a Saving Archive will create a sequence of bytes. Given a sequence of bytes created by a Saving Archive, a Loading Archive will reconstitute the orginal configuration of C++ data structures. Both Archive concepts are derived from the more basic concept of Archive.
This is confusing and self-contradictory. Your text clearly states that there are two Archive concepts and then goes on to describe three Archive concepts: Archive, Saving Archive, and Loading Archive.
Notation
In the following descriptions, it is assumed that: ^^^^^^^^^^^^^^^^^^^^ Strike this. You are telling the reader what these identifiers mean, not interpreting something about which you need to make some assumption.
• A is an Archive type • T is an Serializable Type • ar is an instance of type A. • x is an instance of type T. • u is an address.
An address is an abstract notion; it doesn't have any value in the type system. You have to say "u is any pointer"... but see below.
Common Type Definitions in all Archives
This should be a section for the "Archive" concept. These are not type definitions but valid expressions.
A::is_saving
An integral constant of type boost::mpl::bool_.
I'm sorry to be so blunt, but that's nonsense. A::is_saving is a type, not an integral constant, and boost::mpl::bool_ is a class template, not a type. If you mean to refer to the MPL Integral Constant concept, the correct thing to say would be: A boolean MPL Integral Constant with a link to the documentation for that concept.
Value is boost::mpl::bool_<true>
"Value?" This is also nonsense. The ::value member of an MPL Integral Constant is an integral constant, not a type, but boost::mpl::bool_<true> is a type. I normally
if the Archive is a Saving Archive (see below) and boost::mpl::bool_<false> otherwise.
A::is_loading
An integral constant of type boost::mpl::bool_. Value is boost::mpl::bool_<true> if the Archive is a Loading Archive (see below) and boost::mpl::bool_<false> otherwise.
Ditto.
Common Member Functions in all Archives
Again, these are not member functions, but valid expressions. Presumably "ar & x" can be implemented by a free function and "ar.template register_type<T>()" invokes a member function template.
ar & x
Returns a reference to ar. Appends the value of x along with other information to ar.
I think you should swap the two sentences; emphasis should be on effects and only secondarily on return value. But wait. Surely this expression, with the specified semantics, doesn't have to be valid for loading archives? Are you saying that all archives have to be able to save?
ar.template register_type<T>();
You should leave out "template." This is a little tricky, but that expression will never be valid in a context where A is not a dependent type. I realize you do need it when A is a dependent type, but the convention is to use the simpler notation. The author of an archive isn't going to be calling register_type anyway (especially not in a dependent context), so it won't help prevent him from making errors.
ar.register_type(u);
Append information about class T to the archive.
^--"s" If so then you need to say that u is an expression of type T*
This information is used to construct the correct class when a derived pointer is loaded. Invocation of this member function is referred to as "class registration". This is explained in detail in Special Considerations - Derived Pointers.
ar.library_version()
Returns an unsigned integer containing the version number of the serialization library that created the archive. This number will be incremented each time the library is altered in such a way that serialization could be altered for some type. For example, suppose the type used for a count of collection members is changed. The code that loads collections might be conditioned on the library version to make sure that libraries created by previous versions of the library can still be read.
Good!
Saving Archive
A Saving Archive is a refinement of the Archive Concept. ^--- strike "A." The Saving Archive concept refines Archive. "A saving archive" referes either to a model of Saving Archive or an instance of such a model.
Notation
In the following descriptions, it is assumed that:
• ar is an instance of a Saving Archive. • x is an instance of a Serializable Type. • u is an address.
A pointer again.
• count is an integer that can be converted to std::size_t. ^^^^^^^ no, it's an instance of any type that can be so converted. Your "strong typedef" isn't an integral type.
Common Member Functions
Valid expressions again.
ar << x
Returns a reference to ar. Appends the value of x along with other information to ar.
Doesn't this have to call serialize(...) somehow?
ar.save_binary(u, count)
Appends to the archive count bytes found at address.
Actually it must be Appends to ar the std::size_t(count) bytes found at address. but doesn't it have to call serialize(...) somehow?
Loading Archive
Notation
In the following descriptions, it is assumed that:
• ar is an instance of a Loading Archive. • x is an instance of a Serializable Type. • u, v are pointers to any type. • count is an integer that can be converted to std::size_t.
Common Member Functions in all Archives
ar >> x
Returns a reference to ar. Sets x with a value retrieved from ^^^^ I would say "to" the ar. ^^^ strike this.
Doesn't this have to call serialize(...) somehow?
ar.load_binary(u, count)
Retrieves from the archive count bytes and stores them in ^^^^^^^^^^ "ar" memory starting at address. ^^^^^^^ "u"
Doesn't this have to call serialize(...) somehow?
ar.reset_object_address(v, u)
Communicates to the archive that the object originally at address u has been moved to address v.
In order to facilitate loading of objects through a pointer and to elminate redundant loading of objects, this system implements object address tracking. Normally this is done automatically with no action required on the part of the user.
For an implementor of an archive, this whole statement is confusing. Do I need to implement object tracking, or is provided for me somehow by "this system?" Is it done automatically? If so, by whom? I think I know the answers to these questions, but I'm not sure a new reader will.
However, there are cases when an object must be de-serialized to a temporary location then moved to its final destination. This is common in loading collections.
In such cases, reset_object_address should be invoked to communicate the final address of the last item loaded. This permits the internal tables to be correctly maintained in these special cases.
ar.delete_created_pointers()
Deletes all objects created by the loading of pointers. This can be used to avoid memory leaks that might otherwise occur if pointers are being loaded and the archive load encounters an exception.
The following sentence belongs under "Archive Models."
There are archives based on text, binary and XML file formats but all have the above interface.
Given that all archives present the same public interface, specifcation of serialization is exactly the same for all archives. Archive classes have other members not mentioned here. However they are related to the internal functioning of the library and are not meant to be called by users of an archive.
Are you telling me, after all this, that there are additional requirements on archives not documented in the section on Archive concepts? I find this rather alarming. Haven't I made it abundantly clear that the concept documentation has to give at least a minimal and complete documentation of what's required of an Archive?
Implementation of new archives is discussed in New Archives - Implementation.
Which then goes on to describe some "input archive" idea that hasn't been defined, etc... <snip> Okay, I don't know what to say at this point. I'm about to give up, because I don't have the time to keep going over this. It sure seems like you want to do this your own way, rather than by following the established practices and norms. If you were just "creative" but still rigorous, it would be one thing, but it doesn't even seem like you're paying close attention to what you yourself are writing. What should I do?
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
© Copyright Robert Ramey 2002-2004. Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
You might want to update the copyright date. -- Dave Abrahams Boost Consulting www.boost-consulting.com