文档章节

Multi thread: std::promise

SHIHUAMarryMe
 SHIHUAMarryMe
发布于 2016/05/14 16:59
字数 1074
阅读 83
收藏 1
点赞 2
评论 0

前面我们了解到可以使用std::shared_future/std::shared_future在多个其他线程中处理另外一个线程的函数的返回结果.

 

那么疑问来了,我们要怎样在多线程之间传递数据呢?

demo1 :std::promise在线程之间传递参数/处理异常:

#include <iostream>
#include <thread>
#include <chrono>
#include <future>
#include <utility>
#include <exception>
#include <stdexcept>
#include <string>

void doSomething(std::promise<std::string>&  p)
{
	try {
		std::cout << "read char('x' for exception): ";
		char c = std::cin.get();
		if (c == 'x') {
			throw  std::runtime_error(std::string("runtime_error"));
		}

		std::string str = std::string("char ") + c + std::string(" read");
		p.set_value(std::move(str));

		p.set_value(std::string("shihuawoaini"));

	}catch (...) {
		p.set_exception(std::current_exception());

	}
}

int main()
{
	try {
		std::promise<std::string> p;
		std::thread t1(doSomething, std::ref(p)); //注意这里是以引用的形式传递的std::promise对象.
        //只有以引用的形式我们才能改变std::promise中的shared state的状态,而且本事std::promise是不支持拷贝的
		t1.detach();

		std::future<std::string> f(p.get_future()); //此时的std::future和前面的std::promise共用同一个shared state;

		std::cout << "result: " << f.get() << std::endl; //注意这里的get(),当std::future的shared state未被设置为ready的时候会block mian线程.直到被设置为ready.

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

	}catch (...) {
		std::cerr << "EXCEPTION: " << std::endl;
	}
}

 最好自己跑一下上面的例子再看下面的内容

 

 

在向线程传递std::promise对象作为参数的时候尽量用std::ref.

1,因为std::promise对象是不支持拷贝的.

2,只有以by-reference的形式传递我们才能改变原std::promise对象的shared state.

std::promise的构造函数:

1,构造函数在构建std::promise的时候构建一个新的shared state.

2,移动构造函数从另外的std::promise对象获得shared state,被移动的std::promise对象不再具有shared state.

std::promise内的shared state存放一个相应类型的值或者异常.

promise(); //默认构造函数.

template <class Alloc> promise (allocator_arg_t aa, const Alloc& alloc);//自己设置内存分配器的构造函数.
	
promise (const promise&) = delete; //拷贝构造函数被删除掉了. 

promise (promise&& x) noexcept;//移动构造函数.

std::promise::get_future

该函数返回一个std::future对象,且std::future对象与当前std::promise共用一个shared state:

1, 也就是说当当前std::promise对象的shared state被设为ready的时候,被返回出来的std::future对象的shared state也被设置为ready.

2,也就是说我们可以通过被返回的std::future对象获得std::promise中的值和异常.

future<T> get_future();

std::promise::operator=

虽然是operator=但是只能使用移动赋值运算符.抛弃当前std::promise内的shared state,获得rhs的shared state,且被移动的std::promise对象变成不能使用状态,否则抛出std::future_error异常.

promise& operator= (promise&& rhs) noexcept;
	
promise& operator= (const promise&) = delete; //拷贝复制运算符被删除了.

std::promise::set_exception

exception_ptr是一个智能指针,存储一个指向异常的智能指针到std::promise的shared state,

且当前shared state的状态会立即被设置为ready.

void set_exception (exception_ptr p);

std::promise::set_value

设置一个值到存储到当前std::promise的shared state,且立即将shared state的状态设置为ready.

void set_value (const T& val);

void set_value (T&& val);

void promise<R&>::set_value (R& val);   // when T is a reference type (R&)

void promise<void>::set_value (void);   // when T is void

std::promise::set_exception_at_thread_exit

设置一个存储异常的智能指针存储到当前std::promise对象的shared state里,但是并没有立即把该shared state设置为ready,而是直到当前线程完成退出的时才被设置为ready.

void set_exception_at_thread_exit (exception_ptr p);

std::promise::set_value_at_thread_exit

设置一个值存储到当前std::promise对象的shared state里,但是并没有立即把该shared sate设置为ready,而是直到当前线程结束退出的时候才被设置为ready.

void set_value_at_thread_exit (const T& val);

void set_value_at_thread_exit (T&& val);

void promise<R&>::set_value_at_thread_exit (R& val);     // when T is a reference type (R&)

void promise<void>::set_value_at_thread_exit (void);     // when T is void

总结:

如果我们通过当前std::promise对象的get_future()得到一个std::future,由于是得到的std::future和当前std::promise对象是共用一个shared state的,因此当我们想要通过std::future对象的get()获得存储于shared state状态中的值的时候,如果这个shared state没有被设置为ready,就会阻塞正在调用该std::future对象get()函数的线程.

© 著作权归作者所有

共有 人打赏支持
SHIHUAMarryMe
粉丝 12
博文 165
码字总数 138772
作品 0
武汉
程序员
C++11实现跨平台线程池

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

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

Multi thread: std::shared_future(2)

在之前我们了解了class std::future,但是通过class std::future获得的结果只能get()一次,第二次调用就会产生不可预期的结果,通常会抛出一个std::future_error。 但是当多个其他线程想处理另...

SHIHUAMarryMe ⋅ 2016/05/13 ⋅ 0

Multi thread: std::async()和std::future(1)

对于初学者而言,“以多线程运行程序”的最佳起点就是C++标准库中的 std::async() 和 class std::future提供的高级接口. (1),std::async()提供一个接口,让一段机能或者说一个callable obje...

SHIHUAMarryMe ⋅ 2016/05/10 ⋅ 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++ 11 多线程处理(1)

几种线程的方式 创建线程 通过函数指针来创建一个线程 使用函数对象创建一个线程 使用 匿名函数来创建线程 不同线程之间的区别 第一个线程都会有一个ID成员函数指定关联线程对象的IDstd::th...

罗布V ⋅ 2016/07/07 ⋅ 0

boost库,Multi_Index的组合索引使用字符串数组

///@brief 声明字符比较 struct CharCompareLess { static inline int compare(const char left, const char right) { return strcmp(left, right); } inline bool operator()(const char le......

魔界卧龙 ⋅ 2015/09/06 ⋅ 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 并发编程教程 - Part 1 : thread 初探(bill译)

C++11 引入了一个新的线程库,包含了用于启动、管理线程的诸多工具,与此同时,该库还提供了包括互斥量、锁、原子量等在内的同步机制。在这个系列的教程中,我将尝试向大家展示这个新库提供的...

天下杰论 ⋅ 2013/12/29 ⋅ 0

C++11 并发编程教程 - Part 3 : 锁的进阶与条件变量

上一篇文章中我们学习了如何使用互斥量来解决一些线程同步问题。这一讲我们将进一步讨论互斥量的话题,并向大家介绍 C++11 并发库中的另一种同步机制 —— 条件变量。 递归锁 考虑下面这个简...

天下杰论 ⋅ 2013/12/29 ⋅ 0

condition_variable的怪事

今天看了篇介绍condition_variable的文章。于是copy例子到IDE下运行看看,小改了个地方,就出现了让我百思不得姐的结果。程序如下: include // std::cout include // std::thread include ...

人不知 ⋅ 2014/11/08 ⋅ 2

没有更多内容

加载失败,请刷新页面

加载更多

下一页

来自一个优秀Java工程师的简历

写在前面: 鉴于前几天的一份前端简历,虽然带着很多不看好的声音,但却帮助了很多正在求职路上的人,不管评论怎么说,我还是决定要贴出一份后端的简历。 XXX ID:357912485 目前正在找工作 ...

颖伙虫 ⋅ 18分钟前 ⋅ 0

Confluence 6 恢复一个站点有关使用站点导出为备份的说明

推荐使用生产备份策略。我们推荐你针对你的生产环境中使用的 Confluence 参考 Production Backup Strategy 页面中的内容进行备份和恢复(这个需要你备份你的数据库和 home 目录)。XML 导出备...

honeymose ⋅ 今天 ⋅ 0

JavaScript零基础入门——(九)JavaScript的函数

JavaScript零基础入门——(九)JavaScript的函数 欢迎回到我们的JavaScript零基础入门,上一节课我们了解了有关JS中数组的相关知识点,不知道大家有没有自己去敲一敲,消化一下?这一节课,...

JandenMa ⋅ 今天 ⋅ 0

火狐浏览器各版本下载及插件httprequest

各版本下载地址:http://ftp.mozilla.org/pub/mozilla.org//firefox/releases/ httprequest插件截至57版本可用

xiaoge2016 ⋅ 今天 ⋅ 0

Docker系列教程28-实战:使用Docker Compose运行ELK

原文:http://www.itmuch.com/docker/28-docker-compose-in-action-elk/,转载请说明出处。 ElasticSearch【存储】 Logtash【日志聚合器】 Kibana【界面】 答案: version: '2'services: ...

周立_ITMuch ⋅ 今天 ⋅ 0

使用快嘉sdkg极速搭建接口模拟系统

在具体项目研发过程中,一旦前后端双方约定好接口,前端和app同事就会希望后台同事可以尽快提供可供对接的接口方便调试,而对后台同事来说定好接口还仅是个开始、设计流程,实现业务逻辑,编...

fastjrun ⋅ 今天 ⋅ 0

PXE/KickStart 无人值守安装

导言 作为中小公司的运维,经常会遇到一些机械式的重复工作,例如:有时公司同时上线几十甚至上百台服务器,而且需要我们在短时间内完成系统安装。 常规的办法有什么? 光盘安装系统 ===> 一...

kangvcar ⋅ 昨天 ⋅ 0

使用Puppeteer撸一个爬虫

Puppeteer是什么 puppeteer是谷歌chrome团队官方开发的一个无界面(Headless)chrome工具。Chrome Headless将成为web应用自动化测试的行业标杆。所以我们很有必要来了解一下它。所谓的无头浏...

小草先森 ⋅ 昨天 ⋅ 0

Java Done Right

* 表示难度较大或理论性较强。 ** 表示难度更大或理论性更强。 【Java语言本身】 基础语法,面向对象,顺序编程,并发编程,网络编程,泛型,注解,lambda(Java8),module(Java9),var(...

风华神使 ⋅ 昨天 ⋅ 0

Linux系统日志

linux 系统日志 /var/log/messages /etc/logrotate.conf 日志切割配置文件 https://my.oschina.net/u/2000675/blog/908189 logrotate 使用详解 dmesg 命令 /var/log/dmesg 日志 last命令,调......

Linux学习笔记 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部