C/C++ 中事件循环的实现在调用堆栈上很好

Implementations for event loop in C/C++ that's nice on the call stack

TL;DR

在 C/C++ 中管理调用堆栈的事件循环的最佳实现是什么?

事件循环,问题所在

它们是一个简单的概念:等待事件、处理事件、等待更多事件。

我回顾了一些旧项目,发现了一个简单(但有点差)的搜索引擎实现,我对 正确 的实现方式感到好奇事件循环。

当时我做了这样(非常)简化的例子:

int wait_for_query();
int handle_query();

int main(int argc, const char** argv) {
  return wait_for_query();
}

int wait_for_query() {
  // Do some stuff
  return handle_query();
}

int handle_query() {
  // Handle it
  // if query is quit, return quit();
  return wait_for_query();
}

int quit() {
  return 0;
}

此实现依靠调用链来实现 "event loop"。我使用引号是因为虽然它在逻辑上是一个事件循环,但调用堆栈会不断增加并且永远不会展开:

                                            wait_for_query____...
                                           /
                       handle_query_______/
                      /
wait_for_query_______/

虽然它有效,但它总是在堆栈上添加新的堆栈帧,最终,在发生足够多的事件后,它会导致 堆栈溢出 错误! (哈哈太元了)。

我想要的是这样的:

                       handle_query           handle_query
                      /            \         /            \
wait_for_query_______/              \_______/              \_____...

到目前为止我得到了什么

我一直听说 OS 只是一个被中断的 while(true) 循环,所以(因为我的 OS 最近没有出现 SO 错误)这就是我认为会很好:

但这 实际上 是否提高了堆栈效率?据我所知,while 循环(和一般的循环)仍然会产生汇编语言中的堆栈帧(因为它们都是使用 scope/local variables/etc 执行的分支。)

C/C++ 中事件循环的最佳实现是什么很好地管理调用堆栈

备注

这个问题假设一个单线程事件循环。并行的答案也是可以接受的,但我认为一次询问所有问题会有点多;)

开火

实际上,while 不会自行生成任何新的堆栈帧。发出 call 指令时会创建堆栈帧。

如果你像你提到的那样 handle_query return 1 ,那么你的循环将不会增加堆栈超过两层 (wait_query+handle_query) 对于它处理的每个事件:

                                  handle_query           handle_query
                                 /            \         /            \
           wait_for_query_______/              \_______/              \_____...
          /
         /
main_loop

这看起来像您正在寻找的堆栈结构。

最初的解决方案基本上已损坏Event loop 看起来像这样:

while (q != QUITE) {
  q = wait_for_query();
  handle_query(q);
}

就这么简单。这实际上与您的描述一致:

They're an easy concept: Wait for an event, handle event, wait for more events.

在初始代码中,从语义上讲,处理事件 handle_query() 将永远不会完成,直到所有未来事件也完成为止,递归地,这意味着永远不会完成任何事件。这不是你想要的。

详细的可能会很复杂,比如你是怎么得到事件的?它是否阻止?事件是如何发送的? ...等等