- 主题:用协程不如用go和rust
【 在 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.*
【 在 hgoldfish 的大作中提到: 】
: 你思维一直没跳出来。。
: 你考虑一个问题啊。假如。你在是内核里面实现协程调度呢?
: epoll() 这些都没有了。也没有 ucontext 帮我搞啥协程切换。
: ...................
12楼的问题怎么解决?
--
FROM 221.218.60.*
【 在 hgoldfish 的大作中提到: 】
: c++20 里面会把 co_yield 转换成真正的调度代码啊。
: 转换成 c/asm 代码,co_yield 就是个 return 语句。也就是返回它的调用者。
: 而调用者用 co_await 切换到 generator 刚才退出的位置继续执行。
: ...................
多线程协程就得有调度器呀,没想出来怎么使用别的线程的协程。
就如你的数据库洗数据的例子,如果一个协程在一个线程里,一个在另一个线程里,显然,二者就有了并行性,性能就会有优势。
--
修改:ylh1969 FROM 221.218.60.*
FROM 221.218.60.*
【 在 hgoldfish 的大作中提到: 】
: 你思维一直没跳出来。。
: 你考虑一个问题啊。假如。你在是内核里面实现协程调度呢?
: epoll() 这些都没有了。也没有 ucontext 帮我搞啥协程切换。
: ...................
内核调度,就是线程/进程呀,你说的所有异步过程发生在内核,在IO时,肯定会锁死线程/进程,但是别的线程/进程不受影响,在用户态,看起来就是同步IO。
在所有的例子里,协程就是语法糖,就如你说的,性能另说,它不是关键的,必不可少的技术方法。
如果把协程的context封装了,那跟线程又有什么区别呢?你的那些例子用多线程干可能更好。
12楼的例子,就是要在IO时挂起一个协程,而不挂起线程,线程可以为其他协程服务(特别是单线程协程),实现用户级的异步IO,那么必须开放context,不然,挂起谁呢?
--
修改:ylh1969 FROM 221.218.60.*
FROM 221.218.60.*
我是用C的协程,解决同步IO异步化的问题。
原先用回调函数,太繁琐,很难推行到业务逻辑层。人家关心业务,如12楼,对同步异步不感兴趣,也懒得弄。
C++的协程,还不知道怎么和epoll结合解决12楼的问题。
26楼有yield的方案,但是在C++的协程,不知道要把啥东西交给epoll,context被封装了。
如13楼
std::generator<int> generate_numbers(int start, int end) {
for (int i = start; i <= end; ++i) {
do_epoll(context,0,flg);// put context to epoll
co_yield SUSPEND; // 请线程去epoll_wait()等结果。
【 在 munaiyi 的大作中提到: 】
: 是的,但是用c++协程不如用异步方式也许更好。
:
--
修改:ylh1969 FROM 221.218.60.*
FROM 221.218.60.*
要解决12楼问题,只有协程。
对协程系统的要求,必须提供context。
对事件系统的要求,必须能够绑定context。
最好支持多线程,能够各个线程独立的随时的,立即生效的,加入,删除,等待事件队列。
协程本来与线程无关,但是,要想真正实现多线程,就必须有调度,要想调度,就得有context。
【 在 hgoldfish 的大作中提到: 】
: 对啊。协程有时候和线程相比就是模糊不清的。
: 一个线程,在内核空间时碰到 IO 就主动 yield 的纤程,在用户空间时又是因为陷入内核态被调度器切换走的线程。
: 我们完全可以把 syscall 这条指令看成是纤程的 co_yield
: ...................
--
修改:ylh1969 FROM 221.218.60.*
FROM 221.218.60.*
你22楼,我想了很长时间。最后那一段说明了问题的困境。
目前我能够想到的,就是线程对协程的调度。
还得以事件为调度核心,由线程等待事件。当被一个事件激活时,找到关联的context,那里边有协程,就把任务交给这个协程。用resume。之后就是协程的context。
协程在遇到IO未完成时,就把context挂到事件队列,然后yield。之后成了线程的context,继续等待事件。
所谓调度,就是操作context,c的context是显式的,好操作。C++的,或者rust等等,能拿到这个东西吗?
拿不到怎么调度?你最后一段就是这个问题。
12楼的问题,如果是你,怎么解决?
【 在 hgoldfish 的大作中提到: 】
: await, co_yield 都只涉及到纤程的切换。
: epoll_wait() 是给事件循环纤程用的。这个纤程干的事情和操作系统内核差不多,专门搞调度。
: 但是纤程不一定要被某个控制中心调度。就像我前面说的,两个纤程可以自主地来回切换。完全不需要第三者的参与。这个时候,epoll_wait() 就没有用了。
: ...................
--
修改:ylh1969 FROM 221.218.61.*
FROM 221.218.61.*