c++ 11 多线线程 future

这里写图片描述

std::promise 类介绍

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

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

promise 对象是异步 Provider,它可以在某一时刻设置共享状态的值。
future 对象可以异步返回共享状态的值,或者在必要的情况下阻塞调用者并等待共享状态标志变为 ready,然后才能获取共享状态的值。
下面以一个简单的例子来说明上述关系

// promise example  
#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 << std::endl;  
}  

int main()  
{  
    std::promise<int> prom;                      // create promise  

    std::future<int> fut = prom.get_future();    // engagement with future  

    std::thread th1(print_int, std::ref(fut));  // send future to new thread  

    prom.set_value(10);                         // fulfill promise  
    // (synchronizes with getting the future)  
    th1.join();  
    return 0;  
}  

std::promise 类的构造函数讲解
这里写图片描述
另外,std::promise 的 operator= 没有拷贝语义,即 std::promise 普通的赋值操作被禁用,operator= 只有 move 语义,所以 std::promise 对象是禁止拷贝的。

// promise constructors  
#include <iostream>       // std::cout  
#include <functional>     // std::ref  
#include <memory>         // std::allocator, std::allocator_arg  
#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';  
}  

int main()  
{  
    std::promise<int> foo;  
    std::promise<int> bar = std::promise<int>(std::allocator_arg, std::allocator<int>());  

    std::future<int> fut = bar.get_future();  

    std::thread th(print_int, std::ref(fut));  

    bar.set_value(20);  

    th.join();  
    return 0;  
}  

std::promise::get_future 介绍

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

future

简单来说,std::future提供了一种访问异步操作结果的机制。

从字面意思看,它表示未来。通常一个异步操作我们是不能马上就获取操作结果的,只能在未来某个时候获取。我们可以以同步等待的方式来获取结果,可以通过查询future的状态(future_status)来获取异步操作的结果。future_status有三种状态:
deferred:异步操作还没开始
ready:异步操作已经完成
timeout:异步操作超时

获取future结果有三种方式:get、wait、wait_for,其中get等待异步操作结束并返回结果,wait只是等待异步操作完成,没有返回值,wait_for是超时等待返回结果。

   //查询future的状态
    std::future_status status;
    do {
        status = future.wait_for(std::chrono::seconds(1));
        if (status == std::future_status::deferred) {
            std::cout << "deferred\n";
        } else if (status == std::future_status::timeout) {
            std::cout << "timeout\n";
        } else if (status == std::future_status::ready) {
            std::cout << "ready!\n";
        }
    } while (status != std::future_status::ready);

std::promise

Promise对象可保存T类型的值,该值可被future对象读取(可能在另一个线程中),这是promise提供同步的一种手段。在构造promise时,promise对象可以与共享状态关联起来,这个共享状态可以存储一个T类型或者一个由std::exception派生出的类的值,并可以通过get_future来获取与promise对象关联的对象,调用该函数之后,两个对象共享相同的共享状态(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::get_future:返回一个与promise共享状态相关联的future对象
std::promise::set_value:设置共享状态的值,此后promise共享状态标识变为ready
std::promise::set_exception:为promise设置异常,此后promise的共享状态标识变为ready
std::promise::set_value_at_thread_exit:设置共享状态的值,但是不将共享状态的标志设置为 ready,当线程退出时该 promise 对象会自动设置为 ready(注意:该线程已设置promise的值,如果在线程结束之后有其他修改共享状态值的操作,会抛出future_error(promise_already_satisfied)异常)
std::promise::swap:交换 promise 的共享状态

std::packaged_task

std::packaged_task包装了一个可调用的目标(如function, lambda expression, bind expression, or another function object),以便异步调用,它和promise在某种程度上有点像,promise保存了一个共享状态的值,而packaged_task保存的是一个函数。

小结

Promise,Future 和 Callback常常作为并发编程中一组非阻塞的模型。其中 Future 表示一个可能还没有实际完成的异步任务的【结果】,针对这个结果可以添加 Callback 以便在任务执行成功或失败后做出对应的操作,而 Promise 交由任务执行者,任务执行者通过 Promise 可以标记任务完成或者失败。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值