Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:29:13

0001 //
0002 // execution_context.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2025 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   class service_maker;
0112 
0113 public:
0114   /// Constructor.
0115   BOOST_ASIO_DECL execution_context();
0116 
0117   /// Constructor.
0118   /**
0119    * Construct with a service maker, to create an initial set of services that
0120    * will be installed into the execution context at construction time.
0121    *
0122    * @param initial_services Used to create the initial services. The @c make
0123    * function will be called once at the end of execution_context construction.
0124    */
0125   BOOST_ASIO_DECL explicit execution_context(
0126       const service_maker& initial_services);
0127 
0128   /// Destructor.
0129   BOOST_ASIO_DECL ~execution_context();
0130 
0131 protected:
0132   /// Shuts down all services in the context.
0133   /**
0134    * This function is implemented as follows:
0135    *
0136    * @li For each service object @c svc in the execution_context set, in
0137    * reverse order of the beginning of service object lifetime, performs @c
0138    * svc->shutdown().
0139    */
0140   BOOST_ASIO_DECL void shutdown();
0141 
0142   /// Destroys all services in the context.
0143   /**
0144    * This function is implemented as follows:
0145    *
0146    * @li For each service object @c svc in the execution_context set, in
0147    * reverse order * of the beginning of service object lifetime, performs
0148    * <tt>delete static_cast<execution_context::service*>(svc)</tt>.
0149    */
0150   BOOST_ASIO_DECL void destroy();
0151 
0152 public:
0153   /// Fork-related event notifications.
0154   enum fork_event
0155   {
0156     /// Notify the context that the process is about to fork.
0157     fork_prepare,
0158 
0159     /// Notify the context that the process has forked and is the parent.
0160     fork_parent,
0161 
0162     /// Notify the context that the process has forked and is the child.
0163     fork_child
0164   };
0165 
0166   /// Notify the execution_context of a fork-related event.
0167   /**
0168    * This function is used to inform the execution_context that the process is
0169    * about to fork, or has just forked. This allows the execution_context, and
0170    * the services it contains, to perform any necessary housekeeping to ensure
0171    * correct operation following a fork.
0172    *
0173    * This function must not be called while any other execution_context
0174    * function, or any function associated with the execution_context's derived
0175    * class, is being called in another thread. It is, however, safe to call
0176    * this function from within a completion handler, provided no other thread
0177    * is accessing the execution_context or its derived class.
0178    *
0179    * @param event A fork-related event.
0180    *
0181    * @throws boost::system::system_error Thrown on failure. If the notification
0182    * fails the execution_context object should no longer be used and should be
0183    * destroyed.
0184    *
0185    * @par Example
0186    * The following code illustrates how to incorporate the notify_fork()
0187    * function:
0188    * @code my_execution_context.notify_fork(execution_context::fork_prepare);
0189    * if (fork() == 0)
0190    * {
0191    *   // This is the child process.
0192    *   my_execution_context.notify_fork(execution_context::fork_child);
0193    * }
0194    * else
0195    * {
0196    *   // This is the parent process.
0197    *   my_execution_context.notify_fork(execution_context::fork_parent);
0198    * } @endcode
0199    *
0200    * @note For each service object @c svc in the execution_context set,
0201    * performs <tt>svc->notify_fork();</tt>. When processing the fork_prepare
0202    * event, services are visited in reverse order of the beginning of service
0203    * object lifetime. Otherwise, services are visited in order of the beginning
0204    * of service object lifetime.
0205    */
0206   BOOST_ASIO_DECL void notify_fork(fork_event event);
0207 
0208   /// Obtain the service object corresponding to the given type.
0209   /**
0210    * This function is used to locate a service object that corresponds to the
0211    * given service type. If there is no existing implementation of the service,
0212    * then the execution_context will create a new instance of the service.
0213    *
0214    * @param e The execution_context object that owns the service.
0215    *
0216    * @return The service interface implementing the specified service type.
0217    * Ownership of the service interface is not transferred to the caller.
0218    */
0219   template <typename Service>
0220   friend Service& use_service(execution_context& e);
0221 
0222   /// Obtain the service object corresponding to the given type.
0223   /**
0224    * This function is used to locate a service object that corresponds to the
0225    * given service type. If there is no existing implementation of the service,
0226    * then the io_context will create a new instance of the service.
0227    *
0228    * @param ioc The io_context object that owns the service.
0229    *
0230    * @return The service interface implementing the specified service type.
0231    * Ownership of the service interface is not transferred to the caller.
0232    *
0233    * @note This overload is preserved for backwards compatibility with services
0234    * that inherit from io_context::service.
0235    */
0236   template <typename Service>
0237   friend Service& use_service(io_context& ioc);
0238 
0239   /// Creates a service object and adds it to the execution_context.
0240   /**
0241    * This function is used to add a service to the execution_context.
0242    *
0243    * @param e The execution_context object that owns the service.
0244    *
0245    * @param args Zero or more arguments to be passed to the service
0246    * constructor.
0247    *
0248    * @throws boost::asio::service_already_exists Thrown if a service of the
0249    * given type is already present in the execution_context.
0250    */
0251   template <typename Service, typename... Args>
0252   friend Service& make_service(execution_context& e, Args&&... args);
0253 
0254   /// (Deprecated: Use make_service().) Add a service object to the
0255   /// execution_context.
0256   /**
0257    * This function is used to add a service to the execution_context.
0258    *
0259    * @param e The execution_context object that owns the service.
0260    *
0261    * @param svc The service object. On success, ownership of the service object
0262    * is transferred to the execution_context. When the execution_context object
0263    * is destroyed, it will destroy the service object by performing: @code
0264    * delete static_cast<execution_context::service*>(svc) @endcode
0265    *
0266    * @throws boost::asio::service_already_exists Thrown if a service of the
0267    * given type is already present in the execution_context.
0268    *
0269    * @throws boost::asio::invalid_service_owner Thrown if the service's owning
0270    * execution_context is not the execution_context object specified by the
0271    * @c e parameter.
0272    */
0273   template <typename Service>
0274   friend void add_service(execution_context& e, Service* svc);
0275 
0276   /// Determine if an execution_context contains a specified service type.
0277   /**
0278    * This function is used to determine whether the execution_context contains a
0279    * service object corresponding to the given service type.
0280    *
0281    * @param e The execution_context object that owns the service.
0282    *
0283    * @return A boolean indicating whether the execution_context contains the
0284    * service.
0285    */
0286   template <typename Service>
0287   friend bool has_service(execution_context& e);
0288 
0289 private:
0290   // The service registry.
0291   boost::asio::detail::service_registry* service_registry_;
0292 };
0293 
0294 /// Class used to uniquely identify a service.
0295 class execution_context::id
0296   : private noncopyable
0297 {
0298 public:
0299   /// Constructor.
0300   id() {}
0301 };
0302 
0303 /// Base class for all execution context services.
0304 class execution_context::service
0305   : private noncopyable
0306 {
0307 public:
0308   /// Get the context object that owns the service.
0309   execution_context& context();
0310 
0311 protected:
0312   /// Constructor.
0313   /**
0314    * @param owner The execution_context object that owns the service.
0315    */
0316   BOOST_ASIO_DECL service(execution_context& owner);
0317 
0318   /// Destructor.
0319   BOOST_ASIO_DECL virtual ~service();
0320 
0321 private:
0322   /// Destroy all user-defined handler objects owned by the service.
0323   virtual void shutdown() = 0;
0324 
0325   /// Handle notification of a fork-related event to perform any necessary
0326   /// housekeeping.
0327   /**
0328    * This function is not a pure virtual so that services only have to
0329    * implement it if necessary. The default implementation does nothing.
0330    */
0331   BOOST_ASIO_DECL virtual void notify_fork(
0332       execution_context::fork_event event);
0333 
0334   friend class boost::asio::detail::service_registry;
0335   struct key
0336   {
0337     key() : type_info_(0), id_(0) {}
0338     const std::type_info* type_info_;
0339     const execution_context::id* id_;
0340   } key_;
0341 
0342   execution_context& owner_;
0343   service* next_;
0344 };
0345 
0346 /// Base class for all execution context service makers.
0347 /**
0348  * A service maker is called by the execution context to create services that
0349  * need to be installed into the execution context at construction time.
0350  */
0351 class execution_context::service_maker
0352   : private noncopyable
0353 {
0354 public:
0355   /// Make services to be added to the execution context.
0356   virtual void make(execution_context& context) const = 0;
0357 
0358 protected:
0359   /// Destructor.
0360   BOOST_ASIO_DECL virtual ~service_maker();
0361 };
0362 
0363 /// Exception thrown when trying to add a duplicate service to an
0364 /// execution_context.
0365 class service_already_exists
0366   : public std::logic_error
0367 {
0368 public:
0369   BOOST_ASIO_DECL service_already_exists();
0370 };
0371 
0372 /// Exception thrown when trying to add a service object to an
0373 /// execution_context where the service has a different owner.
0374 class invalid_service_owner
0375   : public std::logic_error
0376 {
0377 public:
0378   BOOST_ASIO_DECL invalid_service_owner();
0379 };
0380 
0381 namespace detail {
0382 
0383 // Special derived service id type to keep classes header-file only.
0384 template <typename Type>
0385 class service_id
0386   : public execution_context::id
0387 {
0388 };
0389 
0390 // Special service base class to keep classes header-file only.
0391 template <typename Type>
0392 class execution_context_service_base
0393   : public execution_context::service
0394 {
0395 public:
0396   static service_id<Type> id;
0397 
0398   // Constructor.
0399   execution_context_service_base(execution_context& e)
0400     : execution_context::service(e)
0401   {
0402   }
0403 };
0404 
0405 template <typename Type>
0406 service_id<Type> execution_context_service_base<Type>::id;
0407 
0408 } // namespace detail
0409 } // namespace asio
0410 } // namespace boost
0411 
0412 #include <boost/asio/detail/pop_options.hpp>
0413 
0414 #include <boost/asio/impl/execution_context.hpp>
0415 #if defined(BOOST_ASIO_HEADER_ONLY)
0416 # include <boost/asio/impl/execution_context.ipp>
0417 #endif // defined(BOOST_ASIO_HEADER_ONLY)
0418 
0419 #endif // BOOST_ASIO_EXECUTION_CONTEXT_HPP