文档章节

Multi thread: std::promise

SHIHUAMarryMe
 SHIHUAMarryMe
发布于 2016/05/14 16:59
字数 1074
阅读 152
收藏 1

码上生花,ECharts 作品展示赛正式启动!>>>

前面我们了解到可以使用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
粉丝 13
博文 162
码字总数 138435
作品 0
武汉
程序员
私信 提问
加载中
请先登录后再评论。
C++11中std::promise的使用

C++11中的std::promise是个模板类。一个std::promise对象可以存储由future对象(可能在另一个线程中)检索的T类型的值或派生自std::exception的异常,并提供一个同步点。 在构造std::promise对...

fengbingchun
01/31
0
0
5分钟速成C++14多线程编程

原文链接:Learn C++ Multi-Threading in 5 Minutes   C++14的新的多线程架构非常简单易学,如果你对C或者C++很熟悉,那么本文非常适合你。作者用C++14作为基准参考,但是所介绍的东西在C...

osc_nd0lr8gs
2019/03/25
4
0
C++并发低级接口:std::thread和std::promise

std::thread和std::promise 相比,就原始多了。thread一定会创建新线程(而不是像async那样创建的时候可能不会,后面才创建新线程(std::launch::deferred)),并且创建它的线程还必须指定以何种...

osc_jghpf0ob
2018/04/29
2
0
C++11之std::future和std::promise和std::std::packaged_task

为什么C++11引入std::future和std::promise?C++11创建了线程以后,我们不能直接从thread.join()得到结果,必须定义一个变量,在线程执行时,对这个变量赋值,然后执行join(),过程相对繁琐。...

osc_jo6rqvdg
2018/04/18
2
0
第28课 “共享状态”提供者(std::promise/std::package_task)

一. std::promise和std::package_task (一)共享状态、提供者和管理者 template class _Promise { // class that implements core of promisepublic: } } } State.Swap(Other.State); priva......

浅墨浓香
2019/11/07
0
0

没有更多内容

加载失败,请刷新页面

加载更多

JDBC:ResultSet Types

ResultSet Types 用于确定ResultSet的某些特征和功能。 ResultSet.TYPE_FORWARD_ONLY 只能调用 next,不能调用 previous 。否则报错 ResultSet.TYPE_SCROLL_INSENSITIVE 能调用 next/previou...

mrsuperli
昨天
7
0
Cesium笔记(3):基本控件简介—ImageryProvider地图瓦片地图配

cesiumjs中可定制多种图层,可以使用互联网上很多地图提供商的图层数据,也可以使用自己的地图数据。Cesium支持多种标准化格式的GIS瓦片服务,可以把栅格图层绘制到地球的表面——cesiumjs的...

zhoulujun
昨天
15
0
跟小伟一起学习类加载机制

我们在学习 java 基础的时候,从宏观上了解了一个类到运行大致是:.java 文件通过 javac 编译器编译得到 .class 文件,在用到该类时,jvm 会加载该 class 文件,并创建对应的 class 对象,将...

niceyoo
昨天
8
0
Electron整合React使用搭建开发环境

Electron整合React使用搭建开发环境 博客说明 文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢! 简介 用于构建用户界面的 ...

归子莫
昨天
17
0
MyBatis常见面试题和答案

MyBatis是什么? MyBatis 是一款持久层框架,一个半 ORM(对象关系映射)框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。...

JaneRoad
昨天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部