/* -*- C++ -*- */
// $Id$

// ============================================================================
//
// = LIBRARY
//    ace
//
// = FILENAME
//    Select_Reactor.h
//
// = AUTHOR
//    Doug Schmidt
// 
// ============================================================================

#if !defined (ACE_SELECT_REACTOR_H)
#define ACE_SELECT_REACTOR_H

#include "ace/Signal.h"
#include "ace/Timer_Queue.h"
#include "ace/Event_Handler.h"
#include "ace/Handle_Set.h"
#include "ace/Token.h"
#include "ace/Pipe.h"
#include "ace/Reactor_Impl.h"

// Add useful typedefs to simplify the following code.
typedef void (ACE_Handle_Set::*ACE_FDS_PTMF) (ACE_HANDLE);
typedef int (ACE_Event_Handler::*ACE_EH_PTMF) (ACE_HANDLE);

// Forward declaration.
class ACE_Select_Reactor;

class ACE_Export ACE_Select_Reactor_Handle_Set
  // = TITLE
  //      Track handles we are interested for various events.
{
public:
  ACE_Handle_Set rd_mask_;
  // Read events (e.g., input pending, accept pending).

  ACE_Handle_Set wr_mask_;
  // Write events (e.g., flow control abated, non-blocking connection
  // complete).

  ACE_Handle_Set ex_mask_;
  // Exception events (e.g., SIG_URG).
};

#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)

#if defined (ACE_SELECT_REACTOR_HAS_DEADLOCK_DETECTION)
#include "ace/Local_Tokens.h"
typedef ACE_Local_Mutex ACE_SELECT_REACTOR_MUTEX;
#else 
typedef ACE_Token ACE_SELECT_REACTOR_MUTEX;
#endif /* ACE_SELECT_REACTOR_HAS_DEADLOCK_DETECTION */
 
class ACE_Export ACE_Select_Reactor_Token : public ACE_SELECT_REACTOR_MUTEX
  // = TITLE
  //
  //     Used as a synchronization mechanism to coordinate concurrent
  //     access to a Select_Reactor object.
{
public:
  ACE_Select_Reactor_Token (ACE_Select_Reactor &r);
  ACE_Select_Reactor_Token (void);
  virtual ~ACE_Select_Reactor_Token (void);

  virtual void sleep_hook (void);
  // Called just before the ACE_Event_Handler goes to sleep.

  ACE_Select_Reactor &select_reactor (void);
  void select_reactor (ACE_Select_Reactor &);
  // Set/Get methods

  void dump (void) const;
  // Dump the state of an object.

  ACE_ALLOC_HOOK_DECLARE;
  // Declare the dynamic allocation hooks.

private:
  ACE_Select_Reactor *select_reactor_;
};
#else
// If we're non-MT safe then this is just a no-op...
typedef ACE_Null_Mutex ACE_Select_Reactor_Token;
#endif /* ACE_MT_SAFE */

struct ACE_Event_Tuple
  // = TITLE
  //
  //     An ACE_Event_Handler and its associated ACE_HANDLE.
  //
  // = DESCRIPTION
  //
  //     One ACE_Event_Handler is registered for one or more
  //     ACE_HANDLE, in some points this information must be stored
  //     explicitly. This structure provides a lightweight mechanism
  //     to do so.
{
  ACE_Event_Tuple (void);
  ACE_Event_Tuple (ACE_Event_Handler* eh, ACE_HANDLE h);
  
  int operator== (const ACE_Event_Tuple &rhs) const;
  // Equality operator.

  int operator!= (const ACE_Event_Tuple &rhs) const;
  // Inequality operator.

  ACE_HANDLE handle_;
  ACE_Event_Handler* event_handler_;
};

// The following two classes have to be moved out here to keep the SGI
// C++ compiler happy (it doesn't like nested classes).

class ACE_Export ACE_Select_Reactor_Notify : public ACE_Event_Handler
  // = TITLE
  // 
  //     Unblock the <ACE_Select_Reactor> from its event loop.
  //
  // = DESCRIPTION
  //
  //     This implementation is necessary for cases where the
  //     <ACE_Select_Reactor> is run in a multi-threaded program.  In
  //     this case, we need to be able to unblock select() or poll()
  //     when updates occur other than in the main
  //     <ACE_Select_Reactor> thread.  To do this, we signal an
  //     auto-reset event the <ACE_Select_Reactor> is listening on.
  //     If an <ACE_Event_Handler> and <ACE_Select_Reactor_Mask> is
  //     passed to <notify>, the appropriate <handle_*> method is
  //     dispatched in the context of the <ACE_Select_Reactor> thread.
{
public:
  // = Initialization and termination methods.
  int open (ACE_Select_Reactor *);
  int close (void);

  int dispatch_notifications (int &number_of_active_handles,
                              const ACE_Handle_Set &rd_mask);
  // Handles pending threads (if any) that are waiting to unblock the
  // Select_Reactor.

  ssize_t 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 <ACE_Select_Reactor> if currently blocked in
  // select()/poll().  Pass over both the <Event_Handler> *and* the
  // <mask> to allow the caller to dictate which <Event_Handler>
  // method the <Select_Reactor> will invoke.  The <ACE_Time_Value>
  // indicates how long to blocking trying to notify the
  // <Select_Reactor>.  If <timeout> == 0, the caller will block until
  // action is possible, else will wait until the relative time
  // specified in *<timeout> elapses).

  virtual int handle_input (ACE_HANDLE handle);
  // Called back by the Select_Reactor when a thread wants to unblock us.

  void dump (void) const;
  // Dump the state of an object.

  ACE_ALLOC_HOOK_DECLARE;
  // Declare the dynamic allocation hooks.

private:
  ACE_Select_Reactor *select_reactor_;
  // Keep a back pointer to the Select_Reactor.

  ACE_Pipe notification_pipe_;
  // Contains the HANDLE the Select_Reactor is listening on, as well
  // as the HANDLE that threads wanting the attention of the
  // Select_Reactor will write to.
};

class ACE_Export ACE_Select_Reactor_Handler_Repository
  // = TITLE
  //
  //     Used to map <ACE_HANDLE>s onto the appropriate
  //     <ACE_Event_Handler> *. 
  // 
  // = DESCRIPTION
  //
  //     This class is necessary to shield differences between UNIX
  //     and Win32.  In UNIX, <ACE_HANDLE> is an int, whereas in Win32
  //     it's a void *.  This class hides all these details from the
  //     bulk of the <ACE_Select_Reactor> code.  All of these methods
  //     are called with the main <Select_Reactor> token lock held.
{
public:
  friend class ACE_Select_Reactor_Handler_Repository_Iterator;

  // = Initialization and termination methods.
  ACE_Select_Reactor_Handler_Repository (ACE_Select_Reactor &);
  // Default "do-nothing" constructor.
  
  int open (size_t size);
  // Initialize a repository of the appropriate <size>.

  int close (void);
  // Close down the repository.

  // = Search structure operations.

  ACE_Event_Handler *find (ACE_HANDLE handle, size_t *index_p = 0);
  // Return the <ACE_Event_Handler *> associated with <ACE_HANDLE>.
  // If <index_p> is non-0, then return the index location of the
  // <handle>, if found.

  int bind (ACE_HANDLE, 
            ACE_Event_Handler *, 
            ACE_Reactor_Mask);
  // Bind the <ACE_Event_Handler *> to the <ACE_HANDLE> with the
  // appropriate <ACE_Reactor_Mask> settings.

  int unbind (ACE_HANDLE, 
              ACE_Reactor_Mask mask);
  // Remove the binding of <ACE_HANDLE> in accordance with the <mask>.

  int unbind_all (void);
  // Remove all the <ACE_HANDLE, ACE_Event_Handler> tuples.

  // = Sanity checking.

  // Check the <handle> to make sure it's a valid ACE_HANDLE that
  // within the range of legal handles (i.e., >= 0 && < max_size_).
  int invalid_handle (ACE_HANDLE handle);

  // Check the <handle> to make sure it's a valid ACE_HANDLE that
  // within the range of currently registered handles (i.e., >= 0 && <
  // max_handlep1_).
  int handle_in_range (ACE_HANDLE handle);

  // = Accessors.
  size_t size (void);
  // Returns the current table size.

  size_t max_handlep1 (void);
  // Maximum ACE_HANDLE value, plus 1.

  void dump (void) const;
  // Dump the state of an object.

  ACE_ALLOC_HOOK_DECLARE;
  // Declare the dynamic allocation hooks.

private:
  ACE_Select_Reactor &select_reactor_;
  // Reference to our <Select_Reactor>.

  ssize_t max_size_;
  // Maximum number of handles.

  int max_handlep1_;
  // The highest currently active handle, plus 1 (ranges between 0 and
  // <max_size_>.

#if defined (ACE_WIN32)
  // = The mapping from <HANDLES> to <Event_Handlers>.

  ACE_Event_Tuple *event_handlers_;
  // The NT version implements this via a dynamically allocated
  // array of <ACE_Event_Tuple *>.  Since NT implements ACE_HANDLE
  // as a void * we can't directly index into this array.  Therefore,
  // we just do a linear search (for now).  Next, we'll modify
  // things to use hashing or something faster...
#else
  ACE_Event_Handler **event_handlers_;
  // The UNIX version implements this via a dynamically allocated
  // array of <ACE_Event_Handler *> that is indexed directly using
  // the ACE_HANDLE value.
#endif /* ACE_WIN32 */
};

class ACE_Export ACE_Select_Reactor_Handler_Repository_Iterator
  // = TITLE
  //
  //     Iterate through the <ACE_Select_Reactor_Handler_Repository>.
{
public:
  // = Initialization method.
  ACE_Select_Reactor_Handler_Repository_Iterator (const ACE_Select_Reactor_Handler_Repository *s);

  // = Iteration methods.

  int next (ACE_Event_Handler *&next_item);
  // Pass back the <next_item> that hasn't been seen in the Set.
  // Returns 0 when all items have been seen, else 1.

  int done (void) const;
  // Returns 1 when all items have been seen, else 0.

  int advance (void);
  // Move forward by one element in the set.  Returns 0 when all the
  // items in the set have been seen, else 1.

  void dump (void) const;
  // Dump the state of an object.

  ACE_ALLOC_HOOK_DECLARE;
  // Declare the dynamic allocation hooks.

private:
  const ACE_Select_Reactor_Handler_Repository *rep_;
  // Reference to the Handler_Repository we are iterating over.

  ssize_t current_;
  // Pointer to the current iteration level.
};

class ACE_Export ACE_Select_Reactor : public ACE_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 <Select_Reactor> 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:
  enum 
  {
    DEFAULT_SIZE = ACE_DEFAULT_SELECT_REACTOR_SIZE
    // Default size of the Select_Reactor's handle table.
  };

  // = Initialization and termination methods.

  ACE_Select_Reactor (ACE_Sig_Handler * = 0,
                      ACE_Timer_Queue * = 0);
  // Initialize <ACE_Select_Reactor> with the default size.

  ACE_Select_Reactor (size_t size, 
                      int restart = 0, 
                      ACE_Sig_Handler * = 0,
                      ACE_Timer_Queue * = 0);
  // Initialize <ACE_Select_Reactor> with size <size>.

  virtual int open (size_t size = DEFAULT_SIZE, 
                    int restart = 0, 
                    ACE_Sig_Handler * = 0,
                    ACE_Timer_Queue * = 0);
  // Initialize <ACE_Select_Reactor> with size <size>.

  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 (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 <max_wait_time> before
  // returning.  It will return earlier if timer events, I/O events,
  // or signal events occur.  Note that <max_wait_time> can be 0, in
  // which case this method blocks indefinitely until events occur.
  //
  // <max_wait_time> 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,
  // <max_wait_time> 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 <ACE_Event_Handler>s that were
  // dispatched, 0 if the <max_wait_time> elapsed without dispatching
  // any handlers, or -1 if something goes wrong.
  //
  // Current <alertable_handle_events> is identical to
  // <handle_events>.

  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
  // <max_wait_time> value is a reference and can therefore never be
  // NULL.
  //
  // Current <alertable_handle_events> is identical to
  // <handle_events>.

  // = Register and remove <ACE_Event_Handler>s. 
  virtual int register_handler (ACE_Event_Handler *eh,
                                ACE_Reactor_Mask mask);
  // Register a <eh> with a particular <mask>.  Note that the
  // <Select_Reactor> 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 <eh> with a particular <mask>.  Note that since the
  // <handle> 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 <eh> with all the <handles> in the <Handle_Set>.

  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 <new_sh> to handle the signal <signum> using the
  // <new_disp>.  Returns the <old_sh> that was previously registered
  // (if any), along with the <old_disp> 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 <new_sh> to handle a set of signals <sigset> using the
  // <new_disp>.

  virtual int remove_handler (ACE_Event_Handler *eh,
                              ACE_Reactor_Mask mask);
  // Removes the <mask> binding of <eh> from the Select_Reactor.  If
  // there are no more bindings for this <eh> 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 <mask> bind of <Event_Handler> whose handle is
  // <handle> from the Select_Reactor.  If there are no more bindings
  // for this <eh> then it is removed from the Select_Reactor.

  virtual int remove_handler (const ACE_Handle_Set &handle_set,
                              ACE_Reactor_Mask);
  // Removes all the <mask> bindings for handles in the <handle_set>
  // bind of <Event_Handler>.  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 <signum>.
  // <sigkey> 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 <signum> is invalid.

  virtual int remove_handler (const ACE_Sig_Set &sigset);
  // Calls <remove_handler> for every signal in <sigset>.

  // = Suspend and resume Handlers. 

  virtual int suspend_handler (ACE_Event_Handler *eh);
  // Temporarily suspend the <Event_Handler> associated with <eh>.

  virtual int suspend_handler (ACE_HANDLE handle);
  // Temporarily suspend the <Event_Handler> associated with <handle>.

  virtual int suspend_handler (const ACE_Handle_Set &handles);
  // Suspend all <handles> in handle set temporarily. 

  virtual int suspend_handlers (void);
  // Suspend all the <Event_Handlers> in the Select_Reactor.

  virtual int resume_handler (ACE_Event_Handler *eh);
  // Resume a temporarily suspend <Event_Handler> associated with
  // <eh>. 

  virtual int resume_handler (ACE_HANDLE handle);
  // Resume a temporarily suspended <Event_Handler> associated with
  // <handle>.

  virtual int resume_handler (const ACE_Handle_Set &handles);
  // Resume all <handles> in handle set. 

  virtual int resume_handlers (void);
  // Resume all the <Event_Handlers> 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 <event_handler> that will expire after <delta_time>
  // amount of time.  If it expires then <arg> is passed in as the
  // value to the <event_handler>'s <handle_timeout> callback method.
  // If <interval> is != to <ACE_Time_Value::zero> then it is used to
  // reschedule the <event_handler> automatically.  This method
  // returns a <timer_id> that uniquely identifies the <event_handler>
  // in an internal list.  This <timer_id> can be used to cancel an
  // <event_handler> before it expires.  The cancellation ensures that
  // <timer_ids> 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 <timer_id>.

  virtual int cancel_timer (ACE_Event_Handler *event_handler,
                            int dont_call_handle_close = 1);
  // Cancel all <event_handlers> that match the address of
  // <event_handler>.  If <dont_call_handle_close> is 0 then the
  // <handle_close> method of <event_handler> 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 <ACE_Event_Handler> that matches the <timer_id>
  // value (which was returned from the <schedule> method).  If arg is
  // non-NULL then it will be set to point to the ``magic cookie''
  // argument passed in when the <Event_Handler> was registered.  This
  // makes it possible to free up the memory and avoid memory leaks.
  // If <dont_call_handle_close> is 0 then the <handle_close> method
  // of <event_handler> will be invoked.  Returns 1 if cancellation
  // succeeded and 0 if the <timer_id> 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 <eh> and the <mask>.

  virtual int schedule_wakeup (ACE_HANDLE handle,
                               ACE_Reactor_Mask mask);
  // ADD the dispatch MASK "bit" bound with the <handle> and the <mask>.

  virtual int cancel_wakeup (ACE_Event_Handler *eh,
                             ACE_Reactor_Mask mask);
  // CLR the dispatch MASK "bit" bound with the <eh> and the <mask>.

  virtual int cancel_wakeup (ACE_HANDLE handle,
                             ACE_Reactor_Mask mask);
  // CLR the dispatch MASK "bit" bound with the <handle> and the <mask>.

  // = 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 <ACE_Select_Reactor> if currently blocked in
  // select()/poll().  Pass over both the <Event_Handler> *and* the
  // <mask> to allow the caller to dictate which <Event_Handler>
  // method the <Select_Reactor> will invoke.  The <ACE_Time_Value>
  // indicates how long to blocking trying to notify the
  // <Select_Reactor>.  If <timeout> == 0, the caller will block until
  // action is possible, else will wait until the relative time
  // specified in *<timeout> elapses).

  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.

  virtual void max_notify_iterations (int);
  // Set the maximum number of times that the
  // <ACE_Select_Reactor_Notify::handle_input> method will iterate and
  // dispatch the <ACE_Event_Handlers> that are passed in via the
  // notify pipe before breaking out of its <recv> 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
  // <ACE_Select_Reactor_Notify::handle_input> method will iterate and
  // dispatch the <ACE_Event_Handlers> that are passed in via the
  // notify pipe before breaking out of its <recv> loop.

  // = 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 <eh> and
  // <mask>.

  virtual int mask_ops (ACE_HANDLE handle, 
                        ACE_Reactor_Mask mask, 
                        int ops);  
  // GET/SET/ADD/CLR the dispatch MASK "bit" bound with the <handle>
  // and <mask>.

  // = 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 <eh> and <mask>.

  virtual int ready_ops (ACE_HANDLE handle, 
                         ACE_Reactor_Mask, 
                         int ops);
  // GET/SET/ADD/CLR the ready "bit" bound with the <handle> and <mask>.

  virtual void wakeup_all_threads (void);
  // Wake up all threads in waiting in the event loop

  // = Only the owner thread that can perform a <handle_events>.

  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 <handle> is associated with a valid Event_Handler
  // bound to <mask>.  Return the <eh> associated with this <handler>
  // if <eh> != 0.

  virtual int handler (int signum, 
                       ACE_Event_Handler ** = 0);
  // Check to see if <signum> is associated with a valid Event_Handler
  // bound to a signal.  Return the <eh> associated with this
  // <handler> if <eh> != 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 <ACE_Select_Reactor_Token> 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 <ACE_Event_Handlers> are used in
  // multiple threads.

  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 <Select_Reactor>'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 <handle> and <eh> with the
  // <mask>.

  virtual int register_handler_i (const ACE_Handle_Set &handles, 
                                  ACE_Event_Handler *handler, 
                                  ACE_Reactor_Mask mask);
  // Register a set of <handles>.

  virtual int remove_handler_i (ACE_HANDLE handle, 
                                ACE_Reactor_Mask);
  // Do the work of actually unbinding the <handle> and <eh> with the
  // <mask>.

  virtual int remove_handler_i (const ACE_Handle_Set &handles, 
                                ACE_Reactor_Mask);
  // Remove a set of <handles>.

  virtual int suspend_i (ACE_HANDLE handle);
  // Suspend the <Event_Handler> associated with <handle>

  virtual int resume_i (ACE_HANDLE handle);
  // Resume the <Event_Handler> associated with <handle>

  virtual int handler_i (ACE_HANDLE handle, 
                         ACE_Reactor_Mask, 
                         ACE_Event_Handler ** = 0);
  // Implement the public <handler> method.

  virtual int handler_i (int signum, ACE_Event_Handler ** = 0);
  // Implement the public <handler> method.

  virtual int any_ready (ACE_Select_Reactor_Handle_Set &handle_set);
  // Check if there are any HANDLEs enabled in the <ready_set_>, and
  // if so, update the <handle_set> 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 bit_ops (ACE_HANDLE handle, 
                       ACE_Reactor_Mask mask, 
                       ACE_Select_Reactor_Handle_Set &wait_Set,
                       int ops);
  // Allow manipulation of the <wait_set_> mask and <ready_set_> mask.

  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 <ACE_Event_Handler>s for time
  // events, I/O events, and signal events.  Returns the total number
  // of <ACE_Event_Handler>s that were dispatched or -1 if something
  // goes wrong.

  virtual int dispatch_timer_handlers (void);
  // Dispatch any expired timer handlers.  Returns -1 if the state of
  // the <wait_set_> has changed, else returns number of timer
  // handlers dispatched.

  virtual int dispatch_notification_handlers (int &number_of_active_handles,
                                              ACE_Select_Reactor_Handle_Set &dispatch_set);
  // Dispatch any notification handlers.  Returns -1 if the state of
  // the <wait_set_> has changed, else returns number of handlers
  // notified.

  virtual int dispatch_io_handlers (int &number_of_active_handles,
                                    ACE_Select_Reactor_Handle_Set &dispatch_set);
  // Dispatch all the input/output/except handlers that are enabled in
  // the <dispatch_set>.  Returns -1 if the state of the <wait_set_>
  // has changed, else returns number of handlers dispatched.

  virtual int dispatch_io_set (int number_of_active_handles,
			       int& number_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 number of handles already dispatched and
  // invokes this->notify_handle for all the handles in <dispatch_set>
  // using the <mask>, <ready_set> and <callback> 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 <callback> in the context of the <eh>
  // associated with <handle> that a particular event has occurred.

  ACE_Select_Reactor_Handler_Repository handler_rep_;
  // Table that maps <ACE_HANDLEs> to <ACE_Event_Handler *>'s.

  ACE_Timer_Queue *timer_queue_; 
  // Defined as a pointer to allow overriding by derived classes...

  int delete_timer_queue_;
  // Keeps track of whether we should delete the timer queue (if we
  // didn't create it, then we don't delete it).

  ACE_Sig_Handler *signal_handler_;
  // Handle signals without requiring global/static variables. 

  int delete_signal_handler_;
  // Keeps track of whether we should delete the signal handler (if we
  // didn't create it, then we don't delete it).

  ACE_Select_Reactor_Handle_Set wait_set_;
  // Tracks handles that are waited for by select().

  ACE_Select_Reactor_Handle_Set suspend_set_;
  // Tracks handles that are currently suspended.

  ACE_Select_Reactor_Handle_Set ready_set_;
  // Track HANDLES we are interested in for various events that must
  // be dispatched *without* going through select().

  int restart_; 
  // Restart automatically when interrupted 

  int requeue_position_;
  // Position that the main ACE_Select_Reactor thread is requeued in
  // the list of waiters during a notify() callback.  If this value ==
  // -1 we are requeued at the end of the list.  Else if it's 0 then
  // we are requeued at the front of the list.  Else if it's > 1 then
  // that indicates the number of waiters to skip over.

  int max_notify_iterations_;
  // Keeps track of the maximum number of times that the
  // <ACE_Select_Reactor_Notify::handle_input> method will iterate and
  // dispatch the <ACE_Event_Handlers> that are passed in via the
  // notify pipe before breaking out of its <recv> loop.  By default,
  // this is set to -1, which means "iterate until the pipe is empty."

  int initialized_;
  // True if we've been initialized yet...

  ACE_thread_t owner_;
  // The original thread that created this Select_Reactor.

  int state_changed_;
  // True if state has changed during dispatching of
  // <ACE_Event_Handlers>, else false.  This is used to determine
  // whether we need to make another trip through the <Select_Reactor>'s
  // <wait_for_multiple_events> loop.

  ACE_Select_Reactor_Token token_;
  // Synchronization token for the MT_SAFE ACE_Select_Reactor.

  ACE_Lock_Adapter<ACE_Select_Reactor_Token> lock_adapter_;
  // Adapter used to return internal lock to outside world.

  ACE_Select_Reactor_Notify notify_handler_;
  // Callback object that unblocks the ACE_Select_Reactor if it's sleeping.

  void renew (void);
  // Enqueue ourselves into the list of waiting threads at the
  // appropriate point specified by <requeue_position_>.  

  friend class ACE_Select_Reactor_Notify;
  friend class ACE_Select_Reactor_Handler_Repository;

private:
  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

  ACE_UNIMPLEMENTED_FUNC (ACE_Select_Reactor (const ACE_Select_Reactor &));
  ACE_UNIMPLEMENTED_FUNC (ACE_Select_Reactor &operator = (const ACE_Select_Reactor &));
  // Deny access since member-wise won't work...
};

#if defined (__ACE_INLINE__)
#include "ace/Select_Reactor.i"
#endif /* __ACE_INLINE__ */

#endif /* ACE_SELECT_REACTOR_H */