μHAL (v2.8.17)
Part of the IPbus software repository
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
test_gil_scoped.cpp
Go to the documentation of this file.
1/*
2 tests/test_gil_scoped.cpp -- acquire and release gil
3
4 Copyright (c) 2017 Borja Zarco (Google LLC) <bzarco@google.com>
5
6 All rights reserved. Use of this source code is governed by a
7 BSD-style license that can be found in the LICENSE file.
8*/
9
10#include <pybind11/functional.h>
11
12#include "pybind11_tests.h"
13
14#include <string>
15#include <thread>
16
17#define CROSS_MODULE(Function) \
18 auto cm = py::module_::import("cross_module_gil_utils"); \
19 auto target = reinterpret_cast<void (*)()>(PyLong_AsVoidPtr(cm.attr(Function).ptr()));
20
21class VirtClass {
22public:
23 virtual ~VirtClass() = default;
24 VirtClass() = default;
25 VirtClass(const VirtClass &) = delete;
26 virtual void virtual_func() {}
27 virtual void pure_virtual_func() = 0;
28};
29
30class PyVirtClass : public VirtClass {
32 void pure_virtual_func() override {
34 }
35};
36
37TEST_SUBMODULE(gil_scoped, m) {
38 m.attr("defined_THREAD_SANITIZER") =
39#if defined(THREAD_SANITIZER)
40 true;
41#else
42 false;
43#endif
44
45 m.def("intentional_deadlock",
46 []() { std::thread([]() { py::gil_scoped_acquire gil_acquired; }).join(); });
47
48 py::class_<VirtClass, PyVirtClass>(m, "VirtClass")
49 .def(py::init<>())
50 .def("virtual_func", &VirtClass::virtual_func)
51 .def("pure_virtual_func", &VirtClass::pure_virtual_func);
52
53 m.def("test_callback_py_obj", [](py::object &func) { func(); });
54 m.def("test_callback_std_func", [](const std::function<void()> &func) { func(); });
55 m.def("test_callback_virtual_func", [](VirtClass &virt) { virt.virtual_func(); });
56 m.def("test_callback_pure_virtual_func", [](VirtClass &virt) { virt.pure_virtual_func(); });
57 m.def("test_cross_module_gil_released", []() {
58 CROSS_MODULE("gil_acquire_funcaddr")
59 py::gil_scoped_release gil_release;
60 target();
61 });
62 m.def("test_cross_module_gil_acquired", []() {
63 CROSS_MODULE("gil_acquire_funcaddr")
64 py::gil_scoped_acquire gil_acquire;
65 target();
66 });
67 m.def("test_cross_module_gil_inner_custom_released", []() {
68 CROSS_MODULE("gil_acquire_inner_custom_funcaddr")
69 py::gil_scoped_release gil_release;
70 target();
71 });
72 m.def("test_cross_module_gil_inner_custom_acquired", []() {
73 CROSS_MODULE("gil_acquire_inner_custom_funcaddr")
74 py::gil_scoped_acquire gil_acquire;
75 target();
76 });
77 m.def("test_cross_module_gil_inner_pybind11_released", []() {
78 CROSS_MODULE("gil_acquire_inner_pybind11_funcaddr")
79 py::gil_scoped_release gil_release;
80 target();
81 });
82 m.def("test_cross_module_gil_inner_pybind11_acquired", []() {
83 CROSS_MODULE("gil_acquire_inner_pybind11_funcaddr")
84 py::gil_scoped_acquire gil_acquire;
85 target();
86 });
87 m.def("test_cross_module_gil_nested_custom_released", []() {
88 CROSS_MODULE("gil_acquire_nested_custom_funcaddr")
89 py::gil_scoped_release gil_release;
90 target();
91 });
92 m.def("test_cross_module_gil_nested_custom_acquired", []() {
93 CROSS_MODULE("gil_acquire_nested_custom_funcaddr")
94 py::gil_scoped_acquire gil_acquire;
95 target();
96 });
97 m.def("test_cross_module_gil_nested_pybind11_released", []() {
98 CROSS_MODULE("gil_acquire_nested_pybind11_funcaddr")
99 py::gil_scoped_release gil_release;
100 target();
101 });
102 m.def("test_cross_module_gil_nested_pybind11_acquired", []() {
103 CROSS_MODULE("gil_acquire_nested_pybind11_funcaddr")
104 py::gil_scoped_acquire gil_acquire;
105 target();
106 });
107 m.def("test_release_acquire", [](const py::object &obj) {
108 py::gil_scoped_release gil_released;
109 py::gil_scoped_acquire gil_acquired;
110 return py::str(obj);
111 });
112 m.def("test_nested_acquire", [](const py::object &obj) {
113 py::gil_scoped_release gil_released;
114 py::gil_scoped_acquire gil_acquired_outer;
115 py::gil_scoped_acquire gil_acquired_inner;
116 return py::str(obj);
117 });
118 m.def("test_multi_acquire_release_cross_module", [](unsigned bits) {
119 py::set internals_ids;
120 internals_ids.add(PYBIND11_INTERNALS_ID);
121 {
122 py::gil_scoped_release gil_released;
123 auto thread_f = [bits, &internals_ids]() {
124 py::gil_scoped_acquire gil_acquired;
125 auto cm = py::module_::import("cross_module_gil_utils");
126 auto target = reinterpret_cast<std::string (*)(unsigned)>(
127 PyLong_AsVoidPtr(cm.attr("gil_multi_acquire_release_funcaddr").ptr()));
128 std::string cm_internals_id = target(bits >> 3);
129 internals_ids.add(cm_internals_id);
130 };
131 if ((bits & 0x1u) != 0u) {
132 thread_f();
133 }
134 if ((bits & 0x2u) != 0u) {
135 std::thread non_python_thread(thread_f);
136 non_python_thread.join();
137 }
138 if ((bits & 0x4u) != 0u) {
139 thread_f();
140 }
141 }
142 return internals_ids;
143 });
144}
void pure_virtual_func() override
void virtual_func() override
virtual void virtual_func()
VirtClass()=default
virtual void pure_virtual_func()=0
virtual ~VirtClass()=default
VirtClass(const VirtClass &)=delete
#define PYBIND11_INTERNALS_ID
Definition: internals.h:280
#define PYBIND11_OVERRIDE_PURE(ret_type, cname, fn,...)
\rst Macro for pure virtual functions, this function is identical to :c:macro:PYBIND11_OVERRIDE,...
Definition: pybind11.h:2838
#define PYBIND11_OVERRIDE(ret_type, cname, fn,...)
\rst Macro to populate the virtual method in the trampoline class.
Definition: pybind11.h:2831
#define TEST_SUBMODULE(name, variable)
#define CROSS_MODULE(Function)