2
May

Functional

   Posted by: Foxtox   in Uncategorized

Sometimes I find that I need to use delegates in C++, in the past I almost always used the fast delegate library available on codeproject, but over the last year or so I’ve been using std::tr1::functional often enough instead–functional is somewhat more powerful as you can
bind functors containing state.

I was curious if the std::tr1::functional that ships with VS2010 has any sort of SBO.

(small buffer optimization- this allows it to avoid any dynamic memory allocation if the bound object is small enough).

Turns out it does, although it isn’t terribly large, in the header xxxfunction I found this union…

union _Space_union
{ // storage for small wrappers
_Pfnty _Pfn[3];
void *_Pobj[3];
long double _Ldbl; // for maximum alignment
char _Alias[3 * sizeof (void *)]; // to permit aliasing
} _Space;

Only 12 bytes for storage(in 32 bit mode).

//member fxn takes up 16 bytes and thus causes dynamic allocation
auto memfxn = std::tr1::bind(&RenderModule::UpdateDisplay, this);

//free fxn is only 4 bytes
auto freeFxn = std::tr1::bind(Hello);

//lambda capturing this, is only 4 bytes also
auto lambda = [this](){this->UpdateDisplay();};

Functional also seems to tack on an extra 4 bytes when you pass the bind to the functional,
so the mem fxn ends up requiring a 20 byte SBO to avoid dynamic allocation.

So to avoid dynamic allocation on member functions you can either go into xxxfunction and
simply change the size of the SBO(changing the 3 to a 5 works for mem fxn),
or use a lambda which in turn calls the desired mem fxn, the disadvantage being it involves an extra function call.

The fast delegate library uses less static memory(sizeof shows only 8 bytes)
and does not dynamically allocate, also as the name implies– it is quite fast.

So I’ll continue using fast delegate wherever speed is paramount.

This entry was posted on Sunday, May 2nd, 2010 at 8:21 pm and is filed under Uncategorized. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

3 Responses to “Functional”

  1. Daevius Says:

    Well, did you do speed measurements? I’ve been into programming my own delegates for some time now, and found that with GCC 4.4.1 and Win7 there is no (notable) speed difference between my implementation and FastDelegate. This is probably very compiler / platform specific, and my naive implementation might be slower on other platform of course, but it follows the standard, is only a fraction of the code FastDelegate has and is really simple.

    An example for a one parameter member function might be:

    template
    struct NormalDelegate
    {
    NormalDelegate(T *i_object, R (T::*i_member_function)(P)) :
    object(i_object),
    member_function(i_member_function)
    {
    }

    T *object;
    R (T::*member_function)(P);

    void emit(P p)
    {
    (object->*member_function)(p);
    }
    };

    It’s really straightforward, you can extend this to 9 parameters with some macro hacking and add regular funtions and const member functions. But I was astonished FastDelegate and my naive implementation resulted in equal performances (no significant differences). I guess this is because GCC improved over the last couple of years with respect to these kind of optimizations.

  2. Foxtox Says:

    Hey Daevius, sorry I took so long to respond..

    No I didn’t do any speed measurements, but you are right that I should :)

    The code you posted appears to be missing a part at the begging that I assume
    looks something like this?

    template< class T, class R, class P>

    (edit) It appears that if you don’t surround the template def with code markings it deletes the template params, doh

    This seems to be to bind the the delegate to that specific class type, whereas
    fastdelegate supports delegates that can be bound to any class(only the return type,
    and parameter types must match). I actually wouldn’t be surprised if your code was faster
    given that it isn’t quite as generic.

    I don’t use GCC, one of my friends does though– gotta admit I’m abit envious of how quickly
    some of the new C++/0x features are making it into the latest builds.

  3. Daevius Says:

    Hey Foxtox, sorry it took me even longer to respond.

    Yes, I forgot the template parameters.

    But you can bind the implementation I any class (hence the class T template parameter) with any number of parameters (up to 9) and any parameter types as well as any return type.

    Luckily with C++0x we can leave out the macros, that saves us a lot!
    So I’d argue it’s just as generic as it can bind any function. I have some small limitations or “features”, whatever you like to call them, so it fits with the big library I’m writing.

    Good luck with it, if you’re still working on it ;)

Leave a Reply