<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Coroutine on Mer's Blog</title><link>https://merisky.top/tags/coroutine/</link><description>Recent content in Coroutine on Mer's Blog</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Sun, 26 Mar 2023 11:13:42 +0800</lastBuildDate><atom:link href="https://merisky.top/tags/coroutine/index.xml" rel="self" type="application/rss+xml"/><item><title>C++ Coroutine: 通用异步任务 Task</title><link>https://merisky.top/posts/3692590940/</link><pubDate>Sat, 25 Mar 2023 12:19:31 +0000</pubDate><guid>https://merisky.top/posts/3692590940/</guid><description>&lt;p&gt;本文使用协程实现了一个通用的异步任务执行类 Task，支持设置回调函数并将在 Task 完成后执行回调。&lt;/p&gt;&#10;&lt;p&gt;Task、TaskPromise 和 TaskAwaiter 覆盖到了大部分的协程执行过程，把这几个类的实现理解了那基本上就可以说已经理解了 c++ 协程的工作方式。&lt;/p&gt;&#10;&lt;p&gt;阅读下面这段代码的方式建议通过 main 函数开始，对照运行结果一点一点来看。&lt;/p&gt;&#10;&lt;h2 id="Source-Code"&gt;&lt;a href="#Source-Code" class="headerlink" title="Source Code"&gt;&lt;/a&gt;Source Code&lt;/h2&gt;&lt;figure class="highlight cpp"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre&gt;&lt;span class="line"&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;89&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;90&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;91&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;92&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;93&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;94&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;95&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;96&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;97&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;98&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;99&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;100&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;101&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;102&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;103&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;104&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;105&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;106&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;107&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;108&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;109&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;110&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;111&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;112&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;113&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;114&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;115&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;116&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;117&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;118&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;119&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;120&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;121&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;122&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;123&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;124&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;125&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;126&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;127&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;128&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;129&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;130&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;131&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;132&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;133&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;134&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;135&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;136&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;137&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;138&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;139&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;140&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;141&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;142&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;143&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;144&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;145&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;146&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;147&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;148&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;149&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;150&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;151&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;152&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;153&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;154&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;155&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;156&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;157&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;158&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;159&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;160&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;161&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;162&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;163&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;164&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;165&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;166&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;167&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;168&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;169&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;170&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;171&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;172&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;173&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;174&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;175&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;176&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;177&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;178&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;179&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;180&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;181&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;182&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;183&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;184&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;185&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;186&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;187&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;188&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;189&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;190&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;191&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;192&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;193&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;194&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;195&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;196&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;197&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;198&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;199&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;200&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;201&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;202&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;203&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;204&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;205&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;206&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;207&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;208&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;209&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;210&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;211&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;212&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;213&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;214&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;215&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;216&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;217&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;218&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;219&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;220&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;221&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;222&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;223&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;224&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;225&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;226&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;227&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;228&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;229&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;230&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;231&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;232&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;233&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;234&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;235&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;236&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;237&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;238&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;239&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;240&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;241&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;242&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;243&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;244&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;245&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;246&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;247&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;248&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;249&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;250&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;251&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;252&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;253&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;254&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;255&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;256&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;257&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;258&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;259&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;260&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;261&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;262&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;263&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;264&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;265&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;266&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;267&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;268&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;269&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;270&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;271&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;272&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;273&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;274&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;275&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;276&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;277&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;278&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;279&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;280&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;281&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;282&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;283&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;284&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;285&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;286&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;287&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;288&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;289&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;290&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;291&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;292&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;293&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;294&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;295&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;296&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;297&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;298&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;299&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;300&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;301&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;302&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;303&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;304&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;305&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;306&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;307&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;308&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;309&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;310&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;311&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;312&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;313&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;314&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;315&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;316&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;317&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;318&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;319&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;320&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;321&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;322&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre&gt;&lt;span class="line"&gt;&lt;span class="meta"&gt;#&lt;span class="keyword"&gt;include&lt;/span&gt; &lt;span class="string"&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="meta"&gt;#&lt;span class="keyword"&gt;include&lt;/span&gt; &lt;span class="string"&gt;&amp;lt;coroutine&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="meta"&gt;#&lt;span class="keyword"&gt;include&lt;/span&gt; &lt;span class="string"&gt;&amp;lt;functional&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="meta"&gt;#&lt;span class="keyword"&gt;include&lt;/span&gt; &lt;span class="string"&gt;&amp;lt;exception&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="meta"&gt;#&lt;span class="keyword"&gt;include&lt;/span&gt; &lt;span class="string"&gt;&amp;lt;optional&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="meta"&gt;#&lt;span class="keyword"&gt;include&lt;/span&gt; &lt;span class="string"&gt;&amp;lt;atomic&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="meta"&gt;#&lt;span class="keyword"&gt;include&lt;/span&gt; &lt;span class="string"&gt;&amp;lt;utility&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="meta"&gt;#&lt;span class="keyword"&gt;include&lt;/span&gt; &lt;span class="string"&gt;&amp;lt;chrono&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="meta"&gt;#&lt;span class="keyword"&gt;include&lt;/span&gt; &lt;span class="string"&gt;&amp;lt;thread&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="meta"&gt;#&lt;span class="keyword"&gt;include&lt;/span&gt; &lt;span class="string"&gt;&amp;lt;list&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="meta"&gt;#&lt;span class="keyword"&gt;include&lt;/span&gt; &lt;span class="string"&gt;&amp;lt;condition_variable&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="meta"&gt;#&lt;span class="keyword"&gt;include&lt;/span&gt; &lt;span class="string"&gt;&amp;lt;algorithm&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="meta"&gt;#&lt;span class="keyword"&gt;include&lt;/span&gt; &lt;span class="string"&gt;&amp;lt;atomic&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="meta"&gt;#&lt;span class="keyword"&gt;define&lt;/span&gt; debug(info) std::cout &amp;lt;&amp;lt; __LINE__ &amp;lt;&amp;lt; &lt;span class="string"&gt;&amp;quot; &amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; __func__ &amp;lt;&amp;lt; &lt;span class="string"&gt;&amp;quot;: &amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; info &amp;lt;&amp;lt; std::endl;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="keyword"&gt;template&lt;/span&gt;&amp;lt;&lt;span class="keyword"&gt;typename&lt;/span&gt; Task&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="keyword"&gt;struct&lt;/span&gt; &lt;span class="title class_"&gt;Result&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="comment"&gt;// 初始化为默认值&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="function"&gt;&lt;span class="keyword"&gt;explicit&lt;/span&gt; &lt;span class="title"&gt;Result&lt;/span&gt;&lt;span class="params"&gt;()&lt;/span&gt; &lt;/span&gt;= &lt;span class="keyword"&gt;default&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="comment"&gt;// 当 Task 正常返回时用结果初始化 Result&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="function"&gt;&lt;span class="keyword"&gt;explicit&lt;/span&gt; &lt;span class="title"&gt;Result&lt;/span&gt;&lt;span class="params"&gt;(Task &amp;amp;&amp;amp;value)&lt;/span&gt; : _value(value) &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt; &amp;#123;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;Construct from value&amp;quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="comment"&gt;// 当 Task 抛异常时用异常初始化 Result&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="function"&gt;&lt;span class="keyword"&gt;explicit&lt;/span&gt; &lt;span class="title"&gt;Result&lt;/span&gt;&lt;span class="params"&gt;(std::exception_ptr &amp;amp;&amp;amp;exception_ptr)&lt;/span&gt; : _exception_ptr(exception_ptr)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt; &amp;#123;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;Construct from exception_ptr&amp;quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="comment"&gt;// 读取结果，有异常则抛出异常&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="function"&gt;Task &lt;span class="title"&gt;get_or_throw&lt;/span&gt;&lt;span class="params"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; (_exception_ptr)&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; std::&lt;span class="built_in"&gt;rethrow_exception&lt;/span&gt;(_exception_ptr);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;return&lt;/span&gt; _value;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;private&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; Task _value&amp;#123;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; std::exception_ptr _exception_ptr;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="keyword"&gt;template&lt;/span&gt;&amp;lt;&lt;span class="keyword"&gt;template&lt;/span&gt;&amp;lt;&lt;span class="keyword"&gt;typename&lt;/span&gt;&amp;gt; &lt;span class="keyword"&gt;class&lt;/span&gt; &lt;span class="title class_"&gt;Task&lt;/span&gt;, &lt;span class="keyword"&gt;typename&lt;/span&gt; R&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="keyword"&gt;struct&lt;/span&gt; &lt;span class="title class_"&gt;TaskAwaiter&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="function"&gt;&lt;span class="keyword"&gt;explicit&lt;/span&gt; &lt;span class="title"&gt;TaskAwaiter&lt;/span&gt;&lt;span class="params"&gt;(Task&amp;lt;R&amp;gt; &amp;amp;&amp;amp;task)&lt;/span&gt; &lt;span class="keyword"&gt;noexcept&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt; : task(std::move(task))&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt; &amp;#123;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;Construct from task&amp;quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;TaskAwaiter&lt;/span&gt;(TaskAwaiter &amp;amp;&amp;amp;completion) &lt;span class="keyword"&gt;noexcept&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; : &lt;span class="built_in"&gt;task&lt;/span&gt;(std::&lt;span class="built_in"&gt;exchange&lt;/span&gt;(completion.task, &amp;#123;&amp;#125;))&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;Construct from completion&amp;quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;TaskAwaiter&lt;/span&gt;(TaskAwaiter &amp;amp;) = &lt;span class="keyword"&gt;delete&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; TaskAwaiter &amp;amp;&lt;span class="keyword"&gt;operator&lt;/span&gt;=(TaskAwaiter &amp;amp;) = &lt;span class="keyword"&gt;delete&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="function"&gt;&lt;span class="keyword"&gt;constexpr&lt;/span&gt; &lt;span class="type"&gt;bool&lt;/span&gt; &lt;span class="title"&gt;await_ready&lt;/span&gt;&lt;span class="params"&gt;()&lt;/span&gt; &lt;span class="type"&gt;const&lt;/span&gt; &lt;span class="keyword"&gt;noexcept&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;&amp;quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="literal"&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="function"&gt;&lt;span class="type"&gt;void&lt;/span&gt; &lt;span class="title"&gt;await_suspend&lt;/span&gt;&lt;span class="params"&gt;(std::coroutine_handle&amp;lt;&amp;gt; handle)&lt;/span&gt; &lt;span class="keyword"&gt;noexcept&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;&amp;quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; std::cout &amp;lt;&amp;lt; handle.&lt;span class="built_in"&gt;address&lt;/span&gt;() &amp;lt;&amp;lt; std::endl;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="comment"&gt;// 当 task 执行完之后调用 resume&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; task.&lt;span class="built_in"&gt;finally&lt;/span&gt;([handle]() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; handle.&lt;span class="built_in"&gt;resume&lt;/span&gt;();&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="comment"&gt;// 协程恢复执行时，被等待的 Task 已经执行完，调用 get_result 来获取结果&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="function"&gt;R &lt;span class="title"&gt;await_resume&lt;/span&gt;&lt;span class="params"&gt;()&lt;/span&gt; &lt;span class="keyword"&gt;noexcept&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;&amp;quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;return&lt;/span&gt; task.&lt;span class="built_in"&gt;get_result&lt;/span&gt;();&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;private&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; Task&amp;lt;R&amp;gt; task;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="keyword"&gt;template&lt;/span&gt;&amp;lt;&lt;span class="keyword"&gt;template&lt;/span&gt;&amp;lt;&lt;span class="keyword"&gt;typename&lt;/span&gt;&amp;gt; &lt;span class="keyword"&gt;class&lt;/span&gt; &lt;span class="title class_"&gt;Task&lt;/span&gt;, &lt;span class="keyword"&gt;typename&lt;/span&gt; ResultType&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="keyword"&gt;struct&lt;/span&gt; &lt;span class="title class_"&gt;TaskPromise&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="function"&gt;&lt;span class="keyword"&gt;auto&lt;/span&gt; &lt;span class="title"&gt;initial_suspend&lt;/span&gt;&lt;span class="params"&gt;()&lt;/span&gt; &lt;span class="keyword"&gt;noexcept&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;&amp;quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;return&lt;/span&gt; std::suspend_never&amp;#123;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="function"&gt;&lt;span class="keyword"&gt;auto&lt;/span&gt; &lt;span class="title"&gt;final_suspend&lt;/span&gt;&lt;span class="params"&gt;()&lt;/span&gt; &lt;span class="keyword"&gt;noexcept&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;&amp;quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;return&lt;/span&gt; std::suspend_always&amp;#123;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="function"&gt;Task&amp;lt;ResultType&amp;gt; &lt;span class="title"&gt;get_return_object&lt;/span&gt;&lt;span class="params"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;return&lt;/span&gt; Task&amp;#123;std::coroutine_handle&amp;lt;TaskPromise&amp;gt;::&lt;span class="built_in"&gt;from_promise&lt;/span&gt;(*&lt;span class="keyword"&gt;this&lt;/span&gt;)&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="function"&gt;&lt;span class="type"&gt;void&lt;/span&gt; &lt;span class="title"&gt;unhandled_exception&lt;/span&gt;&lt;span class="params"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;&amp;quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="function"&gt;std::lock_guard &lt;span class="title"&gt;lock&lt;/span&gt;&lt;span class="params"&gt;(completion_lock)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; result = &lt;span class="built_in"&gt;Result&lt;/span&gt;&amp;lt;ResultType&amp;gt;(std::&lt;span class="built_in"&gt;current_exception&lt;/span&gt;());&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; completion.&lt;span class="built_in"&gt;notify_all&lt;/span&gt;();&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="comment"&gt;// 调用回调&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;notify_callbacks&lt;/span&gt;();&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="function"&gt;&lt;span class="type"&gt;void&lt;/span&gt; &lt;span class="title"&gt;return_value&lt;/span&gt;&lt;span class="params"&gt;(ResultType value)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;&amp;quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="function"&gt;std::lock_guard &lt;span class="title"&gt;lock&lt;/span&gt;&lt;span class="params"&gt;(completion_lock)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; result = &lt;span class="built_in"&gt;Result&lt;/span&gt;&amp;lt;ResultType&amp;gt;(std::&lt;span class="built_in"&gt;move&lt;/span&gt;(value));&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; completion.&lt;span class="built_in"&gt;notify_all&lt;/span&gt;();&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="comment"&gt;// 调用回调&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;notify_callbacks&lt;/span&gt;();&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="function"&gt;ResultType &lt;span class="title"&gt;get_result&lt;/span&gt;&lt;span class="params"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;from TaskPromise&amp;quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="comment"&gt;// 如果 result 没有值，说明协程还没有运行完，等待值被写入再返回&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="function"&gt;std::unique_lock &lt;span class="title"&gt;lock&lt;/span&gt;&lt;span class="params"&gt;(completion_lock)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; (!result.&lt;span class="built_in"&gt;has_value&lt;/span&gt;()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;hasn&amp;#x27;t value now&amp;quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="comment"&gt;// 等待写入值之后调用 notify_all&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; completion.&lt;span class="built_in"&gt;wait&lt;/span&gt;(lock);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125; &lt;span class="keyword"&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;already has value now&amp;quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="comment"&gt;// 如果有值，则直接返回（或者抛出异常）&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;return&lt;/span&gt; result-&amp;gt;&lt;span class="built_in"&gt;get_or_throw&lt;/span&gt;();&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="function"&gt;&lt;span class="type"&gt;void&lt;/span&gt; &lt;span class="title"&gt;on_completed&lt;/span&gt;&lt;span class="params"&gt;(std::function&amp;lt;&lt;span class="type"&gt;void&lt;/span&gt;(Result&amp;lt;ResultType&amp;gt;)&amp;gt; &amp;amp;&amp;amp;func)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;&amp;quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="function"&gt;std::unique_lock &lt;span class="title"&gt;lock&lt;/span&gt;&lt;span class="params"&gt;(completion_lock)&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="comment"&gt;// 加锁判断 result&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; (result.&lt;span class="built_in"&gt;has_value&lt;/span&gt;()) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;already has value&amp;quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="comment"&gt;// result 已经有值&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;auto&lt;/span&gt; value = result.&lt;span class="built_in"&gt;value&lt;/span&gt;();&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="comment"&gt;// 解锁之后再调用 func&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; lock.&lt;span class="built_in"&gt;unlock&lt;/span&gt;();&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;func&lt;/span&gt;(value);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125; &lt;span class="keyword"&gt;else&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;waiting for execution&amp;quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="comment"&gt;// 否则添加回调函数，等待调用&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; completion_callbacks.&lt;span class="built_in"&gt;push_back&lt;/span&gt;(func);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="comment"&gt;// 注意这里的模板参数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="function"&gt;&lt;span class="keyword"&gt;template&lt;/span&gt;&amp;lt;&lt;span class="keyword"&gt;typename&lt;/span&gt; _ResultType&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt; &lt;span class="keyword"&gt;auto&lt;/span&gt; &lt;span class="title"&gt;await_transform&lt;/span&gt;&lt;span class="params"&gt;(Task&amp;lt;_ResultType&amp;gt; &amp;amp;&amp;amp;task)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;&amp;quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;return&lt;/span&gt; TaskAwaiter&amp;lt;Task, _ResultType&amp;gt;&amp;#123;std::&lt;span class="built_in"&gt;move&lt;/span&gt;(task)&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;private&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="comment"&gt;// 回调列表，我们允许对同一个 Task 添加多个回调&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; std::list&amp;lt;std::function&amp;lt;&lt;span class="type"&gt;void&lt;/span&gt;(Result&amp;lt;ResultType&amp;gt;)&amp;gt;&amp;gt; completion_callbacks;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="function"&gt;&lt;span class="type"&gt;void&lt;/span&gt; &lt;span class="title"&gt;notify_callbacks&lt;/span&gt;&lt;span class="params"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;&amp;quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;auto&lt;/span&gt; value = result.&lt;span class="built_in"&gt;value&lt;/span&gt;();&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;for&lt;/span&gt; (&lt;span class="keyword"&gt;auto&lt;/span&gt; &amp;amp;callback : completion_callbacks) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;call callback function from completion_callbacks&amp;quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;callback&lt;/span&gt;(value);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="comment"&gt;// 调用完成，清空回调&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; completion_callbacks.&lt;span class="built_in"&gt;clear&lt;/span&gt;();&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="comment"&gt;// 使用 std::optional 可以区分协程是否执行完成&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; std::optional&amp;lt;Result&amp;lt;ResultType&amp;gt;&amp;gt; result;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; std::mutex completion_lock;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; std::condition_variable completion;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="keyword"&gt;template&lt;/span&gt;&amp;lt;&lt;span class="keyword"&gt;typename&lt;/span&gt; ResultType&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="keyword"&gt;struct&lt;/span&gt; &lt;span class="title class_"&gt;Task&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="comment"&gt;// 声明 promise_type 为 TaskPromise 类型&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;using&lt;/span&gt; promise_type = TaskPromise&amp;lt;Task, ResultType&amp;gt;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="function"&gt;ResultType &lt;span class="title"&gt;get_result&lt;/span&gt;&lt;span class="params"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;from Task&amp;quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;return&lt;/span&gt; handle.&lt;span class="built_in"&gt;promise&lt;/span&gt;().&lt;span class="built_in"&gt;get_result&lt;/span&gt;();&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="function"&gt;Task &amp;amp;&lt;span class="title"&gt;then&lt;/span&gt;&lt;span class="params"&gt;(std::function&amp;lt;&lt;span class="type"&gt;void&lt;/span&gt;(ResultType)&amp;gt; &amp;amp;&amp;amp;func)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;task id = &amp;quot;&lt;/span&gt; + std::&lt;span class="built_in"&gt;to_string&lt;/span&gt;(task_id));&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; std::cout &amp;lt;&amp;lt; handle.&lt;span class="built_in"&gt;address&lt;/span&gt;() &amp;lt;&amp;lt; std::endl;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; handle.&lt;span class="built_in"&gt;promise&lt;/span&gt;().&lt;span class="built_in"&gt;on_completed&lt;/span&gt;([func](&lt;span class="keyword"&gt;auto&lt;/span&gt; result) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;try&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;func&lt;/span&gt;(result.&lt;span class="built_in"&gt;get_or_throw&lt;/span&gt;());&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125; &lt;span class="built_in"&gt;catch&lt;/span&gt; (std::exception &amp;amp;e) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="comment"&gt;// 忽略异常&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;return&lt;/span&gt; *&lt;span class="keyword"&gt;this&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="function"&gt;Task &amp;amp;&lt;span class="title"&gt;catching&lt;/span&gt;&lt;span class="params"&gt;(std::function&amp;lt;&lt;span class="type"&gt;void&lt;/span&gt;(std::exception &amp;amp;)&amp;gt; &amp;amp;&amp;amp;func)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;task id = &amp;quot;&lt;/span&gt; + std::&lt;span class="built_in"&gt;to_string&lt;/span&gt;(task_id));&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; handle.&lt;span class="built_in"&gt;promise&lt;/span&gt;().&lt;span class="built_in"&gt;on_completed&lt;/span&gt;([func](&lt;span class="keyword"&gt;auto&lt;/span&gt; result) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;try&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="comment"&gt;// 忽略返回值&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; result.&lt;span class="built_in"&gt;get_or_throw&lt;/span&gt;();&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125; &lt;span class="built_in"&gt;catch&lt;/span&gt; (std::exception &amp;amp;e) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;func&lt;/span&gt;(e);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;return&lt;/span&gt; *&lt;span class="keyword"&gt;this&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="function"&gt;Task &amp;amp;&lt;span class="title"&gt;finally&lt;/span&gt;&lt;span class="params"&gt;(std::function&amp;lt;&lt;span class="type"&gt;void&lt;/span&gt;()&amp;gt; &amp;amp;&amp;amp;func)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;task id = &amp;quot;&lt;/span&gt; + std::&lt;span class="built_in"&gt;to_string&lt;/span&gt;(task_id));&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; std::cout &amp;lt;&amp;lt; handle.&lt;span class="built_in"&gt;address&lt;/span&gt;() &amp;lt;&amp;lt; std::endl;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; handle.&lt;span class="built_in"&gt;promise&lt;/span&gt;().&lt;span class="built_in"&gt;on_completed&lt;/span&gt;([func](&lt;span class="keyword"&gt;auto&lt;/span&gt; result) &amp;#123; &lt;span class="built_in"&gt;func&lt;/span&gt;(); &amp;#125;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;return&lt;/span&gt; *&lt;span class="keyword"&gt;this&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="function"&gt;&lt;span class="keyword"&gt;explicit&lt;/span&gt; &lt;span class="title"&gt;Task&lt;/span&gt;&lt;span class="params"&gt;(std::coroutine_handle&amp;lt;promise_type&amp;gt; handle)&lt;/span&gt; &lt;span class="keyword"&gt;noexcept&lt;/span&gt;: handle(handle), task_id(cnt)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt; &amp;#123;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; ++cnt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;Construct from handle, task id = &amp;quot;&lt;/span&gt; + std::&lt;span class="built_in"&gt;to_string&lt;/span&gt;(task_id));&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; std::cout &amp;lt;&amp;lt; handle.&lt;span class="built_in"&gt;address&lt;/span&gt;() &amp;lt;&amp;lt; std::endl;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;Task&lt;/span&gt;(Task &amp;amp;&amp;amp;task) &lt;span class="keyword"&gt;noexcept&lt;/span&gt;: &lt;span class="built_in"&gt;handle&lt;/span&gt;(std::&lt;span class="built_in"&gt;exchange&lt;/span&gt;(task.handle, &amp;#123;&amp;#125;)), &lt;span class="built_in"&gt;task_id&lt;/span&gt;(cnt)&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; ++cnt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;Move Construct from task, task id = &amp;quot;&lt;/span&gt; + std::&lt;span class="built_in"&gt;to_string&lt;/span&gt;(task.task_id) &amp;lt;&amp;lt; &lt;span class="string"&gt;&amp;quot;-&amp;gt;&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; std::&lt;span class="built_in"&gt;to_string&lt;/span&gt;(task_id));&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; std::cout &amp;lt;&amp;lt; handle.&lt;span class="built_in"&gt;address&lt;/span&gt;() &amp;lt;&amp;lt; std::endl;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;Task&lt;/span&gt;(Task &amp;amp;) = &lt;span class="keyword"&gt;delete&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; Task &amp;amp;&lt;span class="keyword"&gt;operator&lt;/span&gt;=(Task &amp;amp;) = &lt;span class="keyword"&gt;delete&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; ~&lt;span class="built_in"&gt;Task&lt;/span&gt;() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; (handle) handle.&lt;span class="built_in"&gt;destroy&lt;/span&gt;();&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;private&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; std::coroutine_handle&amp;lt;promise_type&amp;gt; handle;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="type"&gt;static&lt;/span&gt; std::atomic&amp;lt;&lt;span class="type"&gt;int&lt;/span&gt;&amp;gt; cnt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="type"&gt;const&lt;/span&gt; &lt;span class="type"&gt;int&lt;/span&gt; task_id;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="keyword"&gt;template&lt;/span&gt; &amp;lt;&lt;span class="keyword"&gt;typename&lt;/span&gt; T&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;std::atomic&amp;lt;&lt;span class="type"&gt;int&lt;/span&gt;&amp;gt; Task&amp;lt;T&amp;gt;::cnt = &lt;span class="number"&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt;Task&amp;lt;&lt;span class="type"&gt;int&lt;/span&gt;&amp;gt; &lt;span class="title"&gt;simple_task2&lt;/span&gt;&lt;span class="params"&gt;()&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;task 2 start ...&amp;quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;using&lt;/span&gt; &lt;span class="keyword"&gt;namespace&lt;/span&gt; std::chrono_literals;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; std::this_thread::&lt;span class="built_in"&gt;sleep_for&lt;/span&gt;(&lt;span class="number"&gt;1&lt;/span&gt;s);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;task 2 returns after 1s.&amp;quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;co_return&lt;/span&gt; &lt;span class="number"&gt;2&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt;Task&amp;lt;&lt;span class="type"&gt;int&lt;/span&gt;&amp;gt; &lt;span class="title"&gt;simple_task3&lt;/span&gt;&lt;span class="params"&gt;()&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;in task 3 start ...&amp;quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;using&lt;/span&gt; &lt;span class="keyword"&gt;namespace&lt;/span&gt; std::chrono_literals;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; std::this_thread::&lt;span class="built_in"&gt;sleep_for&lt;/span&gt;(&lt;span class="number"&gt;2&lt;/span&gt;s);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;task 3 returns after 2s.&amp;quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;co_return&lt;/span&gt; &lt;span class="number"&gt;3&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt;Task&amp;lt;&lt;span class="type"&gt;int&lt;/span&gt;&amp;gt; &lt;span class="title"&gt;simple_task&lt;/span&gt;&lt;span class="params"&gt;()&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;task start ...&amp;quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;auto&lt;/span&gt; result2 = &lt;span class="keyword"&gt;co_await&lt;/span&gt; &lt;span class="built_in"&gt;simple_task2&lt;/span&gt;();&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;returns from task2: &amp;quot;&lt;/span&gt; + std::&lt;span class="built_in"&gt;to_string&lt;/span&gt;(result2));&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;auto&lt;/span&gt; result3 = &lt;span class="keyword"&gt;co_await&lt;/span&gt; &lt;span class="built_in"&gt;simple_task3&lt;/span&gt;();&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;returns from task3: &amp;quot;&lt;/span&gt; + std::&lt;span class="built_in"&gt;to_string&lt;/span&gt;(result3));&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;co_return&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt; + result2 + result3;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="function"&gt;&lt;span class="type"&gt;int&lt;/span&gt; &lt;span class="title"&gt;main&lt;/span&gt;&lt;span class="params"&gt;()&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;auto&lt;/span&gt; simpleTask = &lt;span class="built_in"&gt;simple_task&lt;/span&gt;();&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; std::cout &amp;lt;&amp;lt; &lt;span class="string"&gt;&amp;quot;======================&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; std::endl;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; simpleTask.&lt;span class="built_in"&gt;then&lt;/span&gt;([](&lt;span class="type"&gt;int&lt;/span&gt; i) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;simple task end: &amp;quot;&lt;/span&gt; + std::&lt;span class="built_in"&gt;to_string&lt;/span&gt;(i));&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;).&lt;span class="built_in"&gt;catching&lt;/span&gt;([](std::exception &amp;amp;e) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;error occurred&amp;quot;&lt;/span&gt; + std::string&amp;#123;e.&lt;span class="built_in"&gt;what&lt;/span&gt;()&amp;#125;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; std::cout &amp;lt;&amp;lt; &lt;span class="string"&gt;&amp;quot;======================&amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; std::endl;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;try&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;auto&lt;/span&gt; i = simpleTask.&lt;span class="built_in"&gt;get_result&lt;/span&gt;();&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;simple task end from get: &amp;quot;&lt;/span&gt; + std::&lt;span class="built_in"&gt;to_string&lt;/span&gt;(i));&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125; &lt;span class="built_in"&gt;catch&lt;/span&gt; (std::exception &amp;amp;e) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="built_in"&gt;debug&lt;/span&gt;(&lt;span class="string"&gt;&amp;quot;error: &amp;quot;&lt;/span&gt; + std::string&amp;#123;e.&lt;span class="built_in"&gt;what&lt;/span&gt;()&amp;#125;);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;h2 id="运行结果分析"&gt;&lt;a href="#运行结果分析" class="headerlink" title="运行结果分析"&gt;&lt;/a&gt;运行结果分析&lt;/h2&gt;&lt;figure class="highlight cpp"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="gutter"&gt;&lt;pre&gt;&lt;span class="line"&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;89&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;90&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;91&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;92&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;93&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;94&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;95&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;96&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;97&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;98&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;99&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;100&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;101&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;102&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;103&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;104&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;105&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;106&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;107&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;108&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;109&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;110&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre&gt;&lt;span class="line"&gt;ASM generation compiler returned: &lt;span class="number"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;Execution build compiler returned: &lt;span class="number"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;Program returned: &lt;span class="number"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 这里通过 auto simpleTask = simple_task(); 构建第一个 Task1 0x5562ea17feb0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;250&lt;/span&gt; Task: Construct from handle, task id = &lt;span class="number"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;0x5562ea17feb0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 构建协程类第一步 initial_suspend&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;100&lt;/span&gt; initial_suspend: &lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 这里因为 suspend_never 所以继往下走&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;295&lt;/span&gt; simple_task: task start ...&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 通过 auto result2 = co_await simple_task2(); 构建第二个 Task2 0x5562ea180fe0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;250&lt;/span&gt; Task: Construct from handle, task id = &lt;span class="number"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;0x5562ea180fe0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;100&lt;/span&gt; initial_suspend: &lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;279&lt;/span&gt; simple_task2: task &lt;span class="number"&gt;2&lt;/span&gt; start ...&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;282&lt;/span&gt; simple_task2: task &lt;span class="number"&gt;2&lt;/span&gt; returns after &lt;span class="number"&gt;1&lt;/span&gt;s.&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 一直走到 co_return 2; 进入 TaskPromise::return_value&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;126&lt;/span&gt; return_value: &lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 通过 result = Result&amp;lt;ResultType&amp;gt;(std::move(value)); 用 value(2) 构建了一个 Result&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;26&lt;/span&gt; Result: Construct from value&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 中间调了 completion.notify_all(); 但是这里没有 wait&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 继续在 TaskPromise::return_value 中 notify_callbacks();&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;181&lt;/span&gt; notify_callbacks: &lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// co_return 之后这个协程 0x5562ea180fe0 就结束了 (还没释放，因为 finial 是 suspend_always)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;105&lt;/span&gt; final_suspend: &lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 这里把 co_return 的结果给到 Task1 的 TaskPromise&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;170&lt;/span&gt; await_transform: &lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// await_transform 返回一个 TaskAwaiter, 把刚刚的 Task2 存起来了（移动拷贝）&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;257&lt;/span&gt; Task: Move Construct from task, task id = &lt;span class="number"&gt;1&lt;/span&gt;-&amp;gt;&lt;span class="number"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;0x5562ea180fe0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;55&lt;/span&gt; TaskAwaiter: Construct from task&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 这里先判断 ready, 直接返回 false&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;70&lt;/span&gt; await_ready: &lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// false 的情况下需要 suspend (注意这里传入的参数 handle 是 Task1 的 handle)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;76&lt;/span&gt; await_suspend: &lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;0x5562ea17feb0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 这里 task.finally([handle]() &amp;#123; 就是刚刚存起来的 Task2&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 传了一个回调去 handle.resume();&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;241&lt;/span&gt; finally: task id = &lt;span class="number"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;0x5562ea180fe0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// handle.promise().on_completed([func](auto result) &amp;#123; func(); &amp;#125;);&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;149&lt;/span&gt; on_completed: &lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 这里判断了一下 result 有没有值, 那么这里因为是 Task2 的 Promise &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 所以 result 在刚刚 return_value 填充上了&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;153&lt;/span&gt; on_completed: already has value&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 这里是通过刚刚的回调调到的 Task1 Promise 的 handle.resume()&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;87&lt;/span&gt; await_resume: &lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 这里 return task.get_result(); 这里的 task 是刚刚传到 TaskAwaiter 的 Task2&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;207&lt;/span&gt; get_result: from Task&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;136&lt;/span&gt; get_result: from TaskPromise&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 这里还是一样的 result 是 value(2)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;144&lt;/span&gt; get_result: already has value now&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 这里因为 TaskAwaiter 在 finally 中 resume 了 Task1 的 handle 所以继续进行&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;297&lt;/span&gt; simple_task: returns from task2: &lt;span class="number"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 通过 auto result3 = co_await simple_task3(); 构建 Task3 0x5562ea180fe0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;250&lt;/span&gt; Task: Construct from handle, task id = &lt;span class="number"&gt;3&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;0x5562ea180fe0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 后面 Task3 执行和返回的过程大部分都一样的&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;100&lt;/span&gt; initial_suspend: &lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;287&lt;/span&gt; simple_task3: in task &lt;span class="number"&gt;3&lt;/span&gt; start ...&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;290&lt;/span&gt; simple_task3: task &lt;span class="number"&gt;3&lt;/span&gt; returns after &lt;span class="number"&gt;2&lt;/span&gt;s.&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;126&lt;/span&gt; return_value: &lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;26&lt;/span&gt; Result: Construct from value&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;181&lt;/span&gt; notify_callbacks: &lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;105&lt;/span&gt; final_suspend: &lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;170&lt;/span&gt; await_transform: &lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;257&lt;/span&gt; Task: Move Construct from task, task id = &lt;span class="number"&gt;3&lt;/span&gt;-&amp;gt;&lt;span class="number"&gt;4&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;0x5562ea180fe0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;55&lt;/span&gt; TaskAwaiter: Construct from task&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;70&lt;/span&gt; await_ready: &lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;76&lt;/span&gt; await_suspend: &lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;0x5562ea17feb0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;241&lt;/span&gt; finally: task id = &lt;span class="number"&gt;4&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;0x5562ea180fe0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;149&lt;/span&gt; on_completed: &lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;153&lt;/span&gt; on_completed: already has value&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;87&lt;/span&gt; await_resume: &lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;207&lt;/span&gt; get_result: from Task&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;136&lt;/span&gt; get_result: from TaskPromise&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;144&lt;/span&gt; get_result: already has value now&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 一直到这里同样 Task1 通过 Task3 的回调被 resume 继续执行&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;299&lt;/span&gt; simple_task: returns from task3: &lt;span class="number"&gt;3&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 这里 co_return 1 + result2 + result3; 调到 return_value&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;126&lt;/span&gt; return_value: &lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 这里和前面一样同样构建了 Result&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;26&lt;/span&gt; Result: Construct from value&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;181&lt;/span&gt; notify_callbacks: &lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 这里 Task 也走完了, suspend&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;105&lt;/span&gt; final_suspend: &lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;======================&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 刚刚所有的过程只在声明了 simpleTask 之后就执行完了&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 接着调用 simpleTask.then()&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;213&lt;/span&gt; then: task id = &lt;span class="number"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;0x5562ea17feb0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 那这里同样之前已经有值了&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;149&lt;/span&gt; on_completed: &lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;153&lt;/span&gt; on_completed: already has value&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 这里通过 on_completed 调回到 lambda 回调 debug(&amp;quot;simple task end: &amp;quot; + std::to_string(i));&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;306&lt;/span&gt; &lt;span class="built_in"&gt;operator&lt;/span&gt;(): simple task end: &lt;span class="number"&gt;6&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// 这里 catch 了一下异常，但是因为没有异常所以没有触发 debug(&amp;quot;error: &amp;quot; + std::string&amp;#123;e.what()&amp;#125;);&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;227&lt;/span&gt; catching: task id = &lt;span class="number"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;149&lt;/span&gt; on_completed: &lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;153&lt;/span&gt; on_completed: already has value&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;======================&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="comment"&gt;// try-catch 里的逻辑也类似&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;207&lt;/span&gt; get_result: from Task&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;136&lt;/span&gt; get_result: from TaskPromise&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;144&lt;/span&gt; get_result: already has value now&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="number"&gt;313&lt;/span&gt; main: simple task end from get: &lt;span class="number"&gt;6&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="References"&gt;&lt;a href="#References" class="headerlink" title="References"&gt;&lt;/a&gt;References&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="url:" title="https://www.bennyhuo.com/2022/03/19/cpp-coroutines-04-task"&gt;渡劫 C++ 协程（4）：通用异步任务 Task&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;</description></item></channel></rss>