Resync with src/cas/example/simple: "improved structure and thread safety"
This commit is contained in:
@@ -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 ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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,27 +79,25 @@ 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);
|
||||
if ( cas || ( ! this->pValue.valid() ) ) {
|
||||
return cas;
|
||||
caStatus status = this->updateValue ( valueIn );
|
||||
if ( status || ( ! this->pValue.valid() ) ) {
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// 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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -38,7 +38,9 @@
|
||||
//
|
||||
// EPICS
|
||||
//
|
||||
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
|
||||
#include "gddAppFuncTable.h"
|
||||
#include "smartGDDPointer.h"
|
||||
#include "epicsTimer.h"
|
||||
#include "casdef.h"
|
||||
#include "epicsAssert.h"
|
||||
@@ -124,7 +126,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 +161,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 +193,8 @@ public:
|
||||
const char * const pHostName );
|
||||
|
||||
protected:
|
||||
smartConstGDDPointer pValue;
|
||||
smartGDDPointer pValue;
|
||||
exServer & cas;
|
||||
epicsTimer & timer;
|
||||
pvInfo & info;
|
||||
bool interest;
|
||||
@@ -198,7 +202,7 @@ protected:
|
||||
bool scanOn;
|
||||
static epicsTime currentTime;
|
||||
|
||||
virtual caStatus updateValue ( smartConstGDDPointer pValue ) = 0;
|
||||
virtual caStatus updateValue ( const gdd & ) = 0;
|
||||
|
||||
private:
|
||||
|
||||
@@ -229,11 +233,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 +247,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 +307,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 +334,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 +348,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 +535,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 )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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" );
|
||||
|
||||
Reference in New Issue
Block a user