我正在编写一个事件驱动程序,事件调度是用C语言编写的。该程序使用Python作为扩展模块。我希望允许扩展模块使用
async
/await
语法来实现协程。协程只会与我的程序的部分交互,不涉及 IO。我的 C 调度程序是单线程的,我需要协程在其线程中执行。
在纯Python程序中,我会按原样使用
asyncio
,并让我的程序使用其事件循环来驱动所有事件。但这不是一个选择;我的事件循环需要每秒处理数百万个基于 C 的事件,但我无法承担 Python 的开销。
我尝试编写自己的事件循环实现,将所有调度委托给我的 C 调度程序。我尝试了几种方法:
EventLoop
、Future
、Task
等以模仿 asyncio
的工作原理(减去 IO),以便 call_soon
将调度委托给我的 C 事件循环。这是安全的,但需要一些工作,而且在文档、调试支持、复杂的语义细节和正确性/测试覆盖率方面,我的实现总是不如 asyncio
。Task
中的普通 Future
、asyncio
等,并且仅创建 AbstractEventLoop
的自定义实现,以相同的方式将调度委托给我的 C 事件循环。这非常简单,但我可以看到普通的 EventLoop
访问不明显的内部结构(task._source_traceback
、_asyncgen_finalizer_hook
、_set_running_loop
),所以我的实现仍然是二流的。我还必须依赖未记录的 Handle._run
来实际调用回调。BaseEventLoop
而不是 AbstractEventLoop
进行子类化,事情似乎会变得更简单更好(但文档说我不应该这样做)。不过,我仍然需要Handle._run
。run_forever
:一个普通的asyncio.DefaultEventLoop
,并在那里运行我的所有协程,但协程依赖于我的程序的扩展 API,它不支持并发调用。所以我必须以某种方式让 DefaultEventLoop
在调用 Handle._run()
时暂停我的 C 事件循环。我没有找到实现这一目标的合理方法。关于如何最好地做到这一点有什么想法吗?其他人是如何解决这个问题的?