| 38 | } // namespace |
| 39 | |
| 40 | TEST_SUBMODULE(thread, m) { |
| 41 | py::class_<IntStruct>(m, "IntStruct").def(py::init([](const int i) { return IntStruct(i); })); |
| 42 | |
| 43 | // implicitly_convertible uses loader_life_support when an implicit |
| 44 | // conversion is required in order to lifetime extend the reference. |
| 45 | // |
| 46 | // This test should be run with ASAN for better effectiveness. |
| 47 | py::implicitly_convertible<int, IntStruct>(); |
| 48 | |
| 49 | m.def("test", [](int expected, const IntStruct &in) { |
| 50 | { |
| 51 | py::gil_scoped_release release; |
| 52 | std::this_thread::sleep_for(std::chrono::milliseconds(5)); |
| 53 | } |
| 54 | |
| 55 | if (in.value != expected) { |
| 56 | throw std::runtime_error("Value changed!!"); |
| 57 | } |
| 58 | }); |
| 59 | |
| 60 | m.def( |
| 61 | "test_no_gil", |
| 62 | [](int expected, const IntStruct &in) { |
| 63 | std::this_thread::sleep_for(std::chrono::milliseconds(5)); |
| 64 | if (in.value != expected) { |
| 65 | throw std::runtime_error("Value changed!!"); |
| 66 | } |
| 67 | }, |
| 68 | py::call_guard<py::gil_scoped_release>()); |
| 69 | |
| 70 | py::class_<EmptyStruct>(m, "EmptyStruct") |
| 71 | .def_readonly_static("SharedInstance", &SharedInstance); |
| 72 | |
| 73 | #if defined(PYBIND11_HAS_STD_BARRIER) |
| 74 | // In the free-threaded build, during PyThreadState_Clear, removing the thread from the biased |
| 75 | // reference counting table may call destructors. Make sure that it doesn't crash. |
| 76 | m.def("test_pythread_state_clear_destructor", [](py::type cls) { |
| 77 | py::handle obj; |
| 78 | |
| 79 | std::barrier barrier{2}; |
| 80 | std::thread thread1{[&]() { |
| 81 | py::gil_scoped_acquire gil; |
| 82 | obj = cls().release(); |
| 83 | barrier.arrive_and_wait(); |
| 84 | }}; |
| 85 | std::thread thread2{[&]() { |
| 86 | py::gil_scoped_acquire gil; |
| 87 | barrier.arrive_and_wait(); |
| 88 | // ob_ref_shared becomes negative; transition to the queued state |
| 89 | obj.dec_ref(); |
| 90 | }}; |
| 91 | |
| 92 | // jthread is not supported by Apple Clang |
| 93 | thread1.join(); |
| 94 | thread2.join(); |
| 95 | }); |
| 96 | #endif |
| 97 | |