Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-15 09:03:25

0001 //
0002 // execution_context.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_EXECUTION_CONTEXT_HPP
0012 #define BOOST_ASIO_EXECUTION_CONTEXT_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 #include <cstddef>
0020 #include <stdexcept>
0021 #include <typeinfo>
0022 #include <boost/asio/detail/noncopyable.hpp>
0023 
0024 #include <boost/asio/detail/push_options.hpp>
0025 
0026 namespace boost {
0027 namespace asio {
0028 
0029 class execution_context;
0030 class io_context;
0031 
0032 #if !defined(GENERATING_DOCUMENTATION)
0033 template <typename Service> Service& use_service(execution_context&);
0034 template <typename Service> Service& use_service(io_context&);
0035 template <typename Service> void add_service(execution_context&, Service*);
0036 template <typename Service> bool has_service(execution_context&);
0037 #endif // !defined(GENERATING_DOCUMENTATION)
0038 
0039 namespace detail { class service_registry; }
0040 
0041 /// A context for function object execution.
0042 /**
0043  * An execution context represents a place where function objects will be
0044  * executed. An @c io_context is an example of an execution context.
0045  *
0046  * @par The execution_context class and services
0047  *
0048  * Class execution_context implements an extensible, type-safe, polymorphic set
0049  * of services, indexed by service type.
0050  *
0051  * Services exist to manage the resources that are shared across an execution
0052  * context. For example, timers may be implemented in terms of a single timer
0053  * queue, and this queue would be stored in a service.
0054  *
0055  * Access to the services of an execution_context is via three function
0056  * templates, use_service(), add_service() and has_service().
0057  *
0058  * In a call to @c use_service<Service>(), the type argument chooses a service,
0059  * making available all members of the named type. If @c Service is not present
0060  * in an execution_context, an object of type @c Service is created and added
0061  * to the execution_context. A C++ program can check if an execution_context
0062  * implements a particular service with the function template @c
0063  * has_service<Service>().
0064  *
0065  * Service objects may be explicitly added to an execution_context using the
0066  * function template @c add_service<Service>(). If the @c Service is already
0067  * present, the service_already_exists exception is thrown. If the owner of the
0068  * service is not the same object as the execution_context parameter, the
0069  * invalid_service_owner exception is thrown.
0070  *
0071  * Once a service reference is obtained from an execution_context object by
0072  * calling use_service(), that reference remains usable as long as the owning
0073  * execution_context object exists.
0074  *
0075  * All service implementations have execution_context::service as a public base
0076  * class. Custom services may be implemented by deriving from this class and
0077  * then added to an execution_context using the facilities described above.
0078  *
0079  * @par The execution_context as a base class
0080  *
0081  * Class execution_context may be used only as a base class for concrete
0082  * execution context types. The @c io_context is an example of such a derived
0083  * type.
0084  *
0085  * On destruction, a class that is derived from execution_context must perform
0086  * <tt>execution_context::shutdown()</tt> followed by
0087  * <tt>execution_context::destroy()</tt>.
0088  *
0089  * This destruction sequence permits programs to simplify their resource
0090  * management by using @c shared_ptr<>. Where an object's lifetime is tied to
0091  * the lifetime of a connection (or some other sequence of asynchronous
0092  * operations), a @c shared_ptr to the object would be bound into the handlers
0093  * for all asynchronous operations associated with it. This works as follows:
0094  *
0095  * @li When a single connection ends, all associated asynchronous operations
0096  * complete. The corresponding handler objects are destroyed, and all @c
0097  * shared_ptr references to the objects are destroyed.
0098  *
0099  * @li To shut down the whole program, the io_context function stop() is called
0100  * to terminate any run() calls as soon as possible. The io_context destructor
0101  * calls @c shutdown() and @c destroy() to destroy all pending handlers,
0102  * causing all @c shared_ptr references to all connection objects to be
0103  * destroyed.
0104  */
0105 class execution_context
0106   : private noncopyable
0107 {
0108 public:
0109   class id;
0110   class service;
0111 
0112 public:
0113   /// Constructor.
0114   BOOST_ASIO_DECL execution_context();
0115 
0116   /// Destructor.
0117   BOOST_ASIO_DECL ~execution_context();
0118 
0119 protected:
0120   /// Shuts down all services in the context.
0121   /**
0122    * This function is implemented as follows:
0123    *
0124    * @li For each service object @c svc in the execution_context set, in
0125    * reverse order of the beginning of service object lifetime, performs @c
0126    * svc->shutdown().
0127    */
0128   BOOST_ASIO_DECL void shutdown();
0129 
0130   /// Destroys all services in the context.
0131   /**
0132    * This function is implemented as follows:
0133    *
0134    * @li For each service object @c svc in the execution_context set, in
0135    * reverse order * of the beginning of service object lifetime, performs
0136    * <tt>delete static_cast<execution_context::service*>(svc)</tt>.
0137    */
0138   BOOST_ASIO_DECL void destroy();
0139 
0140 public:
0141   /// Fork-related event notifications.
0142   enum fork_event
0143   {
0144     /// Notify the context that the process is about to fork.
0145     fork_prepare,
0146 
0147     /// Notify the context that the process has forked and is the parent.
0148     fork_parent,
0149 
0150     /// Notify the context that the process has forked and is the child.
0151     fork_child
0152   };
0153 
0154   /// Notify the execution_context of a fork-related event.
0155   /**
0156    * This function is used to inform the execution_context that the process is
0157    * about to fork, or has just forked. This allows the execution_context, and
0158    * the services it contains, to perform any necessary housekeeping to ensure
0159    * correct operation following a fork.
0160    *
0161    * This function must not be called while any other execution_context
0162    * function, or any function associated with the execution_context's derived
0163    * class, is being called in another thread. It is, however, safe to call
0164    * this function from within a completion handler, provided no other thread
0165    * is accessing the execution_context or its derived class.
0166    *
0167    * @param event A fork-related event.
0168    *
0169    * @throws boost::system::system_error Thrown on failure. If the notification
0170    * fails the execution_context object should no longer be used and should be
0171    * destroyed.
0172    *
0173    * @par Example
0174    * The following code illustrates how to incorporate the notify_fork()
0175    * function:
0176    * @code my_execution_context.notify_fork(execution_context::fork_prepare);
0177    * if (fork() == 0)
0178    * {
0179    *   // This is the child process.
0180    *   my_execution_context.notify_fork(execution_context::fork_child);
0181    * }
0182    * else
0183    * {
0184    *   // This is the parent process.
0185    *   my_execution_context.notify_fork(execution_context::fork_parent);
0186    * } @endcode
0187    *
0188    * @note For each service object @c svc in the execution_context set,
0189    * performs <tt>svc->notify_fork();</tt>. When processing the fork_prepare
0190    * event, services are visited in reverse order of the beginning of service
0191    * object lifetime. Otherwise, services are visited in order of the beginning
0192    * of service object lifetime.
0193    */
0194   BOOST_ASIO_DECL void notify_fork(fork_event event);
0195 
0196   /// Obtain the service object corresponding to the given type.
0197   /**
0198    * This function is used to locate a service object that corresponds to the
0199    * given service type. If there is no existing implementation of the service,
0200    * then the execution_context will create a new instance of the service.
0201    *
0202    * @param e The execution_context object that owns the service.
0203    *
0204    * @return The service interface implementing the specified service type.
0205    * Ownership of the service interface is not transferred to the caller.
0206    */
0207   template <typename Service>
0208   friend Service& use_service(execution_context& e);
0209 
0210   /// Obtain the service object corresponding to the given type.
0211   /**
0212    * This function is used to locate a service object that corresponds to the
0213    * given service type. If there is no existing implementation of the service,
0214    * then the io_context will create a new instance of the service.
0215    *
0216    * @param ioc The io_context object that owns the service.
0217    *
0218    * @return The service interface implementing the specified service type.
0219    * Ownership of the service interface is not transferred to the caller.
0220    *
0221    * @note This overload is preserved for backwards compatibility with services
0222    * that inherit from io_context::service.
0223    */
0224   template <typename Service>
0225   friend Service& use_service(io_context& ioc);
0226 
0227   /// Creates a service object and adds it to the execution_context.
0228   /**
0229    * This function is used to add a service to the execution_context.
0230    *
0231    * @param e The execution_context object that owns the service.
0232    *
0233    * @param args Zero or more arguments to be passed to the service
0234    * constructor.
0235    *
0236    * @throws boost::asio::service_already_exists Thrown if a service of the
0237    * given type is already present in the execution_context.
0238    */
0239   template <typename Service, typename... Args>
0240   friend Service& make_service(execution_context& e, Args&&... args);
0241 
0242   /// (Deprecated: Use make_service().) Add a service object to the
0243   /// execution_context.
0244   /**
0245    * This function is used to add a service to the execution_context.
0246    *
0247    * @param e The execution_context object that owns the service.
0248    *
0249    * @param svc The service object. On success, ownership of the service object
0250    * is transferred to the execution_context. When the execution_context object
0251    * is destroyed, it will destroy the service object by performing: @code
0252    * delete static_cast<execution_context::service*>(svc) @endcode
0253    *
0254    * @throws boost::asio::service_already_exists Thrown if a service of the
0255    * given type is already present in the execution_context.
0256    *
0257    * @throws boost::asio::invalid_service_owner Thrown if the service's owning
0258    * execution_context is not the execution_context object specified by the
0259    * @c e parameter.
0260    */
0261   template <typename Service>
0262   friend void add_service(execution_context& e, Service* svc);
0263 
0264   /// Determine if an execution_context contains a specified service type.
0265   /**
0266    * This function is used to determine whether the execution_context contains a
0267    * service object corresponding to the given service type.
0268    *
0269    * @param e The execution_context object that owns the service.
0270    *
0271    * @return A boolean indicating whether the execution_context contains the
0272    * service.
0273    */
0274   template <typename Service>
0275   friend bool has_service(execution_context& e);
0276 
0277 private:
0278   // The service registry.
0279   boost::asio::detail::service_registry* service_registry_;
0280 };
0281 
0282 /// Class used to uniquely identify a service.
0283 class execution_context::id
0284   : private noncopyable
0285 {
0286 public:
0287   /// Constructor.
0288   id() {}
0289 };
0290 
0291 /// Base class for all io_context services.
0292 class execution_context::service
0293   : private noncopyable
0294 {
0295 public:
0296   /// Get the context object that owns the service.
0297   execution_context& context();
0298 
0299 protected:
0300   /// Constructor.
0301   /**
0302    * @param owner The execution_context object that owns the service.
0303    */
0304   BOOST_ASIO_DECL service(execution_context& owner);
0305 
0306   /// Destructor.
0307   BOOST_ASIO_DECL virtual ~service();
0308 
0309 private:
0310   /// Destroy all user-defined handler objects owned by the service.
0311   virtual void shutdown() = 0;
0312 
0313   /// Handle notification of a fork-related event to perform any necessary
0314   /// housekeeping.
0315   /**
0316    * This function is not a pure virtual so that services only have to
0317    * implement it if necessary. The default implementation does nothing.
0318    */
0319   BOOST_ASIO_DECL virtual void notify_fork(
0320       execution_context::fork_event event);
0321 
0322   friend class boost::asio::detail::service_registry;
0323   struct key
0324   {
0325     key() : type_info_(0), id_(0) {}
0326     const std::type_info* type_info_;
0327     const execution_context::id* id_;
0328   } key_;
0329 
0330   execution_context& owner_;
0331   service* next_;
0332 };
0333 
0334 /// Exception thrown when trying to add a duplicate service to an
0335 /// execution_context.
0336 class service_already_exists
0337   : public std::logic_error
0338 {
0339 public:
0340   BOOST_ASIO_DECL service_already_exists();
0341 };
0342 
0343 /// Exception thrown when trying to add a service object to an
0344 /// execution_context where the service has a different owner.
0345 class invalid_service_owner
0346   : public std::logic_error
0347 {
0348 public:
0349   BOOST_ASIO_DECL invalid_service_owner();
0350 };
0351 
0352 namespace detail {
0353 
0354 // Special derived service id type to keep classes header-file only.
0355 template <typename Type>
0356 class service_id
0357   : public execution_context::id
0358 {
0359 };
0360 
0361 // Special service base class to keep classes header-file only.
0362 template <typename Type>
0363 class execution_context_service_base
0364   : public execution_context::service
0365 {
0366 public:
0367   static service_id<Type> id;
0368 
0369   // Constructor.
0370   execution_context_service_base(execution_context& e)
0371     : execution_context::service(e)
0372   {
0373   }
0374 };
0375 
0376 template <typename Type>
0377 service_id<Type> execution_context_service_base<Type>::id;
0378 
0379 } // namespace detail
0380 } // namespace asio
0381 } // namespace boost
0382 
0383 #include <boost/asio/detail/pop_options.hpp>
0384 
0385 #include <boost/asio/impl/execution_context.hpp>
0386 #if defined(BOOST_ASIO_HEADER_ONLY)
0387 # include <boost/asio/impl/execution_context.ipp>
0388 #endif // defined(BOOST_ASIO_HEADER_ONLY)
0389 
0390 #endif // BOOST_ASIO_EXECUTION_CONTEXT_HPP