Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:09

0001 //
0002 // executor.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_HPP
0012 #define BOOST_ASIO_EXECUTOR_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 #if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
0021 
0022 #include <new>
0023 #include <typeinfo>
0024 #include <boost/asio/detail/cstddef.hpp>
0025 #include <boost/asio/detail/executor_function.hpp>
0026 #include <boost/asio/detail/memory.hpp>
0027 #include <boost/asio/detail/throw_exception.hpp>
0028 #include <boost/asio/execution_context.hpp>
0029 
0030 #include <boost/asio/detail/push_options.hpp>
0031 
0032 namespace boost {
0033 namespace asio {
0034 
0035 /// Exception thrown when trying to access an empty polymorphic executor.
0036 class bad_executor
0037   : public std::exception
0038 {
0039 public:
0040   /// Constructor.
0041   BOOST_ASIO_DECL bad_executor() noexcept;
0042 
0043   /// Obtain message associated with exception.
0044   BOOST_ASIO_DECL virtual const char* what() const
0045     noexcept;
0046 };
0047 
0048 /// Polymorphic wrapper for executors.
0049 class executor
0050 {
0051 public:
0052   /// Default constructor.
0053   executor() noexcept
0054     : impl_(0)
0055   {
0056   }
0057 
0058   /// Construct from nullptr.
0059   executor(nullptr_t) noexcept
0060     : impl_(0)
0061   {
0062   }
0063 
0064   /// Copy constructor.
0065   executor(const executor& other) noexcept
0066     : impl_(other.clone())
0067   {
0068   }
0069 
0070   /// Move constructor.
0071   executor(executor&& other) noexcept
0072     : impl_(other.impl_)
0073   {
0074     other.impl_ = 0;
0075   }
0076 
0077   /// Construct a polymorphic wrapper for the specified executor.
0078   template <typename Executor>
0079   executor(Executor e);
0080 
0081   /// Construct a polymorphic executor that points to the same target as
0082   /// another polymorphic executor.
0083   executor(std::nothrow_t, const executor& other) noexcept
0084     : impl_(other.clone())
0085   {
0086   }
0087 
0088   /// Construct a polymorphic executor that moves the target from another
0089   /// polymorphic executor.
0090   executor(std::nothrow_t, executor&& other) noexcept
0091     : impl_(other.impl_)
0092   {
0093     other.impl_ = 0;
0094   }
0095 
0096   /// Construct a polymorphic wrapper for the specified executor.
0097   template <typename Executor>
0098   executor(std::nothrow_t, Executor e) noexcept;
0099 
0100   /// Allocator-aware constructor to create a polymorphic wrapper for the
0101   /// specified executor.
0102   template <typename Executor, typename Allocator>
0103   executor(allocator_arg_t, const Allocator& a, Executor e);
0104 
0105   /// Destructor.
0106   ~executor()
0107   {
0108     destroy();
0109   }
0110 
0111   /// Assignment operator.
0112   executor& operator=(const executor& other) noexcept
0113   {
0114     destroy();
0115     impl_ = other.clone();
0116     return *this;
0117   }
0118 
0119   // Move assignment operator.
0120   executor& operator=(executor&& other) noexcept
0121   {
0122     destroy();
0123     impl_ = other.impl_;
0124     other.impl_ = 0;
0125     return *this;
0126   }
0127 
0128   /// Assignment operator for nullptr_t.
0129   executor& operator=(nullptr_t) noexcept
0130   {
0131     destroy();
0132     impl_ = 0;
0133     return *this;
0134   }
0135 
0136   /// Assignment operator to create a polymorphic wrapper for the specified
0137   /// executor.
0138   template <typename Executor>
0139   executor& operator=(Executor&& e) noexcept
0140   {
0141     executor tmp(static_cast<Executor&&>(e));
0142     destroy();
0143     impl_ = tmp.impl_;
0144     tmp.impl_ = 0;
0145     return *this;
0146   }
0147 
0148   /// Obtain the underlying execution context.
0149   execution_context& context() const noexcept
0150   {
0151     return get_impl()->context();
0152   }
0153 
0154   /// Inform the executor that it has some outstanding work to do.
0155   void on_work_started() const noexcept
0156   {
0157     get_impl()->on_work_started();
0158   }
0159 
0160   /// Inform the executor that some work is no longer outstanding.
0161   void on_work_finished() const noexcept
0162   {
0163     get_impl()->on_work_finished();
0164   }
0165 
0166   /// Request the executor to invoke the given function object.
0167   /**
0168    * This function is used to ask the executor to execute the given function
0169    * object. The function object is executed according to the rules of the
0170    * target executor object.
0171    *
0172    * @param f The function object to be called. The executor will make a copy
0173    * of the handler object as required. The function signature of the function
0174    * object must be: @code void function(); @endcode
0175    *
0176    * @param a An allocator that may be used by the executor to allocate the
0177    * internal storage needed for function invocation.
0178    */
0179   template <typename Function, typename Allocator>
0180   void dispatch(Function&& f, const Allocator& a) const;
0181 
0182   /// Request the executor to invoke the given function object.
0183   /**
0184    * This function is used to ask the executor to execute the given function
0185    * object. The function object is executed according to the rules of the
0186    * target executor object.
0187    *
0188    * @param f The function object to be called. The executor will make
0189    * a copy of the handler object as required. The function signature of the
0190    * function object must be: @code void function(); @endcode
0191    *
0192    * @param a An allocator that may be used by the executor to allocate the
0193    * internal storage needed for function invocation.
0194    */
0195   template <typename Function, typename Allocator>
0196   void post(Function&& f, const Allocator& a) const;
0197 
0198   /// Request the executor to invoke the given function object.
0199   /**
0200    * This function is used to ask the executor to execute the given function
0201    * object. The function object is executed according to the rules of the
0202    * target executor object.
0203    *
0204    * @param f The function object to be called. The executor will make
0205    * a copy of the handler object as required. The function signature of the
0206    * function object must be: @code void function(); @endcode
0207    *
0208    * @param a An allocator that may be used by the executor to allocate the
0209    * internal storage needed for function invocation.
0210    */
0211   template <typename Function, typename Allocator>
0212   void defer(Function&& f, const Allocator& a) const;
0213 
0214   struct unspecified_bool_type_t {};
0215   typedef void (*unspecified_bool_type)(unspecified_bool_type_t);
0216   static void unspecified_bool_true(unspecified_bool_type_t) {}
0217 
0218   /// Operator to test if the executor contains a valid target.
0219   operator unspecified_bool_type() const noexcept
0220   {
0221     return impl_ ? &executor::unspecified_bool_true : 0;
0222   }
0223 
0224   /// Obtain type information for the target executor object.
0225   /**
0226    * @returns If @c *this has a target type of type @c T, <tt>typeid(T)</tt>;
0227    * otherwise, <tt>typeid(void)</tt>.
0228    */
0229 #if !defined(BOOST_ASIO_NO_TYPEID) || defined(GENERATING_DOCUMENTATION)
0230   const std::type_info& target_type() const noexcept
0231   {
0232     return impl_ ? impl_->target_type() : typeid(void);
0233   }
0234 #else // !defined(BOOST_ASIO_NO_TYPEID) || defined(GENERATING_DOCUMENTATION)
0235   const void* target_type() const noexcept
0236   {
0237     return impl_ ? impl_->target_type() : 0;
0238   }
0239 #endif // !defined(BOOST_ASIO_NO_TYPEID) || defined(GENERATING_DOCUMENTATION)
0240 
0241   /// Obtain a pointer to the target executor object.
0242   /**
0243    * @returns If <tt>target_type() == typeid(T)</tt>, a pointer to the stored
0244    * executor target; otherwise, a null pointer.
0245    */
0246   template <typename Executor>
0247   Executor* target() noexcept;
0248 
0249   /// Obtain a pointer to the target executor object.
0250   /**
0251    * @returns If <tt>target_type() == typeid(T)</tt>, a pointer to the stored
0252    * executor target; otherwise, a null pointer.
0253    */
0254   template <typename Executor>
0255   const Executor* target() const noexcept;
0256 
0257   /// Compare two executors for equality.
0258   friend bool operator==(const executor& a,
0259       const executor& b) noexcept
0260   {
0261     if (a.impl_ == b.impl_)
0262       return true;
0263     if (!a.impl_ || !b.impl_)
0264       return false;
0265     return a.impl_->equals(b.impl_);
0266   }
0267 
0268   /// Compare two executors for inequality.
0269   friend bool operator!=(const executor& a,
0270       const executor& b) noexcept
0271   {
0272     return !(a == b);
0273   }
0274 
0275 private:
0276 #if !defined(GENERATING_DOCUMENTATION)
0277   typedef detail::executor_function function;
0278   template <typename, typename> class impl;
0279 
0280 #if !defined(BOOST_ASIO_NO_TYPEID)
0281   typedef const std::type_info& type_id_result_type;
0282 #else // !defined(BOOST_ASIO_NO_TYPEID)
0283   typedef const void* type_id_result_type;
0284 #endif // !defined(BOOST_ASIO_NO_TYPEID)
0285 
0286   template <typename T>
0287   static type_id_result_type type_id()
0288   {
0289 #if !defined(BOOST_ASIO_NO_TYPEID)
0290     return typeid(T);
0291 #else // !defined(BOOST_ASIO_NO_TYPEID)
0292     static int unique_id;
0293     return &unique_id;
0294 #endif // !defined(BOOST_ASIO_NO_TYPEID)
0295   }
0296 
0297   // Base class for all polymorphic executor implementations.
0298   class impl_base
0299   {
0300   public:
0301     virtual impl_base* clone() const noexcept = 0;
0302     virtual void destroy() noexcept = 0;
0303     virtual execution_context& context() noexcept = 0;
0304     virtual void on_work_started() noexcept = 0;
0305     virtual void on_work_finished() noexcept = 0;
0306     virtual void dispatch(function&&) = 0;
0307     virtual void post(function&&) = 0;
0308     virtual void defer(function&&) = 0;
0309     virtual type_id_result_type target_type() const noexcept = 0;
0310     virtual void* target() noexcept = 0;
0311     virtual const void* target() const noexcept = 0;
0312     virtual bool equals(const impl_base* e) const noexcept = 0;
0313 
0314   protected:
0315     impl_base(bool fast_dispatch) : fast_dispatch_(fast_dispatch) {}
0316     virtual ~impl_base() {}
0317 
0318   private:
0319     friend class executor;
0320     const bool fast_dispatch_;
0321   };
0322 
0323   // Helper function to check and return the implementation pointer.
0324   impl_base* get_impl() const
0325   {
0326     if (!impl_)
0327     {
0328       bad_executor ex;
0329       boost::asio::detail::throw_exception(ex);
0330     }
0331     return impl_;
0332   }
0333 
0334   // Helper function to clone another implementation.
0335   impl_base* clone() const noexcept
0336   {
0337     return impl_ ? impl_->clone() : 0;
0338   }
0339 
0340   // Helper function to destroy an implementation.
0341   void destroy() noexcept
0342   {
0343     if (impl_)
0344       impl_->destroy();
0345   }
0346 
0347   impl_base* impl_;
0348 #endif // !defined(GENERATING_DOCUMENTATION)
0349 };
0350 
0351 } // namespace asio
0352 } // namespace boost
0353 
0354 BOOST_ASIO_USES_ALLOCATOR(boost::asio::executor)
0355 
0356 #include <boost/asio/detail/pop_options.hpp>
0357 
0358 #include <boost/asio/impl/executor.hpp>
0359 #if defined(BOOST_ASIO_HEADER_ONLY)
0360 # include <boost/asio/impl/executor.ipp>
0361 #endif // defined(BOOST_ASIO_HEADER_ONLY)
0362 
0363 #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
0364 
0365 #endif // BOOST_ASIO_EXECUTOR_HPP