|
||||
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
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |