jeudi 30 juin 2016

placement new for lambda capture

I have an interesting problem with C++ lambdas. The use case is a performance-critical thread that constructs a lambda with non-empty closure which is then passed to a different thread so it can be "worked" on.

The overall idea works but my lambda closure object gets copied one extra time and compiler (currently g++ 5.4.0) is not able to optimize away this copy including with copy elision. I also tried clang with similar outcome.

Ideally I would like to use a placement new when creating lambda objects directly in the durable memory instead of first creating object on stack for example:

auto l = new (buf) [a,b,c](){}

The error is something like:

lambda_ctor.cpp:39:19: error: expected type-specifier before '[' token
    auto al = (buf) new [a,b,c](){};

I was thinking maybe if I had a type in hand instead of actual lambda expression compiler should accept it but trying to lift type of closure without evaluating it runs into another problem:

using T = decltype([a,b,c](){});

with this error:

lambda_ctor.cpp:41:24: error: lambda-expression in unevaluated context
    using T = decltype([a,b,c](){});

I can't seem to find a way around this, there are a number of ideas on how to keep lambda from disintegrating on scope exit but every solution seems to involve copying/moving the closure object once it has been created (aka extra copy). This is a little strange because normally we have full control over how a user-defined functor is created and passed around and similar rules should apply to closures.

Aucun commentaire:

Enregistrer un commentaire