c++ - What is the difference between packaged_task and async -
while working threaded model of c++11, noticed that
std::packaged_task<int(int,int)> task([](int a, int b) { return + b; }); auto f = task.get_future(); task(2,3); std::cout << f.get() << '\n';
and
auto f = std::async(std::launch::async, [](int a, int b) { return + b; }, 2, 3); std::cout << f.get() << '\n';
seem same thing. understand there major difference if ran std::async
std::launch::deferred
, there 1 in case?
what difference between these 2 approaches, , more importantly, in use cases should use 1 on other?
actually example gave shows differences if use rather long function, such as
//! sleeps 1 second , returns 1 auto sleep = [](){ std::this_thread::sleep_for(std::chrono::seconds(1)); return 1; };
packaged task
a packaged_task
won't start on it's own, have invoke it:
std::packaged_task<int()> task(sleep); auto f = task.get_future(); task(); // invoke function // have wait until task returns. since task calls sleep // have wait @ least 1 second. std::cout << "you can see after 1 second\n"; // however, f.get() available, since task has finished. std::cout << f.get() << std::endl;
std::async
on other hand, std::async
launch::async
try run task in different thread:
auto f = std::async(std::launch::async, sleep); std::cout << "you can see immediately!\n"; // however, value of future available after sleep has finished // f.get() can block 1 second. std::cout << f.get() << "this shown after second!\n";
drawback (c++11 only)
but before try use async
everything, keep in mind returned future has special shared state, demands future::~future
blocks:
std::async(do_work1); // ~future blocks std::async(do_work2); // ~future blocks /* output: (assuming do_work* log progress) do_work1() started; do_work1() stopped; do_work2() started; do_work2() stopped; */
so if want real asynchronous need keep returned future
, or if don't care result if circumstances change:
{ auto pizza = std::async(get_pizza); /* ... */ if(need_to_go) return; // ~future block else eat(pizza.get()); }
for more information on this, see herb sutter's article async
, ~future
, describes problem, , scott meyer's std::futures
std::async
aren't special, describes insights. note behavior specific c++11, in c++14 destructor not block in calling thread.
further differences
by using std::async
cannot run task on specific thread anymore, std::packaged_task
can moved other threads.
std::packaged_task<int(int,int)> task(...); auto f = task.get_future(); std::thread mythread(std::move(task),2,3); std::cout << f.get() << "\n";
also, packaged_task
needs invoked before call f.get()
, otherwise program freeze future never become ready:
std::packaged_task<int(int,int)> task(...); auto f = task.get_future(); std::cout << f.get() << "\n"; // oops! task(2,3);
tl;dr
use std::async
if want things done , don't care when they're done, , std::packaged_task
if want wrap things in order move them other threads or call them later. or, quote christian:
in end
std::packaged_task
lower level feature implementingstd::async
(which why can morestd::async
if used other lower level stuff,std::thread
). spokenstd::packaged_task
std::function
linkedstd::future
,std::async
wraps , callsstd::packaged_task
(possibly in different thread).
Comments
Post a Comment