首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在C扩展中释放全局VM锁而不使用其他函数

在C扩展中释放全局VM锁而不使用其他函数
EN

Stack Overflow用户
提问于 2016-03-27 09:35:20
回答 2查看 634关注 0票数 9

我不明白为什么在Ruby中发布或获取GVL时还需要另一个级别的间接定向。

rb_thread_call_without_gvl()rb_thread_call_with_gvl()都需要一个只接受一个参数的函数,而这种情况并不总是如此。我不想仅仅为了释放GVL而将我的论点包装在一个结构中。它使代码的可读性变得复杂,并要求从指针转换为无效指针。

在查看了Ruby的线程代码之后,我找到了与Python的GVL_UNLOCK_BEGIN/GVL_UNLOCK_END宏相匹配的Py_END_ALLOW_THREADS,但是我无法找到关于它们的文档,以及它们何时可以安全使用。

BLOCKING_REGION宏也在rb_thread_call_without_gvl()中使用,但我不确定在不调用rb_thread_call_without_gvl()本身的情况下将其作为独立使用是否安全。

在不需要调用其他函数的情况下,在执行流中间安全地发布的正确方法是什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-04-02 21:11:44

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

以前有一个“基于区域的”API,rb_thread_blocking_region_begin/rb_thread_blocking_region_end,但是这个API在Ruby1.9.3中被废弃了,在Ruby2.2中被删除了(关于CAPI的废弃时间表,请参阅definitions )。

因此,不幸的是,您只能使用rb_thread_call_without_gvl

尽管如此,你还是可以做一些事情来减轻疼痛。在标准C中,大多数指针和void *之间的转换是隐式的,因此不必添加强制转换。此外,使用指定的初始化器语法可以简化参数结构的创建。

因此,您可以编写

代码语言:javascript
运行
复制
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);
    ...
}

虽然这并不能解决你最初的问题,但它至少能让你更容易接受(我希望)。

票数 7
EN

Stack Overflow用户

发布于 2016-04-02 20:19:08

在执行流中间安全地释放GVL而不必调用另一个函数的正确方法是什么?

您必须使用所提供的API,否则您使用的任何方法最终都会中断。GVL的API是在thread.h中定义的。

代码语言:javascript
运行
复制
void *rb_thread_call_with_gvl(void *(*func)(void *), void *data1);
void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1,
         rb_unblock_function_t *ubf, void *data2);
void *rb_thread_call_without_gvl2(void *(*func)(void *), void *data1,
          rb_unblock_function_t *ubf, void *data2);

您在标题中发现的是API的使用者和API的作者之间的协议,把它看作是一种契约。在.c中发现的任何东西,特别是静态方法和宏,都不适合在文件之外使用,除非在头文件中找到。static关键字阻止了这种情况的发生,这是它存在的原因之一,也是C中最重要的用途之一。您可以在thread.c中穿插,但是使用它的任何东西都违反了API的约定,即它不安全,而且永远不会安全。

,我不是建议您做这个,但是您要做的唯一方法是将它们的部分实现复制到您自己的代码中,这不会通过代码评审。您需要复制的代码数量可能会使您为安全使用API而需要做的任何事情都相形见绌。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36245878

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档