对于对其他语言(Python/JavaScript)有一定异步经验的人来说,当谈论异步/等待时,总是会假设在某个地方有一个事件循环。但是对于C++,我已经浏览了文档,没有找到任何讨论事件循环的地方。为什么会这样呢?
对于Node,它只有一个默认的事件循环。对于Python,如果需要,您可以创建多个。但是对于C++,这个事件循环是不是和Node一样呢?或者出于某种原因,我们根本不需要它吗?
发布于 2021-02-20 00:42:22
Python和JavaScript不处理CPU线程(好吧,Python可以处理线程,但这里不相关,因为Python线程本身并不是可等待的)。所以他们用“事件循环”来伪装线程。
C++是一种低级语言,它知道什么是CPU线程,并期望使用它们。因此,当您在某个表达式上执行co_await时,您通常是在等待(可能)在另一个线程中发生的进程。
当然,您可以使用事件循环来伪造线程,并创建一些使用事件循环处理的可等待类型。但这通常不是C++程序员对异步处理所做的事情。
在C++协程中,恢复执行协程的方式完全取决于您所使用的可等待类型。它控制着函数恢复的调度。C++中的大多数可等待对象将使用某种形式的CPU线程(最常见的方法是在执行它正在等待的异步进程的线程上调用协程)。其他的可能有某种类型的事件循环或其他东西。但重点是,这是产生你所等待的值的东西的函数,而不是协程本身。
发布于 2021-02-20 00:33:02
协程不需要事件循环。
当计算机读取co_await时,它会跳转到称为协程的函数,并保存它的所有帧(局部变量、值等等)。
这里的神奇之处在于,下一次调用协程时,您会回到这种状态。正如你所看到的,不需要事件循环,只需要一个地方来存储这个帧。
发布于 2021-02-20 04:22:39
C++中没有事件循环,线程与协程的关系也很小。
当您在C++中执行co_await时,函数的执行被挂起,代码继续执行调用者,就像函数已经返回一样。实际上,它是这样实现的。co_await将更改协程的内部状态机并返回。
当代码显式恢复函数时,将恢复执行。
这就是协作多任务处理。对执行的控制是显式的和可预测的。
现在,使用大多数库,您不必回调要恢复的协程。这就是执行者的用武之地。它们有点像事件循环,但在库中,而不是在语言中烘焙。用户代码也可以实现它们,您可以针对不同的用例使用不同的代码。它们通常会调度协程的执行,也可以管理多个线程来一次执行其中的许多线程。
例如,您可以完全在线程池的顶部实现一个executor。等待io的大型操作不需要为自己阻塞线程,它将启动io操作并将线程返回给其他任务。在内部,io操作将把协程调度回线程池中进行恢复。
另一个例子是linux上的io_uring,它是新的async io api。您可以使用executor包装工具,并将io操作作为协程运行。从技术上讲,你不需要线程来做这件事。对co_await的调用将简单地调度io操作,一旦内核将结果入队,协程将恢复。
https://stackoverflow.com/questions/66281348
复制相似问题