|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(PYBIND11_INTERNALS_VERSION) |
|
|
# undef PYBIND11_INTERNALS_VERSION |
|
|
#endif |
|
|
#define PYBIND11_INTERNALS_VERSION 21814642 |
|
|
#include <pybind11/pybind11.h> |
|
|
|
|
|
#include <cstdint> |
|
|
#include <string> |
|
|
#include <thread> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace { |
|
|
|
|
|
namespace py = pybind11; |
|
|
|
|
|
void gil_acquire() { py::gil_scoped_acquire gil; } |
|
|
|
|
|
std::string gil_multi_acquire_release(unsigned bits) { |
|
|
if ((bits & 0x1u) != 0u) { |
|
|
py::gil_scoped_acquire gil; |
|
|
} |
|
|
if ((bits & 0x2u) != 0u) { |
|
|
py::gil_scoped_release gil; |
|
|
} |
|
|
if ((bits & 0x4u) != 0u) { |
|
|
py::gil_scoped_acquire gil; |
|
|
} |
|
|
if ((bits & 0x8u) != 0u) { |
|
|
py::gil_scoped_release gil; |
|
|
} |
|
|
return PYBIND11_INTERNALS_ID; |
|
|
} |
|
|
|
|
|
struct CustomAutoGIL { |
|
|
CustomAutoGIL() : gstate(PyGILState_Ensure()) {} |
|
|
~CustomAutoGIL() { PyGILState_Release(gstate); } |
|
|
|
|
|
PyGILState_STATE gstate; |
|
|
}; |
|
|
struct CustomAutoNoGIL { |
|
|
CustomAutoNoGIL() : save(PyEval_SaveThread()) {} |
|
|
~CustomAutoNoGIL() { PyEval_RestoreThread(save); } |
|
|
|
|
|
PyThreadState *save; |
|
|
}; |
|
|
|
|
|
template <typename Acquire, typename Release> |
|
|
void gil_acquire_inner() { |
|
|
Acquire acquire_outer; |
|
|
Acquire acquire_inner; |
|
|
Release release; |
|
|
} |
|
|
|
|
|
template <typename Acquire, typename Release> |
|
|
void gil_acquire_nested() { |
|
|
Acquire acquire_outer; |
|
|
Acquire acquire_inner; |
|
|
Release release; |
|
|
auto thread = std::thread(&gil_acquire_inner<Acquire, Release>); |
|
|
thread.join(); |
|
|
} |
|
|
|
|
|
constexpr char kModuleName[] = "cross_module_gil_utils"; |
|
|
|
|
|
struct PyModuleDef moduledef = { |
|
|
PyModuleDef_HEAD_INIT, kModuleName, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr}; |
|
|
|
|
|
} |
|
|
|
|
|
#define ADD_FUNCTION(Name, ...) \ |
|
|
PyModule_AddObject(m, Name, PyLong_FromVoidPtr(reinterpret_cast<void *>(&__VA_ARGS__))); |
|
|
|
|
|
extern "C" PYBIND11_EXPORT PyObject *PyInit_cross_module_gil_utils() { |
|
|
|
|
|
PyObject *m = PyModule_Create(&moduledef); |
|
|
|
|
|
if (m != nullptr) { |
|
|
static_assert(sizeof(&gil_acquire) == sizeof(void *), |
|
|
"Function pointer must have the same size as void*"); |
|
|
ADD_FUNCTION("gil_acquire_funcaddr", gil_acquire) |
|
|
ADD_FUNCTION("gil_multi_acquire_release_funcaddr", gil_multi_acquire_release) |
|
|
ADD_FUNCTION("gil_acquire_inner_custom_funcaddr", |
|
|
gil_acquire_inner<CustomAutoGIL, CustomAutoNoGIL>) |
|
|
ADD_FUNCTION("gil_acquire_nested_custom_funcaddr", |
|
|
gil_acquire_nested<CustomAutoGIL, CustomAutoNoGIL>) |
|
|
ADD_FUNCTION("gil_acquire_inner_pybind11_funcaddr", |
|
|
gil_acquire_inner<py::gil_scoped_acquire, py::gil_scoped_release>) |
|
|
ADD_FUNCTION("gil_acquire_nested_pybind11_funcaddr", |
|
|
gil_acquire_nested<py::gil_scoped_acquire, py::gil_scoped_release>) |
|
|
} |
|
|
|
|
|
return m; |
|
|
} |
|
|
|