C++11 <future>中std::promise 介绍

 更新时间:2020年02月06日 11:20:38   作者:Haippy  
这篇文章主要介绍了C++11 <future>中std::promise 介绍,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前面两讲《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(10); // 设置共享状态的值, 此处和线程t保持同步.
  t.join();
  return 0;
}

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;

  • 默认构造函数,初始化一个空的共享状态。
  • 带自定义内存分配器的构造函数,与默认构造函数类似,但是使用自定义分配器来分配共享状态。
  • 拷贝构造函数,被禁用。
  • 移动构造函数。

另外,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(10);
  th1.join();

  prom = std::promise<int>();  // prom 被move赋值为一个新的 promise 对象.

  std::thread th2 (print_global_promise);
  prom.set_value (20);
  th2.join();

 return 0;
}

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 0;
}

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 的共享状态。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 浅析C++中的动态内存分配

    浅析C++中的动态内存分配

    这篇文章主要为大家详细介绍了C++中动态内存分配的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-03-03
  • C语言全方位讲解数组的使用

    C语言全方位讲解数组的使用

    数组是一组有序的数据的集合,数组中元素类型相同,由数组名和下标唯一地确定,数组中数据不仅数据类型相同,而且在计算机内存里连续存放,地址编号最低的存储单元存放数组的起始元素,地址编号最高的存储单元存放数组的最后一个元素
    2022-04-04
  • C语言算术运算符整理

    C语言算术运算符整理

    算术运算符用于各类数值运算,包括加(+)、减(-)、乘(*)、除(/)、求余(或称模运算,%)、自增(++)、自减(--)共七种
    2023-03-03
  • C语言实现绘制南丁格尔玫瑰图的示例代码

    C语言实现绘制南丁格尔玫瑰图的示例代码

    玫瑰图中有一种不等半径的统计图称为南丁格尔玫瑰图,网上很热门,是一很有艺术感的漂亮的统计图,下面我们就来看看如何使用C语言绘制它吧
    2024-03-03
  • c语言获取直播吧最近一周nba比赛信息

    c语言获取直播吧最近一周nba比赛信息

    这篇文章主要介绍了使用c语言获取直播吧最近一周nba比赛信息的方法,需要的朋友可以参考下
    2014-04-04
  • Qt实现绘制网格背景的示例代码

    Qt实现绘制网格背景的示例代码

    这篇文章主要介绍了Qt如何实现绘制网格背景,并且能实现窗口大小调整时网格背景也自动调整重绘,感兴趣的小伙伴可以跟随小编一起学习一下
    2022-06-06
  • C语言二维数组运用实现扫雷游戏

    C语言二维数组运用实现扫雷游戏

    这篇文章主要为大家详细介绍了C语言二维数组运用实现扫雷游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • C++虚函数表和虚析构介绍

    C++虚函数表和虚析构介绍

    这篇文章主要介绍了C++虚函数表和虚析构,虚函数表是C++实现多态的基础,多态是面向对象的三大特性之一,下面文章我们一起来看看详细内容,需要的朋友可以参考一下
    2021-11-11
  • C++ decltype用法举例说明

    C++ decltype用法举例说明

    decltype是C++11添加的一个新的关键字,目的是选择并返回操作数的数据类型,重要的是,在此过程中编译器分析表达式并得到它的类型,却不实际计算表达式的值,今天通过本文给大家介绍C++ decltype用法,通过实例代码给大家介绍的非常详细,需要的朋友参考下吧
    2021-07-07
  • 浅析c++中new和delete的用法

    浅析c++中new和delete的用法

    以下是对c++中new和delete的用法进行了详细的分析介绍,需要的朋友可以过来参考下
    2013-09-09

最新评论