色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

關于C++ 20協程最全面詳解

Linux愛好者 ? 來源:Tangwz ? 作者:計算機科學 ? 2021-04-12 11:10 ? 次閱讀

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:xxx 而不是 std:xxx。

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

C++ 協程簡介

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

首先,什么是協程?

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

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

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

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

0511f8d4-9b2f-11eb-8b86-12bb97331649.png

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

promise_type

Awaitable

std::coroutine_handle《》

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

Promise

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

get_return_object:控制協程的返回對象

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

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

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

061ed03a-9b2f-11eb-8b86-12bb97331649.png

可以看到,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

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

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

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

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

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

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

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

066f0cee-9b2f-11eb-8b86-12bb97331649.png

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 將指向垃圾,并在調用時表現出未定義行為。

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

示例

0685f77e-9b2f-11eb-8b86-12bb97331649.png

這個簡短的示例展示了 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 方法。上面的例子可以改為:

069b7752-9b2f-11eb-8b86-12bb97331649.png

可以用 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 的版本:

06dfe96e-9b2f-11eb-8b86-12bb97331649.png

復雜一些

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

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

073746dc-9b2f-11eb-8b86-12bb97331649.png

小結

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

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

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

不過,可以預見到的是,我們會在越來越多的 C++ 項目中看到協程的身影。比如 facebook folly 就已經實現了一個實驗階段的協程框架
編輯:lyn

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • C++
    C++
    +關注

    關注

    22

    文章

    2112

    瀏覽量

    73717
  • 代碼
    +關注

    關注

    30

    文章

    4803

    瀏覽量

    68752
  • 編譯器
    +關注

    關注

    1

    文章

    1636

    瀏覽量

    49173

原文標題:如何編寫 C++ 20 協程(Coroutines)

文章出處:【微信號:LinuxHub,微信公眾號:Linux愛好者】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    國產舜銘存儲SF25C20對標MB85RS2MT性能、優勢全面解析

    國產舜銘存儲SF25C20對標MB85RS2MT性能、優勢全面解析
    的頭像 發表于 01-06 10:20 ?64次閱讀
    國產舜銘存儲SF25<b class='flag-5'>C20</b>對標MB85RS2MT性能、優勢<b class='flag-5'>全面</b>解析

    HighTec C/C++編譯器套件全面支持芯來RISC-V IP

    德國薩爾布呂肯,2024年12月5日——世界領先的汽車C/C++編譯器解決方案提供商HighTec EDV Systeme GmbH宣布全面支持芯來科技的RISC-V IP。HighTec編譯器
    的頭像 發表于 12-23 09:04 ?221次閱讀
    HighTec <b class='flag-5'>C</b>/<b class='flag-5'>C++</b>編譯器套件<b class='flag-5'>全面</b>支持芯來RISC-V IP

    C語言和C++中結構體的區別

    同樣是結構體,看看在C語言和C++中有什么區別?
    的頭像 發表于 10-30 15:11 ?286次閱讀

    C7000優化C/C++編譯器

    電子發燒友網站提供《C7000優化C/C++編譯器.pdf》資料免費下載
    發表于 10-30 09:45 ?0次下載
    <b class='flag-5'>C</b>7000優化<b class='flag-5'>C</b>/<b class='flag-5'>C++</b>編譯器

    使用TMS320C6416處理器:Turbo處理器(TCP)

    電子發燒友網站提供《使用TMS320C6416處理器:Turbo處理器(TCP).pdf》資料免費下載
    發表于 10-23 10:16 ?0次下載
    使用TMS320<b class='flag-5'>C</b>6416<b class='flag-5'>協</b>處理器:Turbo<b class='flag-5'>協</b>處理器(TCP)

    使用TMS320C6416處理器:Viterbi處理器(VCP)

    電子發燒友網站提供《使用TMS320C6416處理器:Viterbi處理器(VCP).pdf》資料免費下載
    發表于 10-21 09:36 ?0次下載
    使用TMS320<b class='flag-5'>C</b>6416<b class='flag-5'>協</b>處理器:Viterbi<b class='flag-5'>協</b>處理器(VCP)

    OpenVINO2024 C++推理使用技巧

    很多人都使用OpenVINO新版的C++ 或者Python的SDK,都覺得非常好用,OpenVINO2022之后的版本C++ SDK做了大量的優化與整理,已經是非常貼近開發的使用習慣與推理方式。與OpenCV的Mat對象對接方式更是幾乎無縫對接,非常的方便好用。
    的頭像 發表于 07-26 09:20 ?994次閱讀

    C++語言基礎知識

    電子發燒友網站提供《C++語言基礎知識.pdf》資料免費下載
    發表于 07-19 10:58 ?7次下載

    C++中實現類似instanceof的方法

    C++有多態與繼承,但是很多人開始學習C++,有時候會面臨一個常見問題,就是如何向下轉型,特別是不知道具體類型的時候,這個時候就希望C++ 可以向Java或者Python中有instanceof這個
    的頭像 發表于 07-18 10:16 ?613次閱讀
    <b class='flag-5'>C++</b>中實現類似instanceof的方法

    鴻蒙OS開發實例:【Native C++

    使用DevEco Studio創建一個Native C++應用。應用采用Native C++模板,實現使用NAPI調用C標準庫的功能。使用C標準庫hypot接口計算兩個給定數平方和的平
    的頭像 發表于 04-14 11:43 ?2681次閱讀
    鴻蒙OS開發實例:【Native <b class='flag-5'>C++</b>】

    使用 MISRA C++:2023? 避免基于范圍的 for 循環中的錯誤

    在前兩篇博客中,我們?向您介紹了新的 MISRA C++ 標準?和?C++ 的歷史?。在這篇博客中,我們將仔細研究以 C++ 中?for?循環為中心的特定規則。
    的頭像 發表于 03-28 13:53 ?822次閱讀
    使用 MISRA <b class='flag-5'>C++</b>:2023? 避免基于范圍的 for 循環中的錯誤

    c語言,c++,java,python區別

    C語言、C++、Java和Python是四種常見的編程語言,各有優點和特點。 C語言: C語言是一種面向過程的編程語言。它具有底層的特性,能夠對計算機硬件進行直接操作。
    的頭像 發表于 02-05 14:11 ?2460次閱讀

    vb語言和c++語言的區別

    VB語言和C++語言是兩種不同的編程語言,雖然它們都屬于高級編程語言,但在設計和用途上有很多區別。下面將詳細比較VB語言和C++語言的區別。 設計目標: VB語言(Visual Basic)是由
    的頭像 發表于 02-01 10:20 ?2387次閱讀

    談談的那些事兒

    隨著異步編程的發展以及各種并發框架的普及,作為一種異步編程規范在各類語言中地位逐步提高。我們不單單會在自己的程序中使用,各類框架如fastapi,aiohttp等也都是基于異步
    的頭像 發表于 01-26 11:36 ?1124次閱讀
    談談<b class='flag-5'>協</b><b class='flag-5'>程</b>的那些事兒

    C++簡史:C++是如何開始的

    MISRA C++:2023,MISRA? C++ 標準的下一個版本,來了!為了幫助您做好準備,我們介紹了 Perforce 首席技術支持工程師 Frank van den Beuken 博士撰寫
    的頭像 發表于 01-11 09:00 ?622次閱讀
    <b class='flag-5'>C++</b>簡史:<b class='flag-5'>C++</b>是如何開始的
    主站蜘蛛池模板: 野花视频在线观看免费| 丰满五十六十老熟女HD60| 国产亚洲精品黑人粗大精选| 性色AV乱码一区二区三区视频| 国产成人无码区免费内射一片色欲 | 久久成人免费观看草草影院| 91亚洲精品| 十分钟免费观看高清视频大全| 国产一区二区在线观看免费| 伊人久久网站| 日本午夜视频在线| 精品含羞草免费视频观看| 99E久热只有精品8在线直播| 受被三个攻各种道具PLAY| 久cao在线香蕉| 超碰免费视频部落格| 亚洲高清在线精品一区| 免费观看的毛片| 国产人妻麻豆蜜桃色在线| 97超碰射射射| 迅雷成人论坛| 欧美高清 videos sexo| 果冻传媒2021一二三区| OLDMAN老头456 TUBE| 亚洲国产成人爱AV在线播放丿| 免费A级毛片无码鲁大师| 国产精品AV色欲蜜臀在线| 中文字幕成人免费高清在线| 视频一区亚洲视频无码| 久久青草影院| 国产亚洲精品精品国产亚洲综合| a国产成人免费视频| 一本之道高清在线3线观看| 日韩成人黄色| 美女裸露100%奶头视频| 韩国hd高清xxx| 国产不卡在线观看视频| 538prom精品视频我们不只是| 亚洲国产精品嫩草影院| 日韩少妇爆乳无码专区| 美国特级成人毛片|