File indexing completed on 2026-08-17 08:38:33
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_ASIO_INLINE_OR_EXECUTOR_HPP
0012 #define BOOST_ASIO_INLINE_OR_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/non_const_lvalue.hpp>
0020 #include <boost/asio/detail/type_traits.hpp>
0021 #include <boost/asio/execution/blocking.hpp>
0022 #include <boost/asio/execution/executor.hpp>
0023 #include <boost/asio/execution/inline_exception_handling.hpp>
0024 #include <boost/asio/execution_context.hpp>
0025 #include <boost/asio/is_executor.hpp>
0026
0027 #include <boost/asio/detail/push_options.hpp>
0028
0029 namespace boost {
0030 namespace asio {
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043 template <typename Executor,
0044 typename Blocking = execution::blocking_t::always_t,
0045 typename InlineExceptionHandling
0046 = execution::inline_exception_handling_t::propagate_t>
0047 class inline_or_executor
0048 {
0049 public:
0050
0051 typedef Executor inner_executor_type;
0052
0053
0054
0055
0056
0057
0058 inline_or_executor()
0059 : executor_()
0060 {
0061 }
0062
0063
0064 template <typename Executor1>
0065 explicit inline_or_executor(const Executor1& e,
0066 constraint_t<
0067 conditional_t<
0068 !is_same<Executor1, inline_or_executor>::value,
0069 is_convertible<Executor1, Executor>,
0070 false_type
0071 >::value
0072 > = 0)
0073 : executor_(e)
0074 {
0075 }
0076
0077
0078 inline_or_executor(const inline_or_executor& other) noexcept
0079 : executor_(other.executor_)
0080 {
0081 }
0082
0083
0084
0085
0086
0087
0088 template <class OtherExecutor>
0089 inline_or_executor(
0090 const inline_or_executor<OtherExecutor>& other) noexcept
0091 : executor_(other.executor_)
0092 {
0093 }
0094
0095
0096 inline_or_executor& operator=(const inline_or_executor& other) noexcept
0097 {
0098 executor_ = other.executor_;
0099 return *this;
0100 }
0101
0102
0103
0104
0105
0106
0107 template <class OtherExecutor>
0108 inline_or_executor& operator=(
0109 const inline_or_executor<OtherExecutor>& other) noexcept
0110 {
0111 executor_ = other.executor_;
0112 return *this;
0113 }
0114
0115
0116 inline_or_executor(inline_or_executor&& other) noexcept
0117 : executor_(static_cast<Executor&&>(other.executor_))
0118 {
0119 }
0120
0121
0122
0123
0124
0125
0126 template <class OtherExecutor>
0127 inline_or_executor(inline_or_executor<OtherExecutor>&& other) noexcept
0128 : executor_(static_cast<OtherExecutor&&>(other.executor_))
0129 {
0130 }
0131
0132
0133 inline_or_executor& operator=(inline_or_executor&& other) noexcept
0134 {
0135 executor_ = static_cast<Executor&&>(other.executor_);
0136 return *this;
0137 }
0138
0139
0140
0141
0142
0143
0144 template <class OtherExecutor>
0145 inline_or_executor& operator=(
0146 inline_or_executor<OtherExecutor>&& other) noexcept
0147 {
0148 executor_ = static_cast<OtherExecutor&&>(other.executor_);
0149 return *this;
0150 }
0151
0152
0153 ~inline_or_executor() noexcept
0154 {
0155 }
0156
0157
0158 inner_executor_type get_inner_executor() const noexcept
0159 {
0160 return executor_;
0161 }
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174 static constexpr execution::blocking_t query(execution::blocking_t) noexcept
0175 {
0176 return Blocking();
0177 }
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191 static constexpr execution::inline_exception_handling_t query(
0192 execution::inline_exception_handling_t) noexcept
0193 {
0194 return InlineExceptionHandling();
0195 }
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208 template <typename Property>
0209 query_result_t<const Executor&, Property> query(const Property& p,
0210 constraint_t<
0211 can_query<const Executor&, Property>::value
0212 > = 0,
0213 constraint_t<
0214 !is_convertible<Property, execution::blocking_t>::value
0215 > = 0,
0216 constraint_t<
0217 !is_convertible<Property, execution::inline_exception_handling_t>::value
0218 > = 0) const
0219 noexcept(is_nothrow_query<const Executor&, Property>::value)
0220 {
0221 return boost::asio::query(executor_, p);
0222 }
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234 inline_or_executor<Executor, execution::blocking_t::possibly_t,
0235 InlineExceptionHandling>
0236 require(const execution::blocking_t::possibly_t&) const noexcept
0237 {
0238 return inline_or_executor<Executor, execution::blocking_t::possibly_t,
0239 InlineExceptionHandling>(executor_);
0240 }
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252 inline_or_executor<Executor, execution::blocking_t::always_t,
0253 InlineExceptionHandling>
0254 require(const execution::blocking_t::always_t&) const noexcept
0255 {
0256 return inline_or_executor<Executor, execution::blocking_t::always_t,
0257 InlineExceptionHandling>(executor_);
0258 }
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270 inline_or_executor<Executor, execution::blocking_t::never_t,
0271 InlineExceptionHandling>
0272 require(const execution::blocking_t::never_t&) const noexcept
0273 {
0274 return inline_or_executor<Executor, execution::blocking_t::never_t,
0275 InlineExceptionHandling>(executor_);
0276 }
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289 inline_or_executor<Executor, Blocking,
0290 execution::inline_exception_handling_t::propagate_t>
0291 require(const execution::inline_exception_handling_t::propagate_t&)
0292 const noexcept
0293 {
0294 return inline_or_executor<Executor, Blocking,
0295 execution::inline_exception_handling_t::propagate_t>(executor_);
0296 }
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309 inline_or_executor<Executor, Blocking,
0310 execution::inline_exception_handling_t::terminate_t>
0311 require(const execution::inline_exception_handling_t::terminate_t&)
0312 const noexcept
0313 {
0314 return inline_or_executor<Executor, Blocking,
0315 execution::inline_exception_handling_t::terminate_t>(executor_);
0316 }
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328 template <typename Property>
0329 inline_or_executor<decay_t<require_result_t<const Executor&, Property>>,
0330 Blocking, InlineExceptionHandling>
0331 require(const Property& p,
0332 constraint_t<
0333 can_require<const Executor&, Property>::value
0334 > = 0,
0335 constraint_t<
0336 !is_convertible<Property, execution::blocking_t>::value
0337 > = 0,
0338 constraint_t<
0339 !is_convertible<Property, execution::inline_exception_handling_t>::value
0340 > = 0) const
0341 noexcept(is_nothrow_require<const Executor&, Property>::value)
0342 {
0343 return inline_or_executor<
0344 decay_t<require_result_t<const Executor&, Property>>,
0345 Blocking, InlineExceptionHandling>(boost::asio::require(executor_, p));
0346 }
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358 template <typename Property>
0359 inline_or_executor<decay_t<prefer_result_t<const Executor&, Property>>,
0360 Blocking, InlineExceptionHandling>
0361 prefer(const Property& p,
0362 constraint_t<
0363 can_prefer<const Executor&, Property>::value
0364 > = 0,
0365 constraint_t<
0366 !is_convertible<Property, execution::blocking_t>::value
0367 > = 0,
0368 constraint_t<
0369 !is_convertible<Property, execution::inline_exception_handling_t>::value
0370 > = 0) const
0371 noexcept(is_nothrow_prefer<const Executor&, Property>::value)
0372 {
0373 return inline_or_executor<
0374 decay_t<prefer_result_t<const Executor&, Property>>,
0375 Blocking, InlineExceptionHandling>(boost::asio::prefer(executor_, p));
0376 }
0377
0378 #if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
0379
0380 execution_context& context() const noexcept
0381 {
0382 return executor_.context();
0383 }
0384
0385
0386
0387
0388
0389 void on_work_started() const noexcept
0390 {
0391 executor_.on_work_started();
0392 }
0393
0394
0395
0396
0397
0398 void on_work_finished() const noexcept
0399 {
0400 executor_.on_work_finished();
0401 }
0402 #endif
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414 template <typename Function>
0415 constraint_t<
0416 traits::execute_member<const Executor&, Function>::is_valid,
0417 void
0418 > execute(Function&& f) const
0419 {
0420 this->execute_helper(static_cast<Function&&>(f), Blocking{});
0421 }
0422
0423 #if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436 template <typename Function, typename Allocator>
0437 void dispatch(Function&& f, const Allocator& a) const
0438 {
0439 (void)a;
0440 detail::non_const_lvalue<Function> f2(f);
0441 static_cast<decay_t<Function>&&>(f2.value)();
0442 }
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457 template <typename Function, typename Allocator>
0458 void post(Function&& f, const Allocator& a) const
0459 {
0460 executor_.post(static_cast<Function&&>(f), a);
0461 }
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476 template <typename Function, typename Allocator>
0477 void defer(Function&& f, const Allocator& a) const
0478 {
0479 executor_.defer(static_cast<Function&&>(f), a);
0480 }
0481 #endif
0482
0483
0484
0485
0486
0487 friend bool operator==(const inline_or_executor& a,
0488 const inline_or_executor& b) noexcept
0489 {
0490 return a.executor_ == b.executor_;
0491 }
0492
0493
0494
0495
0496
0497 friend bool operator!=(const inline_or_executor& a,
0498 const inline_or_executor& b) noexcept
0499 {
0500 return a.executor_ != b.executor_;
0501 }
0502
0503 #if defined(GENERATING_DOCUMENTATION)
0504 private:
0505 #endif
0506 template <typename Function>
0507 void execute_helper(Function&& f, execution::blocking_t::possibly_t) const
0508 {
0509 #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
0510 try
0511 #endif
0512 {
0513 detail::non_const_lvalue<Function> f2(f);
0514 static_cast<decay_t<Function>&&>(f2.value)();
0515 }
0516 #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
0517 catch (...)
0518 {
0519 if (is_same<InlineExceptionHandling,
0520 execution::inline_exception_handling_t::terminate_t>::value)
0521 {
0522 std::terminate();
0523 }
0524 else
0525 {
0526 throw;
0527 }
0528 }
0529 #endif
0530 }
0531
0532 template <typename Function>
0533 void execute_helper(Function&& f, execution::blocking_t::always_t) const
0534 {
0535 this->execute_helper(static_cast<Function&&>(f),
0536 execution::blocking.possibly);
0537 }
0538
0539 template <typename Function>
0540 void execute_helper(Function&& f, execution::blocking_t::never_t) const
0541 {
0542 boost::asio::require(executor_, execution::blocking.never).execute(
0543 static_cast<Function&&>(f));
0544 }
0545
0546 Executor executor_;
0547 };
0548
0549
0550
0551
0552
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562 template <typename Executor>
0563 inline inline_or_executor<Executor> inline_or(const Executor& ex,
0564 constraint_t<
0565 is_executor<Executor>::value || execution::is_executor<Executor>::value
0566 > = 0)
0567 {
0568 return inline_or_executor<Executor>(ex);
0569 }
0570
0571
0572
0573
0574
0575
0576
0577
0578 template <typename ExecutionContext>
0579 inline inline_or_executor<typename ExecutionContext::executor_type>
0580 inline_or(ExecutionContext& ctx,
0581 constraint_t<
0582 is_convertible<ExecutionContext&, execution_context&>::value
0583 > = 0)
0584 {
0585 return inline_or_executor<typename ExecutionContext::executor_type>(
0586 ctx.get_executor());
0587 }
0588
0589
0590
0591 #if !defined(GENERATING_DOCUMENTATION)
0592
0593 namespace traits {
0594
0595 #if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
0596
0597 template <typename Executor, typename Blocking,
0598 typename InlineExceptionHandling>
0599 struct equality_comparable<
0600 inline_or_executor<Executor, Blocking, InlineExceptionHandling>>
0601 {
0602 static constexpr bool is_valid = true;
0603 static constexpr bool is_noexcept = true;
0604 };
0605
0606 #endif
0607
0608 #if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
0609
0610 template <typename Executor, typename Blocking,
0611 typename InlineExceptionHandling, typename Function>
0612 struct execute_member<
0613 inline_or_executor<Executor, Blocking, InlineExceptionHandling>, Function,
0614 enable_if_t<
0615 traits::execute_member<const Executor&, Function>::is_valid
0616 >
0617 >
0618 {
0619 static constexpr bool is_valid = true;
0620 static constexpr bool is_noexcept = false;
0621 typedef void result_type;
0622 };
0623
0624 #endif
0625
0626 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
0627
0628 template <typename Executor, typename Blocking,
0629 typename InlineExceptionHandling, typename Property>
0630 struct query_static_constexpr_member<
0631 inline_or_executor<Executor, Blocking, InlineExceptionHandling>,
0632 Property,
0633 enable_if_t<
0634 is_convertible<
0635 Property,
0636 execution::blocking_t
0637 >::value
0638 >
0639 >
0640 {
0641 static constexpr bool is_valid = true;
0642 static constexpr bool is_noexcept = true;
0643 typedef Blocking result_type;
0644
0645 static constexpr result_type value() noexcept
0646 {
0647 return result_type();
0648 }
0649 };
0650
0651 template <typename Executor, typename Blocking,
0652 typename InlineExceptionHandling, typename Property>
0653 struct query_static_constexpr_member<
0654 inline_or_executor<Executor, Blocking, InlineExceptionHandling>,
0655 Property,
0656 enable_if_t<
0657 is_convertible<
0658 Property,
0659 execution::inline_exception_handling_t
0660 >::value
0661 >
0662 >
0663 {
0664 static constexpr bool is_valid = true;
0665 static constexpr bool is_noexcept = true;
0666 typedef InlineExceptionHandling result_type;
0667
0668 static constexpr result_type value() noexcept
0669 {
0670 return result_type();
0671 }
0672 };
0673
0674 #endif
0675
0676 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
0677
0678 template <typename Executor, typename Blocking,
0679 typename InlineExceptionHandling, typename Property>
0680 struct query_member<
0681 inline_or_executor<Executor, Blocking, InlineExceptionHandling>, Property,
0682 enable_if_t<
0683 can_query<const Executor&, Property>::value
0684 && !is_convertible<Property,
0685 execution::blocking_t>::value
0686 && !is_convertible<Property,
0687 execution::inline_exception_handling_t>::value
0688 >
0689 >
0690 {
0691 static constexpr bool is_valid = true;
0692 static constexpr bool is_noexcept =
0693 is_nothrow_query<Executor, Property>::value;
0694 typedef query_result_t<Executor, Property> result_type;
0695 };
0696
0697 #endif
0698
0699 #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
0700
0701 template <typename Executor, typename Blocking,
0702 typename InlineExceptionHandling>
0703 struct require_member<
0704 inline_or_executor<Executor, Blocking, InlineExceptionHandling>,
0705 execution::blocking_t::possibly_t
0706 >
0707 {
0708 static constexpr bool is_valid = true;
0709 static constexpr bool is_noexcept = true;
0710 typedef inline_or_executor<Executor, execution::blocking_t::possibly_t,
0711 InlineExceptionHandling> result_type;
0712 };
0713
0714 template <typename Executor, typename Blocking,
0715 typename InlineExceptionHandling>
0716 struct require_member<
0717 inline_or_executor<Executor, Blocking, InlineExceptionHandling>,
0718 execution::blocking_t::always_t
0719 >
0720 {
0721 static constexpr bool is_valid = true;
0722 static constexpr bool is_noexcept = true;
0723 typedef inline_or_executor<Executor, execution::blocking_t::always_t,
0724 InlineExceptionHandling> result_type;
0725 };
0726
0727 template <typename Executor, typename Blocking,
0728 typename InlineExceptionHandling>
0729 struct require_member<
0730 inline_or_executor<Executor, Blocking, InlineExceptionHandling>,
0731 execution::blocking_t::never_t
0732 >
0733 {
0734 static constexpr bool is_valid = true;
0735 static constexpr bool is_noexcept = true;
0736 typedef inline_or_executor<Executor, execution::blocking_t::never_t,
0737 InlineExceptionHandling> result_type;
0738 };
0739
0740 template <typename Executor, typename Blocking,
0741 typename InlineExceptionHandling>
0742 struct require_member<
0743 inline_or_executor<Executor, Blocking, InlineExceptionHandling>,
0744 execution::inline_exception_handling_t::propagate_t
0745 >
0746 {
0747 static constexpr bool is_valid = true;
0748 static constexpr bool is_noexcept = true;
0749 typedef inline_or_executor<Executor, Blocking,
0750 execution::inline_exception_handling_t::propagate_t> result_type;
0751 };
0752
0753 template <typename Executor, typename Blocking,
0754 typename InlineExceptionHandling>
0755 struct require_member<
0756 inline_or_executor<Executor, Blocking, InlineExceptionHandling>,
0757 execution::inline_exception_handling_t::terminate_t
0758 >
0759 {
0760 static constexpr bool is_valid = true;
0761 static constexpr bool is_noexcept = true;
0762 typedef inline_or_executor<Executor, Blocking,
0763 execution::inline_exception_handling_t::terminate_t> result_type;
0764 };
0765
0766 template <typename Executor, typename Blocking,
0767 typename InlineExceptionHandling, typename Property>
0768 struct require_member<
0769 inline_or_executor<Executor, Blocking, InlineExceptionHandling>, Property,
0770 enable_if_t<
0771 can_require<const Executor&, Property>::value
0772 && !is_convertible<Property,
0773 execution::blocking_t>::value
0774 && !is_convertible<Property,
0775 execution::inline_exception_handling_t>::value
0776 >
0777 >
0778 {
0779 static constexpr bool is_valid = true;
0780 static constexpr bool is_noexcept =
0781 is_nothrow_require<const Executor&, Property>::value;
0782 typedef inline_or_executor<
0783 decay_t<require_result_t<const Executor&, Property>>,
0784 Blocking, InlineExceptionHandling> result_type;
0785 };
0786
0787 #endif
0788
0789 #if !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)
0790
0791 template <typename Executor, typename Blocking,
0792 typename InlineExceptionHandling, typename Property>
0793 struct prefer_member<
0794 inline_or_executor<Executor, Blocking, InlineExceptionHandling>, Property,
0795 enable_if_t<
0796 can_prefer<const Executor&, Property>::value
0797 && !is_convertible<Property, execution::blocking_t::always_t>::value
0798 >
0799 >
0800 {
0801 static constexpr bool is_valid = true;
0802 static constexpr bool is_noexcept =
0803 is_nothrow_prefer<const Executor&, Property>::value;
0804 typedef inline_or_executor<
0805 decay_t<prefer_result_t<const Executor&, Property>>,
0806 Blocking, InlineExceptionHandling> result_type;
0807 };
0808
0809 #endif
0810
0811 }
0812
0813 #endif
0814
0815 }
0816 }
0817
0818 #include <boost/asio/detail/pop_options.hpp>
0819
0820 #endif