a few more GIL-related compatibility fixes

This commit is contained in:
Wenzel Jakob 2016-04-25 15:02:43 +02:00
parent 17b10d7cbf
commit fbafdea672
3 changed files with 38 additions and 10 deletions

View File

@ -117,6 +117,18 @@ PYBIND11_NOINLINE inline handle get_object_handle(const void *ptr) {
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 {
public:
PYBIND11_NOINLINE type_caster_generic(const std::type_info &type_info)

View File

@ -110,6 +110,13 @@
extern "C" PYBIND11_EXPORT PyObject *init##name()
#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_STRINGIFY(x) #x
#define PYBIND11_TOSTRING(x) PYBIND11_STRINGIFY(x)

View File

@ -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
* 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 {
public:
gil_scoped_acquire() {
PYBIND11_NOINLINE gil_scoped_acquire() {
auto const &internals = detail::get_internals();
tstate = (PyThreadState *) PyThread_get_key_value(internals.tstate);
@ -1068,17 +1070,24 @@ public:
pybind11_fail("scoped_acquire: could not create thread state!");
#endif
tstate->gilstate_counter = 0;
#if PY_MAJOR_VERSION < 3
PyThread_delete_key_value(internals.tstate);
#endif
PyThread_set_key_value(internals.tstate, tstate);
} else {
release = PyThreadState_GET() != tstate;
release = detail::get_thread_state_unchecked() != tstate;
}
if (release) {
PyInterpreterState *interp = tstate->interp;
/* Work around an annoying assertion in PyThreadState_Swap */
#if defined(Py_DEBUG)
PyInterpreterState *interp = tstate->interp;
tstate->interp = nullptr;
#endif
PyEval_AcquireThread(tstate);
#if defined(Py_DEBUG)
tstate->interp = interp;
#endif
}
inc_ref();
@ -1088,10 +1097,10 @@ public:
++tstate->gilstate_counter;
}
void dec_ref() {
PYBIND11_NOINLINE void dec_ref() {
--tstate->gilstate_counter;
#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!");
if (tstate->gilstate_counter < 0)
pybind11_fail("scoped_acquire::dec_ref(): reference count underflow!");
@ -1103,12 +1112,12 @@ public:
#endif
PyThreadState_Clear(tstate);
PyThreadState_DeleteCurrent();
PyThread_set_key_value(detail::get_internals().tstate, nullptr);
PyThread_delete_key_value(detail::get_internals().tstate);
release = false;
}
}
~gil_scoped_acquire() {
PYBIND11_NOINLINE ~gil_scoped_acquire() {
dec_ref();
if (release)
PyEval_SaveThread();