1

我正在实现一个简单的窗口库作为 Ruby C 扩展。Windows 有一种handle_events!方法可以进入其本机事件循环。

问题是我想要每个窗口和方法块有一个事件循环。我希望该方法立即返回并让循环在单独的线程中运行。实现这一目标的最佳方法是什么?

我尝试使用rb_thread_call_without_gvl来调用事件循环函数,然后使用rb_thread_call_with_gvl来调用窗口的回调,即Procs. 完整的源代码可以在这里找到。

它仍然有效,但不是我想要的:该方法仍然阻塞。Ruby 的线程模型甚至可以做到这一点吗?

4

2 回答 2

0

我有同样的问题要解决。由于 rb_thread_call_with_gvl() 在 1.9.2 中被标记为实验性的并且它不是导出符号,因此我采用了不同的方法:

我调用了阻塞的handle_event!函数来自一个单独的线程。我使用了第二个 ruby​​ 线程,它被阻塞在消息队列中。在消息队列上阻塞时,gvl 被 rb_thread_blocking_region() 释放。

如果现在线程调用handle_event!由于某个事件而被解除阻塞,它将 Proc 调用所需的所有信息拉到一个队列元素中,并将该元素推送到队列中。ruby 线程接收到从 rb_thread_blocking_region() 返回的元素,因此重新获取 gvl 并使用接收到的元素中的信息调用 Proc。

亲切的问候托斯滕

于 2012-07-16T17:27:32.557 回答
0

据我了解,使用rb_thread_call_with_gvl()仍然需要在同一个线程上完成。即:它是关于释放和获取全局锁,而不是真正关于更改线程。例如,长时间运行的 gzip 函数可以在没有锁的情况下运行,以便其他 ruby​​ 线程可以并行运行。

如果您希望在另一个线程上回调您的 Procs,您是否需要为这些 Procs 创建一个 ruby​​ 线程?然后在该线程上,调用使用rb_thread_call_without_gvl()不持有 GVL(允许其他 ruby​​ 线程运行),然后当您在辅助窗口线程上有事件时,调用rb_thread_call_with_gvl()获取锁,然后您应该正确调用 Proc同一个线程。

这就是我理解它的方式......(没有做过很长时间的C扩展。)

于 2013-07-20T10:55:28.027 回答