最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++20 新特性 協(xié)程 Coroutines(2)

 更新時間:2021年10月08日 10:45:03   作者:孫孟越  
上篇文章簡單給大介紹了 C++20 特性 協(xié)程 Coroutines co_yield 和 co_return 那么這篇文章繼續(xù)給大家介紹C++20 的新特性協(xié)程 Coroutines co_await,需要的朋友可以參考一下

想了解上一篇文章內(nèi)容的小伙伴可點擊 C++20 特性 協(xié)程 Coroutines (1)

談到什么是協(xié)程. 并且介紹了 co_yield co_return 的作用. 這篇來介紹一下 co_await.

1、co_await

一個形如:

co_await awaitable

的表達式就叫一個 await-expression. co_await 表達式是用來暫停當前協(xié)程的運行, 轉(zhuǎn)而等待 awaitable 的結(jié)果. 然后 awaitable 進行計算, 最終返回一個 awaiter 結(jié)構(gòu)用來告訴 co_await 要做什么.

co_await 所在的函數(shù)塊本身就是協(xié)程, 所以這個 co_await 也得配上一個 promise 和一個 coroutine_handle. 就像上篇文章里面 generator 類之類的東西.

這個 awaitable 可以是很多東西, 首先會檢查 promise 有沒有提供 await_transform 函數(shù), 如果有就會用上, 沒有就不管.

(只要提供了任何一個 await_transform, 那么每一個 awaitable 都需要找到適合它的重載, 否則就會報錯. 庫的實現(xiàn)者可以通過 await_transform 接口來限制哪些 awaitable 可以用在協(xié)程之中. 參見https://stackoverflow.com/q/65787797/14406396 )

之后的話, 會查找 operator co_await 這個函數(shù), 預期這個 operator 返回一個 awaiter.已經(jīng)是一個 awaiter 了.

2、awaiter 的三個接口用途

一個 awaiter 需要實現(xiàn)三個接口 await_ready() , await_suspend(std::coroutine_handle<P>) , await_resume() .

只要實現(xiàn)了這三個接口的東西就是 awaiter.

await_ready() 告訴 co_await 自己好了沒.

await_suspend(h) 可以選擇返回 void , bool , std::coroutine_handle<P> 之一. h 是本協(xié)程的 handle. P是本協(xié)程的 promise 類型 (或者是 void, 見第三篇中的解釋).

如果 await_ready() 返回 false , 這個協(xié)程就會暫停. 之后:

  • 如果 await_suspend(h) 返回類型是 std::coroutine_handle<Z>, 那么就會恢復這個 handle. 即運行 await_suspend(h).resume(). 這意味著暫停本協(xié)程的時候, 可以恢復另一個協(xié)程.
  • 如果 await_suspend(h) 返回類型是 bool, 那么看 await_suspend(h) 的結(jié)果, 是 false 就恢復自己.
  • 如果 await_suspend(h) 返回類型是 void, 那么就直接執(zhí)行. 執(zhí)行完暫停本協(xié)程.

如果 await_ready() 返回 true 或者協(xié)程被恢復了, 那么就執(zhí)行 await_resume() , 它得到的結(jié)果就是最終結(jié)果.

所以說, 這await_ready, await_suspend, await_resume 三個接口分別表示 "有沒有準備好", "停不停", "好了該咋辦". 設計還是很自然的.

C++ 的協(xié)程是非對稱協(xié)程, 是有一個調(diào)用/被調(diào)用的關(guān)系的. 一個協(xié)程被某個東西喚醒了, 那么它下次暫停的時候, 就會把控制流還給那個喚醒它的東西. 所以 C++ 的協(xié)程完全可以看作是一個可重入的函數(shù).

3、協(xié)程用法的回顧

再來看上一篇文章中的偽代碼

{
promise-type promise(promise-constructor-arguments); 
try {
    co_await promise.initial_suspend(); // 創(chuàng)建之后 第一次暫停
    function-body // 函數(shù)體
} catch ( ... ) {
    if (!initial-await-resume-called)
    throw; 
    promise.unhandled_exception(); 
}

final-suspend:
co_await promise.final_suspend(); // 最后一次暫停
}

catch 塊里面出現(xiàn)的 !initial-await-resume-called 就是指 promise.initial_suspend() 返回的那個 await_resume() 有沒有被執(zhí)行過.

如果執(zhí)行了, 那么這個 flag 就會立刻變成 true. 然后調(diào)用 promise.unhandled_exception() 來處理異常.

一個例子:

由于 co_await 對這三個東西的應該做什么沒有做任何限制, 所以可以用來實現(xiàn)很多功能.

舉個例子 (來自標準庫), 比如我們想要設計一個協(xié)程, 能夠停下任意的正時長, 就可以這樣設計:

template <class Rep, class Period>
auto operator co_await(std::chrono::duration<Rep, Period> d) // operator co_await
{
    struct awaiter
    {
        std::chrono::system_clock::duration duration;
        awaiter(std::chrono::system_clock::duration d) : duration(d) {}
        bool await_ready() const { return duration.count() <= 0; }
        int await_resume() {  return 1;  }
        void await_suspend(std::coroutine_handle<> h)
        {
            std::this_thread::sleep_for(duration);
        }
    };
    return awaiterwppm3vysvbp;
}


這樣的話, 如果輸入一個正的時間, 就會調(diào)用 await_suspend() 進行暫停了. 如果輸入的時間是負的, 那就通過 await_ready() 返回 true 繞過了這個過程.

當然, 調(diào)用它需要在一個協(xié)程中, 也就意味著需要一個 promise coroutine_handle 包裝類的配合. 像這樣

struct my_future
{
    struct promise_type;
    using handle = std::coroutine_handle<promise_type>;
    struct promise_type
    {
        int current_value;
        auto initial_suspend() { return std::suspend_always{}; }
        auto final_suspend() { return std::suspend_always{}; }
        void unhandled_exception() { std::terminate(); }
        /* ... */
    };
    /* ... */
private:
    my_future(handle h) : coro(h) {}
    handle coro;
};

my_future sleep_coro()
{
    printf("Start sleeping\n");
    int ans = co_await 1s;
    printf("End sleeping, with ans = %d\n", ans);
}

當然, 一個函數(shù)也可以放在 co_await 的右邊, 就像 co_await g(); 只要返回的結(jié)構(gòu)里面有那三個 await_* 接口就行. 甚至你可以直接 co_await std::suspend_always{};

下面是協(xié)程流控的細致分析.

int main()
{
    auto h = sleep_coro(); 
// 這一步創(chuàng)建協(xié)程, 在 co_await initial_suspend 處, 執(zhí)行完 await_ready, await_suspend. 返回 main
// 注意 initial_suspend 返回的是 std::suspend_always{}
// 所以是一定暫停, 并且 resume 的時候什么都不做

    h.resume();
// 這一步執(zhí)行上一個 await_resume 以后(什么都不做), 執(zhí)行了 printf("Start sleeping\n");
// 然后收到 co_await 1s 返回的結(jié)構(gòu), 其中 await_suspend 里面需要暫停.
// 然后執(zhí)行完 await_ready, await_suspend (在這個函數(shù)里暫停 1s), 返回 main

    h.resume();
// 這一步執(zhí)行完 await_resume 以后(初始化 ans = 1)
// 執(zhí)行了 printf("End sleeping, with ans = %d\n", ans);
// 然后在 co_await final_suspend 處執(zhí)行完 await_ready, await_suspend. 就返回 main

}

示列代碼見這里

到這里大家可以重新會到(1)去看看:C++20 特性 協(xié)程 Coroutines(1)

到此這篇關(guān)于C++20 新特性 協(xié)程 Coroutines(2)的文章就介紹到這了,更多相關(guān)C++20 協(xié)程 Coroutines內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++ 再識類和對象

    C++ 再識類和對象

    類是創(chuàng)建對象的模板,一個類可以創(chuàng)建多個對象,每個對象都是類類型的一個變量;創(chuàng)建對象的過程也叫類的實例化。每個對象都是類的一個具體實例(Instance),擁有類的成員變量和成員函數(shù)
    2021-10-10
  • Qt如何自定義滑動條

    Qt如何自定義滑動條

    這篇文章主要介紹了Qt如何自定義滑動條問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • C語言利用結(jié)構(gòu)體數(shù)組實現(xiàn)學生成績管理系統(tǒng)

    C語言利用結(jié)構(gòu)體數(shù)組實現(xiàn)學生成績管理系統(tǒng)

    這篇文章主要為大家詳細介紹了C語言利用結(jié)構(gòu)體數(shù)組實現(xiàn)學生成績管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • 基于Matlab制作偽3D第一視角迷宮小游戲

    基于Matlab制作偽3D第一視角迷宮小游戲

    這篇文章主要為大家詳細介紹了如何利用Matlab語言制作偽3D第一視角迷宮小游戲,文中的示例代碼講解詳細,感興趣的小伙伴可以動手嘗試一下
    2022-07-07
  • C語言使用廣度優(yōu)先搜索算法解決迷宮問題(隊列)

    C語言使用廣度優(yōu)先搜索算法解決迷宮問題(隊列)

    這篇文章主要介紹了C語言使用廣度優(yōu)先搜索算法解決迷宮問題,結(jié)合迷宮問題分析了C語言隊列廣度優(yōu)先搜索算法的相關(guān)使用技巧,需要的朋友可以參考下
    2017-09-09
  • C++如何向Lambda傳遞參數(shù)與捕獲

    C++如何向Lambda傳遞參數(shù)與捕獲

    文章介紹了C++中向Lambda表達式傳遞參數(shù)和使用捕獲列表的基本規(guī)則和示例,參數(shù)傳遞要求嚴格匹配類型和數(shù)量,而捕獲列表允許Lambda訪問外部變量,并可以按值或引用捕獲,文章還討論了捕獲的陷阱和解決方案,以及參數(shù)傳遞與捕獲列表的區(qū)別和應用場景,感興趣的朋友一起看看吧
    2025-03-03
  • C++連接mysql數(shù)據(jù)庫(改進版)

    C++連接mysql數(shù)據(jù)庫(改進版)

    C++是大家都非常熟悉的,也是大家平時辦公中經(jīng)常會用到的,下面這篇文章主要給大家介紹了關(guān)于C++連接mysql數(shù)據(jù)庫的相關(guān)資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2023-12-12
  • C++迭代器失效解決辦法詳解

    C++迭代器失效解決辦法詳解

    這篇文章主要介紹了迭代器失效的概念,以及在vector、list和map等容器中插入和刪除操作導致迭代器失效的情況,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-12-12
  • C語言控制臺應用程序GDI繪制正弦曲線

    C語言控制臺應用程序GDI繪制正弦曲線

    這篇文章主要為大家詳細介紹了C語言控制臺應用程序GDI繪制正弦曲線,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-06-06
  • C++的智能指針你真的了解嗎

    C++的智能指針你真的了解嗎

    這篇文章主要為大家詳細介紹了C++的智能指針,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03

最新評論

泰兴市| 阳春市| 双牌县| 庆阳市| 大连市| 岱山县| 沈阳市| 柘荣县| 福鼎市| 突泉县| 英吉沙县| 桐城市| 舟山市| 于田县| 铜梁县| 鄄城县| 本溪| 和田县| 葫芦岛市| 资讯 | 宜良县| 莒南县| 汉中市| 天台县| 福安市| 洞口县| 临泽县| 苏尼特左旗| 张家川| 敦化市| 枞阳县| 海城市| 体育| 龙游县| 长岛县| 桂平市| 运城市| 牙克石市| 内乡县| 寿宁县| 邯郸县|