- 主题:用协程不如用go和rust
这个列表经常是不确定的,比如数据来源于网络或者数据库。
【 在 ylh1969 的大作中提到: 】
: for(i:{1,2,3,4,5})
: cout << i;
: 不是更省事,要协程干啥?
: ...................
--
FROM 117.28.163.*
明白,这只是例子。
不过还是不懂await如何与epoll_wait结合进行协程调度。
【 在 hgoldfish 的大作中提到: 】
: 这个列表经常是不确定的,比如数据来源于网络或者数据库。
:
--
FROM 221.218.60.*
await, co_yield 都只涉及到纤程的切换。
epoll_wait() 是给事件循环纤程用的。这个纤程干的事情和操作系统内核差不多,专门搞调度。
但是纤程不一定要被某个控制中心调度。就像我前面说的,两个纤程可以自主地来回切换。完全不需要第三者的参与。这个时候,epoll_wait() 就没有用了。
事实上,我之前还考虑过完全没有事件循环,几个纤程自己内部任意协调的玩法。或者一次性从 epoll_wait() 返回多个事件,然后唤醒几个相关的纤程,让这几个纤程自己内部搞定完再返回事件循环的。不过不太好实现。API 不好弄。
【 在 ylh1969 的大作中提到: 】
: 明白,这只是例子。
: 不过还是不懂await如何与epoll_wait结合进行协程调度。
--
修改:hgoldfish FROM 117.28.163.*
FROM 117.28.163.*
看了你的例子,就是一些语法变化,如parse,只不过把主程序和子程序掉了个个。对性能没有大的影响。
那个数据库洗数据的例子,协程也不如多线程处理的更好。
最需要协程的,就是同步IO异步化,这躲不掉事件处理。
想不出来C++的协程怎么处理的。
C的协程处理这个问题简单而直观。
只不过目前还没有办法把第三方库的底层IO给解放出来,如数据库的IO。
【 在 hgoldfish 的大作中提到: 】
: await, co_yield 都只涉及到纤程的切换。
: epoll_wait() 是给事件循环纤程用的。这个纤程干的事情和操作系统内核差不多,专门搞调度。
: 但是纤程不一定要被某个控制中心调度。就像我前面说的,两个纤程可以自主地来回切换。完全不需要第三者的参与。这个时候,epoll_wait() 就没有用了。
: ...................
--
修改:ylh1969 FROM 221.218.60.*
FROM 221.218.60.*
协程本来就只是异步函数的一种写法而已啊。
性能是另外的事情。应该通过算法来提升。
另外我一直强调说协程是(纤程,线程,进程)三者的抽象。像 golang 的协程和 python 的协程实现就不太一样。
【 在 ylh1969 的大作中提到: 】
: 看了你的例子,就是一些语法变化,如parse,只不过把主程序和子程序掉了个个。对性能没有大的影响。
: 那个数据库洗数据的例子,协程也不如多线程处理的更好。
: 最需要协程的,就是同步IO异步化,这躲不掉事件处理。
: ...................
--
FROM 117.28.163.*
【 在 hgoldfish 的大作中提到: 】
: 协程本来就只是异步函数的一种写法而已啊。
: 性能是另外的事情。应该通过算法来提升。
: 另外我一直强调说协程是(纤程,线程,进程)三者的抽象。像 golang 的协程和 python 的协程实现就不太一样。
: ...................
还是没有解决异步IO的问题。
思考了一下,在C++协程里,co_yield没有出现context,不知道yield跑哪去了。
所以没办法调度。
不像C的协程,它不是抽象的,是具象的,有一个开放的ucontext,想放哪放哪,搁队列里也行,做自变量提交给函数也行,放epoll里也行。这样怎么调度都方便。
其他语言的也是,如果想调度它,得拿到一个实体,才可以耍。他们太抽象了,看不见摸不着的。
为什么不可以自己调度线程?就是因为不提供线程的实体。
--
修改:ylh1969 FROM 221.218.60.*
FROM 221.218.60.*
【 在 ylh1969 的大作中提到: 】
: 还是没有解决异步IO的问题。
: 思考了一下,在C++协程里,co_yield没有出现context,不知道yield跑哪去了。
: 所以没办法调度。
: ...................
具体看一个调度实例:
pthread_t tid=pthread_self();
resource *rs=tpool.pool;
for(ret=0;ret<tpool.num;ret++,rs++) { //从线程池找本线程的ucontext
if(tid == rs->tid) break;
}
if(ret>=tpool.num) return THREAD_ESCAPE;
task=(TCB *)rs->tc.uc_link;
........
ret=do_epoll(task,0,flg);//ucontext put in epoll
ret=swapcontext(&task->uc,&rs->tc);//uc是当前协程的context,tc是母线程的context,这就是yield了。
--
修改:ylh1969 FROM 221.218.60.*
FROM 221.218.60.*
c++20 里面会把 co_yield 转换成真正的调度代码啊。
转换成 c/asm 代码,co_yield 就是个 return 语句。也就是返回它的调用者。
而调用者用 co_await 切换到 generator 刚才退出的位置继续执行。
这就是最简单的纤程调度了啊。只有两个纤程,相互跳来跳去。
有了这个最简单的模型,再推广到更广泛的应用领域去。比如 c++20 的协程没说不能多线程。
【 在 ylh1969 的大作中提到: 】
: 还是没有解决异步IO的问题。
: 思考了一下,在C++协程里,co_yield没有出现context,不知道yield跑哪去了。
: 所以没办法调度。
: ...................
--
FROM 117.28.163.*
你思维一直没跳出来。。
你考虑一个问题啊。假如。你在是内核里面实现协程调度呢?
epoll() 这些都没有了。也没有 ucontext 帮我搞啥协程切换。
内核里面有大量的异步工作的。比如从磁盘读数据,使用 DMA 向网卡写数据,从键盘中断读数据。所以内核完全可以多多使用协程。
同时现代 CPU 又是多核的。所以这个协程还不能只跑在单核。。
那现在你要怎么样实现你的协程框架呢?
想明白了,恭喜!你已经会写操作系统内核了。
【 在 ylh1969 的大作中提到: 】
: 具体看一个调度实例:
: pthread_t tid=pthread_self();
: resource *rs=tpool.pool;
: ...................
--
修改:hgoldfish FROM 117.28.163.*
FROM 117.28.163.*
【 在 hgoldfish 的大作中提到: 】
: 你思维一直没跳出来。。
: 你考虑一个问题啊。假如。你在是内核里面实现协程调度呢?
: epoll() 这些都没有了。也没有 ucontext 帮我搞啥协程切换。
: ...................
12楼的问题怎么解决?
--
FROM 221.218.60.*