Files
epics-base/src/cas/generic/casdef.h
T
2000-10-13 01:22:49 +00:00

1004 lines
33 KiB
C++

//
// $Id$
//
// Author: Jeffrey O. Hill
// johill@lanl.gov
// (505) 665 1831
// Date: 1-95
//
// Experimental Physics and Industrial Control System (EPICS)
//
// Copyright 1991, the Regents of the University of California,
// and the University of Chicago Board of Governors.
//
// This software was produced under U.S. Government contracts:
// (W-7405-ENG-36) at the Los Alamos National Laboratory,
// and (W-31-109-ENG-38) at Argonne National Laboratory.
//
// Initial development by:
// The Controls and Automation Group (AT-8)
// Ground Test Accelerator
// Accelerator Technology Division
// Los Alamos National Laboratory
//
// Co-developed with
// The Controls and Computing Group
// Accelerator Systems Division
// Advanced Photon Source
// Argonne National Laboratory
//
//
#ifndef includecasdefh
#define includecasdefh
//
// EPICS
//
#include "alarm.h" // EPICS alarm severity/condition
#include "errMdef.h" // EPICS error codes
#include "gdd.h" // EPICS data descriptors
#include "shareLib.h" // EPICS compiler specific sharable lib keywords
typedef aitUint32 caStatus;
/*
* ===========================================================
* for internal use by the server library
* (and potentially returned to the server tool)
* ===========================================================
*/
#define S_cas_success 0
#define S_cas_internal (M_cas| 1) /*Internal failure*/
#define S_cas_noMemory (M_cas| 2) /*Memory allocation failed*/
#define S_cas_bindFail (M_cas| 3) /*Attempt to set server's IP address/port failed*/
#define S_cas_hugeRequest (M_cas | 4) /*Requested op does not fit*/
#define S_cas_sendBlocked (M_cas | 5) /*Blocked for send q space*/
#define S_cas_badElementCount (M_cas | 6) /*Bad element count*/
#define S_cas_noConvert (M_cas | 7) /*No conversion between src & dest types*/
#define S_cas_badWriteType (M_cas | 8) /*Src type inappropriate for write*/
#define S_cas_noContext (M_cas | 11) /*Context parameter is required*/
#define S_cas_disconnect (M_cas | 12) /*Lost connection to server*/
#define S_cas_recvBlocked (M_cas | 13) /*Recv blocked*/
#define S_cas_badType (M_cas | 14) /*Bad data type*/
#define S_cas_timerDoesNotExist (M_cas | 15) /*Timer does not exist*/
#define S_cas_badEventType (M_cas | 16) /*Bad event type*/
#define S_cas_badResourceId (M_cas | 17) /*Bad resource identifier*/
#define S_cas_chanCreateFailed (M_cas | 18) /*Unable to create channel*/
#define S_cas_noRead (M_cas | 19) /*read access denied*/
#define S_cas_noWrite (M_cas | 20) /*write access denied*/
#define S_cas_noEventsSelected (M_cas | 21) /*no events selected*/
#define S_cas_noFD (M_cas | 22) /*no file descriptors available*/
#define S_cas_badProtocol (M_cas | 23) /*protocol from client was invalid*/
#define S_cas_redundantPost (M_cas | 24) /*redundundant io completion post*/
#define S_cas_badPVName (M_cas | 25) /*bad PV name from server tool*/
#define S_cas_badParameter (M_cas | 26) /*bad parameter from server tool*/
#define S_cas_validRequest (M_cas | 27) /*valid request*/
#define S_cas_tooManyEvents (M_cas | 28) /*maximum simult event types exceeded*/
#define S_cas_noInterface (M_cas | 29) /*server isnt attached to a network*/
#define S_cas_badBounds (M_cas | 30) /*server tool changed bounds on request*/
#define S_cas_pvAlreadyAttached (M_cas | 31) /*PV attached to another server*/
#define S_cas_badRequest (M_cas | 32) /*client's request was invalid*/
#define S_cas_invalidAsynchIO (M_cas | 33) /*inappropriate asynchronous IO type*/
/*
* ===========================================================
* returned by the application (to the server library)
* ===========================================================
*/
#define S_casApp_success 0
#define S_casApp_noMemory (M_casApp | 1) /*Memory allocation failed*/
#define S_casApp_pvNotFound (M_casApp | 2) /*PV not found*/
#define S_casApp_badPVId (M_casApp | 3) /*Unknown PV identifier*/
#define S_casApp_noSupport (M_casApp | 4) /*No application support for op*/
#define S_casApp_asyncCompletion (M_casApp | 5) /*will complete asynchronously*/
#define S_casApp_badDimension (M_casApp | 6) /*bad matrix size in request*/
#define S_casApp_canceledAsyncIO (M_casApp | 7) /*asynchronous io canceled*/
#define S_casApp_outOfBounds (M_casApp | 8) /*operation was out of bounds*/
#define S_casApp_undefined (M_casApp | 9) /*undefined value*/
#define S_casApp_postponeAsyncIO (M_casApp | 10) /*postpone asynchronous IO*/
#include "caNetAddr.h"
//
// pv exist test return
//
// If the server tool does not wish to start another simultaneous
// asynchronous IO operation or if there is not enough memory
// to do so return pverDoesNotExistHere (and the client will
// retry the request later).
//
enum pvExistReturnEnum {pverExistsHere, pverDoesNotExistHere,
pverAsyncCompletion};
class epicsShareClass pvExistReturn {
public:
//
// most server tools will use this
//
pvExistReturn (pvExistReturnEnum s=pverDoesNotExistHere) :
status(s) {}
//
// directory service server tools
// will use this
//
// (see caNetAddr.h)
//
pvExistReturn (const caNetAddr &addressIn) :
status(pverExistsHere), address(addressIn) {}
const pvExistReturn &operator = (pvExistReturnEnum rhs)
{
this->status = rhs;
this->address.clear();
return *this;
}
const pvExistReturn &operator = (const caNetAddr &rhs)
{
this->status = pverExistsHere;
this->address = rhs;
return *this;
}
pvExistReturnEnum getStatus() const {return this->status;}
int addrIsValid() const {return this->address.isValid();}
caNetAddr getAddr() const {return this->address;}
private:
pvExistReturnEnum status;
caNetAddr address;
};
class casPV;
//
// pvAttachReturn
//
class epicsShareClass pvAttachReturn {
public:
pvAttachReturn ()
{
this->pPV = NULL;
//
// A pv name is required for success
//
this->stat = S_cas_badParameter;
}
pvAttachReturn (caStatus statIn)
{
this->pPV = NULL;
if (statIn==S_casApp_success) {
//
// A pv name is required for success
//
this->stat = S_cas_badParameter;
}
else {
this->stat = statIn;
}
}
pvAttachReturn (casPV &pv)
{
this->pPV = &pv;
this->stat = S_casApp_success;
}
const pvAttachReturn &operator = (caStatus rhs)
{
this->pPV = NULL;
if (rhs == S_casApp_success) {
this->stat = S_cas_badParameter;
}
else {
this->stat = rhs;
}
return *this;
}
//
// const pvAttachReturn &operator = (casPV &pvIn)
//
// The above assignment operator is not included
// because it does not match the strict definition of an
// assignment operator unless "const casPV &"
// is passed in, and we cant use a const PV
// pointer here because the server library _will_ make
// controlled modification of the PV in the future.
//
const pvAttachReturn &operator = (casPV *pPVIn)
{
if (pPVIn!=NULL) {
this->stat = S_casApp_success;
}
else {
this->stat = S_casApp_pvNotFound;
}
this->pPV = pPVIn;
return *this;
}
const caStatus getStatus() const { return this->stat; }
casPV *getPV() const { return this->pPV; }
private:
casPV *pPV;
caStatus stat;
};
//
// pvCreateReturn (deprecated)
// (the class "pvCreateReturn" will be deleted in a future release)
//
class epicsShareClass pvCreateReturn : public pvAttachReturn {
public:
pvCreateReturn (caStatus statIn) : pvAttachReturn(statIn) {};
pvCreateReturn (casPV &pvIn) : pvAttachReturn (pvIn) {};
};
#include "casEventMask.h" // EPICS event select class
#include "casInternal.h" // CA server private
class caServerI;
//
// caServer - Channel Access Server API Class
//
class caServer {
friend class casPVI;
public:
epicsShareFunc caServer (unsigned pvCountEstimate=1024u);
epicsShareFunc virtual ~caServer() = 0;
//
// pvExistTest()
//
// This function is called by the server library when it needs to
// determine if a named PV exists (or could be created) in the
// server tool.
//
// The request is allowed to complete asynchronously
// (see Asynchronous IO Classes below).
//
// The server tool is encouraged to accept multiple PV name
// aliases for the same PV here.
//
// example return from this procedure:
// return pverExistsHere; // server has PV
// return pverDoesNotExistHere; // server does know of this PV
// return pverAsynchCompletion; // deferred result
//
// Return pverDoesNotExistHere if too many simultaneous
// asynchronous IO operations are pending against the server.
// The client library will retry the request at some time
// in the future.
//
epicsShareFunc virtual pvExistReturn pvExistTest (const casCtx &ctx,
const char *pPVAliasName);
//
// pvAttach()
//
// This function is called _every_ time that a client attaches to the PV.
// The name supplied here will be either a canonical PV name or an alias
// PV name.
//
// The request is allowed to complete asynchronously
// (see Asynchronous IO Classes below).
//
// IMPORTANT:
// It is a responsibility of the server tool to detect attempts by
// the server library to attach to an existing PV. If the PV does not
// exist then the server tool should create it. Otherwise, the server
// tool typically will return a pointer to the preexisting PV.
//
// The server tool is encouraged to accept multiple PV name aliases
// for the same PV here.
//
// In most situations the server tool should avoid PV duplication
// by returning a pointer to an existing PV if the PV alias name
// matches a preexisting PV's name or any of its aliases.
//
// example return from this procedure:
// return pPV; // success (pass by pointer)
// return PV; // success (pass by ref)
// return S_casApp_pvNotFound; // no PV by that name here
// return S_casApp_noMemory; // no resource to create pv
// return S_casApp_asyncCompletion; // deferred completion
//
// Return S_casApp_postponeAsyncIO if too many simultaneous
// asynchronous IO operations are pending against the server.
// The server library will retry the request whenever an
// asynchronous IO operation (create or exist) completes
// against the server.
//
// In certain specialized rare situations the server tool may choose
// to create client private process variables that are not shared between
// clients. In this situation there might be several process variables
// with the same name. One for each client. For example, a server tool
// might be written that provides access to archival storage of the
// historic values of a set of process variables. Each client would
// specify its date of interest by writing into a client private process
// variable. Next the client would determine the current value of its
// subset of named process variables at its privately specified date by
// attaching to additional client private process variables.
//
epicsShareFunc virtual pvAttachReturn pvAttach (const casCtx &ctx,
const char *pPVAliasName);
//
// createPV() (deprecated)
// The virtual member function "createPV" will be deleted in a
// future release. The base implementation of pvAttach() currently
// calls createPV().
//
epicsShareFunc virtual pvCreateReturn createPV (const casCtx &ctx,
const char *pPVAliasName);
//
// obtain an event mask for a named event type
// to be used with casPV::postEvent()
//
epicsShareFunc casEventMask registerEvent (const char *pName);
//
// common event masks
// (what is currently used by the CA clients)
//
epicsShareFunc casEventMask valueEventMask() const; // DBE_VALUE
epicsShareFunc casEventMask logEventMask() const; // DBE_LOG
epicsShareFunc casEventMask alarmEventMask() const; // DBE_ALARM
epicsShareFunc void setDebugLevel (unsigned level);
epicsShareFunc unsigned getDebugLevel () const;
//
// dump internal state of server to standard out
//
epicsShareFunc virtual void show (unsigned level) const;
//
// examine or clear diagnostic counters
//
// eventsPosted - number of events posted by server tool to the event queue
// eventsProcessed - number of events removed by server library from the event queue
//
// NOTE: this is an experimental interface which may change or vanish in
// the future. Perhaps a better alternative is to export this sort of
// information via dedicated process variables.
//
#ifdef CAS_DIAGNOSTICS_API_WHICH_MAY_VANISH_IN_THE_FUTURE
epicsShareFunc unsigned readEventsProcessedCounter (void) const;
epicsShareFunc void clearEventsProcessedCounter (void);
epicsShareFunc unsigned readEventsPostedCounter (void) const;
epicsShareFunc void clearEventsPostedCounter (void);
#endif
//caStatus enableClients ();
//caStatus disableClients ();
private:
//
// We do not use private inheritance here beacuse:
// o wish to avoid os/io dependent -I during server tool compile
// o server tool rebuild when internal structure of the server changes
//
caServerI *pCAS;
};
//
// casPV() - Channel Access Server Process Variable API Class
//
// Objects of this type are created by the caServer::pvAttach()
// object factory virtual function.
//
// Deletion Responsibility
// -------- --------------
// o the server lib will not call "delete" directly for any
// casPV because we dont know that "new" was called to create
// the object
// o The server tool is responsible for reclaiming storage for any
// casPV it creates. The destroy() virtual function will
// assist the server tool with this responsibility. The
// virtual function casPV::destroy() does a "delete this".
// o The virtual function "destroy()" is called by the server lib
// each time that the last client attachment to the PV object is removed.
// o The destructor for this object will cancel any
// client attachment to this PV (and reclaim any resources
// allocated by the server library on its behalf)
//
// NOTE: if the server tool precreates the PV during initialization
// then it may decide to provide a "destroy()" implementation in the
// derived class which is a noop.
//
class casPV : private casPVI {
public:
epicsShareFunc casPV ();
epicsShareFunc virtual ~casPV () = 0;
//
// This is called for each PV in the server if
// caServer::show() is called and the level is high
// enough
//
epicsShareFunc virtual void show (unsigned level) const;
//
// called by the server libary each time that it wishes to
// subscribe for PV change notification from the server
// tool via postEvent() below
//
epicsShareFunc virtual caStatus interestRegister ();
//
// called by the server library each time that it wishes to
// remove its subscription for PV value change events
// from the server tool via postEvent() below
//
epicsShareFunc virtual void interestDelete ();
//
// called by the server library immediately before initiating
// a transaction (PV state must not be modified during a
// transaction)
//
// NOTE: there may be many read/write operations performed within
// a single transaction if a large array is being transferred
//
epicsShareFunc virtual caStatus beginTransaction ();
//
// called by the server library immediately after completing
// a tranaction (PV state modification may resume after the
// transaction completes)
//
epicsShareFunc virtual void endTransaction ();
//
// read
//
// The request is allowed to complete asynchronously
// (see Asynchronous IO Classes below).
//
// RULE: if this completes asynchronously and the server tool references
// its data into the prototype descriptor passed in the args to read()
// then this data must _not_ be modified while the reference count
// on the prototype is greater than zero.
//
// Return S_casApp_postponeAsyncIO if too many simultaneous
// asynchronous IO operations are pending aginst the PV.
// The server library will retry the request whenever an
// asynchronous IO operation (read or write) completes
// against the PV.
//
// NOTE:
// o the server tool is encouraged to change the prototype GDD's
// primitive type to whatever primitive data type is most convient
// for the server side tool. Conversion libraries in the CA server
// will convert as necessary to the client's primitive data type.
//
epicsShareFunc virtual caStatus read (const casCtx &ctx, gdd &prototype);
//
// write
//
// The request is allowed to complete asynchronously
// (see Asynchronous IO Classes below).
//
// Return S_casApp_postponeAsyncIO if too many simultaneous
// asynchronous IO operations are pending aginst the PV.
// The server library will retry the request whenever an
// asynchronous IO operation (read or write) completes
// against the PV.
//
// NOTE:
// o The incoming GDD with application type "value" is always
// converted to the PV.bestExternalType() primitive type.
// o The time stamp in the incoming GDD is set to the time that
// the last message was received from the client.
// o Currently, no container type GDD's are passed here and
// the application type is always "value". This may change.
//
epicsShareFunc virtual caStatus write (const casCtx &ctx, const gdd &value);
//
// chCreate() is called each time that a PV is attached to
// by a client. The server tool may choose not to
// implement this routine (in which case the channel
// will be created by the server). If the server tool
// implements this function then it must create a casChannel object
// (or a derived class) each time that this routine is called
//
epicsShareFunc virtual casChannel *createChannel (const casCtx &ctx,
const char * const pUserName, const char * const pHostName);
//
// destroy() is called
// 1) each time that a PV transitions from
// a situation where clients are attached to a situation
// where no clients are attached.
// 2) once for all PVs that exist when the server is deleted
//
// the default (base) "destroy()" executes "delete this"
//
epicsShareFunc virtual void destroy ();
//
// tbe best type for clients to use when accessing the
// value of the PV
//
epicsShareFunc virtual aitEnum bestExternalType () const;
//
// Returns the maximum bounding box for all present and
// future data stored within the PV.
//
// The virtual function "dimension()" returns the maximum
// number of dimensions in the hypercube (0=scalar,
// 1=array, 2=plane, 3=cube ...}.
//
// The virtual function "maxBound(dimension)" returns the
// maximum number of elements in a particular dimension
// of the hypercube as follows:
//
// scalar - maxDimension() returns 0
//
// array - maxDimension() returns 1
// maxBounds(0) supplies number of elements in array
//
// plane - maxDimension() returns 2
// maxBounds(0) supplies number of elements in X dimension
// maxBounds(1) supplies number of elements in Y dimension
//
// cube - maxDimension() returns 3
// maxBounds(0) supplies number of elements in X dimension
// maxBounds(1) supplies number of elements in Y dimension
// maxBounds(2) supplies number of elements in Z dimension
// .
// .
// .
//
// The default (base) "dimension()" returns zero (scalar).
// The default (base) "maxBound()" returns one (scalar bounds)
// for all dimensions.
//
// Clients will see that the PV's data is scalar if
// these routines are not supplied in the derived class.
//
// If the "dimension" argument to maxBounds() is set to
// zero then the bound on the first dimension is being
// fetched. If the "dimension" argument to maxBound() is
// set to one then the bound on the second dimension
// are being fetched...
//
epicsShareFunc virtual unsigned maxDimension() const; // return zero if scalar
epicsShareFunc virtual aitIndex maxBound (unsigned dimension) const;
//
// Server tool calls this function to post a PV event.
//
epicsShareFunc void postEvent (const casEventMask &select, const gdd &event);
//
// peek at the pv name
//
// NOTE if there are several aliases for the same PV
// this routine should return the canonical (base)
// name for the PV
//
// pointer returned must remain valid for the life time
// o fthe process variable
//
//
// !! not thread safe !!
//
epicsShareFunc virtual const char *getName() const = 0;
//
// Find the server associated with this PV
// ****WARNING****
// this returns NULL if the PV isnt currently installed
// into a server (this situation will exist if
// the pv isnt deleted in a derived classes replacement
// for virtual casPV::destroy() or if the PV is created
// before the server
// ***************
//
epicsShareFunc caServer *getCAS() const;
//
// only used when caStrmClient converts from
// casPV * to casPVI *
//
friend class casStrmClient;
private:
casPV *apiPointer (); //retruns NULL if casPVI isnt a base of casPV
public:
//
// This constructor has been deprecated, and is preserved for
// backwards compatibility only. Please do not use it.
//
epicsShareFunc casPV (caServer &);
};
//
// casChannel - Channel Access Server - Channel API Class
//
// Objects of this type are created by the casPV::createChannel()
// object factory virtual function.
//
// A casChannel object is created each time that a CA client
// attaches to a process variable.
//
// Deletion Responsibility
// -------- --------------
// o the server lib will not call "delete" directly for any
// casChannel created by the server tool because we dont know
// that "new" was called to create the object
// o The server tool is responsible for reclaiming storage for any
// casChannel it creates. The destroy() virtual function will
// assist the server tool with this responsibility. The
// virtual function casChannel::destroy() does a "delete this".
// o The destructor for this object will cancel any
// client attachment to this channel (and reclaim any resources
// allocated by the server library on its behalf)
//
class casChannel : private casPVListChan {
public:
epicsShareFunc casChannel (const casCtx &ctx);
epicsShareFunc virtual ~casChannel();
//
// Called when the user name and the host name are changed
// for a live connection.
//
epicsShareFunc virtual void setOwner (const char * const pUserName,
const char * const pHostName);
//
// the following are encouraged to change during an channel's
// lifetime
//
epicsShareFunc virtual bool readAccess () const;
epicsShareFunc virtual bool writeAccess () const;
// return true to hint that the opi should ask the operator
// for confirmation prior writing to this PV
epicsShareFunc virtual bool confirmationRequested () const;
//
// This is called for each channel in the server if
// caServer::show() is called and the level is high
// enough
//
epicsShareFunc virtual void show (unsigned level) const;
//
// destroy() is called when
// 1) there is a client initiated channel delete
// 2) there is a server tool initiaed PV delete
// 3) there is a server tool initiated server delete
//
// the casChannel::destroy() executes a "delete this"
//
epicsShareFunc virtual void destroy ();
//
// server tool calls this to indicate change in access
// rights has occurred
//
epicsShareFunc void postAccessRightsEvent ();
//
// Find the PV associated with this channel
// ****WARNING****
// this returns NULL if the channel isnt currently installed
// into a PV (this situation will exist only if
// the channel isnt deleted in a derived classes replacement
// for virtual casChannel::destroy()
// ***************
//
epicsShareFunc casPV *getPV ();
//
// only used when casStrmClient converts between
// casChannel * and casChannelI *
//
friend class casStrmClient;
};
//
// Asynchronous IO Classes
//
// The following virtual functions allow for asynchronous completion:
//
// Virtual Function Asynchronous IO Class
// ----------------- ---------------------
// caServer::pvExistTest() casAsyncPVExistIO
// caServer::pvAttach() casAsyncPVAttachIO
// casPV::read() casAsyncReadIO
// casPV::write() casAsyncWriteIO
//
// To initiate asynchronous completion create a corresponding
// asynchronous IO object from within one of the virtual
// functions shown in the table above and return the status code
// S_casApp_asyncCompletion. Use the member function
// "postIOCompletion()" to inform the server library that the
// requested operation has completed.
//
//
// Deletion Responsibility
// -------- --------------
// o the server lib will not call "delete" directly for any
// casAsyncXxxIO created by the server tool because we dont know
// that "new" was called to create the object.
// o The server tool is responsible for reclaiming storage for any
// casAsyncXxxxIO it creates. The destroy virtual function will
// assist the server tool with this responsibility. The
// virtual function casAsyncXxxxIO::destroy() does a "delete this".
// o Avoid deleting the async IO object immediately after calling
// postIOCompletion(). Instead, proper operation requires that
// the server tool wait for the server lib to call destroy after
// the response is successfully queued to the client
// o If for any reason the server tool needs to cancel an IO
// operation then it should post io completion with status
// S_casApp_canceledAsyncIO. Deleting the asynchronous io
// object prior to its being allowed to forward an IO termination
// message to the client will result in NO IO CALL BACK TO THE
// CLIENT PROGRAM (in this situation a warning message will be
// printed by the server lib).
//
//
// casAsyncReadIO
// - for use with casPV::read()
//
// **Warning**
// The server tool must reference the gdd object
// passed in the arguments to casPV::read() if it is
// necessary for this gdd object to continue to exist
// after the return from casPV::read(). If this
// is done then it is suggested that this gdd object
// be referenced in the constructor, and unreferenced
// in the destructor, for the class deriving from
// casAsyncReadIO.
// **
class casAsyncReadIO : private casAsyncIOI {
public:
//
// casAsyncReadIO()
//
epicsShareFunc casAsyncReadIO (const casCtx &ctx);
epicsShareFunc virtual ~casAsyncReadIO ();
//
// place notification of IO completion on the event queue
// (this function does not delete the casAsyncReadIO object)
//
// only the first call to this function has any effect
//
epicsShareFunc caStatus postIOCompletion (caStatus completionStatusIn, const gdd &valueRead);
//
// Find the server associated with this async IO
// ****WARNING****
// this returns NULL if the async io isnt currently installed
// into a server
// ***************
//
epicsShareFunc caServer *getCAS () const;
//
// called by the server lib after the response message
// is succesfully queued to the client or when the
// IO operation is canceled (client disconnects etc)
//
// default destroy executes a "delete this"
//
epicsShareFunc virtual void destroy ();
private:
caHdr const msg;
casChannelI &chan;
smartConstGDDPointer pDD;
caStatus completionStatus;
epicsShareFunc bool readOP() const;
epicsShareFunc caStatus cbFuncAsyncIO();
};
//
// casAsyncWriteIO
// - for use with casPV::write()
//
// **Warning**
// The server tool must reference the gdd object
// passed in the arguments to casPV::write() if it is
// necessary for this gdd object to continue to exist
// after the return from casPV::write(). If this
// is done then it is suggested that this gdd object
// be referenced in the constructor, and unreferenced
// in the destructor, for the class deriving from
// casAsyncWriteIO.
// **
//
class casAsyncWriteIO : private casAsyncIOI {
public:
//
// casAsyncWriteIO()
//
epicsShareFunc casAsyncWriteIO (const casCtx &ctx);
epicsShareFunc virtual ~casAsyncWriteIO ();
//
// place notification of IO completion on the event queue
// (this function does not delete the casAsyncWriteIO object).
// Only the first call to this function has any effect.
//
epicsShareFunc caStatus postIOCompletion (caStatus completionStatusIn);
//
// Find the server associated with this async IO
// ****WARNING****
// this returns NULL if the async io isnt currently installed
// into a server
// ***************
//
epicsShareFunc caServer *getCAS () const;
//
// called by the server lib after the response message
// is succesfully queued to the client or when the
// IO operation is canceled (client disconnects etc)
//
// default destroy executes a "delete this"
//
epicsShareFunc virtual void destroy ();
private:
caHdr const msg;
casChannelI &chan;
caStatus completionStatus;
epicsShareFunc caStatus cbFuncAsyncIO ();
};
//
// casAsyncPVExistIO
// - for use with caServer::pvExistTest()
//
class casAsyncPVExistIO : private casAsyncIOI {
public:
//
// casAsyncPVExistIO()
//
epicsShareFunc casAsyncPVExistIO (const casCtx &ctx);
epicsShareFunc virtual ~casAsyncPVExistIO ();
//
// place notification of IO completion on the event queue
// (this function does not delete the casAsyncPVExistIO object)
//
// only the first call to this function has any effect.
//
epicsShareFunc caStatus postIOCompletion (const pvExistReturn &retValIn);
//
// Find the server associated with this async IO
// ****WARNING****
// this returns NULL if the async io isnt currently installed
// into a server
// ***************
//
epicsShareFunc caServer *getCAS() const;
//
// called by the server lib after the response message
// is succesfully queued to the client or when the
// IO operation is canceled (client disconnects etc)
//
// default destroy executes a "delete this"
//
epicsShareFunc virtual void destroy();
private:
caHdr const msg;
pvExistReturn retVal;
const caNetAddr dgOutAddr;
epicsShareFunc caStatus cbFuncAsyncIO();
};
//
// casAsyncPVAttachIO
// - for use with caServer::pvAttach()
//
class casAsyncPVAttachIO : private casAsyncIOI {
public:
//
// casAsyncPVAttachIO()
//
epicsShareFunc casAsyncPVAttachIO (const casCtx &ctx);
epicsShareFunc virtual ~casAsyncPVAttachIO ();
//
// place notification of IO completion on the event queue
// (this function does not delete the casAsyncPVAttachIO object).
// Only the first call to this function has any effect.
//
epicsShareFunc caStatus postIOCompletion (const pvAttachReturn &retValIn);
//
// Find the server associated with this async IO
// ****WARNING****
// this returns NULL if the async io isnt currently installed
// into a server
// ***************
//
epicsShareFunc caServer *getCAS() const;
//
// called by the server lib after the response message
// is succesfully queued to the client or when the
// IO operation is canceled (client disconnects etc)
//
// default destroy executes a "delete this"
//
epicsShareFunc virtual void destroy ();
private:
caHdr const msg;
pvAttachReturn retVal;
epicsShareFunc caStatus cbFuncAsyncIO ();
};
//
// casAsyncPVCreateIO (deprecated)
// (this class will be deleted in a future release)
//
class casAsyncPVCreateIO : private casAsyncPVAttachIO {
public:
epicsShareFunc casAsyncPVCreateIO(const casCtx &ctx);
epicsShareFunc virtual ~casAsyncPVCreateIO();
};
// TODO:
// .03 document new event types for limits change etc
// .04 certain things like native type cant be changed during
// pv id's life time or we will be required to have locking
// (doc this)
// .08 Need a mechanism by which an error detail string can be returned
// to the server from a server app (in addition to the normal
// error constant)
// .12 Should the server have an interface so that all PV names
// can be obtained (even ones created after init)? This
// would be used to implement update of directory services and
// wild cards? Problems here with knowing PV name structure and
// maximum permutations of name components.
// .16 go through this file and make sure that we are consistent about
// the use of const - use a pointer only in spots where NULL is
// allowed?
// NOTES:
// .01 When this code is used in a multi threaded situation we
// must be certain that the derived class's virtual function
// are not called between derived class destruction and base
// class destruction (or prevent problems if they are).
// Possible solutions
// 1) in the derived classes destructor set a variable which
// inhibits use of the derived classes virtual function.
// Each virtual function must check this inhibit bit and return
// an error if it is set
// 2) call a method on the base which prevents further use
// of it by the server from the derived class destructor.
// 3) some form of locking (similar to (1) above)
//
#endif // ifdef includecasdefh (this must be the last line in this file)