std::future
是 C++11 引入的一个类模板,用于表示一个异步操作的结果。它通常与 std::async
、std::promise
或线程池等一起使用,以便在不阻塞当前线程的情况下获取其他线程或异步任务的结果。
以下是如何使用 std::future
的一些基本步骤和示例:
1. 使用 std::async
创建 std::future
std::async
是一个函数模板,它启动一个新的异步任务,并返回一个 std::future
对象,该对象表示该任务的结果。
#include <iostream>
#include <future>
#include <chrono>
int some_task() {
std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时操作
return 42; // 返回结果
}
int main() {
// 启动异步任务并获取表示结果的 std::future 对象
std::future<int> result = std::async(std::launch::async, some_task);
// 在这里可以做其他工作...
// 获取异步任务的结果(这可能会阻塞,直到结果可用)
int value = result.get();
std::cout << "Result of async task: " << value << std::endl;
return 0;
}
在这个例子中,std::async
启动了 some_task
函数作为一个异步任务,并返回一个 std::future<int>
对象。通过调用 result.get()
,我们可以获取该任务的结果。注意,get()
函数是阻塞的,它会等待直到结果可用。
2. 使用 std::promise
和 std::future
有时候,你可能想要手动设置一个 std::future
的值,而不是通过 std::async
。在这种情况下,你可以使用 std::promise
对象。
#include <iostream>
#include <future>
#include <thread>
void set_value(std::promise<int> prom) {
std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟耗时操作
prom.set_value(42); // 设置 future 的值
}
int main() {
// 创建一个 promise 对象
std::promise<int> prom;
// 获取与 promise 关联的 future 对象
std::future<int> result = prom.get_future();
// 在新线程中运行设置值的函数
std::thread t(set_value, std::move(prom));
// 在这里可以做其他工作...
// 获取 future 的值(这可能会阻塞,直到值被设置)
int value = result.get();
std::cout << "Value set by promise: " << value << std::endl;
// 确保线程结束
t.join();
return 0;
}
在这个例子中,我们创建了一个 std::promise<int>
对象,并通过调用 get_future()
获取了一个与之关联的 std::future<int>
对象。然后,我们在一个新线程中运行了 set_value
函数,该函数接受 std::promise
对象作为参数,并在模拟耗时操作后调用 set_value()
来设置 std::future
的值。
注意事项
std::future
的get()
方法是阻塞的,它会等待直到结果可用。如果你不想阻塞,你可以使用wait_for
或wait_until
方法来检查结果是否可用。std::future
和std::promise
是线程安全的,可以在多个线程之间安全地共享和访问。- 如果你不再需要
std::future
的结果,你应该调用std::future::discard_result()
来避免不必要的资源消耗。 - 当
std::promise
的对象被销毁且其关联的std::future
尚未获取结果时,任何对std::future
的get()
调用都将抛出std::future_error
异常。
std::future
的 wait_for
和 wait_until
是两个用于等待异步操作结果的成员函数。它们允许你在不阻塞当前线程的情况下,检查与 std::future
关联的异步操作是否已经完成,或者是否已经达到了指定的等待时间。
wait_for
的使用方法
wait_for
函数接受一个表示等待时间的 std::chrono::duration
对象作为参数,并返回一个 std::future_status
枚举值,指示异步操作的状态。
template<class Rep, class Period>
std::future_status wait_for(const std::chrono::duration<Rep, Period>& timeout_duration) const;
timeout_duration
:要等待的时间长度。- 返回值:
std::future_status
,可以是以下三个值之一:std::future_status::ready
:异步操作已经完成,结果已经就绪。std::future_status::timeout
:等待时间已过,但异步操作尚未完成。std::future_status::deferred
:如果std::async
被调用时使用了std::launch::deferred
策略,并且异步操作尚未被启动。
示例代码:
#include <iostream>
#include <future>
#include <chrono>
#include <thread>
int some_task() {
std::this_thread::sleep_for(std::chrono::seconds(3)); // 模拟耗时操作
return 42; // 返回结果
}
int main() {
// 启动异步任务并获取表示结果的 std::future 对象
std::future<int> result = std::async(std::launch::async, some_task);
// 等待异步任务2秒
std::future_status status = result.wait_for(std::chrono::seconds(2));
if (status == std::future_status::ready) {
std::cout << "Task completed, result: " << result.get() << std::endl;
} else if (status == std::future_status::timeout) {
std::cout << "Task not completed within the specified time." << std::endl;
// 可以选择继续等待或执行其他操作
} else if (status == std::future_status::deferred) {
std::cout << "Task is deferred and has not been started yet." << std::endl;
}
return 0;
}
wait_until
的使用方法
wait_until
函数接受一个表示绝对等待时间点的 std::chrono::time_point
对象作为参数,并返回一个 std::future_status
枚举值。
template<class Clock, class Duration>
std::future_status wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time) const;
timeout_time
:要等待到的绝对时间点。- 返回值:与
wait_for
相同,为std::future_status
枚举值。
示例代码:
#include <iostream>
#include <future>
#include <chrono>
#include <thread>
int some_task() {
std::this_thread::sleep_for(std::chrono::seconds(5)); // 模拟耗时操作
return 42; // 返回结果
}
int main() {
// 获取当前时间点并计算等待到的绝对时间点(当前时间+4秒)
auto now = std::chrono::system_clock::now();
auto timeout = now + std::chrono::seconds(4);
// 启动异步任务并获取表示结果的 std::future 对象
std::future<int> result = std::async(std::launch::async, some_task);
// 等待异步任务直到指定的时间点
std::future_status status = result.wait_until(timeout);
if (status == std::future_status::ready) {
std::cout << "Task completed, result: " << result.get() << std::endl;
} else if (status == std::future_status::timeout) {
std::cout << "Task not completed by the specified time." << std::endl;
// 可以选择继续等待或执行其他操作
} else if (status == std::future_status::deferred) {
std::cout << "Task is deferred and has not been started yet." << std::endl;
}
return 0;
}
在这两个示例中,wait_for
和 wait_until
分别用于等待异步操作完成一定的时间或直到指定的时间点。如果异步操作在这段时间内完成,std::future
的状态将变为 ready
,并且你可以调用 get()
方法来获取结果。如果等待时间已过但异步操作尚未完成,状态将为 timeout
,你可以根据需要决定是继续等待还是执行其他操作。如果异步操作被延迟执行(使用了 std::launch::deferred
策略),状态将为 deferred
。