mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 13:15:12 +00:00
Clarify GIL documentation (#4057)
This commit is contained in:
parent
8524b20c3c
commit
1874f8fa87
@ -39,15 +39,42 @@ The ``PYBIND11_MAKE_OPAQUE`` macro does *not* require the above workarounds.
|
|||||||
Global Interpreter Lock (GIL)
|
Global Interpreter Lock (GIL)
|
||||||
=============================
|
=============================
|
||||||
|
|
||||||
When calling a C++ function from Python, the GIL is always held.
|
The Python C API dictates that the Global Interpreter Lock (GIL) must always
|
||||||
|
be held by the current thread to safely access Python objects. As a result,
|
||||||
|
when Python calls into C++ via pybind11 the GIL must be held, and pybind11
|
||||||
|
will never implicitly release the GIL.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
void my_function() {
|
||||||
|
/* GIL is held when this function is called from Python */
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_MODULE(example, m) {
|
||||||
|
m.def("my_function", &my_function);
|
||||||
|
}
|
||||||
|
|
||||||
|
pybind11 will ensure that the GIL is held when it knows that it is calling
|
||||||
|
Python code. For example, if a Python callback is passed to C++ code via
|
||||||
|
``std::function``, when C++ code calls the function the built-in wrapper
|
||||||
|
will acquire the GIL before calling the Python callback. Similarly, the
|
||||||
|
``PYBIND11_OVERRIDE`` family of macros will acquire the GIL before calling
|
||||||
|
back into Python.
|
||||||
|
|
||||||
|
When writing C++ code that is called from other C++ code, if that code accesses
|
||||||
|
Python state, it must explicitly acquire and release the GIL.
|
||||||
|
|
||||||
The classes :class:`gil_scoped_release` and :class:`gil_scoped_acquire` can be
|
The classes :class:`gil_scoped_release` and :class:`gil_scoped_acquire` can be
|
||||||
used to acquire and release the global interpreter lock in the body of a C++
|
used to acquire and release the global interpreter lock in the body of a C++
|
||||||
function call. In this way, long-running C++ code can be parallelized using
|
function call. In this way, long-running C++ code can be parallelized using
|
||||||
multiple Python threads. Taking :ref:`overriding_virtuals` as an example, this
|
multiple Python threads, **but great care must be taken** when any
|
||||||
|
:class:`gil_scoped_release` appear: if there is any way that the C++ code
|
||||||
|
can access Python objects, :class:`gil_scoped_acquire` should be used to
|
||||||
|
reacquire the GIL. Taking :ref:`overriding_virtuals` as an example, this
|
||||||
could be realized as follows (important changes highlighted):
|
could be realized as follows (important changes highlighted):
|
||||||
|
|
||||||
.. code-block:: cpp
|
.. code-block:: cpp
|
||||||
:emphasize-lines: 8,9,31,32
|
:emphasize-lines: 8,30,31
|
||||||
|
|
||||||
class PyAnimal : public Animal {
|
class PyAnimal : public Animal {
|
||||||
public:
|
public:
|
||||||
@ -56,9 +83,7 @@ could be realized as follows (important changes highlighted):
|
|||||||
|
|
||||||
/* Trampoline (need one for each virtual function) */
|
/* Trampoline (need one for each virtual function) */
|
||||||
std::string go(int n_times) {
|
std::string go(int n_times) {
|
||||||
/* Acquire GIL before calling Python code */
|
/* PYBIND11_OVERRIDE_PURE will acquire the GIL before accessing Python state */
|
||||||
py::gil_scoped_acquire acquire;
|
|
||||||
|
|
||||||
PYBIND11_OVERRIDE_PURE(
|
PYBIND11_OVERRIDE_PURE(
|
||||||
std::string, /* Return type */
|
std::string, /* Return type */
|
||||||
Animal, /* Parent class */
|
Animal, /* Parent class */
|
||||||
@ -78,7 +103,8 @@ could be realized as follows (important changes highlighted):
|
|||||||
.def(py::init<>());
|
.def(py::init<>());
|
||||||
|
|
||||||
m.def("call_go", [](Animal *animal) -> std::string {
|
m.def("call_go", [](Animal *animal) -> std::string {
|
||||||
/* Release GIL before calling into (potentially long-running) C++ code */
|
// GIL is held when called from Python code. Release GIL before
|
||||||
|
// calling into (potentially long-running) C++ code
|
||||||
py::gil_scoped_release release;
|
py::gil_scoped_release release;
|
||||||
return call_go(animal);
|
return call_go(animal);
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user