//-----------------------------------------------------------------------------
// Copyright (c) 1994,1995 Southeastern Universities Research Association,
//                         Continuous Electron Beam Accelerator Facility
//
// This software was developed under a United States Government license
// described in the NOTICE file included as part of this distribution.
//
//-----------------------------------------------------------------------------
//
// Description:
//      cdevGroup: handle multiple asynchronous operations
//
// Author:  Jie Chen
//
// Revision History:
//   cdevGroup.h,v
// Revision 1.5  1997/03/03  17:36:05  chen
// add buffering to channel access connection
//
// Revision 1.4  1995/12/08  15:35:37  chen
// handle deferred mode
//
// Revision 1.3  1995/07/05  18:42:44  chen
// change status interface
//
// Revision 1.2  1995/06/30  16:03:36  chen
// use generic list
//
// Revision 1.1.1.1  1995/06/16  17:14:07  epics
// initial import of cdev
//
//
#ifndef _CDEV_GROUP_H
#define _CDEV_GROUP_H

#include <cdevSpec.h>
#include <cdevSync.h>
#include <cdevSystem.h>
#include <cdevTranObj.h>
#include <cdevExecObj.h>
#include <cdevCallback.h>
#include <cdevSlist.h>

#include "cdevBlockList.h"

#define CDEV_EXEC_IMMEDIATE 0
#define CDEV_EXEC_DEFERRED  1


class CDEV_CLASS_SPEC cdevGroup: public cdevSync
{
public:
  // constructors and destructor
  cdevGroup (unsigned int blockSize = DEFAULT_BLOCK_SIZE,
	     cdevSystem& system = cdevSystem::defaultSystem());
  virtual ~cdevGroup (void);

  virtual int start (void);
  // PURPOSE: start this group. (see next)
  // REQUIRE: nothing
  // PROMISE: group stared, return CDEV_SUCCESS

  virtual int end   (void);
  // PURPOSE: end this group, all async IO between 
  //          start and end will be in the group
  // REQUIRE: nothing
  // PROMISE: group ended, return CDEV_SUCCESS

  virtual int flush (void);
  // PURPOSE: flush all network requests inside this group
  // REQUIRE: nothing
  // PROMISE: all network requests of this group will be sent out
  //          return CDEV_SUCCESS

  virtual int poll  (void);
  // PURPOSE: polling all outstanding IO events of this group
  // REQUIRE: nothing
  // PROMISE: return CDEV_SUCCESS

  virtual int pend  (int fd = -1);
  // PURPOSE: do network pending for IO events forever until all
  //          network requests of this group have come back
  // REQUIRE: nothing
  // PROMISE: all come back or block forever (return CDEV_SUCCESS)

  virtual int pend  (double seconds, int fd = -1);
  // PURPOSE: do network pending for IO events for upto 'seconds' long or
  //          all network requests of this group have come back
  // REQUIRE: nothing
  // PROMISE: return CDEV_SUCCESS: finished, return CDEV_TIMEOUT: timeout

  int         allFinished (void);
  // PURPOSE: check all transaction finished of this group
  // REQUIRE: after pend call
  // PROMISE: return 1: all finished, 0: not yet

  int         status (int status[], int &numTransactions);
  // PURPOSE: check status of all transactions
  // REQURIE: transaction status will be in the integer array returned
  //          by this call. Element of the array = 0 finished. 
  //          Callers provide integer array buffer with buffer size
  // PROMISE: return CDEV_SUCCESS on success and numTransaction will be
  //          real number of trasanctions. return CDEV_INVALIDARG
  //          when the integer buffer is not big enough.

  void        execDeferred  (void);
  void        execImmediate (void);
  // PURPOSE: change behaviour of execution of command inside the group
  //          execDeferred will buffer all commands until pend or poll or
  //          flush is called
  //          execImmediate will flush commands to underlying services 
  //          immediately
  // REQUIRE: none
  // PROMISE: execution mode changed

  int         executionMode (void) const;
  // PURPOSE: return execution mode
  // REQUIRE: none
  // PROMISE: CDEV_EXEC_DEFERRED or CDEV_EXEC_IMMEDIATE

  int         readyToExec (void) const;
  // PURPOSE: for deferred mode group only. Return execution stage.
  // REQUIRE: none
  // PROMISE: 0: the deferred group is still in the buffered stage
  //          1: the deferred group is ready to flush all buffered
  //          commands

  virtual const char *className (void) const {return "cdevGroup";}

protected:
  // all add and remove operation on the transaction object
  cdevTranObj **addTranObj (cdevTranObj* obj);
  // clean out all transaction objects
  void cleanAll (void);
  // get all services associaed with transaction objects
  // only used when one about to call IO operations
  void getServices (void);
  // find out which service is ready
  cdevService *pendingService (int handle);
  // handle events inherited from cdevSync
  virtual int  handleEvents  (cdevTimeValue *tv);
  // notify one partucular service
  virtual void notifyService (int fd);
  // quick polling underlying services
  virtual void qpoll         (void);

  // setup file read mask
  void    setupFdMask (void);

  // add execution object to the list
  cdevExecObj **addExecObj (cdevExecObj* eobj);
  // cleanout all execution objects
  void cleanAllEobjs (void);
  // send out all buffered commands
  int execAllCommands (void);
  
protected:
  // data member
  // transaction object list
  cdevBlockList objList_;
  // order dependent, careful!!!
  cdevBlockListIterator ite_;
  // execution object list
  cdevBlockList eobjList_;
  // order dependent, careful!!!
  cdevBlockListIterator eite_;
  // service list associcated with this group
  cdevSlist serviceList_;
  cdevSystem &system_;
  // flag to tell whether one unregister itself from the system
  int unregOn_;
  // flag to see whether this group is created successfully
  int errBit_;
  // flag to see whether transaction object should remove itself
  // from the object list
  int remXobj_;
  // flag to lock the execution object list
  int remEobj_;
  // how many transaction objects are in this group
  int hwMark_;
  // group active flag
  int active_;
  // operation mode of group
  int mode_;
  // number of execution objects
  int numEobjs_;
  // stage of deferred execution: buffer mode or execution mode
  // 0: buffer stage, 1: execution stage
  int execStage_;

  // deny access of copy and assignment since the group is a manager
  cdevGroup (const cdevGroup& );
  cdevGroup& operator = (const cdevGroup&);

  // friend class
  friend class cdevSystem;
  friend class cdevTranObj;
  friend class cdevExecObj;
};
#endif

