• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // schedule.cpp
3 // ~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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 {
startoperation_state31   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 {
sendersender58   sender()
59   {
60   }
61 
62   template <typename R>
connectsender63   operation_state connect(BOOST_ASIO_MOVE_ARG(R) r) const
64   {
65     (void)r;
66     return operation_state();
67   }
68 
69   template <typename R>
submitsender70   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 {
scheduleconst_member_schedule115   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 {
schedule(const free_schedule_const_receiver &)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 {
schedulenon_const_member_schedule172   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 {
schedule(free_schedule_non_const_receiver &)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 {
executorexecutor229   executor()
230   {
231   }
232 
executorexecutor233   executor(const executor&) BOOST_ASIO_NOEXCEPT
234   {
235   }
236 
237 #if defined(BOOST_ASIO_HAS_MOVE)
executorexecutor238   executor(executor&&) BOOST_ASIO_NOEXCEPT
239   {
240   }
241 #endif // defined(BOOST_ASIO_HAS_MOVE)
242 
243   template <typename F>
executeexecutor244   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 
operator ==executor250   bool operator==(const executor&) const BOOST_ASIO_NOEXCEPT
251   {
252     return true;
253   }
254 
operator !=executor255   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 
test_can_schedule()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 
receiverreceiver346   receiver(int* count)
347     : count_(count)
348   {
349   }
350 
receiverreceiver351   receiver(const receiver& other) BOOST_ASIO_NOEXCEPT
352     : count_(other.count_)
353   {
354   }
355 
356 #if defined(BOOST_ASIO_HAS_MOVE)
receiverreceiver357   receiver(receiver&& other) BOOST_ASIO_NOEXCEPT
358     : count_(other.count_)
359   {
360     other.count_ = 0;
361   }
362 #endif // defined(BOOST_ASIO_HAS_MOVE)
363 
set_valuereceiver364   void set_value() BOOST_ASIO_NOEXCEPT
365   {
366     ++(*count_);
367   }
368 
369   template <typename E>
set_errorreceiver370   void set_error(BOOST_ASIO_MOVE_ARG(E) e) BOOST_ASIO_NOEXCEPT
371   {
372     (void)e;
373   }
374 
set_donereceiver375   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 
test_schedule()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 )
507