Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:17:51

0001 /*
0002     tests/cross_module_gil_utils.cpp -- tools for acquiring GIL from a different module
0003 
0004     Copyright (c) 2019 Google LLC
0005 
0006     All rights reserved. Use of this source code is governed by a
0007     BSD-style license that can be found in the LICENSE file.
0008 */
0009 #if defined(PYBIND11_INTERNALS_VERSION)
0010 #    undef PYBIND11_INTERNALS_VERSION
0011 #endif
0012 #define PYBIND11_INTERNALS_VERSION 21814642 // Ensure this module has its own `internals` instance.
0013 #include <pybind11/pybind11.h>
0014 
0015 #include <cstdint>
0016 #include <string>
0017 #include <thread>
0018 
0019 // This file mimics a DSO that makes pybind11 calls but does not define a
0020 // PYBIND11_MODULE. The purpose is to test that such a DSO can create a
0021 // py::gil_scoped_acquire when the running thread is in a GIL-released state.
0022 //
0023 // Note that we define a Python module here for convenience, but in general
0024 // this need not be the case. The typical scenario would be a DSO that implements
0025 // shared logic used internally by multiple pybind11 modules.
0026 
0027 namespace {
0028 
0029 namespace py = pybind11;
0030 
0031 void gil_acquire() { py::gil_scoped_acquire gil; }
0032 
0033 std::string gil_multi_acquire_release(unsigned bits) {
0034     if ((bits & 0x1u) != 0u) {
0035         py::gil_scoped_acquire gil;
0036     }
0037     if ((bits & 0x2u) != 0u) {
0038         py::gil_scoped_release gil;
0039     }
0040     if ((bits & 0x4u) != 0u) {
0041         py::gil_scoped_acquire gil;
0042     }
0043     if ((bits & 0x8u) != 0u) {
0044         py::gil_scoped_release gil;
0045     }
0046     return PYBIND11_INTERNALS_ID;
0047 }
0048 
0049 struct CustomAutoGIL {
0050     CustomAutoGIL() : gstate(PyGILState_Ensure()) {}
0051     ~CustomAutoGIL() { PyGILState_Release(gstate); }
0052 
0053     PyGILState_STATE gstate;
0054 };
0055 struct CustomAutoNoGIL {
0056     CustomAutoNoGIL() : save(PyEval_SaveThread()) {}
0057     ~CustomAutoNoGIL() { PyEval_RestoreThread(save); }
0058 
0059     PyThreadState *save;
0060 };
0061 
0062 template <typename Acquire, typename Release>
0063 void gil_acquire_inner() {
0064     Acquire acquire_outer;
0065     Acquire acquire_inner;
0066     Release release;
0067 }
0068 
0069 template <typename Acquire, typename Release>
0070 void gil_acquire_nested() {
0071     Acquire acquire_outer;
0072     Acquire acquire_inner;
0073     Release release;
0074     auto thread = std::thread(&gil_acquire_inner<Acquire, Release>);
0075     thread.join();
0076 }
0077 
0078 constexpr char kModuleName[] = "cross_module_gil_utils";
0079 
0080 struct PyModuleDef moduledef = {
0081     PyModuleDef_HEAD_INIT, kModuleName, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr};
0082 
0083 } // namespace
0084 
0085 #define ADD_FUNCTION(Name, ...)                                                                   \
0086     PyModule_AddObject(m, Name, PyLong_FromVoidPtr(reinterpret_cast<void *>(&__VA_ARGS__)));
0087 
0088 extern "C" PYBIND11_EXPORT PyObject *PyInit_cross_module_gil_utils() {
0089 
0090     PyObject *m = PyModule_Create(&moduledef);
0091 
0092     if (m != nullptr) {
0093         static_assert(sizeof(&gil_acquire) == sizeof(void *),
0094                       "Function pointer must have the same size as void*");
0095         ADD_FUNCTION("gil_acquire_funcaddr", gil_acquire)
0096         ADD_FUNCTION("gil_multi_acquire_release_funcaddr", gil_multi_acquire_release)
0097         ADD_FUNCTION("gil_acquire_inner_custom_funcaddr",
0098                      gil_acquire_inner<CustomAutoGIL, CustomAutoNoGIL>)
0099         ADD_FUNCTION("gil_acquire_nested_custom_funcaddr",
0100                      gil_acquire_nested<CustomAutoGIL, CustomAutoNoGIL>)
0101         ADD_FUNCTION("gil_acquire_inner_pybind11_funcaddr",
0102                      gil_acquire_inner<py::gil_scoped_acquire, py::gil_scoped_release>)
0103         ADD_FUNCTION("gil_acquire_nested_pybind11_funcaddr",
0104                      gil_acquire_nested<py::gil_scoped_acquire, py::gil_scoped_release>)
0105     }
0106 
0107     return m;
0108 }