//-----------------------------------------------------------------------------
// 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 class implementation
//
// Author:  Jie Chen
//
// Revision History:
//   cdevExecGroup.cc,v
// Revision 1.2  1997/04/02  17:54:05  akers
// Ongoing Development of CDEV 1.6
//
// Revision 1.1  1997/03/03  17:35:59  chen
// add buffering to channel access connection
//
//
//
#include <cdevClock.h>
#include <cdevErrCode.h>
#include <cdevRequestObject.h>
#include "cdevExecGroup.h"

cdevExecGroup::cdevExecGroup (cdevService* service,
			      unsigned int blockSize, cdevSystem &system)
:cdevGroup (blockSize, system)
{
#ifdef _TRACE_OBJECTS
  printf("    Create cdevExecGroup class\n");
#endif
  // remove this group from the system
  // this group will no visible from system
  unregOn_ = 0;
  if (!errBit_)
    system.removeGroup (this);
  errBit_ = 0;

  // mode is always in the deferred mode
  mode_ = CDEV_EXEC_DEFERRED;

  // add this service to the list
  serviceList_.add (service);
}

cdevExecGroup::~cdevExecGroup (void)
{
#ifdef _TRACE_OBJECTS
  printf("    Destroy cdevExecGroup class\n");
#endif  
  // empty
}

int
cdevExecGroup::start (void)
{
  return CDEV_SUCCESS;
}

int
cdevExecGroup::end (void)
{
  return CDEV_SUCCESS;
}

int
cdevExecGroup::flush (void)
{
  // must send out commands before closing the group
  if (mode_ == CDEV_EXEC_DEFERRED) {
    ite_.init ();
    execAllCommands ();
  }

  if (hwMark_) {
    getServices ();
    cdevSlistIterator sit(serviceList_);
    cdevService *tsvc = 0;
    for (sit.init(); !sit; ++sit){
      tsvc = (cdevService *)sit ();
      tsvc->flush();
    }
  }
  return CDEV_SUCCESS;
}

int
cdevExecGroup::poll (void)
{
  return CDEV_SUCCESS;
}

int
cdevExecGroup::pend (int /* fd */)
{
  return CDEV_SUCCESS;
}

int
cdevExecGroup::pend (double /* seconds */, int /* fd */)
{
  return CDEV_SUCCESS;
}

int
cdevExecGroup::handleEvents (cdevTimeValue * /* tv */)
{
  return CDEV_SUCCESS;
}

void 
cdevExecGroup::notifyService (int /* handle */)
{
  // empty
}

cdevService *
cdevExecGroup::pendingService (int /* handle */)
{
  return 0;
}

int
cdevExecGroup::allFinished (void)
{
  return 1;
}

int
cdevExecGroup::status (int /* status */[], int & /* numTransactions */)
{
  return CDEV_SUCCESS;
}

void
cdevExecGroup::getServices (void)
{
  // empty
}


void
cdevExecGroup::execDeferred (void)
{
  mode_ = CDEV_EXEC_DEFERRED;
}

void
cdevExecGroup::execImmediate (void)
{
  mode_ = CDEV_EXEC_IMMEDIATE;
}

int
cdevExecGroup::executionMode (void) const
{
  return mode_;
}

int
cdevExecGroup::execAllCommands (void)
{
  int status= CDEV_SUCCESS;
  int ist;

  // change execution stage to execution
  execStage_ = 1;
  // lock the list
  remEobj_ = 0;

  cdevExecObj *obj = 0;
  int i = 0;
  for (eite_.init (); i < numEobjs_ && !eite_; ++eite_) {
    obj = (cdevExecObj *) eite_ ();
    cdevRequestObject *reqobj = obj->reqObj_;
    if (obj->userCallback_ != 0) {
      if ((ist = reqobj->execCallback (obj->outData_, *(obj->userCallback_),
				       obj->arg_)) != CDEV_SUCCESS)
	status = ist;
    }
    else {
      if ((ist= reqobj->execNoBlock (obj->outData_, obj->resultData_,
				     obj->arg_)) != CDEV_SUCCESS)
	status = ist;
    }
    // delete execution obejct
    delete obj;
    i++;
  }

  remEobj_ = 1;
  numEobjs_ = 0;

  // turn the execution stage to buffering stage again
  execStage_ = 0;

  return status;
}

int
cdevExecGroup::readyToExec (void) const
{
  return execStage_;
}
