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