File indexing completed on 2025-07-15 08:28:37
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) const
0362 {
0363 return target_(static_cast<Args&&>(args)...);
0364 }
0365
0366 private:
0367 Executor executor_;
0368 T target_;
0369 };
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379 template <typename Executor>
0380 struct partial_immediate_executor_binder
0381 {
0382
0383 explicit partial_immediate_executor_binder(const Executor& ex)
0384 : executor_(ex)
0385 {
0386 }
0387
0388
0389
0390 template <typename CompletionToken>
0391 BOOST_ASIO_NODISCARD inline
0392 constexpr immediate_executor_binder<decay_t<CompletionToken>, Executor>
0393 operator()(CompletionToken&& completion_token) const
0394 {
0395 return immediate_executor_binder<decay_t<CompletionToken>, Executor>(
0396 static_cast<CompletionToken&&>(completion_token), executor_);
0397 }
0398
0399
0400 Executor executor_;
0401 };
0402
0403
0404 template <typename Executor>
0405 BOOST_ASIO_NODISCARD inline partial_immediate_executor_binder<Executor>
0406 bind_immediate_executor(const Executor& ex)
0407 {
0408 return partial_immediate_executor_binder<Executor>(ex);
0409 }
0410
0411
0412
0413 template <typename Executor, typename T>
0414 BOOST_ASIO_NODISCARD inline immediate_executor_binder<decay_t<T>, Executor>
0415 bind_immediate_executor(const Executor& e, T&& t)
0416 {
0417 return immediate_executor_binder<
0418 decay_t<T>, Executor>(
0419 e, static_cast<T&&>(t));
0420 }
0421
0422 #if !defined(GENERATING_DOCUMENTATION)
0423
0424 namespace detail {
0425
0426 template <typename TargetAsyncResult, typename Executor, typename = void>
0427 class immediate_executor_binder_completion_handler_async_result
0428 {
0429 public:
0430 template <typename T>
0431 explicit immediate_executor_binder_completion_handler_async_result(T&)
0432 {
0433 }
0434 };
0435
0436 template <typename TargetAsyncResult, typename Executor>
0437 class immediate_executor_binder_completion_handler_async_result<
0438 TargetAsyncResult, Executor,
0439 void_t<
0440 typename TargetAsyncResult::completion_handler_type
0441 >>
0442 {
0443 private:
0444 TargetAsyncResult target_;
0445
0446 public:
0447 typedef immediate_executor_binder<
0448 typename TargetAsyncResult::completion_handler_type, Executor>
0449 completion_handler_type;
0450
0451 explicit immediate_executor_binder_completion_handler_async_result(
0452 typename TargetAsyncResult::completion_handler_type& handler)
0453 : target_(handler)
0454 {
0455 }
0456
0457 auto get() -> decltype(target_.get())
0458 {
0459 return target_.get();
0460 }
0461 };
0462
0463 template <typename TargetAsyncResult, typename = void>
0464 struct immediate_executor_binder_async_result_return_type
0465 {
0466 };
0467
0468 template <typename TargetAsyncResult>
0469 struct immediate_executor_binder_async_result_return_type<
0470 TargetAsyncResult,
0471 void_t<
0472 typename TargetAsyncResult::return_type
0473 >>
0474 {
0475 typedef typename TargetAsyncResult::return_type return_type;
0476 };
0477
0478 }
0479
0480 template <typename T, typename Executor, typename Signature>
0481 class async_result<immediate_executor_binder<T, Executor>, Signature> :
0482 public detail::immediate_executor_binder_completion_handler_async_result<
0483 async_result<T, Signature>, Executor>,
0484 public detail::immediate_executor_binder_async_result_return_type<
0485 async_result<T, Signature>>
0486 {
0487 public:
0488 explicit async_result(immediate_executor_binder<T, Executor>& b)
0489 : detail::immediate_executor_binder_completion_handler_async_result<
0490 async_result<T, Signature>, Executor>(b.get())
0491 {
0492 }
0493
0494 template <typename Initiation>
0495 struct init_wrapper : detail::initiation_base<Initiation>
0496 {
0497 using detail::initiation_base<Initiation>::initiation_base;
0498
0499 template <typename Handler, typename... Args>
0500 void operator()(Handler&& handler, const Executor& e, Args&&... args) &&
0501 {
0502 static_cast<Initiation&&>(*this)(
0503 immediate_executor_binder<
0504 decay_t<Handler>, Executor>(
0505 e, static_cast<Handler&&>(handler)),
0506 static_cast<Args&&>(args)...);
0507 }
0508
0509 template <typename Handler, typename... Args>
0510 void operator()(Handler&& handler,
0511 const Executor& e, Args&&... args) const &
0512 {
0513 static_cast<const Initiation&>(*this)(
0514 immediate_executor_binder<
0515 decay_t<Handler>, Executor>(
0516 e, static_cast<Handler&&>(handler)),
0517 static_cast<Args&&>(args)...);
0518 }
0519 };
0520
0521 template <typename Initiation, typename RawCompletionToken, typename... Args>
0522 static auto initiate(Initiation&& initiation,
0523 RawCompletionToken&& token, Args&&... args)
0524 -> decltype(
0525 async_initiate<
0526 conditional_t<
0527 is_const<remove_reference_t<RawCompletionToken>>::value, const T, T>,
0528 Signature>(
0529 declval<init_wrapper<decay_t<Initiation>>>(),
0530 token.get(), token.get_immediate_executor(),
0531 static_cast<Args&&>(args)...))
0532 {
0533 return async_initiate<
0534 conditional_t<
0535 is_const<remove_reference_t<RawCompletionToken>>::value, const T, T>,
0536 Signature>(
0537 init_wrapper<decay_t<Initiation>>(
0538 static_cast<Initiation&&>(initiation)),
0539 token.get(), token.get_immediate_executor(),
0540 static_cast<Args&&>(args)...);
0541 }
0542
0543 private:
0544 async_result(const async_result&) = delete;
0545 async_result& operator=(const async_result&) = delete;
0546
0547 async_result<T, Signature> target_;
0548 };
0549
0550 template <typename Executor, typename... Signatures>
0551 struct async_result<partial_immediate_executor_binder<Executor>, Signatures...>
0552 {
0553 template <typename Initiation, typename RawCompletionToken, typename... Args>
0554 static auto initiate(Initiation&& initiation,
0555 RawCompletionToken&& token, Args&&... args)
0556 -> decltype(
0557 async_initiate<Signatures...>(
0558 static_cast<Initiation&&>(initiation),
0559 immediate_executor_binder<
0560 default_completion_token_t<associated_executor_t<Initiation>>,
0561 Executor>(token.executor_,
0562 default_completion_token_t<associated_executor_t<Initiation>>{}),
0563 static_cast<Args&&>(args)...))
0564 {
0565 return async_initiate<Signatures...>(
0566 static_cast<Initiation&&>(initiation),
0567 immediate_executor_binder<
0568 default_completion_token_t<associated_executor_t<Initiation>>,
0569 Executor>(token.executor_,
0570 default_completion_token_t<associated_executor_t<Initiation>>{}),
0571 static_cast<Args&&>(args)...);
0572 }
0573 };
0574
0575 template <template <typename, typename> class Associator,
0576 typename T, typename Executor, typename DefaultCandidate>
0577 struct associator<Associator,
0578 immediate_executor_binder<T, Executor>,
0579 DefaultCandidate>
0580 : Associator<T, DefaultCandidate>
0581 {
0582 static typename Associator<T, DefaultCandidate>::type get(
0583 const immediate_executor_binder<T, Executor>& b) noexcept
0584 {
0585 return Associator<T, DefaultCandidate>::get(b.get());
0586 }
0587
0588 static auto get(const immediate_executor_binder<T, Executor>& b,
0589 const DefaultCandidate& c) noexcept
0590 -> decltype(Associator<T, DefaultCandidate>::get(b.get(), c))
0591 {
0592 return Associator<T, DefaultCandidate>::get(b.get(), c);
0593 }
0594 };
0595
0596 template <typename T, typename Executor, typename Executor1>
0597 struct associated_immediate_executor<
0598 immediate_executor_binder<T, Executor>,
0599 Executor1>
0600 {
0601 typedef Executor type;
0602
0603 static auto get(const immediate_executor_binder<T, Executor>& b,
0604 const Executor1& = Executor1()) noexcept
0605 -> decltype(b.get_immediate_executor())
0606 {
0607 return b.get_immediate_executor();
0608 }
0609 };
0610
0611 #endif
0612
0613 }
0614 }
0615
0616 #include <boost/asio/detail/pop_options.hpp>
0617
0618 #endif