c - 在不使用其他功能的情况下释放 C 扩展中的全局 VM 锁

标签 c ruby multithreading

我不明白为什么在发布或获取 Ruby C API 中的 GVL 时需要另一个间接级别。
rb_thread_call_without_gvl()rb_thread_call_with_gvl() 都需要一个只接受一个参数的函数,但情况并非总是如此。 我不想仅仅为了发布 GVL 而将我的参数包装在一个结构中。它使代码的可读性变得复杂,并且需要从 void 指针转换到 void 指针。
在查看 Ruby 的线程代码后,我找到了 GVL_UNLOCK_BEGIN。/GVL_UNLOCK_END与 Python 的 Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS 匹配的宏但我找不到关于它们以及何时可以安全使用它们的文档。
还有 BLOCKING_REGION rb_thread_call_without_gvl() 中使用了宏但我不确定在不调用 rb_thread_call_without_gvl() 本身的情况下将它作为独立使用是否安全。

在执行流程中间安全释放 GVL 而不必调用其他函数的正确方法是什么?

最佳答案

在 Ruby 2.x 中,只有 rb_thread_call_without_gvl API。 GVL_UNLOCK_BEGINGVL_UNLOCK_END 是仅在 thread.c 中定义的实现细节,因此对 Ruby 扩展不可用 .因此,您问题的直接答案是“没有办法在不调用另一个函数的情况下正确安全地释放 GVL”。

以前有一个“基于区域”的 API,rb_thread_blocking_region_begin/rb_thread_blocking_region_end,但是这个 API 在 Ruby 1.9.3 中被弃用并在 Ruby 2.2 中被移除(参见 https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/CAPI_obsolete_definitions CAPI 弃用时间表)。

因此,不幸的是,您被 rb_thread_call_without_gvl 困住了。


也就是说,您可以采取一些措施来缓解疼痛。在标准 C 中,大多数指针和 void * 之间的转换是隐式的,因此您不必添加强制转换。此外,使用指定的初始化语法可以简化参数结构的创建。

因此,你可以这样写

struct my_func_args {
    int arg1;
    char *arg2;
};

void *func_no_gvl(void *data) {
    struct my_func_args *args = data;
    /* do stuff with args->arg... */
    return NULL;
}

VALUE my_ruby_function(...) {
    ...
    struct my_func_args args = {
        // designated initializer syntax (C99) for cleaner code
        .arg1 = ...,
        .arg2 = ...,
    };

    // call without an unblock function
    void *res = rb_thread_call_without_gvl(func_no_gvl, &args, NULL, NULL);
    ...
}

虽然这不能解决您原来的问题,但它至少使它更容易被接受(我希望如此)。

关于c - 在不使用其他功能的情况下释放 C 扩展中的全局 VM 锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36245878/

相关文章:

c - 重新分配问题

c - Windows编写的CentOS上运行C程序

c - PC Lint 警告 537 : Repeated include file

ruby-on-rails - If 语句中额外的 Ruby 行会导致 Haml 出现问题吗?

python - Flask 启动新线程 - RuntimeError : Working outside of request context

c++ 程序在不同的机器上显示出非常不同的内存行为

C++ 'substitute' 用于具有灵活数组成员的结构

mysql - Rails 4 + ActiveRecord : How to merge data from 2 models?

ruby - 如何计算 ruby​​ 中文件上传的内容长度?

java - CORBA 不清楚的东西