Boost logo

Boost :

Subject: Re: [boost] [function] function wrapping and exception safety recap
From: Daniel Walker (daniel.j.walker_at_[hidden])
Date: 2010-10-11 15:57:01


On Mon, Oct 11, 2010 at 3:20 PM, Emil Dotchevski
<emil_at_[hidden]> wrote:
> On Mon, Oct 11, 2010 at 11:53 AM, Daniel Walker
> <daniel.j.walker_at_[hidden]> wrote:
>> On Mon, Oct 11, 2010 at 2:45 PM, Daniel Walker
>> <daniel.j.walker_at_[hidden]> wrote:
>>> On Mon, Oct 11, 2010 at 2:05 PM, Emil Dotchevski
>>> <emil_at_[hidden]> wrote:
>>>> On Mon, Oct 11, 2010 at 10:45 AM, Daniel Walker
>>>> <daniel.j.walker_at_[hidden]> wrote:
>>>>> On Mon, Oct 11, 2010 at 2:49 AM, Nevin Liber <nevin_at_[hidden]> wrote:
>>>>>> On 11 October 2010 00:01, Emil Dotchevski <emil_at_[hidden]> wrote:
>>>>>>> On Sat, Oct 9, 2010 at 12:38 PM, Daniel Walker
>>>>>>> <daniel.j.walker_at_[hidden]> wrote:
>>>>>>>> Finally, there have been suggestions to alter boost::function's
>>>>>>>> exception safety guarantee directly through either policies or
>>>>>>>> constructor options.
>>>>>>>
>>>>>>> We used to have an Allocator parameter to the boost::function template
>>>>>>> and it was removed (just in time for this change to also be reflected
>>>>>>> in C++0x) to reduce coupling.
>>>>>>
>>>>>> So what exactly is the proposed behavior if the function object cannot
>>>>>> fit in the small object optimization space of unsafe_function and the
>>>>>> allocation fails?
>>>>>
>>>>> As proposed, unsafe_function has the same semantics as boost::function
>>>>> with one (and only one) exception: the behavior of operator() is
>>>>> undefined when it has no target.
>>>>
>>>> If that was the only motivation, you could just disable exception
>>>> handling, and then define:
>>>>
>>>> namespace boost
>>>> {
>>>>  void throw_exception( std::exception const & )
>>>>  {
>>>>    assert(0);
>>>>  }
>>>> }
>>>>
>>>
>>> Correct. But users have complained about this, which is exactly the
>>> motivation for unsafe_function. It works out-of-the-box in RTTI-free
>>> environments with no dependency on boost::throw_exception. It's a
>>> simple problem really.
>>
>> P.S. Sorry I spoke to soon. That's not exactly correct. A user could
>> do what you describe, but boost::function could not, since that would
>> change its exception safety guarantee; i.e. it would no longer throw
>> (or call a user definable function) when it had no target.
>
> This is not exception safety issue, it is a choice between defined and
> undefined behavior.

A strong exception safety guarantee is a defined behavior.
unsafe_function removes that guarantee and leaves its behavior
undefined when its preconditions aren't met; namely, it dereferences a
null pointer, which has an undefined (and undefinable) behavior.

>
> Undefined behavior is desirable when there are performance or
> portability problems with defining a behavior. No such problems exist
> with the current boost::function semantics. You can't both want
> undefined behavior and be against any particular behavior, such as
> throwing an exception or calling a function.

boost::function's behavior is defined in all circumstance, even when
it's preconditions are met. That's a necessary requirement of a strong
exception safety guarantee. However, some users have complained about
the definitions. From listening, I believe they would prefer a
function wrapper that behaved more like a function pointer when its
preconditions are not met; i.e. they do not want RTTI or
boost::throw_exception. The simplest way to establish this is to adopt
no exception safety guarantee. (I am trying to follow Dave's exception
safety paper by the way. I linked to it in the documentation in the
patch, to provide users some background.)

>
> The only viewpoint from which this discussion makes sense to me is
> that it might be beneficial to remove the coupling between
> boost/function.hpp and boost/throw_exception.hpp,
> <snip>

Yes, that's exactly the way you should look at it. However, the
coupling is a good thing for boost::function. If you're going to offer
a strong exception safety guarantee, Boost.Exception is a good way to
implement it. So, for one group of users, boost::function is perfect
as is.

But one size does not fit all.

Another group of users, would like a function wrapper without coupling
Boost.Exception, and indeed, without an exception safety guarantee.
unsafe_function address the demands of this second group of users.

Daniel Walker


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