【C++高级编程 | 23】future、packaged_task等使用机制

call_onced

简介 - 原文链接:https://blog.csdn.net/xijiacun/article/details/71023777

#include <mutex>
template <class Fn, class... Args>
void call_once(once_flag &flag, Fn &&fn, Args &&... args);

第一个参数是std::once_flag的对象(once_flag是不允许修改的,其拷贝构造函数和operator=函数都声明为delete),第二个参数可调用实体,即要求只执行一次的代码,后面可变参数是其参数列表。

        call_once保证函数fn只被执行一次,如果有多个线程同时执行函数fn调用,则只有一个活动线程(active call)会执行函数,其他的线程在这个线程执行返回之前会处于”passive execution”(被动执行状态)——不会直接返回,直到活动线程对fn调用结束才返回。对于所有调用函数fn的并发线程,数据可见性都是同步的(一致的)。 

    如果活动线程在执行fn时抛出异常,则会从处于”passive execution”状态的线程中挑一个线程成为活动线程继续执行fn,依此类推。一旦活动线程返回,所有”passive execution”状态的线程也返回,不会成为活动线程。(实际上once_flag相当于一个锁,使用它的线程都会在上面等待,只有一个线程允许执行。如果该线程抛出异常,那么从等待中的线程中选择一个,重复上面的流程)

注意: once_flag的生命周期,它必须要比使用它的线程的生命周期要长。所以通常定义为全局变量。

1. 示例

 1 #include <thread>
 2 #include <iostream>
 3 #include <mutex>
 4 #include <vector>
 5 
 6 using namespace std;
 7 
 8 once_flag gOnceFlag;
 9 
10 void initializeSharedResources() {
11     cout << "Shared resources initialized." << endl;
12 }
13 
14 void processingFunction() {
15     call_once(gOnceFlag, initializeSharedResources);
16     cout << "Processing" << endl;
17 }
18 
19 int main() {
20     vector<thread> threads(3);
21     for (auto &t : threads) {
22         t = thread{processingFunction};
23     }
24 
25     for (auto &t : threads) {
26         t.join();
27     }
28 
29     return 0;
30 }

std::future 介绍

1. future图解

 

 1 #include <iostream>
 2 #include <thread>
 3 #include <future>
 4 
 5 using namespace std;
 6 
 7 void DoWork(promise<int> thePromise)
 8 {
 9     thePromise.set_value(42);
10 }
11 
12 int main()
13 {
14     promise<int> myPromise;
15     std::future<int> theFuture = myPromise.get_future();
16     thread theThread{DoWork, std::move(myPromise)};
17     int result = theFuture.get();
18 
19     cout << "Result: " << result << endl;
20     theThread.join();
21 
22     return 0;
23 }

std::packaged_task

 1 #include <iostream>
 2 #include <thread>
 3 #include <future>
 4 using namespace std;
 5 
 6 int CalculateSum(int a, int b)
 7 {
 8     return a + b;
 9 }
10 
11 int main()
12 {
13     packaged_task<int(int, int)> task(CalculateSum);
14     std::future<int> theFuture = task.get_future();
15     thread theThread{ std::move(task), 39, 3 };
16     int result = theFuture.get();
17     cout << result << endl;
18     theThread.join();
19     return 0;
20 }
 1 #include <iostream>
 2 #include <thread>
 3 #include <future>
 4 
 5 using namespace std;
 6 
 7 void DoWork(promise<int> thePromise)
 8 {
 9     thePromise.set_value(42);
10 }
11 
12 int main()
13 {
14     promise<int> myPromise;
15     std::future<int> theFuture = myPromise.get_future();
16     thread theThread{DoWork, std::move(myPromise)};
17     int result = theFuture.get();
18 
19     cout << "Result: " << result << endl;
20     theThread.join();
21 
22     return 0;
23 }

 

参考资料

1. C++11之std::future对象使用说明

2. C++11多线程编程 第八章: 使用 std::future std::promise 更优雅的获取线程返回值

原文地址:https://www.cnblogs.com/sunbines/p/14587435.html