Boost logo

Boost :

Subject: Re: [boost] [function] function wrapping with no exceptionsafetyguarantee
From: Daniel Walker (daniel.j.walker_at_[hidden])
Date: 2010-10-20 16:51:50

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
>> >
>> >
>> >> ... 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.

Alternatively, we could rewrite the target management mechanisms to
ensure that boost::function always has a usable vtable object. This
implies providing a defualt "empty" vtable, which boost::function's
vtable pointer could refer to when in an empty state, so that the
pointer is always non-null. There would need to be a different "empty"
vtable each time boost::function is instantiated with a different call
signature, so that the "empty" vtable can be used seamlessly by
operator() for any call signature. These "empty" vtable objects could
not be allocated on demand, since they would need to be available to
boost::function even in the event of heap allocation failures. So,
adding "empty" vtable objects would increase the space requirements of
boost::function; each template instantiation would need two
corresponding vtable objects, one for actual targets and one as a
fallback that throws bad_function_call. (The "empty" vtable objects
could be stored statically, but static storage is also a very precious
resource on many platforms.) Not all users would appreciate this
trade-off; i.e. an increase in the space overhead for a small decrease
in time overhead (with compiler optimization the time savings are
minuscule, in my experience).

I've been studying boost::function's implementation for a while, but
perhaps I've missed something. Does anyone have any other insights?

Daniel Walker

Boost list run by bdawes at, gregod at, cpdaniel at, john at