一、std::promise介紹
std::promise是C++11併發編程中常用的一個類,常配合std::future使用。其作用是在一個線程t1中保存一個類型typename T的值,可供相綁定的std::future對象在另一線程t2中獲取。
二、代碼示例:
下面我們通過幾個簡單小例子逐漸深入瞭解std::promise的使用方法。
示例1:
#include <iostream>
#include <future>
#include <chrono>
void Thread_Fun1(std::promise<int> &p)
{
//爲了突出效果,可以使線程休眠5s
std::this_thread::sleep_for(std::chrono::seconds(5));
int iVal = 233;
std::cout << "傳入數據(int):" << iVal << std::endl;
//傳入數據iVal
p.set_value(iVal);
}
void Thread_Fun2(std::future<int> &f)
{
//阻塞函數,直到收到相關聯的std::promise對象傳入的數據
auto iVal = f.get(); //iVal = 233
std::cout << "收到數據(int):" << iVal << std::endl;
}
int main()
{
//聲明一個std::promise對象pr1,其保存的值類型爲int
std::promise<int> pr1;
//聲明一個std::future對象fu1,並通過std::promise的get_future()函數與pr1綁定
std::future<int> fu1 = pr1.get_future();
//創建一個線程t1,將函數Thread_Fun1及對象pr1放在線程裏面執行
std::thread t1(Thread_Fun1, std::ref(pr1));
//創建一個線程t2,將函數Thread_Fun2及對象fu1放在線程裏面執行
std::thread t2(Thread_Fun2, std::ref(fu1));
//阻塞至線程結束
t1.join();
t2.join();
return 1;
}
可以看到std::future對象fu1先是通過std::promise的函數get_future()與std::promise對象pr1相綁定,pr1在線程t1中通過set_value()傳入共享數據,fu1在線程t2中通過阻塞函數get()獲取到傳入的數據。
示例1中傳入的數據類型是int,前面介紹中說std::promise可以保存typename T的數據,那麼可以保存函數指針嗎?答案是可行的,請看示例。
示例2:
#include <iostream>
#include <future>
#include <chrono>
#include <functional>
//聲明一個可調對象T
using T = std::function<int(int)>; //等同於typedef std::function<int(int)> T;
int Test_Fun(int iVal)
{
std::cout << "Value is:" << iVal << std::endl;
return iVal + 232;
}
void Thread_Fun1(std::promise<T> &p)
{
//爲了突出效果,可以使線程休眠5s
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "傳入函數Test_Fun" << std::endl;
//傳入函數Test_Fun
p.set_value(std::bind(&Test_Fun, std::placeholders::_1));
}
void Thread_Fun2(std::future<T> &f)
{
//阻塞函數,直到收到相關聯的std::promise對象傳入的數據
auto fun = f.get(); //iVal = 233
int iVal = fun(1);
std::cout << "收到函數並運行,結果:" << iVal << std::endl;
}
int main()
{
//聲明一個std::promise對象pr1,其保存的值類型爲int
std::promise<T> pr1;
//聲明一個std::future對象fu1,並通過std::promise的get_future()函數與pr1綁定
std::future<T> fu1 = pr1.get_future();
//創建一個線程t1,將函數Thread_Fun1及對象pr1放在線程裏面執行
std::thread t1(Thread_Fun1, std::ref(pr1));
//創建一個線程t2,將函數Thread_Fun2及對象fu1放在線程裏面執行
std::thread t2(Thread_Fun2, std::ref(fu1));
//阻塞至線程結束
t1.join();
t2.join();
return 1;
}
既然可以傳函數對象,那麼是否可以通過模板魔改,傳入可變元函數?請看示例。示例3:
#include <iostream>
#include <future>
#include <chrono>
#include <functional>
//聲明一個可調對象F
using F = std::function<int(int, int, int&)>; //等同於typedef std::function<int(int, int, int&)> F;
//函數可以改成任意參數,任意返回類型
int Test_Fun(int a, int b, int &c)
{
//a = 1, b = 2
c = a + b + 230;
return c;
}
void Thread_Fun1(std::promise<F> &p)
{
//爲了突出效果,可以使線程休眠5s
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "傳入函數Test_Fun" << std::endl;
//傳入函數Test_Fun
p.set_value(std::bind(&Test_Fun, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
}
template<typename T, typename ...Args>
void Thread_Fun2(std::future<T> &f, Args&& ...args)
{
//阻塞函數,直到收到相關聯的std::promise對象傳入的數據
auto fun = f.get(); //fun等同於Test_Fun
auto fResult = fun(std::forward<Args>(args)...);
std::cout << "收到函數並運行,結果:" << fResult << std::endl;
}
int main()
{
//聲明一個std::promise對象pr1,其保存的值類型爲int
std::promise<F> pr1;
//聲明一個std::future對象fu1,並通過std::promise的get_future()函數與pr1綁定
std::future<F> fu1 = pr1.get_future();
//聲明一個變量
int iVal = 0;
//創建一個線程t1,將函數Thread_Fun1及對象pr1放在線程裏面執行
std::thread t1(Thread_Fun1, std::ref(pr1));
//創建一個線程t2,將函數Thread_Fun2及對象fu1放在線程裏面執行
std::thread t2(Thread_Fun2<F, int, int, int&>, std::ref(fu1), 1, 2, std::ref(iVal));
//阻塞至線程結束
t1.join();
t2.join();
//此時iVal的值變成233
return 1;
}
原文:https://blog.csdn.net/godmaycry/article/details/72844159?utm_source=copy