<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>C++ on Mer's Blog</title><link>https://merisky.top/tags/c++/</link><description>Recent content in C++ on Mer's Blog</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Mon, 29 May 2023 11:38:32 +0800</lastBuildDate><atom:link href="https://merisky.top/tags/c++/index.xml" rel="self" type="application/rss+xml"/><item><title>如何实现一个最小堆</title><link>https://merisky.top/posts/2906464195/</link><pubDate>Sat, 25 Mar 2023 17:36:41 +0000</pubDate><guid>https://merisky.top/posts/2906464195/</guid><description>&lt;p&gt;本文介绍如何使用 C++ 实现一个通用的、线程安全的最小堆&lt;/p&gt;&#10;&lt;p&gt;顺便一提，写此文的时候突然想到了多年以前（16、17年）盛行的 Mooc，当时国内有很多类似的慕课网站，也有很多优秀的课程，我的基础数据结构和算法就是一位 ACM 铜牌的老师教的，至今受用，但是现在好像很少看到此类网站了，还是比较可惜的。&lt;/p&gt;&#10;&lt;p&gt;进入正题，最小堆本身是一个完全二叉树，保证每一个节点都不会大于其左右子节点，要实现一个最小堆的两个核心函数是 &lt;code&gt;sift_up&lt;/code&gt; 和 &lt;code&gt;sift_down&lt;/code&gt;，用于调整最小堆结构以符合定义。&lt;/p&gt;&#10;&lt;p&gt;首先给出 &lt;code&gt;MinHeap&lt;/code&gt; 的基本定义和成员变量：&lt;/p&gt;&#10;&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;/pre&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre&gt;&lt;span class="line"&gt;&lt;span class="keyword"&gt;template&lt;/span&gt; &amp;lt;std::three_way_comparable T&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;span class="keyword"&gt;class&lt;/span&gt; &lt;span class="title class_"&gt;MinHeap&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; std::shared_mutex mtx;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; std::vector&amp;lt;T&amp;gt; vec;&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;p&gt;这里 &lt;code&gt;vec&lt;/code&gt; 用于保存最小堆的各个节点（完全二叉树很适合用数组保存），而 &lt;code&gt;std::three_way_comparable&lt;/code&gt; 则是对容器元素类型的 &lt;code&gt;concept&lt;/code&gt; 约束，要求元素类型必须是可比较的，毕竟不可比较的话也就没有“最小”的概念了。&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;sift_down&lt;/code&gt; 和 &lt;code&gt;sift_up&lt;/code&gt; 是相反的一组用于调整堆的操作，&lt;code&gt;sift_down&lt;/code&gt; 用于将一个元素向下调整至满足最小堆的条件，&lt;code&gt;sift_up&lt;/code&gt; 则相反，由此可以知道对于任何一个完全二叉数我们只需要上到下执行 &lt;code&gt;sift_down&lt;/code&gt; 或者从下到上执行 &lt;code&gt;sift_up&lt;/code&gt; 就可以使得堆中的每一个节点都满足最小堆的条件&lt;/p&gt;</description></item><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><item><title>C++20 Asio With Boost 获取 B 站徽章（直播间牌子）</title><link>https://merisky.top/posts/173569173/</link><pubDate>Sat, 25 Feb 2023 14:17:24 +0000</pubDate><guid>https://merisky.top/posts/173569173/</guid><description>&lt;p&gt;本文介绍了如何使用 C++20 with Asio (Boost 版本) 完成一个简单的客户端用于获取 B 站徽章。&lt;/p&gt;&#10;&lt;p&gt;强烈推荐昨天发现的一个视频 《Why C++20 is the Awesomest Language for Network Programming》，可以去油管上搜一下，总时长一个小时，比较长但是讲的很好，听的巨舒服，上次有这种感觉还是听那个 c10k 问题的视频。&lt;/p&gt;&#10;&lt;p&gt;总之先看一下程序执行的效果：&lt;/p&gt;&#10;&lt;figure class="highlight bash"&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;/pre&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre&gt;&lt;span class="line"&gt;➜ bili-medal git:(master) ./build/main &amp;#123;my_cookie&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;当前登录账号的 mid 为 29248492&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;当前登陆账号所佩戴的直播间徽章为 &lt;span class="string"&gt;&amp;quot;ASAKI&amp;quot;&lt;/span&gt;, 等级为 15 级&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;p&gt;贴一下主要逻辑：&lt;/p&gt;&#10;&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;/pre&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre&gt;&lt;span class="line"&gt;&lt;span class="function"&gt;awaitable&amp;lt;&lt;span class="type"&gt;void&lt;/span&gt;&amp;gt; &lt;span class="title"&gt;start&lt;/span&gt;&lt;span class="params"&gt;(asio::io_context &amp;amp;ctx, &lt;span class="type"&gt;const&lt;/span&gt; std::string &amp;amp;cookie)&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="type"&gt;const&lt;/span&gt; std::string host = &lt;span class="string"&gt;&amp;quot;api.bilibili.com&amp;quot;&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;// 解析域名&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;auto&lt;/span&gt; [e1, endpoint] = &lt;span class="keyword"&gt;co_await&lt;/span&gt; tcp::&lt;span class="built_in"&gt;resolver&lt;/span&gt;(ctx).&lt;span class="built_in"&gt;async_resolve&lt;/span&gt;(host, &lt;span class="string"&gt;&amp;quot;https&amp;quot;&lt;/span&gt;, use_nothrow_awaitable);&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;// ssl_ctx 用于建立 https 连接&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; ssl::context ssl_ctx &amp;#123;ssl::context::sslv23&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; ssl_socket socket &amp;#123;ctx, ssl_ctx&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;static_assert&lt;/span&gt;(std::is_same_v&amp;lt;std::&lt;span class="type"&gt;decay_t&lt;/span&gt;&amp;lt;&lt;span class="keyword"&gt;decltype&lt;/span&gt;(socket.&lt;span class="built_in"&gt;next_layer&lt;/span&gt;())&amp;gt;, tcp::socket&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="comment"&gt;// 建立 tcp 连接&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; ssl_ctx.&lt;span class="built_in"&gt;set_default_verify_paths&lt;/span&gt;();&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;auto&lt;/span&gt; [e2, _] = &lt;span class="keyword"&gt;co_await&lt;/span&gt; asio::&lt;span class="built_in"&gt;async_connect&lt;/span&gt;(socket.&lt;span class="built_in"&gt;lowest_layer&lt;/span&gt;(), endpoint, use_nothrow_awaitable);&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;// https 握手，建立 https 连接&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;auto&lt;/span&gt; [e3] = &lt;span class="keyword"&gt;co_await&lt;/span&gt; socket.&lt;span class="built_in"&gt;async_handshake&lt;/span&gt;(ssl::stream_base::client, use_nothrow_awaitable);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; std::string mid;&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;// 创建并发送一个 api 请求到 B 站服务器，获得返回结果并解析 mid 字段&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;auto&lt;/span&gt; request = &lt;span class="built_in"&gt;make_request&lt;/span&gt;(http::verb::get, host, &lt;span class="string"&gt;&amp;quot;/x/web-interface/nav&amp;quot;&lt;/span&gt;, cookie);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;auto&lt;/span&gt; response = &lt;span class="keyword"&gt;co_await&lt;/span&gt; &lt;span class="built_in"&gt;async_send_request&lt;/span&gt;(socket, request);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;auto&lt;/span&gt; data = json::&lt;span class="built_in"&gt;parse&lt;/span&gt;(beast::&lt;span class="built_in"&gt;buffers_to_string&lt;/span&gt;(response.&lt;span class="built_in"&gt;body&lt;/span&gt;().&lt;span class="built_in"&gt;data&lt;/span&gt;()));&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; mid = data[&lt;span class="string"&gt;&amp;quot;data&amp;quot;&lt;/span&gt;][&lt;span class="string"&gt;&amp;quot;mid&amp;quot;&lt;/span&gt;].&lt;span class="built_in"&gt;dump&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; std::cout &amp;lt;&amp;lt; &lt;span class="string"&gt;&amp;quot;当前登录账号的 mid 为 &amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; mid &amp;lt;&amp;lt; std::endl;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; std::string medal_id, medal_name, medal_level;&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;// 创建并发送一个 api 请求到 B 站服务器，获得返回结果并解析直播间徽章&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;auto&lt;/span&gt; request = &lt;span class="built_in"&gt;make_request&lt;/span&gt;(http::verb::get, host, &lt;span class="string"&gt;&amp;quot;/x/space/acc/info?mid=&amp;quot;&lt;/span&gt;+mid, cookie);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;auto&lt;/span&gt; response = &lt;span class="keyword"&gt;co_await&lt;/span&gt; &lt;span class="built_in"&gt;async_send_request&lt;/span&gt;(socket, request);&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; &lt;span class="keyword"&gt;auto&lt;/span&gt; data = json::&lt;span class="built_in"&gt;parse&lt;/span&gt;(beast::&lt;span class="built_in"&gt;buffers_to_string&lt;/span&gt;(response.&lt;span class="built_in"&gt;body&lt;/span&gt;().&lt;span class="built_in"&gt;data&lt;/span&gt;()));&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; medal_id = data[&lt;span class="string"&gt;&amp;quot;data&amp;quot;&lt;/span&gt;][&lt;span class="string"&gt;&amp;quot;fans_medal&amp;quot;&lt;/span&gt;][&lt;span class="string"&gt;&amp;quot;medal&amp;quot;&lt;/span&gt;][&lt;span class="string"&gt;&amp;quot;medal_id&amp;quot;&lt;/span&gt;].&lt;span class="built_in"&gt;dump&lt;/span&gt;();&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; medal_level = data[&lt;span class="string"&gt;&amp;quot;data&amp;quot;&lt;/span&gt;][&lt;span class="string"&gt;&amp;quot;fans_medal&amp;quot;&lt;/span&gt;][&lt;span class="string"&gt;&amp;quot;medal&amp;quot;&lt;/span&gt;][&lt;span class="string"&gt;&amp;quot;level&amp;quot;&lt;/span&gt;].&lt;span class="built_in"&gt;dump&lt;/span&gt;();&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt; medal_name = data[&lt;span class="string"&gt;&amp;quot;data&amp;quot;&lt;/span&gt;][&lt;span class="string"&gt;&amp;quot;fans_medal&amp;quot;&lt;/span&gt;][&lt;span class="string"&gt;&amp;quot;medal&amp;quot;&lt;/span&gt;][&lt;span class="string"&gt;&amp;quot;medal_name&amp;quot;&lt;/span&gt;].&lt;span class="built_in"&gt;dump&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; std::cout &amp;lt;&amp;lt; &lt;span class="string"&gt;&amp;quot;当前登陆账号所佩戴的直播间徽章为 &amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; medal_name &amp;lt;&amp;lt; &lt;span class="string"&gt;&amp;quot;, 等级为 &amp;quot;&lt;/span&gt; &amp;lt;&amp;lt; medal_level &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;&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;p&gt;整体流程我觉得是比较清晰的，基本上对 https 请求过程有所了解的话应该能容易能理解这里做了什么。&lt;/p&gt;</description></item><item><title>如何向 STL 算法中传入重载函数</title><link>https://merisky.top/posts/781272769/</link><pubDate>Fri, 01 Jul 2022 04:02:45 +0000</pubDate><guid>https://merisky.top/posts/781272769/</guid><description>&lt;p&gt;本文分享如何向 STL 算法中传入重载函数，来自 Jonathan 2017 年在 Fluent C++ 上发起的一个挑战&lt;/p&gt;&#10;&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;/pre&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre&gt;&lt;span class="line"&gt;The STL is a fantastic tool to make your code more expressive &lt;span class="keyword"&gt;and&lt;/span&gt; more robust. If you’re a C++ developer &lt;span class="keyword"&gt;and&lt;/span&gt; want to become proficient, it is essential that you learn the STL.&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;But there is one &lt;span class="keyword"&gt;case&lt;/span&gt; where we can’t apply STL algorithms right out of the box: when the function passed has overloads.&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;p&gt;大概意思是说 STL 本身非常好用，但是如果传递一个具有重载的函数就会使得 STL 失效。&lt;/p&gt;</description></item><item><title>Manacher's Algorithm（求最长回文子串）</title><link>https://merisky.top/posts/4278205636/</link><pubDate>Sat, 25 Jul 2020 09:47:41 +0000</pubDate><guid>https://merisky.top/posts/4278205636/</guid><description>&lt;p&gt;本文讲述 Manacher 算法（马拉车算法）的原理以及如何利用 Manacher 算法获取最长回文子串。&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;给定一个字符串s，找到这个字符串的最长回文子串&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Example 1:&lt;/strong&gt;&lt;/p&gt;&#10;&lt;figure class="highlight plaintext"&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;/pre&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre&gt;&lt;span class="line"&gt;Input: &amp;quot;babad&amp;quot;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;Output: &amp;quot;bab&amp;quot;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;Note: &amp;quot;aba&amp;quot; is also a valid answer.&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;p&gt;&lt;strong&gt;Example 2:&lt;/strong&gt;&lt;/p&gt;&#10;&lt;figure class="highlight plaintext"&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;/pre&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre&gt;&lt;span class="line"&gt;Input: &amp;quot;cbbd&amp;quot;&lt;/span&gt;&lt;br&gt;&lt;span class="line"&gt;Output: &amp;quot;bb&amp;quot;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;要找到一个字符串中的最长回文子串有以下几种方法：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;暴力搜索，算法复杂度O(N&lt;sup&gt;3&lt;/sup&gt;)&lt;/li&gt;&#10;&lt;li&gt;动态规划，算法复杂度O(N&lt;sup&gt;2&lt;/sup&gt;)&lt;/li&gt;&#10;&lt;li&gt;Manacher算法，算法复杂度O(N)&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;而本文的主角就是Manacher’s algorithm，一起来看看它的实现&lt;/p&gt;&#10;&lt;h2 id="核心思想"&gt;&lt;a href="#核心思想" class="headerlink" title="核心思想"&gt;&lt;/a&gt;核心思想&lt;/h2&gt;&lt;p&gt;Manacher算法的核心思想在于搜索以每个字符为中心的回文子串长度，并利用先前搜索的结果加快后续回文子串长度的计算&lt;/p&gt;&#10;&lt;p&gt;其中从中心向两边搜索是Manacher和动态规划方法相比暴力搜索降低复杂度的关键，而利用先前的搜索结果加快后续回文子串计算则是Manacher算法能够以不可思议的O(N)复杂度完成回文串查找的关键&lt;/p&gt;&#10;&lt;h2 id="过程"&gt;&lt;a href="#过程" class="headerlink" title="过程"&gt;&lt;/a&gt;过程&lt;/h2&gt;&lt;p&gt;以Manacher算法的一个中间过程为例&lt;/p&gt;&#10;&lt;p&gt;&lt;img src="https://merisky.top/images/Manacher-s-Algorithm/%E6%88%AA%E5%B1%8F2020-07-24%2023.54.30.png" loading="lazy" decoding="async" alt="截屏2020-07-24 23.54.30"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;s：&lt;/strong&gt;给定的字符串&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;P：&lt;/strong&gt;手动维护，&lt;code&gt;P[i]&lt;/code&gt;保存以i位置为中心的最长子串长度&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Center：&lt;/strong&gt;当前最近的回文子串中心&lt;/p&gt;</description></item></channel></rss>