/************************************************************************/
/* Copyright 1998 MBARI							*/
/************************************************************************/
#ifndef _APERIODICHANDLER_H
#define _APERIODICHANDLER_H
static char AperiodicHandler_h_id[] = "$Header: /u/oreilly/rov/tmacs/RCS/AperiodicHandler.h,v 1.7 1998/12/18 21:07:21 oreilly Exp $";

/*
$Log: AperiodicHandler.h,v $
Revision 1.7  1998/12/18 21:07:21  oreilly
Added documentation

Revision 1.6  1997/10/03 09:38:22  oreilly
*** empty log message ***

 * Revision 1.5  97/03/20  12:32:48  12:32:48  oreilly (Thomas C. O'Reilly)
 * *** empty log message ***
 * 
 * Revision 1.4  96/10/28  09:13:22  09:13:22  oreilly (Thomas C. O'Reilly)
 * *** empty log message ***
 * 
 * Revision 1.3  96/10/18  14:15:38  14:15:38  oreilly (Thomas C. O'Reilly)
 * Using workprocs to read input pipe
 * 
*/

#include <unistd.h>
#include "SList.h"
#include "DmMonitor.h"
#include "DmGuiObject.h"
#include "RegisteredItem.h"

#define NoInput MAXLONG

class AperiodicHandler;

/*
CLASS 
RegisteredItem

DESCRIPTION
RegisteredDmItem describes a DM item registered with AperiodicHandler

AUTHOR
Tom O'Reilly
*/
class RegisteredDmItem : public RegisteredItem
{
  friend class AperiodicHandler;

  public:
  RegisteredDmItem(const char *name, DM_Item handle);

  ~RegisteredDmItem()
  {
    free(_itemName);
  }

  ///////////////////////////////////////////////////////////////////
  // Terminate child process, remove semaphore
  int cleanup();
  
  private:  

  char *_itemName;
  DM_Item _handle;
};


class DmGuiApp;

/*
CLASS 
AperiodicHandler

DESCRIPTION
Maintains a list of "registered" DM_Items to be consumed aperiodically. 
For each registered DM_Item, there is a list of DmGuiObjects which contain it. 
When data becomes available for a registered DM_Item, AperiodicHandler
calls DmGuiObject::updateGui() for the associated DmGuiObject(s). 

AperiodicHandler collaborates closely with DmMonitor which is created in the
separate "dmonitor" process. Interprocess communication is via semaphore 
and pipes. 

AUTHOR
Tom O'Reilly
*/
class AperiodicHandler
{
  friend class DmGuiApp;
  
  public:
  AperiodicHandler();
  ~AperiodicHandler();
  
  ///////////////////////////////////////////////////////////////////
  // Register DM item and associated GUI(s)
  registerObj(DmGuiObject *guiObj);
  
  ///////////////////////////////////////////////////////////////////
  // Unregister DM item
  unregisterObj(DmGuiObject *);

  ///////////////////////////////////////////////////////////////////
  // Start handler
  void start();
  
  protected:

  SList<RegisteredDmItem *> _dmItemList;

  XtInputId _inputId;

  ///////////////////////////////////////////////////////////////////
  // File descriptor for writing requests to DM Monitor process
  int _writePipe;

  ///////////////////////////////////////////////////////////////////
  // File descriptor for receiving data notification from DM Monitor process
  int _readPipe;

  ///////////////////////////////////////////////////////////////////
  // Pid of monitor process
  pid_t _monitorPid;
  
  ///////////////////////////////////////////////////////////////////
  // ID of monitor semaphore
  SEM_ID _monitorSem;

  ///////////////////////////////////////////////////////////////////
  // Process notification messages in pipe
  Boolean processNewData();

  ///////////////////////////////////////////////////////////////////
  // Get pointer to DmGuiApp
  static DmGuiApp *getDmGuiApp(); 

  ///////////////////////////////////////////////////////////////////
  // Write request to monitor process
  int writeRequest(RequestMessage *request);

  ///////////////////////////////////////////////////////////////////
  // Clean up child process and IPC stuff
  int cleanup();
  
  private:
  
  ///////////////////////////////////////////////////////////////////
  // dataReadyCallback() is called data is ready for a DM consumer
  static void dataReadyCallback(XtPointer clientData, int *fid, 
				XtInputId *id);
  
  static Boolean newDataWorkProc(XtPointer clientData);
};


#endif
