/*
 * Copyright (c) 1987, 1988, 1989, 1990, 1991 Stanford University
 * Copyright (c) 1991 Silicon Graphics, Inc.
 *
 * Permission to use, copy, modify, distribute, and sell this software and 
 * its documentation for any purpose is hereby granted without fee, provided
 * that (i) the above copyright notices and this permission notice appear in
 * all copies of the software and related documentation, and (ii) the names of
 * Stanford and Silicon Graphics may not be used in any advertising or
 * publicity relating to the software without the specific, prior written
 * permission of Stanford and Silicon Graphics.
 * 
 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
 *
 * IN NO EVENT SHALL STANFORD OR SILICON GRAPHICS BE LIABLE FOR
 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
 * OF THIS SOFTWARE.
 */

/*
 * Wait on multiple file descriptors until a condition occurs.
 */

// 
// <file> 
// 
// Name:        dispatcher.h
// 
// Purpose:     
// 
// Created:     
// 
// Modified:    2 Nov 95   Joerg Faschingbauer
// 
// Description: 
// 
// $Id: dispatcher.h,v 1.5 1997/02/13 12:39:34 gorasche Exp $
//
// $Log: dispatcher.h,v $
// Revision 1.5  1997/02/13 12:39:34  gorasche
// change for DLL support
//
// Revision 1.4  1997/01/24 14:18:36  jfasch
// link time assertion
//
// Revision 1.3  1997/01/24 14:09:38  gorasche
// changes for WIN32
//
// Revision 1.2  1996/05/03 11:41:34  jfasch
// added method children() to retrieve the registered child processes and
// their handlers
//
// 
// </file> 


#ifndef dp_dispatcher_h
#define dp_dispatcher_h

#include "libdispatch.h"

#include <hyperg/utils/types.h>
#include <hyperg/utils/hgunistd.h>

#include <sys/types.h>

#include "enter-scope.h"

#ifndef WIN32
class ChildLookup ;
#endif
class ChildHandler ;
class FdMask;
class IOHandler;
class TimerQueue;
struct timeval;
#ifdef WIN32
class SockList;
#endif

class Dispatcher {
public:
   enum DispatcherMask {
     ReadMask,
     WriteMask,
     ExceptMask
   } ;

   Dispatcher();
   virtual ~Dispatcher();

   virtual void link(int fd, DispatcherMask, IOHandler*);
   virtual IOHandler* handler(int fd, DispatcherMask) const;
   virtual void unlink(int fd);
   virtual void unlink(int fd, DispatcherMask);

   virtual void startTimer(long sec, long usec, IOHandler*);
   virtual void stopTimer(IOHandler*);

   virtual boolean setReady(int fd, DispatcherMask);
   virtual void dispatch();
   virtual boolean dispatch(long& sec, long& usec);

   virtual void setActive (const FdMask& ,const FdMask& ,const FdMask&);
   virtual void resetActive() ;

#ifdef WIN32
   int m_iDropoutPort;
   void dropOut();
#else
   void registerChild (pid_t, ChildHandler*) ;
   void unregisterChild (pid_t) ;
   void childSignal() ; // a 'signal handler' which is called *asyncronously*
   const ChildLookup& children() const { return *child_handlers_; }
   void dropOut() { dropout_ = true; }
#endif

   static Dispatcher& instance();
   static void instance(Dispatcher*);

protected:
   virtual void attach(int fd, DispatcherMask, IOHandler*);
   virtual void detach(int fd);
   virtual void detach(int fd, DispatcherMask);
   virtual boolean dispatch(timeval*);
   virtual boolean anyReady() const;
   virtual int fillInReady(FdMask&, FdMask&, FdMask&);
   virtual int waitFor(FdMask&, FdMask&, FdMask&, timeval*) ;
   virtual void notify(int, FdMask&, FdMask&, FdMask&) ;
   virtual timeval* calculateTimeout(timeval*) const;
   virtual void handleError();
   virtual void checkConnections();
   virtual void waitForChild() ;

protected:
   int	_nfds;
   FdMask* _rmask;
   FdMask* _wmask;
   FdMask* _emask;
   FdMask* _rmaskready;
   FdMask* _wmaskready;
   FdMask* _emaskready;

   // jschipf, jfasch 11 Sep 1995
   boolean saved_;
   FdMask* rsaved_;
   FdMask* wsaved_;
   FdMask* esaved_;
   FdMask* rrsaved_;
   FdMask* wrsaved_;
   FdMask* ersaved_;
#ifdef WIN32
   SockList* _rtable;
   SockList* _wtable;
   SockList* _etable;
   boolean bItemsChanged_;
#else
   IOHandler** _rtable;
   IOHandler** _wtable;
   IOHandler** _etable;
#endif
   TimerQueue* _queue;

   // flag to be set for instance in signal handlers if I should quit
   // the select loop
   boolean dropout_ ;

#ifndef WIN32
   // the registered child handlers
   ChildLookup* child_handlers_ ;
#endif

   // flag set asyncronously on a child signal (childSignal())
   boolean child_signal_ ;

private:
   long _openMax;		/* max open files per process  */
#ifdef WIN32
  // fd and port no of the dropout socket
  int m_iDropoutSock;
  // this is dynamic thread local data (only valid when not within a DLL!!)
#  ifdef DLL
  static Dispatcher* _instance;
#  else
  THREADSTATIC Dispatcher* _instance;
#  endif /* DLL */
#else
  static Dispatcher* _instance;
#endif

private:
   /* deny access since member-wise won't work */
   Dispatcher(const Dispatcher&) {};
   Dispatcher& operator =(const Dispatcher&) { return *this; }
public:
   static const char* version1 ;
};
static const char* Dispatcher_version = Dispatcher::version1 ;

#endif
