C++ Boost Coroutine使用協(xié)程詳解
一、說明語言擴(kuò)展
以下庫擴(kuò)展了編程語言 C++。
- Boost.Coroutine 使得在 C++ 中使用協(xié)程成為可能——其他編程語言通常通過關(guān)鍵字 yield 支持。
- Boost.Foreach 提供了一個基于范圍的 for 循環(huán),它是在 C++11 中添加到語言中的。
- Boost.Parameter 允許您以名稱/值對的形式并以任何順序傳遞參數(shù)——例如,這在 Python 中是允許的。
- Boost.Conversion 提供了兩個轉(zhuǎn)換運算符來替換 dynamic_cast 并允許您區(qū)分向下轉(zhuǎn)換和交叉轉(zhuǎn)換。
二、庫Boost.Coroutine
通過 Boost.Coroutine,可以在 C++ 中使用協(xié)程。協(xié)程是其他編程語言的一個特性,通常使用關(guān)鍵字 yield 來表示協(xié)程。在這些編程語言中,yield 可以像 return 一樣使用。但是,當(dāng)使用 yield 時,該函數(shù)會記住該位置,如果再次調(diào)用該函數(shù),將從該位置繼續(xù)執(zhí)行。
C++ 沒有定義關(guān)鍵字 yield。但是,使用 Boost.Coroutine 可以從函數(shù)返回并稍后從同一位置繼續(xù)。 Boost.Asio 庫也使用 Boost.Coroutine 并受益于協(xié)程。
三、示例和代碼
Boost.Coroutine 有兩個版本。本章介紹第二個版本,即當(dāng)前版本。這個版本從 Boost 1.55.0 開始可用,并取代了第一個版本。
示例 51.1。使用協(xié)程
#include <boost/coroutine/all.hpp> #include <iostream> using namespace boost::coroutines; void cooperative(coroutine<void>::push_type &sink) { std::cout << "Hello"; sink(); std::cout << "world"; } int main() { coroutine<void>::pull_type source{cooperative}; std::cout << ", "; source(); std::cout << "!\n"; }
示例 51.1 定義了一個函數(shù) cooperative(),它作為協(xié)程從 main() 調(diào)用。 cooperative() 提前返回 main() 并被第二次調(diào)用。在第二次調(diào)用時,它會從中斷處繼續(xù)。
要將 cooperative() 用作協(xié)程,使用類型 pull_type 和 push_type。這些類型由 boost::coroutines::coroutine 提供,這是一個在示例 51.1 中用 void 實例化的模板。
要使用協(xié)程,您需要 pull_type 和 push_type。其中一種類型將用于創(chuàng)建一個對象,該對象將使用您想用作協(xié)程的函數(shù)進(jìn)行初始化。另一種類型將是協(xié)程函數(shù)的第一個參數(shù)。
示例 51.1 在 main() 中創(chuàng)建了一個名為 source 的 pull_type 類型的對象。 cooperative() 傳遞給構(gòu)造函數(shù)。 push_type 用作 cooperative() 簽名中的唯一參數(shù)。
創(chuàng)建源時,傳遞給構(gòu)造函數(shù)的函數(shù) cooperative() 會立即作為協(xié)程調(diào)用。發(fā)生這種情況是因為源基于 pull_type。如果源基于 push_type,則構(gòu)造函數(shù)不會將 cooperative() 作為協(xié)程調(diào)用。
cooperative() 將 Hello 寫入標(biāo)準(zhǔn)輸出。之后,函數(shù)像訪問函數(shù)一樣訪問 sink 。這是可能的,因為 push_type 重載了 operator()。 main() 中的 source 表示協(xié)程 cooperative(),cooperative() 中的 sink 表示函數(shù) main()。調(diào)用 sink 使 cooperative() 返回,而 main() 從調(diào)用 cooperative() 的地方繼續(xù),并將逗號寫入標(biāo)準(zhǔn)輸出。
然后,main() 調(diào)用 source 就好像它是一個函數(shù)一樣。同樣,這是可能的,因為重載了 operator()。這一次,cooperative() 從中斷點繼續(xù)并將世界寫入標(biāo)準(zhǔn)輸出。因為 cooperative() 中沒有其他代碼,協(xié)程結(jié)束。它返回到 main(),它將一個感嘆號寫入標(biāo)準(zhǔn)輸出。
結(jié)果是示例 51.1 顯示 Hello, world!
您可以將協(xié)程視為協(xié)作線程。在某種程度上,函數(shù) main() 和 cooperative() 同時運行。代碼在 main() 和 cooperative() 中輪流執(zhí)行。每個函數(shù)內(nèi)的指令按順序執(zhí)行。多虧了協(xié)程,一個函數(shù)不需要在另一個函數(shù)執(zhí)行之前返回。
示例 51.2。從協(xié)程返回一個值
#include <boost/coroutine/all.hpp> #include <functional> #include <iostream> using boost::coroutines::coroutine; void cooperative(coroutine<int>::push_type &sink, int i) { int j = i; sink(++j); sink(++j); std::cout << "end\n"; } int main() { using std::placeholders::_1; coroutine<int>::pull_type source{std::bind(cooperative, _1, 0)}; std::cout << source.get() << '\n'; source(); std::cout << source.get() << '\n'; source(); }
示例 51.2 與前面的示例類似。這次模板 boost::coroutines::coroutine 是用 int 實例化的。這使得從協(xié)程返回一個 int 給調(diào)用者成為可能。
傳遞 int 值的方向取決于使用 pull_type 和 push_type 的位置。該示例使用 pull_type 在 main() 中實例化一個對象。 cooperative() 可以訪問 push_type 類型的對象。 push_type 發(fā)送一個值,pull_type 接收一個值;因此,設(shè)置了數(shù)據(jù)傳輸?shù)姆较颉?/p>
cooperative() 調(diào)用 sink,參數(shù)類型為 int。此參數(shù)是必需的,因為協(xié)程是使用數(shù)據(jù)類型 int 實例化的。通過使用由 pull_type 提供的成員函數(shù) get() 從 main() 中的 source 接收傳遞給 sink 的值。
示例 51.2 還說明了如何將具有多個參數(shù)的函數(shù)用作協(xié)程。 cooperative() 有一個額外的 int 類型參數(shù),不能直接傳遞給 pull_type 的構(gòu)造函數(shù)。該示例使用 std::bind() 將函數(shù)與 pull_type 鏈接起來。
該示例將 1 和 2 后跟 end 寫入標(biāo)準(zhǔn)輸出。
示例 51.3。將兩個值傳遞給協(xié)程
#include <boost/coroutine/all.hpp> #include <tuple> #include <string> #include <iostream> using boost::coroutines::coroutine; void cooperative(coroutine<std::tuple<int, std::string>>::pull_type &source) { auto args = source.get(); std::cout << std::get<0>(args) << " " << std::get<1>(args) << '\n'; source(); args = source.get(); std::cout << std::get<0>(args) << " " << std::get<1>(args) << '\n'; } int main() { coroutine<std::tuple<int, std::string>>::push_type sink{cooperative}; sink(std::make_tuple(0, "aaa")); sink(std::make_tuple(1, "bbb")); std::cout << "end\n"; }
示例 51.3 在 main() 中使用 push_type,在 cooperative() 中使用 pull_type,這意味著數(shù)據(jù)從調(diào)用方傳輸?shù)絽f(xié)程。
此示例說明如何傳遞多個值。 Boost.Coroutine 不支持傳遞多個值,因此必須使用元組。您需要將多個值打包到元組或其他結(jié)構(gòu)中。
示例 51.3 顯示 0 aaa、1 bbb 和 end。
示例 51.4。協(xié)程和異常
#include <boost/coroutine/all.hpp> #include <stdexcept> #include <iostream> using boost::coroutines::coroutine; void cooperative(coroutine<void>::push_type &sink) { sink(); throw std::runtime_error("error"); } int main() { coroutine<void>::pull_type source{cooperative}; try { source(); } catch (const std::runtime_error &e) { std::cerr << e.what() << '\n'; } }
協(xié)程在拋出異常時立即返回。異常被傳輸?shù)絽f(xié)程的調(diào)用者,在那里它可以被捕獲。因此,異常與常規(guī)函數(shù)調(diào)用沒有什么不同。
示例 51.4 顯示了這是如何工作的。此示例會將字符串錯誤寫入標(biāo)準(zhǔn)輸出。
到此這篇關(guān)于C++ Boost Coroutine使用協(xié)程詳解的文章就介紹到這了,更多相關(guān)C++ Boost Coroutine內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于雙向鏈表的增刪改查和排序的C++實現(xiàn)
下面小編就為大家?guī)硪黄P(guān)于雙向鏈表的增刪改查和排序的C++實現(xiàn)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-12-12C++中4種管理數(shù)據(jù)內(nèi)存的方式總結(jié)
根據(jù)用于分配內(nèi)存的方法,C++中有3中管理數(shù)據(jù)內(nèi)存的方式:自動存儲、靜態(tài)存儲和動態(tài)存儲。在存在時間的長短方面,以這三種方式分配的數(shù)據(jù)對象各不相同。下面簡要介紹這三種類型2022-09-09opencv配置的完整步驟(win10+VS2015+OpenCV3.1.0)
OpenCV是計算機(jī)視覺中經(jīng)典的專用庫,其支持多語言、跨平臺,功能強(qiáng)大,這篇文章主要給大家介紹了關(guān)于opencv配置(win10+VS2015+OpenCV3.1.0)的相關(guān)資料,需要的朋友可以參考下2021-06-06