23

The async call below is blocking because the destructor of the returned future is blocking:

void foo() {}

void foo_async() {
    std::async(std::launch::async, foo);
}

But I don't want to block!

I'm considering to use the following workaround:

void foo_async() {
    std::thread(foo).detach();
}

Is this ok? Or would you recommend a different solution?

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
StackedCrooked
  • 34,653
  • 44
  • 154
  • 278
  • 4
    If you have no need to return a value from the task or to wait for it to finish this seems reasonable to me. – jcoder Apr 30 '13 at 09:22

2 Answers2

11

You could use the following version of async which provides a non-blocking future. As such you can take advantage of the future if you need it and on the other side you can just ignore it when you want a fire-and-forget task.

template< class Function, class... Args>
std::future<typename std::result_of<Function(Args...)>::type> async( Function&& f, Args&&... args ) 
{
    typedef typename std::result_of<Function(Args...)>::type R;
    auto bound_task = std::bind(std::forward<Function>(f), std::forward<Args>(args)...);
    std::packaged_task<R()> task(std::move(bound_task));
    auto ret = task.get_future();
    std::thread t(std::move(task));
    t.detach();
    return ret;   
}
Stephan Dollberg
  • 32,985
  • 16
  • 81
  • 107
4

If you really want to fire-and-forget the call to foo(), I would say your workaround is OK.

Otherwise, just do auto f = std::async(std::launch::async, foo);, and possibly return the future from foo_async().

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451