如何避免在红宝石扩展中违反交叉线程?
-
04-10-2019 - |
题
我正在编写C扩展名,并在Ruby和异步I/O库之间提供接口。通过我的代码运行测试时,我经常会遇到错误(但不限于):
[BUG] cross-thread violation in rb_thread_schedule()
异步IO意味着我的C扩展名需要从多个线程(而不是主解释器线程)向Ruby传递消息。在此过程中,如何避免这些违规行为?
解决方案
对于Ruby 1.8.x,避免错误的唯一方法是显而易见的 - 仅调用主解释器线程中的Ruby/C API。我相信这也适用于Ruby 1.9.x,但我没有使用它,也不知道其本机线程支持如何改变事物。您需要使用生产者/消费者模式将多个本机线程直接调用API,将请求从次级本机线程传递到主解释器线程中的代码。理想情况下是这样做的,而不会不必要地阻止其他红宝石绿色线。如果您查看Ruby的实现,Ruby Green Thread Scheduler实际上是一个 select()
环形。这表明以下整体结构:
- 创建管道或其他IPC机制,该机制提供真实
select()
-able文件描述符。 - 产卵本地线并为它们提供管道的写入端。
- 在主解释器线程中,输入呼叫的事件循环
rb_thread_wait_fd()
在管道的读取端。这将允许Ruby Green线程调度程序运行其他绿色线程。 - 当您的次级本地线程要求主线程请求时,它们会排队并写入管道,唤醒运行事件循环的绿色线程。
看 rb_io_sysread()
(实施 IO#sysread
)可能是Ruby代码库中最简单的干净IO使用功能。
不隶属于 StackOverflow