c++11 std::promise介紹及使用

一、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 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章