// // SocketReactor.h // // $Id: //poco/1.4/Net/include/Poco/Net/SocketReactor.h#1 $ // // Library: Net // Package: Reactor // Module: SocketReactor // // Definition of the SocketReactor class. // // Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. // and Contributors. // // Permission is hereby granted, free of charge, to any person or organization // obtaining a copy of the software and accompanying documentation covered by // this license (the "Software") to use, reproduce, display, distribute, // execute, and transmit the Software, and to prepare derivative works of the // Software, and to permit third-parties to whom the Software is furnished to // do so, all subject to the following: // // The copyright notices in the Software and this entire statement, including // the above license grant, this restriction and the following disclaimer, // must be included in all copies of the Software, in whole or in part, and // all derivative works of the Software, unless such copies or derivative // works are solely in the form of machine-executable object code generated by // a source language processor. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. // #ifndef Net_SocketReactor_INCLUDED #define Net_SocketReactor_INCLUDED #include "Poco/Net/Net.h" #include "Poco/Net/Socket.h" #include "Poco/Runnable.h" #include "Poco/Timespan.h" #include "Poco/Observer.h" #include "Poco/AutoPtr.h" #include namespace Poco { namespace Net { class Socket; class SocketNotification; class SocketNotifier; class Net_API SocketReactor: public Poco::Runnable /// This class, which is part of the Reactor pattern, /// implements the "Initiation Dispatcher". /// /// The Reactor pattern has been described in the book /// "Pattern Languages of Program Design" by Jim Coplien /// and Douglas C. Schmidt (Addison Wesley, 1995). /// /// The Reactor design pattern handles service requests that /// are delivered concurrently to an application by one or more /// clients. Each service in an application may consist of several /// methods and is represented by a separate event handler. The event /// handler is responsible for servicing service-specific requests. /// The SocketReactor dispatches the event handlers. /// /// Event handlers (any class can be an event handler - there /// is no base class for event handlers) can be registered /// with the addEventHandler() method and deregistered with /// the removeEventHandler() method. /// /// An event handler is always registered for a certain socket, /// which is given in the call to addEventHandler(). Any method /// of the event handler class can be registered to handle the /// event - the only requirement is that the method takes /// a pointer to an instance of SocketNotification (or a subclass of it) /// as argument. /// /// Once started, the SocketReactor waits for events /// on the registered sockets, using Socket::select(). /// If an event is detected, the corresponding event handler /// is invoked. There are five event types (and corresponding /// notification classes) defined: ReadableNotification, WritableNotification, /// ErrorNotification, TimeoutNotification, IdleNotification and /// ShutdownNotification. /// /// The ReadableNotification will be dispatched if a socket becomes /// readable. The WritableNotification will be dispatched if a socket /// becomes writable. The ErrorNotification will be dispatched if /// there is an error condition on a socket. /// /// If the timeout expires and no event has occured, a /// TimeoutNotification will be dispatched to all event handlers /// registered for it. This is done in the onTimeout() method /// which can be overridden by subclasses to perform custom /// timeout processing. /// /// If there are no sockets for the SocketReactor to pass to /// Socket::select(), an IdleNotification will be dispatched to /// all event handlers registered for it. This is done in the /// onIdle() method which can be overridden by subclasses /// to perform custom idle processing. Since onIdle() will be /// called repeatedly in a loop, it is recommended to do a /// short sleep or yield in the event handler. /// /// Finally, when the SocketReactor is about to shut down (as a result /// of stop() being called), it dispatches a ShutdownNotification /// to all event handlers. This is done in the onShutdown() method /// which can be overridded by subclasses to perform custom /// shutdown processing. /// /// The SocketReactor is implemented so that it can /// run in its own thread. It is also possible to run /// multiple SocketReactors in parallel, as long as /// they work on different sockets. /// /// It is safe to call addEventHandler() and removeEventHandler() /// from another thread while the SocketReactor is running. Also, /// it is safe to call addEventHandler() and removeEventHandler() /// from event handlers. { public: SocketReactor(); /// Creates the SocketReactor. explicit SocketReactor(const Poco::Timespan& timeout); /// Creates the SocketReactor, using the given timeout. virtual ~SocketReactor(); /// Destroys the SocketReactor. void run(); /// Runs the SocketReactor. The reactor will run /// until stop() is called (in a separate thread). void stop(); /// Stops the SocketReactor. /// /// The reactor will be stopped when the next event /// (including a timeout event) occurs. void setTimeout(const Poco::Timespan& timeout); /// Sets the timeout. /// /// If no other event occurs for the given timeout /// interval, a timeout event is sent to all event listeners. /// /// The default timeout is 250 milliseconds; /// /// The timeout is passed to the Socket::select() /// method. const Poco::Timespan& getTimeout() const; /// Returns the timeout. void addEventHandler(const Socket& socket, const Poco::AbstractObserver& observer); /// Registers an event handler with the SocketReactor. /// /// Usage: /// Poco::Observer obs(*this, &MyEventHandler::handleMyEvent); /// reactor.addEventHandler(obs); void removeEventHandler(const Socket& socket, const Poco::AbstractObserver& observer); /// Unregisters an event handler with the SocketReactor. /// /// Usage: /// Poco::Observer obs(*this, &MyEventHandler::handleMyEvent); /// reactor.removeEventHandler(obs); protected: virtual void onTimeout(); /// Called if the timeout expires and no other events are available. /// /// Can be overridden by subclasses. The default implementation /// dispatches the TimeoutNotification and thus should be called by overriding /// implementations. virtual void onIdle(); /// Called if no sockets are available to call select() on. /// /// Can be overridden by subclasses. The default implementation /// dispatches the IdleNotification and thus should be called by overriding /// implementations. virtual void onShutdown(); /// Called when the SocketReactor is about to terminate. /// /// Can be overridden by subclasses. The default implementation /// dispatches the ShutdownNotification and thus should be called by overriding /// implementations. virtual void onBusy(); /// Called when the SocketReactor is busy and at least one notification /// has been dispatched. /// /// Can be overridden by subclasses to perform additional /// periodic tasks. The default implementation does nothing. void dispatch(const Socket& socket, SocketNotification* pNotification); /// Dispatches the given notification to all observers /// registered for the given socket. void dispatch(SocketNotification* pNotification); /// Dispatches the given notification to all observers. private: typedef Poco::AutoPtr NotifierPtr; typedef Poco::AutoPtr NotificationPtr; typedef std::map EventHandlerMap; void dispatch(NotifierPtr& pNotifier, SocketNotification* pNotification); enum { DEFAULT_TIMEOUT = 250000 }; bool _stop; Poco::Timespan _timeout; EventHandlerMap _handlers; NotificationPtr _pReadableNotification; NotificationPtr _pWritableNotification; NotificationPtr _pErrorNotification; NotificationPtr _pTimeoutNotification; NotificationPtr _pIdleNotification; NotificationPtr _pShutdownNotification; Poco::FastMutex _mutex; friend class SocketNotifier; }; } } // namespace Poco::Net #endif // Net_SocketReactor_INCLUDED