是否可以在阻塞并可能回调到 Python 的 C 函数之前释放 GIL?

发布于 2024-10-20 08:13:51 字数 497 浏览 3 评论 0原文

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

Py_BEGIN_ALLOW_THREADS                                                  
blocking_function();
Py_END_ALLOW_THREADS

但是,这个函数恰好将回调指针作为参数。在处理由 C 函数预处理的传入消息时调用此回调。我已成功将此回调包装在调用 PyEval_CallObject() 的函数中,允许我向其传递 Python 回调。

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

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

这会引起问题吗?如果是这样,有办法解决吗?

谢谢。

I am wrapping a C function which performs a blocking operation (select) and then handles incoming messages. My understanding is that when a C function is going to block, the correct way to call it while allowing other threads to run is:

Py_BEGIN_ALLOW_THREADS                                                  
blocking_function();
Py_END_ALLOW_THREADS

However, it happens that this function takes as a parameter a callback pointer. This callback is called on handling the incoming message that is pre-processed by the C function. I have successfully wrapped this callback in a function which calls PyEval_CallObject(), allowing me to pass it a Python callback.

Now that I'm adding threading support, I'm wondering if it's possible to simultaneously:

  • Release the GIL before calling this blocking operation.
  • Have this blocking operation safely call back into the python interpreter.

Is this going to cause problems? If so, is there a way around it?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

嗳卜坏 2024-10-27 08:13:51

我几个月前使用过这些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 文档

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

I used these API functions several months ago, and my recollection is a bit hazy, but I believe this code will solve your problem. I am assuming version 2.x (3.x may be different):

PyGILState_STATE gstate;
gstate = PyGILState_Ensure();

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

PyGILState_Release(gstate);

(The above was taken from: Python C/API docs)

This is basically the inverse of the Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS
macros. Within those, you release the GIL, but within the PyGILState functions you acquire the GIL.

醉殇 2024-10-27 08:13:51

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

Works if I use a global to store the result of PyEval_SaveThread, and use this in the callback to call PyEval_RestoreThread. I just need to figure out how to more cleanly pass this to the callback in my code through the callback's context pointer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文