]>
Commit | Line | Data |
---|---|---|
7c673cae | 1 | // |
b32b8144 | 2 | // io_context.cpp |
7c673cae FG |
3 | // ~~~~~~~~~~~~~~ |
4 | // | |
1e59de90 | 5 | // Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
7c673cae FG |
6 | // |
7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
9 | // | |
10 | ||
11 | // Disable autolinking for unit tests. | |
12 | #if !defined(BOOST_ALL_NO_LIB) | |
13 | #define BOOST_ALL_NO_LIB 1 | |
14 | #endif // !defined(BOOST_ALL_NO_LIB) | |
15 | ||
16 | // Test that header file is self-contained. | |
b32b8144 | 17 | #include <boost/asio/io_context.hpp> |
7c673cae FG |
18 | |
19 | #include <sstream> | |
b32b8144 FG |
20 | #include <boost/asio/bind_executor.hpp> |
21 | #include <boost/asio/dispatch.hpp> | |
22 | #include <boost/asio/post.hpp> | |
7c673cae FG |
23 | #include <boost/asio/detail/thread.hpp> |
24 | #include "unit_test.hpp" | |
25 | ||
26 | #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) | |
27 | # include <boost/asio/deadline_timer.hpp> | |
28 | #else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) | |
29 | # include <boost/asio/steady_timer.hpp> | |
30 | #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) | |
31 | ||
32 | #if defined(BOOST_ASIO_HAS_BOOST_BIND) | |
f67539c2 | 33 | # include <boost/bind/bind.hpp> |
7c673cae FG |
34 | #else // defined(BOOST_ASIO_HAS_BOOST_BIND) |
35 | # include <functional> | |
36 | #endif // defined(BOOST_ASIO_HAS_BOOST_BIND) | |
37 | ||
38 | using namespace boost::asio; | |
39 | ||
40 | #if defined(BOOST_ASIO_HAS_BOOST_BIND) | |
41 | namespace bindns = boost; | |
42 | #else // defined(BOOST_ASIO_HAS_BOOST_BIND) | |
43 | namespace bindns = std; | |
44 | #endif | |
45 | ||
46 | #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) | |
47 | typedef deadline_timer timer; | |
48 | namespace chronons = boost::posix_time; | |
b32b8144 | 49 | #elif defined(BOOST_ASIO_HAS_CHRONO) |
7c673cae | 50 | typedef steady_timer timer; |
b32b8144 | 51 | namespace chronons = boost::asio::chrono; |
7c673cae FG |
52 | #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) |
53 | ||
54 | void increment(int* count) | |
55 | { | |
56 | ++(*count); | |
57 | } | |
58 | ||
b32b8144 | 59 | void decrement_to_zero(io_context* ioc, int* count) |
7c673cae FG |
60 | { |
61 | if (*count > 0) | |
62 | { | |
63 | --(*count); | |
64 | ||
65 | int before_value = *count; | |
b32b8144 | 66 | boost::asio::post(*ioc, bindns::bind(decrement_to_zero, ioc, count)); |
7c673cae FG |
67 | |
68 | // Handler execution cannot nest, so count value should remain unchanged. | |
69 | BOOST_ASIO_CHECK(*count == before_value); | |
70 | } | |
71 | } | |
72 | ||
b32b8144 | 73 | void nested_decrement_to_zero(io_context* ioc, int* count) |
7c673cae FG |
74 | { |
75 | if (*count > 0) | |
76 | { | |
77 | --(*count); | |
78 | ||
b32b8144 FG |
79 | boost::asio::dispatch(*ioc, |
80 | bindns::bind(nested_decrement_to_zero, ioc, count)); | |
7c673cae FG |
81 | |
82 | // Handler execution is nested, so count value should now be zero. | |
83 | BOOST_ASIO_CHECK(*count == 0); | |
84 | } | |
85 | } | |
86 | ||
b32b8144 | 87 | void sleep_increment(io_context* ioc, int* count) |
7c673cae | 88 | { |
b32b8144 | 89 | timer t(*ioc, chronons::seconds(2)); |
7c673cae FG |
90 | t.wait(); |
91 | ||
92 | if (++(*count) < 3) | |
b32b8144 | 93 | boost::asio::post(*ioc, bindns::bind(sleep_increment, ioc, count)); |
7c673cae FG |
94 | } |
95 | ||
b32b8144 | 96 | void start_sleep_increments(io_context* ioc, int* count) |
7c673cae FG |
97 | { |
98 | // Give all threads a chance to start. | |
b32b8144 | 99 | timer t(*ioc, chronons::seconds(2)); |
7c673cae FG |
100 | t.wait(); |
101 | ||
102 | // Start the first of three increments. | |
b32b8144 | 103 | boost::asio::post(*ioc, bindns::bind(sleep_increment, ioc, count)); |
7c673cae FG |
104 | } |
105 | ||
106 | void throw_exception() | |
107 | { | |
108 | throw 1; | |
109 | } | |
110 | ||
b32b8144 | 111 | void io_context_run(io_context* ioc) |
7c673cae | 112 | { |
b32b8144 | 113 | ioc->run(); |
7c673cae FG |
114 | } |
115 | ||
b32b8144 | 116 | void io_context_test() |
7c673cae | 117 | { |
b32b8144 | 118 | io_context ioc; |
7c673cae FG |
119 | int count = 0; |
120 | ||
b32b8144 | 121 | boost::asio::post(ioc, bindns::bind(increment, &count)); |
7c673cae FG |
122 | |
123 | // No handlers can be called until run() is called. | |
b32b8144 | 124 | BOOST_ASIO_CHECK(!ioc.stopped()); |
7c673cae FG |
125 | BOOST_ASIO_CHECK(count == 0); |
126 | ||
b32b8144 | 127 | ioc.run(); |
7c673cae FG |
128 | |
129 | // The run() call will not return until all work has finished. | |
b32b8144 | 130 | BOOST_ASIO_CHECK(ioc.stopped()); |
7c673cae FG |
131 | BOOST_ASIO_CHECK(count == 1); |
132 | ||
133 | count = 0; | |
b32b8144 FG |
134 | ioc.restart(); |
135 | boost::asio::post(ioc, bindns::bind(increment, &count)); | |
136 | boost::asio::post(ioc, bindns::bind(increment, &count)); | |
137 | boost::asio::post(ioc, bindns::bind(increment, &count)); | |
138 | boost::asio::post(ioc, bindns::bind(increment, &count)); | |
139 | boost::asio::post(ioc, bindns::bind(increment, &count)); | |
7c673cae FG |
140 | |
141 | // No handlers can be called until run() is called. | |
b32b8144 | 142 | BOOST_ASIO_CHECK(!ioc.stopped()); |
7c673cae FG |
143 | BOOST_ASIO_CHECK(count == 0); |
144 | ||
b32b8144 | 145 | ioc.run(); |
7c673cae FG |
146 | |
147 | // The run() call will not return until all work has finished. | |
b32b8144 | 148 | BOOST_ASIO_CHECK(ioc.stopped()); |
7c673cae FG |
149 | BOOST_ASIO_CHECK(count == 5); |
150 | ||
151 | count = 0; | |
b32b8144 FG |
152 | ioc.restart(); |
153 | executor_work_guard<io_context::executor_type> w = make_work_guard(ioc); | |
154 | boost::asio::post(ioc, bindns::bind(&io_context::stop, &ioc)); | |
155 | BOOST_ASIO_CHECK(!ioc.stopped()); | |
156 | ioc.run(); | |
7c673cae FG |
157 | |
158 | // The only operation executed should have been to stop run(). | |
b32b8144 | 159 | BOOST_ASIO_CHECK(ioc.stopped()); |
7c673cae FG |
160 | BOOST_ASIO_CHECK(count == 0); |
161 | ||
b32b8144 FG |
162 | ioc.restart(); |
163 | boost::asio::post(ioc, bindns::bind(increment, &count)); | |
164 | w.reset(); | |
7c673cae FG |
165 | |
166 | // No handlers can be called until run() is called. | |
b32b8144 | 167 | BOOST_ASIO_CHECK(!ioc.stopped()); |
7c673cae FG |
168 | BOOST_ASIO_CHECK(count == 0); |
169 | ||
b32b8144 | 170 | ioc.run(); |
7c673cae FG |
171 | |
172 | // The run() call will not return until all work has finished. | |
b32b8144 | 173 | BOOST_ASIO_CHECK(ioc.stopped()); |
7c673cae FG |
174 | BOOST_ASIO_CHECK(count == 1); |
175 | ||
176 | count = 10; | |
b32b8144 FG |
177 | ioc.restart(); |
178 | boost::asio::post(ioc, bindns::bind(decrement_to_zero, &ioc, &count)); | |
7c673cae FG |
179 | |
180 | // No handlers can be called until run() is called. | |
b32b8144 | 181 | BOOST_ASIO_CHECK(!ioc.stopped()); |
7c673cae FG |
182 | BOOST_ASIO_CHECK(count == 10); |
183 | ||
b32b8144 | 184 | ioc.run(); |
7c673cae FG |
185 | |
186 | // The run() call will not return until all work has finished. | |
b32b8144 | 187 | BOOST_ASIO_CHECK(ioc.stopped()); |
7c673cae FG |
188 | BOOST_ASIO_CHECK(count == 0); |
189 | ||
190 | count = 10; | |
b32b8144 FG |
191 | ioc.restart(); |
192 | boost::asio::post(ioc, bindns::bind(nested_decrement_to_zero, &ioc, &count)); | |
7c673cae FG |
193 | |
194 | // No handlers can be called until run() is called. | |
b32b8144 | 195 | BOOST_ASIO_CHECK(!ioc.stopped()); |
7c673cae FG |
196 | BOOST_ASIO_CHECK(count == 10); |
197 | ||
b32b8144 | 198 | ioc.run(); |
7c673cae FG |
199 | |
200 | // The run() call will not return until all work has finished. | |
b32b8144 | 201 | BOOST_ASIO_CHECK(ioc.stopped()); |
7c673cae FG |
202 | BOOST_ASIO_CHECK(count == 0); |
203 | ||
204 | count = 10; | |
b32b8144 FG |
205 | ioc.restart(); |
206 | boost::asio::dispatch(ioc, | |
207 | bindns::bind(nested_decrement_to_zero, &ioc, &count)); | |
7c673cae FG |
208 | |
209 | // No handlers can be called until run() is called, even though nested | |
210 | // delivery was specifically allowed in the previous call. | |
b32b8144 | 211 | BOOST_ASIO_CHECK(!ioc.stopped()); |
7c673cae FG |
212 | BOOST_ASIO_CHECK(count == 10); |
213 | ||
b32b8144 | 214 | ioc.run(); |
7c673cae FG |
215 | |
216 | // The run() call will not return until all work has finished. | |
b32b8144 | 217 | BOOST_ASIO_CHECK(ioc.stopped()); |
7c673cae FG |
218 | BOOST_ASIO_CHECK(count == 0); |
219 | ||
220 | count = 0; | |
221 | int count2 = 0; | |
b32b8144 FG |
222 | ioc.restart(); |
223 | BOOST_ASIO_CHECK(!ioc.stopped()); | |
224 | boost::asio::post(ioc, bindns::bind(start_sleep_increments, &ioc, &count)); | |
225 | boost::asio::post(ioc, bindns::bind(start_sleep_increments, &ioc, &count2)); | |
226 | boost::asio::detail::thread thread1(bindns::bind(io_context_run, &ioc)); | |
227 | boost::asio::detail::thread thread2(bindns::bind(io_context_run, &ioc)); | |
7c673cae FG |
228 | thread1.join(); |
229 | thread2.join(); | |
230 | ||
231 | // The run() calls will not return until all work has finished. | |
b32b8144 | 232 | BOOST_ASIO_CHECK(ioc.stopped()); |
7c673cae FG |
233 | BOOST_ASIO_CHECK(count == 3); |
234 | BOOST_ASIO_CHECK(count2 == 3); | |
235 | ||
236 | count = 10; | |
b32b8144 FG |
237 | io_context ioc2; |
238 | boost::asio::dispatch(ioc, boost::asio::bind_executor(ioc2, | |
239 | bindns::bind(decrement_to_zero, &ioc2, &count))); | |
240 | ioc.restart(); | |
241 | BOOST_ASIO_CHECK(!ioc.stopped()); | |
242 | ioc.run(); | |
7c673cae FG |
243 | |
244 | // No decrement_to_zero handlers can be called until run() is called on the | |
b32b8144 FG |
245 | // second io_context object. |
246 | BOOST_ASIO_CHECK(ioc.stopped()); | |
7c673cae FG |
247 | BOOST_ASIO_CHECK(count == 10); |
248 | ||
b32b8144 | 249 | ioc2.run(); |
7c673cae FG |
250 | |
251 | // The run() call will not return until all work has finished. | |
252 | BOOST_ASIO_CHECK(count == 0); | |
253 | ||
254 | count = 0; | |
255 | int exception_count = 0; | |
b32b8144 FG |
256 | ioc.restart(); |
257 | boost::asio::post(ioc, &throw_exception); | |
258 | boost::asio::post(ioc, bindns::bind(increment, &count)); | |
259 | boost::asio::post(ioc, bindns::bind(increment, &count)); | |
260 | boost::asio::post(ioc, &throw_exception); | |
261 | boost::asio::post(ioc, bindns::bind(increment, &count)); | |
7c673cae FG |
262 | |
263 | // No handlers can be called until run() is called. | |
b32b8144 | 264 | BOOST_ASIO_CHECK(!ioc.stopped()); |
7c673cae FG |
265 | BOOST_ASIO_CHECK(count == 0); |
266 | BOOST_ASIO_CHECK(exception_count == 0); | |
267 | ||
268 | for (;;) | |
269 | { | |
270 | try | |
271 | { | |
b32b8144 | 272 | ioc.run(); |
7c673cae FG |
273 | break; |
274 | } | |
275 | catch (int) | |
276 | { | |
277 | ++exception_count; | |
278 | } | |
279 | } | |
280 | ||
281 | // The run() calls will not return until all work has finished. | |
b32b8144 | 282 | BOOST_ASIO_CHECK(ioc.stopped()); |
7c673cae FG |
283 | BOOST_ASIO_CHECK(count == 3); |
284 | BOOST_ASIO_CHECK(exception_count == 2); | |
285 | } | |
286 | ||
b32b8144 | 287 | class test_service : public boost::asio::io_context::service |
7c673cae FG |
288 | { |
289 | public: | |
b32b8144 FG |
290 | static boost::asio::io_context::id id; |
291 | test_service(boost::asio::io_context& s) | |
292 | : boost::asio::io_context::service(s) {} | |
7c673cae FG |
293 | private: |
294 | virtual void shutdown_service() {} | |
295 | }; | |
296 | ||
b32b8144 | 297 | boost::asio::io_context::id test_service::id; |
7c673cae | 298 | |
b32b8144 | 299 | void io_context_service_test() |
7c673cae | 300 | { |
b32b8144 FG |
301 | boost::asio::io_context ioc1; |
302 | boost::asio::io_context ioc2; | |
303 | boost::asio::io_context ioc3; | |
7c673cae FG |
304 | |
305 | // Implicit service registration. | |
306 | ||
b32b8144 | 307 | boost::asio::use_service<test_service>(ioc1); |
7c673cae | 308 | |
b32b8144 | 309 | BOOST_ASIO_CHECK(boost::asio::has_service<test_service>(ioc1)); |
7c673cae | 310 | |
b32b8144 | 311 | test_service* svc1 = new test_service(ioc1); |
7c673cae FG |
312 | try |
313 | { | |
b32b8144 | 314 | boost::asio::add_service(ioc1, svc1); |
7c673cae FG |
315 | BOOST_ASIO_ERROR("add_service did not throw"); |
316 | } | |
317 | catch (boost::asio::service_already_exists&) | |
318 | { | |
319 | } | |
320 | delete svc1; | |
321 | ||
322 | // Explicit service registration. | |
323 | ||
b32b8144 FG |
324 | test_service* svc2 = new test_service(ioc2); |
325 | boost::asio::add_service(ioc2, svc2); | |
7c673cae | 326 | |
b32b8144 FG |
327 | BOOST_ASIO_CHECK(boost::asio::has_service<test_service>(ioc2)); |
328 | BOOST_ASIO_CHECK(&boost::asio::use_service<test_service>(ioc2) == svc2); | |
7c673cae | 329 | |
b32b8144 | 330 | test_service* svc3 = new test_service(ioc2); |
7c673cae FG |
331 | try |
332 | { | |
b32b8144 | 333 | boost::asio::add_service(ioc2, svc3); |
7c673cae FG |
334 | BOOST_ASIO_ERROR("add_service did not throw"); |
335 | } | |
336 | catch (boost::asio::service_already_exists&) | |
337 | { | |
338 | } | |
339 | delete svc3; | |
340 | ||
341 | // Explicit registration with invalid owner. | |
342 | ||
b32b8144 | 343 | test_service* svc4 = new test_service(ioc2); |
7c673cae FG |
344 | try |
345 | { | |
b32b8144 | 346 | boost::asio::add_service(ioc3, svc4); |
7c673cae FG |
347 | BOOST_ASIO_ERROR("add_service did not throw"); |
348 | } | |
349 | catch (boost::asio::invalid_service_owner&) | |
350 | { | |
351 | } | |
352 | delete svc4; | |
353 | ||
b32b8144 | 354 | BOOST_ASIO_CHECK(!boost::asio::has_service<test_service>(ioc3)); |
7c673cae FG |
355 | } |
356 | ||
20effc67 TL |
357 | void io_context_executor_query_test() |
358 | { | |
359 | io_context ioc; | |
360 | ||
361 | BOOST_ASIO_CHECK( | |
362 | &boost::asio::query(ioc.get_executor(), | |
363 | boost::asio::execution::context) | |
364 | == &ioc); | |
365 | ||
366 | BOOST_ASIO_CHECK( | |
367 | boost::asio::query(ioc.get_executor(), | |
368 | boost::asio::execution::blocking) | |
369 | == boost::asio::execution::blocking.possibly); | |
370 | ||
371 | BOOST_ASIO_CHECK( | |
372 | boost::asio::query(ioc.get_executor(), | |
373 | boost::asio::execution::blocking.possibly) | |
374 | == boost::asio::execution::blocking.possibly); | |
375 | ||
376 | BOOST_ASIO_CHECK( | |
377 | boost::asio::query(ioc.get_executor(), | |
378 | boost::asio::execution::outstanding_work) | |
379 | == boost::asio::execution::outstanding_work.untracked); | |
380 | ||
381 | BOOST_ASIO_CHECK( | |
382 | boost::asio::query(ioc.get_executor(), | |
383 | boost::asio::execution::outstanding_work.untracked) | |
384 | == boost::asio::execution::outstanding_work.untracked); | |
385 | ||
386 | BOOST_ASIO_CHECK( | |
387 | boost::asio::query(ioc.get_executor(), | |
388 | boost::asio::execution::relationship) | |
389 | == boost::asio::execution::relationship.fork); | |
390 | ||
391 | BOOST_ASIO_CHECK( | |
392 | boost::asio::query(ioc.get_executor(), | |
393 | boost::asio::execution::relationship.fork) | |
394 | == boost::asio::execution::relationship.fork); | |
395 | ||
396 | BOOST_ASIO_CHECK( | |
397 | boost::asio::query(ioc.get_executor(), | |
398 | boost::asio::execution::mapping) | |
399 | == boost::asio::execution::mapping.thread); | |
400 | ||
401 | BOOST_ASIO_CHECK( | |
402 | boost::asio::query(ioc.get_executor(), | |
403 | boost::asio::execution::allocator) | |
404 | == std::allocator<void>()); | |
405 | } | |
406 | ||
407 | void io_context_executor_execute_test() | |
408 | { | |
409 | io_context ioc; | |
410 | int count = 0; | |
411 | ||
412 | boost::asio::execution::execute(ioc.get_executor(), | |
413 | bindns::bind(increment, &count)); | |
414 | ||
415 | // No handlers can be called until run() is called. | |
416 | BOOST_ASIO_CHECK(!ioc.stopped()); | |
417 | BOOST_ASIO_CHECK(count == 0); | |
418 | ||
419 | ioc.run(); | |
420 | ||
421 | // The run() call will not return until all work has finished. | |
422 | BOOST_ASIO_CHECK(ioc.stopped()); | |
423 | BOOST_ASIO_CHECK(count == 1); | |
424 | ||
425 | count = 0; | |
426 | ioc.restart(); | |
427 | boost::asio::execution::execute( | |
428 | boost::asio::require(ioc.get_executor(), | |
429 | boost::asio::execution::blocking.possibly), | |
430 | bindns::bind(increment, &count)); | |
431 | ||
432 | // No handlers can be called until run() is called. | |
433 | BOOST_ASIO_CHECK(!ioc.stopped()); | |
434 | BOOST_ASIO_CHECK(count == 0); | |
435 | ||
436 | ioc.run(); | |
437 | ||
438 | // The run() call will not return until all work has finished. | |
439 | BOOST_ASIO_CHECK(ioc.stopped()); | |
440 | BOOST_ASIO_CHECK(count == 1); | |
441 | ||
442 | count = 0; | |
443 | ioc.restart(); | |
444 | boost::asio::execution::execute( | |
445 | boost::asio::require(ioc.get_executor(), | |
446 | boost::asio::execution::blocking.never), | |
447 | bindns::bind(increment, &count)); | |
448 | ||
449 | // No handlers can be called until run() is called. | |
450 | BOOST_ASIO_CHECK(!ioc.stopped()); | |
451 | BOOST_ASIO_CHECK(count == 0); | |
452 | ||
453 | ioc.run(); | |
454 | ||
455 | // The run() call will not return until all work has finished. | |
456 | BOOST_ASIO_CHECK(ioc.stopped()); | |
457 | BOOST_ASIO_CHECK(count == 1); | |
458 | ||
459 | count = 0; | |
460 | ioc.restart(); | |
461 | BOOST_ASIO_CHECK(!ioc.stopped()); | |
462 | ||
463 | boost::asio::execution::execute( | |
464 | boost::asio::require(ioc.get_executor(), | |
465 | boost::asio::execution::blocking.never, | |
466 | boost::asio::execution::outstanding_work.tracked), | |
467 | bindns::bind(increment, &count)); | |
468 | ||
469 | // No handlers can be called until run() is called. | |
470 | BOOST_ASIO_CHECK(!ioc.stopped()); | |
471 | BOOST_ASIO_CHECK(count == 0); | |
472 | ||
473 | ioc.run(); | |
474 | ||
475 | // The run() call will not return until all work has finished. | |
476 | BOOST_ASIO_CHECK(ioc.stopped()); | |
477 | BOOST_ASIO_CHECK(count == 1); | |
478 | ||
479 | count = 0; | |
480 | ioc.restart(); | |
481 | boost::asio::execution::execute( | |
482 | boost::asio::require(ioc.get_executor(), | |
483 | boost::asio::execution::blocking.never, | |
484 | boost::asio::execution::outstanding_work.untracked), | |
485 | bindns::bind(increment, &count)); | |
486 | ||
487 | // No handlers can be called until run() is called. | |
488 | BOOST_ASIO_CHECK(!ioc.stopped()); | |
489 | BOOST_ASIO_CHECK(count == 0); | |
490 | ||
491 | ioc.run(); | |
492 | ||
493 | // The run() call will not return until all work has finished. | |
494 | BOOST_ASIO_CHECK(ioc.stopped()); | |
495 | BOOST_ASIO_CHECK(count == 1); | |
496 | ||
497 | count = 0; | |
498 | ioc.restart(); | |
499 | boost::asio::execution::execute( | |
500 | boost::asio::require(ioc.get_executor(), | |
501 | boost::asio::execution::blocking.never, | |
502 | boost::asio::execution::outstanding_work.untracked, | |
503 | boost::asio::execution::relationship.fork), | |
504 | bindns::bind(increment, &count)); | |
505 | ||
506 | // No handlers can be called until run() is called. | |
507 | BOOST_ASIO_CHECK(!ioc.stopped()); | |
508 | BOOST_ASIO_CHECK(count == 0); | |
509 | ||
510 | ioc.run(); | |
511 | ||
512 | // The run() call will not return until all work has finished. | |
513 | BOOST_ASIO_CHECK(ioc.stopped()); | |
514 | BOOST_ASIO_CHECK(count == 1); | |
515 | ||
516 | count = 0; | |
517 | ioc.restart(); | |
518 | boost::asio::execution::execute( | |
519 | boost::asio::require(ioc.get_executor(), | |
520 | boost::asio::execution::blocking.never, | |
521 | boost::asio::execution::outstanding_work.untracked, | |
522 | boost::asio::execution::relationship.continuation), | |
523 | bindns::bind(increment, &count)); | |
524 | ||
525 | // No handlers can be called until run() is called. | |
526 | BOOST_ASIO_CHECK(!ioc.stopped()); | |
527 | BOOST_ASIO_CHECK(count == 0); | |
528 | ||
529 | ioc.run(); | |
530 | ||
531 | // The run() call will not return until all work has finished. | |
532 | BOOST_ASIO_CHECK(ioc.stopped()); | |
533 | BOOST_ASIO_CHECK(count == 1); | |
534 | ||
535 | count = 0; | |
536 | ioc.restart(); | |
537 | boost::asio::execution::execute( | |
538 | boost::asio::prefer( | |
539 | boost::asio::require(ioc.get_executor(), | |
540 | boost::asio::execution::blocking.never, | |
541 | boost::asio::execution::outstanding_work.untracked, | |
542 | boost::asio::execution::relationship.continuation), | |
543 | boost::asio::execution::allocator(std::allocator<void>())), | |
544 | bindns::bind(increment, &count)); | |
545 | ||
546 | // No handlers can be called until run() is called. | |
547 | BOOST_ASIO_CHECK(!ioc.stopped()); | |
548 | BOOST_ASIO_CHECK(count == 0); | |
549 | ||
550 | ioc.run(); | |
551 | ||
552 | // The run() call will not return until all work has finished. | |
553 | BOOST_ASIO_CHECK(ioc.stopped()); | |
554 | BOOST_ASIO_CHECK(count == 1); | |
555 | ||
556 | count = 0; | |
557 | ioc.restart(); | |
558 | boost::asio::execution::execute( | |
559 | boost::asio::prefer( | |
560 | boost::asio::require(ioc.get_executor(), | |
561 | boost::asio::execution::blocking.never, | |
562 | boost::asio::execution::outstanding_work.untracked, | |
563 | boost::asio::execution::relationship.continuation), | |
564 | boost::asio::execution::allocator), | |
565 | bindns::bind(increment, &count)); | |
566 | ||
567 | // No handlers can be called until run() is called. | |
568 | BOOST_ASIO_CHECK(!ioc.stopped()); | |
569 | BOOST_ASIO_CHECK(count == 0); | |
570 | ||
571 | ioc.run(); | |
572 | ||
573 | // The run() call will not return until all work has finished. | |
574 | BOOST_ASIO_CHECK(ioc.stopped()); | |
575 | BOOST_ASIO_CHECK(count == 1); | |
576 | } | |
577 | ||
7c673cae FG |
578 | BOOST_ASIO_TEST_SUITE |
579 | ( | |
b32b8144 FG |
580 | "io_context", |
581 | BOOST_ASIO_TEST_CASE(io_context_test) | |
582 | BOOST_ASIO_TEST_CASE(io_context_service_test) | |
20effc67 TL |
583 | BOOST_ASIO_TEST_CASE(io_context_executor_query_test) |
584 | BOOST_ASIO_TEST_CASE(io_context_executor_execute_test) | |
7c673cae | 585 | ) |