特性完成:VS2019 v16.8全面支持C++協程

2020-09-18 漫漫開發路

一段往事

回首有關C++協程的往事,真是猶如一段十分漫長的旅程。
早在2013年,我們就官宣了一個有關」可恢復函數」的早期預覽版本,接下來在2014年,我們添加了/await開關並提交了C++標準化建議的初始版本。2015年,我們提交了修訂版本。後來,通過Visual Studio 2017和Visual Studio 2019,我們都在持續地跟蹤有關協程TS(Technical Sepecificaion)的內容更新。2019年,隨著協程完全實現被納入到C++標準中,我們終於可以宣布了:Visual Studio 2019 v16.8將完全支持C++20協程特性。

Standard vs. TS Coroutines

最終通過標準化程序成為C++20一部分的協程支持,與早期的提議草案以及我們在/await開關下在MSVC中獲得的實驗版本協程有所不同。
我們在實現v16.8中的協程支持時,考慮了兩個重要,但是相互矛盾的目標。
1. 提供一個嚴格遵循C++標準的協程實現,使得用戶可以編寫和使用可移植代碼。
2. 確保那些使用實驗版本協程的用戶可以毫不費力地升級到v16.8而無需改動他們的代碼。

隨著提案的更改,我們會儘可能增加新的支持,而不破壞針使用早期協程版本的代碼。
這當然不是標準的:它仍然接受所有舊的關鍵字,名稱和籤名,和上面的第一個目標對應。
與我們在/await下實現的原始版本相比,還存在少量的行為更改,例如一個promise對象的構建方式。這些可能導致先前可以通過編譯的程序變得無法編譯或表現出與之前不一樣的行為。

Standard Mode – /std:c++latest

使用比C++17更新的編譯器語言版本模式時,就能實現對C++20協程的支持,同時,不帶有對舊版TS的支持。現在,這是/std:c++latest,在添加了C ++ 17之後,它將繼續進入編號版本的開關。使用這種語言開關進行編譯且不帶/await時,你就可以獲得對C++20協程的嚴格支持,我們在頭文件中和std名稱空間中提供了庫級別支持。此模式將針對早期建議中的非標準代碼會給出錯誤提示,例如,使用了bare await關鍵字或返回bool的initial_suspend函數,並且僅在其與早期實現不同時才支持這種標準行為。

Extension Mode – /await

協程的早期使用者可以繼續使用/await開關和任何語言版本的開關(包括/std:c++latest)來編譯其非標準化的代碼,並繼續使用實驗性頭文件和命名空間。只要不破壞兼容性,我們都會在此模式下添加那些缺少的標準功能並提供錯誤修復。

我們建議現有的協程使用者儘快地遷移到標準版協程,新用戶應優先使用標準模式而不是/await。 針對現有用戶,我們將繼續支持/await開關,但是將來的協程開發版本將處於標準模式,並且在那裡將實現新功能。除了一些極端的情況,將項目從/await遷移到C++20應該是一個簡單的過程。

Visual Studio 2019 v16.8 都有那些新東西?

v16.8版本中引入了一些有關協程的新功能和改進:

> 對稱轉移(Symmetric transfer)
> 無操作協程(No-op coroutines)
> 協程Promise構造函數參數
> 定義良好的行為,使異常控制流從協程中退出
> 標準返回對象轉換行為
> 優化後的調試體驗
> 通用幀布局,以提高與其他供應商的兼容性
> 大量錯誤修復

無操作協程和大多數錯誤修復程序也已在/await下實現,但大多數這些更改僅在以標準模式構建時可用。在本文的其餘部分,我們將仔細研究其中一些新功能的細節以及Visual Studio有關協程的下一個階段版本。

對稱轉移和無操作協程

這是C++20協程支持的最後兩個缺失的部分。對於對稱轉移,協程可以指示協程句柄,以便另一個協程在掛起時立即恢復。這是通過使用coroutine_handle的返回類型定義協程await_suspend函數來完成的,如下圖所示:

在標準模式下,此掛起和恢復操作可以在不將另一個幀引入到調用堆棧的情況下工作。這樣就可以在協程之間進行不限大小的數據傳輸,而不會冒堆棧溢出的風險。

優化後的調試體驗

v16.8版引入了一些用於協程的新調試功能。
修正了協程步入的一些問題,尤其是和選項」Just My Code」一起工作的時候。
你還可以在協程程序中展開棧指針。通過這個特性,你可以看到一些公開的數據,例如協程參數值和promise類型的成員(僅限標準協程)。
我們還更改了許多由編譯器生成的符號的名稱,以更好地與調試器的表達式求值一起使用。有了它們,就可以更容易在即時窗口或監視窗口中使用,也可以作為條件斷點使用。如下圖所示:

通用幀布局

在標準C++ 20模式下,協程框架有了新的內部表示形式。這暴露了對協程非常重要的框架部分,例如如何以廠商之間通用的方式恢復或銷毀它。一個供應商生產的目標文件或庫中生成的協程可能會被另一供應商使用。這並不意味著完整框架的布局在各供應商之間是通用的,甚至不能保證在編譯器版本之間是穩定的,但是它確實標準化了(儘管是非正式的)標準庫類型std::coroutine_handle與基礎協程框架對象之間的接口,並在從庫中公開或使用協程時應有助於提高兼容性和靈活性。我們還引入了在Clang使用相同內置函數的支持,從而實現了更好的頭文件級兼容性。

當前,不同編譯器廠商之間的協程支持級別有所不同,但大部分正在不斷提高。隨著C++20支持在各個編譯器中廣泛推廣,我們希望這將變得更加有用和重要。我們致力於為協程提供通用,穩定的ABI,以使不同版本之間的接口儘可能實現無縫升級。

接下來

C++20中的協程還存在一些限制。雖然已經採用了核心語言功能,但是標準庫中沒有真正的協程支持。好消息是,我們預計很快就會有改變,在下一個C++語言版本中將對協程提供更廣泛的庫支持。

我們針對C++ 20協程的下一階段的目標是不斷改善調試體驗。這種情況的一個方面是,這是一個更自然的趨勢,使開發者可以更容易跟蹤協程執行,就好像它是普通的同步功能一樣。我們還在尋找改進的協程句柄可視化功能,以實現輕鬆查看協程運行狀態。

總結

協程來了,老哥們是否準備好了呢?
還是,和我一樣,繼續寫寫HelloWorld,混混日子?

最後

Microsoft Visual C++團隊的博客是我非常喜歡的博客之一,裡面有很多關於Visual C++的知識和最新開發進展。大浪淘沙,如果你對Visual C++這門古老的技術還是那麼感興趣,則可以經常去他們那(或者我這)逛逛。
本文來自:《C++ Coroutines in Visual Studio 2019 Version 16.8》

相關焦點

  • 總結一下:VS2019中對C++20語言特性的支持
    我們的開發團隊一直都在努力工作,嘗試在MSVC工具集中實現C++20儘可能多的語言特性,在已發布的VS2019 v16.7和VS2019 v16.8中,我們取得了比較大的進展。今天,我們就來總結一下這兩個大版本中對C++20的支持情況。今天我們將特別關注MSVC編譯器(cl.exe)中實現的C++20語言特性。
  • 總結一下:VS2019中對C+20語言特性的支持
    我們的開發團隊一直都在努力工作,嘗試在MSVC工具集中實現C++20儘可能多的語言特性,在已發布的VS2019 v16.7和VS2019 v16.8中,我們取得了比較大的進展。今天,我們就來總結一下這兩個大版本中對C++20的支持情況。 今天我們將特別關注MSVC編譯器(cl.exe)中實現的C++20語言特性。
  • 進度更新:VS2019 v16.8中對C++20模塊的支持
    /std:c++latest隱式包含C++模塊由於MSVC已經開始實現C++模塊標準,工具集會在任何時候都強制使用/experimental:module編譯開關。因為模塊已經被正式移入到C++20,編譯器團體做了大量的工作,終於將模塊合併到了/std:c++latest中。
  • VS2019 v16.5新特性出爐:增強對C++ Modules的支持
    伴隨著新標準的發布,我們一直期待的Modules特性終於粉墨登場了。早在2017年,編譯器開發團隊就寫了一篇文章表明他們正在圍繞著Modules TS開展了工作,從那個時候開始,我們就一直努力的工作來改進這一特性並提升編譯器對這一標準特性的適應性。今天,我們終於覺得是時候來分享一些我們在Modules支持上的一些進展了。有哪些新東西?
  • GCC 10編譯器已對C++20的主要功能協程 進行了初始支持
    最近發布的GCC 10 編譯器已對C++20 的主要功能協程(Co-Routines)進行了初始支持,但是除非顯式地開啟該選項,否則並不會啟用此功能。當 GCC 10 在C++20 模式(std=c++20) 中運行時,默認情況下會啟用C++ 協程。
  • 說說VS2019 v16.8 預覽版3中的一大波更新
    偵測到一大波的在途更新對於C++開發者來說,Visual Studio 2019 v16.8 Preview 3引入了大量的更新,主要涵蓋標準化,性能改進和生產力提升。下面,我們來看看。C++20我們從編譯器,標準庫和IDE等各個層面對主要的C++20特性的支持做了改進。
  • 說說VS2019 v16.8 預覽版3中的一大波更新
    偵測到一大波的在途更新對於C++開發者來說,Visual Studio 2019 v16.8 Preview 3引入了大量的更新,主要涵蓋標準化,性能改進和生產力提升C++20我們從編譯器,標準庫和IDE等各個層面對主要的C++20特性的支持做了改進。
  • C++20 新特性(15):協程(Coroutines )
    lt;< " " << sum[6] << endl; pthread_mutex_destroy( &mutex ); pthread_cond_destroy( &cond ); return 0;}編譯和運行結果為:[smlc@test code]$ g++ -std=c++
  • 新鮮特性出爐:VS2019 v16.5 預覽版2 更新一覽
    VS對CMake的原生支持,可以實現在同一個IDE中面向Windows和Linux平臺編寫應用程式。在最新版的VS2019 v16.5 Preview 2中,我們為跨平臺開發引入了一些新的功能特性,如下:File copy optimizations for CMake projects targeting a remote Linux systemNative WSL support when separating your build system from your remote
  • VS2019 v16.3跨平臺開發四件套
    通過使用VS中對CMake的原生支持,我們可以在VS中直接打開任何包含C++代碼和CMakeLists.text的目錄,進行編碼,並面向Windows, Linux和WSL(Windows Subsystem for Linux)這三種目標平臺進行構建並調試。
  • Visual Studio 2019 v16.8 和 v16.9 Preview 1 發布
    Visual Studio 團隊宣布 Visual Studio 2019 v16.8 和 v16.9 Preview 1 發布
  • C/C++協程學習筆記丨C/C++實現協程及原理分析視頻
    Python對協程的支持還非常有限,用在generator中的yield可以一定程度上實現協程。雖然支持不完全,但已經可以發揮相當大的威力了。與 Python 不同,C/C++ 語言本身是不能天然支持協程的。
  • 第一次肉眼可見的對C++20 Ranges的支持
    今兒個,咱們十分高興Visual Studio 2019 v16.6正式開始支持C++20 Ranges。我們已經針對系統支持的部分開發了一些版本,這些雖然很重要,但是用戶看不到它們的存在。但是在此版本中,冰山一角終於打破了水面,現在終於可以有一些工具供用戶使用了。
  • 曾被「勸退」的 C++ 20 正式發布
    作為程式設計師,看到新標準發布總想嘗鮮,目前 gcc 10.2 可以支持部分 C++ 20 標準,編譯的時候需要使用編譯選項:-std=c++2a。在模板編程中,可以限制模板參數的類型或具用某種特性,如:可以限制為整型、數值型、bool 型、或必須支持 hash 特性、或某個類的派生類型等。在 C++20 中 Concepts 是非常重要的概念,模板編程終於有了質的提升。
  • 解讀C++即將迎來的重大更新(一):C++20的四大新特性
    目前這個系列文章已經更新了兩篇,本篇是第一篇,主要介紹了 C++20 的 Big Four(四大新特性:概念、範圍、協程和模塊)以及核心語言(包括一些新的運算符和指示符)。C++20 有很多更新,上圖展示了 C++20 更新的概況。下面作者首先介紹 了 C++20 的編譯器支持情況,然後介紹 The Big Four(四大新特性)以及核心語言方面的新特性。
  • VS2019更新:更快的C++工程迭代構建
    在VS2019 v16.7中,我們測試發現,在某些增量連結場景下,連結速度提升了5倍之多,在調試場景下,則觀測到了高達1.5倍的完整連結速度提升。在之前的一篇關於《戰爭機器5》開發團隊的一篇文章中,會有關於此信息的更多內容,歡迎觀看。在v16.0和v16.2中進行了連結性能優化之後,我們回顧並重新評估了C++開發者的」編輯-構建-調試」的完整流程。
  • 揭秘:微信如何用 libco 支撐8億用戶
    libco支持後臺敏捷的同步風格編程模式,同時提供系統的高並發能力。libco支持的特性支持CGI框架,輕鬆構建web服務(New);支持gethostbyname、mysqlclient、ssl等常用第三庫(New);可選的共享棧模式,單機輕鬆接入千萬連接(New);完善簡潔的協程編程接口:        ▪  類pthread接口設計,通過co_create
  • VS2019中對C++內聯器的改進:Zipliner
    官一下宣Visual Studio 2019 v16.3和v16.4包含了對C++內聯器的一系列改進,其中包含這麼一條:具備對某些經過優化後的代碼進行內聯的能力,我們稱之為」Zipliner」。根據你的應用的不同,你可能會看到一些較小的代碼質量改進或者編譯時間的顯著縮短。
  • 深入理解異步I/O+epoll+協程
    前言同步和異步的概念描述的是用戶線程與內核的交互方式:同步是指用戶線程發起IO請求後需要等待或者輪詢內核IO操作完成後才能繼續執行;而異步是指用戶線程發起IO請求後仍繼續執行,當內核IO操作完成後會通知用戶線程,或者調用用戶線程註冊的回調函數。
  • 5分鐘看懂:啟發式更新算法——React17新特性
    該版本的最大特性是「無新特性」。那麼,從v16到v17這一年多時間React團隊究竟在做什麼?遙想從v15到v16,React團隊花了兩年時間將源碼架構中的Stack Reconciler重構為Fiber Reconciler,事情一定沒有這麼簡單。事實上,這次版本更迭確實有「新特性」 —— 替換了內部使用的啟發式更新算法。