【C++基本语法】系列用来记录C++常用基本语法,惯用法。先放示例,再写语法分析。
本文主要回忆std::future相关用法,用例来自https://cplusplus.com/reference/future/future/
1. std::future
1.1 example
// future example
#include <iostream> // std::cout
#include <future> // std::async, std::future
#include <chrono> // std::chrono::milliseconds
// a non-optimized way of checking for prime numbers:
bool is_prime (int x) {
for (int i=2; i<x; ++i) if (x%i==0) return false;
return true;
}
int main ()
{
// call function asynchronously:
std::future<bool> fut = std::async (is_prime,444444443);
// do something while waiting for function to set future:
std::cout << "checking, please wait";
std::chrono::milliseconds span (100);
while (fut.wait_for(span)==std::future_status::timeout)
std::cout << '.' << std::flush;
bool x = fut.get(); // retrieve return value
std::cout << "\n444444443 " << (x?"is":"is not") << " prime.\n";
return 0;
}
结果
checking, please wait........
444444443 is prime.
代码解释
- std::async。它启动一个异步任务,这个任务是调用给定的函数(is_prime)并传递给它指定的参数(这里是444444443)。std::async可以自动决定该任务是立即在另一个线程上执行还是延迟执行直到其结果被需要时。
- std::future<>是一个模板类,用于获取异步操作的结果,这里用来接收is_prime函数的返回值。变量fut持有异步任务(即is_prime函数)的结果。通过调用fut.get()获取该结果。如果结果还没有准备好,调用get()会阻塞当前线程直到结果变为可用。
//在等待异步操作完成的同时,每隔100毫秒检查一次操作是否完成。
//如果操作未在100毫秒内完成,它会继续等待,同时执行循环体内的代码。
while (fut.wait_for(span)==std::future_status::timeout)
- fut.wait_for(span)调用会阻塞当前线程,直到以下三种情况之一发生:
– 指定的时间段span已经过去。
– 异步操作已经完成。
– 异步操作被异常终止。 - span是一个std::chrono::milliseconds对象,表示等待的时间长度。
- std::future_status::timeout是std::future_status枚举的一个值,表示等待期间异步操作没有完成。
如果wait_for的结果是std::future_status::timeout,意味着指定的时间段已经过去,但异步操作还没有完成。在这种情况下,循环体内的代码会被执行。这通常用于在等待异步操作完成的同时执行一些其他任务,这里是打印‘.’
1.2 future注意点
官网描述如下。
future是一个对象,可以异步获取“provider”对象的结果,并可以在多线程中同步结果。它有两个重要概念,一是“合法性”,二是“共享状态”
- 合法性是指,它只能通过调用async、promise::get_future和packaged_task::get_future这三个接口构造得到;通过future的默认构造函数生成的对象是不合法的(除非move一个合法对象)
- 合法的future对象是与“共享状态”关联的对象
- 共享状态的生存期至少持续到与其关联的最后一个对象释放或销毁为止。
1.3 std::future::get() 示例和简介
该接口返回future的结果(当有结果时);或者抛出异常。
官网关于它的表述如下,当shared state 是ready状态时返回结果,否则阻塞。
一旦返回,则对应的future不再合法,所以此接口只能被调用一次。
示例
// future::get
#include <iostream> // std::cout, std::ios
#include <future> // std::async, std::future
#include <exception> // std::exception
int get_int() {
std::cin.exceptions (std::ios::failbit); // throw on failbit set
int x;
std::cin >> x; // sets failbit if invalid
return x;
}
int main ()
{
std::future<int> fut = std::async (get_int);
std::cout << "Please, enter an integer value: ";
try {
int x = fut.get();
std::cout << "You entered: " << x << '\n';
}
catch (std::exception&) {
std::cout << "[exception caught]";
}
return 0;
}
结果
Please, enter an integer value:
123
You entered: 123