File indexing completed on 2025-01-30 09:33:44
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_ASIO_EXECUTOR_WORK_GUARD_HPP
0012 #define BOOST_ASIO_EXECUTOR_WORK_GUARD_HPP
0013
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif
0017
0018 #include <boost/asio/detail/config.hpp>
0019
0020 #include <boost/asio/associated_executor.hpp>
0021 #include <boost/asio/detail/type_traits.hpp>
0022 #include <boost/asio/execution.hpp>
0023 #include <boost/asio/is_executor.hpp>
0024
0025 #include <boost/asio/detail/push_options.hpp>
0026
0027 namespace boost {
0028 namespace asio {
0029
0030 #if !defined(BOOST_ASIO_EXECUTOR_WORK_GUARD_DECL)
0031 #define BOOST_ASIO_EXECUTOR_WORK_GUARD_DECL
0032
0033 template <typename Executor, typename = void, typename = void>
0034 class executor_work_guard;
0035
0036 #endif
0037
0038 #if defined(GENERATING_DOCUMENTATION)
0039
0040
0041
0042 template <typename Executor>
0043 class executor_work_guard
0044 {
0045 public:
0046
0047 typedef Executor executor_type;
0048
0049
0050
0051
0052
0053 explicit executor_work_guard(const executor_type& e) noexcept;
0054
0055
0056 executor_work_guard(const executor_work_guard& other) noexcept;
0057
0058
0059 executor_work_guard(executor_work_guard&& other) noexcept;
0060
0061
0062
0063
0064
0065
0066 ~executor_work_guard();
0067
0068
0069 executor_type get_executor() const noexcept;
0070
0071
0072 bool owns_work() const noexcept;
0073
0074
0075
0076
0077
0078
0079 void reset() noexcept;
0080 };
0081
0082 #endif
0083
0084 #if !defined(GENERATING_DOCUMENTATION)
0085
0086 #if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
0087
0088 template <typename Executor>
0089 class executor_work_guard<Executor,
0090 enable_if_t<
0091 is_executor<Executor>::value
0092 >>
0093 {
0094 public:
0095 typedef Executor executor_type;
0096
0097 explicit executor_work_guard(const executor_type& e) noexcept
0098 : executor_(e),
0099 owns_(true)
0100 {
0101 executor_.on_work_started();
0102 }
0103
0104 executor_work_guard(const executor_work_guard& other) noexcept
0105 : executor_(other.executor_),
0106 owns_(other.owns_)
0107 {
0108 if (owns_)
0109 executor_.on_work_started();
0110 }
0111
0112 executor_work_guard(executor_work_guard&& other) noexcept
0113 : executor_(static_cast<Executor&&>(other.executor_)),
0114 owns_(other.owns_)
0115 {
0116 other.owns_ = false;
0117 }
0118
0119 ~executor_work_guard()
0120 {
0121 if (owns_)
0122 executor_.on_work_finished();
0123 }
0124
0125 executor_type get_executor() const noexcept
0126 {
0127 return executor_;
0128 }
0129
0130 bool owns_work() const noexcept
0131 {
0132 return owns_;
0133 }
0134
0135 void reset() noexcept
0136 {
0137 if (owns_)
0138 {
0139 executor_.on_work_finished();
0140 owns_ = false;
0141 }
0142 }
0143
0144 private:
0145
0146 executor_work_guard& operator=(const executor_work_guard&);
0147
0148 executor_type executor_;
0149 bool owns_;
0150 };
0151
0152 #endif
0153
0154 template <typename Executor>
0155 class executor_work_guard<Executor,
0156 enable_if_t<
0157 !is_executor<Executor>::value
0158 >,
0159 enable_if_t<
0160 execution::is_executor<Executor>::value
0161 >>
0162 {
0163 public:
0164 typedef Executor executor_type;
0165
0166 explicit executor_work_guard(const executor_type& e) noexcept
0167 : executor_(e),
0168 owns_(true)
0169 {
0170 new (&work_) work_type(boost::asio::prefer(executor_,
0171 execution::outstanding_work.tracked));
0172 }
0173
0174 executor_work_guard(const executor_work_guard& other) noexcept
0175 : executor_(other.executor_),
0176 owns_(other.owns_)
0177 {
0178 if (owns_)
0179 {
0180 new (&work_) work_type(boost::asio::prefer(executor_,
0181 execution::outstanding_work.tracked));
0182 }
0183 }
0184
0185 executor_work_guard(executor_work_guard&& other) noexcept
0186 : executor_(static_cast<Executor&&>(other.executor_)),
0187 owns_(other.owns_)
0188 {
0189 if (owns_)
0190 {
0191 new (&work_) work_type(
0192 static_cast<work_type&&>(
0193 *static_cast<work_type*>(
0194 static_cast<void*>(&other.work_))));
0195 other.owns_ = false;
0196 }
0197 }
0198
0199 ~executor_work_guard()
0200 {
0201 if (owns_)
0202 static_cast<work_type*>(static_cast<void*>(&work_))->~work_type();
0203 }
0204
0205 executor_type get_executor() const noexcept
0206 {
0207 return executor_;
0208 }
0209
0210 bool owns_work() const noexcept
0211 {
0212 return owns_;
0213 }
0214
0215 void reset() noexcept
0216 {
0217 if (owns_)
0218 {
0219 static_cast<work_type*>(static_cast<void*>(&work_))->~work_type();
0220 owns_ = false;
0221 }
0222 }
0223
0224 private:
0225
0226 executor_work_guard& operator=(const executor_work_guard&);
0227
0228 typedef decay_t<
0229 prefer_result_t<
0230 const executor_type&,
0231 execution::outstanding_work_t::tracked_t
0232 >
0233 > work_type;
0234
0235 executor_type executor_;
0236 aligned_storage_t<sizeof(work_type), alignment_of<work_type>::value> work_;
0237 bool owns_;
0238 };
0239
0240 #endif
0241
0242
0243
0244
0245
0246
0247
0248 template <typename Executor>
0249 BOOST_ASIO_NODISCARD inline executor_work_guard<Executor>
0250 make_work_guard(const Executor& ex,
0251 constraint_t<
0252 is_executor<Executor>::value || execution::is_executor<Executor>::value
0253 > = 0)
0254 {
0255 return executor_work_guard<Executor>(ex);
0256 }
0257
0258
0259
0260
0261
0262
0263
0264
0265 template <typename ExecutionContext>
0266 BOOST_ASIO_NODISCARD inline
0267 executor_work_guard<typename ExecutionContext::executor_type>
0268 make_work_guard(ExecutionContext& ctx,
0269 constraint_t<
0270 is_convertible<ExecutionContext&, execution_context&>::value
0271 > = 0)
0272 {
0273 return executor_work_guard<typename ExecutionContext::executor_type>(
0274 ctx.get_executor());
0275 }
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285 template <typename T>
0286 BOOST_ASIO_NODISCARD inline
0287 executor_work_guard<
0288 typename constraint_t<
0289 !is_executor<T>::value
0290 && !execution::is_executor<T>::value
0291 && !is_convertible<T&, execution_context&>::value,
0292 associated_executor<T>
0293 >::type>
0294 make_work_guard(const T& t)
0295 {
0296 return executor_work_guard<associated_executor_t<T>>(
0297 associated_executor<T>::get(t));
0298 }
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312 template <typename T, typename Executor>
0313 BOOST_ASIO_NODISCARD inline
0314 executor_work_guard<associated_executor_t<T, Executor>>
0315 make_work_guard(const T& t, const Executor& ex,
0316 constraint_t<
0317 is_executor<Executor>::value || execution::is_executor<Executor>::value
0318 > = 0)
0319 {
0320 return executor_work_guard<associated_executor_t<T, Executor>>(
0321 associated_executor<T, Executor>::get(t, ex));
0322 }
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336 template <typename T, typename ExecutionContext>
0337 BOOST_ASIO_NODISCARD inline executor_work_guard<
0338 associated_executor_t<T, typename ExecutionContext::executor_type>>
0339 make_work_guard(const T& t, ExecutionContext& ctx,
0340 constraint_t<
0341 !is_executor<T>::value
0342 > = 0,
0343 constraint_t<
0344 !execution::is_executor<T>::value
0345 > = 0,
0346 constraint_t<
0347 !is_convertible<T&, execution_context&>::value
0348 > = 0,
0349 constraint_t<
0350 is_convertible<ExecutionContext&, execution_context&>::value
0351 > = 0)
0352 {
0353 return executor_work_guard<
0354 associated_executor_t<T, typename ExecutionContext::executor_type>>(
0355 associated_executor<T, typename ExecutionContext::executor_type>::get(
0356 t, ctx.get_executor()));
0357 }
0358
0359 }
0360 }
0361
0362 #include <boost/asio/detail/pop_options.hpp>
0363
0364 #endif