|
Boost : |
Subject: Re: [boost] [function] function wrapping with no exceptionsafetyguarantee
From: Daniel Walker (daniel.j.walker_at_[hidden])
Date: 2010-10-12 19:04:51
On Tue, Oct 12, 2010 at 4:15 PM, David Abrahams <dave_at_[hidden]> wrote:
> At Tue, 12 Oct 2010 15:14:58 -0400,
> Daniel Walker wrote:
>>
>> 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:
>> >
>> >> 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),
>
> I think that's irrelevant. Actually RTTI and EH are orthogonal in
> principle, though they use similar mechanisms and some compiler
> vendors may tie them together. In any case Boost.Exception can be
> configured not to use it.
>
>> 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.
>
> If users are going to use a subset of C++, they should not be too
> surprised that they have to add a -D option to their command-line to
> keep everything linking. Avoiding that is certainly not worth the
> cost of supporting a parallel copy of boost::function.
Sorry, I may not have been clear. In order to configure Boost.Function
to work without RTTI, you need to define a function not a
configuration macro. So, there is no -D option. This is part of the
reason that some users are frustrated.
>
>> >> 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
>
> Yes, I invented the term and wrote that definition, but no, you're not
> using it properly.
OK, thanks for the help. Sorry for the confusion.
>
> All constructors with no side-effects offer the strong guarantee, by
> the way. So asserting that a constructor offers the strong guarantee
> is not very meaningful once you know that the constructor's semantics
> are side-effect free.
>
I'm only talking about operator(), so I should have said
boost::function invocation has strong exception safety, instead of
just "boost::function has strong exception safety," which was
incorrect usage.
>> 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.
>
> Sorry, but that makes no sense. Classes don't have strong
> exception-safety. Only operations do.
Right, so I'll rephrase.
Formally, boost::function invocation has strong exception safety if
invoking 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.
>
> I don't think you can redefine the phrase throws an exception to
> mean something that might not throw an exception, and still communicate
> effectively here.
Yes, this could be confusing. For this to be meaningful you would have
to be clear about using boost::throw_exception instead of a throw
statement and the reader would need to be familiar with
Boost.Exception. But I don't think that's too much to ask.
>
>> >> 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?
>
> nonempty::function ?
OK, I might try to roll this together. It could be a better solution.
>
>> >> > 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.
>
> That is *not* exception-unsafe! There are documented preconditions on
> the function call operator, and you must satisfy them or all bets are
> off. Almost every operation in std:: has such conditions here or
> there. That doesn't make them exception-unsafe. Exception-unsafe
> means that *when* an exception is thrown, invariants are violated (or
> resources leaked).
OK. I think I see the confusion here. I was using the exception safety
guarantees to describe how an operation behaves when its preconditions
are not met, but you use the terms only to describe how an operation
behaves when an exception is thrown. With boost::function these are
the same events; it throws an exception when its preconditions aren't
met. With a function pointer, the system checks the preconditions and
may throw an exception or terminate execution with a segfault or
whatever. I was trying to make an analogy between invoking an empty
function object wrapper and invoking a null function pointer. Anyway,
to avoid confusion, I'll stop using this analogy, and I will not use
the exception safety guarantees to refer to the behavior of a function
pointer invocation.
>
>> >> 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?
>
> Other than studying the definitions and taking them literally, I don't
> know what to suggest.
Thanks. I will try to do so.
Daniel Walker
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk