Chris@16: // Chris@16: // detail/signal_set_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_DETAIL_SIGNAL_SET_SERVICE_HPP Chris@16: #define BOOST_ASIO_DETAIL_SIGNAL_SET_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: 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: #include Chris@16: #include Chris@16: Chris@16: #if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) Chris@16: # include Chris@16: #endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) Chris@16: Chris@16: #include Chris@16: Chris@16: namespace boost { Chris@16: namespace asio { Chris@16: namespace detail { Chris@16: Chris@16: #if defined(NSIG) && (NSIG > 0) Chris@16: enum { max_signal_number = NSIG }; Chris@16: #else Chris@16: enum { max_signal_number = 128 }; Chris@16: #endif Chris@16: Chris@16: extern BOOST_ASIO_DECL struct signal_state* get_signal_state(); Chris@16: Chris@16: extern "C" BOOST_ASIO_DECL void boost_asio_signal_handler(int signal_number); Chris@16: Chris@16: class signal_set_service Chris@16: { Chris@16: public: Chris@16: // Type used for tracking an individual signal registration. Chris@16: class registration Chris@16: { Chris@16: public: Chris@16: // Default constructor. Chris@16: registration() Chris@16: : signal_number_(0), Chris@16: queue_(0), Chris@16: undelivered_(0), Chris@16: next_in_table_(0), Chris@16: prev_in_table_(0), Chris@16: next_in_set_(0) Chris@16: { Chris@16: } Chris@16: Chris@16: private: Chris@16: // Only this service will have access to the internal values. Chris@16: friend class signal_set_service; Chris@16: Chris@16: // The signal number that is registered. Chris@16: int signal_number_; Chris@16: Chris@16: // The waiting signal handlers. Chris@16: op_queue* queue_; Chris@16: Chris@16: // The number of undelivered signals. Chris@16: std::size_t undelivered_; Chris@16: Chris@16: // Pointers to adjacent registrations in the registrations_ table. Chris@16: registration* next_in_table_; Chris@16: registration* prev_in_table_; Chris@16: Chris@16: // Link to next registration in the signal set. Chris@16: registration* next_in_set_; Chris@16: }; Chris@16: Chris@16: // The implementation type of the signal_set. Chris@16: class implementation_type Chris@16: { Chris@16: public: Chris@16: // Default constructor. Chris@16: implementation_type() Chris@16: : signals_(0) Chris@16: { Chris@16: } Chris@16: Chris@16: private: Chris@16: // Only this service will have access to the internal values. Chris@16: friend class signal_set_service; Chris@16: Chris@16: // The pending signal handlers. Chris@16: op_queue queue_; Chris@16: Chris@16: // Linked list of registered signals. Chris@16: registration* signals_; Chris@16: }; Chris@16: Chris@16: // Constructor. Chris@16: BOOST_ASIO_DECL signal_set_service(boost::asio::io_service& io_service); Chris@16: Chris@16: // Destructor. Chris@16: BOOST_ASIO_DECL ~signal_set_service(); Chris@16: Chris@16: // Destroy all user-defined handler objects owned by the service. Chris@16: BOOST_ASIO_DECL void shutdown_service(); Chris@16: Chris@16: // Perform fork-related housekeeping. Chris@16: BOOST_ASIO_DECL void fork_service( Chris@16: boost::asio::io_service::fork_event fork_ev); Chris@16: Chris@16: // Construct a new signal_set implementation. Chris@16: BOOST_ASIO_DECL void construct(implementation_type& impl); Chris@16: Chris@16: // Destroy a signal_set implementation. Chris@16: BOOST_ASIO_DECL void destroy(implementation_type& impl); Chris@16: Chris@16: // Add a signal to a signal_set. Chris@16: BOOST_ASIO_DECL boost::system::error_code add(implementation_type& impl, Chris@16: int signal_number, boost::system::error_code& ec); Chris@16: Chris@16: // Remove a signal to a signal_set. Chris@16: BOOST_ASIO_DECL boost::system::error_code remove(implementation_type& impl, Chris@16: int signal_number, boost::system::error_code& ec); Chris@16: Chris@16: // Remove all signals from a signal_set. Chris@16: BOOST_ASIO_DECL boost::system::error_code clear(implementation_type& impl, Chris@16: boost::system::error_code& ec); Chris@16: Chris@16: // Cancel all operations associated with the signal set. Chris@16: BOOST_ASIO_DECL boost::system::error_code cancel(implementation_type& impl, Chris@16: boost::system::error_code& ec); Chris@16: Chris@16: // Start an asynchronous operation to wait for a signal to be delivered. Chris@16: template Chris@16: void async_wait(implementation_type& impl, Handler& handler) Chris@16: { Chris@16: // Allocate and construct an operation to wrap the handler. Chris@16: typedef signal_handler op; Chris@16: typename op::ptr p = { boost::asio::detail::addressof(handler), Chris@16: boost_asio_handler_alloc_helpers::allocate( Chris@16: sizeof(op), handler), 0 }; Chris@16: p.p = new (p.v) op(handler); Chris@16: Chris@16: BOOST_ASIO_HANDLER_CREATION((p.p, "signal_set", &impl, "async_wait")); Chris@16: Chris@16: start_wait_op(impl, p.p); Chris@16: p.v = p.p = 0; Chris@16: } Chris@16: Chris@16: // Deliver notification that a particular signal occurred. Chris@16: BOOST_ASIO_DECL static void deliver_signal(int signal_number); Chris@16: Chris@16: private: Chris@16: // Helper function to add a service to the global signal state. Chris@16: BOOST_ASIO_DECL static void add_service(signal_set_service* service); Chris@16: Chris@16: // Helper function to remove a service from the global signal state. Chris@16: BOOST_ASIO_DECL static void remove_service(signal_set_service* service); Chris@16: Chris@16: // Helper function to create the pipe descriptors. Chris@16: BOOST_ASIO_DECL static void open_descriptors(); Chris@16: Chris@16: // Helper function to close the pipe descriptors. Chris@16: BOOST_ASIO_DECL static void close_descriptors(); Chris@16: Chris@16: // Helper function to start a wait operation. Chris@16: BOOST_ASIO_DECL void start_wait_op(implementation_type& impl, signal_op* op); Chris@16: Chris@16: // The io_service instance used for dispatching handlers. Chris@16: io_service_impl& io_service_; Chris@16: Chris@16: #if !defined(BOOST_ASIO_WINDOWS) \ Chris@16: && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ Chris@16: && !defined(__CYGWIN__) Chris@16: // The type used for registering for pipe reactor notifications. Chris@16: class pipe_read_op; Chris@16: Chris@16: // The reactor used for waiting for pipe readiness. Chris@16: reactor& reactor_; Chris@16: Chris@16: // The per-descriptor reactor data used for the pipe. Chris@16: reactor::per_descriptor_data reactor_data_; Chris@16: #endif // !defined(BOOST_ASIO_WINDOWS) Chris@16: // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) Chris@16: // && !defined(__CYGWIN__) Chris@16: Chris@16: // A mapping from signal number to the registered signal sets. Chris@16: registration* registrations_[max_signal_number]; Chris@16: Chris@16: // Pointers to adjacent services in linked list. Chris@16: signal_set_service* next_; Chris@16: signal_set_service* prev_; Chris@16: }; Chris@16: Chris@16: } // namespace detail Chris@16: } // namespace asio Chris@16: } // namespace boost Chris@16: Chris@16: #include Chris@16: 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_DETAIL_SIGNAL_SET_SERVICE_HPP