C++ Futures與Promises線程使用示例講解
一、說(shuō)明
Futures 和 Promises 是將數(shù)據(jù)從一個(gè)線程傳遞到另一個(gè)線程的工具。雖然這也可以通過(guò)其他功能來(lái)完成,例如全局變量、futures 和 promises 在沒(méi)有它們的情況下也能工作。此外,您不需要自己處理同步。
未來(lái)是一個(gè)從另一個(gè)線程接收值的變量。如果您訪問(wèn)未來(lái)以獲取值,您可能需要等到其他線程提供該值。 Boost.Thread 提供 boost::future 來(lái)定義未來(lái)。該類(lèi)定義了一個(gè)成員函數(shù) get() 來(lái)獲取值。 get() 是一個(gè)阻塞函數(shù),可能需要等待另一個(gè)線程。
要在未來(lái)設(shè)置一個(gè)值,您需要使用一個(gè)承諾,因?yàn)?boost::future 不提供成員函數(shù)來(lái)設(shè)置一個(gè)值。
二、示例
Boost.Thread 提供類(lèi) boost::promise,它有一個(gè)成員函數(shù) set_value()。您總是將 future 和 promise 成對(duì)使用。您可以使用 get_future() 從承諾中獲得未來(lái)。您可以在不同的線程中使用未來(lái)和承諾。如果在一個(gè)線程中的 promise 中設(shè)置了一個(gè)值,則可以在另一個(gè)線程中從 future 中獲取它。
示例 44.14。使用 boost::future 和 boost::promise
#define BOOST_THREAD_PROVIDES_FUTURE #include <boost/thread.hpp> #include <boost/thread/future.hpp> #include <functional> #include <iostream> void accumulate(boost::promise<int> &p) { int sum = 0; for (int i = 0; i < 5; ++i) sum += i; p.set_value(sum); } int main() { boost::promise<int> p; boost::future<int> f = p.get_future(); boost::thread t{accumulate, std::ref(p)}; std::cout << f.get() << '\n'; }
示例使用未來(lái)和承諾。未來(lái) f 是從承諾 p 中接收到的。然后將對(duì) promise 的引用傳遞給執(zhí)行 accumulate() 函數(shù)的線程 t。 accumulate() 計(jì)算 0 到 5 之間所有數(shù)字的總和并將其保存在 promise 中。在 main() get() 中調(diào)用 future 將總數(shù)寫(xiě)入標(biāo)準(zhǔn)輸出。
未來(lái) f 和承諾 p 是相關(guān)聯(lián)的。當(dāng)對(duì)未來(lái)調(diào)用 get() 時(shí),將返回使用 set_value() 存儲(chǔ)在承諾中的值。因?yàn)樵撌纠褂脙蓚€(gè)線程,所以可能會(huì)在 accumulate() 調(diào)用 set_value() 之前在 main() 中調(diào)用 get()。在這種情況下,get() 會(huì)阻塞,直到使用 set_value() 將一個(gè)值存儲(chǔ)在 promise 中。
示例 44.14 顯示 10。
accumulate() 必須調(diào)整為在線程中執(zhí)行。它必須采用 boost::promise 類(lèi)型的參數(shù)并將結(jié)果存儲(chǔ)在其中。示例 44.15 引入了 boost::packaged_task,這是一個(gè)將值從任何函數(shù)轉(zhuǎn)發(fā)到未來(lái)的類(lèi),只要該函數(shù)通過(guò) return 返回結(jié)果即可。
示例 44.15。使用 boost::packaged_task
#define BOOST_THREAD_PROVIDES_FUTURE #include <boost/thread.hpp> #include <boost/thread/future.hpp> #include <utility> #include <iostream> int accumulate() { int sum = 0; for (int i = 0; i < 5; ++i) sum += i; return sum; } int main() { boost::packaged_task<int> task{accumulate}; boost::future<int> f = task.get_future(); boost::thread t{std::move(task)}; std::cout << f.get() << '\n'; }
示例 44.15 與前一個(gè)類(lèi)似,但這次沒(méi)有使用 boost::promise。相反,此示例使用類(lèi) boost::packaged_task,它與 boost::promise 一樣提供返回未來(lái)的成員函數(shù) get_future()。
boost::packaged_task 的構(gòu)造函數(shù)期望將在線程中執(zhí)行的函數(shù)作為參數(shù),但 boost::packaged_task 本身并不啟動(dòng)線程。必須將類(lèi)型為 boost::packaged_task 的對(duì)象傳遞給 boost::thread 的構(gòu)造函數(shù),以便在新線程中執(zhí)行該函數(shù)。
boost::packaged_task 的優(yōu)點(diǎn)是它在未來(lái)存儲(chǔ)函數(shù)的返回值。你不需要調(diào)整一個(gè)函數(shù)來(lái)在未來(lái)存儲(chǔ)它的值。 boost::packaged_task 可以看作是一個(gè)適配器,它可以存儲(chǔ)未來(lái)任何函數(shù)的返回值。
雖然該示例擺脫了 boost::promise,但以下示例也沒(méi)有使用 boost::packaged_task 和 boost::thread。
示例 44.16。使用 boost::async()
#define BOOST_THREAD_PROVIDES_FUTURE #include <boost/thread.hpp> #include <boost/thread/future.hpp> #include <iostream> int accumulate() { int sum = 0; for (int i = 0; i < 5; ++i) sum += i; return sum; } int main() { boost::future<int> f = boost::async(accumulate); std::cout << f.get() << '\n'; }
在示例 44.16 中,accumulate() 被傳遞給函數(shù) boost::async()。這個(gè)函數(shù)統(tǒng)一了 boost::packaged_task 和 boost::thread。它在新線程中啟動(dòng) accumulate() 并返回未來(lái)。
可以將啟動(dòng)策略傳遞給 boost::async()。這個(gè)附加參數(shù)決定了 boost::async() 是在新線程中還是在當(dāng)前線程中執(zhí)行該函數(shù)。如果您傳遞 boost::launch::async,boost::async() 將啟動(dòng)一個(gè)新線程;這是默認(rèn)行為。如果您傳遞 boost::launch::deferred,該函數(shù)將在調(diào)用 get() 時(shí)在當(dāng)前線程中執(zhí)行。
盡管 Boost 1.56.0 允許將 boost::launch::async 或 boost::launch::deferred 傳遞給 boost::async(),但尚未實(shí)現(xiàn)在當(dāng)前線程中執(zhí)行函數(shù)。如果您傳遞 boost::launch::deferred,程序?qū)⒔K止。
到此這篇關(guān)于C++ Futures與Promises線程使用示例講解的文章就介紹到這了,更多相關(guān)C++ Futures與Promises內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言中程序環(huán)境和預(yù)處理的詳細(xì)圖文講解
這篇文章主要給大家介紹了關(guān)于C語(yǔ)言中程序環(huán)境和預(yù)處理的相關(guān)資料,我們寫(xiě)的C語(yǔ)言代碼,從運(yùn)行,到在屏幕上生成結(jié)果,經(jīng)歷了比較復(fù)雜的過(guò)程,需要的朋友可以參考下2023-02-02C++&&Opencv實(shí)現(xiàn)控制臺(tái)字符動(dòng)畫(huà)的方法
這篇文章主要介紹了C++&&Opencv實(shí)現(xiàn)控制臺(tái)字符動(dòng)畫(huà)的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07使用OpenCV實(shí)現(xiàn)檢測(cè)和追蹤車(chē)輛
這篇文章主要為大家詳細(xì)介紹了使用OpenCV實(shí)現(xiàn)檢測(cè)和追蹤車(chē)輛,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01C++聚合關(guān)系類(lèi)的構(gòu)造函數(shù)的調(diào)用順序詳解
下面小編就為大家?guī)?lái)一篇C++聚合關(guān)系類(lèi)的構(gòu)造函數(shù)的調(diào)用順序詳解。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧2016-05-05用標(biāo)準(zhǔn)c++實(shí)現(xiàn)string與各種類(lèi)型之間的轉(zhuǎn)換
這個(gè)類(lèi)在頭文件中定義, < sstream>庫(kù)定義了三種類(lèi):istringstream、ostringstream和stringstream,分別用來(lái)進(jìn)行流的輸入、輸出和輸入輸出操作。另外,每個(gè)類(lèi)都有一個(gè)對(duì)應(yīng)的寬字符集版本2013-09-09C#委托所蘊(yùn)含的函數(shù)指針概念詳細(xì)解析
C#中用委托這種概念實(shí)現(xiàn)了函數(shù)指針技術(shù)而已,另外.ent提供額外的安全性,當(dāng)然也損失了靈活性2013-09-09