Does mudo have plans to increase the ability of the coroutine?

154 views
Skip to first unread message

吴迪

unread,
Jun 28, 2021, 2:01:05 PM6/28/21
to Muduo network library
Based on the current reactor code, adding simple scheduling capabilities and context preservation and restore capabilities should be able to implement the coroutine
The general idea is as follows:
1. The whole is divided into three types of coroutines,
  1.1 The main coroutine,does not allocate an execution stack,
  1.2 event_loop coroutine,execute event dispatch and call callback, need to allocate execution stack separately
  1.3 Other coroutines,execute the function set by the user and need to allocate the execution stack separately
2. Each time an io operation is executed, the context of the current function is saved to an io queue, and a timeout callback and an io event ready callback are set. The callback logic is to move the coroutine to the runnable queue.
3. Every time the io operation is executed, go to the runnable queue to find the next coroutine context and switch to this context. If the next runnable coroutine is not found, then switch directly to the coroutine that executes event_loop, if there is an io event is ready, the corresponding callback function will be called back
4. Write coroutine version functions for commonly used io system calls

基于当前的 reactor 代码,在这上面增加简单的调度能力和上下文保存与 restore 能力应该就能实现协程
大致思路如下:
1. 整体分为三种协程,
  1.1 主协程-不分配执行栈,
  1.2 event_loop 协程-执行event dispatch 并调用回调,需要单独分配执行栈
  1.3 其他协程-执行用户设定的 function,需要单独分配执行栈
2. 每次执行 io 操作时,将当前函数的上下文保存到一个 io 队列中,并设置一个超时回调和 io 事件 ready 回调,回调的逻辑是将协程移动到可运行队列。
3. 每次执行 io 操作时,去可运行队列中寻找下一个协程上下文,并切换到这个上下文,如果没有找到下一个可运行的协程,则直接切换到执行 event_loop 的协程,如果有 io 事件 ready,则会回调对应的回调函数
4. 为常用的 io 系统调用编写协程版本的函数

吴迪

unread,
Jun 28, 2021, 2:01:08 PM6/28/21
to Muduo network library

Shuo Chen

unread,
Jun 28, 2021, 2:35:13 PM6/28/21
to Muduo network library
长话短说:首先,我认为 Go 的并发模型非常好用,写起来比基于事件回调的风格思路要顺畅许多;但是,我目前认为在 C/C++ 里搞用纯户态的 coroutine 没有前途。

coroutine 的本质是对 OS thread 的复用,好处是比 thread 更轻量(10 倍以上),memory locality 也更好,一个程序可以有几百上千的线程 vs. 几万的 coroutine。
坏处是 OS / monitor / debugger 失去对程序的观察力,例如 /proc/pid/task 看不到 coroutine,而且 thread-local storage 和 gettid() 也都废掉了。
比如我通过 OS 看到某个某个 thread 死锁或者 busy-loop,其实很难知道具体是哪个 coroutine 出了问题。
一般的 debugger 能看到 OS threads,但看不到你自己实现的 coroutines,特别是当前没有运行的 coroutine。
profiler 也不容易正确找出热点,因为看不到正确的 call stack trace。

根据我这几年所学,我认为正确的做法是让内核做上下文切换,但同时可以把调度的任务放到用户态,这样两方面的好处都占住了。

具体说来,如果 Linux 内核接受了 Google 的 switchto() 系统调用,那么 C/C++ 服务端编程就可以采用 Go 一样的编程模型,大家都轻松很多。

ref.

ps. Google 内部用 switchto() 已经很多年了。这也是我对 C++20 里的协程不感兴趣的原因。

陈硕

Reply all
Reply to author
Forward
0 new messages