当前位置: 首页 > 编程日记 > 正文

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

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::future介绍参考:https://blog.csdn.net/fengbingchun/article/details/104115489

模板类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 <iostream>
#include <future>
#include <chrono>
#include <utility>
#include <thread>
#include <functional>
#include <memory>
#include <exception> 
#include <numeric>
#include <vector>
#include <cmath>
#include <string>namespace future_ {///
// reference: http://www.cplusplus.com/reference/future/packaged_task/
int test_packaged_task_1()
{{ // constructor/get_future/operator=/validstd::packaged_task<int(int)> foo; // default-constructedstd::packaged_task<int(int)> bar([](int x) { return x * 2; }); // initializedfoo = std::move(bar); // move-assignmentstd::cout << "valid: " << foo.valid() << "\n";std::future<int> ret = foo.get_future(); // get futurestd::thread(std::move(foo), 10).detach(); // spawn thread and call taskint value = ret.get(); // wait for the task to finish and get resultstd::cout << "The double of 10 is " << value << ".\n";
}{ // reset/operator()std::packaged_task<int(int)> tsk([](int x) { return x * 3; }); // package taskstd::future<int> 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_futureauto 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<int(int, int)> tsk(countdown); // set up packaged_taskstd::future<int> ret = tsk.get_future(); // get futurestd::thread th(std::move(tsk), 5, 0); // spawn thread to count down from 5 to 0int value = ret.get(); // wait for the task to finish and get resultstd::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()
{
{ // lambdastd::packaged_task<int(int, int)> task([](int a, int b) { return std::pow(a, b);});std::future<int> result = task.get_future();task(2, 9);std::cout << "task_lambda:\t" << result.get() << '\n';
}{ // bindstd::packaged_task<int()> task(std::bind([](int x, int y) { return std::pow(x, y); }, 2, 11));std::future<int> result = task.get_future();task();std::cout << "task_bind:\t" << result.get() << '\n';
}{ // threadstd::packaged_task<int(int, int)> task([](int x, int y) { return std::pow(x, y); });std::future<int> 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 datastd::string data = "Data From " + token;return data;}
};int test_packaged_task_3()
{// Create a packaged_task<> that encapsulated a Function Objectstd::packaged_task<std::string(std::string)> task(std::move(DBDataFetcher()));// Fetch the associated future<> from packaged_task<>std::future<std::string> result = task.get_future();// Pass the packaged_task to thread to run asynchronouslystd::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 1auto 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 itstd::packaged_task<int()> 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_

GitHub:https://github.com/fengbingchun/Messy_Test

相关文章:

Swift3.0和OC桥接方法

1.直接在工程中commandn&#xff0c;出现如图&#xff0c;点击Header File创建桥接文件Bridging-Header.h,如图&#xff1a; 2.点击next&#xff0c;出现如图画面&#xff0c;一定要记得勾选第一项&#xff0c;再点击create创建完成。 3.配置桥接文件&#xff0c;点击target - …

量子算命,在线掷筊:一个IBM量子云计算机的应用实践,代码都有了

整理 | Jane 出品| AI科技大本营&#xff08;ID&#xff1a;rgznai100&#xff09; “算命”&#xff0c;古今中外&#xff0c;亘古不衰的一门学问&#xff0c;哪怕到了今天&#xff0c;大家对算命占卜都抱着一些”敬畏“的信任心理&#xff0c;西方流行塔罗牌&#xff0c;国…

rails应用ajax之二:使用rails自身支持

考虑另一种情况&#xff1a; 1. 页面上半部分显示当前的所有用户&#xff0c;页面下半部分是输入新用户的界面&#xff1b; 2. 每当输入新用户时&#xff0c;页面上半部分会动态更新新加用户的内容&#xff1b; 我们还是用ajax实现&#xff0c;不过这次用rails内部对ajax的支持…

C++11中std::async的使用

C11中的std::async是个模板函数。std::async异步调用函数&#xff0c;在某个时候以Args作为参数(可变长参数)调用Fn&#xff0c;无需等待Fn执行完成就可返回&#xff0c;返回结果是个std::future对象。Fn返回的值可通过std::future对象的get成员函数获取。一旦完成Fn的执行&…

BAT数据披露:缺人!110万AI人才缺口,两者矛盾,凉凉了!

人工智能到底有多火&#xff1f;近日国内首份《BAT人工智能领域人才发展报告》新鲜出炉&#xff0c;此次报告是针对国内人工智能领域的人才争夺情况进行了梳理。并把研究对象锁定在BAT三大巨头的身上。来源&#xff1a;《BAT人工智能领域人才发展报告》其中得出最为核心的结论&…

swift3.0最新拨打电话方法

let alertVC : UIAlertController UIAlertController.init(title: "是否拨打报警电话:10086", message: "", preferredStyle: .alert) let falseAA : UIAlertAction UIAlertAction.init(title: "取消", style: .cancel, handler: nil) let tr…

关于手机已处理里重复单据的处理办法

更新视图 VWFE_TASK去掉 union TWFE_TASK_BAK 的部分&#xff0c;原因是因为后面做了流程预演导致的问题转载于:https://blog.51cto.com/iderun/1602828

swiftswift3.0自己封装的快速构建页面的方法

//#param mark 控件 func creatLabel(frame:CGRect,text:String,textColor:UIColor,textFont:CGFloat,textAlignment:NSTextAlignment) -> UILabel { let label UILabel.init(frame: frame) label.text text label.textColor textColor label.font UIFont.systemFont(of…

Google是如何做Code Review的?| CSDN原力计划

作者 | 帅昕 xindoo 编辑 | 屠敏出品 | CSDN 博客我和几个小伙伴一起翻译了Google前一段时间放出来的Google’s Engineering Practices documentation&#xff08;https://github.com/google/eng-practices&#xff09;&#xff0c;翻译后的GitHub仓库&#xff1a;https://gith…

从FFmpeg 4. 2源码中提取dshow mjpeg code步骤

之前在https://blog.csdn.net/fengbingchun/article/details/103735560 中介绍过在Windows上通过vs2017编译FFmpeg源码进行单步调试的步骤&#xff0c;为了进一步熟悉FFmpeg这里以提取FFmpeg dshow mjpeg源码为例介绍其实现过程及注意事项&#xff1a; FFmpeg是用C实现的&…

ControlButton按钮事件

#ifndef __HControlButton_H__#define __HControlButton_H__#include "cocos2d.h"#include "cocos-ext.h"USING_NS_CC;USING_NS_CC_EXT; //用于标识当前按钮的状态typedef enum{ touch_begin, touch_down, touch_up,}tagForTouch;class HControlB…

swift3.0UIAlertController使用方法

let alertVC : UIAlertController UIAlertController.init(title: "添加照片", message: "", preferredStyle: .actionSheet) let cleanAction UIAlertAction(title: "取消", style: UIAlertActionStyle.cancel,handler:nil) let photoActi…

Doxygen使用介绍

Doxygen的主页为http://doxygen.nl/&#xff0c;它的license为GPL&#xff0c;最新发布版本为1.8.17&#xff0c;源代码存放在https://github.com/doxygen/doxygen&#xff0c;它支持的语言包括C、C、Objective-C、C#、Java、Python等&#xff0c;它支持的系统平台包括Winodws、…

云计算软件生态圈:摸到一把大牌

作者 | 老姜编辑 | 阿秃出品 | CSDN云计算&#xff08;ID&#xff1a;CSDNcloud&#xff09;“我觉得我摸着了一把大牌。”软件领域的新锐企业——有赞公司创始人兼CEO白鸦在转向SaaS领域的一个细分市场时&#xff0c;曾对天使投资人这样说。而老牌软件企业金蝶创始人徐少春在2…

iOS封装HTTPS双向和单向验证

1.HttpsUtil (1) 对双向和单向验证的封装 #import <Foundation/Foundation.h> #import "AFNetworking.h" interface HttpsUtil : NSObject // 双向认证 (void)configHTTPSessionManager:(AFHTTPSessionManager *)manager serverCers:(NSArray *) serverCerNam…

开源库BearSSL介绍及使用

BearSSL是用C语言实现的SSL/TLS协议&#xff0c;它的源码可直接通过git clone https://www.bearssl.org/git/BearSSL 下载&#xff0c;它的license是MIT&#xff0c;最新版本为0.6。 BearSSL的主要特性是&#xff1a; (1). 正确且安全&#xff1a;对不安全的协议版本和算法选…

个推CTO安森:我所理解的数据中台

作者 | 个推CTO安森来源 | 个推技术学院&#xff08;ID:ID: getuitech&#xff09;引言在前面两篇文章&#xff08;《数据智能时代来临&#xff1a;本质及技术体系要求》和《多维度分析系统的选型方法》&#xff09;之中&#xff0c;我们概括性地阐述了对于数据智能的理解&…

玩弹珠手游-杂想

前言 为什么会写这个杂想呢&#xff1f; 因为最近这一个月来&#xff0c;我有点太沉迷怪物弹珠这个游戏了&#xff0c;每天下班回来的时间和上下班路途都在玩这个游戏&#xff0c;占据了我大部分的业余时间&#xff0c;也该是时候放一放玩游戏了。 为什么会玩这个游戏呢&#x…

OC封装时间选择器

#import <UIKit/UIKit.h> protocol TimeDatePickerViewDelegate <NSObject> //必须实现的两个协议 required - (void)changeTime : (NSDate *)date;//当时改变时出发 - (void)daterMine : (NSDate *)date;//更确定时间 end interface TimeDatePickerView :UIView /…

银行卡大小的充电宝,买就送耳机!

每个人的朋友圈和微博上似乎都有那么几个活得让人羡慕的朋友他们的生活看起来不仅精致&#xff0c;还很丰富多彩从早上第一刻就开始了↓出门旅游新一天的穿搭逆天朋友团咖啡馆到书店逼格十足的日料夜景太迷人忍不住发个小视频最后一定不要错过傍晚的夕阳&#xff0c;真的好上镜…

C++中插件使用举例

插件并不是在构建时链接的&#xff0c;而是在运行时发现并加载的。因此&#xff0c;用户可以利用你定义好的插件API来编写自己的插件。这样他们就能以指定方式扩展API的功能。插件库是一个动态库&#xff0c;它可以独立于核心API编译&#xff0c;在运行时根据需要显示加载。不过…

C和C++安全编码笔记:指针诡计

指针诡计(pointer subterfuge)是通过修改指针值来利用程序漏洞的方法的统称。 可以通过覆盖函数指针将程序的控制权转移到攻击者提供的外壳代码(shellcode)。当程序通过函数指针执行一个函数调用时&#xff0c;攻击者提供的代码将会取代原本希望执行的代码而得到执行。 对象指…

runLoop和runtime的分析

一.RunLoop: Runloop是事件接收和分发机制的一个实现。 Runloop提供了一种异步执行代码的机制&#xff0c;不能并行执行任务。 在主队列中&#xff0c;Main RunLoop直接配合任务的执行&#xff0c;负责处理UI事件、定时器以及其他内核相关事件。 (1).RunLoop的主要目的&#…

脑出血遇到深度学习,是否可以无所遁形?

近期大家对身体健康这个话题格外关注&#xff0c;而我们今天公开课的主题也恰巧与此不谋而合。我国脑卒的发病率已经超过心血管疾病&#xff0c;成为致死、致残率最高的疾病&#xff0c;并且发病率呈逐年上升的趋势&#xff0c;此外脑血管病和颅内肿瘤等脑部疾病也危害人们的健…

Cloudera Manager 5.3 和 CDH5.3.0 本地(离线)

为什么80%的码农都做不了架构师&#xff1f;>>> 声明一下&#xff1a;http://my.oschina.net/dataRunner/blog/369129 是本人所写&#xff0c;并非抄袭。 有部分内容来自 http://www.wangyongkui.com/hadoop-cdh5/ 这个文件是根据官网操作&#xff0c;翻译的不…

万字长文详解如何用Python玩转OpenGL | CSDN 博文精选

作者 | 天元浪子来源 | CSDN博文精选【编者按】OpenGL&#xff08;开放式图形库&#xff09;&#xff0c;用于渲染 2D、3D 矢量图形的跨语言、跨平台的应用程序编程接口&#xff0c;C、C、Python、Java等语言都能支持 OpenGL。本文作者以 Python 语法为例&#xff0c;用两万字详…

模仿视频抓帧实现

路口或某些场所可能并不会把从摄像头获取到的视频全部存储下来或对所有的视频帧进行处理&#xff0c;即摄像设备是一直处于打开状态&#xff0c;可能会根据需要间隔性的抓取其中一帧&#xff0c;或当某事件触发时才会抓取当前的一帧数据进行处理。这里使用两个线程来模仿此场景…

iOS--MD5加密封装

#import <Foundation/Foundation.h> interface MD5 : NSObject /** * md5加密 * * param inPutText 需要加密的字符串 * * return 加密好的字符串 */ (NSString *)md5:(NSString *)inPutText; end #import "MD5.h" #import "CommonCrypto/CommonDiges…

Akka路由_RoundRobinRoutingLogic

2019独角兽企业重金招聘Python工程师标准>>> Akka路由_RoundRobinRoutingLogic 使用Round Robin算法的Router&#xff0c;代码中有注释&#xff0c;基本和上篇文章中的代码一样 http://my.oschina.net/xinxingegeya/blog/369721&#xff0c; 具体如下&#xff0c;关…