Boost logo

Boost :

From: Brian McNamara (lorgon_at_[hidden])
Date: 2003-10-30 18:45:21


On Thu, Oct 30, 2003 at 02:19:21PM -0800, E. Gladyshev wrote:
> --- Brian McNamara <lorgon_at_[hidden]> wrote:
> [...]
> >
> > ...the basic guarantee says that, when an exception occurs during a call
> > to f(), things are still "safe". For example, objects are still in
> > "safe" states
>
> I don't think that it is a true statement. In general
> you cannot make this assumption.
> Basic guarantees allow you to break invariants,
> so the objects may not be in a "safe" state
> at the *moment* of exception.

Not according to the definition of "basic guarantee" I'm using. See

   http://www.boost.org/more/generic_exception_safety.html

which says, among other things

   The basic guarantee: that the invariants of the component are
   preserved, and no resources are leaked.

In order to provide the basic guarantee, you have to do work. If the
class invariant is broken in the middle of a method, and an exception
is thrown, you must ensure that the class invariant is restored by the
time the method exits.

> Even if we assume that the abstract objects are "safe",
> we all know that in practice there is not such thing
> as abstract C++ machine. If we add the h/w factor into
> the picture, the question is is it still safe to try
> to use/destroy objects and possible screw everything up
> even more? I know that there is probably
> no a definite answer to this one... just brought it up
> for the heck of it. :)

Using one of your earlier examples,

   class Foo {
      int x, y; // invariant: x+y=10
   public:
      ...
      void m() {
         x = 0; // break inv.
         foo(); // may raise h/w exception
         y = 10;
      }
   };

This class does not provide the basic guarantee. In order to provide
it, it must do something like

      void m() {
         x = 0; // break inv.
         try {
            foo(); // may raise h/w exception
            y = 10;
         }
         catch(...) {
            y = 10;
            throw;
         }
      }

or

      void m() {
         x = 0; // break inv.
         ScopeGuard g( var(y)=10 ); // when g is destroyed,
            // boost::lambda function is called to restore invariant
         foo(); // may raise h/w exception
      } // restore invariant via g's destructor

Agree/disagree/other comments?

-- 
-Brian McNamara (lorgon_at_[hidden])

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