
原文链接http://en.cppreference.com/w/cpp/thread/packaged_taskhttp://en.cppreference.com/w/cpp/thread/packaged_task/packaged_taskhttp://en.cppreference.com/w/cpp/thread/packaged_task/~packaged_taskhttp://en.cppreference.com/w/cpp/thread/packaged_task/validhttp://en.cppreference.com/w/cpp/thread/packaged_task/get_futurehttp://en.cppreference.com/w/cpp/thread/packaged_task/make_ready_at_thread_exithttp://en.cppreference.com/w/cpp/thread/packaged_task/resetstd::packaged_task定义在头文件future中。(1)template class class packaged_task; // not defined(2)templateclassR,class...Argsclasspackaged_taskR(Args...);类模板std::packaged_task可以封装任何 Callable 的目标如函数、lambda表达式、bind expression、或其他函数对象因此它可以被异步地调用。它的返回值或抛出的异常是被存储在共享状态shared state中的而该共享状态可以通过std::future 对象被访问。正如std::function,std::packaged_task是一个多态的、分配敏感的容器在其中存储的callable的目标可能被分配在堆上或者自带一个allocator.构造函数packaged_task();构造一个不带task或shared state的packaged_task对象。templateclassFexplicitpackaged_task(Ff);构造一个packaged_task对象它带有一个shared state和一个task的拷贝该拷贝以std::forward(f)来初始化。This constructor does not participate in overload resolution if std::decay::type is the same type as std::packaged_taskR(ArgTypes…).packaged_task( packaged_task rhs );构造一个packaged_task对象它带有rhs所拥有的task和shared state但调用后将使得rhs不具有shared state和task.示例程序#includefuture#includeiostream#includethreadintfib(intn){if(n3)return1;elsereturnfib(n-1)fib(n-2);}intmain(){std::packaged_taskint(int)fib_task(fib);std::coutstarting task\n;autoresultfib_task.get_future();std::threadt(std::move(fib_task),40);std::coutwaiting for task to finish...\n;std::coutresult.get()\n;std::couttask complete\n;t.join();}/* Output: starting task waiting for task to finish... 102334155 task complete */析构函数~packaged_task();禁止shared state并销毁所存储的task对象。operator 略valid函数bool valid() const;检查 *this 是否有一个共享状态。get_future函数std::futureR get_future();返回一个future对象它和 *this 共享同一个shared state.对每一个packaged_task, get_future只能被调用一次。异常std::future_error会出现在以下的条件下如果已经调用过了get_future此时再调用会出现future_already_retrieved错误如果 *this 没有shared state那么错误类别是 no_state.make_ready_at_thread_exitvoid make_ready_at_thread_exit( ArgTypes... args );使用转交的args作为参数调用所存储的task. task的返回值或任何抛出的异常都被存储在*this的shared state中。仅仅在线程退出并且所有的线程局部变量都被销毁后shared state才会被变成ready.异常std::future_error会出现在下列的错误条件上。所存储的task已经被调用了。那么错误类别为promise_already_satisfied.*this没有shared state. 错误类别为 no_state.示例程序// Not supported by g 4.9.3 or Visual Studio 2013#includefuture#includeiostream#includechrono#includethread#includefunctional#includeutilityvoidworker(std::futurevoidoutput){std::packaged_taskvoid(bool)my_task{[](booldone){donetrue;}};autoresultmy_task.get_future();booldonefalse;my_task.make_ready_at_thread_exit(done);// execute task right awaystd::coutworker: done std::boolalphadonestd::endl;autostatusresult.wait_for(std::chrono::seconds(0));if(statusstd::future_status::timeout)std::coutworker: result is not ready yetstd::endl;outputstd::move(result);}intmain(){std::futurevoidresult;std::thread{worker,std::ref(result)}.join();autostatusresult.wait_for(std::chrono::seconds(0));if(statusstd::future_status::ready)std::coutmain: result is readystd::endl;}reset 函数void reset();丢弃之前的执行重置状态。新的shared state被构建。等同于 *this packaged_task(std::move(f)), f就是task.示例程序#includeiostream#includecmath#includethread#includefutureintmain(){std::packaged_taskint(int,int)task([](inta,intb){returnstd::pow(a,b);});std::futureintresulttask.get_future();task(2,9);std::cout2^9 result.get()\n;task.reset();resulttask.get_future();std::threadtask_td(std::move(task),2,10);task_td.join();std::cout2^10 result.get()\n;}/* Output: 2^9 512 2^10 1024 */总示例程序#includeiostream#includecmath#includethread#includefuture#includefunctional// unique function to avoid disambiguating the std::pow overload setintf(intx,inty){returnstd::pow(x,y);}voidtask_lambda(){std::packaged_taskint(int,int)task([](inta,intb){returnstd::pow(a,b);});std::futureintresulttask.get_future();task(2,9);std::couttask_lambda:\tresult.get()\n;}voidtask_bind(){std::packaged_taskint()task(std::bind(f,2,11));std::futureintresulttask.get_future();task();std::couttask_bind:\tresult.get()\n;}voidtask_thread(){std::packaged_taskint(int,int)task(f);std::futureintresulttask.get_future();std::threadtask_td(std::move(task),2,10);task_td.join();std::couttask_thread:\tresult.get()\n;}intmain(){task_lambda();task_bind();task_thread();}/* Output: task_lambda: 512 task_bind: 2048 task_thread: 1024 */(END)