|
Boost : |
Subject: Re: [boost] Rave for proposed Boost.Local (functions)
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2011-02-06 20:46:56
On Sun, Feb 6, 2011 at 3:23 PM, Jeffrey Lee Hellrung, Jr.
<jhellrung_at_[hidden]> wrote:
> On 2/6/2011 9:17 AM, Lorenzo Caminiti wrote:
> [...]
>>
>> I am posting here the code generated by the macros which might help
>> curious readers in spotting costly operations performed by Boost.Local
>> (if there are any). This of course does not include the preprocessing
>> time. (I hope it's not too much code... just try to get passed the
>> typeof noise at the beginning...)
>
> Is the use of Boost.Typeof optional? I.e., can I just provide the types of
> the arguments and bound variables myself?
No but I think you can simply use a normal (not bound) local function
parameters to do this:
int main() {
double sum = 0.0;
int factor = 10;
BOOST_LOCAL_FUNCTION(
(void) (add)( (double)(num) (const int)(factor) (double&)(sum) )
// No binds so no typeof.
) {
sum += factor * num;
std::clog << "Summed: " << sum << std::endl;
} BOOST_LOCAL_FUNCTION_END(add)
add(100.0, factor, sum);
}
>> int main() {
>> double sum = 0.0;
>> int factor = 10;
>>
>> // BOOST_LOCAL_FUNCTION( (void) (add)( (double)(num) (const
>> bind)((factor)) ) expands to:
>> // Determining bound variable types (taken from Boost.ScopeExit).
>> typedef void (*boost_se_tag_0_add36)(int factor );
>> typedef void (*boost_se_tag_1_add36)(int&sum );
>
> Where did sum come from??? I don't see it in the BOOST_LOCAL_FUNCTION( ...
> ) line...I guess you're *really* showing the expansion of a similar macro
> invocation, but with sum also bound...?
Ooops, I missed it. The code I posted is the expansion of this:
int main() {
double sum = 0.0;
int factor = 10;
BOOST_LOCAL_FUNCTION(
(void) (add)( (double)(num) (const bind)((factor)) (bind)((&sum)) )
) {
sum += factor * num;
std::clog << "Summed: " << sum << std::endl;
} BOOST_LOCAL_FUNCTION_END(add)
add(100.0);
}
>> typedef
>> __typeof__(boost::type_of::ensure_obj(boost::scope_exit::aux::wrap(
>> boost::scope_exit::aux::deref(factor,
>> (boost_se_tag_0_add36)0))))
>> boost_se_wrapped_t_0_add36;
>> typedef boost_se_wrapped_t_0_add36::type boost_se_capture_t_0_add36;
>> typedef
>> __typeof__(boost::type_of::ensure_obj(boost::scope_exit::aux::wrap(
>> boost::scope_exit::aux::deref(&sum,
>> (boost_se_tag_1_add36)0))))
>> boost_se_wrapped_t_1_add36;
>> typedef boost_se_wrapped_t_1_add36::type boost_se_capture_t_1_add36;
>
> I have a feeling there should be a typename here when
> boost_se_wrapped_t_1_add36 is a dependent type...
Yes, you use `BOOST_LOCAL_FUNCTION_TPL` in dependent type contexts
(from within templates, etc) which adds the typenames. (It's in the
docs.)
>> struct boost_se_params_t_add36 {
>> typedef boost_se_capture_t_0_add36 boost_se_param_t_0_add36;
>> typedef boost_se_capture_t_1_add36 boost_se_param_t_1_add36;
>> boost::scope_exit::aux::member< boost_se_param_t_0_add36,
>> boost_se_tag_0_add36>
>> boost_se_param_0_add36;
>> boost::scope_exit::aux::member< boost_se_param_t_1_add36,
>> boost_se_tag_1_add36>
>> boost_se_param_1_add36;
>> } boost_local_auxXparams_add36 = {
>> { boost::scope_exit::aux::deref(factor, (boost_se_tag_0_add36)0)
>> }
>> , { boost::scope_exit::aux::deref(&sum, (boost_se_tag_1_add36)0) }
>> };
>> boost::scope_exit::aux::declared< boost::scope_exit::aux::resolve<
>> sizeof(boost_local_auxXargs)>::cmp1<0>::cmp2>
>> boost_local_auxXargs;
>
> Shouldn't the name boost_local_auxXargs have some kind of line number or
> counter or function name pasted into it to prevent name collision of
> multiple BOOST_LOCAL_FUNCTION declarations in the same scope?
No, this has to be a global extern variable declared as:
extern boost::scope_exit::aux::undeclared boost_local_auxXargs;
in one of Boost.Local headers. It's a trick carried over 100% from
Boost.ScopeExit (as I understand it, this is because only global or
static variables can be used from within a nested block
http://lists.boost.org/Archives/boost/2006/11/113658.php).
>> boost_local_auxXargs.value =&boost_local_auxXparams_add36;
>> // Functor for the local function.
>> typedef ::boost::local::function_ref< void ( double ) , 0>
>> boost_local_auxXaddXref;
>> struct boost_local_auxXfunctorXadd :
>> ::boost::local::aux::function_base< void ( double ), 0> {
>> explicit boost_local_auxXfunctorXadd(void* bind_params) :
>> boost_local_auxXparams( (boost_se_params_t_add36*)
>> bind_params) {}
>
> static_cast ? Just being picky here... ;)
Ooops, again. I'll fix this C-style cast (it probably was a quick
piece of code that I then forgot to go back and fix). Thanks.
>> void operator()( double num ) {
>> return boost_local_auxXbody( *this
>> , boost_local_auxXparams-> boost_se_param_0_add36.value
>> , boost_local_auxXparams-> boost_se_param_1_add36.value
>> , num
>> );
>> }
>> private:
>> boost_se_params_t_add36* boost_local_auxXparams;
>> static void boost_local_auxXbody( boost_local_auxXfunctorXadd&
>> add
>> , ::boost::add_const< boost_se_params_t_add36::
>> boost_se_param_t_0_add36>::type factor
>> , boost_se_params_t_add36:: boost_se_param_t_1_add36&sum
>> , double num
>> )
>>
>> // Programmers' write the local function body.
>> {
>> sum += factor * num;
>> std::clog<< "Summed: "<< sum<< std::endl;
>> }
>>
>> // BOOST_LOCAL_FUNCTION_END(add) expands to:
>> };
>> boost_local_auxXfunctorXadd boost_local_auxXobjectXadd(
>> boost_local_auxXargs.value);
>> boost_local_auxXaddXref add( boost_local_auxXobjectXadd); //
>> Finally the actual functor...
>>
>> add(100.0);
>>
>> return 0;
>> }
>>
>
> For maintenance purposes, do you plan on providing a brief sketch of the
> above mechanism (e.g., the main players in the above macro expansion, and
> the inheritance from function_base and type-erasure to simulate the binding
> of local functions to template parameters)?
Yes, I can add an Appendix with the pseudo code in the library docs.
> I remember you doing an earlier study on the performance impact of using
> this type erasure (compared to moving the local function to namespace scope
> and avoid the overhead of the virtual dispatch)...is that included in the
> documentation? I don't see it from a quick glance...
A preliminary study was hinted by John Bytheway
(http://lists.boost.org/Archives/boost/2010/09/170891.php). I have not
done any performance study of Boost.Local yet (yes, I will include
performance considerations in the docs once I do them).
-- Lorenzo
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk