文档章节

C++11: std::packaged_task

SHIHUAMarryMe
 SHIHUAMarryMe
发布于 2016/05/15 14:52
字数 1430
阅读 95
收藏 3
点赞 2
评论 0

class std::packaged_task被用来同时存储callable object,以及该callable object的返回值(也可能是个异常).

#include <iostream>
#include <thread>
#include <future>
#include <exception>

int main()
{
	std::packaged_task<int(const int&)> t1; //空的packaged_task即没有shared state,也没有callable object.
	std::packaged_task<int(const int&)> t2([](const int& number) { return 10; }); //构造函数,运行时候构建一个shared state,并且存储一个callable object进去.
	t1 = std::move(t2); //移动赋值运算符.这样一来t2中的shared state和callable object都转移到了t1中,t2不可再使用.

	std::future<int> result = t1.get_future();
	std::thread t3(std::move(t1), 20); //此时t1处于无效状态.

	t3.detach(); //t3成为一个独立的线程.

	int value = result.get(); //如果t3内的callable object还没有执行完成,那么会阻塞调用result.get()的线程直到t3类的callable object调用完成.
	std::cout << "result: " << value << std::endl;

	return 0;

}

----------------------------我是分割线------------------------------

std::packaged_task构造函数:

packaged_task() noexcept;

template <class Fn>
  explicit packaged_task (Fn&& fn);

template <class Fn, class Alloc>
  explicit packaged_task (allocator_arg_t aa, const Alloc& alloc, Fn&& fn);

packaged_task (const packaged_task&) = delete; //不支持拷贝.

packaged_task (packaged_task&& x) noexcept;

1,默认构造函数构建一个std::packaged_task对象,即没有shared state,也没有callable object.

2,显式构造函数接受一个callable object初始化std::packaged_task。同时创建一个not ready的shared state.

3,被删除了的copy-constructor.

4,移动构造函数,被移动的对象不再可用,且当前对象获得被移动对象的callable object和shared state.

std::packaged_task::get_future

该函数返回一个std::future对象且该std::future与当前std::packaged_task共同使用同一个shared state.这样也就意味着,如果我们对被返回出来的std::future调用get(),wait()等,如果std::packaged_task中的callable object未执行完成(也就是shared state还处于not ready状态),这样就会阻塞当前正在调用get()或者wait()的线程.

future<Ret> get_future();
#include <iostream>
#include <thread>
#include <future>
#include <string>

int function(const int& number)
{
	return number * 3;
}

int main()
{
	std::packaged_task<int(const int&)> t1(function);
	std::future<int> result = t1.get_future(); //此时result 和 t1共享shared state.

	std::thread t2(std::move(t1), 20); //t1被移动变成不可用状态.
	t2.detach();

	int value = result.get(); //这里调用get(),如果t2未执行完成(也就是shared state处于not ready状态),会block当前调用get()的线程(这里是main线程).

	std::cout << "value: " << value << std::endl;


	return 0;


}

std::packaged_task::make_ready_at_thread_exit

调用当前std::packaged_task中的callable object以一个独立的线程运行该callable object,并转发参数进去callable object,但是callable object调用完成后并不是立即把该std::packaged_task中的shared state设置为ready,而是直到该线程完全结束的时候才设为ready.

void make_ready_at_thread_exit (args... args);

std::packaged_task::operator=

该std::packaged_task对象的拷贝赋值运算被删除了,也就是说std::packaged_task对象不能被拷贝.

但是可以被移动,被移动的std::packaged_task的shared state和callable object被移动当前std::packaged_task.被移动对象变成不可用的状态.

packaged_task& operator= (packaged_task&& rhs) noexcept;

packaged_task& operator= (const packaged_task&) = delete;//拷贝构造函数被删除了.

std::packaged_task::operator()

调用当前对象内的callable object,并转发参数进去(不过需要注意的是如果我们通过operator()调用callable object并不是并行的):

1,如果当前std::packaged_task中的callable object执行完成,则callable object的返回值被存储到当前std::packaged_task的shared state中,且将该shared state的状态设置为ready.

2,如果当前的std::packaged_task中的callable object在执行过程中抛出了异常,那么该异常会被捕获,也被存储在shared state中,并且该shared state被设置为ready.

#include <iostream>
#include <thread>
#include <future>
#include <string>
#include <utility>

class Object {
private:
	int number;

public:
	Object();
	~Object() = default;
	int& operator()(const int& number)noexcept;
};

Object::Object()
	:number(1)
{
	//
}

int& Object::operator()(const int& number)noexcept
{
	this->number = 20 * number;

	std::this_thread::sleep_for(std::chrono::seconds(2));
	return (this->number);
}

class MyObject {
private:
	int number;

public:
	inline MyObject():number(1){}
	~MyObject() = default;
	int getNumber(const int& num)noexcept
	{
		return (this->number * num);
	}
};


int function(const int& number)
{
	return number * 3;
}

int main()
{
	//callable object case 1:
	std::packaged_task<int(const int&)> t1(function);
	std::future<int> result = t1.get_future(); //此时result 和 t1共享shared state.
	std::thread t2(std::move(t1), 20); //t1被移动变成不可用状态.
	t2.detach();
	int value = result.get(); //这里调用get(),如果t2未执行完成(也就是shared state处于not ready状态),会block当前调用get()的线程(这里是main线程).
	std::cout << "value: " << value << std::endl;

	//callable object case 2:
	try {
		Object object;
		std::packaged_task<int& (const int&)noexcept> t3(object);
		std::future<int&> result1 = t3.get_future();
		//t3(20); //调用callable object但是并不会并行调用.
		std::thread t4(std::move(t3), 20);
		t4.detach();
		std::cout << " test " << std::endl;
		int value1 = result1.get();
		std::cout << "value1: " << value1 << std::endl;

	}catch (const std::exception& e) {
		std::cerr << "exception!" << std::endl;
	}


	//callable object case 3:
	MyObject myObject;
	std::function<int(const int&)> memberFunction = std::bind(&MyObject::getNumber, &myObject, std::placeholders::_1);

	std::packaged_task<int(const int&)> t5(memberFunction);
	std::future<int> result2 = t5.get_future();
	std::thread t6(std::move(t5), 20);
	t6.detach();
	int value2 = result2.get();

	std::cout << "value2: " << value2 << std::endl;
	return 0;
}

std::packaged_task::reset

当我们执行完了callable object(无论是通过当前std::packaged_task的operator(),还是通过std::thread),当前std::packaged_task对象内的shared state都被设置为了ready,这样也就造成了我们通过调用当前std::packaged_task对象的get_future()函数获得的std::future只能get()一次,

那么我们想要再次执行该callable object怎么办呢?这个时候就需要调用当前std::packaged_task对象的reset()函数了给当前std::packaged_task对象创建一个新的shared state且处于not ready状态.

void reset();
#include <iostream>
#include <thread>
#include <future>
#include <string>

int getNumber(const int& number)
{
	return number * 20;
}

int main()
{
	std::packaged_task<int(const int&)> package(getNumber);

	std::future<int> result = package.get_future();
	package(20);
	int value = result.get();
	std::cout << "value(now shared state is ready): " << value << std::endl;

	std::cout << "reset the shared state." << std::endl;
	package.reset();
	std::future<int> result2 = package.get_future();
	std::thread t2(std::move(package), 40); //注意这里用了std::move(),package对象会不再可用.
	t2.detach();
	int value2 = result2.get();
	std::cout << " value2(now share state is again ready): " << value2 << std::endl;

	return 0;
}

 

© 著作权归作者所有

共有 人打赏支持
SHIHUAMarryMe
粉丝 12
博文 165
码字总数 138772
作品 0
武汉
程序员
c++11实现异步定时器

c++11提供了丰富的时间和线程操作函数,比如 std::this_thread::sleep, std::chrono::seconds等。可以利用这些来很方便的实现一个定时器。 实现 ifndef TIMERH define TIMERH include includ...

moki_oschina ⋅ 05/23 ⋅ 0

C++11: std::thread和std::this_thread

C++11起,标准库除了提供std::async(),这样的高级线程接口以外,还提供了更加简单的std::thread,我们只需要声明一个std::thread对象,然后传递进去函数(function注意这里并不是callable obje...

SHIHUAMarryMe ⋅ 2016/03/07 ⋅ 0

C++原子类实现

引言 在系统实现的过程中,经常需要用到计数功能,为了多线程下的安全使用,我自己定义了一个原子类。 基于Mutex的实现 我基于Mutex实现了一个简单的原子类,代码如下 如代码所示,这是一种最...

西昆仑 ⋅ 2016/08/29 ⋅ 0

GCC 4.7相对4.6.x的改进点

原文:http://www.iteye.com/news/24628 针对C的功能改进: 支持ISO C11标准中的更多特性。除了之前的-std=c1x和-std=gnu1x选项外,GCC现在还支持-std=c11和-std=gnu11选项。 针对C++的功能改...

一见蓝天 ⋅ 2013/08/21 ⋅ 0

C++11: Mutex和Lock

Mutex全名mutual exclusion(互斥体),是一个可加锁对象(lockable object),用来协助采取独占排他方式控制对资源的并发访问.这里的资源可能是个object,也可能是多个object的组合。为了获得独占式...

SHIHUAMarryMe ⋅ 2016/03/18 ⋅ 0

C++11实现跨平台线程池

生产者消费者 转自:http://www.cnblogs.com/sanjin/archive/2012/08/09/2629890.html std::conditionvariable的使用方法如下: ·当持有锁(mutex)之后,线程调用wait ·wait解开持有的互斥锁...

初雪之音 ⋅ 2016/03/19 ⋅ 0

你们以为我在学C++?其实我在学 Python

我在用 C++ 来学习 Python. 不信?来跟着我学? 字面量 Python 早在 2.6 版本中就支持将二进制作为字面量了[1], 最近 C++14 逐步成熟,刚刚支持这么干[2]: static const int primes = 0b1010...

铁扇公主1 ⋅ 2017/04/28 ⋅ 0

GCC4.7 和C++11

GCC(GNU Compiler Collection,GNU编译器套装),是一套由 GNU 开发的编程语言编译器。GCC 使用 GPL 与 LGPL 许可证,是 GNU 计划的关键部分。GCC 目前可处理 C++、Fortran、Pascal、Objec...

mickelfeng ⋅ 2012/12/21 ⋅ 0

cannot convert ‘a’ (type ‘int’) to type ‘int&&’

背景 启用C++11编译老代码的时候,g++报错。示例代码如下: #include <utility> int main() { int a = 0; auto b = std::make_pair<int, int>(a, 1); return 0;} 出错信息: test.cpp: In f......

kyos ⋅ 2015/03/14 ⋅ 0

C++11的初始化语法

首先我要强调,C++中struct和class唯一的区别是,前者的成员默认公有,后者成员默认私有. 在C++03中,结构体/类的初始化方式只有来自C语言的一种写法: struct A{ }; A a{123,456}; //a.x=12...

王子亭 ⋅ 2012/12/23 ⋅ 4

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Spring Cloud构建微服务架构—创建“服务注册中心”

创建一个基础的Spring Boot工程,命名为eureka-server,并在pom.xml中引入需要的依赖内容: <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-par......

itcloud ⋅ 22分钟前 ⋅ 0

拖动

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>event</title> <style> #box { width: 100px; height: 100px; background-color: aquamarine; position: absolute; } </style......

fyliujj ⋅ 24分钟前 ⋅ 0

es6 polyfill array

polyfill之javascript函数的兼容写法——Array篇 1. Array.isArray(obj) if (!Array.isArray) { Array.isArray = function(arg) { return Object.prototype.toString.call(arg) === '[objec......

球球 ⋅ 26分钟前 ⋅ 0

kibana启动异常

检查一下:kibana.yml 每一对key:value中,冒号之后应有空格。

增删改查1 ⋅ 28分钟前 ⋅ 0

js修改img的src属性刷新图片时的图片缓存问题

问题:上传一张图片,通过js更新src属性刷新图片使其即时显示时, 当img的src当前的url与上次地址无变化时(只更改图片,名称不变,不同图片名称相同)图片不变化(仍显示原来的图片) 但通过...

HaierBrother ⋅ 28分钟前 ⋅ 0

Mysql

1.Jdbc Url 设置allowMultiQueries为true和false mysql的批量更新是要我们主动去设置的, 就是在数据库的连接url上设置一下,加上* &allowMultiQueries=true *即可。 参数名称 参数说明 缺省...

瑟青豆 ⋅ 32分钟前 ⋅ 0

mysql导出导入表结构与数据

当我们需要进行数据迁移时,mysql自带的mysqldump会是最好的方式。 1.导出某张表的结构和数据 首先,我们应当使用服务器,打开终端,连接到所需要导出的表所在的服务器上。执行命令: mysqld...

hengbao5 ⋅ 32分钟前 ⋅ 0

世界杯也走向“比拼”大数据的时代

《日本经济新闻》6月19日报道称,俄罗斯足球世界杯已于6月14日揭开战幕。作为第21次举办的足球世界杯,如何活用大数据有可能成为决定各支球队胜负的重要因素。从对阵球队的分析到战术建议,还...

加米谷大数据 ⋅ 32分钟前 ⋅ 0

金额转为千分制,金额转中文大写

金额转关为大写 /** 数字金额大写转换(可以处理整数,小数,负数) */ function digitUppercase(n){ if(!n) reutrn "" let fraction = ['角', '分']; let digit = [...

YXMBetter ⋅ 35分钟前 ⋅ 0

开发利器JRebel部署SpringBoot项目

不要以为年纪轻轻就跌倒了人生谷底,未来还有更大的下降空间等着你。 idea下载和安装JRebel 激活JRebel 访问https://my.jrebel.com/ 使用facebook或twitter登录 勾选 Build project automati...

郑龙飞 ⋅ 41分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部