亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

蟲蟲首頁| 資源下載| 資源專輯| 精品軟件
登錄| 注冊

您現在的位置是:首頁 > 技術閱讀 >  如何編寫 C++ 20 協程(Coroutines)

如何編寫 C++ 20 協程(Coroutines)

時間:2024-02-13

喵哥技術交流群發現了很多水平很高的朋友,歡迎大家來加喵哥微信,進群一起討論計算機知識!

程序喵大人微信


C++20 帶著 Coroutines 來了!

花了一兩周的時間后,我想寫寫 C++20 協程的基本用法,因為 C++ 的協程讓我感到很奇怪,寫一個協程程序十分費勁。讓我們拋去復雜的東西,來看看寫一個 C++ 協程需要哪些東西。

編譯器支持

由于 C++ 20 還沒被所有編譯器完全支持,首先需要確保你的編譯器實現了 Coroutines,可以通過下面的網站查看編譯器支持情況:https://en.cppreference.com/w/cpp/compiler_support#cpp20

值得一提,我使用的 MacOS 自帶的 Apple Clang 對 C++20 支持很弱,我選擇通過 Homebrew 安裝最新版的 GNU GCC (10 以上版本)來編譯。

我使用的 GNU GCC 10.2 版本編譯指令:

g++ -fcoroutines -std=c++20

Clang 支持不夠好,不推薦使用。Clang 可以使用如下命令編譯:

clang++ -std=c++20 -stdlib=libc++ -fcoroutines-ts

不推薦 Clang 還有一個理由:使用 Clang 需要 include 頭文件 <experimental/coroutine> 而不是 <coroutine>。此外,一些類型被命名為 std::experimental:xxx 而不是 std:xxx

以下示例代碼只支持 GNU GCC 版本的編譯器。

C++ 協程簡介

在正式開始之前,我們先要理解 C++20 中協程使用的一些術語。

首先,什么是協程?

協程就是一個可以掛起(suspend)恢復(resume)的函數(但無論如何不能是 main 函數)。你可以暫停協程的執行,去做其他事情,然后在適當的時候恢復到暫停的位置繼續執行。協程讓我們使用同步方式寫異步代碼

怎么掛起協程呢?C++ 提供了三個方法:co_awaitco_yield 和 co_return

順便說一句:coroutine 不是并行(parallelism),和 Go 語言的 goroutine 不一樣!

與你之前接觸到的協程完全不同,一個 C++ 協程一般長這樣:

這奇怪的協程代碼涉及了 C++ 協程很重要的三個概念:

  • promise_type

  • Awaitable

  • std::coroutine_handle<>

在寫 C++20 的協程之前,我們必須需要先了解三個概念,可以用這三張圖來形容這三個概念:

圖來源: https://www.youtube.com/watch?v=vzC2iRfO_H8

Promise

C++ 協程的返回類型必須是 promise_typepromise_type 是一個 interface,你可以用它來控制協程,在協程的生命周期中注入自定義行為:

  • get_return_object:控制協程的返回對象

  • initial_suspend:在協程開始的時候掛起

  • final_suspend:在協程結束的時候掛起

協程的生命周期如下,用戶自定義的函數 <function-body> 被包裹在下面的偽代碼中(來源:http://eel.is/c++draft/dcl.fct.def.coroutine#5):

可以看到,initial_suspend 會在進入協程(也就是函數)之前執行,final_suspend 會在協程返回之前執行。

如果 final_suspend 真的掛起了協程,那么作為協程的調用者,你需要手動的調用 destroy 來釋放協程;如果 final_suspend 沒有掛起協程,那么協程將自動銷毀。先記住這句話,在后面還會提到。

除此之外,Promise 還有一些其它責任:

  • return_void()/return_value()/yield_value() 方法: 用來控制 co_return 和 co_yield的行為;

  • unhandled_exception() 處理異常

  • 創建和銷毀協程的 stackframe

  • 處理 stackframe 創建可能發生的異常

stackframe :函數運行時占用的內存空間,是棧上的數據集合,它包括:

  • Local variables

  • Saved copies of registers modified by subprograms that could need restoration

  • Argument parameters

  • Return address

Awaitable

第二個概念是 AwaitableAwaitable 負責管理協程掛起時的行為。

一個 Awaitable 對象可以成為 co_await 調用的對象。Awaitable 擁有以下方法:

  • await_ready():是否要掛起,如果返回 true,那么 co_await 就不會掛起函數;

  • await_resume()co_await 的返回值,通常返回空; 

  • await_suspend():協程掛起時的行為;

可以在 await_suspend 中實現 await_ready 的效果,例如直接不掛起當前的協程,但在調用 await_suspend 之前,編譯器必須將所有狀態捆綁到協程的 stackframe 中,這會更耗時。

有時候我們的協程并不需要自定義復雜的行為,C++ 提供了兩個默認的 Awaitable

suspend_always::await_ready() 總是返回 false,而 suspend_always::await_ready() 總是返回 true。其他的方法都是空的,沒有任何作用。

如果沒有其它多余的行為,我們可以在函數中直接調用 co_await std::suspend_always{} 來掛起一個函數。

Coroutine Handle

co_await 掛起函數,并創建了一個可調用對象,這個對象可以用來恢復Hanns乎的執行。這個可調用對象的類型就是 std::coroutine_handle<>,最常用的兩個方法是:

  • handle.resume():恢復協程的執行;

  • handle.destroy():銷毀協程;

Coroutine Handle 很像指針,我們可以復制它,但析構函數不會釋放相關狀態的內存。為了避免內存泄漏,一般要調用 handle.destroy() 來釋放(盡管在某些情況下,協程會在完成后自行銷毀——前文有提到)。同樣像指針一樣,一旦銷毀了一個 Coroutine Handle ,指向同一個協程的另一個 Coroutine Handle 將指向垃圾,并在調用時表現出未定義行為。

學習更復雜的用法之前,我們先看下示例。

示例

這個簡短的示例展示了 C++ 實現協程 "Hello world" 程序。我們執行完 "Hello " 后掛起函數,又在執行 handle.resume() 后恢復函數的運行。

非常簡單,不再過多解釋。

co_yield

C++ 協程與一個 Promise 交互之所以如此笨拙,有一個特殊原因就是為了 co_yield

如果 promise 是當前協程的 Promise 對象,那么執行:

co_yield <expression>;

相當于執行了:

co_await promise.yield_value(<expression>);

所以,需要在 promise_type 中添加一個 yield_value 方法。上面的例子可以改為:

可以用 co_yield 實現 Python 中的生成器,參考:https://lewissbaker.github.io/2018/09/05/understanding-the-promise-type

co_return

執行 co_return 語句時:

co_return <expression>;

相當于執行了:

co_return promise.return_value(<expression>); goto end;

下面再給出示例加上 co_return 的版本:

復雜一些

到此, Awaitable 和 Coroutine Handle 好像還沒有發揮什么作用,我寫的示例程序都非常簡單。

如果我們想在協程掛起的時候,做更多的動作,一般將 Coroutine Handle 傳到 Awaitable 的 await_suspend() 中,用一個官網的例子展示一下:

小結

本文簡單介紹了 C++ 協程,希望下次你寫 C++ 協程的時候,首先想到這三個東西:

我本人也不是編程語言專家,對于 C++ 協程總覺得有些繁瑣、怪異,或許是我并不清楚 C++ 在原有情況下支持協程的困難,但我依然覺得 C++ 團隊可以做得更好。

我還需要花時間弄明白到底該如何在項目中使用這臃腫的協程。

不過,可以預見到的是,我們會在越來越多的 C++ 項目中看到協程的身影。比如 facebook folly 就已經實現了一個實驗階段的協程框架: https://github.com/facebook/folly/tree/master/folly/experimental/coro

也許等我再研究一段時間,會寫一篇到底該如何使用 C++ 協程。

Reference

  • C++ Coroutine definitions: http://eel.is/c++draft/dcl.fct.def.coroutine#5

  • C++ draft expr.await: http://eel.is/c++draft/expr.await

  • C++ Coroutines: Understanding the promise type: https://lewissbaker.github.io/2018/09/05/understanding-the-promise-type

  • 官網的例子:https://en.cppreference.com/w/cpp/language/coroutines

  • My tutorial and take on C++20 coroutines:https://www.scs.stanford.edu/~dm/blog/c++-coroutines.html#coroutine-handles

往期推薦


1、少寫點
if-else吧,它的效率有多低你知道嗎?
2、年度原創好文匯總
3、深度好文|面試官:進程和線程,我只問這19個問題
4
他來了,他來了,C+
+17新特性精華都在這了
5一文讓你搞懂設計模式
6、C++11新特性,所有知識點都在這了!





C++學習資料免費獲取方法:關注程序喵大人,后臺回復“程序喵”即可免費獲取40萬字C++進階獨家學習資料。


亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
国产精品无码永久免费888| 亚洲天堂网在线观看| 亚洲欧美亚洲| 亚洲精一区二区三区| 国产深夜精品福利| 国产精品欧美经典| 欧美性开放视频| 欧美日韩爆操| 欧美黄色视屏| 欧美黄在线观看| 欧美激情一区在线| 欧美国产一区二区在线观看| 玖玖视频精品| 老牛影视一区二区三区| 久久五月婷婷丁香社区| 久久综合伊人77777麻豆| 久久久免费精品视频| 久久久亚洲精品一区二区三区 | 99精品久久久| 最新日韩在线| 日韩亚洲欧美一区二区三区| 中国成人亚色综合网站| 亚洲午夜精品久久| 欧美一级视频免费在线观看| 久久久久久久一区二区三区| 免费人成精品欧美精品| 欧美日韩视频在线第一区| 国产精品久久精品日日| 国产日韩欧美精品| 一区二区在线看| 日韩午夜av在线| 久久久99免费视频| 久久综合色播五月| 欧美日韩亚洲一区在线观看| 国产精品一二| 亚洲电影观看| 亚洲最新视频在线| 欧美影院在线| 欧美成人午夜免费视在线看片| 欧美日韩不卡一区| 国产一区二区三区观看| 亚洲三级视频在线观看| 欧美一区二区三区免费看| 欧美成人精精品一区二区频| 欧美系列亚洲系列| 亚洲电影免费观看高清| 亚洲天堂免费观看| 久久综合久色欧美综合狠狠 | 亚洲免费高清| 久久www免费人成看片高清| 欧美大片一区二区| 国产欧美视频一区二区三区| 亚洲激情综合| 久久国产精品久久久久久久久久| 欧美高清自拍一区| 国产在线不卡精品| 在线中文字幕不卡| 欧美xxx成人| 亚洲欧美日韩一区在线| 玖玖视频精品| 国产视频一区在线观看一区免费| 日韩视频久久| 欧美福利小视频| 黄色av日韩| 羞羞答答国产精品www一本| 欧美日韩精品综合| 亚洲电影免费在线| 午夜电影亚洲| 国产精品久久| 夜夜精品视频| 欧美精品一二三| 亚洲大胆美女视频| 久久国产精品一区二区三区| 国产精品日韩电影| 中文在线资源观看网站视频免费不卡 | 欧美在线啊v一区| 欧美日韩亚洲一区二区三区在线 | 亚洲人成绝费网站色www| 欧美一级免费视频| 国产精品福利在线观看| 99精品国产高清一区二区| 欧美大色视频| 最新热久久免费视频| 久久亚洲国产精品一区二区| 国产日韩欧美一区二区三区四区| 夜夜嗨一区二区| 欧美日韩不卡一区| 日韩网站免费观看| 欧美激情一区二区三区在线视频 | 午夜国产精品视频免费体验区| 欧美日韩p片| 一区二区三区产品免费精品久久75 | 影音先锋日韩精品| 欧美专区日韩视频| 国产一区二区三区四区hd| 欧美在线观看日本一区| 国产综合色产在线精品| 久久精品一区二区三区四区 | 91久久在线视频| 免费久久精品视频| 亚洲美洲欧洲综合国产一区| 欧美日韩成人综合在线一区二区| 一区二区日韩| 国产婷婷一区二区| 久久亚洲欧美| 亚洲精品一区二区在线| 欧美日韩一区二区三区在线| 亚洲少妇最新在线视频| 国产精品亚洲激情| 久久亚洲免费| 日韩亚洲欧美成人一区| 国产精品日韩久久久久| 久久久之久亚州精品露出| 亚洲国内欧美| 国产精品高潮呻吟久久av黑人| 亚洲免费视频中文字幕| 韩国一区二区三区在线观看| 女仆av观看一区| 一区二区三区免费观看| 国产日韩欧美视频在线| 欧美成人精品1314www| 一区二区三区四区五区精品视频| 国产精品国产三级国产aⅴ9色| 久久国产精品黑丝| 亚洲电影视频在线| 国产精品高潮久久| 久久综合久久美利坚合众国| 亚洲一卡久久| 亚洲国产精品传媒在线观看| 国产精品久久久久久一区二区三区| 久久不见久久见免费视频1| 亚洲精品一区二区三区樱花| 国产日韩欧美亚洲一区| 欧美日产国产成人免费图片| 久久国产视频网站| 亚洲午夜羞羞片| 亚洲国产综合在线看不卡| 国产精品乱码久久久久久| 另类亚洲自拍| 午夜亚洲福利在线老司机| 亚洲激情第一区| 国内精品福利| 国产精品久久久久久av福利软件 | 国产精品视频精品| 蜜臀99久久精品久久久久久软件| 亚洲天堂男人| 亚洲精选大片| 亚洲第一中文字幕| 国产欧美日韩专区发布| 欧美日韩一区精品| 欧美激情一区二区三区蜜桃视频 | 美女露胸一区二区三区| 欧美亚洲一区二区在线观看| 一区二区日本视频| 亚洲欧洲一区二区在线观看 | 欧美午夜电影在线| 欧美成人精品激情在线观看| 久久精品国产亚洲a| 亚洲一二区在线| 日韩视频―中文字幕| 亚洲大片精品永久免费| 国产一区二区按摩在线观看| 欧美性片在线观看| 国产精品theporn88| 欧美欧美全黄| 欧美日韩国产成人高清视频| 蜜臀久久99精品久久久久久9 | 欧美日韩裸体免费视频| 麻豆精品一区二区av白丝在线| 久久久国产一区二区三区| 久久久久久久网| 久久综合国产精品| 久久视频在线免费观看| 久久一区激情| 蜜桃av噜噜一区| 欧美大秀在线观看| 欧美国产日韩一区二区| 欧美精品在线一区| 欧美日韩综合| 国产精品高潮在线| 国产视频久久| 精品不卡在线| 91久久精品国产91久久性色| 日韩小视频在线观看专区| 在线视频一区二区| 亚洲欧美综合v| 久久成人免费视频| 毛片精品免费在线观看| 欧美1区视频| 欧美日韩国产精品一区二区亚洲| 欧美人成在线视频| 亚洲国产二区| 日韩视频中文| 亚洲欧美一区二区三区久久| 久久精品人人做人人综合| 美女脱光内衣内裤视频久久网站| 欧美成人精品一区二区| 欧美日韩视频在线一区二区 | 亚洲成人中文| 亚洲精品一区二区三区99|