Chris@16: // Chris@16: // io_service.hpp Chris@16: // ~~~~~~~~~~~~~~ Chris@16: // Chris@101: // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See accompanying Chris@16: // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: Chris@16: #ifndef BOOST_ASIO_IO_SERVICE_HPP Chris@16: #define BOOST_ASIO_IO_SERVICE_HPP Chris@16: Chris@16: #if defined(_MSC_VER) && (_MSC_VER >= 1200) Chris@16: # pragma once Chris@16: #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) Chris@16: # include Chris@16: #elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) \ Chris@16: || defined(__osf__) Chris@16: # include Chris@16: #endif Chris@16: Chris@16: #include Chris@16: Chris@16: namespace boost { Chris@16: namespace asio { Chris@16: Chris@16: class io_service; Chris@16: template Service& use_service(io_service& ios); Chris@16: template void add_service(io_service& ios, Service* svc); Chris@16: template bool has_service(io_service& ios); Chris@16: Chris@16: namespace detail { Chris@16: #if defined(BOOST_ASIO_HAS_IOCP) Chris@16: typedef class win_iocp_io_service io_service_impl; Chris@16: class win_iocp_overlapped_ptr; Chris@16: #else Chris@16: typedef class task_io_service io_service_impl; Chris@16: #endif Chris@16: class service_registry; Chris@16: } // namespace detail Chris@16: Chris@16: /// Provides core I/O functionality. Chris@16: /** Chris@16: * The io_service class provides the core I/O functionality for users of the Chris@16: * asynchronous I/O objects, including: Chris@16: * Chris@16: * @li boost::asio::ip::tcp::socket Chris@16: * @li boost::asio::ip::tcp::acceptor Chris@16: * @li boost::asio::ip::udp::socket Chris@16: * @li boost::asio::deadline_timer. Chris@16: * Chris@16: * The io_service class also includes facilities intended for developers of Chris@16: * custom asynchronous services. Chris@16: * Chris@16: * @par Thread Safety Chris@16: * @e Distinct @e objects: Safe.@n Chris@16: * @e Shared @e objects: Safe, with the specific exceptions of the reset() and Chris@16: * notify_fork() functions. Calling reset() while there are unfinished run(), Chris@16: * run_one(), poll() or poll_one() calls results in undefined behaviour. The Chris@16: * notify_fork() function should not be called while any io_service function, Chris@16: * or any function on an I/O object that is associated with the io_service, is Chris@16: * being called in another thread. Chris@16: * Chris@16: * @par Concepts: Chris@16: * Dispatcher. Chris@16: * Chris@16: * @par Synchronous and asynchronous operations Chris@16: * Chris@16: * Synchronous operations on I/O objects implicitly run the io_service object Chris@16: * for an individual operation. The io_service functions run(), run_one(), Chris@16: * poll() or poll_one() must be called for the io_service to perform Chris@16: * asynchronous operations on behalf of a C++ program. Notification that an Chris@16: * asynchronous operation has completed is delivered by invocation of the Chris@16: * associated handler. Handlers are invoked only by a thread that is currently Chris@16: * calling any overload of run(), run_one(), poll() or poll_one() for the Chris@16: * io_service. Chris@16: * Chris@16: * @par Effect of exceptions thrown from handlers Chris@16: * Chris@16: * If an exception is thrown from a handler, the exception is allowed to Chris@16: * propagate through the throwing thread's invocation of run(), run_one(), Chris@16: * poll() or poll_one(). No other threads that are calling any of these Chris@16: * functions are affected. It is then the responsibility of the application to Chris@16: * catch the exception. Chris@16: * Chris@16: * After the exception has been caught, the run(), run_one(), poll() or Chris@16: * poll_one() call may be restarted @em without the need for an intervening Chris@16: * call to reset(). This allows the thread to rejoin the io_service object's Chris@16: * thread pool without impacting any other threads in the pool. Chris@16: * Chris@16: * For example: Chris@16: * Chris@16: * @code Chris@16: * boost::asio::io_service io_service; Chris@16: * ... Chris@16: * for (;;) Chris@16: * { Chris@16: * try Chris@16: * { Chris@16: * io_service.run(); Chris@16: * break; // run() exited normally Chris@16: * } Chris@16: * catch (my_exception& e) Chris@16: * { Chris@16: * // Deal with exception as appropriate. Chris@16: * } Chris@16: * } Chris@16: * @endcode Chris@16: * Chris@16: * @par Stopping the io_service from running out of work Chris@16: * Chris@16: * Some applications may need to prevent an io_service object's run() call from Chris@16: * returning when there is no more work to do. For example, the io_service may Chris@16: * be being run in a background thread that is launched prior to the Chris@16: * application's asynchronous operations. The run() call may be kept running by Chris@16: * creating an object of type boost::asio::io_service::work: Chris@16: * Chris@16: * @code boost::asio::io_service io_service; Chris@16: * boost::asio::io_service::work work(io_service); Chris@16: * ... @endcode Chris@16: * Chris@16: * To effect a shutdown, the application will then need to call the io_service Chris@16: * object's stop() member function. This will cause the io_service run() call Chris@16: * to return as soon as possible, abandoning unfinished operations and without Chris@16: * permitting ready handlers to be dispatched. Chris@16: * Chris@16: * Alternatively, if the application requires that all operations and handlers Chris@16: * be allowed to finish normally, the work object may be explicitly destroyed. Chris@16: * Chris@16: * @code boost::asio::io_service io_service; Chris@16: * auto_ptr work( Chris@16: * new boost::asio::io_service::work(io_service)); Chris@16: * ... Chris@16: * work.reset(); // Allow run() to exit. @endcode Chris@16: * Chris@16: * @par The io_service class and I/O services Chris@16: * Chris@16: * Class io_service implements an extensible, type-safe, polymorphic set of I/O Chris@16: * services, indexed by service type. An object of class io_service must be Chris@16: * initialised before I/O objects such as sockets, resolvers and timers can be Chris@16: * used. These I/O objects are distinguished by having constructors that accept Chris@16: * an @c io_service& parameter. Chris@16: * Chris@16: * I/O services exist to manage the logical interface to the operating system on Chris@16: * behalf of the I/O objects. In particular, there are resources that are shared Chris@16: * across a class of I/O objects. For example, timers may be implemented in Chris@16: * terms of a single timer queue. The I/O services manage these shared Chris@16: * resources. Chris@16: * Chris@16: * Access to the services of an io_service is via three function templates, Chris@16: * use_service(), add_service() and has_service(). Chris@16: * Chris@16: * In a call to @c use_service(), the type argument chooses a service, Chris@16: * making available all members of the named type. If @c Service is not present Chris@16: * in an io_service, an object of type @c Service is created and added to the Chris@16: * io_service. A C++ program can check if an io_service implements a Chris@16: * particular service with the function template @c has_service(). Chris@16: * Chris@16: * Service objects may be explicitly added to an io_service using the function Chris@16: * template @c add_service(). If the @c Service is already present, the Chris@16: * service_already_exists exception is thrown. If the owner of the service is Chris@16: * not the same object as the io_service parameter, the invalid_service_owner Chris@16: * exception is thrown. Chris@16: * Chris@16: * Once a service reference is obtained from an io_service object by calling Chris@16: * use_service(), that reference remains usable as long as the owning io_service Chris@16: * object exists. Chris@16: * Chris@16: * All I/O service implementations have io_service::service as a public base Chris@16: * class. Custom I/O services may be implemented by deriving from this class and Chris@16: * then added to an io_service using the facilities described above. Chris@16: */ Chris@16: class io_service Chris@16: : private noncopyable Chris@16: { Chris@16: private: Chris@16: typedef detail::io_service_impl impl_type; Chris@16: #if defined(BOOST_ASIO_HAS_IOCP) Chris@16: friend class detail::win_iocp_overlapped_ptr; Chris@16: #endif Chris@16: Chris@16: public: Chris@16: class work; Chris@16: friend class work; Chris@16: Chris@16: class id; Chris@16: Chris@16: class service; Chris@16: Chris@16: class strand; Chris@16: Chris@16: /// Constructor. Chris@16: BOOST_ASIO_DECL io_service(); Chris@16: Chris@16: /// Constructor. Chris@16: /** Chris@16: * Construct with a hint about the required level of concurrency. Chris@16: * Chris@16: * @param concurrency_hint A suggestion to the implementation on how many Chris@16: * threads it should allow to run simultaneously. Chris@16: */ Chris@16: BOOST_ASIO_DECL explicit io_service(std::size_t concurrency_hint); Chris@16: Chris@16: /// Destructor. Chris@16: /** Chris@16: * On destruction, the io_service performs the following sequence of Chris@16: * operations: Chris@16: * Chris@16: * @li For each service object @c svc in the io_service set, in reverse order Chris@16: * of the beginning of service object lifetime, performs Chris@16: * @c svc->shutdown_service(). Chris@16: * Chris@16: * @li Uninvoked handler objects that were scheduled for deferred invocation Chris@16: * on the io_service, or any associated strand, are destroyed. Chris@16: * Chris@16: * @li For each service object @c svc in the io_service set, in reverse order Chris@16: * of the beginning of service object lifetime, performs Chris@16: * delete static_cast(svc). Chris@16: * Chris@16: * @note The destruction sequence described above permits programs to Chris@16: * simplify their resource management by using @c shared_ptr<>. Where an Chris@16: * object's lifetime is tied to the lifetime of a connection (or some other Chris@16: * sequence of asynchronous operations), a @c shared_ptr to the object would Chris@16: * be bound into the handlers for all asynchronous operations associated with Chris@16: * it. This works as follows: Chris@16: * Chris@16: * @li When a single connection ends, all associated asynchronous operations Chris@16: * complete. The corresponding handler objects are destroyed, and all Chris@16: * @c shared_ptr references to the objects are destroyed. Chris@16: * Chris@16: * @li To shut down the whole program, the io_service function stop() is Chris@16: * called to terminate any run() calls as soon as possible. The io_service Chris@16: * destructor defined above destroys all handlers, causing all @c shared_ptr Chris@16: * references to all connection objects to be destroyed. Chris@16: */ Chris@16: BOOST_ASIO_DECL ~io_service(); Chris@16: Chris@16: /// Run the io_service object's event processing loop. Chris@16: /** Chris@16: * The run() function blocks until all work has finished and there are no Chris@16: * more handlers to be dispatched, or until the io_service has been stopped. Chris@16: * Chris@16: * Multiple threads may call the run() function to set up a pool of threads Chris@16: * from which the io_service may execute handlers. All threads that are Chris@16: * waiting in the pool are equivalent and the io_service may choose any one Chris@16: * of them to invoke a handler. Chris@16: * Chris@16: * A normal exit from the run() function implies that the io_service object Chris@16: * is stopped (the stopped() function returns @c true). Subsequent calls to Chris@16: * run(), run_one(), poll() or poll_one() will return immediately unless there Chris@16: * is a prior call to reset(). Chris@16: * Chris@16: * @return The number of handlers that were executed. Chris@16: * Chris@16: * @throws boost::system::system_error Thrown on failure. Chris@16: * Chris@16: * @note The run() function must not be called from a thread that is currently Chris@16: * calling one of run(), run_one(), poll() or poll_one() on the same Chris@16: * io_service object. Chris@16: * Chris@16: * The poll() function may also be used to dispatch ready handlers, but Chris@16: * without blocking. Chris@16: */ Chris@16: BOOST_ASIO_DECL std::size_t run(); Chris@16: Chris@16: /// Run the io_service object's event processing loop. Chris@16: /** Chris@16: * The run() function blocks until all work has finished and there are no Chris@16: * more handlers to be dispatched, or until the io_service has been stopped. Chris@16: * Chris@16: * Multiple threads may call the run() function to set up a pool of threads Chris@16: * from which the io_service may execute handlers. All threads that are Chris@16: * waiting in the pool are equivalent and the io_service may choose any one Chris@16: * of them to invoke a handler. Chris@16: * Chris@16: * A normal exit from the run() function implies that the io_service object Chris@16: * is stopped (the stopped() function returns @c true). Subsequent calls to Chris@16: * run(), run_one(), poll() or poll_one() will return immediately unless there Chris@16: * is a prior call to reset(). Chris@16: * Chris@16: * @param ec Set to indicate what error occurred, if any. Chris@16: * Chris@16: * @return The number of handlers that were executed. Chris@16: * Chris@16: * @note The run() function must not be called from a thread that is currently Chris@16: * calling one of run(), run_one(), poll() or poll_one() on the same Chris@16: * io_service object. Chris@16: * Chris@16: * The poll() function may also be used to dispatch ready handlers, but Chris@16: * without blocking. Chris@16: */ Chris@16: BOOST_ASIO_DECL std::size_t run(boost::system::error_code& ec); Chris@16: Chris@16: /// Run the io_service object's event processing loop to execute at most one Chris@16: /// handler. Chris@16: /** Chris@16: * The run_one() function blocks until one handler has been dispatched, or Chris@16: * until the io_service has been stopped. Chris@16: * Chris@16: * @return The number of handlers that were executed. A zero return value Chris@16: * implies that the io_service object is stopped (the stopped() function Chris@16: * returns @c true). Subsequent calls to run(), run_one(), poll() or Chris@16: * poll_one() will return immediately unless there is a prior call to Chris@16: * reset(). Chris@16: * Chris@16: * @throws boost::system::system_error Thrown on failure. Chris@16: */ Chris@16: BOOST_ASIO_DECL std::size_t run_one(); Chris@16: Chris@16: /// Run the io_service object's event processing loop to execute at most one Chris@16: /// handler. Chris@16: /** Chris@16: * The run_one() function blocks until one handler has been dispatched, or Chris@16: * until the io_service has been stopped. Chris@16: * Chris@16: * @return The number of handlers that were executed. A zero return value Chris@16: * implies that the io_service object is stopped (the stopped() function Chris@16: * returns @c true). Subsequent calls to run(), run_one(), poll() or Chris@16: * poll_one() will return immediately unless there is a prior call to Chris@16: * reset(). Chris@16: * Chris@16: * @return The number of handlers that were executed. Chris@16: */ Chris@16: BOOST_ASIO_DECL std::size_t run_one(boost::system::error_code& ec); Chris@16: Chris@16: /// Run the io_service object's event processing loop to execute ready Chris@16: /// handlers. Chris@16: /** Chris@16: * The poll() function runs handlers that are ready to run, without blocking, Chris@16: * until the io_service has been stopped or there are no more ready handlers. Chris@16: * Chris@16: * @return The number of handlers that were executed. Chris@16: * Chris@16: * @throws boost::system::system_error Thrown on failure. Chris@16: */ Chris@16: BOOST_ASIO_DECL std::size_t poll(); Chris@16: Chris@16: /// Run the io_service object's event processing loop to execute ready Chris@16: /// handlers. Chris@16: /** Chris@16: * The poll() function runs handlers that are ready to run, without blocking, Chris@16: * until the io_service has been stopped or there are no more ready handlers. Chris@16: * Chris@16: * @param ec Set to indicate what error occurred, if any. Chris@16: * Chris@16: * @return The number of handlers that were executed. Chris@16: */ Chris@16: BOOST_ASIO_DECL std::size_t poll(boost::system::error_code& ec); Chris@16: Chris@16: /// Run the io_service object's event processing loop to execute one ready Chris@16: /// handler. Chris@16: /** Chris@16: * The poll_one() function runs at most one handler that is ready to run, Chris@16: * without blocking. Chris@16: * Chris@16: * @return The number of handlers that were executed. Chris@16: * Chris@16: * @throws boost::system::system_error Thrown on failure. Chris@16: */ Chris@16: BOOST_ASIO_DECL std::size_t poll_one(); Chris@16: Chris@16: /// Run the io_service object's event processing loop to execute one ready Chris@16: /// handler. Chris@16: /** Chris@16: * The poll_one() function runs at most one handler that is ready to run, Chris@16: * without blocking. Chris@16: * Chris@16: * @param ec Set to indicate what error occurred, if any. Chris@16: * Chris@16: * @return The number of handlers that were executed. Chris@16: */ Chris@16: BOOST_ASIO_DECL std::size_t poll_one(boost::system::error_code& ec); Chris@16: Chris@16: /// Stop the io_service object's event processing loop. Chris@16: /** Chris@16: * This function does not block, but instead simply signals the io_service to Chris@16: * stop. All invocations of its run() or run_one() member functions should Chris@16: * return as soon as possible. Subsequent calls to run(), run_one(), poll() Chris@16: * or poll_one() will return immediately until reset() is called. Chris@16: */ Chris@16: BOOST_ASIO_DECL void stop(); Chris@16: Chris@16: /// Determine whether the io_service object has been stopped. Chris@16: /** Chris@16: * This function is used to determine whether an io_service object has been Chris@16: * stopped, either through an explicit call to stop(), or due to running out Chris@16: * of work. When an io_service object is stopped, calls to run(), run_one(), Chris@16: * poll() or poll_one() will return immediately without invoking any Chris@16: * handlers. Chris@16: * Chris@16: * @return @c true if the io_service object is stopped, otherwise @c false. Chris@16: */ Chris@16: BOOST_ASIO_DECL bool stopped() const; Chris@16: Chris@16: /// Reset the io_service in preparation for a subsequent run() invocation. Chris@16: /** Chris@16: * This function must be called prior to any second or later set of Chris@16: * invocations of the run(), run_one(), poll() or poll_one() functions when a Chris@16: * previous invocation of these functions returned due to the io_service Chris@16: * being stopped or running out of work. After a call to reset(), the Chris@16: * io_service object's stopped() function will return @c false. Chris@16: * Chris@16: * This function must not be called while there are any unfinished calls to Chris@16: * the run(), run_one(), poll() or poll_one() functions. Chris@16: */ Chris@16: BOOST_ASIO_DECL void reset(); Chris@16: Chris@16: /// Request the io_service to invoke the given handler. Chris@16: /** Chris@16: * This function is used to ask the io_service to execute the given handler. Chris@16: * Chris@16: * The io_service guarantees that the handler will only be called in a thread Chris@16: * in which the run(), run_one(), poll() or poll_one() member functions is Chris@16: * currently being invoked. The handler may be executed inside this function Chris@16: * if the guarantee can be met. Chris@16: * Chris@16: * @param handler The handler to be called. The io_service will make Chris@16: * a copy of the handler object as required. The function signature of the Chris@16: * handler must be: @code void handler(); @endcode Chris@16: * Chris@16: * @note This function throws an exception only if: Chris@16: * Chris@16: * @li the handler's @c asio_handler_allocate function; or Chris@16: * Chris@16: * @li the handler's copy constructor Chris@16: * Chris@16: * throws an exception. Chris@16: */ Chris@16: template Chris@16: BOOST_ASIO_INITFN_RESULT_TYPE(CompletionHandler, void ()) Chris@16: dispatch(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler); Chris@16: Chris@16: /// Request the io_service to invoke the given handler and return immediately. Chris@16: /** Chris@16: * This function is used to ask the io_service to execute the given handler, Chris@16: * but without allowing the io_service to call the handler from inside this Chris@16: * function. Chris@16: * Chris@16: * The io_service guarantees that the handler will only be called in a thread Chris@16: * in which the run(), run_one(), poll() or poll_one() member functions is Chris@16: * currently being invoked. Chris@16: * Chris@16: * @param handler The handler to be called. The io_service will make Chris@16: * a copy of the handler object as required. The function signature of the Chris@16: * handler must be: @code void handler(); @endcode Chris@16: * Chris@16: * @note This function throws an exception only if: Chris@16: * Chris@16: * @li the handler's @c asio_handler_allocate function; or Chris@16: * Chris@16: * @li the handler's copy constructor Chris@16: * Chris@16: * throws an exception. Chris@16: */ Chris@16: template Chris@16: BOOST_ASIO_INITFN_RESULT_TYPE(CompletionHandler, void ()) Chris@16: post(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler); Chris@16: Chris@16: /// Create a new handler that automatically dispatches the wrapped handler Chris@16: /// on the io_service. Chris@16: /** Chris@16: * This function is used to create a new handler function object that, when Chris@16: * invoked, will automatically pass the wrapped handler to the io_service Chris@16: * object's dispatch function. Chris@16: * Chris@16: * @param handler The handler to be wrapped. The io_service will make a copy Chris@16: * of the handler object as required. The function signature of the handler Chris@16: * must be: @code void handler(A1 a1, ... An an); @endcode Chris@16: * Chris@16: * @return A function object that, when invoked, passes the wrapped handler to Chris@16: * the io_service object's dispatch function. Given a function object with the Chris@16: * signature: Chris@16: * @code R f(A1 a1, ... An an); @endcode Chris@16: * If this function object is passed to the wrap function like so: Chris@16: * @code io_service.wrap(f); @endcode Chris@16: * then the return value is a function object with the signature Chris@16: * @code void g(A1 a1, ... An an); @endcode Chris@16: * that, when invoked, executes code equivalent to: Chris@16: * @code io_service.dispatch(boost::bind(f, a1, ... an)); @endcode Chris@16: */ Chris@16: template Chris@16: #if defined(GENERATING_DOCUMENTATION) Chris@16: unspecified Chris@16: #else Chris@16: detail::wrapped_handler Chris@16: #endif Chris@16: wrap(Handler handler); Chris@16: Chris@16: /// Fork-related event notifications. Chris@16: enum fork_event Chris@16: { Chris@16: /// Notify the io_service that the process is about to fork. Chris@16: fork_prepare, Chris@16: Chris@16: /// Notify the io_service that the process has forked and is the parent. Chris@16: fork_parent, Chris@16: Chris@16: /// Notify the io_service that the process has forked and is the child. Chris@16: fork_child Chris@16: }; Chris@16: Chris@16: /// Notify the io_service of a fork-related event. Chris@16: /** Chris@16: * This function is used to inform the io_service that the process is about Chris@16: * to fork, or has just forked. This allows the io_service, and the services Chris@16: * it contains, to perform any necessary housekeeping to ensure correct Chris@16: * operation following a fork. Chris@16: * Chris@16: * This function must not be called while any other io_service function, or Chris@16: * any function on an I/O object associated with the io_service, is being Chris@16: * called in another thread. It is, however, safe to call this function from Chris@16: * within a completion handler, provided no other thread is accessing the Chris@16: * io_service. Chris@16: * Chris@16: * @param event A fork-related event. Chris@16: * Chris@16: * @throws boost::system::system_error Thrown on failure. If the notification Chris@16: * fails the io_service object should no longer be used and should be Chris@16: * destroyed. Chris@16: * Chris@16: * @par Example Chris@16: * The following code illustrates how to incorporate the notify_fork() Chris@16: * function: Chris@16: * @code my_io_service.notify_fork(boost::asio::io_service::fork_prepare); Chris@16: * if (fork() == 0) Chris@16: * { Chris@16: * // This is the child process. Chris@16: * my_io_service.notify_fork(boost::asio::io_service::fork_child); Chris@16: * } Chris@16: * else Chris@16: * { Chris@16: * // This is the parent process. Chris@16: * my_io_service.notify_fork(boost::asio::io_service::fork_parent); Chris@16: * } @endcode Chris@16: * Chris@16: * @note For each service object @c svc in the io_service set, performs Chris@16: * svc->fork_service();. When processing the fork_prepare event, Chris@16: * services are visited in reverse order of the beginning of service object Chris@16: * lifetime. Otherwise, services are visited in order of the beginning of Chris@16: * service object lifetime. Chris@16: */ Chris@16: BOOST_ASIO_DECL void notify_fork(boost::asio::io_service::fork_event event); Chris@16: Chris@16: /// Obtain the service object corresponding to the given type. Chris@16: /** Chris@16: * This function is used to locate a service object that corresponds to Chris@16: * the given service type. If there is no existing implementation of the Chris@16: * service, then the io_service will create a new instance of the service. Chris@16: * Chris@16: * @param ios The io_service object that owns the service. Chris@16: * Chris@16: * @return The service interface implementing the specified service type. Chris@16: * Ownership of the service interface is not transferred to the caller. Chris@16: */ Chris@16: template Chris@16: friend Service& use_service(io_service& ios); Chris@16: Chris@16: /// Add a service object to the io_service. Chris@16: /** Chris@16: * This function is used to add a service to the io_service. Chris@16: * Chris@16: * @param ios The io_service object that owns the service. Chris@16: * Chris@16: * @param svc The service object. On success, ownership of the service object Chris@16: * is transferred to the io_service. When the io_service object is destroyed, Chris@16: * it will destroy the service object by performing: Chris@16: * @code delete static_cast(svc) @endcode Chris@16: * Chris@16: * @throws boost::asio::service_already_exists Thrown if a service of the Chris@16: * given type is already present in the io_service. Chris@16: * Chris@16: * @throws boost::asio::invalid_service_owner Thrown if the service's owning Chris@16: * io_service is not the io_service object specified by the ios parameter. Chris@16: */ Chris@16: template Chris@16: friend void add_service(io_service& ios, Service* svc); Chris@16: Chris@16: /// Determine if an io_service contains a specified service type. Chris@16: /** Chris@16: * This function is used to determine whether the io_service contains a Chris@16: * service object corresponding to the given service type. Chris@16: * Chris@16: * @param ios The io_service object that owns the service. Chris@16: * Chris@16: * @return A boolean indicating whether the io_service contains the service. Chris@16: */ Chris@16: template Chris@16: friend bool has_service(io_service& ios); Chris@16: Chris@16: private: Chris@16: #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) Chris@16: detail::winsock_init<> init_; Chris@16: #elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) \ Chris@16: || defined(__osf__) Chris@16: detail::signal_init<> init_; Chris@16: #endif Chris@16: Chris@16: // The service registry. Chris@16: boost::asio::detail::service_registry* service_registry_; Chris@16: Chris@16: // The implementation. Chris@16: impl_type& impl_; Chris@16: }; Chris@16: Chris@16: /// Class to inform the io_service when it has work to do. Chris@16: /** Chris@16: * The work class is used to inform the io_service when work starts and Chris@16: * finishes. This ensures that the io_service object's run() function will not Chris@16: * exit while work is underway, and that it does exit when there is no Chris@16: * unfinished work remaining. Chris@16: * Chris@16: * The work class is copy-constructible so that it may be used as a data member Chris@16: * in a handler class. It is not assignable. Chris@16: */ Chris@16: class io_service::work Chris@16: { Chris@16: public: Chris@16: /// Constructor notifies the io_service that work is starting. Chris@16: /** Chris@16: * The constructor is used to inform the io_service that some work has begun. Chris@16: * This ensures that the io_service object's run() function will not exit Chris@16: * while the work is underway. Chris@16: */ Chris@16: explicit work(boost::asio::io_service& io_service); Chris@16: Chris@16: /// Copy constructor notifies the io_service that work is starting. Chris@16: /** Chris@16: * The constructor is used to inform the io_service that some work has begun. Chris@16: * This ensures that the io_service object's run() function will not exit Chris@16: * while the work is underway. Chris@16: */ Chris@16: work(const work& other); Chris@16: Chris@16: /// Destructor notifies the io_service that the work is complete. Chris@16: /** Chris@16: * The destructor is used to inform the io_service that some work has Chris@16: * finished. Once the count of unfinished work reaches zero, the io_service Chris@16: * object's run() function is permitted to exit. Chris@16: */ Chris@16: ~work(); Chris@16: Chris@16: /// Get the io_service associated with the work. Chris@16: boost::asio::io_service& get_io_service(); Chris@16: Chris@16: private: Chris@16: // Prevent assignment. Chris@16: void operator=(const work& other); Chris@16: Chris@16: // The io_service implementation. Chris@16: detail::io_service_impl& io_service_impl_; Chris@16: }; Chris@16: Chris@16: /// Class used to uniquely identify a service. Chris@16: class io_service::id Chris@16: : private noncopyable Chris@16: { Chris@16: public: Chris@16: /// Constructor. Chris@16: id() {} Chris@16: }; Chris@16: Chris@16: /// Base class for all io_service services. Chris@16: class io_service::service Chris@16: : private noncopyable Chris@16: { Chris@16: public: Chris@16: /// Get the io_service object that owns the service. Chris@16: boost::asio::io_service& get_io_service(); Chris@16: Chris@16: protected: Chris@16: /// Constructor. Chris@16: /** Chris@16: * @param owner The io_service object that owns the service. Chris@16: */ Chris@16: BOOST_ASIO_DECL service(boost::asio::io_service& owner); Chris@16: Chris@16: /// Destructor. Chris@16: BOOST_ASIO_DECL virtual ~service(); Chris@16: Chris@16: private: Chris@16: /// Destroy all user-defined handler objects owned by the service. Chris@16: virtual void shutdown_service() = 0; Chris@16: Chris@16: /// Handle notification of a fork-related event to perform any necessary Chris@16: /// housekeeping. Chris@16: /** Chris@16: * This function is not a pure virtual so that services only have to Chris@16: * implement it if necessary. The default implementation does nothing. Chris@16: */ Chris@16: BOOST_ASIO_DECL virtual void fork_service( Chris@16: boost::asio::io_service::fork_event event); Chris@16: Chris@16: friend class boost::asio::detail::service_registry; Chris@16: struct key Chris@16: { Chris@16: key() : type_info_(0), id_(0) {} Chris@16: const std::type_info* type_info_; Chris@16: const boost::asio::io_service::id* id_; Chris@16: } key_; Chris@16: Chris@16: boost::asio::io_service& owner_; Chris@16: service* next_; Chris@16: }; Chris@16: Chris@16: /// Exception thrown when trying to add a duplicate service to an io_service. Chris@16: class service_already_exists Chris@16: : public std::logic_error Chris@16: { Chris@16: public: Chris@16: BOOST_ASIO_DECL service_already_exists(); Chris@16: }; Chris@16: Chris@16: /// Exception thrown when trying to add a service object to an io_service where Chris@16: /// the service has a different owner. Chris@16: class invalid_service_owner Chris@16: : public std::logic_error Chris@16: { Chris@16: public: Chris@16: BOOST_ASIO_DECL invalid_service_owner(); Chris@16: }; Chris@16: Chris@16: namespace detail { Chris@16: Chris@16: // Special derived service id type to keep classes header-file only. Chris@16: template Chris@16: class service_id Chris@16: : public boost::asio::io_service::id Chris@16: { Chris@16: }; Chris@16: Chris@16: // Special service base class to keep classes header-file only. Chris@16: template Chris@16: class service_base Chris@16: : public boost::asio::io_service::service Chris@16: { Chris@16: public: Chris@16: static boost::asio::detail::service_id id; Chris@16: Chris@16: // Constructor. Chris@16: service_base(boost::asio::io_service& io_service) Chris@16: : boost::asio::io_service::service(io_service) Chris@16: { Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: boost::asio::detail::service_id service_base::id; Chris@16: Chris@16: } // namespace detail Chris@16: } // namespace asio Chris@16: } // namespace boost Chris@16: Chris@16: #include Chris@16: Chris@16: #include Chris@16: #if defined(BOOST_ASIO_HEADER_ONLY) Chris@16: # include Chris@16: #endif // defined(BOOST_ASIO_HEADER_ONLY) Chris@16: Chris@16: #endif // BOOST_ASIO_IO_SERVICE_HPP