Boost logo

Boost :

Subject: Re: [boost] [variant2] Need rationale for never-empty guarantee
From: Andrey Semashev (andrey.semashev_at_[hidden])
Date: 2019-03-02 11:35:02


On 3/2/19 2:24 PM, Andrey Semashev wrote:
> On 3/2/19 1:44 PM, Andrzej Krzemienski via Boost wrote:
>> sob., 2 mar 2019 o 10:36 Andrey Semashev via Boost
>> <boost_at_[hidden]>
>> napisał(a):
>>
>>> On 3/2/19 11:56 AM, Andrzej Krzemienski via Boost wrote:
>>>>
>>>> This is where my imagination fails me. I cannot imagine why upon
>>> bad_alloc
>>>> I would be stopping the stack unwinding and determining size of my
>>> vectors.
>>>> This is why I ask about others' experience with real-world correct
>>>> code.
>>>
>>> That is not an unimaginable scenario. If you have two branches of code,
>>> one requiring more memory but better performance, and the other that is
>>> slower (or maybe lacking some other qualities but still acceptable) and
>>> less resource consuming, operating on the same vector, you will want the
>>> vector to stay valid if memory allocation fails. Although not
>>> specifically with vectors, I had cases like this in real world.
>>
>> Thanks for sharing your experience.
>> I am not sure we are on the same page here. Are you describing an
>> operation
>> where an operation on vector fails to allocate more storage and therefore
>> throws and leaves the *value* of the vector unchanged (i.e., an operation
>> with strong exception safety guarantee)? Or are you describing an
>> operation
>> that reuses memory owned by a vector and discards the vector's value?
>> Boith
>> these cases can be described as "never observing the value after a failed
>> operation with a basic exception safety guarantee". Or are you
>> describing a
>> different situation?
>
> As I mentioned, I usually don't rely on standard containers in
> situations when I want complete control over memory allocations, so
> vector is not the component I was talking about. However, the program
> logic is often closer to the strong guarantee because I would normally
> try allocating memory early, before the real work is done. Though, in
> some instances some data is modified in non-harmful way in case of OOM.
>
> There are a few instances when I want to "undo" the failed operation, in
> which case the code relies on a particular "half-way through" state of
> the program. The rollback process requires that there is a known number
> of steps that were completed before failure, and the data associated
> with those steps is in a valid state. From the failed operation
> standpoint, this is a "strict" basic guarantee, from the underlying
> components, like containers, this is almost certainly a strong guarantee.
>
> I call "strict" basic guarantee, as opposed to just basic guarantee, a
> case, where the program is allowed to have a *subset* of valid states
> upon failure. Maybe there is a better term for this. I mean, for a
> hypothetical initially non-empty vector, a basic guarantee push_back()
> is allowed to leave the vector empty upon failure, but that might not be
> an acceptable outcome for a higher level user's program. In my case, I
> require a particular state of the program upon my operation failure.
> This state may not be the same as before the operation started, but it
> must at least include results of the steps the failed operation has
> managed to complete. This allows these steps to be rolled back.

I'll add that I could probably agree with you that observing the result
of a failed "purely" basic guarantee operation is not useful. You
basically have no guarantees about the state of the program, except that
the objects can be destroyed or re-initialized from scratch. However,
"strict" basic guarantee is more prevalent in practice, even though it
is often not documented so, and observing result of failed such
operation can be useful, provided that the restrictions on the operation
failure outcome match your requirements.


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