测试代码
#include <coroutine>
#include <iostream>
/**
 * @brief 协程特定返回类型
 */
struct task {
   
  struct promise_type {
   
    std::suspend_never initial_suspend() noexcept {
   
      std::cout << " 4, initial_suspend " << std::endl << std::endl;
      return {
   };
    }
    std::suspend_never final_suspend() noexcept {
   
      std::cout << "20, final_suspend " << std::endl;
      return {
   };
    }
    void unhandled_exception() noexcept {
   }
    task get_return_object() noexcept {
   
      std::cout << " 2, get_return_object " << std::endl;
      auto tk = task{
   std::coroutine_handle<promise_type>::from_promise(*this)};
      return tk;
    }
    void return_value(int v) noexcept {
   
      std::cout << "19, return_value: " << v << std::endl << std::endl;
    }
    std::suspend_always yield_value(std::string&& from) noexcept {
   
      std::cout << "14, yield_value: " << from << std::endl;
      value_ = std::move(from);
      return {
   };
    }
    std::string value_;
  };
  std::coroutine_handle<promise_type> coro_;
  task(std::coroutine_handle<promise_type> h) : coro_(h) {
   
    std::cout << " 3, task construct " << std::endl;
  }
  ~task() {
    std::cout << "22, task deconstruct " << std::endl; }
  std::string value() {
    return coro_.promise().value_; }
};
/**
 * @brief 协程 co_await关键字需要的awaitable
 */
struct awaiter {
   
  awaiter() {
    std::cout << " 6, awaiter construct" << std::endl; }
  ~awaiter() {
    std::cout << "11, awaiter deconstruct" << std::endl; }
  bool await_ready() noexcept {
   
    std::cout << " 7, await_ready " << std::endl;
    return false;
  }
  void await_resume() noexcept {
   
    std::cout << "10, await_resume " << std::endl;
  }
  void await_suspend(std::coroutine_handle<>) noexcept {
   
    std::cout << " 8, await_suspend " << std::endl;
  }
};
/**
 * @brief 协程函数
 * @return 协程特定返回类型
 */
task do_by_coroutine() {
   
  std::cout << " 5, before co_await " << std::endl;
  co_await awaiter{
   };
  std::cout << "12, after co_await " << std::endl << std::endl;
  std::cout << "13, before co_yield " << std::endl;
  co_yield "123";
  std::cout << "17, after co_yield " << std::endl << std::endl;
  std::cout << "18, before co_return " << std::endl;
  co_return 3;
}
int main() {
   
  std::cout << " 1, main start" << std::endl;
  auto result = do_by_coroutine();
  std::cout << " 9, resume co_await-suspend " << std::endl;
  result.coro_.resume();
  std::cout << "15, get yield_value: " << result.value() << std::endl;
  std::cout << "16, resume co_yield-suspend " << std::endl;
  result.coro_.resume();
  std::cout << "21, main end" << std::endl;
  return 0;
}
 运行输出
 1, main start
 2, get_return_object
 3, task construct
 4, initial_suspend
 5, before co_await
 6, awaiter construct
 7, await_ready
 8, await_suspend
 9, resume co_await-suspend
10, await_resume
11, awaiter deconstruct
12, after co_await
13, before co_yield
14, yield_value: 123
15, get yield_value: 123
16, resume co_yield-suspend
17, after co_yield
18, before co_return
19, return_value: 3
20, final_suspend
21, main end
22, task deconstruct
 运行输出解读
第一块 1~4
调用协程函数do_by_coroutine,协程进入准备阶段。
 先调用get_return_object构造协程特定返回对象,在函数get_return_object中构造并返回协程特定返回对象task。
 紧接着调用initial_suspend初始化协程状态,文中为不挂起。
 到此协程准备结束。
第二块 5~12
本块 属于最讲究的co_await操作符使用。
 开始协程do_by_coroutine执行,先构造出awaiter对象,接着判断await_ready状态,文中是false,属于未ready状态,所以紧接着调用await_suspend,协程被挂起。
 因为协程被挂起,所以从协程函数do_by_coroutine中跳出,往下执行以下语句:
std::cout << " 9, resume co_await-suspend " << std::endl;
result.coro_.resume();
然后协程被恢复,所以又跳回协程函数do_by_coroutine中,对应的await_resume函数被执行。
 到此co_await awaiter{} 这一行  执行结束,awaiter对象被析构。打印出 “12, after co_await”。
第三块 13~17
本块 属于较为讲究的co_yield操作符使用。
 目前还在协程函数do_by_coroutine中,所以接着执行co_yield “123” ,对应的yield_value函数被执行,同时yield_value形参from被设置为“123”。上篇文中提到co_yield是co_await的变体,且文中yield_value返回的是suspend_always,所以协程又一次被挂起。
 因为协程被挂起,所以从协程函数do_by_coroutine中跳出,从第一句 result.coro_.resume() 处接着往下执行:
std::cout << "15, get yield_value: " << result.value() << std::endl;
std::cout << "16, resume co_yield-suspend " << std::endl;
result.coro_.resume();
然后协程被恢复,所以又跳回协程函数do_by_coroutine中,到此co_yield “123” 这一行 执行结束,打印出 “17, after co_yield”。
第四块 18~19
本块 属于最简单的co_return操作符使用。
 目前还在协程函数do_by_coroutine中,所以co_return 3 被执行,对应的return_value函数被执行。协程函数执行结束。
第五块 20~22
因为第四块中的co_return操作符,所以协程执行结束。本块属于协程结束收尾阶段,final_suspend函数首先被调用。
 main函数结束。
 特定返回类型task的result对象被析构。
 程序退出。
协程跳转
协程最让人难以理解的就是“跳来跳去”。其实理解起来也不难。
 遇到co_return就表示协程结束,不会再有“跳来跳去”。
 遇到co_yield或者co_await,需要看awaitable是 suspend_always还是suspend_never。不过协程通常会被挂起。
 只要被挂起,就需要调用resume才能回到协程函数的“切出点”(调用co_yield或者co_await的那一行)。
 只要被挂起,就会从当前协程函数中跳出,继续从"切入点"的下一行开始执行。
转载:https://blog.csdn.net/qq_15328161/article/details/128554203
 
					