]>
Commit | Line | Data |
---|---|---|
20effc67 TL |
1 | // |
2 | // schedule.cpp | |
3 | // ~~~~~~~~~~~~ | |
4 | // | |
1e59de90 | 5 | // Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
20effc67 TL |
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. | |
17 | #include <boost/asio/execution/schedule.hpp> | |
18 | ||
19 | #include <boost/system/error_code.hpp> | |
20 | #include <boost/asio/execution/sender.hpp> | |
21 | #include <boost/asio/execution/submit.hpp> | |
22 | #include <boost/asio/traits/connect_member.hpp> | |
23 | #include <boost/asio/traits/start_member.hpp> | |
24 | #include <boost/asio/traits/submit_member.hpp> | |
25 | #include "../unit_test.hpp" | |
26 | ||
27 | namespace exec = boost::asio::execution; | |
28 | ||
29 | struct operation_state | |
30 | { | |
31 | void start() BOOST_ASIO_NOEXCEPT | |
32 | { | |
33 | } | |
34 | }; | |
35 | ||
36 | namespace boost { | |
37 | namespace asio { | |
38 | namespace traits { | |
39 | ||
40 | #if !defined(BOOST_ASIO_HAS_DEDUCED_START_MEMBER_TRAIT) | |
41 | ||
42 | template <> | |
43 | struct start_member<operation_state> | |
44 | { | |
45 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
46 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
47 | typedef void result_type; | |
48 | }; | |
49 | ||
50 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_START_MEMBER_TRAIT) | |
51 | ||
52 | } // namespace traits | |
53 | } // namespace asio | |
54 | } // namespace boost | |
55 | ||
56 | struct sender : exec::sender_base | |
57 | { | |
58 | sender() | |
59 | { | |
60 | } | |
61 | ||
62 | template <typename R> | |
63 | operation_state connect(BOOST_ASIO_MOVE_ARG(R) r) const | |
64 | { | |
65 | (void)r; | |
66 | return operation_state(); | |
67 | } | |
68 | ||
69 | template <typename R> | |
70 | void submit(BOOST_ASIO_MOVE_ARG(R) r) const | |
71 | { | |
72 | typename boost::asio::decay<R>::type tmp(BOOST_ASIO_MOVE_CAST(R)(r)); | |
73 | exec::set_value(tmp); | |
74 | } | |
75 | }; | |
76 | ||
77 | namespace boost { | |
78 | namespace asio { | |
79 | namespace traits { | |
80 | ||
81 | #if !defined(BOOST_ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT) | |
82 | ||
83 | template <typename R> | |
84 | struct connect_member<const sender, R> | |
85 | { | |
86 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
87 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); | |
88 | typedef operation_state result_type; | |
89 | }; | |
90 | ||
91 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT) | |
92 | ||
93 | #if !defined(BOOST_ASIO_HAS_DEDUCED_SUBMIT_MEMBER_TRAIT) | |
94 | ||
95 | template <typename R> | |
96 | struct submit_member<const sender, R> | |
97 | { | |
98 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
99 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); | |
100 | typedef void result_type; | |
101 | }; | |
102 | ||
103 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_SUBMIT_MEMBER_TRAIT) | |
104 | ||
105 | } // namespace traits | |
106 | } // namespace asio | |
107 | } // namespace boost | |
108 | ||
109 | struct no_schedule | |
110 | { | |
111 | }; | |
112 | ||
113 | struct const_member_schedule | |
114 | { | |
115 | sender schedule() const BOOST_ASIO_NOEXCEPT | |
116 | { | |
117 | return sender(); | |
118 | } | |
119 | }; | |
120 | ||
121 | #if !defined(BOOST_ASIO_HAS_DEDUCED_SCHEDULE_MEMBER_TRAIT) | |
122 | ||
123 | namespace boost { | |
124 | namespace asio { | |
125 | namespace traits { | |
126 | ||
127 | template <> | |
128 | struct schedule_member<const const_member_schedule> | |
129 | { | |
130 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
131 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
132 | typedef sender result_type; | |
133 | }; | |
134 | ||
135 | } // namespace traits | |
136 | } // namespace asio | |
137 | } // namespace boost | |
138 | ||
139 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_SCHEDULE_MEMBER_TRAIT) | |
140 | ||
141 | struct free_schedule_const_receiver | |
142 | { | |
143 | friend sender schedule( | |
144 | const free_schedule_const_receiver&) BOOST_ASIO_NOEXCEPT | |
145 | { | |
146 | return sender(); | |
147 | } | |
148 | }; | |
149 | ||
150 | #if !defined(BOOST_ASIO_HAS_DEDUCED_SCHEDULE_FREE_TRAIT) | |
151 | ||
152 | namespace boost { | |
153 | namespace asio { | |
154 | namespace traits { | |
155 | ||
156 | template <> | |
157 | struct schedule_free<const free_schedule_const_receiver> | |
158 | { | |
159 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
160 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
161 | typedef sender result_type; | |
162 | }; | |
163 | ||
164 | } // namespace traits | |
165 | } // namespace asio | |
166 | } // namespace boost | |
167 | ||
168 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_SCHEDULE_FREE_TRAIT) | |
169 | ||
170 | struct non_const_member_schedule | |
171 | { | |
172 | sender schedule() BOOST_ASIO_NOEXCEPT | |
173 | { | |
174 | return sender(); | |
175 | } | |
176 | }; | |
177 | ||
178 | #if !defined(BOOST_ASIO_HAS_DEDUCED_SCHEDULE_MEMBER_TRAIT) | |
179 | ||
180 | namespace boost { | |
181 | namespace asio { | |
182 | namespace traits { | |
183 | ||
184 | template <> | |
185 | struct schedule_member<non_const_member_schedule> | |
186 | { | |
187 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
188 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
189 | typedef sender result_type; | |
190 | }; | |
191 | ||
192 | } // namespace traits | |
193 | } // namespace asio | |
194 | } // namespace boost | |
195 | ||
196 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_SCHEDULE_MEMBER_TRAIT) | |
197 | ||
198 | struct free_schedule_non_const_receiver | |
199 | { | |
200 | friend sender schedule( | |
201 | free_schedule_non_const_receiver&) BOOST_ASIO_NOEXCEPT | |
202 | { | |
203 | return sender(); | |
204 | } | |
205 | }; | |
206 | ||
207 | #if !defined(BOOST_ASIO_HAS_DEDUCED_SCHEDULE_FREE_TRAIT) | |
208 | ||
209 | namespace boost { | |
210 | namespace asio { | |
211 | namespace traits { | |
212 | ||
213 | template <> | |
214 | struct schedule_free<free_schedule_non_const_receiver> | |
215 | { | |
216 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
217 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
218 | typedef sender result_type; | |
219 | }; | |
220 | ||
221 | } // namespace traits | |
222 | } // namespace asio | |
223 | } // namespace boost | |
224 | ||
225 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_SCHEDULE_FREE_TRAIT) | |
226 | ||
227 | struct executor | |
228 | { | |
229 | executor() | |
230 | { | |
231 | } | |
232 | ||
233 | executor(const executor&) BOOST_ASIO_NOEXCEPT | |
234 | { | |
235 | } | |
236 | ||
237 | #if defined(BOOST_ASIO_HAS_MOVE) | |
238 | executor(executor&&) BOOST_ASIO_NOEXCEPT | |
239 | { | |
240 | } | |
241 | #endif // defined(BOOST_ASIO_HAS_MOVE) | |
242 | ||
243 | template <typename F> | |
244 | void execute(BOOST_ASIO_MOVE_ARG(F) f) const BOOST_ASIO_NOEXCEPT | |
245 | { | |
246 | typename boost::asio::decay<F>::type tmp(BOOST_ASIO_MOVE_CAST(F)(f)); | |
247 | tmp(); | |
248 | } | |
249 | ||
250 | bool operator==(const executor&) const BOOST_ASIO_NOEXCEPT | |
251 | { | |
252 | return true; | |
253 | } | |
254 | ||
255 | bool operator!=(const executor&) const BOOST_ASIO_NOEXCEPT | |
256 | { | |
257 | return false; | |
258 | } | |
259 | }; | |
260 | ||
261 | namespace boost { | |
262 | namespace asio { | |
263 | namespace traits { | |
264 | ||
265 | #if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) | |
266 | ||
267 | template <typename F> | |
268 | struct execute_member<executor, F> | |
269 | { | |
270 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
271 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
272 | typedef void result_type; | |
273 | }; | |
274 | ||
275 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT) | |
276 | #if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) | |
277 | ||
278 | template <> | |
279 | struct equality_comparable<executor> | |
280 | { | |
281 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
282 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
283 | }; | |
284 | ||
285 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) | |
286 | ||
287 | } // namespace traits | |
288 | } // namespace asio | |
289 | } // namespace boost | |
290 | ||
291 | void test_can_schedule() | |
292 | { | |
293 | BOOST_ASIO_CONSTEXPR bool b1 = exec::can_schedule< | |
294 | no_schedule&>::value; | |
295 | BOOST_ASIO_CHECK(b1 == false); | |
296 | ||
297 | BOOST_ASIO_CONSTEXPR bool b2 = exec::can_schedule< | |
298 | const no_schedule&>::value; | |
299 | BOOST_ASIO_CHECK(b2 == false); | |
300 | ||
301 | BOOST_ASIO_CONSTEXPR bool b3 = exec::can_schedule< | |
302 | const_member_schedule&>::value; | |
303 | BOOST_ASIO_CHECK(b3 == true); | |
304 | ||
305 | BOOST_ASIO_CONSTEXPR bool b4 = exec::can_schedule< | |
306 | const const_member_schedule&>::value; | |
307 | BOOST_ASIO_CHECK(b4 == true); | |
308 | ||
309 | BOOST_ASIO_CONSTEXPR bool b5 = exec::can_schedule< | |
310 | free_schedule_const_receiver&>::value; | |
311 | BOOST_ASIO_CHECK(b5 == true); | |
312 | ||
313 | BOOST_ASIO_CONSTEXPR bool b6 = exec::can_schedule< | |
314 | const free_schedule_const_receiver&>::value; | |
315 | BOOST_ASIO_CHECK(b6 == true); | |
316 | ||
317 | BOOST_ASIO_CONSTEXPR bool b7 = exec::can_schedule< | |
318 | non_const_member_schedule&>::value; | |
319 | BOOST_ASIO_CHECK(b7 == true); | |
320 | ||
321 | BOOST_ASIO_CONSTEXPR bool b8 = exec::can_schedule< | |
322 | const non_const_member_schedule&>::value; | |
323 | BOOST_ASIO_CHECK(b8 == false); | |
324 | ||
325 | BOOST_ASIO_CONSTEXPR bool b9 = exec::can_schedule< | |
326 | free_schedule_non_const_receiver&>::value; | |
327 | BOOST_ASIO_CHECK(b9 == true); | |
328 | ||
329 | BOOST_ASIO_CONSTEXPR bool b10 = exec::can_schedule< | |
330 | const free_schedule_non_const_receiver&>::value; | |
331 | BOOST_ASIO_CHECK(b10 == false); | |
332 | ||
333 | BOOST_ASIO_CONSTEXPR bool b11 = exec::can_schedule< | |
334 | executor&>::value; | |
335 | BOOST_ASIO_CHECK(b11 == true); | |
336 | ||
337 | BOOST_ASIO_CONSTEXPR bool b12 = exec::can_schedule< | |
338 | const executor&>::value; | |
339 | BOOST_ASIO_CHECK(b12 == true); | |
340 | } | |
341 | ||
342 | struct receiver | |
343 | { | |
344 | int* count_; | |
345 | ||
346 | receiver(int* count) | |
347 | : count_(count) | |
348 | { | |
349 | } | |
350 | ||
351 | receiver(const receiver& other) BOOST_ASIO_NOEXCEPT | |
352 | : count_(other.count_) | |
353 | { | |
354 | } | |
355 | ||
356 | #if defined(BOOST_ASIO_HAS_MOVE) | |
357 | receiver(receiver&& other) BOOST_ASIO_NOEXCEPT | |
358 | : count_(other.count_) | |
359 | { | |
360 | other.count_ = 0; | |
361 | } | |
362 | #endif // defined(BOOST_ASIO_HAS_MOVE) | |
363 | ||
364 | void set_value() BOOST_ASIO_NOEXCEPT | |
365 | { | |
366 | ++(*count_); | |
367 | } | |
368 | ||
369 | template <typename E> | |
370 | void set_error(BOOST_ASIO_MOVE_ARG(E) e) BOOST_ASIO_NOEXCEPT | |
371 | { | |
372 | (void)e; | |
373 | } | |
374 | ||
375 | void set_done() BOOST_ASIO_NOEXCEPT | |
376 | { | |
377 | } | |
378 | }; | |
379 | ||
380 | namespace boost { | |
381 | namespace asio { | |
382 | namespace traits { | |
383 | ||
384 | #if !defined(BOOST_ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT) | |
385 | ||
386 | template <> | |
387 | struct set_value_member<receiver, void()> | |
388 | { | |
389 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
390 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
391 | typedef void result_type; | |
392 | }; | |
393 | ||
394 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT) | |
395 | ||
396 | #if !defined(BOOST_ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT) | |
397 | ||
398 | template <typename E> | |
399 | struct set_error_member<receiver, E> | |
400 | { | |
401 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
402 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
403 | typedef void result_type; | |
404 | }; | |
405 | ||
406 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT) | |
407 | ||
408 | #if !defined(BOOST_ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT) | |
409 | ||
410 | template <> | |
411 | struct set_done_member<receiver> | |
412 | { | |
413 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | |
414 | BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); | |
415 | typedef void result_type; | |
416 | }; | |
417 | ||
418 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT) | |
419 | ||
420 | } // namespace traits | |
421 | } // namespace asio | |
422 | } // namespace boost | |
423 | ||
424 | void test_schedule() | |
425 | { | |
426 | int count = 0; | |
427 | const_member_schedule ex1 = {}; | |
428 | exec::submit( | |
429 | exec::schedule(ex1), | |
430 | receiver(&count)); | |
431 | BOOST_ASIO_CHECK(count == 1); | |
432 | ||
433 | count = 0; | |
434 | const const_member_schedule ex2 = {}; | |
435 | exec::submit( | |
436 | exec::schedule(ex2), | |
437 | receiver(&count)); | |
438 | BOOST_ASIO_CHECK(count == 1); | |
439 | ||
440 | count = 0; | |
441 | exec::submit( | |
442 | exec::schedule(const_member_schedule()), | |
443 | receiver(&count)); | |
444 | BOOST_ASIO_CHECK(count == 1); | |
445 | ||
446 | count = 0; | |
447 | free_schedule_const_receiver ex3 = {}; | |
448 | exec::submit( | |
449 | exec::schedule(ex3), | |
450 | receiver(&count)); | |
451 | BOOST_ASIO_CHECK(count == 1); | |
452 | ||
453 | count = 0; | |
454 | const free_schedule_const_receiver ex4 = {}; | |
455 | exec::submit( | |
456 | exec::schedule(ex4), | |
457 | receiver(&count)); | |
458 | BOOST_ASIO_CHECK(count == 1); | |
459 | ||
460 | count = 0; | |
461 | exec::submit( | |
462 | exec::schedule(free_schedule_const_receiver()), | |
463 | receiver(&count)); | |
464 | BOOST_ASIO_CHECK(count == 1); | |
465 | ||
466 | count = 0; | |
467 | non_const_member_schedule ex5 = {}; | |
468 | exec::submit( | |
469 | exec::schedule(ex5), | |
470 | receiver(&count)); | |
471 | BOOST_ASIO_CHECK(count == 1); | |
472 | ||
473 | count = 0; | |
474 | free_schedule_non_const_receiver ex6 = {}; | |
475 | exec::submit( | |
476 | exec::schedule(ex6), | |
477 | receiver(&count)); | |
478 | BOOST_ASIO_CHECK(count == 1); | |
479 | ||
480 | count = 0; | |
481 | executor ex7; | |
482 | exec::submit( | |
483 | exec::schedule(ex7), | |
484 | receiver(&count)); | |
485 | BOOST_ASIO_CHECK(count == 1); | |
486 | ||
487 | count = 0; | |
488 | const executor ex8; | |
489 | exec::submit( | |
490 | exec::schedule(ex8), | |
491 | receiver(&count)); | |
492 | BOOST_ASIO_CHECK(count == 1); | |
493 | ||
494 | count = 0; | |
495 | exec::submit( | |
496 | exec::schedule(executor()), | |
497 | receiver(&count)); | |
498 | BOOST_ASIO_CHECK(count == 1); | |
499 | } | |
500 | ||
501 | BOOST_ASIO_TEST_SUITE | |
502 | ( | |
503 | "schedule", | |
504 | BOOST_ASIO_TEST_CASE(test_can_schedule) | |
505 | BOOST_ASIO_TEST_CASE(test_schedule) | |
506 | ) |