C/C++ 中事件循环的实现在调用堆栈上很好
Implementations for event loop in C/C++ that's nice on the call stack
TL;DR
在 C/C++ 中管理调用堆栈的事件循环的最佳实现是什么?
- 为什么?
- Benchmarks/Comparisons?
- Literature/Publications/Documentation?
事件循环,问题所在
它们是一个简单的概念:等待事件、处理事件、等待更多事件。
我回顾了一些旧项目,发现了一个简单(但有点差)的搜索引擎实现,我对 正确 的实现方式感到好奇事件循环。
当时我做了这样(非常)简化的例子:
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 错误)这就是我认为会很好:
将 main 替换为:
while(1)
if (wait_for_query() == 0) break;
return 0;
- 将
handle_query
的return改为1
但这 实际上 是否提高了堆栈效率?据我所知,while
循环(和一般的循环)仍然会产生汇编语言中的堆栈帧(因为它们都是使用 scope/local variables/etc 执行的分支。)
C/C++ 中事件循环的最佳实现是什么很好地管理调用堆栈?
- 为什么?
- Benchmarks/Comparisons?
- Literature/Publications/Documentation?
备注
这个问题假设一个单线程事件循环。并行的答案也是可以接受的,但我认为一次询问所有问题会有点多;)
开火
实际上,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()
将永远不会完成,直到所有未来事件也完成为止,递归地,这意味着永远不会完成任何事件。这不是你想要的。
详细的可能会很复杂,比如你是怎么得到事件的?它是否阻止?事件是如何发送的? ...等等
TL;DR
在 C/C++ 中管理调用堆栈的事件循环的最佳实现是什么?
- 为什么?
- Benchmarks/Comparisons?
- Literature/Publications/Documentation?
事件循环,问题所在
它们是一个简单的概念:等待事件、处理事件、等待更多事件。
我回顾了一些旧项目,发现了一个简单(但有点差)的搜索引擎实现,我对 正确 的实现方式感到好奇事件循环。
当时我做了这样(非常)简化的例子:
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 错误)这就是我认为会很好:
将 main 替换为:
while(1) if (wait_for_query() == 0) break; return 0;
- 将
handle_query
的return改为1
但这 实际上 是否提高了堆栈效率?据我所知,while
循环(和一般的循环)仍然会产生汇编语言中的堆栈帧(因为它们都是使用 scope/local variables/etc 执行的分支。)
C/C++ 中事件循环的最佳实现是什么很好地管理调用堆栈?
- 为什么?
- Benchmarks/Comparisons?
- Literature/Publications/Documentation?
备注
这个问题假设一个单线程事件循环。并行的答案也是可以接受的,但我认为一次询问所有问题会有点多;)
开火
实际上,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()
将永远不会完成,直到所有未来事件也完成为止,递归地,这意味着永远不会完成任何事件。这不是你想要的。
详细的可能会很复杂,比如你是怎么得到事件的?它是否阻止?事件是如何发送的? ...等等