|
Boost : |
Subject: Re: [boost] [function] functionwrappingwithnoexceptionsafetyguarantee
From: Daniel Walker (daniel.j.walker_at_[hidden])
Date: 2010-11-07 18:24:51
On Sun, Nov 7, 2010 at 4:14 PM, Peter Dimov <pdimov_at_[hidden]> wrote:
> Daniel Walker wrote:
> On Sat, Nov 6, 2010 at 7:53 PM, Peter Dimov <pdimov_at_[hidden]> wrote:
>>
>> > void throw_bad_function_call()
>> > {
>> > throw bad_function_call();
>> > }
>> >
>> > function<void()> f( &throw_bad_function_call );
>> >
>> > doesn't take up any additional space per type, unless of course the >
>> > program
>> > never stores a function pointer into function<>.
>>
>> This is a special case: all targets are function pointers of the same
>> type, right?
>
> No. It's enough for one of them to be.
Oh, I see, if the user ever assigns a function pointer target, then
you can reuse the vtable from the empty target. OK, that's a
reasonable optimization, but it doesn't decrease the upper bound on
space overhead, which is reached when no user-assigned target has the
same type as the empty target.
>
>> On my system, the text segment grows by up to 14% when boost::function(
>> &throw_bad_function_call ) is used for empty wrappers.
>
> It's very uncommon for real code to not already contain the necessary
> instantiations or the equivalent of throw_bad_function_call itself.
Actually, I just saw a real world example the other day. The benchmark
that Domagoj suggested (the Boost.Signal benchmark code from
Christophe Prud'homme) does not use function pointers and would not
benefit from your suggestion. So, I don't think we can assume it is
uncommon for boost::function to be used without function pointers. (On
a personal note, the first time I started using boost::function was to
store the return value of boost::bind, so none of my old code assigned
boost::function with a function pointer. I imagine there are others
who came down the same road as me.)
> As soon
> as you put a function pointer into boost::function, you ought to get the
> instantiations; and as soon as you call it, you ought to get code that
> throws bad_function_call. Or I may be missing something.
No, you're correct with respect to the text segment. You get all the
instantiations from the first function pointer target. However, if the
user does not assign a function pointer, then the increased text
segment overhead from using an "empty" function pointer approaches 14%
on my system.
Again, all of this just further illustrates that the costs and
benefits of the static empty scheme vary according to circumstances.
Some users will experience little cost and/or little benefit. Those
who decide that the benefit merits the cost can choose to use the
alternative scheme. But I see no reason to increase the costs for any
user when there is no guarantee that there will be some benefit. The
benchmarks demonstrate that removing the null pointer check from
operator() does not always yield a significant time savings.
Daniel Walker
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk