是否有可能在阻止并可能回调为Python的C函数之前释放GIL?

时间:2011-03-01 18:59:45

标签: python gil python-multithreading python-bindings

我正在包装一个执行阻塞操作(选择)的C函数,然后处理传入的消息。我的理解是,当一个C函数要阻塞时,在允许其他线程运行的同时调用它的正确方法是:

Py_BEGIN_ALLOW_THREADS                                                  
blocking_function();
Py_END_ALLOW_THREADS

然而,这个函数将参数作为一个参数作为回调指针。在处理由C函数预处理的传入消息时调用此回调。我已经成功地将这个回调包装在一个调用PyEval_CallObject()的函数中,允许我将它传递给Python回调。

既然我正在添加线程支持,我想知道是否可以同时进行:

  • 在调用此阻止操作之前释放GIL。
  • 让这个阻塞操作安全地回调到python解释器。

这会导致问题吗?如果是这样,有办法吗?

感谢。

2 个答案:

答案 0 :(得分:7)

几个月前我使用过这些API函数,而且我的回忆有点模糊,但我相信这段代码可以解决你的问题。我假设版本2.x(3.x可能不同):

PyGILState_STATE gstate;
gstate = PyGILState_Ensure();

/* Make your call to PyEval_CallObject() here (and any other PY API calls). */

PyGILState_Release(gstate);

(以上摘自:Python C/API docs

这基本上与Py_BEGIN_ALLOW_THREADS / Py_END_ALLOW_THREADS相反  宏。在那些中,你释放GIL,但在PyGILState函数中你获得了GIL。

答案 1 :(得分:1)

如果我使用全局来存储PyEval_SaveThread的结果,并在回调中使用它来调用PyEval_RestoreThread,则可以正常工作。我只需要弄清楚如何通过回调的上下文指针更清晰地将它传递给我的代码中的回调。