@@ -30,23 +30,31 @@ void test_scoped_critical_section(const py::handle &cls) {
3030 auto bool_wrapper = cls (false );
3131 bool output = false ;
3232
33- std::thread t1 ([&]() {
34- py::scoped_critical_section lock{bool_wrapper};
35- barrier.arrive_and_wait ();
36- auto *bw = bool_wrapper.cast <BoolWrapper *>();
37- std::this_thread::sleep_for (std::chrono::milliseconds (10 ));
38- bw->set (true );
39- });
40-
41- std::thread t2 ([&]() {
42- barrier.arrive_and_wait ();
43- py::scoped_critical_section lock{bool_wrapper};
44- auto *bw = bool_wrapper.cast <BoolWrapper *>();
45- output = bw->get ();
46- });
47-
48- t1.join ();
49- t2.join ();
33+ {
34+ py::gil_scoped_release gil_release{};
35+
36+ std::thread t1 ([&]() {
37+ py::gil_scoped_acquire ensure_tstate{};
38+ py::scoped_critical_section lock{bool_wrapper};
39+ barrier.arrive_and_wait ();
40+ auto *bw = bool_wrapper.cast <BoolWrapper *>();
41+ std::this_thread::sleep_for (std::chrono::milliseconds (10 ));
42+ bw->set (true );
43+ });
44+
45+ std::thread t2 ([&]() {
46+ barrier.arrive_and_wait ();
47+ {
48+ py::gil_scoped_acquire ensure_tstate{};
49+ py::scoped_critical_section lock{bool_wrapper};
50+ auto *bw = bool_wrapper.cast <BoolWrapper *>();
51+ output = bw->get ();
52+ }
53+ });
54+
55+ t1.join ();
56+ t2.join ();
57+ }
5058
5159 if (!output) {
5260 throw std::runtime_error (" Scoped critical section test failed: output is false" );
@@ -59,33 +67,44 @@ void test_scoped_critical_section2(const py::handle &cls) {
5967 auto bool_wrapper2 = cls (false );
6068 std::pair<bool , bool > output{false , false };
6169
62- std::thread t1 ([&]() {
63- py::scoped_critical_section lock{bool_wrapper1, bool_wrapper2};
64- barrier.arrive_and_wait ();
65- std::this_thread::sleep_for (std::chrono::milliseconds (10 ));
66- auto *bw1 = bool_wrapper1.cast <BoolWrapper *>();
67- auto *bw2 = bool_wrapper2.cast <BoolWrapper *>();
68- bw1->set (true );
69- bw2->set (true );
70- });
71-
72- std::thread t2 ([&]() {
73- barrier.arrive_and_wait ();
74- py::scoped_critical_section lock{bool_wrapper1};
75- auto *bw1 = bool_wrapper1.cast <BoolWrapper *>();
76- output.first = bw1->get ();
77- });
78-
79- std::thread t3 ([&]() {
80- barrier.arrive_and_wait ();
81- py::scoped_critical_section lock{bool_wrapper2};
82- auto *bw2 = bool_wrapper2.cast <BoolWrapper *>();
83- output.second = bw2->get ();
84- });
85-
86- t1.join ();
87- t2.join ();
88- t3.join ();
70+ {
71+ py::gil_scoped_release gil_release{};
72+
73+ std::thread t1 ([&]() {
74+ py::gil_scoped_acquire ensure_tstate{};
75+ py::scoped_critical_section lock{bool_wrapper1, bool_wrapper2};
76+ barrier.arrive_and_wait ();
77+ std::this_thread::sleep_for (std::chrono::milliseconds (10 ));
78+ auto *bw1 = bool_wrapper1.cast <BoolWrapper *>();
79+ auto *bw2 = bool_wrapper2.cast <BoolWrapper *>();
80+ bw1->set (true );
81+ bw2->set (true );
82+ });
83+
84+ std::thread t2 ([&]() {
85+ barrier.arrive_and_wait ();
86+ {
87+ py::gil_scoped_acquire ensure_tstate{};
88+ py::scoped_critical_section lock{bool_wrapper1};
89+ auto *bw1 = bool_wrapper1.cast <BoolWrapper *>();
90+ output.first = bw1->get ();
91+ }
92+ });
93+
94+ std::thread t3 ([&]() {
95+ barrier.arrive_and_wait ();
96+ {
97+ py::gil_scoped_acquire ensure_tstate{};
98+ py::scoped_critical_section lock{bool_wrapper2};
99+ auto *bw2 = bool_wrapper2.cast <BoolWrapper *>();
100+ output.second = bw2->get ();
101+ }
102+ });
103+
104+ t1.join ();
105+ t2.join ();
106+ t3.join ();
107+ }
89108
90109 if (!output.first || !output.second ) {
91110 throw std::runtime_error (
@@ -98,23 +117,31 @@ void test_scoped_critical_section2_same_object_no_deadlock(const py::handle &cls
98117 auto bool_wrapper = cls (false );
99118 bool output = false ;
100119
101- std::thread t1 ([&]() {
102- py::scoped_critical_section lock{bool_wrapper, bool_wrapper};
103- barrier.arrive_and_wait ();
104- std::this_thread::sleep_for (std::chrono::milliseconds (10 ));
105- auto *bw = bool_wrapper.cast <BoolWrapper *>();
106- bw->set (true );
107- });
108-
109- std::thread t2 ([&]() {
110- barrier.arrive_and_wait ();
111- py::scoped_critical_section lock{bool_wrapper};
112- auto *bw = bool_wrapper.cast <BoolWrapper *>();
113- output = bw->get ();
114- });
115-
116- t1.join ();
117- t2.join ();
120+ {
121+ py::gil_scoped_release gil_release{};
122+
123+ std::thread t1 ([&]() {
124+ py::gil_scoped_acquire ensure_tstate{};
125+ py::scoped_critical_section lock{bool_wrapper, bool_wrapper};
126+ barrier.arrive_and_wait ();
127+ std::this_thread::sleep_for (std::chrono::milliseconds (10 ));
128+ auto *bw = bool_wrapper.cast <BoolWrapper *>();
129+ bw->set (true );
130+ });
131+
132+ std::thread t2 ([&]() {
133+ barrier.arrive_and_wait ();
134+ {
135+ py::gil_scoped_acquire ensure_tstate{};
136+ py::scoped_critical_section lock{bool_wrapper};
137+ auto *bw = bool_wrapper.cast <BoolWrapper *>();
138+ output = bw->get ();
139+ }
140+ });
141+
142+ t1.join ();
143+ t2.join ();
144+ }
118145
119146 if (!output) {
120147 throw std::runtime_error (
0 commit comments