欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++通信新特性協(xié)程詳細(xì)介紹

 更新時(shí)間:2022年10月31日 10:32:23   作者:無(wú)水先生  
這篇文章主要給大家分享得是C++的特性協(xié)程Coroutine,下面文章內(nèi)容我們將來(lái)具體介紹什么是協(xié)程,協(xié)程得好處等知識(shí)點(diǎn),需要的朋友可以參考一下

一、關(guān)于協(xié)程

從 1.54.0 版本開始,Boost.Asio 支持協(xié)程。雖然您可以直接使用 Boost.Coroutine,但 Boost.Asio 中對(duì)協(xié)程的顯式支持使得使用它們變得更加容易。

協(xié)程讓您創(chuàng)建一個(gè)反映實(shí)際程序邏輯的結(jié)構(gòu)。異步操作不會(huì)拆分函數(shù),因?yàn)闆]有處理程序來(lái)定義異步操作完成時(shí)應(yīng)該發(fā)生什么。程序可以使用順序結(jié)構(gòu),而不是讓處理程序相互調(diào)用。

二、協(xié)程的好處

考慮多任務(wù)協(xié)作的場(chǎng)景. 如果是線程的并發(fā), 那么大家需要搶 CPU 用, 還需要條件變量/信號(hào)量或者上鎖等技術(shù), 來(lái)確保正確的線程正在工作.

如果在協(xié)程中, 大家就可以主動(dòng)暫停自己, 多個(gè)任務(wù)互相協(xié)作. 這樣可能就比大家一起搶 CPU 更高效一點(diǎn), 因?yàn)槟隳軌蚩刂颇膫€(gè)協(xié)程用上 CPU.

一個(gè)例子:

生產(chǎn)者/消費(fèi)者模型: 生產(chǎn)者生產(chǎn)完畢后, 暫停自己, 把控制流還給消費(fèi)者. 消費(fèi)者消費(fèi)完畢后, resume 生產(chǎn)者, 生產(chǎn)者繼續(xù)生產(chǎn). 這樣循環(huán)往復(fù).

異步調(diào)用: 比如你要請(qǐng)求網(wǎng)絡(luò)上的一個(gè)資源.

  • 發(fā)請(qǐng)求給協(xié)程
  • 協(xié)程收到請(qǐng)求以后, 發(fā)出請(qǐng)求. 協(xié)程暫停自己, 把控制權(quán)還回去.
  • 你繼續(xù)做些別的事情. 比如發(fā)出下一個(gè)請(qǐng)求. 或者做一些計(jì)算.
  • 恢復(fù)這個(gè)協(xié)程, 拿到資源 (可能還要再等一等)

理想狀態(tài)下, 4 可以直接用上資源, 這樣就完全不浪費(fèi)時(shí)間.

如果是同步的話:

  • 發(fā)請(qǐng)求給函數(shù).
  • 函數(shù)收到請(qǐng)求以后, 等資源.
  • 等了很久, 資源到了, 把控制權(quán)還回去.

明顯需要多等待一會(huì)兒. 如果需要發(fā)送上百個(gè)請(qǐng)求, 那顯然是第一種異步調(diào)用快一點(diǎn). (等待的過(guò)程中可以發(fā)送新的請(qǐng)求)

如果沒有協(xié)程的話, 解決方案之一是使用多線程. 像這樣:

  • 發(fā)請(qǐng)求給函數(shù).
  • 函數(shù)在另外的線程等, 不阻塞你的線程.
  • 你繼續(xù)做些別的事情. 比如發(fā)出下一個(gè)請(qǐng)求. 或者做一些計(jì)算.
  • 等到終于等到了, 他再想一些辦法通知你.

然后通知的辦法就有 promise 和回調(diào)這些辦法.

三、協(xié)程得用法

我們照著 C++20 標(biāo)準(zhǔn)來(lái)看看怎么用協(xié)程. 用 g++, 版本 10.2 進(jìn)行測(cè)試.

目前 C++20 標(biāo)準(zhǔn)只加入了協(xié)程的基本功能, 還沒有直接能上手用的類. GCC 說(shuō)會(huì)盡量與 clang MSVC 保持協(xié)程的 ABI 兼容, 同時(shí)和 libc++ 等保持庫(kù)的兼容. 所以本文可能也適用于它們.

協(xié)程和主程序之間通過(guò) promise 進(jìn)行通信. promise 可以理解成一個(gè)管道, 協(xié)程和其調(diào)用方都能看得到.

以前的 std::async std::future 也是基于一種特殊的 promise 進(jìn)行通信的, 就是 std::promise. 如果要使用協(xié)程, 則需要自己實(shí)現(xiàn)一個(gè)全新的 promise 類, 原理上是類似的.

四、與線程的區(qū)別

線程處于進(jìn)程之中,協(xié)程處于線程之中,線程有系統(tǒng)內(nèi)核調(diào)度,而協(xié)程有程序員自己調(diào)度。一個(gè)線程可以有多個(gè)協(xié)程,而且只要內(nèi)存足夠,一個(gè)線程中可以有任意多個(gè)協(xié)程;但某一時(shí)刻只能有一個(gè)協(xié)程在運(yùn)行,多個(gè)協(xié)程分享該線程分配到的計(jì)算機(jī)資源。協(xié)程是追求極限性能和優(yōu)美的代碼結(jié)構(gòu)的產(chǎn)物。

使用過(guò)程中需要包含#include <boost/coroutine2/all.hpp>,鏈接動(dòng)態(tài)庫(kù):-lboost_coroutine -lboost_context。關(guān)于使用boost庫(kù)錯(cuò)

協(xié)程有如下特點(diǎn):

  1. 同其他數(shù)據(jù)類型一樣,協(xié)程也是第一類(first-class)對(duì)象,可以被當(dāng)參數(shù)傳遞等操作;
  2. 運(yùn)行特點(diǎn)是掛起運(yùn)行,離開協(xié)程,過(guò)后再進(jìn)入,恢復(fù)運(yùn)行;
  3. 具有對(duì)稱和非對(duì)稱的轉(zhuǎn)移控制機(jī)制;
  4. 掛起前和恢復(fù)后本地變量的值是一致的;
  5. 有stackless和stackful兩種類型

五、協(xié)程示例

示例 32.7。使用 Boost.Asio 的協(xié)程

#include <boost/asio/io_service.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/asio/write.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <list>
#include <string>
#include <ctime>
using namespace boost::asio;
using namespace boost::asio::ip;
io_service ioservice;
tcp::endpoint tcp_endpoint{tcp::v4(), 2014};
tcp::acceptor tcp_acceptor{ioservice, tcp_endpoint};
std::list<tcp::socket> tcp_sockets;
void do_write(tcp::socket &tcp_socket, yield_context yield)
{
  std::time_t now = std::time(nullptr);
  std::string data = std::ctime(&now);
  async_write(tcp_socket, buffer(data), yield);
  tcp_socket.shutdown(tcp::socket::shutdown_send);
}
void do_accept(yield_context yield)
{
  for (int i = 0; i < 2; ++i)
  {
    tcp_sockets.emplace_back(ioservice);
    tcp_acceptor.async_accept(tcp_sockets.back(), yield);
    spawn(ioservice, [](yield_context yield)
      { do_write(tcp_sockets.back(), yield); });
  }
}
int main()
{
  tcp_acceptor.listen();
  spawn(ioservice, do_accept);
  ioservice.run();
}

調(diào)用 Boost.Asio 使用協(xié)程的函數(shù)是 boost::asio::spawn()。傳遞的第一個(gè)參數(shù)必須是 I/O 服務(wù)對(duì)象。第二個(gè)參數(shù)是將成為協(xié)程的函數(shù)。此函數(shù)必須接受 boost::asio::yield_context 類型的對(duì)象作為其唯一參數(shù)。它必須沒有返回值。示例 32.7 使用 do_accept() 和 do_write() 作為協(xié)程。如果函數(shù)簽名不同,例如 do_write() 的情況,您必須使用類似 std::bind 的適配器或 lambda 函數(shù)。

您可以將 boost::asio::yield_context 類型的對(duì)象而不是處理程序傳遞給異步函數(shù)。 do_accept() 將參數(shù) yield 傳遞給 async_accept()。在 do_write() 中,yield 被傳遞給 async_write()。這些函數(shù)調(diào)用仍會(huì)啟動(dòng)異步操作,但在操作完成時(shí)不會(huì)調(diào)用任何處理程序。而是恢復(fù)啟動(dòng)異步操作的上下文。當(dāng)這些異步操作完成時(shí),程序會(huì)從中斷的地方繼續(xù)。

do_accept() 包含一個(gè) for 循環(huán)。每次調(diào)用該函數(shù)時(shí),都會(huì)將一個(gè)新套接字傳遞給 async_accept()。一旦客戶端建立連接,do_write() 將作為協(xié)程調(diào)用,并帶有 boost::asio::spawn() 以將當(dāng)前時(shí)間發(fā)送給客戶端。

for 循環(huán)可以很容易地看出程序在退出之前可以為兩個(gè)客戶端提供服務(wù)。由于該示例基于協(xié)程,因此可以在 for 循環(huán)中實(shí)現(xiàn)異步操作的重復(fù)執(zhí)行。這提高了程序的可讀性,因?yàn)槟槐馗檶?duì)處理程序的潛在調(diào)用來(lái)找出最后一個(gè)異步操作何時(shí)完成。如果時(shí)間服務(wù)器需要支持兩個(gè)以上的客戶端,則只需調(diào)整 for 循環(huán)。

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

相關(guān)文章

  • C語(yǔ)言的冒泡排序和快速排序算法使用實(shí)例

    C語(yǔ)言的冒泡排序和快速排序算法使用實(shí)例

    這篇文章主要介紹了C語(yǔ)言的冒泡排序和快速排序算法使用實(shí)例,示例題目也是ACM練習(xí)當(dāng)中的基礎(chǔ)習(xí)題,需要的朋友可以參考下
    2015-08-08
  • 深入理解c++指針的指針和指針的引用

    深入理解c++指針的指針和指針的引用

    下面小編就為大家?guī)?lái)一篇深入理解c++指針的指針和指針的引用。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧
    2016-06-06
  • 使用emacs編寫C語(yǔ)言教程

    使用emacs編寫C語(yǔ)言教程

    這篇文章主要介紹了使用emacs編寫C語(yǔ)言教程,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • C語(yǔ)言中數(shù)組常用的一些排序算法小結(jié)

    C語(yǔ)言中數(shù)組常用的一些排序算法小結(jié)

    數(shù)組的排序方法有很多,效率也各不相同,下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言中數(shù)組常用的一些排序算法的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-01-01
  • C語(yǔ)言實(shí)例講解四大循環(huán)語(yǔ)句的使用

    C語(yǔ)言實(shí)例講解四大循環(huán)語(yǔ)句的使用

    C語(yǔ)言有四大循環(huán)語(yǔ)句,他們之間可以進(jìn)行任意轉(zhuǎn)換。本文將首先對(duì)其語(yǔ)法進(jìn)行講解,然后通過(guò)一個(gè)實(shí)例用四種循環(huán)來(lái)實(shí)現(xiàn)。相信通過(guò)本文的學(xué)習(xí),大家都能夠?qū)語(yǔ)言循環(huán)語(yǔ)句有著熟練的掌握
    2022-05-05
  • C++內(nèi)存模型和名稱空間詳解

    C++內(nèi)存模型和名稱空間詳解

    這篇文章主要給大家介紹了關(guān)于C/C++中的內(nèi)存模型和名稱空間詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用c/c++具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起看看吧
    2021-09-09
  • 深入了解C語(yǔ)言棧的創(chuàng)建

    深入了解C語(yǔ)言棧的創(chuàng)建

    棧只允許在一端進(jìn)行插入或刪除操作的線性表。首先棧是一種線性表,但是限定這種線性表只能在某一端進(jìn)行插入和刪除操作,這篇文章主要介紹了C語(yǔ)言對(duì)棧的實(shí)現(xiàn)基本操作
    2021-07-07
  • 詳解C語(yǔ)言sscanf()函數(shù)、vsscanf()函數(shù)、vscanf()函數(shù)

    詳解C語(yǔ)言sscanf()函數(shù)、vsscanf()函數(shù)、vscanf()函數(shù)

    這篇文章主要介紹了詳解C語(yǔ)言sscanf()函數(shù)、vsscanf()函數(shù)、vscanf()函數(shù),是C語(yǔ)言入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-08-08
  • C語(yǔ)言指針超詳細(xì)講解下篇

    C語(yǔ)言指針超詳細(xì)講解下篇

    指針提供了對(duì)地址操作的一種方法,因此,使用指針可使得?C?語(yǔ)言能夠更高效地實(shí)現(xiàn)對(duì)計(jì)算機(jī)底層硬件的操作。另外,通過(guò)指針可以更便捷地操作數(shù)組。在一定意義上可以說(shuō),指針是?C?語(yǔ)言的精髓
    2022-04-04
  • 簡(jiǎn)要對(duì)比C語(yǔ)言中三個(gè)用于退出進(jìn)程的函數(shù)

    簡(jiǎn)要對(duì)比C語(yǔ)言中三個(gè)用于退出進(jìn)程的函數(shù)

    這篇文章主要介紹了C語(yǔ)言中三個(gè)用于退出進(jìn)程的函數(shù)的對(duì)比,分別為_exit()函數(shù)和on_exit()函數(shù)以及atexit()函數(shù),需要的朋友可以參考下
    2015-08-08

最新評(píng)論