|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
#include "detail/common.h"
|
|
|
|
|
|
#include <cassert>
|
|
|
|
|
|
#if !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
|
|
|
# include "detail/internals.h"
|
|
|
#endif
|
|
|
|
|
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
|
|
|
|
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
|
|
|
|
|
|
|
|
PyThreadState *get_thread_state_unchecked();
|
|
|
|
|
|
PYBIND11_NAMESPACE_END(detail)
|
|
|
|
|
|
#if !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class gil_scoped_acquire {
|
|
|
public:
|
|
|
PYBIND11_NOINLINE gil_scoped_acquire() {
|
|
|
auto &internals = detail::get_internals();
|
|
|
tstate = (PyThreadState *) PYBIND11_TLS_GET_VALUE(internals.tstate);
|
|
|
|
|
|
if (!tstate) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tstate = PyGILState_GetThisThreadState();
|
|
|
}
|
|
|
|
|
|
if (!tstate) {
|
|
|
tstate = PyThreadState_New(internals.istate);
|
|
|
# if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
|
|
if (!tstate) {
|
|
|
pybind11_fail("scoped_acquire: could not create thread state!");
|
|
|
}
|
|
|
# endif
|
|
|
tstate->gilstate_counter = 0;
|
|
|
PYBIND11_TLS_REPLACE_VALUE(internals.tstate, tstate);
|
|
|
} else {
|
|
|
release = detail::get_thread_state_unchecked() != tstate;
|
|
|
}
|
|
|
|
|
|
if (release) {
|
|
|
PyEval_AcquireThread(tstate);
|
|
|
}
|
|
|
|
|
|
inc_ref();
|
|
|
}
|
|
|
|
|
|
gil_scoped_acquire(const gil_scoped_acquire &) = delete;
|
|
|
gil_scoped_acquire &operator=(const gil_scoped_acquire &) = delete;
|
|
|
|
|
|
void inc_ref() { ++tstate->gilstate_counter; }
|
|
|
|
|
|
PYBIND11_NOINLINE void dec_ref() {
|
|
|
--tstate->gilstate_counter;
|
|
|
# if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
|
|
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!");
|
|
|
}
|
|
|
# endif
|
|
|
if (tstate->gilstate_counter == 0) {
|
|
|
# if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
|
|
if (!release) {
|
|
|
pybind11_fail("scoped_acquire::dec_ref(): internal error!");
|
|
|
}
|
|
|
# endif
|
|
|
PyThreadState_Clear(tstate);
|
|
|
if (active) {
|
|
|
PyThreadState_DeleteCurrent();
|
|
|
}
|
|
|
PYBIND11_TLS_DELETE_VALUE(detail::get_internals().tstate);
|
|
|
release = false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PYBIND11_NOINLINE void disarm() { active = false; }
|
|
|
|
|
|
PYBIND11_NOINLINE ~gil_scoped_acquire() {
|
|
|
dec_ref();
|
|
|
if (release) {
|
|
|
PyEval_SaveThread();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
PyThreadState *tstate = nullptr;
|
|
|
bool release = true;
|
|
|
bool active = true;
|
|
|
};
|
|
|
|
|
|
class gil_scoped_release {
|
|
|
public:
|
|
|
|
|
|
explicit gil_scoped_release(bool disassoc = false) : disassoc(disassoc) {
|
|
|
assert(PyGILState_Check());
|
|
|
|
|
|
|
|
|
|
|
|
auto &internals = detail::get_internals();
|
|
|
|
|
|
tstate = PyEval_SaveThread();
|
|
|
if (disassoc) {
|
|
|
|
|
|
|
|
|
auto key = internals.tstate;
|
|
|
PYBIND11_TLS_DELETE_VALUE(key);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
gil_scoped_release(const gil_scoped_release &) = delete;
|
|
|
gil_scoped_release &operator=(const gil_scoped_release &) = delete;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PYBIND11_NOINLINE void disarm() { active = false; }
|
|
|
|
|
|
~gil_scoped_release() {
|
|
|
if (!tstate) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (active) {
|
|
|
PyEval_RestoreThread(tstate);
|
|
|
}
|
|
|
if (disassoc) {
|
|
|
|
|
|
|
|
|
auto key = detail::get_internals().tstate;
|
|
|
PYBIND11_TLS_REPLACE_VALUE(key, tstate);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
PyThreadState *tstate;
|
|
|
bool disassoc;
|
|
|
bool active = true;
|
|
|
};
|
|
|
|
|
|
#else
|
|
|
|
|
|
class gil_scoped_acquire {
|
|
|
PyGILState_STATE state;
|
|
|
|
|
|
public:
|
|
|
gil_scoped_acquire() : state{PyGILState_Ensure()} {}
|
|
|
gil_scoped_acquire(const gil_scoped_acquire &) = delete;
|
|
|
gil_scoped_acquire &operator=(const gil_scoped_acquire &) = delete;
|
|
|
~gil_scoped_acquire() { PyGILState_Release(state); }
|
|
|
void disarm() {}
|
|
|
};
|
|
|
|
|
|
class gil_scoped_release {
|
|
|
PyThreadState *state;
|
|
|
|
|
|
public:
|
|
|
|
|
|
gil_scoped_release() {
|
|
|
assert(PyGILState_Check());
|
|
|
state = PyEval_SaveThread();
|
|
|
}
|
|
|
gil_scoped_release(const gil_scoped_release &) = delete;
|
|
|
gil_scoped_release &operator=(const gil_scoped_release &) = delete;
|
|
|
~gil_scoped_release() { PyEval_RestoreThread(state); }
|
|
|
void disarm() {}
|
|
|
};
|
|
|
|
|
|
#endif
|
|
|
|
|
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
|
|
|