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 implementing std::async (which why can more std::async if used other lower level stuff, std::thread). spoken std::packaged_task std::function linked std::future , std::async wraps , calls std::packaged_task (possibly in different thread).


Comments

Popular posts from this blog

PySide and Qt Properties: Connecting signals from Python to QML -

c# - DevExpress.Wpf.Grid.InfiniteGridSizeException was unhandled -

scala - 'wrong top statement declaration' when using slick in IntelliJ -