Boost logo

Boost :

Subject: Re: [boost] [contract] oldof failure not in N1962?
From: lcaminiti (lorcaminiti_at_[hidden])
Date: 2011-07-19 16:54:14


Dave Abrahams wrote:
>
> on Tue Jul 19 2011, Lorenzo Caminiti <lorcaminiti-AT-gmail.com> wrote:
>
>>
>> I'm sorry I managed to confuse everyone with this post
>> because I meant to ask something different...
>>
>> My question instead, is: What shall I do if I fail to copy an oldof
>> value?
>
> I don't think I misunderstood your question, although I don't happen to
> know what "oldof" means here...
>
>> Specifically, what shall I do if an oldof copy throws an
>> exception? This is not specified by N1962 (as far as I can see). I
>> decided that if I fail to copy and olfof value then I call the
>> postcondition_broken handler but only after executing the body (even
>> if oldof values are internally copied before the body is executed).
>
> As I said, that doesn't make any sense to me, for the reasons I already
> gave, and because failure to allocate memory in precondition checking
> does not amount to a broken postcondition.
>

But in this case the failure is in allocating memory to copy an old value
and NOT in checking preconditions.

Failing to copy an old value (e.g., for an alloc failure) will indeed not
allow to check postconditions because the postconditions use the old value.
Therefore, the postconditions should be considered failed because they
cannot be checked and postcondition_broken should be called.

All of this reasoning does not have anything to do with the preconditions
but only with the postconditions. Old-of values are part of (i.e., they are
specified and used by) the postconditions (even if they are internally
evaluated before the body and after the eventual preconditions).

For example (following N1962 proposed syntax):

    void push_back(T const& value)
        postcondition {
            size() == oldof size() + 1;
        }
    {
        vector_.push_back(value);
    }

Will be effectively implemented by something like this (ignoring class
invariants for simplicity):

    void push_back(T const& value) {
        // eventual preconditions will be checked here

        bool oldof_failed = false;
        size_type old_size;
        try {
            old_size = size(); // old-of copy
        } catch(...) {
            oldof_failed = true;
        }

        // the body can be called here (regardless of oldof_failed) because
precondition passed
        vector_.push_back(value); // body

        try {
            if(oldof_failed) throw runtime_error("old-of failed");
            if(!( size() == old_size + 1 )) throw logic_error("postcondition
failed");
        } catch(...) {
            postcondition_broken(); // will call std::terminate (by default)
        }
    }

Where:

    void default_handler() { std::terminate(); }
    typedef void (*broken_handler)();
    broken_handler postcondition_broken = &default_handler;
    void set_postcondition_broken(broken_handler h) { postcondition_handler
= h; }

You can redefine postcondition_broken to be smart and say "if there is an
active exception that indicates the failure was because of an old-of copy
then free some memory and signal the caller to retry the push_back call,
else call std::terminate".

> That said, the function itself might be a nothrow function and turning
> on contract checking should not change the function's semantics. That
> would be my only argument against throwing an exception.
>

--Lorenzo

--
View this message in context: http://boost.2283326.n4.nabble.com/boost-contract-oldof-failure-not-in-N1962-tp3676021p3679306.html
Sent from the Boost - Dev mailing list archive at Nabble.com.

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