File indexing completed on 2025-11-07 09:33:54
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_ASIO_BIND_IMMEDIATE_EXECUTOR_HPP
0012 #define BOOST_ASIO_BIND_IMMEDIATE_EXECUTOR_HPP
0013
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif
0017
0018 #include <boost/asio/detail/config.hpp>
0019 #include <boost/asio/associated_executor.hpp>
0020 #include <boost/asio/associated_immediate_executor.hpp>
0021 #include <boost/asio/associator.hpp>
0022 #include <boost/asio/async_result.hpp>
0023 #include <boost/asio/detail/initiation_base.hpp>
0024 #include <boost/asio/detail/type_traits.hpp>
0025
0026 #include <boost/asio/detail/push_options.hpp>
0027
0028 namespace boost {
0029 namespace asio {
0030 namespace detail {
0031
0032
0033
0034 template <typename T, typename = void>
0035 struct immediate_executor_binder_result_type
0036 {
0037 protected:
0038 typedef void result_type_or_void;
0039 };
0040
0041 template <typename T>
0042 struct immediate_executor_binder_result_type<T, void_t<typename T::result_type>>
0043 {
0044 typedef typename T::result_type result_type;
0045 protected:
0046 typedef result_type result_type_or_void;
0047 };
0048
0049 template <typename R>
0050 struct immediate_executor_binder_result_type<R(*)()>
0051 {
0052 typedef R result_type;
0053 protected:
0054 typedef result_type result_type_or_void;
0055 };
0056
0057 template <typename R>
0058 struct immediate_executor_binder_result_type<R(&)()>
0059 {
0060 typedef R result_type;
0061 protected:
0062 typedef result_type result_type_or_void;
0063 };
0064
0065 template <typename R, typename A1>
0066 struct immediate_executor_binder_result_type<R(*)(A1)>
0067 {
0068 typedef R result_type;
0069 protected:
0070 typedef result_type result_type_or_void;
0071 };
0072
0073 template <typename R, typename A1>
0074 struct immediate_executor_binder_result_type<R(&)(A1)>
0075 {
0076 typedef R result_type;
0077 protected:
0078 typedef result_type result_type_or_void;
0079 };
0080
0081 template <typename R, typename A1, typename A2>
0082 struct immediate_executor_binder_result_type<R(*)(A1, A2)>
0083 {
0084 typedef R result_type;
0085 protected:
0086 typedef result_type result_type_or_void;
0087 };
0088
0089 template <typename R, typename A1, typename A2>
0090 struct immediate_executor_binder_result_type<R(&)(A1, A2)>
0091 {
0092 typedef R result_type;
0093 protected:
0094 typedef result_type result_type_or_void;
0095 };
0096
0097
0098
0099 template <typename T, typename = void>
0100 struct immediate_executor_binder_argument_type {};
0101
0102 template <typename T>
0103 struct immediate_executor_binder_argument_type<T,
0104 void_t<typename T::argument_type>>
0105 {
0106 typedef typename T::argument_type argument_type;
0107 };
0108
0109 template <typename R, typename A1>
0110 struct immediate_executor_binder_argument_type<R(*)(A1)>
0111 {
0112 typedef A1 argument_type;
0113 };
0114
0115 template <typename R, typename A1>
0116 struct immediate_executor_binder_argument_type<R(&)(A1)>
0117 {
0118 typedef A1 argument_type;
0119 };
0120
0121
0122
0123
0124 template <typename T, typename = void>
0125 struct immediate_executor_binder_argument_types {};
0126
0127 template <typename T>
0128 struct immediate_executor_binder_argument_types<T,
0129 void_t<typename T::first_argument_type>>
0130 {
0131 typedef typename T::first_argument_type first_argument_type;
0132 typedef typename T::second_argument_type second_argument_type;
0133 };
0134
0135 template <typename R, typename A1, typename A2>
0136 struct immediate_executor_binder_argument_type<R(*)(A1, A2)>
0137 {
0138 typedef A1 first_argument_type;
0139 typedef A2 second_argument_type;
0140 };
0141
0142 template <typename R, typename A1, typename A2>
0143 struct immediate_executor_binder_argument_type<R(&)(A1, A2)>
0144 {
0145 typedef A1 first_argument_type;
0146 typedef A2 second_argument_type;
0147 };
0148
0149 }
0150
0151
0152
0153 template <typename T, typename Executor>
0154 class immediate_executor_binder
0155 #if !defined(GENERATING_DOCUMENTATION)
0156 : public detail::immediate_executor_binder_result_type<T>,
0157 public detail::immediate_executor_binder_argument_type<T>,
0158 public detail::immediate_executor_binder_argument_types<T>
0159 #endif
0160 {
0161 public:
0162
0163 typedef T target_type;
0164
0165
0166 typedef Executor immediate_executor_type;
0167
0168 #if defined(GENERATING_DOCUMENTATION)
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182 typedef see_below result_type;
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197 typedef see_below argument_type;
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212 typedef see_below first_argument_type;
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227 typedef see_below second_argument_type;
0228 #endif
0229
0230
0231
0232
0233
0234
0235 template <typename U>
0236 immediate_executor_binder(const immediate_executor_type& e,
0237 U&& u)
0238 : executor_(e),
0239 target_(static_cast<U&&>(u))
0240 {
0241 }
0242
0243
0244 immediate_executor_binder(const immediate_executor_binder& other)
0245 : executor_(other.get_immediate_executor()),
0246 target_(other.get())
0247 {
0248 }
0249
0250
0251 immediate_executor_binder(const immediate_executor_type& e,
0252 const immediate_executor_binder& other)
0253 : executor_(e),
0254 target_(other.get())
0255 {
0256 }
0257
0258
0259
0260
0261
0262
0263
0264 template <typename U, typename OtherExecutor>
0265 immediate_executor_binder(
0266 const immediate_executor_binder<U, OtherExecutor>& other,
0267 constraint_t<is_constructible<Executor, OtherExecutor>::value> = 0,
0268 constraint_t<is_constructible<T, U>::value> = 0)
0269 : executor_(other.get_immediate_executor()),
0270 target_(other.get())
0271 {
0272 }
0273
0274
0275
0276
0277
0278
0279
0280 template <typename U, typename OtherExecutor>
0281 immediate_executor_binder(const immediate_executor_type& e,
0282 const immediate_executor_binder<U, OtherExecutor>& other,
0283 constraint_t<is_constructible<T, U>::value> = 0)
0284 : executor_(e),
0285 target_(other.get())
0286 {
0287 }
0288
0289
0290 immediate_executor_binder(immediate_executor_binder&& other)
0291 : executor_(static_cast<immediate_executor_type&&>(
0292 other.get_immediate_executor())),
0293 target_(static_cast<T&&>(other.get()))
0294 {
0295 }
0296
0297
0298
0299 immediate_executor_binder(const immediate_executor_type& e,
0300 immediate_executor_binder&& other)
0301 : executor_(e),
0302 target_(static_cast<T&&>(other.get()))
0303 {
0304 }
0305
0306
0307 template <typename U, typename OtherExecutor>
0308 immediate_executor_binder(
0309 immediate_executor_binder<U, OtherExecutor>&& other,
0310 constraint_t<is_constructible<Executor, OtherExecutor>::value> = 0,
0311 constraint_t<is_constructible<T, U>::value> = 0)
0312 : executor_(static_cast<OtherExecutor&&>(
0313 other.get_immediate_executor())),
0314 target_(static_cast<U&&>(other.get()))
0315 {
0316 }
0317
0318
0319
0320 template <typename U, typename OtherExecutor>
0321 immediate_executor_binder(const immediate_executor_type& e,
0322 immediate_executor_binder<U, OtherExecutor>&& other,
0323 constraint_t<is_constructible<T, U>::value> = 0)
0324 : executor_(e),
0325 target_(static_cast<U&&>(other.get()))
0326 {
0327 }
0328
0329
0330 ~immediate_executor_binder()
0331 {
0332 }
0333
0334
0335 target_type& get() noexcept
0336 {
0337 return target_;
0338 }
0339
0340
0341 const target_type& get() const noexcept
0342 {
0343 return target_;
0344 }
0345
0346
0347 immediate_executor_type get_immediate_executor() const noexcept
0348 {
0349 return executor_;
0350 }
0351
0352
0353 template <typename... Args>
0354 result_of_t<T(Args...)> operator()(Args&&... args) &
0355 {
0356 return target_(static_cast<Args&&>(args)...);
0357 }
0358
0359
0360 template <typename... Args>
0361 result_of_t<T(Args...)> operator()(Args&&... args) &&
0362 {
0363 return static_cast<T&&>(target_)(static_cast<Args&&>(args)...);
0364 }
0365
0366
0367 template <typename... Args>
0368 result_of_t<T(Args...)> operator()(Args&&... args) const&
0369 {
0370 return target_(static_cast<Args&&>(args)...);
0371 }
0372
0373 private:
0374 Executor executor_;
0375 T target_;
0376 };
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386 template <typename Executor>
0387 struct partial_immediate_executor_binder
0388 {
0389
0390 explicit partial_immediate_executor_binder(const Executor& ex)
0391 : executor_(ex)
0392 {
0393 }
0394
0395
0396
0397 template <typename CompletionToken>
0398 BOOST_ASIO_NODISCARD inline
0399 constexpr immediate_executor_binder<decay_t<CompletionToken>, Executor>
0400 operator()(CompletionToken&& completion_token) const
0401 {
0402 return immediate_executor_binder<decay_t<CompletionToken>, Executor>(
0403 static_cast<CompletionToken&&>(completion_token), executor_);
0404 }
0405
0406
0407 Executor executor_;
0408 };
0409
0410
0411 template <typename Executor>
0412 BOOST_ASIO_NODISCARD inline partial_immediate_executor_binder<Executor>
0413 bind_immediate_executor(const Executor& ex)
0414 {
0415 return partial_immediate_executor_binder<Executor>(ex);
0416 }
0417
0418
0419
0420 template <typename Executor, typename T>
0421 BOOST_ASIO_NODISCARD inline immediate_executor_binder<decay_t<T>, Executor>
0422 bind_immediate_executor(const Executor& e, T&& t)
0423 {
0424 return immediate_executor_binder<
0425 decay_t<T>, Executor>(
0426 e, static_cast<T&&>(t));
0427 }
0428
0429 #if !defined(GENERATING_DOCUMENTATION)
0430
0431 namespace detail {
0432
0433 template <typename TargetAsyncResult, typename Executor, typename = void>
0434 class immediate_executor_binder_completion_handler_async_result
0435 {
0436 public:
0437 template <typename T>
0438 explicit immediate_executor_binder_completion_handler_async_result(T&)
0439 {
0440 }
0441 };
0442
0443 template <typename TargetAsyncResult, typename Executor>
0444 class immediate_executor_binder_completion_handler_async_result<
0445 TargetAsyncResult, Executor,
0446 void_t<
0447 typename TargetAsyncResult::completion_handler_type
0448 >>
0449 {
0450 private:
0451 TargetAsyncResult target_;
0452
0453 public:
0454 typedef immediate_executor_binder<
0455 typename TargetAsyncResult::completion_handler_type, Executor>
0456 completion_handler_type;
0457
0458 explicit immediate_executor_binder_completion_handler_async_result(
0459 typename TargetAsyncResult::completion_handler_type& handler)
0460 : target_(handler)
0461 {
0462 }
0463
0464 auto get() -> decltype(target_.get())
0465 {
0466 return target_.get();
0467 }
0468 };
0469
0470 template <typename TargetAsyncResult, typename = void>
0471 struct immediate_executor_binder_async_result_return_type
0472 {
0473 };
0474
0475 template <typename TargetAsyncResult>
0476 struct immediate_executor_binder_async_result_return_type<
0477 TargetAsyncResult,
0478 void_t<
0479 typename TargetAsyncResult::return_type
0480 >>
0481 {
0482 typedef typename TargetAsyncResult::return_type return_type;
0483 };
0484
0485 }
0486
0487 template <typename T, typename Executor, typename Signature>
0488 class async_result<immediate_executor_binder<T, Executor>, Signature> :
0489 public detail::immediate_executor_binder_completion_handler_async_result<
0490 async_result<T, Signature>, Executor>,
0491 public detail::immediate_executor_binder_async_result_return_type<
0492 async_result<T, Signature>>
0493 {
0494 public:
0495 explicit async_result(immediate_executor_binder<T, Executor>& b)
0496 : detail::immediate_executor_binder_completion_handler_async_result<
0497 async_result<T, Signature>, Executor>(b.get())
0498 {
0499 }
0500
0501 template <typename Initiation>
0502 struct init_wrapper : detail::initiation_base<Initiation>
0503 {
0504 using detail::initiation_base<Initiation>::initiation_base;
0505
0506 template <typename Handler, typename... Args>
0507 void operator()(Handler&& handler, const Executor& e, Args&&... args) &&
0508 {
0509 static_cast<Initiation&&>(*this)(
0510 immediate_executor_binder<
0511 decay_t<Handler>, Executor>(
0512 e, static_cast<Handler&&>(handler)),
0513 static_cast<Args&&>(args)...);
0514 }
0515
0516 template <typename Handler, typename... Args>
0517 void operator()(Handler&& handler,
0518 const Executor& e, Args&&... args) const &
0519 {
0520 static_cast<const Initiation&>(*this)(
0521 immediate_executor_binder<
0522 decay_t<Handler>, Executor>(
0523 e, static_cast<Handler&&>(handler)),
0524 static_cast<Args&&>(args)...);
0525 }
0526 };
0527
0528 template <typename Initiation, typename RawCompletionToken, typename... Args>
0529 static auto initiate(Initiation&& initiation,
0530 RawCompletionToken&& token, Args&&... args)
0531 -> decltype(
0532 async_initiate<
0533 conditional_t<
0534 is_const<remove_reference_t<RawCompletionToken>>::value, const T, T>,
0535 Signature>(
0536 declval<init_wrapper<decay_t<Initiation>>>(),
0537 token.get(), token.get_immediate_executor(),
0538 static_cast<Args&&>(args)...))
0539 {
0540 return async_initiate<
0541 conditional_t<
0542 is_const<remove_reference_t<RawCompletionToken>>::value, const T, T>,
0543 Signature>(
0544 init_wrapper<decay_t<Initiation>>(
0545 static_cast<Initiation&&>(initiation)),
0546 token.get(), token.get_immediate_executor(),
0547 static_cast<Args&&>(args)...);
0548 }
0549
0550 private:
0551 async_result(const async_result&) = delete;
0552 async_result& operator=(const async_result&) = delete;
0553
0554 async_result<T, Signature> target_;
0555 };
0556
0557 template <typename Executor, typename... Signatures>
0558 struct async_result<partial_immediate_executor_binder<Executor>, Signatures...>
0559 {
0560 template <typename Initiation, typename RawCompletionToken, typename... Args>
0561 static auto initiate(Initiation&& initiation,
0562 RawCompletionToken&& token, Args&&... args)
0563 -> decltype(
0564 async_initiate<Signatures...>(
0565 static_cast<Initiation&&>(initiation),
0566 immediate_executor_binder<
0567 default_completion_token_t<associated_executor_t<Initiation>>,
0568 Executor>(token.executor_,
0569 default_completion_token_t<associated_executor_t<Initiation>>{}),
0570 static_cast<Args&&>(args)...))
0571 {
0572 return async_initiate<Signatures...>(
0573 static_cast<Initiation&&>(initiation),
0574 immediate_executor_binder<
0575 default_completion_token_t<associated_executor_t<Initiation>>,
0576 Executor>(token.executor_,
0577 default_completion_token_t<associated_executor_t<Initiation>>{}),
0578 static_cast<Args&&>(args)...);
0579 }
0580 };
0581
0582 template <template <typename, typename> class Associator,
0583 typename T, typename Executor, typename DefaultCandidate>
0584 struct associator<Associator,
0585 immediate_executor_binder<T, Executor>,
0586 DefaultCandidate>
0587 : Associator<T, DefaultCandidate>
0588 {
0589 static typename Associator<T, DefaultCandidate>::type get(
0590 const immediate_executor_binder<T, Executor>& b) noexcept
0591 {
0592 return Associator<T, DefaultCandidate>::get(b.get());
0593 }
0594
0595 static auto get(const immediate_executor_binder<T, Executor>& b,
0596 const DefaultCandidate& c) noexcept
0597 -> decltype(Associator<T, DefaultCandidate>::get(b.get(), c))
0598 {
0599 return Associator<T, DefaultCandidate>::get(b.get(), c);
0600 }
0601 };
0602
0603 template <typename T, typename Executor, typename Executor1>
0604 struct associated_immediate_executor<
0605 immediate_executor_binder<T, Executor>,
0606 Executor1>
0607 {
0608 typedef Executor type;
0609
0610 static auto get(const immediate_executor_binder<T, Executor>& b,
0611 const Executor1& = Executor1()) noexcept
0612 -> decltype(b.get_immediate_executor())
0613 {
0614 return b.get_immediate_executor();
0615 }
0616 };
0617
0618 #endif
0619
0620 }
0621 }
0622
0623 #include <boost/asio/detail/pop_options.hpp>
0624
0625 #endif