/* -*- C++ -*- */ // $Id$ // ============================================================================ // // = LIBRARY // ace // // = FILENAME // Select_Reactor_T.h // // = AUTHOR // Doug Schmidt // // ============================================================================ #ifndef ACE_SELECT_REACTOR_T_H #define ACE_SELECT_REACTOR_T_H #include "ace/Select_Reactor_Base.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ template class ACE_Select_Reactor_Token_T : public ACE_SELECT_REACTOR_MUTEX { // = TITLE // Used as a synchronization mechanism to coordinate concurrent // access to a Select_Reactor object. // // = DESCRIPTION // This class is used to make the // thread-safe. By default, the thread that runs the // loop holds the token, even when it is blocked // in the call and gets // ``re-acquired'' as soon as the // there would be a good chance that the could have // been modified while the . Thus, it is not critical to change the // . The implementation of the mechanism // provided by the enables the // default owner to be the thread that executes the dispatch // loop. public: ACE_Select_Reactor_Token_T (ACE_Select_Reactor_Impl &r); ACE_Select_Reactor_Token_T (void); virtual ~ACE_Select_Reactor_Token_T (void); virtual void sleep_hook (void); // Called just before the ACE_Event_Handler goes to sleep. ACE_Select_Reactor_Impl &select_reactor (void); void select_reactor (ACE_Select_Reactor_Impl &); // Set/Get methods virtual void dump (void) const; // Dump the state of an object. ACE_ALLOC_HOOK_DECLARE; // Declare the dynamic allocation hooks. private: ACE_Select_Reactor_Impl *select_reactor_; }; template class ACE_Select_Reactor_T : public ACE_Select_Reactor_Impl { // = TITLE // An object oriented event demultiplexor and event handler // dispatcher. // // = DESCRIPTION // The ACE_Select_Reactor is an object-oriented event // demultiplexor and event handler dispatcher. The sources of // events that the ACE_Select_Reactor waits for and dispatches // includes I/O events, signals, and timer events. All public // methods acquire the main token lock and call // down to private or protected methods, which assume that the // lock is held and so therefore don't (re)acquire the lock. public: // = Initialization and termination methods. ACE_Select_Reactor_T (ACE_Sig_Handler * = 0, ACE_Timer_Queue * = 0, int disable_notify_pipe = 0, ACE_Reactor_Notify *notify = 0); // Initialize with the default size. ACE_Select_Reactor_T (size_t size, int restart = 0, ACE_Sig_Handler * = 0, ACE_Timer_Queue * = 0, int disable_notify_pipe = 0, ACE_Reactor_Notify *notify = 0); // Initialize with size . virtual int open (size_t size = DEFAULT_SIZE, int restart = 0, ACE_Sig_Handler * = 0, ACE_Timer_Queue * = 0, int disable_notify_pipe = 0, ACE_Reactor_Notify * = 0); // Initialize with size . virtual int current_info (ACE_HANDLE, size_t & /* size */); // Returns -1 (not used in this implementation); virtual int set_sig_handler (ACE_Sig_Handler *signal_handler); // Use a user specified signal handler instead. virtual int set_timer_queue (ACE_Timer_Queue *timer_queue); // Use a user specified timer queue instead. virtual int close (void); // Close down the select_reactor and release all of its resources. virtual ~ACE_Select_Reactor_T (void); // Close down the select_reactor and release all of its resources. // = Event loop drivers. virtual int handle_events (ACE_Time_Value *max_wait_time = 0); virtual int alertable_handle_events (ACE_Time_Value *max_wait_time = 0); // This event loop driver that blocks for before // returning. It will return earlier if timer events, I/O events, // or signal events occur. Note that can be 0, in // which case this method blocks indefinitely until events occur. // // is decremented to reflect how much time this call // took. For instance, if a time value of 3 seconds is passed to // handle_events and an event occurs after 2 seconds, // will equal 1 second. This can be used if an // application wishes to handle events for some fixed amount of // time. // // Returns the total number of I/O and Timer s // that were dispatched, 0 if the elapsed without // dispatching any handlers, or -1 if something goes wrong. // // Current is identical to // . virtual int handle_events (ACE_Time_Value &max_wait_time); virtual int alertable_handle_events (ACE_Time_Value &max_wait_time); // This method is just like the one above, except the // value is a reference and can therefore never be // NULL. // // Current is identical to // . // = Register and remove s. virtual int register_handler (ACE_Event_Handler *eh, ACE_Reactor_Mask mask); // Register a with a particular . Note that the // will call eh->get_handle() to extract the // underlying I/O handle. virtual int register_handler (ACE_HANDLE handle, ACE_Event_Handler *eh, ACE_Reactor_Mask mask); // Register a with a particular . Note that since the // is given the Select_Reactor will *not* call // eh->get_handle() to extract the underlying I/O handle. #if defined (ACE_WIN32) // Originally this interface was available for all platforms, but // because ACE_HANDLE is an int on non-Win32 platforms, compilers // are not able to tell the difference between // register_handler(ACE_Event_Handler*,ACE_Reactor_Mask) and // register_handler(ACE_Event_Handler*,ACE_HANDLE). Therefore, we // have restricted this method to Win32 only. virtual int register_handler (ACE_Event_Handler *event_handler, ACE_HANDLE event_handle = ACE_INVALID_HANDLE); // Not implemented. #endif /* ACE_WIN32 */ virtual int register_handler (ACE_HANDLE event_handle, ACE_HANDLE io_handle, ACE_Event_Handler *event_handler, ACE_Reactor_Mask mask); // Not implemented. virtual int register_handler (const ACE_Handle_Set &handles, ACE_Event_Handler *eh, ACE_Reactor_Mask mask); // Register with all the in the . virtual int register_handler (int signum, ACE_Event_Handler *new_sh, ACE_Sig_Action *new_disp = 0, ACE_Event_Handler **old_sh = 0, ACE_Sig_Action *old_disp = 0); // Register to handle the signal using the // . Returns the that was previously registered // (if any), along with the of the signal handler. virtual int register_handler (const ACE_Sig_Set &sigset, ACE_Event_Handler *new_sh, ACE_Sig_Action *new_disp = 0); // Registers to handle a set of signals using the // . virtual int remove_handler (ACE_Event_Handler *eh, ACE_Reactor_Mask mask); // Removes the binding of from the Select_Reactor. If // there are no more bindings for this then it is removed from // the Select_Reactor. Note that the Select_Reactor will call // eh->get_handle() to extract the underlying I/O handle. virtual int remove_handler (ACE_HANDLE handle, ACE_Reactor_Mask); // Removes the bind of whose handle is // from the Select_Reactor. If there are no more bindings // for this then it is removed from the Select_Reactor. virtual int remove_handler (const ACE_Handle_Set &handle_set, ACE_Reactor_Mask); // Removes all the bindings for handles in the // bind of . If there are no more bindings for any // of these handlers then they are removed from the Select_Reactor. virtual int remove_handler (int signum, ACE_Sig_Action *new_disp, ACE_Sig_Action *old_disp = 0, int sigkey = -1); // Remove the ACE_Event_Handler currently associated with . // is ignored in this implementation since there is only // one instance of a signal handler. Install the new disposition // (if given) and return the previous disposition (if desired by the // caller). Returns 0 on success and -1 if is invalid. virtual int remove_handler (const ACE_Sig_Set &sigset); // Calls for every signal in . // = Suspend and resume Handlers. virtual int suspend_handler (ACE_Event_Handler *eh); // Temporarily suspend the associated with . virtual int suspend_handler (ACE_HANDLE handle); // Temporarily suspend the associated with . virtual int suspend_handler (const ACE_Handle_Set &handles); // Suspend all in handle set temporarily. virtual int suspend_handlers (void); // Suspend all the in the Select_Reactor. virtual int resume_handler (ACE_Event_Handler *eh); // Resume a temporarily suspend associated with // . virtual int resume_handler (ACE_HANDLE handle); // Resume a temporarily suspended associated with // . virtual int resume_handler (const ACE_Handle_Set &handles); // Resume all in handle set. virtual int resume_handlers (void); // Resume all the in the Select_Reactor. virtual int uses_event_associations (void); // Return 1 if we any event associations were made by the reactor // for the handles that it waits on, 0 otherwise. Since the // Select_Reactor does not do any event associations, this function // always return 0. // = Timer management. virtual long schedule_timer (ACE_Event_Handler *, const void *arg, const ACE_Time_Value &delta_time, const ACE_Time_Value &interval = ACE_Time_Value::zero); // Schedule an that will expire after // amount of time. If it expires then is passed in as the // value to the 's callback method. // If is != to then it is used to // reschedule the automatically. This method // returns a that uniquely identifies the // in an internal list. This can be used to cancel an // before it expires. The cancellation ensures that // are unique up to values of greater than 2 billion // timers. As long as timers don't stay around longer than this // there should be no problems with accidentally deleting the wrong // timer. Returns -1 on failure (which is guaranteed never to be a // valid . virtual int cancel_timer (ACE_Event_Handler *event_handler, int dont_call_handle_close = 1); // Cancel all that match the address of // . If is 0 then the // method of will be invoked. // Returns number of handler's cancelled. virtual int cancel_timer (long timer_id, const void **arg = 0, int dont_call_handle_close = 1); // Cancel the single that matches the // value (which was returned from the method). If arg is // non-NULL then it will be set to point to the ``magic cookie'' // argument passed in when the was registered. This // makes it possible to free up the memory and avoid memory leaks. // If is 0 then the method // of will be invoked. Returns 1 if cancellation // succeeded and 0 if the wasn't found. // = High-level Event_Handler scheduling operations virtual int schedule_wakeup (ACE_Event_Handler *eh, ACE_Reactor_Mask mask); // ADD the dispatch MASK "bit" bound with the and the . virtual int schedule_wakeup (ACE_HANDLE handle, ACE_Reactor_Mask mask); // ADD the dispatch MASK "bit" bound with the and the . virtual int cancel_wakeup (ACE_Event_Handler *eh, ACE_Reactor_Mask mask); // CLR the dispatch MASK "bit" bound with the and the . virtual int cancel_wakeup (ACE_HANDLE handle, ACE_Reactor_Mask mask); // CLR the dispatch MASK "bit" bound with the and the . // = Notification methods. virtual int notify (ACE_Event_Handler * = 0, ACE_Reactor_Mask = ACE_Event_Handler::EXCEPT_MASK, ACE_Time_Value * = 0); // Called by a thread when it wants to unblock the Select_Reactor. // This wakeups the if currently blocked in // select()/poll(). Pass over both the *and* the // to allow the caller to dictate which // method the will invoke. The // indicates how long to blocking trying to notify the // . If == 0, the caller will block until // action is possible, else will wait until the relative time // specified in * elapses). virtual void max_notify_iterations (int); // Set the maximum number of times that the // method will iterate and // dispatch the that are passed in via the // notify pipe before breaking out of its loop. By default, // this is set to -1, which means "iterate until the pipe is empty." // Setting this to a value like "1 or 2" will increase "fairness" // (and thus prevent starvation) at the expense of slightly higher // dispatching overhead. virtual int max_notify_iterations (void); // Get the maximum number of times that the // method will iterate and // dispatch the that are passed in via the // notify pipe before breaking out of its loop. virtual void requeue_position (int); // Set position that the main ACE_Select_Reactor thread is requeued in the // list of waiters during a notify() callback. virtual int requeue_position (void); // Get position that the main ACE_Select_Reactor thread is requeued in the // list of waiters during a notify() callback. // = Low-level wait_set mask manipulation methods. virtual int mask_ops (ACE_Event_Handler *eh, ACE_Reactor_Mask mask, int ops); // GET/SET/ADD/CLR the dispatch mask "bit" bound with the and // . virtual int mask_ops (ACE_HANDLE handle, ACE_Reactor_Mask mask, int ops); // GET/SET/ADD/CLR the dispatch MASK "bit" bound with the // and . // = Low-level ready_set mask manipulation methods. virtual int ready_ops (ACE_Event_Handler *eh, ACE_Reactor_Mask mask, int ops); // GET/SET/ADD/CLR the ready "bit" bound with the and . virtual int ready_ops (ACE_HANDLE handle, ACE_Reactor_Mask, int ops); // GET/SET/ADD/CLR the ready "bit" bound with the and . virtual void wakeup_all_threads (void); // Wake up all threads in waiting in the event loop // = Only the owner thread that can perform a . virtual int owner (ACE_thread_t n_id, ACE_thread_t *o_id = 0); // Set the new owner of the thread and return the old owner. virtual int owner (ACE_thread_t *); // Return the current owner of the thread. // = Miscellaneous Handler operations. virtual int handler (ACE_HANDLE handle, ACE_Reactor_Mask mask, ACE_Event_Handler **eh = 0); // Check to see if is associated with a valid Event_Handler // bound to . Return the associated with this // if != 0. virtual int handler (int signum, ACE_Event_Handler ** = 0); // Check to see if is associated with a valid Event_Handler // bound to a signal. Return the associated with this // if != 0. virtual int initialized (void); // Returns true if we've been successfully initialized, else false. virtual size_t size (void); // Returns the current size of the Reactor's internal descriptor // table. virtual ACE_Lock &lock (void); // Returns a reference to the that is // used to serialize the internal Select_Reactor's processing logic. // This can be useful for situations where you need to avoid // deadlock efficiently when are used in // multiple threads. virtual void dump (void) const; // Dump the state of an object. ACE_ALLOC_HOOK_DECLARE; // Declare the dynamic allocation hooks. protected: // = Internal methods that do the actual work. // All of these methods assume that the 's token // lock is held by the public methods that call down to them. virtual int register_handler_i (ACE_HANDLE handle, ACE_Event_Handler *eh, ACE_Reactor_Mask mask); // Do the work of actually binding the and with the // . virtual int register_handler_i (const ACE_Handle_Set &handles, ACE_Event_Handler *handler, ACE_Reactor_Mask mask); // Register a set of . virtual int remove_handler_i (ACE_HANDLE handle, ACE_Reactor_Mask); // Do the work of actually unbinding the and with the // . virtual int remove_handler_i (const ACE_Handle_Set &handles, ACE_Reactor_Mask); // Remove a set of . virtual int suspend_i (ACE_HANDLE handle); // Suspend the associated with virtual int resume_i (ACE_HANDLE handle); // Resume the associated with virtual int handler_i (ACE_HANDLE handle, ACE_Reactor_Mask, ACE_Event_Handler ** = 0); // Implement the public method. virtual int handler_i (int signum, ACE_Event_Handler ** = 0); // Implement the public method. virtual int any_ready (ACE_Select_Reactor_Handle_Set &handle_set); // Check if there are any HANDLEs enabled in the , and // if so, update the and return the number ready. If // there aren't any HANDLEs enabled return 0. virtual int handle_error (void); // Take corrective action when errors occur. virtual int check_handles (void); // Make sure the handles are all valid. virtual int wait_for_multiple_events (ACE_Select_Reactor_Handle_Set &, ACE_Time_Value *); // Wait for events to occur. // = Dispatching methods. virtual int dispatch (int nfound, ACE_Select_Reactor_Handle_Set &); // Template Method that dispatches s for time // events, I/O events, and signal events. Returns the total number // of s that were dispatched or -1 if something // goes wrong. virtual int dispatch_timer_handlers (int &number_dispatched); // Dispatch all timer handlers that have expired. Returns -1 if the // state of the has changed, else 0. // is set to the number of timer handlers // dispatched. virtual int dispatch_notification_handlers (ACE_Select_Reactor_Handle_Set &dispatch_set, int &number_of_active_handles, int &number_of_handlers_dispatched); // Dispatch any notification handlers. Returns -1 if the state of // the has changed, else returns number of handlers // notified. virtual int dispatch_io_handlers (ACE_Select_Reactor_Handle_Set &dispatch_set, int &number_of_active_handles, int &number_of_handlers_dispatched); // Dispatch all the input/output/except handlers that are enabled in // the . Updates and // according to the behavior of the // number Returns -1 if the state of the has changed, // else 0. virtual int dispatch_io_set (int number_of_active_handles, int &number_of_handlers_dispatched, int mask, ACE_Handle_Set& dispatch_mask, ACE_Handle_Set& ready_mask, ACE_EH_PTMF callback); // Factors the dispatching of an io handle set (each WRITE, EXCEPT // or READ set of handles). It updates the // and invokes this->notify_handle // for all the handles in using the , // and parameters. Must return -1 if // this->state_changed otherwise it must return 0. virtual void notify_handle (ACE_HANDLE handle, ACE_Reactor_Mask mask, ACE_Handle_Set &, ACE_Event_Handler *eh, ACE_EH_PTMF callback); // Notify the appropriate in the context of the // associated with that a particular event has occurred. virtual void renew (void); // Enqueue ourselves into the list of waiting threads at the // appropriate point specified by . ACE_SELECT_REACTOR_TOKEN token_; // Synchronization token for the MT_SAFE ACE_Select_Reactor. ACE_Lock_Adapter lock_adapter_; // Adapter used to return internal lock to outside world. int release_token (void); // Release the token lock when a Win32 structured exception occurs. int handle_events_i (ACE_Time_Value *max_wait_time = 0); // Stops the VC++ compiler from bitching about exceptions and destructors private: ACE_UNIMPLEMENTED_FUNC (ACE_Select_Reactor_T (const ACE_Select_Reactor_T &)) ACE_UNIMPLEMENTED_FUNC (ACE_Select_Reactor_T &operator= (const ACE_Select_Reactor_T &) ) // Deny access since member-wise won't work... }; // @@ The latest version of SunCC can't grok the code if we put inline // function here. Therefore, we temporarily disable the code here. // We shall turn this back on once we know the problem gets fixed. #if 0 // defined (__ACE_INLINE__) #include "ace/Select_Reactor_T.i" #endif /* __ACE_INLINE__ */ #if defined (ACE_TEMPLATES_REQUIRE_SOURCE) #include "ace/Select_Reactor_T.cpp" #endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ #if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) #pragma implementation "Select_Reactor_T.cpp" #endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ #endif /* ACE_SELECT_REACTOR_T_H */