What I want to do should be quite easy, but I don't get it...
All I want to do is to start a member function of a class in background at some certain point in time. The result of that function should also be "externally" available. So I want to prepare the task in the constructor (setting the future variable, ... ) and start it at some later point.
I tried to combine std::(packaged_task|async|future) but I didn't get it to work.
This snippet will not compile, but I think it shows what I want to do:
class foo {
private:
  // This function shall run in background as a thread
  // when it gets triggered to start at some certain point
  bool do_something() { return true; }
  std::packaged_task<bool()> task;
  std::future<bool> result;
public:
  foo() : 
    task(do_something), // yes, that's wrong, but how to do it right?
    result(task.get_future()) 
  {
    // do some initialization stuff
    .....
  }
  ~foo() {}
  void start() {
    // Start Task as asynchron thread
    std::async as(std::launch::async, task); // Also doesn't work...
  }
  // This function should return the result of do_something
  bool get_result() { return result.get(); }
};
Thanks in advance!
Just use std::bind():
#include <functional> // For std::bind()
foo() :
    task(std::bind(&foo::do_something, this)),
//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    result(task.get_future()) 
{
    //  ...
}
Moreover, you are doing the wrong thing here:
std::async as(std::launch::async, task)
//         ^^
//         Trying to declare a variable?
Since what you want is to call the std::async() function, not to declare an object of a (non-existing) type std::async(). So as a first step, change this into:
std::async(std::launch::async, task)
Notice, however, that this will not be enough to get the task running asynchronously: because of the odd behavior of std::async() when the returned future is discarded, your task will always be executed as if you started it synchronously - the destructor of the returned future object will block until the completion of the operation. (*)
To solve this last problem, you can hold the returned future in your result member variable (rather than assigning to result the future returned by std::packaged_task::get_future() upon construction):
    result = std::async(std::launch::async, task);
//  ^^^^^^^^
(*) I think that MSVC ignores this specification and actually executes the task asynchronously. So if you are working with VS2012, you may not suffer from this problem.
EDIT:
As correctly mentioned by Praetorian in his answer, the above would still be problematic, since a copy of the packaged_task would be attempted at some point within the implementation of async(). To work around this problem, you wrap your task object in a reference wrapper by using std::ref().
do_something() is a member function, which means it takes an implicit this pointer as the first argument. You'll need to bind the this pointer, or create a lamda that invokes do_something.
foo() : 
  task(std::bind(&foo::do_something, this)),
  result(task.get_future()) 
{}
or
foo() : 
  task([this]{ return do_something(); }),
  result(task.get_future()) 
{}
std::async as(std::launch::async, task);
std::async is a function template, not a type. So the obvious change is 
std::async(std::launch::async, task);
But that causes yet another error because somewhere within the guts of that call a copy of task is attempted, but std::packaged_task has a deleted copy constructor. You can fix that by using std::ref, which will avoid the copy.
std::async(std::launch::async, std::ref(task));
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With