由于搜索出来的帖子,都是老版本的实验协程,很多老的代码已经失去参考性,并且很复杂,所以就自己研究了一下。

 1 #include <iostream>
2 #include <coroutine>
3 #include <thread>
4
5 template<typename _Ty>
6 struct cocontext {
7 struct promise_type;
8 using _Hty = std::coroutine_handle<promise_type>;
9 struct promise_type {
10 // 只要一个函数的返回值是 cocontext<T>,这个函数内存在co_await co_yield co_return这3个语法糖
11 // 就会第一时间调用 get_return_object
12 cocontext get_return_object() {
13 return { _Hty::from_promise(*this) };
14 }
15
16 // 协程异常时抛出到这里,关于异常,见仁见智,反正我是不用的。
17 void unhandled_exception() { std::terminate(); }
18
19 // co_await co_yield co_return 之前回调,只回调一次,它在get_return_object之后回调
20 auto initial_suspend() { return std::suspend_never{}; }
21
22 // 协程函数返回之后,回调这里
23 auto final_suspend() { return std::suspend_always{}; }
24
25 // 如果函数里没有co_return,必须实现return_void,与之相对的还有一个return_value,类似yield_value
26 void return_void() {}
27
28 // 如果函数里有co_yield,必须实现yield_value,这其实并不难理解,co_yield把数据传到参数,然后我储存在_Val里而已
29 auto yield_value(const _Ty &val) {
30 _Val = val;
31 return std::suspend_always{};
32 }
33 _Ty _Val;
34 };
35
36 // 如果 await_ready 返回true,它就会继续执行,所以理论上来说,要模拟异步场景,都只会是return false
37 bool await_ready() const{ return false; }
38
39 // await_suspend是可以有参数的,它还可以是 void await_suspend(std::coroutine_handle<cocontext> handle);
40 // 在co_await co_yield co_return时,首先会调用这里,也就是可以根据情况直接在这里进行handle.resume();
41 void await_suspend() {}
42
43 // 下面是我自己的实现
44 cocontext& resume() { if (!_Handle.done())_Handle.resume(); return *this; }
45 operator _Ty() const { return _Handle.promise()._Val; }
46
47 _Hty _Handle;
48 };
49
50 int main()
51 {
52 auto test = []()->cocontext<int> { for (int i = 0; i < 10; i++) co_yield i; };
53 auto c = test();
54 std::cout << (int)c << std::endl; // 0
55 std::cout << (int)c.resume() << std::endl; // 1
56 std::cout << (int)c.resume() << std::endl; // 2
57 std::cout << (int)c.resume() << std::endl; // 3
58 std::cout << (int)c.resume() << std::endl; // 4
59
60 std::thread([&]() {
61 // 协程真正有意思的地方是,它可以由不同的线程去resume,这会很有意义。
62 std::cout << (int)c.resume() << std::endl; // 5
63 std::cout << (int)c.resume() << std::endl; // 6
64 std::cout << (int)c.resume() << std::endl; // 7
65 std::cout << (int)c.resume() << std::endl; // 8
66 std::cout << (int)c.resume() << std::endl; // 9
67
68 // 这里依旧输出9,上面一个c.resume()之后,test函数已经跳出循环返回了,已经满足了_Handle.done(),不会再继续真正的_Handle.resume();
69 std::cout << (int)c.resume() << std::endl;
70 }).join();
71
72 }
73
74 /*
75 后话:
76 C++ 20所谓的协程,实际上在我看来,更像是语法糖内部包含了一堆回调函数
77 并且这些回调函数得让程序员自己去完全实现,这确实是C++的风格,
78 但说实在的,我相信搞得清楚这些东西的人,都不会太喜欢这种风格。
79
80 虽然我的例子中 cocontext是基本可重用的类型,但我依旧没感觉这种形式为我的程序带来了多少便利。
81 情况还是那个情况,这个东西用起来并不方便,程序员从一开始就要考虑到所有细节,
82 可能最终很多细节考虑之后,用起来还是一大堆代码,到时候可能写着写着把递归逻辑搞成线性逻辑了,然后感叹一句,“我是SB,我TM用个P的协程!”。
83 */

最新文章

  1. Foreach遍历
  2. word record about IR target detecting and tracking
  3. laravel excel迁移到lumen
  4. ios 第三方登录
  5. python to be linux daemon
  6. Rs2008内存管理策略
  7. hdu1505 dp
  8. iOS开发环境C语言基础
  9. 浅析:setsockopt()改善socket网络程序的健壮性
  10. Spring MVC SimpleUrlHandlerMapping example
  11. [leetcode] 401. Binary Watch
  12. HDU 3853 LOOPS 可能性dp(水
  13. Android hook神器frida(一)
  14. Cracking the Coding Interview 题目分析笔记—— Array and String
  15. Linux多进程编程实例
  16. 原创分享!SharePoint母版页修改(实战)
  17. Win10 Service&#39;MongoDB Server&#39; failed to start. Verify that you have sufficient privileges to start system services【简记】
  18. bittorrent 学习(四) tracker peer通讯
  19. Java类更改常量后编译不生效
  20. Python __slots__ 作用

热门文章

  1. 8.18考试总结[NOIP模拟43]
  2. 2021.8.11考试总结[NOIP模拟36]
  3. Netfilter和iptables介绍
  4. 【Go语言学习笔记】Go的函数
  5. prometheus(7)之数据类型与PromQL语法
  6. js深拷贝你还不会吗
  7. [第二章]c++学习笔记2(类和对象的基础3)
  8. OOP 4.21晚 指针知识点
  9. Python基础(@property)
  10. [atARC125F]Tree Degree Subset Sum