//-----------------------------------------------------------------------------
// 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:
//      cdevDevice: a virtual control device
//
// Author:  Jie Chen & Chip Watson
//
// Revision History:
//   cdevDevice.h,v
// Revision 1.4  1996/11/21  17:03:13  akers
// Ongoing Developement of CDEV 1.5
//
// Revision 1.3  1995/07/05  18:39:43  chen
// change interface
//
// Revision 1.2  1995/06/30  15:59:27  chen
// remove all unnecessary files
//
// Revision 1.1.1.1  1995/06/16  17:14:06  epics
// initial import of cdev
//
//
#ifndef _CDEV_DEVICE_H
#define _CDEV_DEVICE_H

#include <cdevSpec.h>
#include <cdevSlist.h>
#include <cdevSystem.h>
#include <cdevData.h>
#include <cdevCallback.h>
#include <cdevIOcontext.h>

class cdevRequestObject;

class CDEV_CLASS_SPEC cdevDevice: public cdevIOcontext
{
 public:
  //===================================================================
  //     Public Interface for Clients
  //===================================================================
  static cdevDevice& attachRef (char *name);
  static cdevDevice* attachPtr (char *name);
  // PURPOSE: create a reference or pointer for device of a given name
  //          within the default system
  // REQUIRE: name != 0
  // PROMISE: a cdevDevice 

  static void detach (cdevDevice& dev);
  static void detach (cdevDevice* dev);
  // PURPOSE: destroy a cdevDevice
  // REQUIRE: dev != 0
  // PROMISE: memory will be freed if no more attachment on this device

  const char *name (void) const;
  // PURPOSE: return device name
  // REQUIRE: nothing
  // PROMISE: a name

  cdevSystem& system (void) const;
  // PURPOSE: return system associated with this device
  // REQUIRE: nothing
  // PROMISE: return reference of the system

  virtual int send (char *msg, cdevData &out, cdevData& result);
  virtual int send (char *msg, cdevData *out, cdevData& result);
  virtual int send (char *msg, cdevData &out, cdevData* result);
  virtual int send (char *msg, cdevData *out, cdevData* result);
  // PURPOSE: synchronous IO operations
  // REQUIRE: when set, provide out, when get, provide result
  // PROMISE: return CDEV_SUCCESS: success. Check cdevErrCode.h for error info

  virtual int sendNoBlock (char *msg, cdevData &out, cdevData &result);
  virtual int sendNoBlock (char *msg, cdevData *out, cdevData &result);
  virtual int sendNoBlock (char *msg, cdevData &out, cdevData *result);
  virtual int sendNoBlock (char *msg, cdevData *out, cdevData *result);
  // PURPOSE: asynchronous IO operations
  // REQUIRE: same as the above and one may use cdevGroup to group these
  // PROMISE: return CDEV_SUCCESS: success. Check cdevErrCode.h for error info

  virtual int sendCallback (char *msg, cdevData &out, cdevCallback &callback);
  virtual int sendCallback (char *msg, cdevData *out, cdevCallback &callback);
  // PURPOSE: asynchronous IO operations with user supplied callback function
  // REQUIRE: out != 0
  // PROMISE: return CDEV_SUCCESS: request sendout success.
  //          check cdevErrCode.h for error info

  // setIOcontext function, pass cxt to requestObject int the list
  virtual int setContext (cdevData& cxt);
  // PURPOSE: set context to this device
  // REQUIRE: nothing
  // PROMISE: always return 0, set constext to all request objects
  //          in this device

  //========================================================================
  //     Public Interface for cdevRequestObject
  //========================================================================
  virtual cdevRequestObject* getRequestObject (char *msg);
  // PURPOSE: get a requestObject based on  message 'msg'
  // REQUIRE: msg != 0
  // PROMISE: return a pointer to requestObject

  virtual int getRequestObject (char *msg, cdevRequestObject* &reqobj);
  // PURPOSE: get right requestObject
  // REQUIRE: msg != 0, callers provide pointer only.
  // PROMISE: always return CDEV_SUCCESS. reqobj may be an errorRequestObject

  virtual int registerReqObject (cdevRequestObject *obj);
  // PURPOSE: register a requestObject into this device
  // REQUIRE: obj != 0
  // PROMISE: return CDEV_SUCCESS: success, CDEV_ERROR: already here

  virtual int removeReqObject (cdevRequestObject *obj);
  // PURPOSE: remove a requestObject from the device
  // REQUIRE: obj != 0
  // PROMISE: return CDEV_SUCCESS: success, CDEV_ERROR: not here

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

 protected:
  //constructors and destructor
  cdevDevice (char *name, cdevSystem& system = cdevSystem::defaultSystem() );
  virtual ~cdevDevice (void);

  // attach pointer or reference with system as second argument
  // protected to prevent application from using multiple systems
  static cdevDevice& attachRef (char *name, cdevSystem& system);
  static cdevDevice* attachPtr (char *name, cdevSystem& system);
  // PURPOSE: create a reference or pointer for device of a given name
  // REQUIRE: name != 0
  // PROMISE: a cdevDevice 

  cdevRequestObject* findRequestObject(char *msg);
  // PURPOSE: find an existing requestObject
  // REQUIRE: name != 0, callers provide pointer only.
  // PROMISE: return valid request object or NULL if not found

  // Protected data items
  char *deviceName_;
  cdevSystem& system_;
  cdevSlist reqObjList_;
  int unregOn_;              // unregister self from system on delete
  int refCount_;

 private:
  // hide assignment and copy operator since the device is
  // a memory manager for requestObject
  cdevDevice& operator = (const cdevDevice &);
  cdevDevice (const cdevDevice &);

  // friend class declaration
  friend class cdevSystem;
  friend class cdevRequestObject;
};
#endif
