C++ 并发三件套 - future, promise, async

C++标准库提供了很多用于并发编程的工具,不太熟悉,总结一下。

#异步计算结果 std::future<T>

std::future<T> 表示一个异步计算过程的结果。

std::future::wait() 方法阻塞当前线程直至计算完成。如果计算已经完成,则直接返回。

std::future::get() 方法等待计算完成,并获取 future<T> 表示的值或异常。get() 方法会消耗掉当前 future 保存的值,因此只能调用一次。

std::future::valid() 方法表示当前 future 中是否还有值可以被获取,如果值已经被 get 过,则会返回 false。

std::future::share() 方法返回一个 std::shared_future<T>

std::future<T> 是 move-only 的结构,且独占 T 的所有权。当多个对等的线程需要访问同一个期望值时,可以使用 copyable 的 std::shared_future<T>。注意,std::shared_future<T> 本身并不是线程安全的,需要每个线程拷贝并持有一个自己的 std::shared_future<T>

#异步生产者 std::promise<T>

std::promise<T> 用于生产者提供一个 std::future<T> 及其中的值给消费者。std::promise<T>::get_future() 方法返回一个 std::future<T> 给消费者。

对于生产者,使用 std::promise<T>::set_value() 方法填充 future 中的值;或者使用 std::promise<T>::set_exception() 方法填充 future 中的异常;

1
2
3
4
5
6
7
extern std::promise<double> some_promise;

try {
some_promise.set_value(calculate_value());
} catch(...) {
some_promise.set_exception(std::current_exception());
}

#异步执行 std::async()

std::async 是一个函数,它启动一个异步任务去执行指定的函数,返回一个表示计算结果的 std::future

std::async 允许额外指定一个std::launch类型的参数来指定任务启动的方式,有以下几种启动策略:

  • std::launch::async: 任务必须在独立线程中执行,因此需要库去负责线程创建和销毁;
  • std::launch::deferred: 任务可以延迟到wait()或者get()的时候,在调用者线程上同步执行 (有点类似Rust Tokio的设计);
  • std::launch::async | std::launch::deferred: 默认的方式,表示以上两种执行时机都可以,由具体实现去选择。