
On Tue, Oct 19, 2010 at 4:56 AM, David Abrahams <dave@boostpro.com> 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@gmail.com> wrote:
"Emil Dotchevski" <emil@revergestudios.com> wrote in message news:AANLkTi=1J3+hD0Oh3Le+6-jfnwDLYpTn_A7a6x=oZFnz@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. 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