有次和同事在食堂排队聊到一个有意思的话题,我说任何程序都跑着一个 while (true)
(也可以说 for (;;)
吧),无论是客户端/服务端程序,游戏,还是操作系统,它们都跑着一个 while (true)
。我想这也是 EventLoop 这种设计被大量使用的原因,这再自然不过了:
while (true) {
Event event = get_event(event_queue); // 如果没有事件,get_event 就阻塞
switch (event) {
case event1: handleEvent1(event); break;
case event2: handleEvent2(event); break;
......
}
}
Event 携带的数据都用拷贝,不共享数据,也能保证线程安全。或者如果 Event 里的数据是共享的,那就要设计一种机制保证数据的生命周期和线程安全。
其实我们能在很多软件库里发现这种模式,比如随便找一个多线程任务库或者无栈协程的运行时库,你都能找到一个类似这样的 loop,在这个 loop 里用各种策略调度它们抽象出来的 Task/Future/Promise
。又或者是一些客户端的 UI 框架,比如 Qt 里的 signal/slot
和 QEventLoop
,Android 里的 handler
和 MessageQueue
等等。
我们甚至可以把后端那些微服务架构也认为就是一个个的 loop,Event 就是 request/response
,Event 携带的数据就是 request/response
的 body。
对于一个 Event 我们可以:
- 过滤不想要的事件,就好比后端程序根据特定条件拦截某个 RPC request;
- 对事件排优先级,分发到不同的 handler,好比负载均衡;
- 把事件缓存起来,再次执行,好比重放一个无状态的请求;
- 把事件转换成别的事件发送,好比请求重定向;
- 把多个事件聚合成一个事件
…