Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:33:44

0001 //
0002 // executor_work_guard.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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 // defined(_MSC_VER) && (_MSC_VER >= 1200)
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 // !defined(BOOST_ASIO_EXECUTOR_WORK_GUARD_DECL)
0037 
0038 #if defined(GENERATING_DOCUMENTATION)
0039 
0040 /// An object of type @c executor_work_guard controls ownership of outstanding
0041 /// executor work within a scope.
0042 template <typename Executor>
0043 class executor_work_guard
0044 {
0045 public:
0046   /// The underlying executor type.
0047   typedef Executor executor_type;
0048 
0049   /// Constructs a @c executor_work_guard object for the specified executor.
0050   /**
0051    * Stores a copy of @c e and calls <tt>on_work_started()</tt> on it.
0052    */
0053   explicit executor_work_guard(const executor_type& e) noexcept;
0054 
0055   /// Copy constructor.
0056   executor_work_guard(const executor_work_guard& other) noexcept;
0057 
0058   /// Move constructor.
0059   executor_work_guard(executor_work_guard&& other) noexcept;
0060 
0061   /// Destructor.
0062   /**
0063    * Unless the object has already been reset, or is in a moved-from state,
0064    * calls <tt>on_work_finished()</tt> on the stored executor.
0065    */
0066   ~executor_work_guard();
0067 
0068   /// Obtain the associated executor.
0069   executor_type get_executor() const noexcept;
0070 
0071   /// Whether the executor_work_guard object owns some outstanding work.
0072   bool owns_work() const noexcept;
0073 
0074   /// Indicate that the work is no longer outstanding.
0075   /**
0076    * Unless the object has already been reset, or is in a moved-from state,
0077    * calls <tt>on_work_finished()</tt> on the stored executor.
0078    */
0079   void reset() noexcept;
0080 };
0081 
0082 #endif // defined(GENERATING_DOCUMENTATION)
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   // Disallow assignment.
0146   executor_work_guard& operator=(const executor_work_guard&);
0147 
0148   executor_type executor_;
0149   bool owns_;
0150 };
0151 
0152 #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
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   // Disallow assignment.
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 // !defined(GENERATING_DOCUMENTATION)
0241 
0242 /// Create an @ref executor_work_guard object.
0243 /**
0244  * @param ex An executor.
0245  *
0246  * @returns A work guard constructed with the specified executor.
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 /// Create an @ref executor_work_guard object.
0259 /**
0260  * @param ctx An execution context, from which an executor will be obtained.
0261  *
0262  * @returns A work guard constructed with the execution context's executor,
0263  * obtained by performing <tt>ctx.get_executor()</tt>.
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 /// Create an @ref executor_work_guard object.
0278 /**
0279  * @param t An arbitrary object, such as a completion handler, for which the
0280  * associated executor will be obtained.
0281  *
0282  * @returns A work guard constructed with the associated executor of the object
0283  * @c t, which is obtained as if by calling <tt>get_associated_executor(t)</tt>.
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 /// Create an @ref executor_work_guard object.
0301 /**
0302  * @param t An arbitrary object, such as a completion handler, for which the
0303  * associated executor will be obtained.
0304  *
0305  * @param ex An executor to be used as the candidate object when determining the
0306  * associated executor.
0307  *
0308  * @returns A work guard constructed with the associated executor of the object
0309  * @c t, which is obtained as if by calling <tt>get_associated_executor(t,
0310  * ex)</tt>.
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 /// Create an @ref executor_work_guard object.
0325 /**
0326  * @param t An arbitrary object, such as a completion handler, for which the
0327  * associated executor will be obtained.
0328  *
0329  * @param ctx An execution context, from which an executor is obtained to use as
0330  * the candidate object for determining the associated executor.
0331  *
0332  * @returns A work guard constructed with the associated executor of the object
0333  * @c t, which is obtained as if by calling <tt>get_associated_executor(t,
0334  * ctx.get_executor())</tt>.
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 } // namespace asio
0360 } // namespace boost
0361 
0362 #include <boost/asio/detail/pop_options.hpp>
0363 
0364 #endif // BOOST_ASIO_EXECUTOR_WORK_GUARD_HPP