zoukankan      html  css  js  c++  java
  • 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,然后才能获取共享状态的值。

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

     1 #include <iostream>       // std::cout
     2 #include <functional>     // std::ref
     3 #include <thread>         // std::thread
     4 #include <future>         // std::promise, std::future
     5 
     6 void print_int(std::future<int>& fut) {
     7     int x = fut.get(); // 获取共享状态的值.
     8     std::cout << "value: " << x << '
    '; // 打印 value: 10.
     9 }
    10 
    11 int main ()
    12 {
    13     std::promise<int> prom; // 生成一个 std::promise<int> 对象.
    14     std::future<int> fut = prom.get_future(); // 和 future 关联.
    15     std::thread t(print_int, std::ref(fut)); // 将 future 交给另外一个线程t.
    16     prom.set_value(10); // 设置共享状态的值, 此处和线程t保持同步.
    17     t.join();
    18     return 0;
    19 }

    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 对象是禁止拷贝的。

    例子:

     1 #include <iostream>       // std::cout
     2 #include <thread>         // std::thread
     3 #include <future>         // std::promise, std::future
     4 
     5 std::promise<int> prom;
     6 
     7 void print_global_promise () {
     8     std::future<int> fut = prom.get_future();
     9     int x = fut.get();
    10     std::cout << "value: " << x << '
    ';
    11 }
    12 
    13 int main ()
    14 {
    15     std::thread th1(print_global_promise);
    16     prom.set_value(10);
    17     th1.join();
    18 
    19     prom = std::promise<int>();    // prom 被move赋值为一个新的 promise 对象.
    20 
    21     std::thread th2 (print_global_promise);
    22     prom.set_value (20);
    23     th2.join();
    24 
    25   return 0;
    26 }

     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 是抛出该异常。

     1 #include <iostream>       // std::cin, std::cout, std::ios
     2 #include <functional>     // std::ref
     3 #include <thread>         // std::thread
     4 #include <future>         // std::promise, std::future
     5 #include <exception>      // std::exception, std::current_exception
     6 
     7 void get_int(std::promise<int>& prom) {
     8     int x;
     9     std::cout << "Please, enter an integer value: ";
    10     std::cin.exceptions (std::ios::failbit);   // throw on failbit
    11     try {
    12         std::cin >> x;                         // sets failbit if input is not int
    13         prom.set_value(x);
    14     } catch (std::exception&) {
    15         prom.set_exception(std::current_exception());
    16     }
    17 }
    18 
    19 void print_int(std::future<int>& fut) {
    20     try {
    21         int x = fut.get();
    22         std::cout << "value: " << x << '
    ';
    23     } catch (std::exception& e) {
    24         std::cout << "[exception caught: " << e.what() << "]
    ";
    25     }
    26 }
    27 
    28 int main ()
    29 {
    30     std::promise<int> prom;
    31     std::future<int> fut = prom.get_future();
    32 
    33     std::thread th1(get_int, std::ref(prom));
    34     std::thread th2(print_int, std::ref(fut));
    35 
    36     th1.join();
    37     th2.join();
    38     return 0;
    39 }

    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

  • 相关阅读:
    DTree中致命的递归
    通过CLR同步SQL Server和Sharepoint List数据(三)
    通过CLR同步SQL Server和Sharepoint List数据(四)
    C#中操作IIS 7.0
    可爱又可恨的梅花雪
    通过CLR同步SQL Server和Sharepoint List数据(一)
    在Javascript中调用WSS
    VBA在Excel中的应用(二)
    自己编写存储过程对Oracle中的序列进行重置
    在Javascript中实现伪哈希表
  • 原文地址:https://www.cnblogs.com/zl1991/p/6993929.html
Copyright © 2011-2022 走看看