Boost logo

Boost :

Subject: Re: [boost] Rave for proposed Boost.Local (functions)
From: Jeffrey Lee Hellrung, Jr. (jhellrung_at_[hidden])
Date: 2011-02-06 15:23:23


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?

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

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

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

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

> 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)?

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

- Jeff


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk