improved structure and thread safety

This commit is contained in:
Jeff Hill
2003-02-12 19:06:15 +00:00
parent 234c515b05
commit 644e6eb273
78 changed files with 2692 additions and 4957 deletions

View File

@@ -8,12 +8,12 @@
* in file LICENSE that is included with this distribution.
\*************************************************************************/
//
// Example EPICS CA directory server
// Example EPICS CA directory server
//
//
// caServer
// |
// directoryServer
// caServer
// |
// directoryServer
//
//
@@ -27,6 +27,7 @@
//
// EPICS
//
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
#define caNetAddrSock
#include "casdef.h"
#include "epicsAssert.h"
@@ -34,7 +35,7 @@
#ifndef NELEMENTS
# define NELEMENTS(A) (sizeof(A)/sizeof(A[0]))
# define NELEMENTS(A) (sizeof(A)/sizeof(A[0]))
#endif
class directoryServer;
@@ -44,24 +45,24 @@ class directoryServer;
//
class pvInfo {
public:
pvInfo (const char *pNameIn, sockaddr_in addrIn) :
addr(addrIn), pNext(pvInfo::pFirst)
{
pvInfo::pFirst = this;
this->pName = new char [strlen(pNameIn)+1u];
assert(this->pName);
strcpy(this->pName, pNameIn);
}
const struct sockaddr_in getAddr() const { return this->addr; }
const char *getName () const { return this->pName; }
const pvInfo *getNext () const { return this->pNext; }
static const pvInfo *getFirst () { return pvInfo::pFirst; }
pvInfo (const char *pNameIn, sockaddr_in addrIn) :
addr(addrIn), pNext(pvInfo::pFirst)
{
pvInfo::pFirst = this;
this->pName = new char [strlen(pNameIn)+1u];
assert(this->pName);
strcpy(this->pName, pNameIn);
}
const struct sockaddr_in getAddr() const { return this->addr; }
const char *getName () const { return this->pName; }
const pvInfo *getNext () const { return this->pNext; }
static const pvInfo *getFirst () { return pvInfo::pFirst; }
private:
struct sockaddr_in addr;
char *pName;
const pvInfo *pNext;
static const pvInfo *pFirst;
struct sockaddr_in addr;
char * pName;
const pvInfo * pNext;
static const pvInfo * pFirst;
};
//
@@ -77,41 +78,39 @@ private:
class pvEntry // X aCC 655
: public stringId, public tsSLNode<pvEntry> {
public:
pvEntry (const pvInfo &infoIn, directoryServer &casIn,
const char *pAliasName) :
stringId(pAliasName), info(infoIn), cas(casIn)
{
assert(this->stringId::resourceName()!=NULL);
}
pvEntry (const pvInfo &infoIn, directoryServer &casIn,
const char *pAliasName) :
stringId(pAliasName), info(infoIn), cas(casIn)
{
assert(this->stringId::resourceName()!=NULL);
}
inline ~pvEntry();
inline ~pvEntry();
const pvInfo &getInfo() const { return this->info; }
inline void destroy ();
const pvInfo &getInfo() const { return this->info; }
inline void destroy ();
private:
const pvInfo &info;
directoryServer &cas;
const pvInfo &info;
directoryServer &cas;
};
//
// directoryServer
//
class directoryServer : public caServer {
public:
directoryServer (const char * const pvPrefix, unsigned aliasCount);
~directoryServer();
void show (unsigned level) const;
pvExistReturn pvExistTest (const casCtx&, const char *pPVName);
directoryServer ( const char * const pvPrefix, unsigned aliasCount );
~directoryServer();
void show ( unsigned level ) const;
pvExistReturn pvExistTest ( const casCtx&, const char *pPVName );
void installAliasName (const pvInfo &info, const char *pAliasName);
inline void removeAliasName(pvEntry &entry);
void installAliasName ( const pvInfo &info, const char *pAliasName );
inline void removeAliasName ( pvEntry &entry );
private:
resTable<pvEntry,stringId> stringResTbl;
resTable < pvEntry, stringId > stringResTbl;
};
@@ -120,9 +119,9 @@ private:
//
inline void directoryServer::removeAliasName(pvEntry &entry)
{
pvEntry *pE;
pE = this->stringResTbl.remove(entry);
assert(pE = &entry);
pvEntry *pE;
pE = this->stringResTbl.remove(entry);
assert(pE = &entry);
}
//
@@ -130,7 +129,7 @@ inline void directoryServer::removeAliasName(pvEntry &entry)
//
inline pvEntry::~pvEntry()
{
this->cas.removeAliasName(*this);
this->cas.removeAliasName(*this);
}
//
@@ -138,9 +137,9 @@ inline pvEntry::~pvEntry()
//
inline void pvEntry::destroy ()
{
//
// always created with new
//
delete this;
//
// always created with new
//
delete this;
}

View File

@@ -13,10 +13,8 @@
#include "directoryServer.h"
#include "fdManager.h"
#define LOCAL static
LOCAL int parseDirectoryFile (const char *pFileName);
LOCAL int parseDirectoryFP (FILE *pf, const char *pFileName);
static int parseDirectoryFile (const char *pFileName);
static int parseDirectoryFP (FILE *pf, const char *pFileName);
#ifndef INADDR_NONE
#define INADDR_NONE (~0ul)
@@ -109,7 +107,7 @@ extern int main (int argc, const char **argv)
// <PV name> <host name or dotted ip address> [<optional IP port number>]
//
//
LOCAL int parseDirectoryFile (const char *pFileName)
static int parseDirectoryFile (const char *pFileName)
{
FILE *pf;
@@ -139,7 +137,7 @@ LOCAL int parseDirectoryFile (const char *pFileName)
// <PV name> <host name or dotted ip address> [<optional IP port number>]
//
//
LOCAL int parseDirectoryFP (FILE *pf, const char *pFileName)
static int parseDirectoryFP (FILE *pf, const char *pFileName)
{
pvInfo *pPVI;
char pvNameStr[128];
@@ -193,8 +191,8 @@ LOCAL int parseDirectoryFP (FILE *pf, const char *pFileName)
ipa.sin_port = 0u; // use the default CA server port
}
pPVI = new pvInfo (pvNameStr, ipa);
if (!pPVI) {
pPVI = new pvInfo ( pvNameStr, ipa );
if ( ! pPVI ) {
fprintf (stderr, "Unable to allocate space for a new PV in \"%s\" with PV=\"%s\" host=\"%s\"\n",
pFileName, pvNameStr, hostNameStr);
return -1;

View File

@@ -29,7 +29,7 @@ caStatus exAsyncPV::read (const casCtx &ctx, gdd &valueIn)
this->simultAsychIOCount++;
pIO = new exAsyncReadIO ( ctx, *this, valueIn );
pIO = new exAsyncReadIO ( this->cas, ctx, *this, valueIn );
if (!pIO) {
return S_casApp_noMemory;
}
@@ -51,7 +51,7 @@ caStatus exAsyncPV::write ( const casCtx &ctx, const gdd &valueIn )
this->simultAsychIOCount++;
pIO = new exAsyncWriteIO ( ctx, *this, valueIn );
pIO = new exAsyncWriteIO ( this->cas, ctx, *this, valueIn );
if ( ! pIO ) {
return S_casApp_noMemory;
}
@@ -62,10 +62,10 @@ caStatus exAsyncPV::write ( const casCtx &ctx, const gdd &valueIn )
//
// exAsyncWriteIO::exAsyncWriteIO()
//
exAsyncWriteIO::exAsyncWriteIO ( const casCtx &ctxIn, exAsyncPV &pvIn,
const gdd &valueIn ) :
exAsyncWriteIO::exAsyncWriteIO ( exServer & cas,
const casCtx & ctxIn, exAsyncPV & pvIn, const gdd & valueIn ) :
casAsyncWriteIO ( ctxIn ), pv ( pvIn ),
timer ( pvIn.getCAS()->createTimer () ), pValue(valueIn)
timer ( cas.createTimer () ), pValue(valueIn)
{
this->timer.start ( *this, 0.1 );
}
@@ -76,9 +76,7 @@ exAsyncWriteIO::exAsyncWriteIO ( const casCtx &ctxIn, exAsyncPV &pvIn,
exAsyncWriteIO::~exAsyncWriteIO()
{
this->pv.removeIO();
if ( this->pv.getCAS() ) {
this->timer.destroy ();
}
this->timer.destroy ();
}
//
@@ -88,7 +86,7 @@ exAsyncWriteIO::~exAsyncWriteIO()
epicsTimerNotify::expireStatus exAsyncWriteIO::expire ( const epicsTime & /* currentTime */ )
{
caStatus status;
status = this->pv.update ( this->pValue );
status = this->pv.update ( *this->pValue );
this->postIOCompletion ( status );
return noRestart;
}
@@ -96,10 +94,10 @@ epicsTimerNotify::expireStatus exAsyncWriteIO::expire ( const epicsTime & /* cur
//
// exAsyncReadIO::exAsyncReadIO()
//
exAsyncReadIO::exAsyncReadIO ( const casCtx &ctxIn, exAsyncPV &pvIn,
gdd &protoIn ) :
exAsyncReadIO::exAsyncReadIO ( exServer & cas, const casCtx & ctxIn,
exAsyncPV & pvIn, gdd & protoIn ) :
casAsyncReadIO ( ctxIn ), pv ( pvIn ),
timer ( pvIn.getCAS()->createTimer() ), pProto ( protoIn )
timer ( cas.createTimer() ), pProto ( protoIn )
{
this->timer.start ( *this, 0.1 );
}
@@ -110,9 +108,7 @@ exAsyncReadIO::exAsyncReadIO ( const casCtx &ctxIn, exAsyncPV &pvIn,
exAsyncReadIO::~exAsyncReadIO()
{
this->pv.removeIO ();
if ( this->pv.getCAS() ) {
this->timer.destroy ();
}
this->timer.destroy ();
}

View File

@@ -30,8 +30,10 @@ class exFixedStringDestructor: public gddDestructor {
//
// exPV::exPV()
//
exPV::exPV ( pvInfo &setup, bool preCreateFlag, bool scanOnIn ) :
timer ( this->getCAS()->createTimer() ),
exPV::exPV ( exServer & casIn, pvInfo & setup,
bool preCreateFlag, bool scanOnIn ) :
cas ( casIn ),
timer ( cas.createTimer() ),
info ( setup ),
interest ( false ),
preCreate ( preCreateFlag ),
@@ -77,17 +79,14 @@ void exPV::destroy()
//
// exPV::update()
//
caStatus exPV::update(smartConstGDDPointer pValueIn)
caStatus exPV::update ( const gdd & valueIn )
{
caServer *pCAS = this->getCAS();
caStatus cas;
# if DEBUG
printf("Setting %s too:\n", this->info.getName().string());
valueIn.dump();
# endif
cas = this->updateValue (pValueIn);
caStatus cas = this->updateValue ( valueIn );
if ( cas || ( ! this->pValue.valid() ) ) {
return cas;
}
@@ -95,9 +94,10 @@ caStatus exPV::update(smartConstGDDPointer pValueIn)
//
// post a value change event
//
if (this->interest==true && pCAS!=NULL) {
casEventMask select(pCAS->valueEventMask()|pCAS->logEventMask());
this->postEvent (select, *this->pValue);
caServer * pCAS = this->getCAS();
if ( this->interest == true && pCAS != NULL ) {
casEventMask select ( pCAS->valueEventMask() | pCAS->logEventMask() );
this->postEvent ( select, valueIn );
}
return S_casApp_success;
@@ -129,16 +129,13 @@ aitEnum exPV::bestExternalType () const
//
// exPV::interestRegister()
//
caStatus exPV::interestRegister()
caStatus exPV::interestRegister ()
{
caServer *pCAS = this->getCAS();
if ( ! pCAS ) {
if ( ! this->getCAS() ) {
return S_casApp_success;
}
this->interest = true;
if ( this->scanOn && this->getScanPeriod() > 0.0 &&
this->getScanPeriod() < this->timer.getExpireDelay() ) {
this->timer.start ( *this, this->getScanPeriod() );
@@ -174,7 +171,7 @@ void exPV::show ( unsigned level ) const
//
// exPV::initFT()
//
void exPV::initFT()
void exPV::initFT ()
{
if ( exPV::hasBeenInitialized ) {
return;
@@ -203,7 +200,7 @@ void exPV::initFT()
//
// exPV::getPrecision()
//
caStatus exPV::getPrecision(gdd &prec)
caStatus exPV::getPrecision ( gdd & prec )
{
prec.put(4u);
return S_cas_success;
@@ -212,7 +209,7 @@ caStatus exPV::getPrecision(gdd &prec)
//
// exPV::getHighLimit()
//
caStatus exPV::getHighLimit(gdd &value)
caStatus exPV::getHighLimit ( gdd & value )
{
value.put(info.getHopr());
return S_cas_success;
@@ -221,7 +218,7 @@ caStatus exPV::getHighLimit(gdd &value)
//
// exPV::getLowLimit()
//
caStatus exPV::getLowLimit(gdd &value)
caStatus exPV::getLowLimit ( gdd & value )
{
value.put(info.getLopr());
return S_cas_success;
@@ -230,7 +227,7 @@ caStatus exPV::getLowLimit(gdd &value)
//
// exPV::getUnits()
//
caStatus exPV::getUnits(gdd &units)
caStatus exPV::getUnits( gdd & units )
{
aitString str("furlongs", aitStrRefConstImortal);
units.put(str);
@@ -283,7 +280,7 @@ caStatus exPV::getEnums ( gdd & enumsIn )
//
// exPV::getValue()
//
caStatus exPV::getValue(gdd &value)
caStatus exPV::getValue ( gdd & value )
{
caStatus status;
@@ -309,18 +306,18 @@ caStatus exPV::getValue(gdd &value)
// exPV::write()
// (synchronous default)
//
caStatus exPV::write (const casCtx &, const gdd &valueIn)
caStatus exPV::write ( const casCtx &, const gdd & valueIn )
{
return this->update (valueIn);
return this->update ( valueIn );
}
//
// exPV::read()
// (synchronous default)
//
caStatus exPV::read (const casCtx &, gdd &protoIn)
caStatus exPV::read ( const casCtx &, gdd & protoIn )
{
return this->ft.read (*this, protoIn);
return this->ft.read ( *this, protoIn );
}
//
@@ -328,11 +325,11 @@ caStatus exPV::read (const casCtx &, gdd &protoIn)
//
// for access control - optional
//
casChannel *exPV::createChannel (const casCtx &ctx,
casChannel *exPV::createChannel ( const casCtx &ctx,
const char * const /* pUserName */,
const char * const /* pHostName */)
const char * const /* pHostName */ )
{
return new exChannel (ctx);
return new exChannel ( ctx );
}
//
@@ -340,7 +337,7 @@ casChannel *exPV::createChannel (const casCtx &ctx,
//
// special gddDestructor guarantees same form of new and delete
//
void exFixedStringDestructor::run (void *pUntyped)
void exFixedStringDestructor::run ( void * pUntyped )
{
aitFixedString *ps = (aitFixedString *) pUntyped;
delete [] ps;

View File

@@ -49,9 +49,9 @@ void exScalarPV::scan()
// throughput under sunos4 because gettimeofday() is
// slow)
//
this->currentTime = epicsTime::getCurrent();
this->currentTime = epicsTime::getCurrent ();
pDD = new gddScalar (gddAppType_value, aitEnumFloat64);
pDD = new gddScalar ( gddAppType_value, aitEnumFloat64 );
if ( ! pDD.valid () ) {
return;
}
@@ -59,27 +59,27 @@ void exScalarPV::scan()
//
// smart pointer class manages reference count after this point
//
gddStatus = pDD->unreference();
assert (!gddStatus);
gddStatus = pDD->unreference ();
assert ( ! gddStatus );
radians = (rand () * 2.0 * myPI)/RAND_MAX;
radians = ( rand () * 2.0 * myPI ) / RAND_MAX;
if ( this->pValue.valid () ) {
this->pValue->getConvert(newValue);
}
else {
newValue = 0.0f;
}
newValue += (float) (sin (radians) / 10.0);
limit = (float) this->info.getHopr();
newValue = tsMin (newValue, limit);
limit = (float) this->info.getLopr();
newValue = tsMax (newValue, limit);
newValue += (float) ( sin (radians) / 10.0 );
limit = (float) this->info.getHopr ();
newValue = tsMin ( newValue, limit );
limit = (float) this->info.getLopr ();
newValue = tsMax ( newValue, limit );
*pDD = newValue;
aitTimeStamp gddts = this->currentTime;
pDD->setTimeStamp (&gddts);
status = this->update (pDD);
pDD->setTimeStamp ( & gddts );
status = this->update ( *pDD );
if (status!=S_casApp_success) {
errMessage (status, "scalar scan update failed\n");
errMessage ( status, "scalar scan update failed\n" );
}
}
@@ -95,21 +95,25 @@ void exScalarPV::scan()
// result in each value change events retaining an
// independent value on the event queue.
//
caStatus exScalarPV::updateValue (smartConstGDDPointer pValueIn)
caStatus exScalarPV::updateValue ( const gdd & valueIn )
{
if ( ! pValueIn.valid () ) {
return S_casApp_undefined;
}
//
// Really no need to perform this check since the
// server lib verifies that all requests are in range
//
if (!pValueIn->isScalar()) {
if ( ! valueIn.isScalar() ) {
return S_casApp_outOfBounds;
}
this->pValue = pValueIn;
if ( ! pValue.valid () ) {
this->pValue = new gddScalar (
gddAppType_value, aitEnumFloat64 );
if ( ! pValue.valid () ) {
return S_casApp_noMemory;
}
}
this->pValue->put ( & valueIn );
return S_casApp_success;
}

View File

@@ -44,9 +44,10 @@ pvInfo exServer::bloaty (-1.0, "bloaty", 10.0f, -10.0f, aitEnumFloat64, excasIoS
// exServer::exServer()
//
exServer::exServer ( const char * const pvPrefix,
unsigned aliasCount, bool scanOnIn ) :
simultAsychIOCount (0u),
scanOn (scanOnIn)
unsigned aliasCount, bool scanOnIn,
bool asyncScan ) :
pTimerQueue ( 0 ), simultAsychIOCount ( 0u ),
scanOn ( scanOnIn )
{
unsigned i;
exPV *pPV;
@@ -58,6 +59,16 @@ exServer::exServer ( const char * const pvPrefix,
exPV::initFT();
if ( asyncScan ) {
unsigned timerPriotity;
epicsThreadBooleanStatus etbs = epicsThreadLowestPriorityLevelAbove (
epicsThreadGetPrioritySelf (), & timerPriotity );
if ( etbs != epicsThreadBooleanStatusSuccess ) {
timerPriotity = epicsThreadGetPrioritySelf ();
}
this->pTimerQueue = & epicsTimerQueueActive::allocate ( false, timerPriotity );
}
//
// pre-create all of the simple PVs that this server will export
//
@@ -236,10 +247,31 @@ pvAttachReturn exServer::pvAttach // X aCC 361
}
}
//
// exServer::setDebugLevel ()
//
void exServer::setDebugLevel ( unsigned level )
{
this->caServer::setDebugLevel ( level );
}
//
// exServer::createTimer ()
//
class epicsTimer & exServer::createTimer ()
{
if ( this->pTimerQueue ) {
return this->pTimerQueue->createTimer ();
}
else {
return this->caServer::createTimer ();
}
}
//
// pvInfo::createPV()
//
exPV *pvInfo::createPV ( exServer & /*cas*/,
exPV *pvInfo::createPV ( exServer & cas,
bool preCreateFlag, bool scanOn )
{
if (this->pPV) {
@@ -256,10 +288,10 @@ exPV *pvInfo::createPV ( exServer & /*cas*/,
if (this->elementCount==1u) {
switch (this->ioType){
case excasIoSync:
pNewPV = new exScalarPV ( *this, preCreateFlag, scanOn );
pNewPV = new exScalarPV ( cas, *this, preCreateFlag, scanOn );
break;
case excasIoAsync:
pNewPV = new exAsyncPV ( *this, preCreateFlag, scanOn );
pNewPV = new exAsyncPV ( cas, *this, preCreateFlag, scanOn );
break;
default:
pNewPV = NULL;
@@ -268,7 +300,7 @@ exPV *pvInfo::createPV ( exServer & /*cas*/,
}
else {
if ( this->ioType == excasIoSync ) {
pNewPV = new exVectorPV ( *this, preCreateFlag, scanOn );
pNewPV = new exVectorPV ( cas, *this, preCreateFlag, scanOn );
}
else {
pNewPV = NULL;

View File

@@ -38,6 +38,7 @@
//
// EPICS
//
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
#include "gddAppFuncTable.h"
#include "epicsTimer.h"
#include "casdef.h"
@@ -124,7 +125,8 @@ private:
class exPV : public casPV, public epicsTimerNotify,
public tsSLNode < exPV > {
public:
exPV ( pvInfo & setup, bool preCreateFlag, bool scanOn );
exPV ( exServer & cas, pvInfo & setup,
bool preCreateFlag, bool scanOn );
virtual ~exPV();
void show ( unsigned level ) const;
@@ -158,7 +160,7 @@ public:
//
// This gets called when the pv gets a new value
//
caStatus update ( smartConstGDDPointer pValue );
caStatus update ( const gdd & );
//
// Gets called when we add noise to the current value
@@ -190,7 +192,8 @@ public:
const char * const pHostName );
protected:
smartConstGDDPointer pValue;
smartGDDPointer pValue;
exServer & cas;
epicsTimer & timer;
pvInfo & info;
bool interest;
@@ -198,7 +201,7 @@ protected:
bool scanOn;
static epicsTime currentTime;
virtual caStatus updateValue ( smartConstGDDPointer pValue ) = 0;
virtual caStatus updateValue ( const gdd & ) = 0;
private:
@@ -229,11 +232,13 @@ private:
//
class exScalarPV : public exPV {
public:
exScalarPV ( pvInfo &setup, bool preCreateFlag, bool scanOnIn ) :
exPV ( setup, preCreateFlag, scanOnIn) {}
exScalarPV ( exServer & cas, pvInfo &setup,
bool preCreateFlag, bool scanOnIn ) :
exPV ( cas, setup,
preCreateFlag, scanOnIn) {}
void scan();
private:
caStatus updateValue (smartConstGDDPointer pValue);
caStatus updateValue ( const gdd & );
};
//
@@ -241,36 +246,45 @@ private:
//
class exVectorPV : public exPV {
public:
exVectorPV ( pvInfo &setup, bool preCreateFlag, bool scanOnIn ) :
exPV ( setup, preCreateFlag, scanOnIn) {}
exVectorPV ( exServer & cas, pvInfo &setup,
bool preCreateFlag, bool scanOnIn ) :
exPV ( cas, setup,
preCreateFlag, scanOnIn) {}
void scan();
unsigned maxDimension() const;
aitIndex maxBound (unsigned dimension) const;
private:
caStatus updateValue (smartConstGDDPointer pValue);
caStatus updateValue ( const gdd & );
};
//
// exServer
//
class exServer : public caServer {
class exServer : private caServer {
public:
exServer ( const char * const pvPrefix,
unsigned aliasCount, bool scanOn );
unsigned aliasCount, bool scanOn,
bool asyncScan );
~exServer ();
void show ( unsigned level ) const;
pvExistReturn pvExistTest ( const casCtx &, const char * pPVName );
pvAttachReturn pvAttach ( const casCtx &, const char * pPVName );
void installAliasName ( pvInfo & info, const char * pAliasName );
inline void removeAliasName ( pvEntry & entry );
void removeIO();
void removeIO ();
void removeAliasName ( pvEntry & entry );
class epicsTimer & createTimer ();
void setDebugLevel ( unsigned level );
private:
resTable < pvEntry, stringId > stringResTbl;
epicsTimerQueueActive * pTimerQueue;
unsigned simultAsychIOCount;
bool scanOn;
void installAliasName ( pvInfo & info, const char * pAliasName );
pvExistReturn pvExistTest ( const casCtx &, const char * pPVName );
pvAttachReturn pvAttach ( const casCtx &, const char * pPVName );
//
// list of pre-created PVs
//
@@ -292,7 +306,8 @@ private:
//
class exAsyncPV : public exScalarPV {
public:
exAsyncPV ( pvInfo &setup, bool preCreateFlag, bool scanOnIn );
exAsyncPV ( exServer & cas, pvInfo &setup,
bool preCreateFlag, bool scanOnIn );
caStatus read ( const casCtx & ctxIn, gdd & protoIn );
caStatus write ( const casCtx & ctxIn, const gdd & value );
void removeIO();
@@ -318,7 +333,7 @@ private:
//
class exAsyncWriteIO : public casAsyncWriteIO, public epicsTimerNotify {
public:
exAsyncWriteIO ( const casCtx & ctxIn, exAsyncPV & pvIn, const gdd & valueIn );
exAsyncWriteIO ( exServer &, const casCtx & ctxIn, exAsyncPV &, const gdd & );
~exAsyncWriteIO ();
private:
exAsyncPV & pv;
@@ -332,7 +347,7 @@ private:
//
class exAsyncReadIO : public casAsyncReadIO, public epicsTimerNotify {
public:
exAsyncReadIO ( const casCtx & ctxIn, exAsyncPV & pvIn, gdd & protoIn );
exAsyncReadIO ( exServer &, const casCtx &, exAsyncPV &, gdd & );
virtual ~exAsyncReadIO ();
private:
exAsyncPV & pv;
@@ -519,9 +534,9 @@ inline void exServer::removeIO()
}
}
inline exAsyncPV::exAsyncPV ( pvInfo & setup, bool preCreateFlag,
bool scanOnIn ) :
exScalarPV ( setup, preCreateFlag, scanOnIn ),
inline exAsyncPV::exAsyncPV ( exServer & cas, pvInfo & setup,
bool preCreateFlag, bool scanOnIn ) :
exScalarPV ( cas, setup, preCreateFlag, scanOnIn ),
simultAsychIOCount ( 0u )
{
}

View File

@@ -141,8 +141,8 @@ void exVectorPV::scan()
*(pF++) = newValue;
}
status = this->update (pDD);
if (status!=S_casApp_success) {
status = this->update ( *pDD );
if ( status != S_casApp_success ) {
errMessage (status, "vector scan update failed\n");
}
}
@@ -161,16 +161,8 @@ void exVectorPV::scan()
// this may result in too much memory consumtion on
// the event queue.
//
caStatus exVectorPV::updateValue(smartConstGDDPointer pValueIn)
caStatus exVectorPV::updateValue ( const gdd & value )
{
gddStatus gdds;
smartGDDPointer pNewValue;
exVecDestructor *pDest;
unsigned i;
if ( ! pValueIn.valid () ) {
return S_casApp_undefined;
}
//
// Check bounds of incoming request
@@ -180,50 +172,47 @@ caStatus exVectorPV::updateValue(smartConstGDDPointer pValueIn)
// Perhaps much of this is unnecessary since the
// server lib checks the bounds of all requests
//
if (pValueIn->isAtomic()) {
if (pValueIn->dimension()!=1u) {
if ( value.isAtomic()) {
if ( value.dimension() != 1u ) {
return S_casApp_badDimension;
}
const gddBounds* pb = pValueIn->getBounds();
if (pb[0u].first()!=0u) {
const gddBounds* pb = value.getBounds ();
if ( pb[0u].first() != 0u ) {
return S_casApp_outOfBounds;
}
else if (pb[0u].size()>this->info.getElementCount()) {
else if ( pb[0u].size() > this->info.getElementCount() ) {
return S_casApp_outOfBounds;
}
}
else if (!pValueIn->isScalar()) {
else if ( ! value.isScalar() ) {
//
// no containers
//
return S_casApp_outOfBounds;
}
aitFloat64 *pF;
int gddStatus;
//
// Create a new array data descriptor
// (so that old values that may be referenced on the
// event queue are not replaced)
//
pNewValue = new gddAtomic (gddAppType_value, aitEnumFloat64,
1u, this->info.getElementCount());
if ( ! pNewValue.valid () ) {
smartGDDPointer pNewValue ( new gddAtomic ( gddAppType_value, aitEnumFloat64,
1u, this->info.getElementCount() ) );
if ( ! pNewValue.valid() ) {
return S_casApp_noMemory;
}
//
// smart pointer class takes care of the reference count
// from here down
//
gddStatus = pNewValue->unreference();
assert (!gddStatus);
gddStatus gdds = pNewValue->unreference( );
assert ( ! gdds );
//
// allocate array buffer
//
pF = new aitFloat64 [this->info.getElementCount()];
aitFloat64 * pF = new aitFloat64 [this->info.getElementCount()];
if (!pF) {
return S_casApp_noMemory;
}
@@ -233,11 +222,11 @@ caStatus exVectorPV::updateValue(smartConstGDDPointer pValueIn)
// if no old values exist
//
unsigned count = this->info.getElementCount();
for ( i = 0u; i < count; i++ ) {
for ( unsigned i = 0u; i < count; i++ ) {
pF[i] = 0.0f;
}
pDest = new exVecDestructor;
exVecDestructor * pDest = new exVecDestructor;
if (!pDest) {
delete [] pF;
return S_casApp_noMemory;
@@ -247,13 +236,13 @@ caStatus exVectorPV::updateValue(smartConstGDDPointer pValueIn)
// install the buffer into the DD
// (do this before we increment pF)
//
pNewValue->putRef(pF, pDest);
pNewValue->putRef ( pF, pDest );
//
// copy in the values that they are writing
//
gdds = pNewValue->put( & (*pValueIn) );
if (gdds) {
gdds = pNewValue->put( & value );
if ( gdds ) {
return S_cas_noConvert;
}
@@ -267,8 +256,8 @@ caStatus exVectorPV::updateValue(smartConstGDDPointer pValueIn)
//
// special gddDestructor guarantees same form of new and delete
//
void exVecDestructor::run (void *pUntyped)
void exVecDestructor::run ( void *pUntyped )
{
aitFloat32 *pf = (aitFloat32 *) pUntyped;
aitFloat32 * pf = reinterpret_cast < aitFloat32 * > ( pUntyped );
delete [] pf;
}

View File

@@ -25,37 +25,40 @@ extern int main (int argc, const char **argv)
double executionTime;
char pvPrefix[128] = "";
unsigned aliasCount = 1u;
unsigned scanOnAsUnsignedInt = true;
unsigned scanOn = true;
unsigned syncScan = true;
char arraySize[64] = "";
bool scanOn;
bool forever = true;
int i;
for ( i = 1; i < argc; i++ ) {
if (sscanf(argv[i], "-d %u", &debugLevel)==1) {
if ( sscanf(argv[i], "-d %u", & debugLevel ) == 1 ) {
continue;
}
if (sscanf(argv[i],"-t %lf", &executionTime)==1) {
if ( sscanf ( argv[i],"-t %lf", & executionTime ) == 1 ) {
forever = false;
continue;
}
if (sscanf(argv[i],"-p %127s", pvPrefix)==1) {
if ( sscanf ( argv[i], "-p %127s", pvPrefix ) == 1 ) {
continue;
}
if (sscanf(argv[i],"-c %u", &aliasCount)==1) {
if ( sscanf ( argv[i],"-c %u", & aliasCount ) == 1 ) {
continue;
}
if (sscanf(argv[i],"-s %u", &scanOnAsUnsignedInt)==1) {
if ( sscanf ( argv[i],"-s %u", & scanOn ) == 1 ) {
continue;
}
if (sscanf(argv[i],"-a %63s", arraySize)==1) {
if ( sscanf ( argv[i],"-a %63s", arraySize ) == 1 ) {
continue;
}
if ( sscanf ( argv[i],"-ss %u", & syncScan ) == 1 ) {
continue;
}
printf ("\"%s\"?\n", argv[i]);
printf (
"usage: %s [-d<debug level> -t<execution time> -p<PV name prefix> "
"-c<numbered alias count> -s<1=scan on (default), 0=scan off]> "
"-a<max array size>]\n",
"-c<numbered alias count> -s<1=scan on (default), 0=scan off> "
"-ss<1=synchronous scan (default), 0=asynchronous scan>]\n",
argv[0]);
return (1);
@@ -65,15 +68,9 @@ extern int main (int argc, const char **argv)
epicsEnvSet ( "EPICS_CA_MAX_ARRAY_BYTES", arraySize );
}
if (scanOnAsUnsignedInt) {
scanOn = true;
}
else {
scanOn = false;
}
try {
pCAS = new exServer ( pvPrefix, aliasCount, scanOn );
pCAS = new exServer ( pvPrefix, aliasCount,
scanOn != 0, syncScan == 0 );
}
catch ( ... ) {
errlogPrintf ( "Server initialization error\n" );