1 | // |
2 | // execution/blocking.hpp |
3 | // ~~~~~~~~~~~~~~~~~~~~~~ |
4 | // |
5 | // Copyright (c) 2003-2024 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 | #ifndef BOOST_ASIO_EXECUTION_BLOCKING_HPP |
12 | #define BOOST_ASIO_EXECUTION_BLOCKING_HPP |
13 | |
14 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) |
15 | # pragma once |
16 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) |
17 | |
18 | #include <boost/asio/detail/config.hpp> |
19 | #include <boost/asio/detail/type_traits.hpp> |
20 | #include <boost/asio/execution/executor.hpp> |
21 | #include <boost/asio/is_applicable_property.hpp> |
22 | #include <boost/asio/prefer.hpp> |
23 | #include <boost/asio/query.hpp> |
24 | #include <boost/asio/require.hpp> |
25 | #include <boost/asio/traits/execute_member.hpp> |
26 | #include <boost/asio/traits/query_free.hpp> |
27 | #include <boost/asio/traits/query_member.hpp> |
28 | #include <boost/asio/traits/query_static_constexpr_member.hpp> |
29 | #include <boost/asio/traits/static_query.hpp> |
30 | #include <boost/asio/traits/static_require.hpp> |
31 | |
32 | #include <boost/asio/detail/push_options.hpp> |
33 | |
34 | namespace boost { |
35 | namespace asio { |
36 | |
37 | #if defined(GENERATING_DOCUMENTATION) |
38 | |
39 | namespace execution { |
40 | |
41 | /// A property to describe what guarantees an executor makes about the blocking |
42 | /// behaviour of their execution functions. |
43 | struct blocking_t |
44 | { |
45 | /// The blocking_t property applies to executors. |
46 | template <typename T> |
47 | static constexpr bool is_applicable_property_v = is_executor_v<T>; |
48 | |
49 | /// The top-level blocking_t property cannot be required. |
50 | static constexpr bool is_requirable = false; |
51 | |
52 | /// The top-level blocking_t property cannot be preferred. |
53 | static constexpr bool is_preferable = false; |
54 | |
55 | /// The type returned by queries against an @c any_executor. |
56 | typedef blocking_t polymorphic_query_result_type; |
57 | |
58 | /// A sub-property that indicates that invocation of an executor's execution |
59 | /// function may block pending completion of one or more invocations of the |
60 | /// submitted function object. |
61 | struct possibly_t |
62 | { |
63 | /// The blocking_t::possibly_t property applies to executors. |
64 | template <typename T> |
65 | static constexpr bool is_applicable_property_v = is_executor_v<T>; |
66 | |
67 | /// The blocking_t::possibly_t property can be required. |
68 | static constexpr bool is_requirable = true; |
69 | |
70 | /// The blocking_t::possibly_t property can be preferred. |
71 | static constexpr bool is_preferable = true; |
72 | |
73 | /// The type returned by queries against an @c any_executor. |
74 | typedef blocking_t polymorphic_query_result_type; |
75 | |
76 | /// Default constructor. |
77 | constexpr possibly_t(); |
78 | |
79 | /// Get the value associated with a property object. |
80 | /** |
81 | * @returns possibly_t(); |
82 | */ |
83 | static constexpr blocking_t value(); |
84 | }; |
85 | |
86 | /// A sub-property that indicates that invocation of an executor's execution |
87 | /// function shall block until completion of all invocations of the submitted |
88 | /// function object. |
89 | struct always_t |
90 | { |
91 | /// The blocking_t::always_t property applies to executors. |
92 | template <typename T> |
93 | static constexpr bool is_applicable_property_v = is_executor_v<T>; |
94 | |
95 | /// The blocking_t::always_t property can be required. |
96 | static constexpr bool is_requirable = true; |
97 | |
98 | /// The blocking_t::always_t property can be preferred. |
99 | static constexpr bool is_preferable = false; |
100 | |
101 | /// The type returned by queries against an @c any_executor. |
102 | typedef blocking_t polymorphic_query_result_type; |
103 | |
104 | /// Default constructor. |
105 | constexpr always_t(); |
106 | |
107 | /// Get the value associated with a property object. |
108 | /** |
109 | * @returns always_t(); |
110 | */ |
111 | static constexpr blocking_t value(); |
112 | }; |
113 | |
114 | /// A sub-property that indicates that invocation of an executor's execution |
115 | /// function shall not block pending completion of the invocations of the |
116 | /// submitted function object. |
117 | struct never_t |
118 | { |
119 | /// The blocking_t::never_t property applies to executors. |
120 | template <typename T> |
121 | static constexpr bool is_applicable_property_v = is_executor_v<T>; |
122 | |
123 | /// The blocking_t::never_t property can be required. |
124 | static constexpr bool is_requirable = true; |
125 | |
126 | /// The blocking_t::never_t property can be preferred. |
127 | static constexpr bool is_preferable = true; |
128 | |
129 | /// The type returned by queries against an @c any_executor. |
130 | typedef blocking_t polymorphic_query_result_type; |
131 | |
132 | /// Default constructor. |
133 | constexpr never_t(); |
134 | |
135 | /// Get the value associated with a property object. |
136 | /** |
137 | * @returns never_t(); |
138 | */ |
139 | static constexpr blocking_t value(); |
140 | }; |
141 | |
142 | /// A special value used for accessing the blocking_t::possibly_t property. |
143 | static constexpr possibly_t possibly; |
144 | |
145 | /// A special value used for accessing the blocking_t::always_t property. |
146 | static constexpr always_t always; |
147 | |
148 | /// A special value used for accessing the blocking_t::never_t property. |
149 | static constexpr never_t never; |
150 | |
151 | /// Default constructor. |
152 | constexpr blocking_t(); |
153 | |
154 | /// Construct from a sub-property value. |
155 | constexpr blocking_t(possibly_t); |
156 | |
157 | /// Construct from a sub-property value. |
158 | constexpr blocking_t(always_t); |
159 | |
160 | /// Construct from a sub-property value. |
161 | constexpr blocking_t(never_t); |
162 | |
163 | /// Compare property values for equality. |
164 | friend constexpr bool operator==( |
165 | const blocking_t& a, const blocking_t& b) noexcept; |
166 | |
167 | /// Compare property values for inequality. |
168 | friend constexpr bool operator!=( |
169 | const blocking_t& a, const blocking_t& b) noexcept; |
170 | }; |
171 | |
172 | /// A special value used for accessing the blocking_t property. |
173 | constexpr blocking_t blocking; |
174 | |
175 | } // namespace execution |
176 | |
177 | #else // defined(GENERATING_DOCUMENTATION) |
178 | |
179 | namespace execution { |
180 | namespace detail { |
181 | namespace blocking { |
182 | |
183 | template <int I> struct possibly_t; |
184 | template <int I> struct always_t; |
185 | template <int I> struct never_t; |
186 | |
187 | } // namespace blocking |
188 | namespace blocking_adaptation { |
189 | |
190 | template <int I> struct allowed_t; |
191 | |
192 | template <typename Executor, typename Function> |
193 | void blocking_execute( |
194 | Executor&& ex, |
195 | Function&& func); |
196 | |
197 | } // namespace blocking_adaptation |
198 | |
199 | template <int I = 0> |
200 | struct blocking_t |
201 | { |
202 | #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) |
203 | template <typename T> |
204 | static constexpr bool is_applicable_property_v = is_executor<T>::value; |
205 | #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) |
206 | |
207 | static constexpr bool is_requirable = false; |
208 | static constexpr bool is_preferable = false; |
209 | typedef blocking_t polymorphic_query_result_type; |
210 | |
211 | typedef detail::blocking::possibly_t<I> possibly_t; |
212 | typedef detail::blocking::always_t<I> always_t; |
213 | typedef detail::blocking::never_t<I> never_t; |
214 | |
215 | constexpr blocking_t() |
216 | : value_(-1) |
217 | { |
218 | } |
219 | |
220 | constexpr blocking_t(possibly_t) |
221 | : value_(0) |
222 | { |
223 | } |
224 | |
225 | constexpr blocking_t(always_t) |
226 | : value_(1) |
227 | { |
228 | } |
229 | |
230 | constexpr blocking_t(never_t) |
231 | : value_(2) |
232 | { |
233 | } |
234 | |
235 | template <typename T> |
236 | struct proxy |
237 | { |
238 | #if defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) |
239 | struct type |
240 | { |
241 | template <typename P> |
242 | auto query(P&& p) const |
243 | noexcept( |
244 | noexcept( |
245 | declval<conditional_t<true, T, P>>().query(static_cast<P&&>(p)) |
246 | ) |
247 | ) |
248 | -> decltype( |
249 | declval<conditional_t<true, T, P>>().query(static_cast<P&&>(p)) |
250 | ); |
251 | }; |
252 | #else // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) |
253 | typedef T type; |
254 | #endif // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) |
255 | }; |
256 | |
257 | template <typename T> |
258 | struct static_proxy |
259 | { |
260 | #if defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) |
261 | struct type |
262 | { |
263 | template <typename P> |
264 | static constexpr auto query(P&& p) |
265 | noexcept( |
266 | noexcept( |
267 | conditional_t<true, T, P>::query(static_cast<P&&>(p)) |
268 | ) |
269 | ) |
270 | -> decltype( |
271 | conditional_t<true, T, P>::query(static_cast<P&&>(p)) |
272 | ) |
273 | { |
274 | return T::query(static_cast<P&&>(p)); |
275 | } |
276 | }; |
277 | #else // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) |
278 | typedef T type; |
279 | #endif // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) |
280 | }; |
281 | |
282 | template <typename T> |
283 | struct query_member : |
284 | traits::query_member<typename proxy<T>::type, blocking_t> {}; |
285 | |
286 | template <typename T> |
287 | struct query_static_constexpr_member : |
288 | traits::query_static_constexpr_member< |
289 | typename static_proxy<T>::type, blocking_t> {}; |
290 | |
291 | #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ |
292 | && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) |
293 | template <typename T> |
294 | static constexpr |
295 | typename query_static_constexpr_member<T>::result_type |
296 | static_query() |
297 | noexcept(query_static_constexpr_member<T>::is_noexcept) |
298 | { |
299 | return query_static_constexpr_member<T>::value(); |
300 | } |
301 | |
302 | template <typename T> |
303 | static constexpr |
304 | typename traits::static_query<T, possibly_t>::result_type |
305 | static_query( |
306 | enable_if_t< |
307 | !query_static_constexpr_member<T>::is_valid |
308 | >* = 0, |
309 | enable_if_t< |
310 | !query_member<T>::is_valid |
311 | >* = 0, |
312 | enable_if_t< |
313 | traits::static_query<T, possibly_t>::is_valid |
314 | >* = 0) noexcept |
315 | { |
316 | return traits::static_query<T, possibly_t>::value(); |
317 | } |
318 | |
319 | template <typename T> |
320 | static constexpr |
321 | typename traits::static_query<T, always_t>::result_type |
322 | static_query( |
323 | enable_if_t< |
324 | !query_static_constexpr_member<T>::is_valid |
325 | >* = 0, |
326 | enable_if_t< |
327 | !query_member<T>::is_valid |
328 | >* = 0, |
329 | enable_if_t< |
330 | !traits::static_query<T, possibly_t>::is_valid |
331 | >* = 0, |
332 | enable_if_t< |
333 | traits::static_query<T, always_t>::is_valid |
334 | >* = 0) noexcept |
335 | { |
336 | return traits::static_query<T, always_t>::value(); |
337 | } |
338 | |
339 | template <typename T> |
340 | static constexpr |
341 | typename traits::static_query<T, never_t>::result_type |
342 | static_query( |
343 | enable_if_t< |
344 | !query_static_constexpr_member<T>::is_valid |
345 | >* = 0, |
346 | enable_if_t< |
347 | !query_member<T>::is_valid |
348 | >* = 0, |
349 | enable_if_t< |
350 | !traits::static_query<T, possibly_t>::is_valid |
351 | >* = 0, |
352 | enable_if_t< |
353 | !traits::static_query<T, always_t>::is_valid |
354 | >* = 0, |
355 | enable_if_t< |
356 | traits::static_query<T, never_t>::is_valid |
357 | >* = 0) noexcept |
358 | { |
359 | return traits::static_query<T, never_t>::value(); |
360 | } |
361 | |
362 | template <typename E, typename T = decltype(blocking_t::static_query<E>())> |
363 | static constexpr const T static_query_v |
364 | = blocking_t::static_query<E>(); |
365 | #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) |
366 | // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) |
367 | |
368 | friend constexpr bool operator==( |
369 | const blocking_t& a, const blocking_t& b) |
370 | { |
371 | return a.value_ == b.value_; |
372 | } |
373 | |
374 | friend constexpr bool operator!=( |
375 | const blocking_t& a, const blocking_t& b) |
376 | { |
377 | return a.value_ != b.value_; |
378 | } |
379 | |
380 | struct convertible_from_blocking_t |
381 | { |
382 | constexpr convertible_from_blocking_t(blocking_t) {} |
383 | }; |
384 | |
385 | template <typename Executor> |
386 | friend constexpr blocking_t query( |
387 | const Executor& ex, convertible_from_blocking_t, |
388 | enable_if_t< |
389 | can_query<const Executor&, possibly_t>::value |
390 | >* = 0) |
391 | #if !defined(__clang__) // Clang crashes if noexcept is used here. |
392 | #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified. |
393 | noexcept(is_nothrow_query<const Executor&, blocking_t<>::possibly_t>::value) |
394 | #else // defined(BOOST_ASIO_MSVC) |
395 | noexcept(is_nothrow_query<const Executor&, possibly_t>::value) |
396 | #endif // defined(BOOST_ASIO_MSVC) |
397 | #endif // !defined(__clang__) |
398 | { |
399 | return boost::asio::query(ex, possibly_t()); |
400 | } |
401 | |
402 | template <typename Executor> |
403 | friend constexpr blocking_t query( |
404 | const Executor& ex, convertible_from_blocking_t, |
405 | enable_if_t< |
406 | !can_query<const Executor&, possibly_t>::value |
407 | >* = 0, |
408 | enable_if_t< |
409 | can_query<const Executor&, always_t>::value |
410 | >* = 0) |
411 | #if !defined(__clang__) // Clang crashes if noexcept is used here. |
412 | #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified. |
413 | noexcept(is_nothrow_query<const Executor&, blocking_t<>::always_t>::value) |
414 | #else // defined(BOOST_ASIO_MSVC) |
415 | noexcept(is_nothrow_query<const Executor&, always_t>::value) |
416 | #endif // defined(BOOST_ASIO_MSVC) |
417 | #endif // !defined(__clang__) |
418 | { |
419 | return boost::asio::query(ex, always_t()); |
420 | } |
421 | |
422 | template <typename Executor> |
423 | friend constexpr blocking_t query( |
424 | const Executor& ex, convertible_from_blocking_t, |
425 | enable_if_t< |
426 | !can_query<const Executor&, possibly_t>::value |
427 | >* = 0, |
428 | enable_if_t< |
429 | !can_query<const Executor&, always_t>::value |
430 | >* = 0, |
431 | enable_if_t< |
432 | can_query<const Executor&, never_t>::value |
433 | >* = 0) |
434 | #if !defined(__clang__) // Clang crashes if noexcept is used here. |
435 | #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified. |
436 | noexcept(is_nothrow_query<const Executor&, blocking_t<>::never_t>::value) |
437 | #else // defined(BOOST_ASIO_MSVC) |
438 | noexcept(is_nothrow_query<const Executor&, never_t>::value) |
439 | #endif // defined(BOOST_ASIO_MSVC) |
440 | #endif // !defined(__clang__) |
441 | { |
442 | return boost::asio::query(ex, never_t()); |
443 | } |
444 | |
445 | BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(possibly_t, possibly); |
446 | BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(always_t, always); |
447 | BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(never_t, never); |
448 | |
449 | private: |
450 | int value_; |
451 | }; |
452 | |
453 | #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ |
454 | && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) |
455 | template <int I> template <typename E, typename T> |
456 | const T blocking_t<I>::static_query_v; |
457 | #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) |
458 | // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) |
459 | |
460 | template <int I> |
461 | const typename blocking_t<I>::possibly_t blocking_t<I>::possibly; |
462 | |
463 | template <int I> |
464 | const typename blocking_t<I>::always_t blocking_t<I>::always; |
465 | |
466 | template <int I> |
467 | const typename blocking_t<I>::never_t blocking_t<I>::never; |
468 | |
469 | namespace blocking { |
470 | |
471 | template <int I = 0> |
472 | struct possibly_t |
473 | { |
474 | #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) |
475 | template <typename T> |
476 | static constexpr bool is_applicable_property_v = is_executor<T>::value; |
477 | #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) |
478 | |
479 | static constexpr bool is_requirable = true; |
480 | static constexpr bool is_preferable = true; |
481 | typedef blocking_t<I> polymorphic_query_result_type; |
482 | |
483 | constexpr possibly_t() |
484 | { |
485 | } |
486 | |
487 | template <typename T> |
488 | struct query_member : |
489 | traits::query_member< |
490 | typename blocking_t<I>::template proxy<T>::type, possibly_t> {}; |
491 | |
492 | template <typename T> |
493 | struct query_static_constexpr_member : |
494 | traits::query_static_constexpr_member< |
495 | typename blocking_t<I>::template static_proxy<T>::type, possibly_t> {}; |
496 | |
497 | #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ |
498 | && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) |
499 | template <typename T> |
500 | static constexpr |
501 | typename query_static_constexpr_member<T>::result_type |
502 | static_query() |
503 | noexcept(query_static_constexpr_member<T>::is_noexcept) |
504 | { |
505 | return query_static_constexpr_member<T>::value(); |
506 | } |
507 | |
508 | template <typename T> |
509 | static constexpr possibly_t static_query( |
510 | enable_if_t< |
511 | !query_static_constexpr_member<T>::is_valid |
512 | >* = 0, |
513 | enable_if_t< |
514 | !query_member<T>::is_valid |
515 | >* = 0, |
516 | enable_if_t< |
517 | !traits::query_free<T, possibly_t>::is_valid |
518 | >* = 0, |
519 | enable_if_t< |
520 | !can_query<T, always_t<I>>::value |
521 | >* = 0, |
522 | enable_if_t< |
523 | !can_query<T, never_t<I>>::value |
524 | >* = 0) noexcept |
525 | { |
526 | return possibly_t(); |
527 | } |
528 | |
529 | template <typename E, typename T = decltype(possibly_t::static_query<E>())> |
530 | static constexpr const T static_query_v |
531 | = possibly_t::static_query<E>(); |
532 | #endif // defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) |
533 | // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) |
534 | |
535 | static constexpr blocking_t<I> value() |
536 | { |
537 | return possibly_t(); |
538 | } |
539 | |
540 | friend constexpr bool operator==( |
541 | const possibly_t&, const possibly_t&) |
542 | { |
543 | return true; |
544 | } |
545 | |
546 | friend constexpr bool operator!=( |
547 | const possibly_t&, const possibly_t&) |
548 | { |
549 | return false; |
550 | } |
551 | |
552 | friend constexpr bool operator==( |
553 | const possibly_t&, const always_t<I>&) |
554 | { |
555 | return false; |
556 | } |
557 | |
558 | friend constexpr bool operator!=( |
559 | const possibly_t&, const always_t<I>&) |
560 | { |
561 | return true; |
562 | } |
563 | |
564 | friend constexpr bool operator==( |
565 | const possibly_t&, const never_t<I>&) |
566 | { |
567 | return false; |
568 | } |
569 | |
570 | friend constexpr bool operator!=( |
571 | const possibly_t&, const never_t<I>&) |
572 | { |
573 | return true; |
574 | } |
575 | }; |
576 | |
577 | #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ |
578 | && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) |
579 | template <int I> template <typename E, typename T> |
580 | const T possibly_t<I>::static_query_v; |
581 | #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) |
582 | // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) |
583 | |
584 | template <typename Executor> |
585 | class adapter |
586 | { |
587 | public: |
588 | adapter(int, const Executor& e) noexcept |
589 | : executor_(e) |
590 | { |
591 | } |
592 | |
593 | adapter(const adapter& other) noexcept |
594 | : executor_(other.executor_) |
595 | { |
596 | } |
597 | |
598 | adapter(adapter&& other) noexcept |
599 | : executor_(static_cast<Executor&&>(other.executor_)) |
600 | { |
601 | } |
602 | |
603 | template <int I> |
604 | static constexpr always_t<I> query(blocking_t<I>) noexcept |
605 | { |
606 | return always_t<I>(); |
607 | } |
608 | |
609 | template <int I> |
610 | static constexpr always_t<I> query(possibly_t<I>) noexcept |
611 | { |
612 | return always_t<I>(); |
613 | } |
614 | |
615 | template <int I> |
616 | static constexpr always_t<I> query(always_t<I>) noexcept |
617 | { |
618 | return always_t<I>(); |
619 | } |
620 | |
621 | template <int I> |
622 | static constexpr always_t<I> query(never_t<I>) noexcept |
623 | { |
624 | return always_t<I>(); |
625 | } |
626 | |
627 | template <typename Property> |
628 | enable_if_t< |
629 | can_query<const Executor&, Property>::value, |
630 | query_result_t<const Executor&, Property> |
631 | > query(const Property& p) const |
632 | noexcept(is_nothrow_query<const Executor&, Property>::value) |
633 | { |
634 | return boost::asio::query(executor_, p); |
635 | } |
636 | |
637 | template <int I> |
638 | enable_if_t< |
639 | can_require<const Executor&, possibly_t<I>>::value, |
640 | require_result_t<const Executor&, possibly_t<I>> |
641 | > require(possibly_t<I>) const noexcept |
642 | { |
643 | return boost::asio::require(executor_, possibly_t<I>()); |
644 | } |
645 | |
646 | template <int I> |
647 | enable_if_t< |
648 | can_require<const Executor&, never_t<I>>::value, |
649 | require_result_t<const Executor&, never_t<I>> |
650 | > require(never_t<I>) const noexcept |
651 | { |
652 | return boost::asio::require(executor_, never_t<I>()); |
653 | } |
654 | |
655 | template <typename Property> |
656 | enable_if_t< |
657 | can_require<const Executor&, Property>::value, |
658 | adapter<decay_t<require_result_t<const Executor&, Property>>> |
659 | > require(const Property& p) const |
660 | noexcept(is_nothrow_require<const Executor&, Property>::value) |
661 | { |
662 | return adapter<decay_t<require_result_t<const Executor&, Property>>>( |
663 | 0, boost::asio::require(executor_, p)); |
664 | } |
665 | |
666 | template <typename Property> |
667 | enable_if_t< |
668 | can_prefer<const Executor&, Property>::value, |
669 | adapter<decay_t<prefer_result_t<const Executor&, Property>>> |
670 | > prefer(const Property& p) const |
671 | noexcept(is_nothrow_prefer<const Executor&, Property>::value) |
672 | { |
673 | return adapter<decay_t<prefer_result_t<const Executor&, Property>>>( |
674 | 0, boost::asio::prefer(executor_, p)); |
675 | } |
676 | |
677 | template <typename Function> |
678 | enable_if_t< |
679 | traits::execute_member<const Executor&, Function>::is_valid |
680 | > execute(Function&& f) const |
681 | { |
682 | blocking_adaptation::blocking_execute( |
683 | executor_, static_cast<Function&&>(f)); |
684 | } |
685 | |
686 | friend bool operator==(const adapter& a, const adapter& b) noexcept |
687 | { |
688 | return a.executor_ == b.executor_; |
689 | } |
690 | |
691 | friend bool operator!=(const adapter& a, const adapter& b) noexcept |
692 | { |
693 | return a.executor_ != b.executor_; |
694 | } |
695 | |
696 | private: |
697 | Executor executor_; |
698 | }; |
699 | |
700 | template <int I = 0> |
701 | struct always_t |
702 | { |
703 | #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) |
704 | template <typename T> |
705 | static constexpr bool is_applicable_property_v = is_executor<T>::value; |
706 | #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) |
707 | |
708 | static constexpr bool is_requirable = true; |
709 | static constexpr bool is_preferable = false; |
710 | typedef blocking_t<I> polymorphic_query_result_type; |
711 | |
712 | constexpr always_t() |
713 | { |
714 | } |
715 | |
716 | template <typename T> |
717 | struct query_member : |
718 | traits::query_member< |
719 | typename blocking_t<I>::template proxy<T>::type, always_t> {}; |
720 | |
721 | template <typename T> |
722 | struct query_static_constexpr_member : |
723 | traits::query_static_constexpr_member< |
724 | typename blocking_t<I>::template static_proxy<T>::type, always_t> {}; |
725 | |
726 | #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ |
727 | && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) |
728 | template <typename T> |
729 | static constexpr typename query_static_constexpr_member<T>::result_type |
730 | static_query() |
731 | noexcept(query_static_constexpr_member<T>::is_noexcept) |
732 | { |
733 | return query_static_constexpr_member<T>::value(); |
734 | } |
735 | |
736 | template <typename E, typename T = decltype(always_t::static_query<E>())> |
737 | static constexpr const T static_query_v = always_t::static_query<E>(); |
738 | #endif // defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) |
739 | // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) |
740 | |
741 | static constexpr blocking_t<I> value() |
742 | { |
743 | return always_t(); |
744 | } |
745 | |
746 | friend constexpr bool operator==( |
747 | const always_t&, const always_t&) |
748 | { |
749 | return true; |
750 | } |
751 | |
752 | friend constexpr bool operator!=( |
753 | const always_t&, const always_t&) |
754 | { |
755 | return false; |
756 | } |
757 | |
758 | friend constexpr bool operator==( |
759 | const always_t&, const possibly_t<I>&) |
760 | { |
761 | return false; |
762 | } |
763 | |
764 | friend constexpr bool operator!=( |
765 | const always_t&, const possibly_t<I>&) |
766 | { |
767 | return true; |
768 | } |
769 | |
770 | friend constexpr bool operator==( |
771 | const always_t&, const never_t<I>&) |
772 | { |
773 | return false; |
774 | } |
775 | |
776 | friend constexpr bool operator!=( |
777 | const always_t&, const never_t<I>&) |
778 | { |
779 | return true; |
780 | } |
781 | |
782 | template <typename Executor> |
783 | friend adapter<Executor> require( |
784 | const Executor& e, const always_t&, |
785 | enable_if_t< |
786 | is_executor<Executor>::value |
787 | >* = 0, |
788 | enable_if_t< |
789 | traits::static_require< |
790 | const Executor&, |
791 | blocking_adaptation::allowed_t<0> |
792 | >::is_valid |
793 | >* = 0) |
794 | { |
795 | return adapter<Executor>(0, e); |
796 | } |
797 | }; |
798 | |
799 | #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ |
800 | && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) |
801 | template <int I> template <typename E, typename T> |
802 | const T always_t<I>::static_query_v; |
803 | #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) |
804 | // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) |
805 | |
806 | template <int I> |
807 | struct never_t |
808 | { |
809 | #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) |
810 | template <typename T> |
811 | static constexpr bool is_applicable_property_v = is_executor<T>::value; |
812 | #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) |
813 | |
814 | static constexpr bool is_requirable = true; |
815 | static constexpr bool is_preferable = true; |
816 | typedef blocking_t<I> polymorphic_query_result_type; |
817 | |
818 | constexpr never_t() |
819 | { |
820 | } |
821 | |
822 | template <typename T> |
823 | struct query_member : |
824 | traits::query_member< |
825 | typename blocking_t<I>::template proxy<T>::type, never_t> {}; |
826 | |
827 | template <typename T> |
828 | struct query_static_constexpr_member : |
829 | traits::query_static_constexpr_member< |
830 | typename blocking_t<I>::template static_proxy<T>::type, never_t> {}; |
831 | |
832 | #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ |
833 | && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) |
834 | template <typename T> |
835 | static constexpr |
836 | typename query_static_constexpr_member<T>::result_type |
837 | static_query() |
838 | noexcept(query_static_constexpr_member<T>::is_noexcept) |
839 | { |
840 | return query_static_constexpr_member<T>::value(); |
841 | } |
842 | |
843 | template <typename E, typename T = decltype(never_t::static_query<E>())> |
844 | static constexpr const T static_query_v |
845 | = never_t::static_query<E>(); |
846 | #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) |
847 | // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) |
848 | |
849 | static constexpr blocking_t<I> value() |
850 | { |
851 | return never_t(); |
852 | } |
853 | |
854 | friend constexpr bool operator==(const never_t&, const never_t&) |
855 | { |
856 | return true; |
857 | } |
858 | |
859 | friend constexpr bool operator!=(const never_t&, const never_t&) |
860 | { |
861 | return false; |
862 | } |
863 | |
864 | friend constexpr bool operator==(const never_t&, const possibly_t<I>&) |
865 | { |
866 | return false; |
867 | } |
868 | |
869 | friend constexpr bool operator!=(const never_t&, const possibly_t<I>&) |
870 | { |
871 | return true; |
872 | } |
873 | |
874 | friend constexpr bool operator==(const never_t&, const always_t<I>&) |
875 | { |
876 | return false; |
877 | } |
878 | |
879 | friend constexpr bool operator!=(const never_t&, const always_t<I>&) |
880 | { |
881 | return true; |
882 | } |
883 | }; |
884 | |
885 | #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ |
886 | && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) |
887 | template <int I> template <typename E, typename T> |
888 | const T never_t<I>::static_query_v; |
889 | #endif // defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) |
890 | |
891 | } // namespace blocking |
892 | } // namespace detail |
893 | |
894 | typedef detail::blocking_t<> blocking_t; |
895 | |
896 | constexpr blocking_t blocking; |
897 | |
898 | } // namespace execution |
899 | |
900 | #if !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) |
901 | |
902 | template <typename T> |
903 | struct is_applicable_property<T, execution::blocking_t> |
904 | : integral_constant<bool, execution::is_executor<T>::value> |
905 | { |
906 | }; |
907 | |
908 | template <typename T> |
909 | struct is_applicable_property<T, execution::blocking_t::possibly_t> |
910 | : integral_constant<bool, execution::is_executor<T>::value> |
911 | { |
912 | }; |
913 | |
914 | template <typename T> |
915 | struct is_applicable_property<T, execution::blocking_t::always_t> |
916 | : integral_constant<bool, execution::is_executor<T>::value> |
917 | { |
918 | }; |
919 | |
920 | template <typename T> |
921 | struct is_applicable_property<T, execution::blocking_t::never_t> |
922 | : integral_constant<bool, execution::is_executor<T>::value> |
923 | { |
924 | }; |
925 | |
926 | #endif // !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) |
927 | |
928 | namespace traits { |
929 | |
930 | #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT) |
931 | |
932 | template <typename T> |
933 | struct query_free_default<T, execution::blocking_t, |
934 | enable_if_t< |
935 | can_query<T, execution::blocking_t::possibly_t>::value |
936 | >> |
937 | { |
938 | static constexpr bool is_valid = true; |
939 | static constexpr bool is_noexcept = |
940 | is_nothrow_query<T, execution::blocking_t::possibly_t>::value; |
941 | |
942 | typedef execution::blocking_t result_type; |
943 | }; |
944 | |
945 | template <typename T> |
946 | struct query_free_default<T, execution::blocking_t, |
947 | enable_if_t< |
948 | !can_query<T, execution::blocking_t::possibly_t>::value |
949 | && can_query<T, execution::blocking_t::always_t>::value |
950 | >> |
951 | { |
952 | static constexpr bool is_valid = true; |
953 | static constexpr bool is_noexcept = |
954 | is_nothrow_query<T, execution::blocking_t::always_t>::value; |
955 | |
956 | typedef execution::blocking_t result_type; |
957 | }; |
958 | |
959 | template <typename T> |
960 | struct query_free_default<T, execution::blocking_t, |
961 | enable_if_t< |
962 | !can_query<T, execution::blocking_t::possibly_t>::value |
963 | && !can_query<T, execution::blocking_t::always_t>::value |
964 | && can_query<T, execution::blocking_t::never_t>::value |
965 | >> |
966 | { |
967 | static constexpr bool is_valid = true; |
968 | static constexpr bool is_noexcept = |
969 | is_nothrow_query<T, execution::blocking_t::never_t>::value; |
970 | |
971 | typedef execution::blocking_t result_type; |
972 | }; |
973 | |
974 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT) |
975 | |
976 | #if !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ |
977 | || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) |
978 | |
979 | template <typename T> |
980 | struct static_query<T, execution::blocking_t, |
981 | enable_if_t< |
982 | execution::detail::blocking_t<0>:: |
983 | query_static_constexpr_member<T>::is_valid |
984 | >> |
985 | { |
986 | static constexpr bool is_valid = true; |
987 | static constexpr bool is_noexcept = true; |
988 | |
989 | typedef typename execution::detail::blocking_t<0>:: |
990 | query_static_constexpr_member<T>::result_type result_type; |
991 | |
992 | static constexpr result_type value() |
993 | { |
994 | return execution::blocking_t::query_static_constexpr_member<T>::value(); |
995 | } |
996 | }; |
997 | |
998 | template <typename T> |
999 | struct static_query<T, execution::blocking_t, |
1000 | enable_if_t< |
1001 | !execution::detail::blocking_t<0>:: |
1002 | query_static_constexpr_member<T>::is_valid |
1003 | && !execution::detail::blocking_t<0>:: |
1004 | query_member<T>::is_valid |
1005 | && traits::static_query<T, execution::blocking_t::possibly_t>::is_valid |
1006 | >> |
1007 | { |
1008 | static constexpr bool is_valid = true; |
1009 | static constexpr bool is_noexcept = true; |
1010 | |
1011 | typedef typename traits::static_query<T, |
1012 | execution::blocking_t::possibly_t>::result_type result_type; |
1013 | |
1014 | static constexpr result_type value() |
1015 | { |
1016 | return traits::static_query<T, execution::blocking_t::possibly_t>::value(); |
1017 | } |
1018 | }; |
1019 | |
1020 | template <typename T> |
1021 | struct static_query<T, execution::blocking_t, |
1022 | enable_if_t< |
1023 | !execution::detail::blocking_t<0>:: |
1024 | query_static_constexpr_member<T>::is_valid |
1025 | && !execution::detail::blocking_t<0>:: |
1026 | query_member<T>::is_valid |
1027 | && !traits::static_query<T, execution::blocking_t::possibly_t>::is_valid |
1028 | && traits::static_query<T, execution::blocking_t::always_t>::is_valid |
1029 | >> |
1030 | { |
1031 | static constexpr bool is_valid = true; |
1032 | static constexpr bool is_noexcept = true; |
1033 | |
1034 | typedef typename traits::static_query<T, |
1035 | execution::blocking_t::always_t>::result_type result_type; |
1036 | |
1037 | static constexpr result_type value() |
1038 | { |
1039 | return traits::static_query<T, execution::blocking_t::always_t>::value(); |
1040 | } |
1041 | }; |
1042 | |
1043 | template <typename T> |
1044 | struct static_query<T, execution::blocking_t, |
1045 | enable_if_t< |
1046 | !execution::detail::blocking_t<0>:: |
1047 | query_static_constexpr_member<T>::is_valid |
1048 | && !execution::detail::blocking_t<0>:: |
1049 | query_member<T>::is_valid |
1050 | && !traits::static_query<T, execution::blocking_t::possibly_t>::is_valid |
1051 | && !traits::static_query<T, execution::blocking_t::always_t>::is_valid |
1052 | && traits::static_query<T, execution::blocking_t::never_t>::is_valid |
1053 | >> |
1054 | { |
1055 | static constexpr bool is_valid = true; |
1056 | static constexpr bool is_noexcept = true; |
1057 | |
1058 | typedef typename traits::static_query<T, |
1059 | execution::blocking_t::never_t>::result_type result_type; |
1060 | |
1061 | static constexpr result_type value() |
1062 | { |
1063 | return traits::static_query<T, execution::blocking_t::never_t>::value(); |
1064 | } |
1065 | }; |
1066 | |
1067 | template <typename T> |
1068 | struct static_query<T, execution::blocking_t::possibly_t, |
1069 | enable_if_t< |
1070 | execution::detail::blocking::possibly_t<0>:: |
1071 | query_static_constexpr_member<T>::is_valid |
1072 | >> |
1073 | { |
1074 | static constexpr bool is_valid = true; |
1075 | static constexpr bool is_noexcept = true; |
1076 | |
1077 | typedef typename execution::detail::blocking::possibly_t<0>:: |
1078 | query_static_constexpr_member<T>::result_type result_type; |
1079 | |
1080 | static constexpr result_type value() |
1081 | { |
1082 | return execution::detail::blocking::possibly_t<0>:: |
1083 | query_static_constexpr_member<T>::value(); |
1084 | } |
1085 | }; |
1086 | |
1087 | template <typename T> |
1088 | struct static_query<T, execution::blocking_t::possibly_t, |
1089 | enable_if_t< |
1090 | !execution::detail::blocking::possibly_t<0>:: |
1091 | query_static_constexpr_member<T>::is_valid |
1092 | && !execution::detail::blocking::possibly_t<0>:: |
1093 | query_member<T>::is_valid |
1094 | && !traits::query_free<T, execution::blocking_t::possibly_t>::is_valid |
1095 | && !can_query<T, execution::blocking_t::always_t>::value |
1096 | && !can_query<T, execution::blocking_t::never_t>::value |
1097 | >> |
1098 | { |
1099 | static constexpr bool is_valid = true; |
1100 | static constexpr bool is_noexcept = true; |
1101 | |
1102 | typedef execution::blocking_t::possibly_t result_type; |
1103 | |
1104 | static constexpr result_type value() |
1105 | { |
1106 | return result_type(); |
1107 | } |
1108 | }; |
1109 | |
1110 | template <typename T> |
1111 | struct static_query<T, execution::blocking_t::always_t, |
1112 | enable_if_t< |
1113 | execution::detail::blocking::always_t<0>:: |
1114 | query_static_constexpr_member<T>::is_valid |
1115 | >> |
1116 | { |
1117 | static constexpr bool is_valid = true; |
1118 | static constexpr bool is_noexcept = true; |
1119 | |
1120 | typedef typename execution::detail::blocking::always_t<0>:: |
1121 | query_static_constexpr_member<T>::result_type result_type; |
1122 | |
1123 | static constexpr result_type value() |
1124 | { |
1125 | return execution::detail::blocking::always_t<0>:: |
1126 | query_static_constexpr_member<T>::value(); |
1127 | } |
1128 | }; |
1129 | |
1130 | template <typename T> |
1131 | struct static_query<T, execution::blocking_t::never_t, |
1132 | enable_if_t< |
1133 | execution::detail::blocking::never_t<0>:: |
1134 | query_static_constexpr_member<T>::is_valid |
1135 | >> |
1136 | { |
1137 | static constexpr bool is_valid = true; |
1138 | static constexpr bool is_noexcept = true; |
1139 | |
1140 | typedef typename execution::detail::blocking::never_t<0>:: |
1141 | query_static_constexpr_member<T>::result_type result_type; |
1142 | |
1143 | static constexpr result_type value() |
1144 | { |
1145 | return execution::detail::blocking::never_t<0>:: |
1146 | query_static_constexpr_member<T>::value(); |
1147 | } |
1148 | }; |
1149 | |
1150 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) |
1151 | // || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) |
1152 | |
1153 | #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_FREE_TRAIT) |
1154 | |
1155 | template <typename T> |
1156 | struct require_free_default<T, execution::blocking_t::always_t, |
1157 | enable_if_t< |
1158 | is_same<T, decay_t<T>>::value |
1159 | && execution::is_executor<T>::value |
1160 | && traits::static_require< |
1161 | const T&, |
1162 | execution::detail::blocking_adaptation::allowed_t<0> |
1163 | >::is_valid |
1164 | >> |
1165 | { |
1166 | static constexpr bool is_valid = true; |
1167 | static constexpr bool is_noexcept = false; |
1168 | typedef execution::detail::blocking::adapter<T> result_type; |
1169 | }; |
1170 | |
1171 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_FREE_TRAIT) |
1172 | |
1173 | #if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) |
1174 | |
1175 | template <typename Executor> |
1176 | struct equality_comparable< |
1177 | execution::detail::blocking::adapter<Executor>> |
1178 | { |
1179 | static constexpr bool is_valid = true; |
1180 | static constexpr bool is_noexcept = true; |
1181 | }; |
1182 | |
1183 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) |
1184 | |
1185 | #if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) |
1186 | |
1187 | template <typename Executor, typename Function> |
1188 | struct execute_member< |
1189 | execution::detail::blocking::adapter<Executor>, Function> |
1190 | { |
1191 | static constexpr bool is_valid = true; |
1192 | static constexpr bool is_noexcept = false; |
1193 | typedef void result_type; |
1194 | }; |
1195 | |
1196 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) |
1197 | |
1198 | #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) |
1199 | |
1200 | template <typename Executor, int I> |
1201 | struct query_static_constexpr_member< |
1202 | execution::detail::blocking::adapter<Executor>, |
1203 | execution::detail::blocking_t<I>> |
1204 | { |
1205 | static constexpr bool is_valid = true; |
1206 | static constexpr bool is_noexcept = true; |
1207 | typedef execution::blocking_t::always_t result_type; |
1208 | |
1209 | static constexpr result_type value() noexcept |
1210 | { |
1211 | return result_type(); |
1212 | } |
1213 | }; |
1214 | |
1215 | template <typename Executor, int I> |
1216 | struct query_static_constexpr_member< |
1217 | execution::detail::blocking::adapter<Executor>, |
1218 | execution::detail::blocking::always_t<I>> |
1219 | { |
1220 | static constexpr bool is_valid = true; |
1221 | static constexpr bool is_noexcept = true; |
1222 | typedef execution::blocking_t::always_t result_type; |
1223 | |
1224 | static constexpr result_type value() noexcept |
1225 | { |
1226 | return result_type(); |
1227 | } |
1228 | }; |
1229 | |
1230 | template <typename Executor, int I> |
1231 | struct query_static_constexpr_member< |
1232 | execution::detail::blocking::adapter<Executor>, |
1233 | execution::detail::blocking::possibly_t<I>> |
1234 | { |
1235 | static constexpr bool is_valid = true; |
1236 | static constexpr bool is_noexcept = true; |
1237 | typedef execution::blocking_t::always_t result_type; |
1238 | |
1239 | static constexpr result_type value() noexcept |
1240 | { |
1241 | return result_type(); |
1242 | } |
1243 | }; |
1244 | |
1245 | template <typename Executor, int I> |
1246 | struct query_static_constexpr_member< |
1247 | execution::detail::blocking::adapter<Executor>, |
1248 | execution::detail::blocking::never_t<I>> |
1249 | { |
1250 | static constexpr bool is_valid = true; |
1251 | static constexpr bool is_noexcept = true; |
1252 | typedef execution::blocking_t::always_t result_type; |
1253 | |
1254 | static constexpr result_type value() noexcept |
1255 | { |
1256 | return result_type(); |
1257 | } |
1258 | }; |
1259 | |
1260 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) |
1261 | |
1262 | #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) |
1263 | |
1264 | template <typename Executor, typename Property> |
1265 | struct query_member< |
1266 | execution::detail::blocking::adapter<Executor>, Property, |
1267 | enable_if_t< |
1268 | can_query<const Executor&, Property>::value |
1269 | >> |
1270 | { |
1271 | static constexpr bool is_valid = true; |
1272 | static constexpr bool is_noexcept = |
1273 | is_nothrow_query<Executor, Property>::value; |
1274 | typedef query_result_t<Executor, Property> result_type; |
1275 | }; |
1276 | |
1277 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) |
1278 | |
1279 | #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) |
1280 | |
1281 | template <typename Executor, int I> |
1282 | struct require_member< |
1283 | execution::detail::blocking::adapter<Executor>, |
1284 | execution::detail::blocking::possibly_t<I>, |
1285 | enable_if_t< |
1286 | can_require< |
1287 | const Executor&, |
1288 | execution::detail::blocking::possibly_t<I> |
1289 | >::value |
1290 | >> |
1291 | { |
1292 | static constexpr bool is_valid = true; |
1293 | static constexpr bool is_noexcept = |
1294 | is_nothrow_require<const Executor&, |
1295 | execution::detail::blocking::possibly_t<I>>::value; |
1296 | typedef require_result_t<const Executor&, |
1297 | execution::detail::blocking::possibly_t<I>> result_type; |
1298 | }; |
1299 | |
1300 | template <typename Executor, int I> |
1301 | struct require_member< |
1302 | execution::detail::blocking::adapter<Executor>, |
1303 | execution::detail::blocking::never_t<I>, |
1304 | enable_if_t< |
1305 | can_require< |
1306 | const Executor&, |
1307 | execution::detail::blocking::never_t<I> |
1308 | >::value |
1309 | >> |
1310 | { |
1311 | static constexpr bool is_valid = true; |
1312 | static constexpr bool is_noexcept = |
1313 | is_nothrow_require<const Executor&, |
1314 | execution::detail::blocking::never_t<I>>::value; |
1315 | typedef require_result_t<const Executor&, |
1316 | execution::detail::blocking::never_t<I>> result_type; |
1317 | }; |
1318 | |
1319 | template <typename Executor, typename Property> |
1320 | struct require_member< |
1321 | execution::detail::blocking::adapter<Executor>, Property, |
1322 | enable_if_t< |
1323 | can_require<const Executor&, Property>::value |
1324 | >> |
1325 | { |
1326 | static constexpr bool is_valid = true; |
1327 | static constexpr bool is_noexcept = |
1328 | is_nothrow_require<Executor, Property>::value; |
1329 | typedef execution::detail::blocking::adapter< |
1330 | decay_t<require_result_t<Executor, Property>>> result_type; |
1331 | }; |
1332 | |
1333 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) |
1334 | |
1335 | #if !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT) |
1336 | |
1337 | template <typename Executor, typename Property> |
1338 | struct prefer_member< |
1339 | execution::detail::blocking::adapter<Executor>, Property, |
1340 | enable_if_t< |
1341 | can_prefer<const Executor&, Property>::value |
1342 | >> |
1343 | { |
1344 | static constexpr bool is_valid = true; |
1345 | static constexpr bool is_noexcept = |
1346 | is_nothrow_prefer<Executor, Property>::value; |
1347 | typedef execution::detail::blocking::adapter< |
1348 | decay_t<prefer_result_t<Executor, Property>>> result_type; |
1349 | }; |
1350 | |
1351 | #endif // !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT) |
1352 | |
1353 | } // namespace traits |
1354 | |
1355 | #endif // defined(GENERATING_DOCUMENTATION) |
1356 | |
1357 | } // namespace asio |
1358 | } // namespace boost |
1359 | |
1360 | #include <boost/asio/detail/pop_options.hpp> |
1361 | |
1362 | #endif // BOOST_ASIO_EXECUTION_BLOCKING_HPP |
1363 | |