[serialization] exception-safety of container-serialization

Dear All, I have just added serialization to Boost.Ptr container. I briefly discussed an issue with Robert, namely that the current implementation calls clear() before reading the new values. The alternative is to provide roll-back guarantee by default by creating a local container and swap() in the end. By default this would temporarily use more memory. IMO we should go for the strong guarantee. Any thoughts? -Thorsten

On Feb 17, 2006, at 8:48 AM, Thorsten Ottosen wrote:
I have just added serialization to Boost.Ptr container. I briefly discussed an issue with Robert, namely that the current implementation calls clear() before reading the new values.
The alternative is to provide roll-back guarantee by default by creating a local container and swap() in the end. By default this would temporarily use more memory.
IMO we should go for the strong guarantee. Any thoughts?
I think the basic guarantee is enough here. Truly paranoid users can copy+swap themselves, but for most purposes you are better off not having two copies of the container in memory. Most people need better performance more than they need the strong guarantee. Doug

Doug Gregor <dgregor@cs.indiana.edu> writes:
On Feb 17, 2006, at 8:48 AM, Thorsten Ottosen wrote:
I have just added serialization to Boost.Ptr container. I briefly discussed an issue with Robert, namely that the current implementation calls clear() before reading the new values.
The alternative is to provide roll-back guarantee by default by creating a local container and swap() in the end. By default this would temporarily use more memory.
IMO we should go for the strong guarantee. Any thoughts?
I think the basic guarantee is enough here. Truly paranoid users can copy+swap themselves, but for most purposes you are better off not having two copies of the container in memory. Most people need better performance more than they need the strong guarantee.
That's one right way to look at it. To look at it another way, if you provide the strong guarantee by copy-and-swap up front, there's no way to recover the efficiency for the (majority of) people who only need the basic guarantee. The *only* reason to use copy-and-swap around the implementation of an operation is to make it less error-prone. This: X& operator=(X rhs) { rhs.swap(*this); return *this; } is almost idiot-proof if you have a working copy ctor. Although for many classes it comes at a substantial efficiency cost when compared with a more laboriously worked-out assignment operator that gives the basic guarantee, I can't fault anyone for going for correctness and low maintenance cost first, and efficiency second. Incidentally, I don't know of any operations other than assignment whose maintainability are helped by copy/swap in this way. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
Doug Gregor <dgregor@cs.indiana.edu> writes:
I think the basic guarantee is enough here. Truly paranoid users can copy+swap themselves, but for most purposes you are better off not having two copies of the container in memory. Most people need better performance more than they need the strong guarantee.
That's one right way to look at it.
Ok, so if efficiency really matters here, would it not be best not to call clear(), but try to assign to the existing elements or create them in-place in the container? IIUC, all elements in a container are first created on the stack and then copied into the container. Isn't this right Robert? -Thorsten

Thorsten Ottosen <tottosen@dezide.com> writes:
David Abrahams wrote:
Doug Gregor <dgregor@cs.indiana.edu> writes:
I think the basic guarantee is enough here. Truly paranoid users can copy+swap themselves, but for most purposes you are better off not having two copies of the container in memory. Most people need better performance more than they need the strong guarantee.
That's one right way to look at it.
Ok, so if efficiency really matters here, would it not be best not to call clear(), but try to assign to the existing elements or create them in-place in the container?
Yes, if efficiency really matters, and the container isn't empty, and no other considerations contravene this, it would be better. However, I think most of the time the container starts out empty anyway, and there would only be savings in edge cases. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
Thorsten Ottosen <tottosen@dezide.com> writes:
Ok, so if efficiency really matters here, would it not be best not to call clear(), but try to assign to the existing elements or create them in-place in the container?
Yes, if efficiency really matters, and the container isn't empty, and no other considerations contravene this, it would be better. However, I think most of the time the container starts out empty anyway, and there would only be savings in edge cases.
The latter case "create them in-place in the container" still seems like something that will remove some overhead. Sad that the standard can help us here. -Thorsten

Thorsten Ottosen wrote:
Dear All,
I have just added serialization to Boost.Ptr container. I briefly discussed an issue with Robert, namely that the current implementation calls clear() before reading the new values.
The alternative is to provide roll-back guarantee by default by creating a local container and swap() in the end. By default this would temporarily use more memory.
IMO we should go for the strong guarantee. Any thoughts?
I have been using basic-guarantee deserialization. It is easy for the client to deserialize a local container and swap if strong guarantee is desirable.

Peter Dimov wrote:
Thorsten Ottosen wrote:
Dear All,
I have just added serialization to Boost.Ptr container. I briefly discussed an issue with Robert, namely that the current implementation calls clear() before reading the new values.
The alternative is to provide roll-back guarantee by default by creating a local container and swap() in the end. By default this would temporarily use more memory.
IMO we should go for the strong guarantee. Any thoughts?
I have been using basic-guarantee deserialization. It is easy for the client to deserialize a local container and swap if strong guarantee is desirable.
Ok, sounds like we have a winner. -Thorsten

Thorsten Ottosen ha escrito:
Dear All,
I have just added serialization to Boost.Ptr container. I briefly discussed an issue with Robert, namely that the current implementation calls clear() before reading the new values.
The alternative is to provide roll-back guarantee by default by creating a local container and swap() in the end. By default this would temporarily use more memory.
IMO we should go for the strong guarantee. Any thoughts?
I would NOT go for the strong guarantee for the following two reasons: 1. Given the basic guarantee, all-or-nothing semantics can be implemented externally, and as efficiently as you'd do it internally. 2. It might be of interest to keep a partially recovered object. For instance, think of the situation in which a container is being marshalled thru a socket and you lose internet conectivity. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

Joaquín Mª López Muñoz <joaquin@tid.es> writes:
Thorsten Ottosen ha escrito:
Dear All,
I have just added serialization to Boost.Ptr container. I briefly discussed an issue with Robert, namely that the current implementation calls clear() before reading the new values.
The alternative is to provide roll-back guarantee by default by creating a local container and swap() in the end. By default this would temporarily use more memory.
IMO we should go for the strong guarantee. Any thoughts?
I would NOT go for the strong guarantee for the following two reasons:
1. Given the basic guarantee, all-or-nothing semantics can be implemented externally, and as efficiently as you'd do it internally. 2. It might be of interest to keep a partially recovered object. For instance, think of the situation in which a container is being marshalled thru a socket and you lose internet conectivity.
That brings up an interesting point: you have to make sure, when writing deserialization for a class, that partial deserialization won't leave its instances with broken invariants. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
Joaquín Mª López Muñoz <joaquin@tid.es> writes:
2. It might be of interest to keep a partially recovered object. For instance, think of the situation in which a container is being marshalled thru a socket and you lose internet conectivity.
That brings up an interesting point: you have to make sure, when writing deserialization for a class, that partial deserialization won't leave its instances with broken invariants.
Well, can't we think if deserialization as just another way of constructing an object? So if deserialization fails, it's like when construction fails and you might throw or abort. No? -Thorsten

Thorsten Ottosen <tottosen@dezide.com> writes:
Well, can't we think if deserialization as just another way of constructing an object?
So if deserialization fails, it's like when construction fails and you might throw or abort. No?
No; the usual deserialization method starts with an already-constructed object. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
Thorsten Ottosen <tottosen@dezide.com> writes:
Well, can't we think if deserialization as just another way of constructing an object?
So if deserialization fails, it's like when construction fails and you might throw or abort. No?
No; the usual deserialization method starts with an already-constructed object.
In boost's framework, sure. In others, eg. one found in C#, each class has a special constructor. -Thorsten

Thorsten Ottosen <tottosen@dezide.com> writes:
David Abrahams wrote:
Thorsten Ottosen <tottosen@dezide.com> writes:
Well, can't we think if deserialization as just another way of constructing an object?
So if deserialization fails, it's like when construction fails and you might throw or abort. No?
No; the usual deserialization method starts with an already-constructed object.
In boost's framework, sure. In others, eg. one found in C#, each class has a special constructor.
But we're discussing Boost's framework (which also happens to support the ctor method; it's just not the usual way). -- Dave Abrahams Boost Consulting www.boost-consulting.com
participants (5)
-
David Abrahams
-
Doug Gregor
-
Joaquín Mª López Muñoz
-
Peter Dimov
-
Thorsten Ottosen