C++11中的std::packaged_task是个模板类。std::packaged_task包装任何可调用目标(函数、lambda表达式、bind表达式、函数对象)以便它可以被异步调用。它的返回值或抛出的异常被存储于能通过std::future对象访问的共享状态中。

std::packaged_task类似于std::function,但是会自动将其结果传递给std::future对象。

std::packaged_task对象内部包含两个元素:(1).存储的任务(stored task)是一些可调用的对象(例如函数指针、成员或函数对象的指针)( A stored task, which is some callable object (such as a function pointer, pointer to member or function object))。(2).共享状态,它可以存储调用存储的任务(stored task)的结果,并可以通过std::future进行异步访问(A shared state, which is able to store the results of calling the stored task and be accessed asynchronously through a future)。

通过调用std::packaged_task的get_future成员将共享状态与std::future对象关联。调用之后,两个对象共享相同的共享状态:(1).std::packaged_task对象是异步提供程序(asynchronous provider),应通过调用存储的任务(stored task)在某个时刻将共享状态设置为就绪。(2).std::future对象是一个异步返回对象,可以检索共享状态的值,并在必要时等待其准备就绪。

共享状态的生存期至少要持续到与之关联的最后一个对象释放或销毁为止。

std::packaged_task不会自己启动,你必须调用它(A packaged_task won't start on it's own, you have to invoke it)。

模板类std::packaged_task成员函数包括:

1. 构造函数:(1).默认构造函数:无共享状态无存储任务(no shared state and no stored task)情况下初始化对象。(2). initialization constructor:该对象具有共享状态,且其存储的任务由fn初始化。(3). initialization constructor with allocator。(4).禁用拷贝构造。(5).支持移动构造。

2. 析构函数:(1).放弃(abandon)共享状态并销毁packaged_task对象。(2). 如果有其它future对象关联到同一共享状态,则共享状态本身不会被销毁。(3). 如果packaged_task对象在共享状态准备就绪前被销毁,则共享状态自动准备就绪并包含一个std::future_error类型的异常。

3. get_future函数:(1).返回一个与packaged_task对象的共享状态关联的std::future对象。(2).一旦存储的任务被调用,返回的std::future对象就可以访问packaged_task对象在共享状态上设置的值或异常。(3).每个packaged_task共享状态只能被一个std::future对象检索(Only one future object can be retrieved for each packaged_task shared state)。(4).调用此函数后,packaged_task应在某个时候使其共享状态准备就绪(通过调用其存储的任务),否则将在销毁后自动准备就绪并包含一个std::future_error类型的异常。

4. make_ready_at_thread_exit函数:在线程退出时才使共享状态ready而不是在调用完成后就立即ready。

5. operator=:(1).禁用拷贝赋值。(2).支持移动赋值。

6. operator():(1).call stored task。(2).如果对存储任务的调用成功完成或抛出异常,则返回的值或捕获的异常存储在共享状态,共享状态准备就绪(解除阻塞当前等待它的所有线程)。

7. reset函数:(1).在保持相同存储的任务的同时,以新的共享状态重置对象。(2).允许再次调用存储的任务。(3).与对象关联的之前的共享状态被放弃(就像packaged_task被销毁了一样)。(4).在内部,该函数的行为就像是移动赋值了一个新构造的packaged_task一样(Internally, the function behaves as if move-assigned a newly constructed packaged_task (with its stored task as argument))。

8. swap函数/非成员模板函数swap:交换共享状态和存储的任务(stored task)。

9. valid函数:检查packaged_task对象是否具有共享状态。

详细用法见下面的测试代码,下面是从其他文章中copy的测试代码,部分作了调整,详细内容介绍可以参考对应的reference:

#include "future.hpp"

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

namespace future_ {

///

// reference: http://www.cplusplus.com/reference/future/packaged_task/

int test_packaged_task_1()

{

{ // constructor/get_future/operator=/valid

std::packaged_task foo; // default-constructed

std::packaged_task bar([](int x) { return x * 2; }); // initialized

foo = std::move(bar); // move-assignment

std::cout << "valid: " << foo.valid() << "\n";

std::future ret = foo.get_future(); // get future

std::thread(std::move(foo), 10).detach(); // spawn thread and call task

int value = ret.get(); // wait for the task to finish and get result

std::cout << "The double of 10 is " << value << ".\n";

}

{ // reset/operator()

std::packaged_task tsk([](int x) { return x * 3; }); // package task

std::future fut = tsk.get_future();

tsk(33);

std::cout << "The triple of 33 is " << fut.get() << ".\n";

// re-use same task object:

tsk.reset();

fut = tsk.get_future();

std::thread(std::move(tsk), 99).detach();

std::cout << "Thre triple of 99 is " << fut.get() << ".\n";

}

{ // constructor/get_future

auto countdown = [](int from, int to) {

for (int i = from; i != to; --i) {

std::cout << i << '\n';

std::this_thread::sleep_for(std::chrono::seconds(1));

}

std::cout << "Lift off!\n";

return from - to;

};

std::packaged_task tsk(countdown); // set up packaged_task

std::future ret = tsk.get_future(); // get future

std::thread th(std::move(tsk), 5, 0); // spawn thread to count down from 5 to 0

int value = ret.get(); // wait for the task to finish and get result

std::cout << "The countdown lasted for " << value << " seconds.\n";

th.join();

}

return 0;

}

///

// reference: https://en.cppreference.com/w/cpp/thread/packaged_task

int test_packaged_task_2()

{

{ // lambda

std::packaged_task task([](int a, int b) { return std::pow(a, b);});

std::future result = task.get_future();

task(2, 9);

std::cout << "task_lambda:\t" << result.get() << '\n';

}

{ // bind

std::packaged_task task(std::bind([](int x, int y) { return std::pow(x, y); }, 2, 11));

std::future result = task.get_future();

task();

std::cout << "task_bind:\t" << result.get() << '\n';

}

{ // thread

std::packaged_task task([](int x, int y) { return std::pow(x, y); });

std::future result = task.get_future();

std::thread task_td(std::move(task), 2, 10);

task_td.join();

std::cout << "task_thread:\t" << result.get() << '\n';

}

return 0;

}

///

// reference: https://thispointer.com/c11-multithreading-part-10-packaged_task-example-and-tutorial/

struct DBDataFetcher {

std::string operator()(std::string token)

{

// Do some stuff to fetch the data

std::string data = "Data From " + token;

return data;

}

};

int test_packaged_task_3()

{

// Create a packaged_task<> that encapsulated a Function Object

std::packaged_task<:string> task(std::move(DBDataFetcher()));

// Fetch the associated future<> from packaged_task<>

std::future<:string> result = task.get_future();

// Pass the packaged_task to thread to run asynchronously

std::thread th(std::move(task), "Arg");

// Join the thread. Its blocking and returns when thread is finished.

th.join();

// Fetch the result of packaged_task<> i.e. value returned by getDataFromDB()

std::string data = result.get();

std::cout << data << std::endl;

return 0;

}

///

// reference: https://stackoverflow.com/questions/18143661/what-is-the-difference-between-packaged-task-and-async

int test_packaged_task_4()

{

// sleeps for one second and returns 1

auto sleep = []() {

std::this_thread::sleep_for(std::chrono::seconds(1));

return 1;

};

{ // std::packaged_task

// >>>>> A packaged_task won't start on it's own, you have to invoke it

std::packaged_task task(sleep);

auto f = task.get_future();

task(); // invoke the function

// You have to wait until task returns. Since task calls sleep

// you will have to wait at least 1 second.

std::cout << "You can see this after 1 second\n";

// However, f.get() will be available, since task has already finished.

std::cout << f.get() << std::endl;

}

{ // std::async

// >>>>> On the other hand, std::async with launch::async will try to run the task in a different thread :

auto f = std::async(std::launch::async, sleep);

std::cout << "You can see this immediately!\n";

// However, the value of the future will be available after sleep has finished

// so f.get() can block up to 1 second.

std::cout << f.get() << "This will be shown after a second!\n";

}

return 0;

}

} // namespace future_

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

C语言中task的用法,C++11中std::packaged_task的使用详解相关推荐

  1. c语言中argc的作用,C语言中 int main(int argc,char *argv[])的两个参数详解

    C语言中 int main(int argc,char *argv[])的两个参数详解 argc是命令行总的参数个数: argv[]是argc个参数,其中第0个参数是程序的全名,以后的参数.命令行后面 ...

  2. C语言中task的用法,C# Task详解

    C# Task详解  https://www.cnblogs.com/zhaoshujie/p/11082753.html 1.Task的优势 ThreadPool相比Thread来说具备了很多优势, ...

  3. C语言中task的用法,c – 在std :: packaged_task中使用成员函数

    我想做的应该很容易,但我不明白-- 我想要做的就是在后台启动一个类的成员函数 在某个特定的时间点.该功能的结果也应该是"外部"可用的.所以我想在构造函数中准备任务(设置future ...

  4. c语言中point的用法_C/C++中 *和amp;的爱恨情仇

    C++中&和*的用法一直是非常让人头疼的难点,课本博客上讲这些的知识点一般都是分开讲其用法的,没有详细的总结,导致我在这方面的知识结构格外混乱,在网上找到了一篇英文文章简单总结了这两个符号的一 ...

  5. C++11中std::packaged_task的使用

    C++11中的std::packaged_task是个模板类.std::packaged_task包装任何可调用目标(函数.lambda表达式.bind表达式.函数对象)以便它可以被异步调用.它的返回 ...

  6. c语言中sign的用法,Excel教程中sign函数用法和实例详解

    第一,sign函数用法说明 excel教程中sign函数用于返回数字的符号.正数为1,零为0,负数为-1. sign函数语法:SIGN(number) SIGN符号函数(一般用sign(x)表示)是很 ...

  7. c语言中 d的用法,C语言中的#define用法总结

    1.宏定义 格式: #define   标识符(也称为宏名)   替换列表 例如; #define PI 3.14 以上代码就是定义了一个宏.  宏的名称为PI, 我们在使用的时候,会在编译预处理时, ...

  8. sql 语言中 when case 用法

    sql语言中有没有相似C语言中的switch case的语句?? 没有,用case when 来取代就行了. 比如,以下的语句显示中文年月 select getdate() as 日期,case mo ...

  9. map函数作用c语言,c语言中map的用法:map基本用法

    c++中map容器提供一个键值对容器,那么你知道map的用法有哪些吗,下面秋天网 Qiutian.ZqNF.Com小编就跟你们详细介绍下c语言中map的用法,希望对你们有用. c语言中map的用法:m ...

最新文章

  1. 程序员的自我修养--链接、装载与库笔记:可执行文件的装载与进程
  2. Warning: Permanently added the RSA host key for IP address '192.30.253.113' to the list of known hos
  3. 青海省西宁市职称计算机考试试题,【青海西宁2017年第一批职称计算机考试时间4月8日起】- 环球网校...
  4. 一文带你领略JS中原型链的精妙设计!
  5. 08 Spring框架 AOP (一)
  6. 基于MaxCompute分布式Python能力的大规模数据科学分析
  7. 用VC写Assembly代码(4)
  8. mysql志新计划,在使用Perl DBI迭代结果集时更新MySQL表是否安全?
  9. 最近使用mysql遇到的几个问题
  10. docker_6 Docker 网络
  11. LR之Java Vuser
  12. PHP7中异常与错误处理与之前版本对比
  13. SQLAPI++ Library 4.2.1 VS2010破解版
  14. 九款实用的在线画图工具(那些可以替代Visio的应用)
  15. 【工控安全产品】工控主机卫士
  16. 多种消息提醒系统的设计模式、实现方案(附功能截图+表结构)
  17. Android程序员该如何进阶?,2021Android面经
  18. 用PS把一张图片变成素描画
  19. 二人成团,阿里云服务器拼团活动开启
  20. TCP协议中的Ack和Seq号

热门文章

  1. 跳一跳python源码下载_微信跳一跳游戏python脚本
  2. C# 博思得 POSTEK 打印机 打码机 SDK 二次开发 指令打印
  3. GeoServer中的WPS服务-概念
  4. 【读书笔记】好好思考-成甲
  5. 压在redis身上的三座大山
  6. concurrent mode failure
  7. 在 Mac 上多开微信,还能看到朋友撤回的信息:WeChatTweak - 少数派
  8. 10000,感谢有你
  9. PLC实验 S7-300超详细硬件组态实验过程
  10. 使用excel进行数据挖掘(4)---- 突出显示异常值