moved down one level

This commit is contained in:
Jeff Hill
1996-12-06 22:20:22 +00:00
parent a7e61ddeb8
commit eff915d837
14 changed files with 2244 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
TOP=../../../..
include $(TOP)/config/CONFIG_BASE
include $(TOP)/config/RULES_ARCHS
+94
View File
@@ -0,0 +1,94 @@
CAS = ../../..
TOP = $(CAS)/../..
include $(TOP)/config/CONFIG_BASE
CXXCMPLR = STRICT
USR_INCLUDES =
USR_LDLIBS = -lcas -lca -lCom -lgdd
USR_LDFLAGS =
DEPLIBS_BASE = $(EPICS_BASE_LIB)
DEPLIBSWOCAS = $(DEPLIBS_BASE)/libca.a $(DEPLIBS_BASE)/libCom.a \
$(DEPLIBS_BASE)/libgdd.a
DEPLIBS = $(DEPLIBS_BASE)/libcas.a $(DEPLIBSWOCAS)
SRCS.cc += ../main.cc
SRCS.cc += ../exServer.cc
SRCS.cc += ../exPV.cc
SRCS.cc += ../exSyncPV.cc
SRCS.cc += ../exAsyncPV.cc
SRCS.cc += ../exChannel.cc
SRCS.cc += ../templInst.cc
OBJS += main.o
OBJS += exServer.o
OBJS += exPV.o
OBJS += exSyncPV.o
OBJS += exAsyncPV.o
OBJS += exChannel.o
OBJS += templInst.o
PROD += excas
BUILDDIR = $(CAS)/build/singleThread/O.sun4/
GLOMBOBJ += $(BUILDDIR)caServer.o
GLOMBOBJ += $(BUILDDIR)caServerI.o
GLOMBOBJ += $(BUILDDIR)casCoreClient.o
GLOMBOBJ += $(BUILDDIR)casClient.o
GLOMBOBJ += $(BUILDDIR)casDGClient.o
GLOMBOBJ += $(BUILDDIR)casStrmClient.o
GLOMBOBJ += $(BUILDDIR)casPV.o
GLOMBOBJ += $(BUILDDIR)casPVI.o
GLOMBOBJ += $(BUILDDIR)casChannel.o
GLOMBOBJ += $(BUILDDIR)casChannelI.o
GLOMBOBJ += $(BUILDDIR)casClientMon.o
GLOMBOBJ += $(BUILDDIR)casChanDelEv.o
GLOMBOBJ += $(BUILDDIR)casMsgIO.o
GLOMBOBJ += $(BUILDDIR)casAsyncIO.o
GLOMBOBJ += $(BUILDDIR)casAsyncIOI.o
GLOMBOBJ += $(BUILDDIR)casEventSys.o
GLOMBOBJ += $(BUILDDIR)casMonitor.o
GLOMBOBJ += $(BUILDDIR)casMonEvent.o
GLOMBOBJ += $(BUILDDIR)outBuf.o
GLOMBOBJ += $(BUILDDIR)inBuf.o
GLOMBOBJ += $(BUILDDIR)casEventMask.o
GLOMBOBJ += $(BUILDDIR)ioBlocked.o
GLOMBOBJ += $(BUILDDIR)caServerOS.o
GLOMBOBJ += $(BUILDDIR)casDGOS.o
GLOMBOBJ += $(BUILDDIR)casStreamOS.o
GLOMBOBJ += $(BUILDDIR)caServerIO.o
GLOMBOBJ += $(BUILDDIR)casDGIO.o
GLOMBOBJ += $(BUILDDIR)casStreamIO.o
GLOMBOBJ += $(BUILDDIR)sigPipeIgnore.o
include $(TOP)/config/RULES.Unix
excas: $(OBJS) $(DEPLIBS)
$(LINK.cc) -o $@ $(OBJS) $(LDFLAGS) $(LDLIBS)
#
# fast link (without waiting for library build)
#
fexcas: $(OBJS) $(GLOMBOBJ) $(DEPLIBSWOCAS)
$(LINK.cc) -o $@ $(OBJS) $(GLOMBOBJ) $(DEPLIBSWOCAS)
#
# build with purify
#
pexcas: $(OBJS) $(DEPLIBS)
$(PURIFY) $(LINK.cc) -o $@ $(OBJS) $(LDFLAGS) $(LDLIBS)
clean::
@$(RM) excas
@$(RM) fexcas
@$(RM) pexcas
@$(RM) -rf Templates.DB
@$(RM) core
@@ -0,0 +1,38 @@
CAS = ../../..
TOP = $(CAS)/../..
include $(TOP)/config/CONFIG_BASE
CXXCMPLR = STRICT
USR_INCLUDES =
USR_LDFLAGS =
DEPLIBS_BASE = $(EPICS_BASE_LIB)
DEPLIBS = $(DEPLIBS_BASE)/libcas.a $(DEPLIBSWOCAS)
SRCS.cc += ../vxEntry.cc
SRCS.cc += ../exServer.cc
SRCS.cc += ../exPV.cc
SRCS.cc += ../exSyncPV.cc
SRCS.cc += ../exAsyncPV.cc
SRCS.cc += ../exChannel.cc
LIBOBJS += vxEntry.o
LIBOBJS += exServer.o
LIBOBJS += exPV.o
LIBOBJS += exSyncPV.o
LIBOBJS += exAsyncPV.o
LIBOBJS += exChannel.o
LIBNAME = libexserver.o
include $(TOP)/config/RULES.Vx
excas: $(OBJS) $(DEPLIBS)
$(LINK.cc) -o $@ $(OBJS) $(LDFLAGS) $(LDLIBS)
clean::
@$(RM) -rf Templates.DB
@$(RM) core
+13
View File
@@ -0,0 +1,13 @@
This directory contains an example ca server. The example server
exports 4 process variables (PVs): "fred", "freddy", "jane", and
"janet". "fred" and "jane" are synchronous PVs. "freddy" and "janet"
are asynchronous. Many ca servers will find that synchronous
variables will meet there needs and therefore will not require
the increased complexity associated with asynchronous PVs. The PVs in
the example server are updated periodically. Some random "noise"
is added to each PVs current value each time that it is updated.
The example server does not so far implement enumerated data types.
+95
View File
@@ -0,0 +1,95 @@
//
// Example EPICS CA server
//
#include <exServer.h>
//
// exAsyncPV::maxSimultAsyncOps()
// (virtual replacement for the default)
//
unsigned exAsyncPV::maxSimultAsyncOps () const
{
return 500u;
}
//
// exAsyncPV::read()
// (virtual replacement for the default)
//
caStatus exAsyncPV::read (const casCtx &ctx, gdd &valueIn)
{
exAsyncReadIO *pIO;
pIO = new exAsyncReadIO(ctx, *this, valueIn);
if (!pIO) {
return S_casApp_noMemory;
}
return S_casApp_asyncCompletion;
}
//
// exAsyncPV::write()
// (virtual replacement for the default)
//
caStatus exAsyncPV::write (const casCtx &ctx, gdd &valueIn)
{
exAsyncWriteIO *pIO;
pIO = new exAsyncWriteIO(ctx, *this, valueIn);
if (!pIO) {
return S_casApp_noMemory;
}
return S_casApp_asyncCompletion;
}
//
// exAsyncWriteIO::expire()
// (a virtual function that runs when the base timer expires)
//
void exAsyncWriteIO::expire()
{
caStatus status;
status = this->pv.update(this->value);
this->postIOCompletion (status);
}
//
// exAsyncWriteIO::name()
//
const char *exAsyncWriteIO::name() const
{
return "exAsyncWriteIO";
}
//
// exAsyncReadIO::expire()
// (a virtual function that runs when the base timer expires)
//
void exAsyncReadIO::expire()
{
caStatus status;
//
// map between the prototype in and the
// current value
//
status = exServer::read(this->pv, this->proto);
//
// post IO completion
//
this->postIOCompletion(status, this->proto);
}
//
// exAsyncReadIO::name()
//
const char *exAsyncReadIO::name() const
{
return "exAsyncReadIO";
}
+7
View File
@@ -0,0 +1,7 @@
//
// Example EPICS CA server
//
#include <exServer.h>
+394
View File
@@ -0,0 +1,394 @@
//
// Example EPICS CA server
//
#include <exServer.h>
#include <gddApps.h>
const double myPI = 3.14159265358979323846;
osiTime exPV::currentTime;
//
// exPV::exPV()
//
exPV::exPV (const casCtx &ctxIn, const pvInfo &setup) :
pValue(NULL),
pScanTimer(NULL),
info(setup),
casPV(ctxIn, setup.getName().string()),
interest(aitFalse)
{
//
// load initial value
//
this->scanPV();
}
//
// exPV::~exPV()
//
exPV::~exPV()
{
if (this->pScanTimer) {
delete this->pScanTimer;
this->pScanTimer = NULL;
}
if (this->pValue) {
this->pValue->unreference();
this->pValue = NULL;
}
}
//
// exPV::scanPV();
//
void exPV::scanPV()
{
caStatus status;
double radians;
gdd *pDD;
float newValue;
float limit;
caServer *pCAS = this->getCAS();
if (!pCAS) {
return;
}
//
// update current time (so we are not required to do
// this every time that we write the PV which impacts
// throughput under sunos4 because gettimeofday() is
// slow)
//
this->currentTime = osiTime::getCurrent();
pDD = new gddScalar (gddAppType_value, aitEnumFloat32);
if (!pDD) {
return;
}
radians = (rand () * 2.0 * myPI)/RAND_MAX;
if (this->pValue) {
this->pValue->getConvert(newValue);
}
else {
newValue = 0.0f;
}
newValue += (float) (sin (radians) / 10.0);
limit = (float) this->info.getHopr();
newValue = min (newValue, limit);
limit = (float) this->info.getLopr();
newValue = max (newValue, limit);
*pDD = newValue;
pDD->setStat (epicsAlarmNone);
pDD->setSevr (epicsSevNone);
status = this->update (*pDD);
if (status) {
errMessage (status, "scan update failed\n");
}
pDD->unreference();
}
//
// exScanTimer::expire ()
//
void exScanTimer::expire ()
{
pv.scanPV();
}
//
// exScanTimer::again()
//
osiBool exScanTimer::again() const
{
return osiTrue;
}
//
// exScanTimer::delay()
//
const osiTime exScanTimer::delay() const
{
return pv.getScanRate();
}
//
// exScanTimer::name()
//
const char *exScanTimer::name() const
{
return "exScanTimer";
}
//
// exPV::update ()
//
caStatus exPV::update(gdd &valueIn)
{
gdd *pNewValue;
caServer *pCAS = this->getCAS();
//
// gettimeofday() is very slow under sunos4
//
osiTime cur (this->currentTime);
struct timespec t;
gddStatus gdds;
if (!pCAS) {
return S_casApp_noSupport;
}
# if DEBUG
printf("Setting %s too:\n", this->info.getName().string());
valueIn.dump();
# endif
if (valueIn.isScalar()) {
pNewValue = &valueIn;
pNewValue->reference();
}
else {
//
// this does not modify the current value
// (because it may be referenced in the event queue)
//
pNewValue = new gddScalar (gddAppType_value, aitEnumFloat32);
if (!pNewValue) {
return S_casApp_noMemory;
}
gdds = gddApplicationTypeTable::
app_table.smartCopy(pNewValue, &valueIn);
if (gdds) {
pNewValue->unreference();
return S_cas_noConvert;
}
pNewValue->setStat (epicsAlarmNone);
pNewValue->setSevr (epicsSevNone);
}
cur.get (t.tv_sec, t.tv_nsec);
pNewValue->setTimeStamp(&t);
//
// release old value and replace it
// with the new one
//
if (this->pValue) {
this->pValue->unreference();
}
this->pValue = pNewValue;
if (this->interest==aitTrue) {
casEventMask select(pCAS->valueEventMask|pCAS->logEventMask);
this->postEvent (select, *this->pValue);
}
return S_casApp_success;
}
//
// exPV::bestExternalType()
//
aitEnum exPV::bestExternalType() const
{
return aitEnumFloat32;
}
//
// exPV::interestRegister()
//
caStatus exPV::interestRegister()
{
caServer *pCAS = this->getCAS();
if (!pCAS) {
return S_casApp_success;
}
if (!this->pScanTimer) {
this->pScanTimer = new exScanTimer
(this->info.getScanRate(), *this);
if (!this->pScanTimer) {
errPrintf (S_cas_noMemory, __FILE__, __LINE__,
"Scan init for %s failed\n",
this->info.getName().string());
return S_cas_noMemory;
}
}
this->interest = aitTrue;
return S_casApp_success;
}
//
// exPV::interestDelete()
//
void exPV::interestDelete()
{
if (this->pScanTimer) {
delete this->pScanTimer;
this->pScanTimer = NULL;
}
this->interest = aitFalse;
}
//
// exPV::show()
//
void exPV::show(unsigned level)
{
if (level>1u) {
if (this->pValue) {
printf("exPV: cond=%d\n", this->pValue->getStat());
printf("exPV: sevr=%d\n", this->pValue->getSevr());
printf("exPV: value=%f\n", (double) *this->pValue);
}
printf("exPV: interest=%d\n", this->interest);
printf("exPV: pScanTimer=%x\n", (unsigned) this->pScanTimer);
}
}
//
// exPV::getStatus()
//
caStatus exPV::getStatus(gdd &value)
{
if (this->pValue) {
value.put(this->pValue->getStat());
}
else {
value.put((aitUint16)epicsAlarmUDF);
}
return S_cas_success;
}
//
// exPV::getSeverity()
//
caStatus exPV::getSeverity(gdd &value)
{
if (this->pValue) {
value.put(this->pValue->getSevr());
}
else {
value.put((aitUint16)epicsSevInvalid);
}
return S_cas_success;
}
//
// exPV::getTS()
//
inline aitTimeStamp exPV::getTS()
{
aitTimeStamp ts;
if (this->pValue) {
this->pValue->getTimeStamp(&ts);
}
else {
osiTime cur(osiTime::getCurrent());
cur.get(ts.tv_sec, ts.tv_nsec);
}
return ts;
}
//
// exPV::getSeconds()
//
caStatus exPV::getSeconds(gdd &value)
{
aitUint32 sec (this->getTS().tv_sec);
value.put(sec);
return S_cas_success;
}
//
// exPV::getNanoseconds()
//
caStatus exPV::getNanoseconds(gdd &value)
{
aitUint32 nsec (this->getTS().tv_nsec);
value.put(nsec);
return S_cas_success;
}
//
// exPV::getPrecision()
//
caStatus exPV::getPrecision(gdd &prec)
{
prec.put(4u);
return S_cas_success;
}
//
// exPV::getHighLimit()
//
caStatus exPV::getHighLimit(gdd &value)
{
value.put(info.getHopr());
return S_cas_success;
}
//
// exPV::getLowLimit()
//
caStatus exPV::getLowLimit(gdd &value)
{
value.put(info.getLopr());
return S_cas_success;
}
//
// exPV::getUnits()
//
caStatus exPV::getUnits(gdd &units)
{
static aitString str("@#$%");
units.put(str);
return S_cas_success;
}
//
// exPV::getEnums()
//
caStatus exPV::getEnums(gdd &)
{
return S_cas_noConvert;
}
//
// exPV::getValue()
//
caStatus exPV::getValue(gdd &value)
{
caStatus status;
if (this->pValue) {
gddStatus gdds;
gdds = gddApplicationTypeTable::
app_table.smartCopy(&value, this->pValue);
if (gdds) {
status = S_cas_noConvert;
}
else {
status = S_cas_success;
}
}
else {
status = S_casApp_undefined;
}
return status;
}
+161
View File
@@ -0,0 +1,161 @@
//
// fileDescriptorManager.process(delay);
// (the name of the global symbol has leaked in here)
//
//
// Example EPICS CA server
//
#include <exServer.h>
const pvInfo exServer::pvList[] = {
pvInfo (1.0e-1, "jane", 10.0f, 0.0f, excasIoSync),
pvInfo (2.0, "fred", 10.0f, -10.0f, excasIoSync),
pvInfo (1.0e-1, "janet", 10.0f, 0.0f, excasIoAsync),
pvInfo (2.0, "freddy", 10.0f, -10.0f, excasIoAsync)
};
//
// static data for exServer
//
gddAppFuncTable<exPV> exServer::ft;
//
// exServer::exServer()
//
exServer::exServer(unsigned pvMaxNameLength, unsigned pvCountEstimate,
unsigned maxSimultaneousIO) :
caServer(pvMaxNameLength, pvCountEstimate, maxSimultaneousIO)
{
ft.installReadFunc("status",exPV::getStatus);
ft.installReadFunc("severity",exPV::getSeverity);
ft.installReadFunc("seconds",exPV::getSeconds);
ft.installReadFunc("nanoseconds",exPV::getNanoseconds);
ft.installReadFunc("precision",exPV::getPrecision);
ft.installReadFunc("graphicHigh",exPV::getHighLimit);
ft.installReadFunc("graphicLow",exPV::getLowLimit);
ft.installReadFunc("controlHigh",exPV::getHighLimit);
ft.installReadFunc("controlLow",exPV::getLowLimit);
ft.installReadFunc("alarmHigh",exPV::getHighLimit);
ft.installReadFunc("alarmLow",exPV::getLowLimit);
ft.installReadFunc("alarmHighWarning",exPV::getHighLimit);
ft.installReadFunc("alarmLowWarning",exPV::getLowLimit);
ft.installReadFunc("units",exPV::getUnits);
ft.installReadFunc("value",exPV::getValue);
ft.installReadFunc("enums",exPV::getEnums);
}
//
// exServer::pvExistTest()
//
pvExistReturn exServer::pvExistTest(const casCtx &ctxIn, const char *pPVName)
{
const pvInfo *pPVI;
pPVI = exServer::findPV(pPVName);
if (pPVI) {
if (pPVI->getIOType()==excasIoAsync) {
exAsyncExistIO *pIO;
pIO = new exAsyncExistIO(*pPVI, ctxIn);
if (pIO) {
return pvExistReturn(S_casApp_asyncCompletion);
}
else {
return pvExistReturn(S_casApp_noMemory);
}
}
const char *pName = pPVI->getName();
return pvExistReturn(S_casApp_success, pName);
}
return pvExistReturn(S_casApp_pvNotFound);
}
//
// findPV()
//
const pvInfo *exServer::findPV(const char *pName)
{
const pvInfo *pPVI;
const pvInfo *pPVAfter =
&exServer::pvList[NELEMENTS(exServer::pvList)];
for (pPVI = exServer::pvList; pPVI < pPVAfter; pPVI++) {
if (strcmp (pName, pPVI->getName().string()) == '\0') {
return pPVI;
}
}
return NULL;
}
//
// exServer::createPV()
//
casPV *exServer::createPV (const casCtx &ctxIn, const char *pPVName)
{
const pvInfo *pInfo;
pInfo = exServer::findPV(pPVName);
if (!pInfo) {
return NULL;
}
switch (pInfo->getIOType()){
case excasIoSync:
return new exSyncPV (ctxIn, *pInfo);
case excasIoAsync:
return new exAsyncPV (ctxIn, *pInfo);
default:
return NULL;
}
}
//
// exServer::show()
//
void exServer::show (unsigned level)
{
//
// server tool specific show code goes here
//
//
// print information about ca server libarary
// internals
//
this->caServer::show(level);
}
//
// this is a noop that postpones the timer expiration
// destroy so the exAsyncIO class will hang around until the
// casAsyncIO::destroy() is called
//
void exOSITimer::destroy()
{
}
//
// exAsyncExistIO::expire()
// (a virtual function that runs when the base timer expires)
//
void exAsyncExistIO::expire()
{
const char *pName = pvi.getName();
//
// post IO completion
//
this->postIOCompletion (pvExistReturn(S_cas_success, pName));
}
//
// exAsyncExistIO::name()
//
const char *exAsyncExistIO::name() const
{
return "exAsyncExistIO";
}
+390
View File
@@ -0,0 +1,390 @@
//
// Example EPICS CA server
//
//
// ANSI C
//
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>
//
// SUN C++ does not have RAND_MAX yet
//
#if !defined(RAND_MAX)
//
// Apparently SUN C++ is using the SYSV version of rand
//
#if 0
#define RAND_MAX INT_MAX
#else
#define RAND_MAX SHRT_MAX
#endif
#endif
//
// EPICS
//
#include <epicsAssert.h>
#include <casdef.h>
#include <gddAppFuncTable.h>
#include <osiTimer.h>
#ifndef max
#define max(A,B) ((A)<(B)?(B):(A))
#endif
#ifndef min
#define min(A,B) ((A)>(B)?(B):(A))
#endif
#ifndef NELEMENTS
# define NELEMENTS(A) (sizeof(A)/sizeof(A[0]))
#endif
#define LOCAL static
//
// info about all pv in this server
//
enum excasIoType {excasIoSync, excasIoAsync};
class pvInfo {
public:
pvInfo (double scanRateIn, const char *pName,
aitFloat32 hoprIn, aitFloat32 loprIn,
excasIoType ioTypeIn) :
scanRate(scanRateIn), name(pName), hopr(hoprIn),
lopr(loprIn), ioType(ioTypeIn)
{
}
//
// for use when MSVC++ will not build a defualt copy constructor
// for this class
//
pvInfo (const pvInfo &copyIn) :
scanRate(copyIn.scanRate), name(copyIn.name),
hopr(copyIn.hopr), lopr(copyIn.lopr),
ioType(copyIn.ioType)
{
}
const double getScanRate () const { return this->scanRate; }
const aitString &getName () const { return this->name; }
const double getHopr () const { return this->hopr; }
const double getLopr () const { return this->lopr; }
const excasIoType getIOType () const { return this->ioType; }
private:
const double scanRate;
const aitString name;
const double hopr;
const double lopr;
const excasIoType ioType;
};
class exPV;
//
// exScanTimer
//
class exScanTimer : public osiTimer {
public:
exScanTimer (double delayIn, exPV &pvIn) :
pv(pvIn), osiTimer(delayIn) {}
void expire ();
osiBool again() const;
const osiTime delay() const;
const char *name() const;
private:
exPV &pv;
};
//
// exPV
//
class exPV : public casPV {
public:
exPV (const casCtx &ctxIn, const pvInfo &setup);
virtual ~exPV();
void scanPV();
void show(unsigned level);
//
// Called by the server libary each time that it wishes to
// subscribe for PV the server tool via postEvent() below.
//
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 caServerPostEvents()
//
void interestDelete();
aitEnum bestExternalType() const;
//
// chCreate() is called each time that a PV is attached to
// by a client. The server tool must create a casChannel object
// (or a derived class) each time that this routine is called
//
// If the operation must complete asynchronously then return
// the status code S_casApp_asyncCompletion and then
// create the casChannel object at some time in the future
//
//casChannel *createChannel ();
caStatus update (gdd &value);
//
// Std PV Attribute fetch support
//
gddAppFuncTableStatus getStatus(gdd &value);
gddAppFuncTableStatus getSeverity(gdd &value);
gddAppFuncTableStatus getSeconds(gdd &value);
gddAppFuncTableStatus getNanoseconds(gdd &value);
gddAppFuncTableStatus getPrecision(gdd &value);
gddAppFuncTableStatus getHighLimit(gdd &value);
gddAppFuncTableStatus getLowLimit(gdd &value);
gddAppFuncTableStatus getUnits(gdd &value);
gddAppFuncTableStatus getValue(gdd &value);
gddAppFuncTableStatus getEnums(gdd &value);
//
//
//
aitTimeStamp getTS();
const float getScanRate()
{
return this->info.getScanRate();
}
protected:
gdd *pValue;
exScanTimer *pScanTimer;
const pvInfo & info;
aitBool interest;
private:
static osiTime currentTime;
};
//
// exServer
//
class exServer : public caServer {
public:
exServer(unsigned pvMaxNameLength, unsigned pvCountEstimate=0x3ff,
unsigned maxSimultaneousIO=1u);
void show (unsigned level);
pvExistReturn pvExistTest (const casCtx &ctxIn, const char *pPVName);
casPV *createPV (const casCtx &ctxIn, const char *pPVName);
static const pvInfo *findPV(const char *pName);
static gddAppFuncTableStatus read(exPV &pv, gdd &value)
{
return exServer::ft.read(pv, value);
}
private:
static const pvInfo pvList[];
static gddAppFuncTable<exPV> ft;
};
//
// exSyncPV
//
class exSyncPV : public exPV {
public:
exSyncPV (const casCtx &ctxIn, const pvInfo &setup);
~exSyncPV();
//
// read
//
caStatus read(const casCtx &ctxIn, gdd &value);
//
// write
//
caStatus write(const casCtx &ctxIn, gdd &value);
private:
};
//
// exAsyncPV
// (asychronous PV)
//
class exAsyncPV : public exPV {
public:
//
// exAsyncPV()
//
exAsyncPV (const casCtx &ctxIn, const pvInfo &setup) :
exPV (ctxIn, setup) {}
//
// read
//
caStatus read(const casCtx &ctxIn, gdd &value);
//
// write
//
caStatus write(const casCtx &ctxIn, gdd &value);
unsigned maxSimultAsyncOps () const;
private:
};
//
// exChannel
//
class exChannel : public casChannel{
public:
exChannel(const casCtx &ctxIn) : casChannel(ctxIn) {}
//void setOwner(const char *pUserName, const char *pHostName){};
//
// called when the first client begins to monitor the PV
//
caStatus interestRegister ()
{
return S_cas_success;
}
//
// called when the last client stops monitoring the PV
//
void interestDelete () {}
//
// the following are encouraged to change during an channel's
// lifetime
//
aitBool readAccess () const {return aitTrue;};
aitBool writeAccess () const {return aitTrue;};
private:
};
//
// exOSITimer
//
// a special version of osiTimer which is only to be used
// within an exAsyncIO. The destroy() method is replaced
// so that the timer destroy() will not destroy the
// exAsyncIO until the casAsyncIO has completed
//
class exOSITimer : public osiTimer {
public:
exOSITimer() : osiTimer(osiTime(0.010)) {} // 10 mSec
//
// this is a noop that postpones the timer expiration
// destroy so this object will hang around until the
// casAsyncIO::destroy() is called
//
void destroy();
};
//
// exAsyncWriteIO
//
class exAsyncWriteIO : public casAsyncWriteIO, public exOSITimer {
public:
//
// exAsyncWriteIO()
//
exAsyncWriteIO(const casCtx &ctxIn, exAsyncPV &pvIn, gdd &valueIn) :
casAsyncWriteIO(ctxIn), pv(pvIn), value(valueIn)
{
this->value.reference();
}
~exAsyncWriteIO()
{
this->value.unreference();
}
//
// expire()
// (a virtual function that runs when the base timer expires)
// see exAsyncPV.cc
//
void expire();
const char *name() const;
private:
exAsyncPV &pv;
gdd &value;
};
//
// exAsyncReadIO
//
class exAsyncReadIO : public casAsyncReadIO, public exOSITimer {
public:
//
// exAsyncReadIO()
//
exAsyncReadIO(const casCtx &ctxIn, exAsyncPV &pvIn, gdd &protoIn) :
casAsyncReadIO(ctxIn), pv(pvIn), proto(protoIn)
{
this->proto.reference();
}
~exAsyncReadIO()
{
this->proto.unreference();
}
//
// expire()
// (a virtual function that runs when the base timer expires)
// see exAsyncPV.cc
//
void expire();
const char *name() const;
private:
exAsyncPV &pv;
gdd &proto;
};
//
// exAsyncExistIO
// (PV exist async IO)
//
class exAsyncExistIO : public casAsyncPVExistIO, public exOSITimer {
public:
//
// exAsyncExistIO()
//
exAsyncExistIO(const pvInfo &pviIn, const casCtx &ctxIn) :
casAsyncPVExistIO(ctxIn), pvi(pviIn) {}
//
// expire()
// (a virtual function that runs when the base timer expires)
// see exServer.cc
//
void expire();
const char *name() const;
private:
const pvInfo &pvi;
};
+38
View File
@@ -0,0 +1,38 @@
//
// Example EPICS CA server
//
#include <exServer.h>
//
// exSyncPV::exSyncPV()
//
exSyncPV::exSyncPV (const casCtx &ctxIn, const pvInfo &setup) :
exPV (ctxIn, setup)
{
}
//
// exSyncPV::~exSyncPV()
//
exSyncPV::~exSyncPV()
{
}
//
// exSyncPV::write()
//
caStatus exSyncPV::write (const casCtx &, gdd &valueIn)
{
return this->update (valueIn);
}
//
// exSyncPV::read()
//
caStatus exSyncPV::read (const casCtx &, gdd &protoIn)
{
return exServer::read(*this, protoIn);
}
+62
View File
@@ -0,0 +1,62 @@
#include <exServer.h>
#include <fdManager.h>
//
// main()
// (example single threaded ca server tool main loop)
//
int main (int argc, const char **argv)
{
osiTime begin(osiTime::getCurrent());
exServer *pCAS;
unsigned debugLevel = 0u;
float executionTime;
aitBool forever = aitTrue;
int i;
pCAS = new exServer(32u,5u,500u);
if (!pCAS) {
return (-1);
}
for (i=1; i<argc; i++) {
if (sscanf(argv[i], "-d %u", &debugLevel)==1) {
continue;
}
if (sscanf(argv[i],"-t %f", &executionTime)==1) {
forever = aitFalse;
continue;
}
printf ("usage: %s -d<debug level> -t<execution time>\n",
argv[0]);
return (1);
}
pCAS->setDebugLevel(debugLevel);
if (forever) {
osiTime delay(1000u,0u);
//
// loop here forever
//
while (aitTrue) {
fileDescriptorManager.process(delay);
}
}
else {
osiTime total(executionTime);
osiTime delay(osiTime::getCurrent() - begin);
//
// loop here untime the specified execution time
// expires
//
while (delay < total) {
fileDescriptorManager.process(delay);
delay = osiTime::getCurrent() - begin;
}
}
delete pCAS;
return (0);
}
+26
View File
@@ -0,0 +1,26 @@
//
// $Id$
//
// Explcit instantiation of template instances used by the
// example server
//
//
#include "exServer.h"
#include "gddAppFuncTable.cc"
//
// Sun C++ 4.1 still appears to be lacking support in this area
//
#if !defined(__SUNPRO_CC)
//
// From Stroustrups's "The C++ Programming Language"
// Appendix A: r.14.9
//
// This explicitly instantiates the template class's
// member functions into "templInst.o"
//
template class gddAppFuncTable <exPV>;
#endif
+846
View File
@@ -0,0 +1,846 @@
file {
name="test.dl"
}
display {
magic="305419896"
majv="2"
mnrv="2"
ndyng="0"
npc="5"
nstr="8"
ndynamic="12"
nplot="0"
nrd="0"
nes="0"
nkd="0"
object {
x="0"
y="0"
width="421"
height="306"
}
clr="0"
bclr="1"
nwords_dspy="1106"
nwords_sta="28"
nwords_cmap="36"
nwords_crules="106"
odyng="306"
osta="278"
odynamic="306"
oplot="1106"
ord="1106"
oes="1106"
okd="1106"
opc="58"
ostr="88"
ocmap="136"
ocrules="172"
style="solid"
fill="outline"
width="0"
clrmod="static"
vismod="static"
RISC_pad1="0"
RISC_pad2="0"
clrrule="alarm"
pv=""
cmap=""
}
"<<color map>>" {
ncolors="8"
dl_color {
r="255"
g="255"
b="255"
inten="255"
blink="off"
RISCpad="128"
}
dl_color {
r="0"
g="0"
b="0"
inten="0"
blink="off"
RISCpad="75"
}
dl_color {
r="255"
g="0"
b="0"
inten="255"
blink="off"
RISCpad="-14684"
}
dl_color {
r="255"
g="0"
b="0"
inten="255"
blink="on"
RISCpad="14744"
}
dl_color {
r="255"
g="255"
b="0"
inten="255"
blink="off"
RISCpad="-16536"
}
dl_color {
r="255"
g="255"
b="0"
inten="255"
blink="on"
RISCpad="-15536"
}
dl_color {
r="0"
g="0"
b="255"
inten="255"
blink="off"
RISCpad="-28408"
}
dl_color {
r="0"
g="0"
b="255"
inten="255"
blink="on"
RISCpad="0"
}
}
"<<color rules>>" {
nrules="1"
dl_color_rule {
name="alarm"
info[0] {
chan="$(C).SEVR"
value="MAJOR"
connector="use"
comparator="equals"
clr="2"
RISCpad="0"
}
info[1] {
chan="$(C).SEVR"
value="MINOR"
connector="use"
comparator="equals"
clr="4"
RISCpad="127"
}
info[2] {
chan="$(C).SEVR"
value="INFO"
connector="use"
comparator="equals"
clr="6"
RISCpad="44"
}
info[3] {
chan=""
value=""
connector="use"
comparator="equals"
clr="1"
RISCpad="-128"
}
info[4] {
chan=""
value=""
connector="use"
comparator="equals"
clr="1"
RISCpad="-1"
}
info[5] {
chan=""
value=""
connector="use"
comparator="equals"
clr="1"
RISCpad="-104"
}
info[6] {
chan=""
value=""
connector="use"
comparator="equals"
clr="1"
RISCpad="-1"
}
info[7] {
chan=""
value=""
connector="use"
comparator="equals"
clr="1"
RISCpad="8"
}
info[8] {
chan=""
value=""
connector="use"
comparator="equals"
clr="1"
RISCpad="120"
}
info[9] {
chan=""
value=""
connector="use"
comparator="equals"
clr="1"
RISCpad="1"
}
info[10] {
chan=""
value=""
connector="use"
comparator="equals"
clr="1"
RISCpad="7"
}
info[11] {
chan=""
value=""
connector="use"
comparator="equals"
clr="1"
RISCpad="19"
}
info[12] {
chan=""
value=""
connector="use"
comparator="equals"
clr="1"
RISCpad="48"
}
info[13] {
chan=""
value=""
connector="use"
comparator="equals"
clr="1"
RISCpad="28"
}
info[14] {
chan=""
value=""
connector="use"
comparator="equals"
clr="1"
RISCpad="-88"
}
info[15] {
chan=""
value=""
connector="use"
comparator="equals"
clr="1"
RISCpad="0"
}
fg_enable="on"
bg_enable="on"
default_fg="0"
default_bg="1"
}
}
"<<basic attribute>>" {
attr {
clr="0"
style="solid"
fill="outline"
width="0"
}
}
"text" {
object {
x="44"
y="16"
width="104"
height="14"
groupid="0"
}
textix="Sync"
align="horiz. left"
RISC_pad="0"
}
"text" {
object {
x="260"
y="13"
width="92"
height="17"
groupid="0"
}
textix="Async"
align="horiz. left"
RISC_pad="0"
}
"indicator" {
object {
x="15"
y="88"
width="170"
height="22"
groupid="0"
}
monitor {
chan="fred"
clr="0"
bclr="1"
label="limits"
clrmod="static"
rulechan[0] = ""
rulechan[1] = ""
rulechan[2] = ""
rulechan[3] = ""
rulechan[4] = ""
rulechan[5] = ""
rulechan[6] = ""
rulechan[7] = ""
rulechan[8] = ""
rulechan[9] = ""
rulechan[10] = ""
rulechan[11] = ""
rulechan[12] = ""
rulechan[13] = ""
rulechan[14] = ""
rulechan[15] = ""
clrrule="alarm"
clrargs=""
rulecolorbg="0"
rulecolorfg="0"
hdl="0"
ldl="0"
prec="0"
newunits=""
units="none"
decorate="none"
convertFunc=""
convertParams=""
}
direction="down"
RISC_pad="0"
}
"text update" {
object {
x="16"
y="133"
width="169"
height="17"
groupid="0"
}
monitor {
chan="fred"
clr="0"
bclr="1"
label="none"
clrmod="static"
rulechan[0] = ""
rulechan[1] = ""
rulechan[2] = ""
rulechan[3] = ""
rulechan[4] = ""
rulechan[5] = ""
rulechan[6] = ""
rulechan[7] = ""
rulechan[8] = ""
rulechan[9] = ""
rulechan[10] = ""
rulechan[11] = ""
rulechan[12] = ""
rulechan[13] = ""
rulechan[14] = ""
rulechan[15] = ""
clrrule="alarm"
clrargs=""
rulecolorbg="0"
rulecolorfg="0"
hdl="0"
ldl="0"
prec="0"
newunits=""
units="append"
decorate="none"
convertFunc=""
convertParams=""
}
align="horiz. left"
format="decimal"
}
"valuator" {
object {
x="15"
y="43"
width="168"
height="26"
groupid="0"
}
control {
chan="fred"
clr="0"
bclr="1"
label="none"
clrmod="static"
rulechan[0] = ""
rulechan[1] = ""
rulechan[2] = ""
rulechan[3] = ""
rulechan[4] = ""
rulechan[5] = ""
rulechan[6] = ""
rulechan[7] = ""
rulechan[8] = ""
rulechan[9] = ""
rulechan[10] = ""
rulechan[11] = ""
rulechan[12] = ""
rulechan[13] = ""
rulechan[14] = ""
rulechan[15] = ""
clrrule="alarm"
clrargs=""
rulecolorbg="0"
rulecolorfg="0"
hdl="0"
ldl="0"
prec="0"
newunits=""
units="none"
decorate="none"
convertFunc=""
convertParams=""
}
direction="down"
gain="coarse"
sendMode="send on motion"
increment="0"
}
"indicator" {
object {
x="215"
y="81"
width="170"
height="30"
groupid="0"
}
monitor {
chan="freddy"
clr="0"
bclr="1"
label="limits"
clrmod="static"
rulechan[0] = ""
rulechan[1] = ""
rulechan[2] = ""
rulechan[3] = ""
rulechan[4] = ""
rulechan[5] = ""
rulechan[6] = ""
rulechan[7] = ""
rulechan[8] = ""
rulechan[9] = ""
rulechan[10] = ""
rulechan[11] = ""
rulechan[12] = ""
rulechan[13] = ""
rulechan[14] = ""
rulechan[15] = ""
clrrule="alarm"
clrargs=""
rulecolorbg="0"
rulecolorfg="0"
hdl="0"
ldl="0"
prec="0"
newunits=""
units="none"
decorate="none"
convertFunc=""
convertParams=""
}
direction="down"
RISC_pad="0"
}
"text update" {
object {
x="216"
y="133"
width="171"
height="18"
groupid="0"
}
monitor {
chan="freddy"
clr="0"
bclr="1"
label="none"
clrmod="static"
rulechan[0] = ""
rulechan[1] = ""
rulechan[2] = ""
rulechan[3] = ""
rulechan[4] = ""
rulechan[5] = ""
rulechan[6] = ""
rulechan[7] = ""
rulechan[8] = ""
rulechan[9] = ""
rulechan[10] = ""
rulechan[11] = ""
rulechan[12] = ""
rulechan[13] = ""
rulechan[14] = ""
rulechan[15] = ""
clrrule="alarm"
clrargs=""
rulecolorbg="0"
rulecolorfg="0"
hdl="0"
ldl="0"
prec="0"
newunits=""
units="append"
decorate="none"
convertFunc=""
convertParams=""
}
align="horiz. left"
format="decimal"
}
"valuator" {
object {
x="215"
y="43"
width="168"
height="28"
groupid="0"
}
control {
chan="freddy"
clr="0"
bclr="1"
label="none"
clrmod="static"
rulechan[0] = ""
rulechan[1] = ""
rulechan[2] = ""
rulechan[3] = ""
rulechan[4] = ""
rulechan[5] = ""
rulechan[6] = ""
rulechan[7] = ""
rulechan[8] = ""
rulechan[9] = ""
rulechan[10] = ""
rulechan[11] = ""
rulechan[12] = ""
rulechan[13] = ""
rulechan[14] = ""
rulechan[15] = ""
clrrule="alarm"
clrargs=""
rulecolorbg="0"
rulecolorfg="0"
hdl="0"
ldl="0"
prec="0"
newunits=""
units="none"
decorate="none"
convertFunc=""
convertParams=""
}
direction="down"
gain="coarse"
sendMode="send on motion"
increment="0"
}
"indicator" {
object {
x="16"
y="225"
width="171"
height="19"
groupid="0"
}
monitor {
chan="jane"
clr="0"
bclr="1"
label="limits"
clrmod="static"
rulechan[0] = ""
rulechan[1] = ""
rulechan[2] = ""
rulechan[3] = ""
rulechan[4] = ""
rulechan[5] = ""
rulechan[6] = ""
rulechan[7] = ""
rulechan[8] = ""
rulechan[9] = ""
rulechan[10] = ""
rulechan[11] = ""
rulechan[12] = ""
rulechan[13] = ""
rulechan[14] = ""
rulechan[15] = ""
clrrule="alarm"
clrargs=""
rulecolorbg="0"
rulecolorfg="0"
hdl="0"
ldl="0"
prec="0"
newunits=""
units="none"
decorate="none"
convertFunc=""
convertParams=""
}
direction="down"
RISC_pad="0"
}
"text update" {
object {
x="17"
y="259"
width="170"
height="20"
groupid="0"
}
monitor {
chan="jane"
clr="0"
bclr="1"
label="none"
clrmod="static"
rulechan[0] = ""
rulechan[1] = ""
rulechan[2] = ""
rulechan[3] = ""
rulechan[4] = ""
rulechan[5] = ""
rulechan[6] = ""
rulechan[7] = ""
rulechan[8] = ""
rulechan[9] = ""
rulechan[10] = ""
rulechan[11] = ""
rulechan[12] = ""
rulechan[13] = ""
rulechan[14] = ""
rulechan[15] = ""
clrrule="alarm"
clrargs=""
rulecolorbg="0"
rulecolorfg="0"
hdl="0"
ldl="0"
prec="0"
newunits=""
units="append"
decorate="none"
convertFunc=""
convertParams=""
}
align="horiz. left"
format="decimal"
}
"valuator" {
object {
x="15"
y="187"
width="170"
height="19"
groupid="0"
}
control {
chan="jane"
clr="0"
bclr="1"
label="none"
clrmod="static"
rulechan[0] = ""
rulechan[1] = ""
rulechan[2] = ""
rulechan[3] = ""
rulechan[4] = ""
rulechan[5] = ""
rulechan[6] = ""
rulechan[7] = ""
rulechan[8] = ""
rulechan[9] = ""
rulechan[10] = ""
rulechan[11] = ""
rulechan[12] = ""
rulechan[13] = ""
rulechan[14] = ""
rulechan[15] = ""
clrrule="alarm"
clrargs=""
rulecolorbg="0"
rulecolorfg="0"
hdl="0"
ldl="0"
prec="0"
newunits=""
units="none"
decorate="none"
convertFunc=""
convertParams=""
}
direction="down"
gain="coarse"
sendMode="send on motion"
increment="0"
}
"indicator" {
object {
x="219"
y="218"
width="173"
height="23"
groupid="0"
}
monitor {
chan="janet"
clr="0"
bclr="1"
label="limits"
clrmod="static"
rulechan[0] = ""
rulechan[1] = ""
rulechan[2] = ""
rulechan[3] = ""
rulechan[4] = ""
rulechan[5] = ""
rulechan[6] = ""
rulechan[7] = ""
rulechan[8] = ""
rulechan[9] = ""
rulechan[10] = ""
rulechan[11] = ""
rulechan[12] = ""
rulechan[13] = ""
rulechan[14] = ""
rulechan[15] = ""
clrrule="alarm"
clrargs=""
rulecolorbg="0"
rulecolorfg="0"
hdl="0"
ldl="0"
prec="0"
newunits=""
units="none"
decorate="none"
convertFunc=""
convertParams=""
}
direction="down"
RISC_pad="0"
}
"text update" {
object {
x="220"
y="257"
width="174"
height="20"
groupid="0"
}
monitor {
chan="janet"
clr="0"
bclr="1"
label="none"
clrmod="static"
rulechan[0] = ""
rulechan[1] = ""
rulechan[2] = ""
rulechan[3] = ""
rulechan[4] = ""
rulechan[5] = ""
rulechan[6] = ""
rulechan[7] = ""
rulechan[8] = ""
rulechan[9] = ""
rulechan[10] = ""
rulechan[11] = ""
rulechan[12] = ""
rulechan[13] = ""
rulechan[14] = ""
rulechan[15] = ""
clrrule="alarm"
clrargs=""
rulecolorbg="0"
rulecolorfg="0"
hdl="0"
ldl="0"
prec="0"
newunits=""
units="append"
decorate="none"
convertFunc=""
convertParams=""
}
align="horiz. left"
format="decimal"
}
"valuator" {
object {
x="219"
y="188"
width="171"
height="21"
groupid="0"
}
control {
chan="janet"
clr="0"
bclr="1"
label="none"
clrmod="static"
rulechan[0] = ""
rulechan[1] = ""
rulechan[2] = ""
rulechan[3] = ""
rulechan[4] = ""
rulechan[5] = ""
rulechan[6] = ""
rulechan[7] = ""
rulechan[8] = ""
rulechan[9] = ""
rulechan[10] = ""
rulechan[11] = ""
rulechan[12] = ""
rulechan[13] = ""
rulechan[14] = ""
rulechan[15] = ""
clrrule="alarm"
clrargs=""
rulecolorbg="0"
rulecolorfg="0"
hdl="0"
ldl="0"
prec="0"
newunits=""
units="none"
decorate="none"
convertFunc=""
convertParams=""
}
direction="down"
gain="coarse"
sendMode="send on motion"
increment="0"
}
+73
View File
@@ -0,0 +1,73 @@
//
// $Id$
// Author: Jeff HIll (LANL)
//
// $Log$
// Revision 1.2 1996/09/16 18:22:09 jhill
// added cvs log entries
//
//
#include <exServer.h>
#include <taskLib.h>
//
// so we can call this from the vxWorks shell
//
extern "C" {
exServer *pExampleCAS;
//
// excas ()
// (vxWorks example server entry point)
//
int excas (unsigned debugLevel, unsigned delaySec)
{
osiTime begin(osiTime::getCurrent());
exServer *pCAS;
pCAS = new exServer(32u,5u,500u);
if (!pCAS) {
return (-1);
}
pCAS->setDebugLevel(debugLevel);
pExampleCAS = pCAS;
if (delaySec==0u) {
//
// loop here forever
//
while (1) {
taskDelay(10);
}
}
else {
osiTime total( ((float)delaySec) );
osiTime delay(osiTime::getCurrent() - begin);
//
// loop here untill the specified execution time
// expires
//
while (delay < total) {
taskDelay(10);
delay = osiTime::getCurrent() - begin;
}
}
pCAS->show(debugLevel);
pExampleCAS = NULL;
delete pCAS;
return 0;
}
int excasShow(unsigned level)
{
if (pExampleCAS!=NULL) {
pExampleCAS->show(level);
}
return 0;
}
} // extern "C"