C++ coroutine-ts 怎么用-Part 2 coroutine有什么用


上一篇說了coroutine的本質是什么,就是resumable function,那么一個函數有了suspend和resume功能之后,會打開什么樣的新世界大門呢?隨便舉幾個例子。

  • 函數每次被喚醒,就丟出一個值,然后暫停——這是generator
  • 函數啟動一個IO操作,注冊IO操作完成時喚醒自己,然后暫停——這是async-await
  • 函數開啟一個管道,暫停,另一個函數往管道里寫一點東西,然后喚醒它——這是channel
  • 函數檢查某個值是不是期望的,如果不是,就暫停——這是exception

其實,2和3的機制是很相似的,只不過2里面喚醒coroutine的是操作系統的callback,3是你自己的另一個線程。4里面說的異常,其實就是這樣的,因為異常和coroutine再往下追溯,他們的理論基礎都是CPS(Continuation Passing Style),也就是把當前操作的后續操作作為閉包傳給當前操作,而當前操作可以選擇執行哪一個(或是否執行)后續操作。雖然coroutine和exception都用到了CPS,但大部分的coroutine都額外支持了exception,耦合在了一起,因為他們沒有直接提供操作continuation的東西。

扯遠了,可以看到了,coroutine解鎖了很多寫代碼的新姿勢。

有了generator,你可以生成一個惰性求值的列表,對他進行變換,而這些所有的操作都是惰性執行的,這就是C#里面的LINQ,Python和Javascirpt里的生成器,Java8的Stream API,C++的range-ts也可以接入coroutine,而避免使用復雜的迭代器封裝狀態。

有了async-await,你可以把異步代碼寫成像同步代碼那樣,而代碼在await的邊界處是自動暫停和繼續的,這無疑降低了程序員手動寫狀態機維護狀態的難度,也避免了一連串.then造成回調地獄的問題。channel和異步操作的async-await很相似,兩條線程如今可以主動的暫停自己和喚醒對方,通過一個普通的原子變量來傳遞信息,而不需要用厚重的管道或者多線程同步機制來等待和喚醒對方。

關於coroutine模擬exception,這倒是沒有太大的必要,不過,考慮到coroutine的本質是CPS,那么就可以用coroutine來模擬rust的自動向上傳播錯誤碼,haskell的maybe monad等等,這些東西是對應語言的錯誤處理機制,就像C++的異常一樣。

腦洞,反過來,異常可以模擬coroutine嗎?不行,異常有點像暫停之后再也不會喚醒的coroutine。


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com