//-----------------------------------------------------------------------------
// 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:
//      cdevExecGroup: handle buffering mechanism for multiple
//                     executions
//                     
//                     For service layer only
//
// Author:  Jie Chen
//
// Revision History:
//   cdevExecGroup.h,v
// Revision 1.1  1997/03/03  17:36:00  chen
// add buffering to channel access connection
//
//
//
#ifndef _CDEV_EXEC_GROUP_H
#define _CDEV_EXEC_GROUP_H

#include <cdevGroup.h>

class cdevExecObj;

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

  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 const char *className (void) const {return "cdevExecGroup";}

protected:

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

  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

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

  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)

  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

  // get underlying service
  void        getServices (void);

  // send out all buffered commands
  int execAllCommands (void);

  // find out which service is ready
  cdevService *pendingService (int handle);
  // handle events inherited from cdevSync
  int  handleEvents  (cdevTimeValue *tv);
  // notify one partucular service
  void notifyService (int fd);

private:
  // data member
  // deny access of copy and assignment since the group is a manager
  cdevExecGroup (const cdevExecGroup& );
  cdevExecGroup& operator = (const cdevExecGroup&);

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

