mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-25 06:35:12 +00:00
a few more GIL-related compatibility fixes
This commit is contained in:
parent
17b10d7cbf
commit
fbafdea672
@ -117,6 +117,18 @@ PYBIND11_NOINLINE inline handle get_object_handle(const void *ptr) {
|
|||||||
return handle((PyObject *) it->second);
|
return handle((PyObject *) it->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline PyThreadState *get_thread_state_unchecked() {
|
||||||
|
#if PY_VERSION_HEX < 0x03000000
|
||||||
|
return _PyThreadState_Current;
|
||||||
|
#elif PY_VERSION_HEX < 0x03050000
|
||||||
|
return (PyThreadState*) _Py_atomic_load_relaxed(&_PyThreadState_Current);
|
||||||
|
#elif PY_VERSION_HEX < 0x03050200
|
||||||
|
return (PyThreadState*) _PyThreadState_Current.value;
|
||||||
|
#else
|
||||||
|
return _PyThreadState_UncheckedGet();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
class type_caster_generic {
|
class type_caster_generic {
|
||||||
public:
|
public:
|
||||||
PYBIND11_NOINLINE type_caster_generic(const std::type_info &type_info)
|
PYBIND11_NOINLINE type_caster_generic(const std::type_info &type_info)
|
||||||
|
@ -110,6 +110,13 @@
|
|||||||
extern "C" PYBIND11_EXPORT PyObject *init##name()
|
extern "C" PYBIND11_EXPORT PyObject *init##name()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if PY_VERSION_HEX >= 0x03050000 && PY_VERSION_HEX < 0x03050200
|
||||||
|
extern "C" {
|
||||||
|
struct _Py_atomic_address { void *value; };
|
||||||
|
PyAPI_DATA(_Py_atomic_address) _PyThreadState_Current;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
#define PYBIND11_TRY_NEXT_OVERLOAD ((PyObject *) 1) // special failure return code
|
#define PYBIND11_TRY_NEXT_OVERLOAD ((PyObject *) 1) // special failure return code
|
||||||
#define PYBIND11_STRINGIFY(x) #x
|
#define PYBIND11_STRINGIFY(x) #x
|
||||||
#define PYBIND11_TOSTRING(x) PYBIND11_STRINGIFY(x)
|
#define PYBIND11_TOSTRING(x) PYBIND11_STRINGIFY(x)
|
||||||
|
@ -1053,11 +1053,13 @@ template <typename InputType, typename OutputType> void implicitly_convertible()
|
|||||||
*
|
*
|
||||||
* 3. The reference count of an acquired thread state can be controlled. This
|
* 3. The reference count of an acquired thread state can be controlled. This
|
||||||
* can be handy to prevent cases where callbacks issued from an external
|
* can be handy to prevent cases where callbacks issued from an external
|
||||||
* thread constantly construct and destroy thread state data structures. */
|
* thread would otherwise constantly construct and destroy thread state data
|
||||||
|
* structures.
|
||||||
|
*/
|
||||||
|
|
||||||
class gil_scoped_acquire {
|
class gil_scoped_acquire {
|
||||||
public:
|
public:
|
||||||
gil_scoped_acquire() {
|
PYBIND11_NOINLINE gil_scoped_acquire() {
|
||||||
auto const &internals = detail::get_internals();
|
auto const &internals = detail::get_internals();
|
||||||
tstate = (PyThreadState *) PyThread_get_key_value(internals.tstate);
|
tstate = (PyThreadState *) PyThread_get_key_value(internals.tstate);
|
||||||
|
|
||||||
@ -1068,17 +1070,24 @@ public:
|
|||||||
pybind11_fail("scoped_acquire: could not create thread state!");
|
pybind11_fail("scoped_acquire: could not create thread state!");
|
||||||
#endif
|
#endif
|
||||||
tstate->gilstate_counter = 0;
|
tstate->gilstate_counter = 0;
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
|
PyThread_delete_key_value(internals.tstate);
|
||||||
|
#endif
|
||||||
PyThread_set_key_value(internals.tstate, tstate);
|
PyThread_set_key_value(internals.tstate, tstate);
|
||||||
} else {
|
} else {
|
||||||
release = PyThreadState_GET() != tstate;
|
release = detail::get_thread_state_unchecked() != tstate;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (release) {
|
if (release) {
|
||||||
PyInterpreterState *interp = tstate->interp;
|
|
||||||
/* Work around an annoying assertion in PyThreadState_Swap */
|
/* Work around an annoying assertion in PyThreadState_Swap */
|
||||||
tstate->interp = nullptr;
|
#if defined(Py_DEBUG)
|
||||||
|
PyInterpreterState *interp = tstate->interp;
|
||||||
|
tstate->interp = nullptr;
|
||||||
|
#endif
|
||||||
PyEval_AcquireThread(tstate);
|
PyEval_AcquireThread(tstate);
|
||||||
tstate->interp = interp;
|
#if defined(Py_DEBUG)
|
||||||
|
tstate->interp = interp;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inc_ref();
|
inc_ref();
|
||||||
@ -1088,10 +1097,10 @@ public:
|
|||||||
++tstate->gilstate_counter;
|
++tstate->gilstate_counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dec_ref() {
|
PYBIND11_NOINLINE void dec_ref() {
|
||||||
--tstate->gilstate_counter;
|
--tstate->gilstate_counter;
|
||||||
#if !defined(NDEBUG)
|
#if !defined(NDEBUG)
|
||||||
if (PyThreadState_GET() != tstate)
|
if (detail::get_thread_state_unchecked() != tstate)
|
||||||
pybind11_fail("scoped_acquire::dec_ref(): thread state must be current!");
|
pybind11_fail("scoped_acquire::dec_ref(): thread state must be current!");
|
||||||
if (tstate->gilstate_counter < 0)
|
if (tstate->gilstate_counter < 0)
|
||||||
pybind11_fail("scoped_acquire::dec_ref(): reference count underflow!");
|
pybind11_fail("scoped_acquire::dec_ref(): reference count underflow!");
|
||||||
@ -1103,12 +1112,12 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
PyThreadState_Clear(tstate);
|
PyThreadState_Clear(tstate);
|
||||||
PyThreadState_DeleteCurrent();
|
PyThreadState_DeleteCurrent();
|
||||||
PyThread_set_key_value(detail::get_internals().tstate, nullptr);
|
PyThread_delete_key_value(detail::get_internals().tstate);
|
||||||
release = false;
|
release = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~gil_scoped_acquire() {
|
PYBIND11_NOINLINE ~gil_scoped_acquire() {
|
||||||
dec_ref();
|
dec_ref();
|
||||||
if (release)
|
if (release)
|
||||||
PyEval_SaveThread();
|
PyEval_SaveThread();
|
||||||
|
Loading…
Reference in New Issue
Block a user