How to pass data to a C++0x lambda function that will run in a different thread?
- by Dimitri C.
In our company we've written a library function to call a function asynchronously in a separate thread. It works using a combination of inheritance and template magic. The client code looks as follows:
DemoThread thread;
std::string stringToPassByValue = "The string to pass by value";
AsyncCall(thread, &DemoThread::SomeFunction, stringToPassByValue);
Since the introduction of lambda functions I'd like to use it in combination with lambda functions. I'd like to write the following client code:
DemoThread thread;
std::string stringToPassByValue = "The string to pass by value";
AsyncCall(thread, [=]()
{
const std::string someCopy = stringToPassByValue;
});
Now, with the Visual C++ 2010 this code doesn't work. What happens is that the stringToPassByValue is not copied. Instead the "capture by value" feature passes the data by reference. The result is that if the function is executed after stringToPassByValue has gone out of scope, the application crashes as its destructor is called already.
So I wonder: is it possible to pass data to a lambda function as a copy?
Note: One possible solution would be to modify our framework to pass the data in the lambda parameter declaration list, as follows:
DemoThread thread;
std::string stringToPassByValue = "The string to pass by value";
AsyncCall(thread, [=](const std::string stringPassedByValue)
{
const std::string someCopy = stringPassedByValue;
}
, stringToPassByValue);
However, this solution is so verbose that our original function pointer solution is both shorter and easier to read.
Update: The full implementation of AsyncCall is too big to post here. In short, what happens is that the AsyncCall template function instantiates a template class holding the lambda function. This class is derived from a base class that contains a virtual Execute() function, and upon an AsyncCall() call, the function call class is put on a call queue. A different thread then executes the queued calls by calling the virtual Execute() function, which is polymorphically dispatched to the template class which then executes the lambda function.