|
Boost : |
Subject: Re: [boost] [function] function wrapping with no exceptionsafetyguarantee
From: Daniel Walker (daniel.j.walker_at_[hidden])
Date: 2010-10-21 19:05:12
On Thu, Oct 21, 2010 at 6:13 PM, Edward Diener <eldiener_at_[hidden]> wrote:
> On 10/21/2010 6:05 PM, Daniel Walker wrote:
>>
>> On Thu, Oct 21, 2010 at 2:25 AM, Doug Gregor<doug.gregor_at_[hidden]>
>> wrote:
>>>
>>> On Wed, Oct 20, 2010 at 1:51 PM, Daniel Walker
>>> <daniel.j.walker_at_[hidden]> wrote:
>>>>
>>>> On Tue, Oct 19, 2010 at 4:56 AM, David Abrahams<dave_at_[hidden]>
>>>> wrote:
>>>>>
>>>>> At Tue, 19 Oct 2010 01:06:00 -0700,
>>>>> Emil Dotchevski wrote:
>>>>>>
>>>>>> On Tue, Oct 19, 2010 at 12:34 AM, Domagoj Saric<dsaritz_at_[hidden]>
>>>>>> wrote:
>>>>>>>
>>>>>>> "Emil Dotchevski"<emil_at_[hidden]> wrote in message
>>>>>>> news:AANLkTi=1J3+hD0Oh3Le+6-jfnwDLYpTn_A7a6x=oZFnz_at_mail.gmail.com...
>>>>>>>
>>>>>>>> ... at worst they'd be mad that you've used
>>>>>>>> Boost (that's common in games, for example.)
>>>>>>>
>>>>>>> Shall we disregard all those cases (of Boost rejection) as irrational
>>>>>>> rants
>>>>>>> (as admittedly they often are, be it of the 'corporate policy' type
>>>>>>> or of
>>>>>>> the Linus Torvalds type) or shall it be admitted that after all,
>>>>>>> sometimes,
>>>>>>> they actually are based on real objections (that Boost, or parts of
>>>>>>> it, made
>>>>>>> some not-so-happy efficiency compromising choices)...?
>>>>>>
>>>>>> You can't talk about Boost efficiency in general. As difficult as it
>>>>>> is to pull apart, Boost contains individual components. Are we talking
>>>>>> about the efficiency of Boost Function then? I'm sure if someone
>>>>>> manages to speed it up, many people on this mailing list (not to
>>>>>> mention the folks who are implementing std::function) would be very
>>>>>> interested to see how it can be done.
>>>>>
>>>>> I think we already know one way: we can easily get rid of the separate
>>>>> empty() check by making sure empty boost::functions all invoke a
>>>>> function that throws bad_function_call.
>>>>
>>>> After taking a closer look at this idea, I don't think it is possible
>>>> to do this without either changing boost::function's semantics or
>>>> incurring other runtime expenses.
>>>>
>>>> First of all, boost::function can be in an empty state for two
>>>> reasons: either it has not been assigned a target function or there
>>>> has been a problem with the internal target management system. Both of
>>>> these conditions are tested simultaneously by the current empty check
>>>> in operator(). If we get rid of the empty check, we will no longer be
>>>> checking that the target management system is in working order and
>>>> able to dispatch function calls (or more specifically, that
>>>> boost::function's internal vtable pointer is non-null). If the target
>>>> management system is not in an usable state, then we cannot dispatch a
>>>> default "empty" function that throws bad_function_call. So, if we get
>>>> rid of the current empty check but retain the current target
>>>> management system, we open the possibility that boost::function could
>>>> be in an empty state but would not throw when invoked, which would be
>>>> a change in semantics.
>>>
>>> The latter "state" isn't a real state; it only exists if there's a bug
>>> in boost::function, and we don't design around bugs.
>>
>> Right. I don't mean the management system has a bug, I mean that it
>> has encountered a problem, for example, cloning the target. So,
>> boost::function could be empty because it has never been assigned a
>> target or because the most recent attempt to assign a target failed...
>> or because it was cleared by the user calling clear(). Are those all
>> of the scenarios that can lead to an empty boost::function?
>
> I don't mean to question the design of boost::function but wouldn't the
> inability of cloning a target, or assign a target, be a problem which should
> lead to an exception being thrown ?
Right, but suppose boost::function was instantiated outside of the try
block where the assignment fails. Then after the exception is thrown
and handled, the boost::function object could still be used.
But actually, I just noticed that, even though the portable function
wrappers are empty after an assignment failure, boost::function is not
actually cleared. So, in fact, a failed assignment is NOT a scenario
that leads to an empty state, as I first thought. This is probably an
oversight/bug in the portable wrappers, right?
>
> I would assume that boost::function not having a target would normally only
> occur if no target had been set or if the user removed a target which had
> been set.
Right, and indeed, this appears to be the case... unless there's some
other scenario we overlooked...
Daniel Walker
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk