Effective Modern C++: 多线程与资源互锁 [三]

std::future

std::future期待一个返回,从一个异步调用的角度来说,future更像是执行函数的返回值,C++标准库使用std::future为一次性事件建模,如果一个事件需要等待特定的一次性事件,那么这线程可以获取一个future对象来代表这个事件。异步调用往往不知道何时返回,但是如果异步调用的过程需要同步,或者说后一个异步调用需要使用前一个异步调用的结果。这个时候就要用到future。
线程可以周期性的在这个future上等待一小段时间,检查future是否已经ready,如果没有,该线程可以先去做另一个任务,一旦future就绪,该future就无法复位(无法再次使用这个future等待这个事件),所以future代表的是一次性事件

 

std::packaged_task

可以通过std::packaged_task对象获取任务相关联的feature,调用get_future()方法可以获得std::packaged_task对象绑定的函数的返回值类型的future。std::packaged_task的模板参数是函数签名

 

std::promise

从字面意思上理解promise代表一个承诺。promise比std::packaged_task抽象层次低。
std::promise<T>提供了一种设置值的方式,它可以在这之后通过相关联的std::future<T>对象进行读取。换种说法,之前已经说过std::future可以读取一个异步函数的返回值了,那么这个std::promise就提供一种方式手动让future就绪。

 

示例代码:

 1 #include <future>
 2 #include <string>
 3 #include <thread>
 4 #include <iostream>
 5 
 6 void print(std::promise<std::string>& p)
 7 {
 8     std::cout << "exe print" << std::endl;
 9     p.set_value("There is the result whitch you want.");
10 }
11 
12 int add(int a, int b)
13 {
14     std::cout << "exe add" << std::endl;
15     return a + b;
16 }
17 
18 void do_some_other_things()
19 {
20     std::cout << "Hello World" << std::endl;
21 }
22 
23 int main()
24 {
25     std::packaged_task<int(int, int)> task(add);
26     std::future<int> res = task.get_future();
27     std::promise<std::string> promise;
28     task(1,1);
29 
30     std::future<std::string> result = promise.get_future();
31     std::thread t(print, std::ref(promise));
32     std::this_thread::sleep_for(std::chrono::seconds(1));
33     do_some_other_things();
34     std::cout << result.get() << std::endl;
35     std::cout << res.get() << std::endl;
36     t.join();
37     return 0;
38 }

 

std::async

功能:第二个参数接收一个可调用对象(仿函数、lambda表达式、类成员函数、普通函数......)作为参数,并且异步或是同步执行他们。

a、对于是异步执行还是同步执行,由第一个参数的执行策略决定:

(1)std::launch::async 传递的可调用对象异步执行;

(2)std::launch::deferred 传递的可调用对象同步执行;

(3)std::launch::async | std::launch::deferred 可以异步或是同步,取决于操作系统,我们无法控制;

(4)如果我们不指定策略,则相当于(3)

b、对于执行结果:

我们可以使用get、wait、wait_for、wait_until等待执行结束,区别是get可以获得执行的结果。如果选择异步执行策略,调用get时,如果异步执行没有结束,get会阻塞当前调用线程,直到异步执行结束并获得结果,如果异步执行已经结束,不等待获取执行结果;如果选择同步执行策略,只有当调用get函数时,同步调用才真正执行,这也被称为函数调用被延迟。

c、返回结果std::future的状态:

(1)deffered:异步操作还没有开始;

(2)ready:异步操作已经完成;

(3)timeout:异步操作超时。

Example:

 1 #include <thread>
 2 #include <future>
 3 #include <iostream>
 4 #include <chrono>
 5 
 6 int main(){
 7     auto f1 = std::async(std::launch::async, [](){
 8         std::this_thread::sleep_for(std::chrono::seconds(9));
 9         return 42;
10     });
11 
12     auto f2 = std::async(std::launch::async, [](){
13         std::this_thread::sleep_for(std::chrono::seconds(3));
14         return 13;
15     });
16 
17     auto f3 = std::async(std::launch::async, [](){
18         std::this_thread::sleep_for(std::chrono::seconds(6));
19         return 666;
20     });
21 
22     auto timeout = std::chrono::milliseconds(10);
23 
24     while(f1.valid() || f2.valid() || f3.valid()){
25         if(f1.valid() && f1.wait_for(timeout) == std::future_status::ready){
26             std::cout << "Task1 is done! " << f1.get() << std::endl;
27         }
28 
29         if(f2.valid() && f2.wait_for(timeout) == std::future_status::ready){
30             std::cout << "Task2 is done! " << f2.get() << std::endl;
31         }
32 
33         if(f3.valid() && f3.wait_for(timeout) == std::future_status::ready){
34             std::cout << "Task3 is done! " << f3.get() << std::endl;
35         }
36 
37         std::cout << "I'm doing my own work!" << std::endl;
38         std::this_thread::sleep_for(std::chrono::seconds(1));
39         std::cout << "I'm done with my own work!" << std::endl;
40     }
41 
42     std::cout << "Everything is done, let's go back to the tutorial" << std::endl;
43 
44     return 0;
45 }

Result:

I'm doing my own work!
I'm done with my own work!
I'm doing my own work!
I'm done with my own work!
I'm doing my own work!
I'm done with my own work!
Task2 is done! 13
I'm doing my own work!
I'm done with my own work!
I'm doing my own work!
I'm done with my own work!
I'm doing my own work!
I'm done with my own work!
Task3 is done! 666
I'm doing my own work!
I'm done with my own work!
I'm doing my own work!
I'm done with my own work!
I'm doing my own work!
I'm done with my own work!
Task1 is done! 42
I'm doing my own work!
I'm done with my own work!
Everything is done, let's go back to the tutorial

 

                                                                                                        

                                               

 

原文链接: https://www.cnblogs.com/Asp1rant/p/12670213.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    Effective Modern C++: 多线程与资源互锁 [三]

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/340873

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 上午12:48
下一篇 2023年3月2日 上午12:48

相关推荐