|
Boost : |
Subject: Re: [boost] [function] function wrapping with no exceptionsafetyguarantee
From: Daniel Walker (daniel.j.walker_at_[hidden])
Date: 2010-10-12 15:14:58
On Tue, Oct 12, 2010 at 2:09 PM, David Abrahams <dave_at_[hidden]> wrote:
> At Tue, 12 Oct 2010 13:48:37 -0400,
> Daniel Walker wrote:
>>
>> > I'm sorry if I missed something important here, but has everybody
>> > really considered the consequences of Peter Dimov's post, where he
>> > wrote:
>> >
>> >> This example implies that unsafe_function is inherently more
>> >> efficient, but this need not be so. An empty function may point to
>> >> throw_bad_function_call instead of NULL.
>> >
>> > One could swap out throw_bad_function_call for any behavior you like.
>>
>> unsafe_function is not inherently more efficient. In optimized object
>> code (gcc -02 or MSVC Release mode) the difference between invoking
>> unsafe_function or boost::function is minuscule (on the order of
>> hundreds of picoseconds). Peter's post similarly relies on removing
>> the NULL pointer check for performance gains. This may be a good idea
>> or it may be a case of premature optimization; whether or not it
>> improves performance depends on the compiler's optimization. But
>> either way, efficiency is tangential to the issue of boost::function's
>> dependency on Boost.Exception.
>
> Is *that* the core issue here? Because it seems like the issue has
> been about various other things earlier in this conversation.
That's my interpretation of the core issue. Efficiency seems like a
side issue to me since in optimized object code operator() seems to
run in about the same amount of time with or with out the NULL pointer
check.
>
>> Also, swapping out throw_bad_function call does not directly address
>> the boost::function/Boost.Exception coupling issue. If
>> boost::function is going to offer a strong exception safety
>> guarantee, then I believe Boost.Exception is the best way to
>> implement that guarantee, no matter how boost::function gets around
>> to calling boost::throw_exception. (I also think boost::function
>> should continue to offer the strong guarantee.)
>
> Which operation of boost::function are you talking about, that offers
> the strong guarantee? And how can Boost.Exception be a way to achieve
> the strong guarantee?
operator() offers a strong guarantee in that it either calls the
target or calls boost::throw_exception. I don't mean Boost.Exception
is used to "achieve" the guarantee, but to implement it; i.e. in the
case where the wrapper is empty, boost::throw_excpetion can be used
instead of a throw statement. This is preferable because it allows the
exception to be reported with or without RTTI.
>
>> But some users are asking for a function object wrapper that is not
>> coupled with Boost.Exception.
>
> Why?
Some users who do not use RTTI (e.g. on some embedded system), do not
want to take the time to configure Boost.Exception for their platform,
and without configuring Boost.Exception, they get unexpected link
errors, because boost::throw_exception is undefined.
>
>> The simplest way to decouple them is to provide a function object
>> wrapper without the strong exception safety guarantee.
>>
>> >> > <snip>
>> >> > However, here http://lists.boost.org/Archives/boost/2010/01/160908.php you
>> >> > can see results that show a measurable difference when function<> is
>> >> > configured to mark itself as nothrow...
>> >>
>> >> The goal of unsafe_function is not to provide a wrapper that doesn't
>> >> throw, but to provide a wrapper with no exception safety guarantee.
>> >
>> > If that's *really* its goal, unsafe_function is strictly unneeded.
>> > boost::function already satisfies all your requirements (and more).
>>
>> boost::function always provides a strong exception safety guarantee.
>> Specifically, if its preconditions are not met, it calls
>> boost::throw_exception.
>
> That's not strong exception-safety. That's throwing an exception
> where an assert belongs. :-(
I'm using the following definition of strong exception safety.
"The strong guarantee: that the operation has either completed
successfully or thrown an exception, leaving the program state exactly
as it was before the operation started."
http://www.boost.org/community/exception_safety.html
I suppose there is a nuance here in that the target function could
throw, so more formally we could say boost::function has strong
exception safety if the target function has strong exception safety.
Here the definition of the phrase "thrown an exception" depends on the
definition of boost::throw_exception, which is user customizable.
>
>> This is true whether or not the system has
>> RTTI. This is great for some users, but others have asked for a
>> function object wrapper that does not call boost::throw_exception. A
>> simple way to meet this requirement is to provide a function object
>> wrapper that is exception unsafe, like a typical function pointer for
>> example, and that is what unsafe_function does.
>
> IMO a better way to do it would be to make a function object that
> has no empty state.
I'm amenable to that. What would you call it?
>
>> > I think if you're looking to supply motivation for unsafe_function,
>> > you'll need to describe the goal differently. ;-)
>>
>> How about this. Typically, function pointers have no RTTI dependency
>> (and no dependency on Boost.Exception) and are exception unsafe.
>
> In what sense are function pointers exception-unsafe?!
Their behavior is undefined when they are null; i.e. when they are
invoked they offer neither a basic, strong nor nothrow guarantee.
>
>> unsafe_function is a function object wrapper that behaves more like
>> a function pointer with respect to exception safety.
>
> I am beginning to think you have a different definition of exception
> safety from the rest of the world.
Well, it's important to use similar definitions. I'm trying to stick
to the definition above. How can I do this better?
Daniel Walker
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk