前面两讲《C++11 并发指南二(std::thread 详解)》,《C++11 并发指南三(std::mutex 详解)》分别介绍了 std::thread 和 std::mutex,相信读者对 C++11 中的多线程编程有了一个最基本的认识,本文将介绍 C++11 标准中 <future> 头文件里面的类和相关函数。

<future> 头文件中包含了以下几个类和函数:

  • Providers 类:std::promise, std::package_task
  • Futures 类:std::future, shared_future.
  • Providers 函数:std::async()
  • 其他类型:std::future_error, std::future_errc, std::future_status, std::launch.

std::promise 类介绍

promise 对象可以保存某一类型 T 的值,该值可被 future 对象读取(可能在另外一个线程中),因此 promise 也提供了一种线程同步的手段。在 promise 对象构造时可以和一个共享状态(通常是std::future)相关联,并可以在相关联的共享状态(std::future)上保存一个类型为 T 的值。

可以通过 get_future 来获取与该 promise 对象相关联的 future 对象,调用该函数之后,两个对象共享相同的共享状态(shared state)

  • promise 对象是异步 Provider,它可以在某一时刻设置共享状态的值。
  • future 对象可以异步返回共享状态的值,或者在必要的情况下阻塞调用者并等待共享状态标志变为 ready,然后才能获取共享状态的值。

下面以一个简单的例子来说明上述关系

 #include <iostream>       // std::cout
#include <functional> // std::ref
#include <thread> // std::thread
#include <future> // std::promise, std::future void print_int(std::future<int>& fut) {
int x = fut.get(); // 获取共享状态的值.
std::cout << "value: " << x << '\n'; // 打印 value: 10.
} int main ()
{
std::promise<int> prom; // 生成一个 std::promise<int> 对象.
std::future<int> fut = prom.get_future(); // 和 future 关联.
std::thread t(print_int, std::ref(fut)); // 将 future 交给另外一个线程t.
prom.set_value(); // 设置共享状态的值, 此处和线程t保持同步.
t.join();
return ;
}

std::promise 构造函数

default (1)
promise();
with allocator (2)
template <class Alloc> promise (allocator_arg_t aa, const Alloc& alloc);
copy [deleted] (3)
promise (const promise&) = delete;
move (4)
promise (promise&& x) noexcept;
  1. 默认构造函数,初始化一个空的共享状态。
  2. 带自定义内存分配器的构造函数,与默认构造函数类似,但是使用自定义分配器来分配共享状态。
  3. 拷贝构造函数,被禁用。
  4. 移动构造函数。

另外,std::promise 的 operator= 没有拷贝语义,即 std::promise 普通的赋值操作被禁用,operator= 只有 move 语义,所以 std::promise 对象是禁止拷贝的。

例子:

 #include <iostream>       // std::cout
#include <thread> // std::thread
#include <future> // std::promise, std::future std::promise<int> prom; void print_global_promise () {
std::future<int> fut = prom.get_future();
int x = fut.get();
std::cout << "value: " << x << '\n';
} int main ()
{
std::thread th1(print_global_promise);
prom.set_value();
th1.join(); prom = std::promise<int>(); // prom 被move赋值为一个新的 promise 对象. std::thread th2 (print_global_promise);
prom.set_value ();
th2.join(); return ;
}

std::promise::get_future 介绍

该函数返回一个与 promise 共享状态相关联的 future 返回的 future 对象可以访问由 promise 对象设置在共享状态上的值或者某个异常对象。只能从 promise 共享状态获取一个 future 对象。在调用该函数之后,promise 对象通常会在某个时间点准备好(设置一个值或者一个异常对象),如果不设置值或者异常,promise 对象在析构时会自动地设置一个 future_error 异常(broken_promise)来设置其自身的准备状态。上面的例子中已经提到了 get_future,此处不再重复。

std::promise::set_value 介绍

generic template (1)
void set_value (const T& val);
void set_value (T&& val);
specializations (2)
void promise<R&>::set_value (R& val);   // when T is a reference type (R&)
void promise<void>::set_value (void); // when T is void

设置共享状态的值,此后 promise 的共享状态标志变为 ready.

std::promise::set_exception 介绍

为 promise 设置异常,此后 promise 的共享状态变标志变为 ready,例子如下,线程1从终端接收一个整数,线程2将该整数打印出来,如果线程1接收一个非整数,则为 promise 设置一个异常(failbit) ,线程2 在std::future::get 是抛出该异常。

 #include <iostream>       // std::cin, std::cout, std::ios
#include <functional> // std::ref
#include <thread> // std::thread
#include <future> // std::promise, std::future
#include <exception> // std::exception, std::current_exception void get_int(std::promise<int>& prom) {
int x;
std::cout << "Please, enter an integer value: ";
std::cin.exceptions (std::ios::failbit); // throw on failbit
try {
std::cin >> x; // sets failbit if input is not int
prom.set_value(x);
} catch (std::exception&) {
prom.set_exception(std::current_exception());
}
} void print_int(std::future<int>& fut) {
try {
int x = fut.get();
std::cout << "value: " << x << '\n';
} catch (std::exception& e) {
std::cout << "[exception caught: " << e.what() << "]\n";
}
} int main ()
{
std::promise<int> prom;
std::future<int> fut = prom.get_future(); std::thread th1(get_int, std::ref(prom));
std::thread th2(print_int, std::ref(fut)); th1.join();
th2.join();
return ;
}

std::promise::set_value_at_thread_exit 介绍

设置共享状态的值,但是不将共享状态的标志设置为 ready,当线程退出时该 promise 对象会自动设置为 ready。如果某个 std::future 对象与该 promise 对象的共享状态相关联,并且该 future 正在调用 get,则调用 get 的线程会被阻塞,当线程退出时,调用 future::get 的线程解除阻塞,同时 get 返回 set_value_at_thread_exit 所设置的值。注意,该函数已经设置了 promise 共享状态的值,如果在线程结束之前有其他设置或者修改共享状态的值的操作,则会抛出 future_error( promise_already_satisfied )。

std::promise::swap 介绍

交换 promise 的共享状态。

转自:http://www.cnblogs.com/haippy/p/3239248.html

C++11 并发指南四(<future> 详解一 std::promise 介绍)(转)的更多相关文章

  1. C++11 并发指南四(<future> 详解一 std::promise 介绍)

    前面两讲<C++11 并发指南二(std::thread 详解)>,<C++11 并发指南三(std::mutex 详解)>分别介绍了 std::thread 和 std::m ...

  2. C++11 并发指南四(<future> 详解二 std::packaged_task 介绍)

    上一讲<C++11 并发指南四(<future> 详解一 std::promise 介绍)>主要介绍了 <future> 头文件中的 std::promise 类, ...

  3. C++11 并发指南四(<future> 详解三 std::future & std::shared_future)

    上一讲<C++11 并发指南四(<future> 详解二 std::packaged_task 介绍)>主要介绍了 <future> 头文件中的 std::pack ...

  4. C++11 并发指南四(<future> 详解三 std::future & std::shared_future)(转)

    上一讲<C++11 并发指南四(<future> 详解二 std::packaged_task 介绍)>主要介绍了 <future> 头文件中的 std::pack ...

  5. C++11 并发指南三(Lock 详解)(转载)

    multithreading 多线程 C++11 C++11多线程基本使用 C++11 并发指南三(Lock 详解) 在 <C++11 并发指南三(std::mutex 详解)>一文中我们 ...

  6. C++11 并发指南三(Lock 详解)

    在 <C++11 并发指南三(std::mutex 详解)>一文中我们主要介绍了 C++11 标准中的互斥量(Mutex),并简单介绍了一下两种锁类型.本节将详细介绍一下 C++11 标准 ...

  7. 【C/C++开发】C++11 并发指南三(std::mutex 详解)

    本系列文章主要介绍 C++11 并发编程,计划分为 9 章介绍 C++11 的并发和多线程编程,分别如下: C++11 并发指南一(C++11 多线程初探)(本章计划 1-2 篇,已完成 1 篇) C ...

  8. C++11 并发指南系列

    本系列文章主要介绍 C++11 并发编程,计划分为 9 章介绍 C++11 的并发和多线程编程,分别如下: C++11 并发指南一(C++11 多线程初探)(本章计划 1-2 篇,已完成 1 篇) C ...

  9. C++11 并发指南系列(转)

    本系列文章主要介绍 C++11 并发编程,计划分为 9 章介绍 C++11 的并发和多线程编程,分别如下: C++11 并发指南一(C++11 多线程初探)(本章计划 1-2 篇,已完成 1 篇) C ...

随机推荐

  1. tzcacm去年训练的好题的AC代码及题解

    A - Tree UVA - 548 You are to determine the value of the leaf node in a given binary tree that is th ...

  2. Educational Codeforces Round 20 D. Magazine Ad

    The main city magazine offers its readers an opportunity to publish their ads. The format of the ad ...

  3. Set容器——TreeSet及常用API

    TreeSet及常用Api ①   TreeSet为使用树来进行存储的Set接口提供了一个工具,对象按升序存储,访问和检索很快; ②   在存储了大量的需要进行快速检索的排序信息的情况下,TreeSe ...

  4. Welcome-to-Swift-12附属脚本(Subscripts)

    附属脚本 可以定义在类(Class).结构体(structure)和枚举(enumeration)这些目标中,可以认为是访问对象.集合或序列的快捷方式,不需要再调用实例的特定的赋值和访问方法.举例来说 ...

  5. python调用C/C++动态链接库和jython

    总结(非原创) Python调用C库比较简单,不经过任何封装打包成so,再使用python的ctypes调用即可. 1. C语言文件:pycall.c #include <stdio.h> ...

  6. 【Luogu】P3396哈希冲突(根号算法)

    题目链接 根号算法真的是博大精深啊……明明是暴力但复杂度就是能过 这也太强了吧!!! 预处理出p<=sqrt(n)的所有情况,耗时n根n 查询: 如果p<=根n,O1查表 如果p>= ...

  7. bzoj 1003 [ZJOI2006]物流运输(最短路+dp)

    [ZJOI2006]物流运输 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 8973  Solved: 3839[Submit][Status][Di ...

  8. 模型表单ModleForm

    官方文档网址   http://python.usyiyi.cn/documents/django_182/topics/forms/modelforms.html 模型表单的应用场景 如果你正在构建 ...

  9. hdu 1250 树形DP

    Anniversary party Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u S ...

  10. 数表(bzoj 3529)

    Description 有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为能同时整除i和j的所有自然数之和.给定a,计算数表中不大于a ...