目录

C++ Promise/Future 模型

从 std::promise/std::future 到业界异步框架的演进

Promise/Future 是一种经典的异步抽象,正因为它提供了一套「标准化」的概念,因而衍生出许多可能性。这就如同工业史上的集装箱、软件界的 Docker——凭借「标准化」这一关键属性,不同组件可以简单地自由组合,从而大幅提升整体效率。

C++11 标准在 <future> 头文件中引入了一组与异步编程相关的类和函数。

<future> 头文件中主要包含以下几类组件:

  • Providers(提供者)类:std::promisestd::packaged_task
  • Futures(未来值)类:std::futurestd::shared_future
  • Providers 函数:std::async()
  • 其他类型:std::future_errorstd::future_errcstd::future_statusstd::launch

promise 对象可以保存某一类型 T 的值,该值可被 future 对象读取(可能在另一个线程中),因此 promise 也提供了一种线程同步的手段。在 promise 对象构造时,可以和一个共享状态(通常是 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;
}

C++11 标准库提供的 std::future 没有提供注册回调的接口,导致其使用受限,通常只用来跨线程传值同步。

业界多种异步编程框架都基于或扩展了 Promise/Future 机制,例如:

相关内容