| 46 | // thread-safe manner. |
| 47 | |
| 48 | void test_scoped_critical_section(const py::handle &cls) { |
| 49 | auto barrier = std::barrier(2); |
| 50 | auto bool_wrapper = cls(false); |
| 51 | bool output = false; |
| 52 | |
| 53 | { |
| 54 | // Release the GIL to allow run threads in parallel. |
| 55 | py::gil_scoped_release gil_release{}; |
| 56 | |
| 57 | std::thread t1([&]() { |
| 58 | // Use gil_scoped_acquire to ensure we have a valid Python thread state |
| 59 | // before entering the critical section. Otherwise, the critical section |
| 60 | // will cause a segmentation fault. |
| 61 | py::gil_scoped_acquire ensure_tstate{}; |
| 62 | // Enter the critical section with the same object as the second thread. |
| 63 | py::scoped_critical_section lock{bool_wrapper}; |
| 64 | // At this point, the object is locked by this thread via the scoped_critical_section. |
| 65 | // This barrier will ensure that the second thread waits until this thread has released |
| 66 | // the critical section before proceeding. |
| 67 | barrier.arrive_and_wait(); |
| 68 | // Sleep for a short time to simulate some work in the critical section. |
| 69 | // This sleep is necessary to test the locking mechanism properly. |
| 70 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); |
| 71 | auto *bw = bool_wrapper.cast<BoolWrapper *>(); |
| 72 | bw->set(true); |
| 73 | }); |
| 74 | |
| 75 | std::thread t2([&]() { |
| 76 | // This thread will wait until the first thread has entered the critical section due to |
| 77 | // the barrier. |
| 78 | barrier.arrive_and_wait(); |
| 79 | { |
| 80 | // Use gil_scoped_acquire to ensure we have a valid Python thread state |
| 81 | // before entering the critical section. Otherwise, the critical section |
| 82 | // will cause a segmentation fault. |
| 83 | py::gil_scoped_acquire ensure_tstate{}; |
| 84 | // Enter the critical section with the same object as the first thread. |
| 85 | py::scoped_critical_section lock{bool_wrapper}; |
| 86 | // At this point, the critical section is released by the first thread, the value |
| 87 | // is set to true. |
| 88 | auto *bw = bool_wrapper.cast<BoolWrapper *>(); |
| 89 | output = bw->get(); |
| 90 | } |
| 91 | }); |
| 92 | |
| 93 | t1.join(); |
| 94 | t2.join(); |
| 95 | } |
| 96 | |
| 97 | if (!output) { |
| 98 | throw std::runtime_error("Scoped critical section test failed: output is false"); |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | void test_scoped_critical_section2(const py::handle &cls) { |
| 103 | auto barrier = std::barrier(3); |
no test coverage detected