1212#include < logics/ArithLogic.h>
1313
1414#include < array>
15- #include < chrono>
1615#include < future>
1716#include < thread>
18-
19- using namespace std ::chrono_literals ;
17+ # include < condition_variable >
18+ # include < mutex >
2019
2120namespace opensmt {
2221
23- constexpr auto const sleep_amount = 10ms;
22+ std::mutex mutex;
23+ std::condition_variable condVar;
24+ size_t ackReadyCnt{0 };
25+ bool reqContinueFlag{false };
26+
27+ class TestMainSolver : public MainSolver {
28+ public:
29+ using MainSolver::MainSolver;
30+
31+ protected:
32+ sstat solve_ (vec<FrameId> const & enabledFrames) override {
33+ std::unique_lock lock (mutex);
34+ ++ackReadyCnt;
35+ lock.unlock ();
36+ condVar.notify_all ();
37+ lock.lock ();
38+ condVar.wait (lock, []{ return reqContinueFlag; });
39+ lock.unlock ();
40+
41+ return MainSolver::solve_ (enabledFrames);
42+ }
43+ };
2444
2545class StopTest : public ::testing::Test {
46+ public:
47+
48+ ~StopTest () {
49+ resetGlobalStop ();
50+
51+ ackReadyCnt = 0 ;
52+ reqContinueFlag = false ;
53+ }
2654protected:
2755 static constexpr size_t nSolvers = 2 ;
2856
2957 void init () {
58+ assert (not globallyStopped ());
59+
3060 for (size_t i = 0 ; i < nSolvers; ++i) {
3161 auto & logic = logics[i];
3262 auto & solver = solvers[i];
@@ -54,24 +84,37 @@ class StopTest : public ::testing::Test {
5484 }
5585 }
5686
57- void notifyAll () {
87+ void waitReadyAll () {
88+ std::unique_lock lock (mutex);
89+ condVar.wait (lock, []{ return ackReadyCnt == nSolvers; });
90+ }
91+
92+ void reqContinue () {
93+ {
94+ std::lock_guard lock (mutex);
95+ reqContinueFlag = true ;
96+ }
97+ condVar.notify_all ();
98+ }
99+
100+ void notifyStopAll () {
58101 for (size_t i = 0 ; i < nSolvers; ++i) {
59102 solvers[i].notifyStop ();
60103 }
61104 }
62105
63- std::array<sstat, nSolvers> waitAll () {
106+ std::array<sstat, nSolvers> joinAll () {
64107 std::array<sstat, nSolvers> results;
65108 for (size_t i = 0 ; i < nSolvers; ++i) {
66- results[i] = wait (i);
109+ results[i] = join (i);
67110 }
68111 return results;
69112 }
70113
71114 SMTConfig config{};
72115 std::array<ArithLogic, nSolvers> logics{Logic_t::QF_LRA, Logic_t::QF_LRA};
73- std::array<MainSolver , nSolvers> solvers{MainSolver {logics[0 ], config, " solver 1" },
74- MainSolver {logics[1 ], config, " solver 2" }};
116+ std::array<TestMainSolver , nSolvers> solvers{TestMainSolver {logics[0 ], config, " solver 1" },
117+ TestMainSolver {logics[1 ], config, " solver 2" }};
75118
76119 std::array<std::thread, nSolvers> threads;
77120 std::array<std::future<sstat>, nSolvers> futures;
@@ -85,12 +128,11 @@ class StopTest : public ::testing::Test {
85128
86129 void solveOnBackground (size_t idx) {
87130 runOnBackground (idx, [this , idx] {
88- std::this_thread::sleep_for (sleep_amount);
89131 return solvers[idx].check ();
90132 });
91133 }
92134
93- sstat wait (size_t idx) {
135+ sstat join (size_t idx) {
94136 threads[idx].join ();
95137 return futures[idx].get ();
96138 }
@@ -100,7 +142,9 @@ TEST_F(StopTest, test_NoStop) {
100142 init ();
101143
102144 solveAllOnBackground ();
103- auto results = waitAll ();
145+ waitReadyAll ();
146+ reqContinue ();
147+ auto results = joinAll ();
104148
105149 ASSERT_EQ (results, std::to_array ({s_False, s_False}));
106150}
@@ -110,7 +154,9 @@ TEST_F(StopTest, test_LocalPreStop) {
110154
111155 solvers.front ().notifyStop ();
112156 solveAllOnBackground ();
113- auto results = waitAll ();
157+ waitReadyAll ();
158+ reqContinue ();
159+ auto results = joinAll ();
114160
115161 ASSERT_EQ (results, std::to_array ({s_Undef, s_False}));
116162}
@@ -120,17 +166,21 @@ TEST_F(StopTest, test_GlobalPreStop) {
120166
121167 notifyGlobalStop ();
122168 solveAllOnBackground ();
123- auto results = waitAll ();
169+ waitReadyAll ();
170+ reqContinue ();
171+ auto results = joinAll ();
124172
125173 ASSERT_EQ (results, std::to_array ({s_Undef, s_Undef}));
126174}
127175
128176TEST_F (StopTest, test_AllLocalPreStop) {
129177 init ();
130178
131- notifyAll ();
179+ notifyStopAll ();
132180 solveAllOnBackground ();
133- auto results = waitAll ();
181+ waitReadyAll ();
182+ reqContinue ();
183+ auto results = joinAll ();
134184
135185 ASSERT_EQ (results, std::to_array ({s_Undef, s_Undef}));
136186}
@@ -141,9 +191,10 @@ TEST_F(StopTest, test_LocalPostStop) {
141191 init ();
142192
143193 solveAllOnBackground ();
144- std::this_thread::sleep_for (sleep_amount / 10 );
194+ waitReadyAll ( );
145195 solvers.front ().notifyStop ();
146- auto results = waitAll ();
196+ reqContinue ();
197+ auto results = joinAll ();
147198
148199 ASSERT_EQ (results, std::to_array ({s_Undef, s_False}));
149200}
@@ -152,9 +203,10 @@ TEST_F(StopTest, test_GlobalPostStop) {
152203 init ();
153204
154205 solveAllOnBackground ();
155- std::this_thread::sleep_for (sleep_amount / 10 );
206+ waitReadyAll ( );
156207 notifyGlobalStop ();
157- auto results = waitAll ();
208+ reqContinue ();
209+ auto results = joinAll ();
158210
159211 ASSERT_EQ (results, std::to_array ({s_Undef, s_Undef}));
160212}
@@ -163,45 +215,10 @@ TEST_F(StopTest, test_AllLocalPostStop) {
163215 init ();
164216
165217 solveAllOnBackground ();
166- std::this_thread::sleep_for (sleep_amount / 10 );
167- notifyAll ();
168- auto results = waitAll ();
169-
170- ASSERT_EQ (results, std::to_array ({s_Undef, s_Undef}));
171- }
172-
173- TEST_F (StopTest, test_LocalTimeout) {
174- init ();
175-
176- solveAllOnBackground ();
177- if (futures.front ().wait_for (sleep_amount / 2 ) != std::future_status::timeout) { ASSERT_TRUE (false ); }
178-
179- solvers.front ().notifyStop ();
180- auto results = waitAll ();
181-
182- ASSERT_EQ (results, std::to_array ({s_Undef, s_False}));
183- }
184-
185- TEST_F (StopTest, test_GlobalTimeout) {
186- init ();
187-
188- solveAllOnBackground ();
189- if (futures.front ().wait_for (sleep_amount / 2 ) != std::future_status::timeout) { ASSERT_TRUE (false ); }
190-
191- notifyGlobalStop ();
192- auto results = waitAll ();
193-
194- ASSERT_EQ (results, std::to_array ({s_Undef, s_Undef}));
195- }
196-
197- TEST_F (StopTest, test_AllLocalTimeout) {
198- init ();
199-
200- solveAllOnBackground ();
201- if (futures.front ().wait_for (sleep_amount / 2 ) != std::future_status::timeout) { ASSERT_TRUE (false ); }
202-
203- notifyAll ();
204- auto results = waitAll ();
218+ waitReadyAll ();
219+ notifyStopAll ();
220+ reqContinue ();
221+ auto results = joinAll ();
205222
206223 ASSERT_EQ (results, std::to_array ({s_Undef, s_Undef}));
207224}
0 commit comments