std::future ---C++17 多线程

std::future —C++17 多线程

std::future

C++标准程序库使用future来模拟这类一次性事件:若线程需等待某个特定的一次性事件发生,则会以恰当的方式取得一个future,它代表目标事件;接着,该线程就能一边执行其他任务(光顾机场茶座),一边在future上等待;同时,它以短暂的间隔反复查验目标事件是否已经发生(查看出发时刻表)。这个线程也可以转换运行模式,先不等目标事件发生,直接暂缓当前任务,而切换到别的任务,及至必要时,才回头等待future准备就绪。future可能与数据关联(如航班的登机口),也可能未关联。一旦目标事件发生,其future即进入就绪状态,无法重置。

总之,先保存一个事件(创建future对象),在未来获取事件的结果(get)

#pragma once
#include <future>
#include <iostream>
#include <format>
using namespace std;

std::string get_answer_from_hard_question()
{
	std::this_thread::sleep_for(2s);
	cout << "id: " << std::this_thread::get_id << endl;
	return string("答案在这\n");
}
void do_something()
{
	std::this_thread::sleep_for(5s);
	cout << "id: " << std::this_thread::get_id << endl;
	cout << "结束任务\n";
}

void start()
{
	std::future<std::string> the_ans = std::async(std::launch::async,get_answer_from_hard_question);
	do_something();
	std::cout << std::format("答案是:{}", the_ans.get());
}

创建future对象的方法

#include <string>
#include <future>
struct X
{
    void foo(int,std::string const&);
    std::string bar(std::string const&);
};
X x;    
auto f1=std::async(&X::foo,&x,42,"hello");---  ①调用p->foo(42,"hello"),其中p的值是&x,即x的地址
auto f2=std::async(&X::bar,x,"goodbye");---  ②调用tmpx.bar("goodbye"),其中tmpx是x的副本
struct Y                                
{
    double operator()(double);
}; 
Y y;
auto f3=std::async(Y(),3.141);---  ③调用tmpy(3.141)。其中,由Y()生成一个匿名变量,传递给std::async(),进而发生移动构造。在std::async()内部产生对象tmpy,在tmpy上执行Y::operator()(3.141) 
auto f4=std::async(std::ref(y),2.718);---  ④调用y(2.718)
X baz(X&);
std::async(baz,std::ref(x));---  ⑤调用baz(x)
class move_only
{
public:
    move_only();
    move_only(move_only&&)
    move_only(move_only const&) = delete;
    move_only& operator=(move_only&&);
    move_only& operator=(move_only const&) = delete;
    void operator()();
}; 
auto f5=std::async(move_only());---  ⑥调用tmp(),其中tmp等价于std::move (move_only()),它的产生过程与③相似

按默认情况下,std::async()的具体实现会自行决定——等待future时,是启动新线程,还是同步执行任务。大多数情况下,我们正希望如此。不过,我们还能够给std::async()补充一个参数,以指定采用哪种运行方式。参数的类型是std::launch,其值可以是std::launch::deferredstd::launch::async。前者指定在当前线程上延后调用任务函数,等到在future上调用了wait()get(),任务函数才会执行;后者指定必须另外开启专属的线程,在其上运行任务函数。该参数的值还可以是std::launch::deferred | std::launch:: async,表示由std::async()的实现自行选择运行方式。最后这项是参数的默认值。若延后调用任务函数,则任务函数有可能永远不会运行。举例如下。

auto f6=std::async(std::launch::async,Y(),1.2);---  ①运行新线程

auto f7=std::async(std::launch::deferred,baz,std::ref(x));---  ②在wait()get()内部运行任务函数
auto f8=std::async(---  
   std::launch::deferred | std::launch::async,
   baz,std::ref(x));
auto f9=std::async(baz,std::ref(x));---  ③交由实现自行选择运行方式
f7.wait();---  ④前面②处的任务函数调用被延后,到这里才运行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值