From cd52995cfa2dba330c169ab6eb21c9d22b7fbad2 Mon Sep 17 00:00:00 2001 From: Jeff Hill Date: Fri, 6 Dec 2002 00:05:55 +0000 Subject: [PATCH] some initial steps towards fre list based memory management --- src/cas/build/Makefile | 1 - src/cas/example/directoryService/main.cc | 6 +- src/cas/example/simple/exVectorPV.cc | 2 +- src/cas/generic/caServer.cc | 32 +-- src/cas/generic/caServerIIL.h | 32 +++ src/cas/generic/casAsyncIOI.cc | 33 +-- src/cas/generic/casAsyncPVAttachIO.cc | 4 +- src/cas/generic/casAsyncPVExistIO.cc | 2 +- src/cas/generic/casAsyncReadIO.cc | 4 +- src/cas/generic/casAsyncWriteIO.cc | 2 +- src/cas/generic/casChanDelEv.cc | 11 +- src/cas/generic/casChannel.cc | 21 +- src/cas/generic/casChannelI.cc | 86 +++++--- src/cas/generic/casChannelIIL.h | 32 +-- src/cas/generic/casClient.cc | 237 +++++++++++--------- src/cas/generic/casClientMon.cc | 89 -------- src/cas/generic/casCoreClient.cc | 63 +++++- src/cas/generic/casCoreClientIL.h | 68 +++++- src/cas/generic/casEventSys.cc | 102 ++++----- src/cas/generic/casEventSysIL.h | 33 +-- src/cas/generic/casInternal.h | 180 ++++++++------- src/cas/generic/casMonEvent.cc | 88 ++++++-- src/cas/generic/casMonitor.cc | 104 +++++---- src/cas/generic/casOpaqueAddr.cc | 2 +- src/cas/generic/casOpaqueAddrIL.h | 4 +- src/cas/generic/casPV.cc | 32 +-- src/cas/generic/casPVI.cc | 6 +- src/cas/generic/casPVListChan.cc | 3 +- src/cas/generic/casStrmClient.cc | 121 ++++++----- src/cas/generic/casdef.h | 1 + src/cas/generic/server.h | 265 ++++++++++++----------- src/cas/generic/st/casDGIntfOS.cc | 8 +- src/cas/generic/st/casOSD.h | 6 +- src/cas/generic/st/casStreamOS.cc | 38 ++-- src/cas/io/bsdSocket/caServerIO.cc | 2 +- src/cas/io/bsdSocket/casDGIntfIO.cc | 4 +- src/cas/io/bsdSocket/casIntfIO.cc | 4 +- src/cas/io/bsdSocket/casStreamIO.cc | 12 +- 38 files changed, 928 insertions(+), 812 deletions(-) delete mode 100644 src/cas/generic/casClientMon.cc diff --git a/src/cas/build/Makefile b/src/cas/build/Makefile index bdde7fcda..3cbeee0c1 100644 --- a/src/cas/build/Makefile +++ b/src/cas/build/Makefile @@ -39,7 +39,6 @@ LIBSRCS += casPVI.cc LIBSRCS += casChannel.cc LIBSRCS += casChannelI.cc LIBSRCS += casPVListChan.cc -LIBSRCS += casClientMon.cc LIBSRCS += casChanDelEv.cc LIBSRCS += casAsyncIOI.cc LIBSRCS += casAsyncReadIO.cc diff --git a/src/cas/example/directoryService/main.cc b/src/cas/example/directoryService/main.cc index 4eda59e5b..f4acdc9d6 100644 --- a/src/cas/example/directoryService/main.cc +++ b/src/cas/example/directoryService/main.cc @@ -18,10 +18,6 @@ LOCAL int parseDirectoryFile (const char *pFileName); LOCAL int parseDirectoryFP (FILE *pf, const char *pFileName); -#ifndef TRUE -#define TRUE 1 -#endif - #ifndef INADDR_NONE #define INADDR_NONE (~0ul) #endif @@ -152,7 +148,7 @@ LOCAL int parseDirectoryFP (FILE *pf, const char *pFileName) int nPV=0; ipa.sin_family = AF_INET; - while (TRUE) { + while ( true ) { // // parse the PV name entry from the file diff --git a/src/cas/example/simple/exVectorPV.cc b/src/cas/example/simple/exVectorPV.cc index 2927e4ff5..829f8a258 100644 --- a/src/cas/example/simple/exVectorPV.cc +++ b/src/cas/example/simple/exVectorPV.cc @@ -175,7 +175,7 @@ caStatus exVectorPV::updateValue(smartConstGDDPointer pValueIn) // // Check bounds of incoming request // (and see if we are replacing all elements - - // replaceOk==TRUE) + // replaceOk==true) // // Perhaps much of this is unnecessary since the // server lib checks the bounds of all requests diff --git a/src/cas/generic/caServer.cc b/src/cas/generic/caServer.cc index 450a9b3ad..ca3b69177 100644 --- a/src/cas/generic/caServer.cc +++ b/src/cas/generic/caServer.cc @@ -24,11 +24,11 @@ // // caServer::caServer() // -epicsShareFunc caServer::caServer () +caServer::caServer () { static bool init = false; - if (!init) { + if ( ! init ) { gddMakeMapDBR(gddApplicationTypeTable::app_table); init = true; } @@ -39,7 +39,7 @@ epicsShareFunc caServer::caServer () // // caServer::~caServer() // -epicsShareFunc caServer::~caServer() +caServer::~caServer() { if (this->pCAS) { delete this->pCAS; @@ -50,7 +50,7 @@ epicsShareFunc caServer::~caServer() // // caServer::pvExistTest() // -epicsShareFunc pvExistReturn caServer::pvExistTest (const casCtx &, const char *) +pvExistReturn caServer::pvExistTest (const casCtx &, const char *) { return pverDoesNotExistHere; } @@ -58,7 +58,7 @@ epicsShareFunc pvExistReturn caServer::pvExistTest (const casCtx &, const char * // // caServer::createPV() // -epicsShareFunc pvCreateReturn caServer::createPV (const casCtx &, const char *) +pvCreateReturn caServer::createPV (const casCtx &, const char *) { return S_casApp_pvNotFound; } @@ -66,7 +66,7 @@ epicsShareFunc pvCreateReturn caServer::createPV (const casCtx &, const char *) // // caServer::pvAttach() // -epicsShareFunc pvAttachReturn caServer::pvAttach (const casCtx &ctx, const char *pAliasName) +pvAttachReturn caServer::pvAttach (const casCtx &ctx, const char *pAliasName) { // // remain backwards compatible (call deprecated routine) @@ -77,7 +77,7 @@ epicsShareFunc pvAttachReturn caServer::pvAttach (const casCtx &ctx, const char // // caServer::registerEvent() // -epicsShareFunc casEventMask caServer::registerEvent (const char *pName) // X aCC 361 +casEventMask caServer::registerEvent (const char *pName) // X aCC 361 { if (this->pCAS) { return this->pCAS->registerEvent(pName); @@ -92,7 +92,7 @@ epicsShareFunc casEventMask caServer::registerEvent (const char *pName) // X aCC // // caServer::show() // -epicsShareFunc void caServer::show(unsigned level) const +void caServer::show(unsigned level) const { if (this->pCAS) { this->pCAS->show(level); @@ -105,7 +105,7 @@ epicsShareFunc void caServer::show(unsigned level) const // // caServer::setDebugLevel() // -epicsShareFunc void caServer::setDebugLevel (unsigned level) +void caServer::setDebugLevel (unsigned level) { if (pCAS) { this->pCAS->setDebugLevel(level); @@ -118,7 +118,7 @@ epicsShareFunc void caServer::setDebugLevel (unsigned level) // // caServer::getDebugLevel() // -epicsShareFunc unsigned caServer::getDebugLevel () const // X aCC 361 +unsigned caServer::getDebugLevel () const // X aCC 361 { if (pCAS) { return this->pCAS->getDebugLevel(); @@ -132,7 +132,7 @@ epicsShareFunc unsigned caServer::getDebugLevel () const // X aCC 361 // // caServer::valueEventMask () // -epicsShareFunc casEventMask caServer::valueEventMask () const // X aCC 361 +casEventMask caServer::valueEventMask () const // X aCC 361 { if (pCAS) { return this->pCAS->valueEventMask(); @@ -146,7 +146,7 @@ epicsShareFunc casEventMask caServer::valueEventMask () const // X aCC 361 // // caServer::logEventMask () // -epicsShareFunc casEventMask caServer::logEventMask () const // X aCC 361 +casEventMask caServer::logEventMask () const // X aCC 361 { if (pCAS) { return this->pCAS->logEventMask(); @@ -160,7 +160,7 @@ epicsShareFunc casEventMask caServer::logEventMask () const // X aCC 361 // // caServer::alarmEventMask () // -epicsShareFunc casEventMask caServer::alarmEventMask () const // X aCC 361 +casEventMask caServer::alarmEventMask () const // X aCC 361 { if (pCAS) { return this->pCAS->alarmEventMask(); @@ -182,7 +182,7 @@ class epicsTimer & caServer::createTimer () // // caServer::subscriptionEventsProcessed // -epicsShareFunc unsigned caServer::subscriptionEventsProcessed () const // X aCC 361 +unsigned caServer::subscriptionEventsProcessed () const // X aCC 361 { if ( pCAS ) { return this->pCAS->subscriptionEventsProcessed(); @@ -195,7 +195,7 @@ epicsShareFunc unsigned caServer::subscriptionEventsProcessed () const // X aCC // // caServer::subscriptionEventsPosted // -epicsShareFunc unsigned caServer::subscriptionEventsPosted () const // X aCC 361 +unsigned caServer::subscriptionEventsPosted () const // X aCC 361 { if ( pCAS ) { return this->pCAS->subscriptionEventsPosted (); @@ -205,7 +205,7 @@ epicsShareFunc unsigned caServer::subscriptionEventsPosted () const // X aCC 361 } } -epicsShareFunc void caServer::generateBeaconAnomaly () +void caServer::generateBeaconAnomaly () { if ( pCAS ) { this->pCAS->generateBeaconAnomaly (); diff --git a/src/cas/generic/caServerIIL.h b/src/cas/generic/caServerIIL.h index f0819687b..5be95d880 100644 --- a/src/cas/generic/caServerIIL.h +++ b/src/cas/generic/caServerIIL.h @@ -169,6 +169,38 @@ inline void caServerI::unlock () const this->mutex.unlock (); } +inline casMonEvent & caServerI::casMonEventFactory ( casMonitor & monitor, + const smartConstGDDPointer & pNewValue ) +{ + return * new ( this->casMonEventFreeList ) casMonEvent ( monitor, pNewValue ); +} + +inline void caServerI::casMonEventDestroy ( casMonEvent & monEvent ) +{ + monEvent.~casMonEvent (); + this->casMonEventFreeList.release ( & monEvent ); +} + +inline casMonitor & caServerI::casMonitorFactory ( + casChannelI & chan, caResId clientId, + const unsigned long count, const unsigned type, + const casEventMask & mask, epicsMutex & mutex, + casMonitorCallbackInterface & cb ) +{ + casMonitor * pMon = + new ( this->casMonitorFreeList ) casMonitor + ( clientId, chan, count, type, mask, mutex, cb ); + this->installItem ( *pMon ); + return *pMon; +} + +inline void caServerI::casMonitorDestroy ( casMonitor & cm ) +{ + casRes * pRes = this->removeItem ( cm ); + assert ( & cm == ( casMonitor * ) pRes ); + cm.~casMonitor (); + this->casMonitorFreeList.release ( & cm ); +} #endif // caServerIIL_h diff --git a/src/cas/generic/casAsyncIOI.cc b/src/cas/generic/casAsyncIOI.cc index d74b86174..ab895135f 100644 --- a/src/cas/generic/casAsyncIOI.cc +++ b/src/cas/generic/casAsyncIOI.cc @@ -71,7 +71,7 @@ casAsyncIOI::casAsyncIOI ( const casCtx & ctx ) : // casAsyncIOI::~casAsyncIOI() { - if (!this->serverDelete) { + if ( ! this->serverDelete ) { fprintf(stderr, "WARNING: An async IO operation was deleted prematurely\n"); fprintf(stderr, @@ -90,8 +90,8 @@ casAsyncIOI::~casAsyncIOI() // pulls itself out of the event queue // if it is installed there // - if (this->inTheEventQueue) { - this->client.casEventSys::removeFromEventQueue(*this); + if ( this->inTheEventQueue ) { + this->client.removeFromEventQueue ( *this ); } } @@ -99,7 +99,7 @@ casAsyncIOI::~casAsyncIOI() // casAsyncIOI::cbFunc() // (called when IO completion event reaches top of event queue) // -caStatus casAsyncIOI::cbFunc(class casEventSys &) +caStatus casAsyncIOI::cbFunc ( casCoreClient & ) { // // Use the client's lock here (which is the same as the @@ -108,7 +108,7 @@ caStatus casAsyncIOI::cbFunc(class casEventSys &) // epicsGuard < casCoreClient > guard ( this->client ); - this->inTheEventQueue = FALSE; + this->inTheEventQueue = false; caStatus status = this->cbFuncAsyncIO(); @@ -116,14 +116,14 @@ caStatus casAsyncIOI::cbFunc(class casEventSys &) // // causes this op to be pushed back on the queue // - this->inTheEventQueue = TRUE; + this->inTheEventQueue = true; return status; } else if (status != S_cas_success) { errMessage (status, "Asynch IO completion failed"); } - this->ioComplete = TRUE; + this->ioComplete = true; // // dont use "this" after potentially destroying the @@ -134,6 +134,11 @@ caStatus casAsyncIOI::cbFunc(class casEventSys &) return S_cas_success; } +void casAsyncIOI::eventSysDestroyNotify ( casCoreClient & ) +{ + this->serverDestroy(); +} + // // casAsyncIOI::postIOCompletionI() // @@ -145,7 +150,7 @@ caStatus casAsyncIOI::postIOCompletionI() // and then it called postIOCompletion() on this object // when it was currently not in use by the server. // - if (this->serverDelete) { + if ( this->serverDelete ) { return S_cas_redundantPost; } @@ -165,21 +170,21 @@ caStatus casAsyncIOI::postIOCompletionI() // // verify that they dont post completion more than once // - if (this->posted) { + if ( this->posted ) { return S_cas_redundantPost; } // // dont call the server tool's cancel() when this object deletes // - this->posted = TRUE; + this->posted = true; // // place this event in the event queue // (this also signals the event consumer) // - this->inTheEventQueue = TRUE; - this->client.casEventSys::addToEventQueue(*this); + this->inTheEventQueue = true; + this->client.addToEventQueue ( *this ); return S_cas_success; } @@ -196,7 +201,7 @@ caServer *casAsyncIOI::getCAS() const // // casAsyncIOI::readOP() // -epicsShareFunc bool casAsyncIOI::readOP() const +bool casAsyncIOI::readOP() const { // // not a read op @@ -230,7 +235,7 @@ void casAsyncIOI::serverDestroyIfReadOP() // void casAsyncIOI::serverDestroy () { - this->serverDelete = TRUE; + this->serverDelete = true; this->destroy(); } diff --git a/src/cas/generic/casAsyncPVAttachIO.cc b/src/cas/generic/casAsyncPVAttachIO.cc index ae2c79844..d72a6c12b 100644 --- a/src/cas/generic/casAsyncPVAttachIO.cc +++ b/src/cas/generic/casAsyncPVAttachIO.cc @@ -52,7 +52,7 @@ caStatus casAsyncPVAttachIO::postIOCompletion ( const pvAttachReturn & retValIn // casAsyncPVAttachIO::cbFuncAsyncIO() // (called when IO completion event reaches top of event queue) // -epicsShareFunc caStatus casAsyncPVAttachIO::cbFuncAsyncIO() +caStatus casAsyncPVAttachIO::cbFuncAsyncIO() { caStatus status; @@ -90,7 +90,7 @@ casAsyncPVCreateIO::casAsyncPVCreateIO ( const casCtx & ctx ) : // // deprecated // -epicsShareFunc casAsyncPVCreateIO::~casAsyncPVCreateIO () +casAsyncPVCreateIO::~casAsyncPVCreateIO () { } diff --git a/src/cas/generic/casAsyncPVExistIO.cc b/src/cas/generic/casAsyncPVExistIO.cc index 85f39d677..075c61773 100644 --- a/src/cas/generic/casAsyncPVExistIO.cc +++ b/src/cas/generic/casAsyncPVExistIO.cc @@ -56,7 +56,7 @@ caStatus casAsyncPVExistIO::postIOCompletion (const pvExistReturn &retValIn) // casAsyncPVExistIO::cbFuncAsyncIO() // (called when IO completion event reaches top of event queue) // -epicsShareFunc caStatus casAsyncPVExistIO::cbFuncAsyncIO() +caStatus casAsyncPVExistIO::cbFuncAsyncIO() { caStatus status; diff --git a/src/cas/generic/casAsyncReadIO.cc b/src/cas/generic/casAsyncReadIO.cc index 6ca7a16ea..50c77fbf8 100644 --- a/src/cas/generic/casAsyncReadIO.cc +++ b/src/cas/generic/casAsyncReadIO.cc @@ -59,7 +59,7 @@ caStatus casAsyncReadIO::postIOCompletion (caStatus completionStatusIn, // // casAsyncReadIO::readOP() // -epicsShareFunc bool casAsyncReadIO::readOP() const +bool casAsyncReadIO::readOP() const { return true; // it is a read op } @@ -68,7 +68,7 @@ epicsShareFunc bool casAsyncReadIO::readOP() const // casAsyncReadIO::cbFuncAsyncIO() // (called when IO completion event reaches top of event queue) // -epicsShareFunc caStatus casAsyncReadIO::cbFuncAsyncIO() +caStatus casAsyncReadIO::cbFuncAsyncIO() { caStatus status; diff --git a/src/cas/generic/casAsyncWriteIO.cc b/src/cas/generic/casAsyncWriteIO.cc index d92d75e6b..1ef9c2fb4 100644 --- a/src/cas/generic/casAsyncWriteIO.cc +++ b/src/cas/generic/casAsyncWriteIO.cc @@ -55,7 +55,7 @@ caStatus casAsyncWriteIO::postIOCompletion ( caStatus completionStatusIn ) // casAsyncWriteIO::cbFuncAsyncIO() // (called when IO completion event reaches top of event queue) // -epicsShareFunc caStatus casAsyncWriteIO::cbFuncAsyncIO () +caStatus casAsyncWriteIO::cbFuncAsyncIO () { caStatus status; diff --git a/src/cas/generic/casChanDelEv.cc b/src/cas/generic/casChanDelEv.cc index 711eb6f63..69efb2196 100644 --- a/src/cas/generic/casChanDelEv.cc +++ b/src/cas/generic/casChanDelEv.cc @@ -29,13 +29,18 @@ casChanDelEv::~casChanDelEv() // // casChanDelEv() // -caStatus casChanDelEv::cbFunc(casEventSys &eSys) +caStatus casChanDelEv::cbFunc ( casCoreClient & client ) { caStatus status; - status = eSys.disconnectChan (this->id); - if (status == S_cas_success) { + status = client.disconnectChan ( this->id ); + if ( status == S_cas_success ) { delete this; } return status; } +void casChanDelEv::eventSysDestroyNotify ( casCoreClient & ) +{ + delete this; +} + diff --git a/src/cas/generic/casChannel.cc b/src/cas/generic/casChannel.cc index 7908f6c43..c53b51621 100644 --- a/src/cas/generic/casChannel.cc +++ b/src/cas/generic/casChannel.cc @@ -22,7 +22,7 @@ // // casChannel::casChannel() // -epicsShareFunc casChannel::casChannel(const casCtx &ctx) : +casChannel::casChannel(const casCtx &ctx) : casPVListChan (ctx) { } @@ -30,14 +30,14 @@ epicsShareFunc casChannel::casChannel(const casCtx &ctx) : // // casChannel::~casChannel() // -epicsShareFunc casChannel::~casChannel() +casChannel::~casChannel() { } // // casChannel::getPV() // -epicsShareFunc casPV *casChannel::getPV() // X aCC 361 +casPV *casChannel::getPV() // X aCC 361 { casPVI *pPVI = &this->casChannelI::getPVI(); @@ -52,7 +52,7 @@ epicsShareFunc casPV *casChannel::getPV() // X aCC 361 // // casChannel::setOwner() // -epicsShareFunc void casChannel::setOwner(const char * const /* pUserName */, +void casChannel::setOwner(const char * const /* pUserName */, const char * const /* pHostName */) { // @@ -63,7 +63,7 @@ epicsShareFunc void casChannel::setOwner(const char * const /* pUserName */, // // casChannel::readAccess() // -epicsShareFunc bool casChannel::readAccess () const +bool casChannel::readAccess () const { return true; } @@ -71,16 +71,15 @@ epicsShareFunc bool casChannel::readAccess () const // // casChannel::writeAccess() // -epicsShareFunc bool casChannel::writeAccess() const +bool casChannel::writeAccess() const { return true; } - // // casChannel::confirmationRequested() // -epicsShareFunc bool casChannel::confirmationRequested() const +bool casChannel::confirmationRequested() const { return false; } @@ -88,7 +87,7 @@ epicsShareFunc bool casChannel::confirmationRequested() const // // casChannel::show() // -epicsShareFunc void casChannel::show(unsigned level) const +void casChannel::show(unsigned level) const { if (level>2u) { printf("casChannel: read access = %d\n", @@ -103,7 +102,7 @@ epicsShareFunc void casChannel::show(unsigned level) const // // casChannel::destroy() // -epicsShareFunc void casChannel::destroy() +void casChannel::destroy() { delete this; } @@ -111,7 +110,7 @@ epicsShareFunc void casChannel::destroy() // // casChannel::postAccessRightsEvent() // -epicsShareFunc void casChannel::postAccessRightsEvent() +void casChannel::postAccessRightsEvent() { this->casChannelI::postAccessRightsEvent(); } diff --git a/src/cas/generic/casChannelI.cc b/src/cas/generic/casChannelI.cc index 5bdf8cea4..9e169f6bc 100644 --- a/src/cas/generic/casChannelI.cc +++ b/src/cas/generic/casChannelI.cc @@ -29,7 +29,8 @@ casChannelI::casChannelI ( const casCtx & ) : { } -void casChannelI::bindToClientI ( casCoreClient & client, casPVI & pv, caResId cidIn ) +void casChannelI::bindToClientI ( + casCoreClient & client, casPVI & pv, caResId cidIn ) { this->pClient = & client; this->pPV = & pv; @@ -42,7 +43,8 @@ void casChannelI::bindToClientI ( casCoreClient & client, casPVI & pv, caResId c // casChannelI::~casChannelI() { - epicsGuard < casCoreClient > guard ( * this->pClient ); + epicsGuard < casCoreClient > + guard ( * this->pClient ); // // cancel any pending asynchronous IO @@ -61,23 +63,16 @@ casChannelI::~casChannelI() // // cancel the monitors // - tsDLIter iterMon = this->monitorList.firstIter (); - while ( iterMon.valid () ) { - // - // destructor removes from this list - // - tsDLIter tmpMon = iterMon; - ++tmpMon; - iterMon->destroy (); - iterMon = tmpMon; + while ( casMonitor * pMon = this->monitorList.get () ) { + this->getClient().destroyMonitor ( *pMon ); } - this->pClient->removeChannel(*this); + this->pClient->removeChannel ( *this ); // // force PV delete if this is the last channel attached // - this->pPV->deleteSignal(); + this->pPV->deleteSignal (); } // @@ -109,7 +104,8 @@ void casChannelI::show ( unsigned level ) const { epicsGuard < casCoreClient > guard ( * this->pClient ); - tsDLIterConst iter = this->monitorList.firstIter (); + tsDLIterConst < casMonitor > iter = + this->monitorList.firstIter (); if ( iter.valid () ) { printf("List of CA events (monitors) for \"%s\".\n", this->pPV->getName()); @@ -127,17 +123,22 @@ void casChannelI::show ( unsigned level ) const // // access rights event call back // -caStatus casChannelI::cbFunc(casEventSys &) +caStatus casChannelI::cbFunc ( casCoreClient & ) { caStatus stat; - stat = this->pClient->accessRightsResponse(this); - if (stat==S_cas_success) { + stat = this->pClient->accessRightsResponse ( this ); + if ( stat == S_cas_success ) { this->accessRightsEvPending = false; } return stat; } +void casChannelI::eventSysDestroyNotify ( casCoreClient & ) +{ + delete this; +} + // // casChannelI::resourceType() // @@ -152,7 +153,7 @@ casResType casChannelI::resourceType() const // this noop version is safe to be called indirectly // from casChannelI::~casChannelI // -epicsShareFunc void casChannelI::destroy() +void casChannelI::destroy() { } @@ -161,13 +162,13 @@ void casChannelI::destroyClientNotify () casChanDelEv *pCDEV; caStatus status; - pCDEV = new casChanDelEv (this->getCID()); - if (pCDEV) { - this->pClient->casEventSys::addToEventQueue (*pCDEV); + pCDEV = new casChanDelEv ( this->getCID() ); + if ( pCDEV ) { + this->pClient->addToEventQueue ( *pCDEV ); } else { - status = this->pClient->disconnectChan (this->getCID()); - if (status) { + status = this->pClient->disconnectChan ( this->getCID () ); + if ( status ) { // // At this point there is no space in pool // for a tiny object and there is also @@ -180,21 +181,20 @@ void casChannelI::destroyClientNotify () // will result in bugs because no doubt this // could be called by a client member function. // - this->pClient->setDestroyPending(); + this->pClient->setDestroyPending (); } } - this->destroy(); + this->destroy (); } -// -// casChannelI::findMonitor -// (it is reasonable to do a linear search here because -// sane clients will require only one or two monitors -// per channel) -// -tsDLIter casChannelI::findMonitor (const caResId clientIdIn) +bool casChannelI::unistallMonitor ( ca_uint32_t clientIdIn ) { epicsGuard < casCoreClient > guard ( * this->pClient ); + // + // (it is reasonable to do a linear search here because + // sane clients will require only one or two monitors + // per channel) + // tsDLIter iter = this->monitorList.firstIter (); while ( iter.valid () ) { if ( clientIdIn == iter->getClientId () ) { @@ -202,6 +202,26 @@ tsDLIter casChannelI::findMonitor (const caResId clientIdIn) } iter++; } - return iter; + if ( ! iter.valid () ) { + return false; + } + this->monitorList.remove ( *iter.pointer() ); + this->getClient().destroyMonitor ( *iter.pointer() ); + return true; +} + +// +// casChannelI::installMonitor () +// +void casChannelI::installMonitor ( + caResId clientId, + const unsigned long count, + const unsigned type, + const casEventMask & mask ) +{ + epicsGuard < casCoreClient > guard ( * this->pClient ); + casMonitor & mon = this->pClient->monitorFactory ( + *this, clientId, count, type, mask ); + this->monitorList.add ( mon ); } diff --git a/src/cas/generic/casChannelIIL.h b/src/cas/generic/casChannelIIL.h index 6b2ce77fa..d268607ff 100644 --- a/src/cas/generic/casChannelIIL.h +++ b/src/cas/generic/casChannelIIL.h @@ -27,7 +27,7 @@ // inline void casChannelI::postEvent (const casEventMask &select, const gdd &event) { - epicsGuard < casCoreClient > guard ( * this->pClient ); + epicsGuard < casCoreClient > guard ( *this->pClient ); tsDLIter iter = this->monitorList.firstIter (); while ( iter.valid () ) { iter->post (select, event); @@ -35,30 +35,6 @@ inline void casChannelI::postEvent (const casEventMask &select, const gdd &event } } - -// -// casChannelI::deleteMonitor() -// -inline void casChannelI::deleteMonitor(casMonitor &mon) -{ - epicsGuard < casCoreClient > guard ( * this->pClient ); - this->getClient().casEventSys::removeMonitor(); - this->monitorList.remove(mon); - casRes *pRes = this->getClient().getCAS().removeItem(mon); - assert ( & mon == (casMonitor *) pRes ); -} - -// -// casChannelI::addMonitor() -// -inline void casChannelI::addMonitor(casMonitor &mon) -{ - epicsGuard < casCoreClient > guard ( * this->pClient ); - this->monitorList.add(mon); - this->getClient().getCAS().installItem(mon); - this->getClient().casEventSys::installMonitor(); -} - // // casChannelI::destroyNoClientNotify() // @@ -78,16 +54,16 @@ inline void casChannelI::destroyNoClientNotify() // inline void casChannelI::installAsyncIO(casAsyncIOI &io) { - epicsGuard < casCoreClient > guard ( * this->pClient ); + epicsGuard < casCoreClient > guard ( *this->pClient ); this->ioInProgList.add(io); } // // casChannelI::removeAsyncIO() // -inline void casChannelI::removeAsyncIO(casAsyncIOI &io) +inline void casChannelI::removeAsyncIO ( casAsyncIOI & io ) { - epicsGuard < casCoreClient > guard ( * this->pClient ); + epicsGuard < casCoreClient > guard ( *this->pClient ); this->ioInProgList.remove(io); this->pPV->unregisterIO(); } diff --git a/src/cas/generic/casClient.cc b/src/cas/generic/casClient.cc index e452be303..05229188b 100644 --- a/src/cas/generic/casClient.cc +++ b/src/cas/generic/casClient.cc @@ -31,7 +31,7 @@ static const caHdr nill_msg = {0u,0u,0u,0u,0u,0u}; // // static declartions for class casClient // -int casClient::msgHandlersInit; +bool casClient::msgHandlersInit; casClient::pCASMsgHandler casClient::msgHandlers[CA_PROTO_LAST_CMMD+1u]; // @@ -94,7 +94,7 @@ void casClient::loadProtoJumpTable() // // Load the static protocol handler tables // - if (casClient::msgHandlersInit) { + if ( casClient::msgHandlersInit ) { return; } @@ -155,7 +155,7 @@ void casClient::loadProtoJumpTable() casClient::msgHandlers[CA_PROTO_CLAIM_CIU_FAILED] = &casClient::uknownMessageAction; - casClient::msgHandlersInit = TRUE; + casClient::msgHandlersInit = true; } // @@ -182,123 +182,148 @@ void casClient::show (unsigned level) const // caStatus casClient::processMsg () { - // drain message that does not fit - if ( this->incommingBytesToDrain ) { - unsigned bytesLeft = this->in.bytesPresent(); - if ( bytesLeft < this->incommingBytesToDrain ) { - this->in.removeMsg ( bytesLeft ); - this->incommingBytesToDrain -= bytesLeft; - return S_cas_success; - } - else { - this->in.removeMsg ( this->incommingBytesToDrain ); - this->incommingBytesToDrain = 0u; - } - } - - // - // process any messages in the in buffer - // int status = S_cas_success; - unsigned bytesLeft; - while ( ( bytesLeft = this->in.bytesPresent() ) ) { - caHdrLargeArray msgTmp; - unsigned msgSize; - ca_uint32_t hdrSize; - char * rawMP; - { - // - // copy as raw bytes in order to avoid - // alignment problems - // - caHdr smallHdr; - if ( bytesLeft < sizeof ( smallHdr ) ) { - break; - } - - rawMP = this->in.msgPtr (); - memcpy ( & smallHdr, rawMP, sizeof ( smallHdr ) ); - - ca_uint32_t payloadSize = epicsNTOH16 ( smallHdr.m_postsize ); - ca_uint32_t nElem = epicsNTOH16 ( smallHdr.m_count ); - if ( payloadSize != 0xffff && nElem != 0xffff ) { - hdrSize = sizeof ( smallHdr ); + try { + // drain message that does not fit + if ( this->incommingBytesToDrain ) { + unsigned bytesLeft = this->in.bytesPresent(); + if ( bytesLeft < this->incommingBytesToDrain ) { + this->in.removeMsg ( bytesLeft ); + this->incommingBytesToDrain -= bytesLeft; + return S_cas_success; } else { - ca_uint32_t LWA[2]; - hdrSize = sizeof ( smallHdr ) + sizeof ( LWA ); - if ( bytesLeft < hdrSize ) { + this->in.removeMsg ( this->incommingBytesToDrain ); + this->incommingBytesToDrain = 0u; + } + } + + // + // process any messages in the in buffer + // + + unsigned bytesLeft; + while ( ( bytesLeft = this->in.bytesPresent() ) ) { + caHdrLargeArray msgTmp; + unsigned msgSize; + ca_uint32_t hdrSize; + char * rawMP; + { + // + // copy as raw bytes in order to avoid + // alignment problems + // + caHdr smallHdr; + if ( bytesLeft < sizeof ( smallHdr ) ) { break; } - // - // copy as raw bytes in order to avoid - // alignment problems - // - memcpy ( LWA, rawMP + sizeof ( caHdr ), sizeof( LWA ) ); - payloadSize = epicsNTOH32 ( LWA[0] ); - nElem = epicsNTOH32 ( LWA[1] ); - } - msgTmp.m_cmmd = epicsNTOH16 ( smallHdr.m_cmmd ); - msgTmp.m_postsize = payloadSize; - msgTmp.m_dataType = epicsNTOH16 ( smallHdr.m_dataType ); - msgTmp.m_count = nElem; - msgTmp.m_cid = epicsNTOH32 ( smallHdr.m_cid ); - msgTmp.m_available = epicsNTOH32 ( smallHdr.m_available ); + rawMP = this->in.msgPtr (); + memcpy ( & smallHdr, rawMP, sizeof ( smallHdr ) ); - - msgSize = hdrSize + payloadSize; - if ( bytesLeft < msgSize ) { - if ( msgSize > this->in.bufferSize() ) { - this->in.expandBuffer (); - // msg to large - set up message drain - if ( msgSize > this->in.bufferSize() ) { - this->dumpMsg ( & msgTmp, 0, - "The client requested transfer is greater than available " - "memory in server or EPICS_CA_MAX_ARRAY_BYTES\n" ); - status = this->sendErr ( & msgTmp, ECA_TOLARGE, - "request didnt fit within the CA server's message buffer" ); - this->in.removeMsg ( bytesLeft ); - this->incommingBytesToDrain = msgSize - bytesLeft; - } + ca_uint32_t payloadSize = epicsNTOH16 ( smallHdr.m_postsize ); + ca_uint32_t nElem = epicsNTOH16 ( smallHdr.m_count ); + if ( payloadSize != 0xffff && nElem != 0xffff ) { + hdrSize = sizeof ( smallHdr ); } - break; + else { + ca_uint32_t LWA[2]; + hdrSize = sizeof ( smallHdr ) + sizeof ( LWA ); + if ( bytesLeft < hdrSize ) { + break; + } + // + // copy as raw bytes in order to avoid + // alignment problems + // + memcpy ( LWA, rawMP + sizeof ( caHdr ), sizeof( LWA ) ); + payloadSize = epicsNTOH32 ( LWA[0] ); + nElem = epicsNTOH32 ( LWA[1] ); + } + + msgTmp.m_cmmd = epicsNTOH16 ( smallHdr.m_cmmd ); + msgTmp.m_postsize = payloadSize; + msgTmp.m_dataType = epicsNTOH16 ( smallHdr.m_dataType ); + msgTmp.m_count = nElem; + msgTmp.m_cid = epicsNTOH32 ( smallHdr.m_cid ); + msgTmp.m_available = epicsNTOH32 ( smallHdr.m_available ); + + + msgSize = hdrSize + payloadSize; + if ( bytesLeft < msgSize ) { + if ( msgSize > this->in.bufferSize() ) { + this->in.expandBuffer (); + // msg to large - set up message drain + if ( msgSize > this->in.bufferSize() ) { + this->dumpMsg ( & msgTmp, 0, + "The client requested transfer is greater than available " + "memory in server or EPICS_CA_MAX_ARRAY_BYTES\n" ); + status = this->sendErr ( & msgTmp, ECA_TOLARGE, + "request didnt fit within the CA server's message buffer" ); + this->in.removeMsg ( bytesLeft ); + this->incommingBytesToDrain = msgSize - bytesLeft; + } + } + break; + } + + this->ctx.setMsg ( msgTmp, rawMP + hdrSize ); + + if ( this->getCAS().getDebugLevel() > 2u ) { + this->dumpMsg ( & msgTmp, rawMP + hdrSize, 0 ); + } + } - this->ctx.setMsg ( msgTmp, rawMP + hdrSize ); + // + // Reset the context to the default + // (guarantees that previous message does not get mixed + // up with the current message) + // + this->ctx.setChannel ( NULL ); + this->ctx.setPV ( NULL ); - if ( this->getCAS().getDebugLevel() > 2u ) { - this->dumpMsg ( & msgTmp, rawMP + hdrSize, 0 ); + // + // Call protocol stub + // + pCASMsgHandler pHandler; + if ( msgTmp.m_cmmd < NELEMENTS ( casClient::msgHandlers ) ) { + pHandler = this->casClient::msgHandlers[msgTmp.m_cmmd]; + } + else { + pHandler = & casClient::uknownMessageAction; + } + status = ( this->*pHandler ) (); + if ( status ) { + break; } - } - - // - // Reset the context to the default - // (guarantees that previous message does not get mixed - // up with the current message) - // - this->ctx.setChannel ( NULL ); - this->ctx.setPV ( NULL ); - - // - // Call protocol stub - // - pCASMsgHandler pHandler; - if ( msgTmp.m_cmmd < NELEMENTS ( casClient::msgHandlers ) ) { - pHandler = this->casClient::msgHandlers[msgTmp.m_cmmd]; - } - else { - pHandler = & casClient::uknownMessageAction; - } - status = ( this->*pHandler ) (); - if ( status ) { - break; - } - - this->in.removeMsg ( msgSize ); - } + this->in.removeMsg ( msgSize ); + } + } + catch ( std::bad_alloc & ) { + status = this->sendErr ( + this->ctx.getMsg(), ECA_ALLOCMEM, + "inablility to allocate memory in " + "the server disconnected client" ); + status = S_cas_noMemory; + } + catch ( std::exception & except ) { + status = this->sendErr ( + this->ctx.getMsg(), ECA_INTERNAL, + "C++ exception \"%s\" in server " + "diconnected client", + except.what () ); + status = S_cas_internal; + } + catch (...) { + status = this->sendErr ( + this->ctx.getMsg(), ECA_INTERNAL, + "unexpected C++ exception in server " + "diconnected client" ); + status = S_cas_internal; + } return status; } diff --git a/src/cas/generic/casClientMon.cc b/src/cas/generic/casClientMon.cc deleted file mode 100644 index a2080a381..000000000 --- a/src/cas/generic/casClientMon.cc +++ /dev/null @@ -1,89 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* - * $Id$ - * - * Author Jeffrey O. Hill - * johill@lanl.gov - * 505 665 1831 - */ - - -#include "server.h" - -#include "casChannelIIL.h" - - -// -// casClientMon::casClientMon() -// -casClientMon::casClientMon(casChannelI &chan, caResId clientIdIn, - const unsigned long count, const unsigned type, - const casEventMask &maskIn, epicsMutex &mutexIn) : - casMonitor(clientIdIn, chan, count, type, maskIn, mutexIn) -{ -} - - -// -// casClientMon::~casClientMon() -// -casClientMon::~casClientMon() -{ -} - - -// -// casClientMon::callBack() -// -caStatus casClientMon::callBack ( const smartConstGDDPointer &value ) -{ - casCoreClient & client = this->getChannel().getClient(); - caStatus status; - caHdrLargeArray msg; - - // - // reconstruct the msg header - // - msg.m_cmmd = CA_PROTO_EVENT_ADD; - msg.m_postsize = 0u; - unsigned type = this->getType(); - assert ( type <= 0xffff ); - msg.m_dataType = static_cast ( type ); - unsigned long count = this->getCount(); - assert ( count <= 0xffffffff ); - msg.m_count = static_cast ( count ); - msg.m_cid = this->getChannel().getSID(); - msg.m_available = this->getClientId(); - - status = client.monitorResponse ( this->getChannel(), - msg, value, S_cas_success ); - return status; -} - -// -// casClientMon::destroy() -// -// this class is always created inside the server -// lib with new -// -void casClientMon::destroy() -{ - delete this; -} - -// -// casClientMon::resourceType() -// -casResType casClientMon::resourceType() const -{ - return casClientMonT; -} - diff --git a/src/cas/generic/casCoreClient.cc b/src/cas/generic/casCoreClient.cc index 3d3a5626a..8baf9f9dd 100644 --- a/src/cas/generic/casCoreClient.cc +++ b/src/cas/generic/casCoreClient.cc @@ -17,16 +17,18 @@ #include "server.h" -#include "caServerIIL.h" // caServerI in line func -#include "casEventSysIL.h" // casEventSys in line func -#include "casCtxIL.h" // casCtx in line func -#include "inBufIL.h" // inBuf in line func -#include "outBufIL.h" // outBuf in line func +#include "caServerIIL.h" +#include "casEventSysIL.h" +#include "casCtxIL.h" +#include "inBufIL.h" +#include "outBufIL.h" +#include "casCoreClientIL.h" // // casCoreClient::casCoreClient() // -casCoreClient::casCoreClient (caServerI &serverInternal) +casCoreClient::casCoreClient ( caServerI & serverInternal ) : + eventSys ( *this ) { assert (&serverInternal); ctx.setServer (&serverInternal); @@ -77,10 +79,10 @@ caStatus casCoreClient::disconnectChan(caResId) return S_cas_success; } -void casCoreClient::show (unsigned level) const +void casCoreClient::show ( unsigned level ) const { printf ( "Core client\n" ); - this->casEventSys::show ( level ); + this->eventSys.show ( level ); printf ( "\t%d io ops in progess\n", this->ioInProgList.count() ); this->ctx.show ( level ); this->mutex.show ( level ); @@ -183,9 +185,46 @@ ca_uint16_t casCoreClient::protocolRevision() const // // casCoreClient::lookupRes() // -casRes *casCoreClient::lookupRes (const caResId &idIn, casResType type) +casRes * casCoreClient::lookupRes (const caResId &idIn, casResType type) { - casRes *pRes; - pRes = this->ctx.getServer()->lookupRes(idIn, type); - return pRes; + return this->ctx.getServer()->lookupRes(idIn, type); } + +// this is a pure virtual function, but we nevertheless need a +// noop to be called if they post events when a channel is being +// destroyed when we are in the casStrmClient destructor +void casCoreClient::eventSignal() +{ +} + +caStatus casCoreClient::casMonitorCallBack ( casMonitor &, + const smartConstGDDPointer & ) +{ + return S_cas_internal; +} + +casMonitor & casCoreClient::monitorFactory ( + casChannelI & chan, + caResId clientId, + const unsigned long count, + const unsigned type, + const casEventMask & mask ) +{ + casMonitor & mon = this->ctx.getServer()->casMonitorFactory ( + chan, clientId, count, + type, mask, + this->mutex, + *this ); + this->installMonitor (); + return mon; +} + +void casCoreClient::destroyMonitor ( casMonitor & mon ) +{ + this->removeMonitor (); + this->ctx.getServer()->casMonitorDestroy ( mon ); +} + + + + diff --git a/src/cas/generic/casCoreClientIL.h b/src/cas/generic/casCoreClientIL.h index 6600d223b..18c6d9273 100644 --- a/src/cas/generic/casCoreClientIL.h +++ b/src/cas/generic/casCoreClientIL.h @@ -47,7 +47,7 @@ inline caServerI &casCoreClient::getCAS() const inline void casCoreClient::installAsyncIO(casAsyncIOI &ioIn) { epicsGuard < epicsMutex > guard ( this->mutex ); - this->ioInProgList.add(ioIn); + this->ioInProgList.add ( ioIn ); } // @@ -56,8 +56,8 @@ inline void casCoreClient::installAsyncIO(casAsyncIOI &ioIn) inline void casCoreClient::removeAsyncIO(casAsyncIOI &ioIn) { epicsGuard < epicsMutex > guard ( this->mutex ); - this->ioInProgList.remove(ioIn); - this->ctx.getServer()->ioBlockedList::signal(); + this->ioInProgList.remove ( ioIn ); + this->ctx.getServer()->ioBlockedList::signal (); } inline bool casCoreClient::okToStartAsynchIO () @@ -69,5 +69,67 @@ inline bool casCoreClient::okToStartAsynchIO () return false; } +inline casMonEvent & casCoreClient::casMonEventFactory ( casMonitor & monitor, + const smartConstGDDPointer & pNewValue ) +{ + return this->ctx.getServer()->casMonEventFactory ( monitor, pNewValue ); +} + +inline void casCoreClient::casMonEventDestroy ( casMonEvent & event ) +{ + this->ctx.getServer()->casMonEventDestroy ( event ); +} + +inline casEventSys::processStatus casCoreClient::eventSysProcess () +{ + return this->eventSys.process (); +} + +inline void casCoreClient::addToEventQueue ( casEvent & ev ) +{ + this->eventSys.addToEventQueue ( ev ); +} + +inline void casCoreClient::insertEventQueue ( casEvent & insert, casEvent & prevEvent ) +{ + this->eventSys.insertEventQueue ( insert, prevEvent ); +} + +inline void casCoreClient::removeFromEventQueue ( casEvent & ev ) +{ + this->eventSys.removeFromEventQueue ( ev ); +} + +inline void casCoreClient::enableEvents () +{ + this->eventSys.eventsOn (); + this->eventSignal (); // wake up the event queue consumer +} + +inline void casCoreClient::disableEvents () +{ + this->eventSys.eventsOff (); +} + +inline void casCoreClient::setDestroyPending () +{ + this->eventSys.setDestroyPending (); +} + +inline bool casCoreClient::eventSysIsFull () +{ + return this->eventSys.full (); +} + +inline void casCoreClient::installMonitor () +{ + this->eventSys.installMonitor (); +} + +inline void casCoreClient::removeMonitor () +{ + this->eventSys.removeMonitor (); +} + #endif // casCoreClientIL_h diff --git a/src/cas/generic/casEventSys.cc b/src/cas/generic/casEventSys.cc index da525fee9..538273717 100644 --- a/src/cas/generic/casEventSys.cc +++ b/src/cas/generic/casEventSys.cc @@ -39,7 +39,8 @@ void casEventSys::show(unsigned level) const printf ("\tthere are %d events in the queue\n", this->eventLogQue.count()); printf ("Replace events flag = %d, dontProcess flag = %d\n", - this->replaceEvents, this->dontProcess); + static_cast < int > ( this->replaceEvents ), + static_cast < int > ( this->dontProcess ) ); } } @@ -60,8 +61,8 @@ casEventSys::~casEventSys() */ casVerify ( this->numEventBlocks == 0 ); - while ( casEvent *pE = this->eventLogQue.get () ) { - delete pE; + while ( casEvent * pE = this->eventLogQue.get () ) { + pE->eventSysDestroyNotify ( this->client ); } } @@ -77,9 +78,9 @@ void casEventSys::installMonitor() } // -// casEventSys::removeMonitor() +// casEventSys::removeMonitor () // -void casEventSys::removeMonitor() +void casEventSys::removeMonitor () { epicsGuard < epicsMutex > guard ( this->mutex ); assert (this->numEventBlocks>=1u); @@ -90,10 +91,11 @@ void casEventSys::removeMonitor() // // casEventSys::process() // -casProcCond casEventSys::process () +casEventSys::processStatus casEventSys::process () { - casProcCond cond = casProcOk; - unsigned long nAccepted = 0u; + casEventSys::processStatus ps; + ps.cond = casProcOk; + ps.nAccepted = 0u; while ( ! this->dontProcess ) { casEvent * pEvent; @@ -108,9 +110,9 @@ casProcCond casEventSys::process () } // lock must remain on until the event is called - caStatus status = pEvent->cbFunc ( *this ); + caStatus status = pEvent->cbFunc ( this->client ); if ( status == S_cas_success ) { - nAccepted++; + ps.nAccepted++; } else if ( status == S_cas_sendBlocked ) { // not accepted so return to the head of the list @@ -119,26 +121,21 @@ casProcCond casEventSys::process () epicsGuard < epicsMutex > guard ( this->mutex ); this->pushOnToEventQueue ( *pEvent ); } - cond = casProcOk; + ps.cond = casProcOk; break; } else if ( status == S_cas_disconnect ) { - cond = casProcDisconnect; + ps.cond = casProcDisconnect; break; } else { errMessage ( status, "- unexpected error processing event" ); - cond = casProcDisconnect; + ps.cond = casProcDisconnect; break; } } - // call flush function if they provided one - if ( nAccepted > 0u ) { - this->eventFlush (); - } - // // allows the derived class to be informed that it // needs to delete itself via the event system @@ -149,10 +146,10 @@ casProcCond casEventSys::process () // pointer. // if ( this->destroyPending ) { - cond = casProcDisconnect; + ps.cond = casProcDisconnect; } - return cond; + return ps; } // @@ -166,12 +163,12 @@ void casEventSys::eventsOn() // // allow multiple events for each monitor // - this->replaceEvents = FALSE; + this->replaceEvents = false; // // allow the event queue to be processed // - this->dontProcess = FALSE; + this->dontProcess = false; // // remove purge event if it is still pending @@ -182,17 +179,12 @@ void casEventSys::eventsOn() this->pPurgeEvent = NULL; } } - - // - // wakes up the event queue consumer - // - this->eventSignal (); } // // casEventSys::eventsOff() // -caStatus casEventSys::eventsOff() +void casEventSys::eventsOff() { epicsGuard < epicsMutex > guard ( this->mutex ); @@ -200,7 +192,7 @@ caStatus casEventSys::eventsOff() // new events will replace the last event on // the queue for a particular monitor // - this->replaceEvents = TRUE; + this->replaceEvents = true; // // suppress the processing and sending of events @@ -208,62 +200,38 @@ caStatus casEventSys::eventsOff() // for this particular client // if ( this->pPurgeEvent == NULL ) { - this->pPurgeEvent = new casEventPurgeEv; + this->pPurgeEvent = new casEventPurgeEv ( *this ); if ( this->pPurgeEvent == NULL ) { // // if there is no room for the event then immediately // stop processing and sending events to the client // until we exit flow control // - this->dontProcess = TRUE; + this->dontProcess = true; } else { this->casEventSys::addToEventQueue ( *this->pPurgeEvent ); } } - - return S_cas_success; } -// this is a pure virtual function, but we nevertheless need a -// noop to be called if they post events when a channel is being -// destroyed when we are in the casStrmClient destructor -void casEventSys::eventSignal() +// +// casEventPurgeEv::casEventPurgeEv () +// +casEventPurgeEv::casEventPurgeEv ( casEventSys & evSysIn ) : + evSys ( evSysIn ) { } -// this is a pure virtual function, but we nevertheless need a -// noop to be called if they call this when we are in the -// casStrmClient destructor -caStatus casEventSys::disconnectChan ( caResId ) -{ - return S_cas_success; -} - -// this is a pure virtual function, but we nevertheless need a -// noop to be called if they call this when we are in the -// casStrmClient destructor -void casEventSys::eventFlush () -{ -} - -// this is a pure virtual function, but we nevertheless need a -// noop to be called if they call this when we are in the -// casStrmClient destructor -casRes * casEventSys::lookupRes ( const caResId &, casResType ) -{ - return 0; -} - // // casEventPurgeEv::cbFunc() // -caStatus casEventPurgeEv::cbFunc ( casEventSys & evSys ) +caStatus casEventPurgeEv::cbFunc ( casCoreClient & ) { { - epicsGuard < epicsMutex > guard ( evSys.mutex ); - evSys.dontProcess = TRUE; - evSys.pPurgeEvent = NULL; + epicsGuard < epicsMutex > guard ( this->evSys.mutex ); + this->evSys.dontProcess = true; + this->evSys.pPurgeEvent = NULL; } delete this; @@ -271,3 +239,9 @@ caStatus casEventPurgeEv::cbFunc ( casEventSys & evSys ) return S_cas_success; } +void casEventPurgeEv::eventSysDestroyNotify ( casCoreClient & ) +{ + delete this; +} + + diff --git a/src/cas/generic/casEventSysIL.h b/src/cas/generic/casEventSysIL.h index 980797a4d..8f952db3a 100644 --- a/src/cas/generic/casEventSysIL.h +++ b/src/cas/generic/casEventSysIL.h @@ -22,13 +22,14 @@ // // casEventSys::casEventSys () // -inline casEventSys::casEventSys () : - pPurgeEvent (NULL), - numEventBlocks (0u), - maxLogEntries (individualEventEntries), - destroyPending (false), - replaceEvents (false), - dontProcess (false) +inline casEventSys::casEventSys ( casCoreClient & clientIn ) : + client ( clientIn ), + pPurgeEvent ( NULL ), + numEventBlocks ( 0u ), + maxLogEntries ( individualEventEntries ), + destroyPending ( false ), + replaceEvents ( false ), + dontProcess ( false ) { } @@ -48,7 +49,7 @@ inline void casEventSys::addToEventQueue ( casEvent & event ) // is in flow control // if ( ! this->dontProcess ) { - this->eventSignal (); + this->client.eventSignal (); } } @@ -61,7 +62,7 @@ inline void casEventSys::setDestroyPending() // // wakes up the event queue consumer // - this->eventSignal (); + this->client.eventSignal (); } // @@ -104,19 +105,5 @@ inline bool casEventSys::full() // X aCC 361 } } -// -// casMonitor::resIdToMon() -// -inline casMonitor *casEventSys::resIdToMon(const caResId id) -{ - casRes *pRes = this->lookupRes (id, casClientMonT); - - // - // safe to cast because we have checked the type code above - // (and we know that casMonitor derived from casRes) - // - return (casMonitor *) pRes; -} - #endif // casEventSysIL_h diff --git a/src/cas/generic/casInternal.h b/src/cas/generic/casInternal.h index d26122cef..9198e450a 100644 --- a/src/cas/generic/casInternal.h +++ b/src/cas/generic/casInternal.h @@ -18,7 +18,9 @@ // // EPICS // +#include "cxxCompilerDependencies.h" #include "tsDLList.h" +#include "tsFreeList.h" #include "resourceLib.h" #define CA_MINOR_PROTOCOL_REVISION 11 #include "caProto.h" @@ -26,38 +28,40 @@ typedef aitUint32 caResId; -class casEventSys; class casChannelI; +class casCoreClient; // // casEvent // -class casEvent : public tsDLNode { +class casEvent : public tsDLNode < casEvent > { public: - epicsShareFunc virtual ~casEvent(); - virtual caStatus cbFunc (casEventSys &)=0; -private: + virtual caStatus cbFunc ( casCoreClient & ) = 0; + virtual void eventSysDestroyNotify ( casCoreClient & ) = 0; +protected: + virtual ~casEvent(); }; class casChanDelEv : public casEvent { public: - casChanDelEv(caResId idIn) : id(idIn) {} - ~casChanDelEv(); - caStatus cbFunc(casEventSys &); + casChanDelEv ( caResId idIn ) : id(idIn) {} + ~casChanDelEv (); private: caResId id; + caStatus cbFunc ( casCoreClient & ); + void eventSysDestroyNotify ( casCoreClient & ); }; -enum casResType {casChanT=1, casClientMonT, casPVT}; +enum casResType {casChanT=1, casMonitorT, casPVT}; class casRes : public chronIntIdRes { public: casRes (); epicsShareFunc virtual ~casRes(); - virtual casResType resourceType() const = 0; - virtual void show (unsigned level) const = 0; - virtual void destroy() = 0; + virtual casResType resourceType () const = 0; + virtual void show ( unsigned level ) const = 0; + //virtual void destroy() = 0; private: casRes ( const casRes & ); casRes & operator = ( const casRes & ); @@ -100,90 +104,90 @@ class casMonitor; // class casMonEvent : public casEvent { public: - // - // only used when this is part of another structure - // (and we need to postpone true construction) - // - inline casMonEvent (); - inline casMonEvent (casMonitor &monitor, const smartConstGDDPointer &pNewValue); - inline casMonEvent (const casMonEvent &initValue); - - // - // ~casMonEvent () - // (not inline because this is virtual in the base class) - // + casMonEvent (); + casMonEvent (casMonitor &monitor, const smartConstGDDPointer &pNewValue); + casMonEvent (const casMonEvent &initValue); ~casMonEvent (); - - caStatus cbFunc (casEventSys &); - - // - // casMonEvent::getValue() - // - inline smartConstGDDPointer getValue () const; - - inline void operator = (const class casMonEvent &monEventIn); - - inline void clear (); - + smartConstGDDPointer getValue () const; + void operator = (const class casMonEvent &monEventIn); + void clear (); void assign (casMonitor &monitor, const smartConstGDDPointer &pValueIn); + void * operator new ( size_t size, tsFreeList < class casMonEvent, 1024 > & ); + epicsPlacementDeleteOperator (( void *, tsFreeList < class casMonEvent, 1024 > & )) private: smartConstGDDPointer pValue; caResId id; + void * operator new ( size_t ); + void operator delete ( void * ); + caStatus cbFunc ( casCoreClient & ); + void eventSysDestroyNotify ( casCoreClient & ); }; +class casMonitorCallbackInterface { +public: + virtual caStatus casMonitorCallBack ( casMonitor &, + const smartConstGDDPointer & pValue ) = 0; +}; // // casMonitor() // -class casMonitor : public tsDLNode, public casRes { +class casMonitor : + public tsDLNode < casMonitor >, public casRes { public: - casMonitor(caResId clientIdIn, casChannelI &chan, - unsigned long nElem, unsigned dbrType, - const casEventMask &maskIn, epicsMutex &mutexIn); + casMonitor ( caResId clientIdIn, casChannelI & chan, + unsigned long nElem, unsigned dbrType, + const casEventMask & maskIn, epicsMutex & mutexIn, + casMonitorCallbackInterface & ); virtual ~casMonitor(); - caStatus executeEvent(casMonEvent *); + void show ( unsigned level ) const; - inline void post(const casEventMask &select, const smartConstGDDPointer &pValue); + caStatus executeEvent ( casMonEvent & ); - virtual void show (unsigned level) const; - virtual caStatus callBack (const smartConstGDDPointer &pValue) = 0; + void post ( const casEventMask & select, const smartConstGDDPointer & pValue ); - caResId getClientId() const + caResId getClientId () const { return this->clientId; } - unsigned getType() const + unsigned getType () const { return this->dbrType; } - unsigned long getCount() const + unsigned long getCount () const { return this->nElem; } - casChannelI &getChannel() const + casChannelI & getChannel () const { return this->ciu; } + void * operator new ( size_t size, + tsFreeList < casMonitor, 1024 > & ); + epicsPlacementDeleteOperator (( void *, + tsFreeList < casMonitor, 1024 > & )) private: casMonEvent overFlowEvent; unsigned long const nElem; epicsMutex & mutex; casChannelI & ciu; + casMonitorCallbackInterface & callBackIntf; const casEventMask mask; caResId const clientId; unsigned char const dbrType; unsigned char nPend; bool ovf; bool enabled; - void enable (); void disable (); - - void push (const smartConstGDDPointer &pValue); + casResType resourceType () const; + void push ( const smartConstGDDPointer & pValue ); + void * operator new ( size_t ); + void operator delete ( void * ); casMonitor ( const casMonitor & ); casMonitor & operator = ( const casMonitor & ); }; @@ -210,7 +214,6 @@ inline void casMonitor::post (const casEventMask &select, const smartConstGDDPoi } class caServer; -class casCoreClient; class casChannelI; class casCtx; class caServer; @@ -248,7 +251,9 @@ private: // casEvent virtual call back function // (called when IO completion event reaches top of event queue) // - epicsShareFunc caStatus cbFunc(casEventSys &); + epicsShareFunc caStatus cbFunc ( casCoreClient & ); + + epicsShareFunc void eventSysDestroyNotify ( casCoreClient & ); // // derived class specic call back @@ -274,15 +279,16 @@ class casPVI; // this derives from casEvent so that access rights // events can be posted // -class casChannelI : public tsDLNode, public casRes, - public casEvent { +class casChannelI : public tsDLNode < casChannelI >, + public casRes, public casEvent { public: - casChannelI (const casCtx &ctx); - epicsShareFunc virtual ~casChannelI(); + casChannelI ( const casCtx & ctx ); + epicsShareFunc virtual ~casChannelI (); - void bindToClientI ( casCoreClient & client, casPVI & pv, caResId cid ); + void bindToClientI ( class casCoreClient & client, + casPVI & pv, caResId cid ); - casCoreClient &getClient () const + class casCoreClient & getClient () const { return *this->pClient; } @@ -295,33 +301,23 @@ public: // const caResId getSID (); - // - // addMonitor() - // - void addMonitor (casMonitor &mon); + void installMonitor ( + caResId clientId, + const unsigned long count, + const unsigned type, + const casEventMask & ); - // - // deleteMonitor() - // - void deleteMonitor (casMonitor &mon); - - // - // findMonitor - // (it is reasonable to do a linear search here because - // sane clients will require only one or two monitors - // per channel) - // - tsDLIter findMonitor (const caResId clientIdIn); + bool unistallMonitor ( ca_uint32_t monId ); casPVI &getPVI () const { return *this->pPV; } - void installAsyncIO (casAsyncIOI &); - void removeAsyncIO (casAsyncIOI &); + void installAsyncIO ( casAsyncIOI & ); + void removeAsyncIO ( casAsyncIOI & ); - void postEvent (const casEventMask &select, const gdd &event); + void postEvent ( const casEventMask & select, const gdd & event ); epicsShareFunc virtual casResType resourceType () const; @@ -330,11 +326,6 @@ public: void clearOutstandingReads (); - // - // access rights event call back - // - epicsShareFunc caStatus cbFunc (casEventSys &); - void postAccessRightsEvent (); const gddEnumStringTable & enumStringTable () const; @@ -342,22 +333,24 @@ public: // // virtual functions // - epicsShareFunc virtual void setOwner (const char * const pUserName, - const char * const pHostName) = 0; + epicsShareFunc virtual void setOwner ( const char * const pUserName, + const char * const pHostName ) = 0; epicsShareFunc virtual bool readAccess () const = 0; epicsShareFunc virtual bool writeAccess () const = 0; epicsShareFunc virtual bool confirmationRequested () const = 0; - epicsShareFunc virtual void show (unsigned level) const; + epicsShareFunc virtual void show ( unsigned level ) const; protected: - tsDLList monitorList; - tsDLList ioInProgList; - casCoreClient * pClient; - casPVI * pPV; - caResId cid; // client id - bool accessRightsEvPending:1; + tsDLList < casMonitor > monitorList; + tsDLList < casAsyncIOI > ioInProgList; + class casCoreClient * pClient; + casPVI * pPV; + caResId cid; // client id + bool accessRightsEvPending:1; epicsShareFunc virtual void destroy (); + epicsShareFunc caStatus cbFunc ( casCoreClient & ); // access rights event call back + epicsShareFunc void eventSysDestroyNotify ( casCoreClient & ); casChannelI ( const casChannelI & ); casChannelI & operator = ( const casChannelI & ); }; @@ -369,7 +362,8 @@ class casPVListChan : public casChannelI, public tsDLNode { public: casPVListChan ( const casCtx &ctx ); - void bindToClient ( casCoreClient & client, casPVI & pv, caResId cid ); + void bindToClient ( casCoreClient & client, + casPVI & pv, caResId cidIn ); epicsShareFunc virtual ~casPVListChan(); private: casPVListChan ( const casPVListChan & ); diff --git a/src/cas/generic/casMonEvent.cc b/src/cas/generic/casMonEvent.cc index 476aa850b..a4e30eaa1 100644 --- a/src/cas/generic/casMonEvent.cc +++ b/src/cas/generic/casMonEvent.cc @@ -15,6 +15,7 @@ * 505 665 1831 */ +#include #include "server.h" #include "casEventSysIL.h" // casEventSys in line func @@ -24,30 +25,37 @@ // // casMonEvent::cbFunc() // -caStatus casMonEvent::cbFunc(casEventSys &eSys) +caStatus casMonEvent::cbFunc ( casCoreClient & client ) { - casMonitor *pMon; - caStatus status; - - // - // ignore this event if it is stale and there is - // no call back object associated with it - // - pMon = eSys.resIdToMon(this->id); - if (!pMon) { - /* - * we know this isnt an overflow event because those are - * removed from the queue when the call back object - * is deleted - */ - status = S_casApp_success; - delete this; - } - else { - status = pMon->executeEvent(this); - } - - return status; + caStatus status; + + // + // ignore this event if it is stale and there is + // no call back object associated with it + // + // safe to cast because we have checked the type code + // + casMonitor * pMon = reinterpret_cast < casMonitor * > + ( client.lookupRes ( this->id, casMonitorT ) ); + if ( ! pMon ) { + // we know this isnt an overflow event because those are + // removed from the queue when the casMonitor object is + // destroyed + client.casMonEventDestroy ( *this ); + status = S_casApp_success; + } + else { + // this object may have been destroyed + // here by the executeEvent() call below + status = pMon->executeEvent ( *this ); + } + + return status; +} + +void casMonEvent::eventSysDestroyNotify ( casCoreClient & client ) +{ + client.casMonEventDestroy ( *this ); } // @@ -68,3 +76,37 @@ casMonEvent::~casMonEvent () this->clear(); } +void * casMonEvent::operator new ( size_t size, + tsFreeList < class casMonEvent, 1024 > & freeList ) +{ + return freeList.allocate ( size ); +} + +#ifdef CXX_PLACEMENT_DELETE +void casMonEvent::operator delete ( void *pCadaver, + tsFreeList < class casMonEvent, 1024 > & freeList ) epicsThrows(()) +{ + freeList.release ( pCadaver, sizeof ( casMonEvent ) ); +} +#endif + +void * casMonEvent::operator new ( size_t ) // X aCC 361 +{ + // The HPUX compiler seems to require this even though no code + // calls it directly + throw std::logic_error ( "why is the compiler calling private operator new" ); +} + +void casMonEvent::operator delete ( void * ) +{ + // Visual C++ .net appears to require operator delete if + // placement operator delete is defined? I smell a ms rat + // because if I declare placement new and delete, but + // comment out the placement delete definition there are + // no undefined symbols. + errlogPrintf ( "%s:%d this compiler is confused about placement delete - memory was probably leaked", + __FILE__, __LINE__ ); +} + + + diff --git a/src/cas/generic/casMonitor.cc b/src/cas/generic/casMonitor.cc index 5c1720e38..c80fc68ff 100644 --- a/src/cas/generic/casMonitor.cc +++ b/src/cas/generic/casMonitor.cc @@ -26,27 +26,27 @@ // // casMonitor::casMonitor() // -casMonitor::casMonitor(caResId clientIdIn, casChannelI &chan, - unsigned long nElemIn, unsigned dbrTypeIn, - const casEventMask &maskIn, epicsMutex &mutexIn) : - nElem(nElemIn), - mutex(mutexIn), - ciu(chan), - mask(maskIn), - clientId(clientIdIn), - dbrType(static_cast ( dbrTypeIn ) ), - nPend(0u), - ovf(false), - enabled(false) +casMonitor::casMonitor ( + caResId clientIdIn, + casChannelI & chan, + unsigned long nElemIn, + unsigned dbrTypeIn, + const casEventMask & maskIn, + epicsMutex & mutexIn, + casMonitorCallbackInterface & cb ) : + nElem ( nElemIn ), + mutex ( mutexIn ), + ciu ( chan ), + callBackIntf ( cb ), + mask ( maskIn ), + clientId ( clientIdIn ), + dbrType ( static_cast ( dbrTypeIn ) ), + nPend ( 0u ), + ovf ( false ), + enabled ( false ) { - // - // If these are nill it is a programmer error - // - assert (&this->ciu); - assert (dbrTypeIn<=0xff); - - this->ciu.addMonitor(*this); - + assert ( &this->ciu ); + assert ( dbrTypeIn <= 0xff ); this->enable(); } @@ -56,18 +56,11 @@ casMonitor::casMonitor(caResId clientIdIn, casChannelI &chan, casMonitor::~casMonitor() { epicsGuard < epicsMutex > guard ( this->mutex ); - this->disable(); - - // - // remove from the event system - // if ( this->ovf ) { casCoreClient &client = this->ciu.getClient(); client.removeFromEventQueue ( this->overFlowEvent ); } - - this->ciu.deleteMonitor ( * this ); } // @@ -101,22 +94,22 @@ void casMonitor::disable() // // casMonitor::push() // -void casMonitor::push (const smartConstGDDPointer &pNewValue) +void casMonitor::push ( const smartConstGDDPointer & pNewValue ) { epicsGuard < epicsMutex > guard ( this->mutex ); - casCoreClient &client = this->ciu.getClient (); + casCoreClient & client = this->ciu.getClient (); client.getCAS().incrEventsPostedCounter (); // // get a new block if we havent exceeded quotas // bool full = ( this->nPend >= individualEventEntries ) - || client.casEventSys::full (); + || client.eventSysIsFull (); casMonEvent * pLog; if ( ! full ) { - pLog = new casMonEvent (*this, pNewValue); - if (pLog) { + pLog = & client.casMonEventFactory ( *this, pNewValue ); + if ( pLog ) { this->nPend++; // X aCC 818 } } @@ -165,19 +158,19 @@ void casMonitor::push (const smartConstGDDPointer &pNewValue) // // casMonitor::executeEvent() // -caStatus casMonitor::executeEvent(casMonEvent *pEV) +caStatus casMonitor::executeEvent ( casMonEvent & ev ) { - caStatus status; - smartConstGDDPointer pVal; - - pVal = pEV->getValue (); + smartConstGDDPointer pVal = ev.getValue (); if ( ! pVal ) { assert ( 0 ); } + caStatus status; { epicsGuard < epicsMutex > guard ( this->mutex ); - status = this->callBack ( * pVal ); + status = + this->callBackIntf. + casMonitorCallBack ( *this, *pVal ); } // @@ -197,13 +190,13 @@ caStatus casMonitor::executeEvent(casMonEvent *pEV) // delete event object if it isnt a cache entry // saved in the call back object // - if ( pEV == &this->overFlowEvent ) { + if ( &ev == &this->overFlowEvent ) { assert ( this->ovf ); this->ovf = false; - pEV->clear(); + ev.clear(); } else { - delete pEV; + this->ciu.getClient().casMonEventDestroy ( ev ); } this->ciu.getClient().getCAS().incrEventsProcessedCounter (); @@ -224,3 +217,32 @@ void casMonitor::show ( unsigned level ) const } } +// +// casMonitor::resourceType() +// +casResType casMonitor::resourceType() const +{ + return casMonitorT; +} + +void * casMonitor::operator new ( + size_t size, + tsFreeList < casMonitor, 1024 > & freeList ) + epicsThrows ( ( std::bad_alloc ) ) +{ + return freeList.allocate ( size ); +} + +#ifdef CXX_PLACEMENT_DELETE +void casMonitor::operator delete ( void * pCadaver, + tsFreeList < casMonitor, 1024 > & freeList ) epicsThrows(()) +{ + freeList.release ( pCadaver ); +} +#endif + +void casMonitor::operator delete ( void * ) +{ + errlogPrintf ( "casMonitor: compiler is confused " + "about placement delete?\n" ); +} diff --git a/src/cas/generic/casOpaqueAddr.cc b/src/cas/generic/casOpaqueAddr.cc index 8c6c0e8c0..ffd611030 100644 --- a/src/cas/generic/casOpaqueAddr.cc +++ b/src/cas/generic/casOpaqueAddr.cc @@ -31,7 +31,7 @@ casOpaqueAddr::casOpaqueAddr() // void casOpaqueAddr::clear() { - this->init = 0; + this->init = false; } diff --git a/src/cas/generic/casOpaqueAddrIL.h b/src/cas/generic/casOpaqueAddrIL.h index 86236f9b0..91e0235d6 100644 --- a/src/cas/generic/casOpaqueAddrIL.h +++ b/src/cas/generic/casOpaqueAddrIL.h @@ -24,7 +24,7 @@ inline void casOpaqueAddr::set (const caAddr &addr) // sizeof(casOpaqueAddr::opaqueAddr) < sizeof(caAddr) // *p = addr; - this->init = TRUE; + this->init = true; } // @@ -42,7 +42,7 @@ inline caAddr casOpaqueAddr::get () const { caAddr *p = (caAddr *) this->opaqueAddr; - assert(this->init); + assert ( this->init ); // // see class casOpaqueAddr::checkSize // for assert fail when diff --git a/src/cas/generic/casPV.cc b/src/cas/generic/casPV.cc index 9cea9cf31..a006d59a6 100644 --- a/src/cas/generic/casPV.cc +++ b/src/cas/generic/casPV.cc @@ -25,7 +25,7 @@ #include "casPVIIL.h" // casPVI inline func #include "casCtxIL.h" // casCtx inline func -epicsShareFunc casPV::casPV () +casPV::casPV () { } @@ -33,11 +33,11 @@ epicsShareFunc casPV::casPV () // This constructor is preserved for backwards compatibility only. // Please do _not_ use this constructor. // -epicsShareFunc casPV::casPV (caServer &) +casPV::casPV (caServer &) { } -epicsShareFunc casPV::~casPV () +casPV::~casPV () { } @@ -55,7 +55,7 @@ void casPV::destroy () // // casPV::createChannel() // -epicsShareFunc casChannel *casPV::createChannel (const casCtx &ctx, const char * const, +casChannel *casPV::createChannel (const casCtx &ctx, const char * const, const char * const) { return new casChannel (ctx); @@ -64,7 +64,7 @@ epicsShareFunc casChannel *casPV::createChannel (const casCtx &ctx, const char * // // casPV::interestRegister() // -epicsShareFunc caStatus casPV::interestRegister () +caStatus casPV::interestRegister () { return S_casApp_success; } @@ -72,14 +72,14 @@ epicsShareFunc caStatus casPV::interestRegister () // // casPV::interestDelete() // -epicsShareFunc void casPV::interestDelete () +void casPV::interestDelete () { } // // casPV::beginTransaction() // -epicsShareFunc caStatus casPV::beginTransaction () +caStatus casPV::beginTransaction () { return S_casApp_success; } @@ -87,14 +87,14 @@ epicsShareFunc caStatus casPV::beginTransaction () // // casPV::endTransaction() // -epicsShareFunc void casPV::endTransaction () +void casPV::endTransaction () { } // // casPV::read() // -epicsShareFunc caStatus casPV::read (const casCtx &, gdd &) +caStatus casPV::read (const casCtx &, gdd &) { return S_casApp_noSupport; } @@ -102,7 +102,7 @@ epicsShareFunc caStatus casPV::read (const casCtx &, gdd &) // // casPV::write() // -epicsShareFunc caStatus casPV::write (const casCtx &, const gdd &) +caStatus casPV::write (const casCtx &, const gdd &) { return S_casApp_noSupport; } @@ -110,7 +110,7 @@ epicsShareFunc caStatus casPV::write (const casCtx &, const gdd &) // // casPV::bestExternalType() // -epicsShareFunc aitEnum casPV::bestExternalType () const +aitEnum casPV::bestExternalType () const { return aitEnumString; } @@ -119,7 +119,7 @@ epicsShareFunc aitEnum casPV::bestExternalType () const // casPV::maxDimension() // (base returns zero - scalar) // -epicsShareFunc unsigned casPV::maxDimension () const +unsigned casPV::maxDimension () const { return 0u; } @@ -128,7 +128,7 @@ epicsShareFunc unsigned casPV::maxDimension () const // casPV::maxBound() // (base returns scalar bound independent of the dimension arg) // -epicsShareFunc aitIndex casPV::maxBound (unsigned /* dimension */) const +aitIndex casPV::maxBound (unsigned /* dimension */) const { return 1u; } @@ -136,7 +136,7 @@ epicsShareFunc aitIndex casPV::maxBound (unsigned /* dimension */) const // // casPV::show (unsigned level) // -epicsShareFunc void casPV::show (unsigned level) const +void casPV::show (unsigned level) const { casPVI::show (level); } @@ -144,7 +144,7 @@ epicsShareFunc void casPV::show (unsigned level) const // // Server tool calls this function to post a PV event. // -epicsShareFunc void casPV::postEvent (const casEventMask &select, const gdd &event) +void casPV::postEvent (const casEventMask &select, const gdd &event) { this->casPVI::postEvent (select, event); } @@ -156,7 +156,7 @@ epicsShareFunc void casPV::postEvent (const casEventMask &select, const gdd &eve // into a server. // *************** // -epicsShareFunc caServer *casPV::getCAS () const +caServer *casPV::getCAS () const { return this->casPVI::getExtServer (); } diff --git a/src/cas/generic/casPVI.cc b/src/cas/generic/casPVI.cc index c45953348..d6e363603 100644 --- a/src/cas/generic/casPVI.cc +++ b/src/cas/generic/casPVI.cc @@ -350,7 +350,7 @@ caServer *casPVI::getExtServer() const // X aCC 361 // // casPVI::show() // -epicsShareFunc void casPVI::show (unsigned level) const +void casPVI::show (unsigned level) const { if (level>1u) { printf ("CA Server PV: nChanAttached=%u nMonAttached=%u nIOAttached=%u\n", @@ -364,7 +364,7 @@ epicsShareFunc void casPVI::show (unsigned level) const // // casPVI::resourceType() // -epicsShareFunc casResType casPVI::resourceType() const +casResType casPVI::resourceType() const { return casPVT; } @@ -373,7 +373,7 @@ epicsShareFunc casResType casPVI::resourceType() const // casPVI::apiPointer() // retuns NULL if casPVI isnt a base of casPV // -epicsShareFunc casPV *casPVI::apiPointer () +casPV *casPVI::apiPointer () { return NULL; } diff --git a/src/cas/generic/casPVListChan.cc b/src/cas/generic/casPVListChan.cc index 332b43a1a..2d25abfb7 100644 --- a/src/cas/generic/casPVListChan.cc +++ b/src/cas/generic/casPVListChan.cc @@ -27,7 +27,8 @@ casPVListChan::casPVListChan (const casCtx &ctx) : { } -void casPVListChan::bindToClient ( casCoreClient & client, casPVI & pv, caResId cidIn ) +void casPVListChan::bindToClient ( + casCoreClient & client, casPVI & pv, caResId cidIn ) { this->bindToClientI ( client, pv, cidIn ); this->pPV->installChannel ( *this ); diff --git a/src/cas/generic/casStrmClient.cc b/src/cas/generic/casStrmClient.cc index e809be057..7a2a80279 100644 --- a/src/cas/generic/casStrmClient.cc +++ b/src/cas/generic/casStrmClient.cc @@ -144,22 +144,21 @@ caStatus casStrmClient::verifyRequest (casChannelI *&pChan) // // find the monitor associated with a resource id // -inline casClientMon *caServerI::resIdToClientMon (const caResId &idIn) +inline casClientMon * caServerI::resIdToClientMon ( + const caResId & idIn ) { - casRes *pRes; - - pRes = this->lookupRes(idIn, casClientMonT); + casRes * pRes = this->lookupRes ( idIn, casMonitorT ); // // cast is ok since the type code was verified // (and we know casClientMon derived from resource) // - return (casClientMon *) pRes; + return reinterpret_cast < casClientMon * > ( pRes ); } // // casStrmClient::show (unsigned level) // -void casStrmClient::show (unsigned level) const +void casStrmClient::show ( unsigned level ) const { this->casClient::show (level); printf ( "casStrmClient at %p\n", @@ -259,7 +258,7 @@ caStatus casStrmClient::readResponse ( casChannelI * pChan, const caHdrLargeArra } #ifdef CONVERSION_REQUIRED ( * cac_dbr_cvrt[msg.m_dataType] ) - ( pPayload, pPayload, TRUE, msg.m_count ); + ( pPayload, pPayload, true, msg.m_count ); #endif if ( msg.m_dataType == DBR_STRING && msg.m_count == 1u ) { @@ -380,7 +379,7 @@ caStatus casStrmClient::readNotifyResponse ( casChannelI * pChan, #ifdef CONVERSION_REQUIRED ( * cac_dbr_cvrt[ msg.m_dataType ] ) - ( pPayload, pPayload, TRUE, msg.m_count ); + ( pPayload, pPayload, true, msg.m_count ); #endif if ( msg.m_dataType == DBR_STRING && msg.m_count == 1u ) { @@ -515,7 +514,7 @@ static smartGDDPointer createDBRDD ( unsigned dbrType, unsigned elemCount ) } // -// casStrmClient::monitorResponse () +// casStrmClient::monitorFailureResponse () // caStatus casStrmClient::monitorFailureResponse ( const caHdrLargeArray & msg, const caStatus ECA_XXXX ) @@ -604,7 +603,7 @@ caStatus casStrmClient::monitorResponse ( casChannelI & chan, const caHdrLargeAr #ifdef CONVERSION_REQUIRED /* use type as index into conversion jumptable */ (* cac_dbr_cvrt[msg.m_dataType]) - ( pPayload, pPayload, TRUE, msg.m_count ); + ( pPayload, pPayload, true, msg.m_count ); #endif // // force string message size to be the true size @@ -1026,7 +1025,8 @@ caStatus casStrmClient::createChanResponse ( const caHdrLargeArray & hdr, const // create server tool XXX derived from casChannel // this->ctx.setPV ( pPV ); - casChannel * pChan = pPV->createChannel ( this->ctx, this->pUserName, this->pHostName ); + casChannel * pChan = pPV->createChannel ( + this->ctx, this->pUserName, this->pHostName ); if ( ! pChan ) { pPV->deleteSignal(); return this->channelCreateFailedResp ( hdr, S_cas_noMemory ); @@ -1220,7 +1220,7 @@ caStatus casStrmClient::disconnectChan ( caResId id ) // caStatus casStrmClient::eventsOnAction () { - this->casEventSys::eventsOn(); + this->enableEvents (); return S_cas_success; } @@ -1229,7 +1229,8 @@ caStatus casStrmClient::eventsOnAction () // caStatus casStrmClient::eventsOffAction() { - return this->casEventSys::eventsOff(); + this->disableEvents (); + return S_cas_success; } // @@ -1240,7 +1241,6 @@ caStatus casStrmClient::eventAddAction () const caHdrLargeArray *mp = this->ctx.getMsg(); struct mon_info *pMonInfo = (struct mon_info *) this->ctx.getData(); - casClientMon *pMonitor; casChannelI *pciu; smartGDDPointer pDD; caStatus status; @@ -1306,24 +1306,14 @@ caStatus casStrmClient::eventAddAction () return S_cas_success; } else { - status = this->monitorResponse ( *pciu, *mp, pDD, status ); + status = this->monitorResponse ( *pciu, + *mp, pDD, status ); } if ( status == S_cas_success ) { - - pMonitor = new casClientMon ( *pciu, mp->m_available, - mp->m_count, mp->m_dataType, mask, this->mutex ); - if ( ! pMonitor ) { - status = this->sendErr ( mp, ECA_ALLOCMEM, NULL ); - if ( status==S_cas_success ) { - // - // If we cant allocate space for a monitor then - // delete (disconnect) the channel - // - pciu->destroyClientNotify (); - } - return status; - } + pciu->installMonitor ( + mp->m_available, mp->m_count, + mp->m_dataType, mask ); } return status; @@ -1390,13 +1380,11 @@ caStatus casStrmClient::eventCancelAction () { const caHdrLargeArray * mp = this->ctx.getMsg (); const void * dp = this->ctx.getData (); - casChannelI *pciu; - int status; /* * Verify the channel */ - pciu = this->resIdToChannel ( mp->m_cid ); + casChannelI *pciu = this->resIdToChannel ( mp->m_cid ); if ( ! pciu ) { /* * it is possible that the event delete arrives just @@ -1409,27 +1397,21 @@ caStatus casStrmClient::eventCancelAction () return S_cas_badResourceId; } - /* - * verify the event (monitor) - */ - tsDLIter pMon = pciu->findMonitor ( mp->m_available ); - if ( ! pMon.valid () ) { - // - // this indicates client or server library corruption so a - // disconnect is the best response - // - logBadId ( mp, dp, ECA_BADMONID, mp->m_available ); - return S_cas_badResourceId; - } - - unsigned type = pMon->getType (); - assert ( type <= 0xff ); - status = this->out.copyInHeader ( CA_PROTO_EVENT_ADD, 0, - static_cast ( type ), pMon->getCount (), - pciu->getCID (), pMon->getClientId (), 0 ); + int status = this->out.copyInHeader ( + CA_PROTO_EVENT_ADD, 0, + mp->m_dataType, mp->m_count, + pciu->getCID (), mp->m_available, 0 ); if ( ! status ) { + if ( ! pciu->unistallMonitor ( mp->m_available ) ) { + // + // this indicates client or server library + // corruption so a disconnect is probably + // the best option + // + logBadId ( mp, dp, ECA_BADMONID, mp->m_available ); + status = S_cas_badResourceId; + } this->out.commitMsg (); - pMon->destroy (); } return status; @@ -1444,10 +1426,10 @@ caStatus casStrmClient::eventCancelAction () */ caStatus casStrmClient::noReadAccessEvent(casClientMon *pMon) { - caHdr falseReply; - unsigned size; - caHdr *reply; - int status; + caHdr falseReply; + unsigned size; + caHdr * reply; + int status; size = dbr_size_n ( pMon->getType(), pMon->getCount() ); @@ -1581,7 +1563,7 @@ caStatus casStrmClient::write() (* cac_dbr_cvrt[pHdr->m_dataType]) ( this->ctx.getData(), this->ctx.getData(), - FALSE, /* net -> host format */ + false, /* net -> host format */ pHdr->m_count); #endif @@ -1973,5 +1955,32 @@ void casStrmClient::flush () this->out.flush (); } +// +// casStrmClient::casMonitorCallBack() +// +caStatus casStrmClient::casMonitorCallBack ( + casMonitor & mon, const smartConstGDDPointer & value ) +{ + caStatus status; + caHdrLargeArray msg; + + // + // reconstruct the msg header + // + msg.m_cmmd = CA_PROTO_EVENT_ADD; + msg.m_postsize = 0u; + unsigned type = mon.getType(); + assert ( type <= 0xffff ); + msg.m_dataType = static_cast ( type ); + unsigned long count = mon.getCount(); + assert ( count <= 0xffffffff ); + msg.m_count = static_cast ( count ); + msg.m_cid = mon.getChannel().getSID(); + msg.m_available = mon.getClientId(); + + status = this->monitorResponse ( mon.getChannel(), + msg, value, S_cas_success ); + return status; +} diff --git a/src/cas/generic/casdef.h b/src/cas/generic/casdef.h index 74800f9d6..90aa585f0 100644 --- a/src/cas/generic/casdef.h +++ b/src/cas/generic/casdef.h @@ -601,6 +601,7 @@ public: // epicsShareFunc casPV *getPV (); +private: casChannel ( const casChannel & ); casChannel & operator = ( const casChannel & ); diff --git a/src/cas/generic/server.h b/src/cas/generic/server.h index 24a0ac02f..80b1f129c 100644 --- a/src/cas/generic/server.h +++ b/src/cas/generic/server.h @@ -96,83 +96,6 @@ typedef caResId caEventId; // class caServerI; -// -// casEventSys -// -class casEventSys { -friend class casEventPurgeEv; -public: - casEventSys (); - virtual ~casEventSys (); - - void show (unsigned level) const; - casProcCond process (); - - void installMonitor (); - void removeMonitor (); - - void removeFromEventQueue (casEvent &); - void addToEventQueue (casEvent &); - - void insertEventQueue (casEvent &insert, casEvent &prevEvent); - void pushOnToEventQueue (casEvent &event); - - bool full (); - - casMonitor *resIdToMon (const caResId id); - - bool getNDuplicateEvents () const; - - void setDestroyPending (); - - void eventsOn (); - - caStatus eventsOff (); - - virtual caStatus disconnectChan (caResId id) = 0; - -private: - tsDLList eventLogQue; - epicsMutex mutex; - casEventPurgeEv *pPurgeEvent; // flow control purge complete event - unsigned numEventBlocks; // N event blocks installed - unsigned maxLogEntries; // max log entries - unsigned char destroyPending; - unsigned char replaceEvents; // replace last existing event on queue - unsigned char dontProcess; // flow ctl is on - dont process event queue - - virtual void eventFlush () = 0; - virtual void eventSignal () = 0; - virtual casRes *lookupRes (const caResId &idIn, casResType type) = 0; - casEventSys ( const casEventSys & ); - casEventSys & operator = ( const casEventSys & ); -}; - -// -// casClientMon -// -class casClientMon : public casMonitor { -public: - casClientMon(casChannelI &, caResId clientId, - const unsigned long count, const unsigned type, - const casEventMask &maskIn, epicsMutex &mutexIn); - virtual ~casClientMon(); - - caStatus callBack (const smartConstGDDPointer &pValue); - - virtual casResType resourceType() const; - - caResId getId() const - { - return this->casRes::getId(); - } - - virtual void destroy(); -private: - casClientMon ( const casClientMon & ); - casClientMon & operator = ( const casClientMon & ); -}; - class casCtx { public: casCtx(); @@ -195,7 +118,7 @@ public: void setPV ( casPVI * p ); - void setChannel ( casChannelI * p ); + void setChannel ( casChannelI * p ); void show ( unsigned level ) const; @@ -430,25 +353,89 @@ private: outBuf & operator = ( const outBuf & ); }; +// +// casEventSys +// +class casEventSys { +public: + casEventSys ( casCoreClient & ); + ~casEventSys (); + + void show ( unsigned level ) const; + struct processStatus { + casProcCond cond; + unsigned nAccepted; + }; + processStatus process (); + + void installMonitor (); + void removeMonitor (); + + void removeFromEventQueue ( casEvent & ); + void addToEventQueue ( casEvent & ); + + void insertEventQueue ( casEvent & insert, casEvent & prevEvent ); + void pushOnToEventQueue ( casEvent & event ); + + bool full (); + + bool getNDuplicateEvents () const; + + void setDestroyPending (); + + void eventsOn (); + void eventsOff (); + +private: + tsDLList < casEvent > eventLogQue; + epicsMutex mutex; + casCoreClient & client; + class casEventPurgeEv * pPurgeEvent; // flow control purge complete event + unsigned numEventBlocks; // N event blocks installed + unsigned maxLogEntries; // max log entries + bool destroyPending; + bool replaceEvents; // replace last existing event on queue + bool dontProcess; // flow ctl is on - dont process event queue + + casEventSys ( const casEventSys & ); + casEventSys & operator = ( const casEventSys & ); + friend class casEventPurgeEv; +}; + +/* + * when this event reaches the top of the queue we + * know that all duplicate events have been purged + * and that now no events should not be sent to the + * client until it exits flow control mode + */ +class casEventPurgeEv : public casEvent { +public: + casEventPurgeEv ( class casEventSys & ); +private: + casEventSys & evSys; + caStatus cbFunc ( casCoreClient & ); + void eventSysDestroyNotify ( casCoreClient & ); +}; + // // casCoreClient // (this will eventually support direct communication // between the client lib and the server lib) // -class casCoreClient : public ioBlocked, - public casEventSys { +class casCoreClient : public ioBlocked, + private casMonitorCallbackInterface { public: - casCoreClient ( caServerI &serverInternal ); - virtual ~casCoreClient(); - virtual void destroy(); + casCoreClient ( caServerI & serverInternal ); + virtual ~casCoreClient (); + virtual void destroy (); virtual caStatus disconnectChan( caResId id ); - virtual void show (unsigned level ) const; + virtual void show ( unsigned level ) const; virtual void installChannel ( casChannelI & ); virtual void removeChannel ( casChannelI & ); - void installAsyncIO( casAsyncIOI & ioIn ); + void installAsyncIO ( casAsyncIOI & ioIn ); - void removeAsyncIO( casAsyncIOI & ioIn ); + void removeAsyncIO ( casAsyncIOI & ioIn ); casRes * lookupRes ( const caResId &idIn, casResType type ); @@ -481,6 +468,8 @@ public: virtual caStatus channelCreateFailedResp ( const caHdrLargeArray &, caStatus createStatus ); + virtual void eventSignal () = 0; + virtual ca_uint16_t protocolRevision () const = 0; // @@ -491,12 +480,42 @@ public: bool okToStartAsynchIO (); + casMonEvent & casMonEventFactory ( casMonitor & monitor, + const smartConstGDDPointer & pNewValue ); + void casMonEventDestroy ( casMonEvent & ); + + casEventSys::processStatus eventSysProcess(); + + void addToEventQueue ( casEvent & ); + void insertEventQueue ( casEvent & insert, + casEvent & prevEvent ); + void removeFromEventQueue ( casEvent & ); + void enableEvents (); + void disableEvents (); + bool eventSysIsFull (); + void installMonitor (); + void removeMonitor (); + + void setDestroyPending (); + + casMonitor & monitorFactory ( + casChannelI & , + caResId clientId, + const unsigned long count, + const unsigned type, + const casEventMask & ); + void destroyMonitor ( casMonitor & ); + + caStatus casMonitorCallBack ( casMonitor &, + const smartConstGDDPointer & ); + protected: epicsMutex mutex; casCtx ctx; bool asyncIOFlag; private: + casEventSys eventSys; tsDLList < casAsyncIOI > ioInProgList; casCoreClient ( const casCoreClient & ); casCoreClient & operator = ( const casCoreClient & ); @@ -585,7 +604,7 @@ private: // static void loadProtoJumpTable(); static pCASMsgHandler msgHandlers[CA_PROTO_LAST_CMMD+1u]; - static int msgHandlersInit; + static bool msgHandlersInit; casClient ( const casClient & ); casClient & operator = ( const casClient & ); @@ -594,13 +613,14 @@ private: // // casStrmClient // -class casStrmClient : public casClient, +class casStrmClient : + public casClient, public tsDLNode { public: casStrmClient ( caServerI &, clientBufMemoryManager & ); virtual ~casStrmClient(); - void show (unsigned level) const; + void show ( unsigned level ) const; void flush (); @@ -632,9 +652,6 @@ public: caStatus channelCreateFailedResp ( const caHdrLargeArray &, caStatus createStatus ); - caStatus noReadAccessEvent( casClientMon * ); - - caStatus disconnectChan ( caResId id ); unsigned getDebugLevel () const; @@ -642,8 +659,6 @@ public: virtual void hostName ( char * pBuf, unsigned bufSize ) const = 0; void userName ( char * pBuf, unsigned bufSize ) const; -protected: - private: tsDLList chanList; char *pUserName; @@ -716,6 +731,9 @@ private: caStatus writeNotifyResponseECA_XXX ( const caHdrLargeArray &msg, const caStatus status ); + caStatus casMonitorCallBack ( casMonitor &, + const smartConstGDDPointer & pValue ); + casStrmClient ( const casStrmClient & ); casStrmClient & operator = ( const casStrmClient & ); }; @@ -754,11 +772,6 @@ public: protected: - casProcCond eventSysProcess() - { - return this->casEventSys::process(); - } - caStatus processDG (); private: @@ -906,9 +919,9 @@ public: caServer *getAdapter (); - void installItem (casRes &res); + void installItem ( casRes & res ); - casRes *removeItem (casRes &res); + casRes * removeItem ( casRes & res ); // // call virtual function in the interface class @@ -936,24 +949,36 @@ public: void generateBeaconAnomaly (); + casMonEvent & casMonEventFactory ( casMonitor & monitor, + const smartConstGDDPointer & pNewValue ); + void casMonEventDestroy ( casMonEvent & ); + + casMonitor & casMonitorFactory ( casChannelI &, + caResId clientId, const unsigned long count, + const unsigned type, const casEventMask &, + epicsMutex & , casMonitorCallbackInterface & ); + void casMonitorDestroy ( casMonitor & ); + private: - clientBufMemoryManager clientBufMemMgr; - mutable epicsMutex mutex; - tsDLList clientList; - tsDLList intfList; - caServer & adapter; - beaconTimer & beaconTmr; - beaconAnomalyGovernor & beaconAnomalyGov; - unsigned debugLevel; - unsigned nEventsProcessed; - unsigned nEventsPosted; + clientBufMemoryManager clientBufMemMgr; + mutable epicsMutex mutex; + tsDLList < casStrmClient > clientList; + tsDLList < casIntfOS > intfList; + tsFreeList < casMonEvent, 1024 > casMonEventFreeList; + tsFreeList < casMonitor, 1024 > casMonitorFreeList; + caServer & adapter; + beaconTimer & beaconTmr; + beaconAnomalyGovernor & beaconAnomalyGov; + unsigned debugLevel; + unsigned nEventsProcessed; + unsigned nEventsPosted; // // predefined event types // - casEventMask valueEvent; // DBE_VALUE registerEvent("value") - casEventMask logEvent; // DBE_LOG registerEvent("log") - casEventMask alarmEvent; // DBE_ALARM registerEvent("alarm") + casEventMask valueEvent; // DBE_VALUE registerEvent("value") + casEventMask logEvent; // DBE_LOG registerEvent("log") + casEventMask alarmEvent; // DBE_ALARM registerEvent("alarm") caStatus attachInterface (const caNetAddr &addr, bool autoBeaconAddr, bool addConfigAddr); @@ -978,18 +1003,6 @@ private: */ #define maxIOInProg 50 -/* - * when this event reaches the top of the queue we - * know that all duplicate events have been purged - * and that now no events should not be sent to the - * client until it exits flow control mode - */ -class casEventPurgeEv : public casEvent { -public: -private: - caStatus cbFunc(casEventSys &); -}; - bool convertContainerMemberToAtomic ( gdd & dd, aitUint32 appType, aitUint32 elemCount ); diff --git a/src/cas/generic/st/casDGIntfOS.cc b/src/cas/generic/st/casDGIntfOS.cc index cdf2c07f0..eae55ebbb 100644 --- a/src/cas/generic/st/casDGIntfOS.cc +++ b/src/cas/generic/st/casDGIntfOS.cc @@ -23,6 +23,7 @@ #include "inBufIL.h" // inBuf in line func #include "outBufIL.h" // outBuf in line func #include "casIODIL.h" // IO Depen in line func +#include "casCoreClientIL.h" // // casDGReadReg @@ -145,7 +146,10 @@ void casDGEvWakeup::show ( unsigned level ) const // epicsTimerNotify::expireStatus casDGEvWakeup::expire ( const epicsTime & /* currentTime */ ) { - this->pOS->casEventSys::process(); + casEventSys::processStatus ps = this->pOS->eventSysProcess (); + if ( ps.nAccepted > 0u ) { + this->pOS->eventFlush (); + } this->pOS = 0; return noRestart; } @@ -441,7 +445,7 @@ void casDGIntfOS::sendCB() // we _are_ able to write to see if additional events // can be sent to the slow client. // - this->casEventSys::process(); + this->eventSysProcess (); // // If we were able to send something then we need diff --git a/src/cas/generic/st/casOSD.h b/src/cas/generic/st/casOSD.h index 0d3b5f2a2..5fba2b166 100644 --- a/src/cas/generic/st/casOSD.h +++ b/src/cas/generic/st/casOSD.h @@ -100,6 +100,8 @@ public: void processInput(); + void eventFlush (); + private: casDGIOWakeup ioWk; casDGEvWakeup evWk; @@ -122,7 +124,6 @@ private: void ioBlockedSignal (); void eventSignal (); - void eventFlush (); casDGIntfOS ( const casDGIntfOS & ); casDGIntfOS & operator = ( const casDGIntfOS & ); @@ -199,6 +200,8 @@ public: casProcCond processInput (); + void eventFlush (); + private: casStreamEvWakeup evWk; casStreamIOWakeup ioWk; @@ -221,7 +224,6 @@ private: void ioBlockedSignal (); void eventSignal (); - void eventFlush (); casStreamOS ( const casStreamOS & ); casStreamOS & operator = ( const casStreamOS & ); diff --git a/src/cas/generic/st/casStreamOS.cc b/src/cas/generic/st/casStreamOS.cc index 3fee5461c..82606d9a6 100644 --- a/src/cas/generic/st/casStreamOS.cc +++ b/src/cas/generic/st/casStreamOS.cc @@ -90,7 +90,7 @@ private: // casStreamWriteReg::casStreamWriteReg() // inline casStreamWriteReg::casStreamWriteReg (casStreamOS &osIn) : - fdReg (osIn.getFD(), fdrWrite, TRUE), os (osIn) + fdReg (osIn.getFD(), fdrWrite, true), os (osIn) { # if defined(DEBUG) printf ("Write on %d\n", this->os.getFD()); @@ -148,10 +148,14 @@ void casStreamEvWakeup::show(unsigned level) const // epicsTimerNotify::expireStatus casStreamEvWakeup::expire ( const epicsTime & /* currentTime */ ) { - casStreamOS &os = *this->pOS; + casStreamOS & os = *this->pOS; this->pOS = 0; - casProcCond cond = os.casEventSys::process(); - if ( cond != casProcOk ) { + + casEventSys::processStatus ps = os.eventSysProcess (); + if ( ps.nAccepted > 0u ) { + os.eventFlush (); + } + if ( ps.cond != casProcOk ) { // // ok to delete the client here // because casStreamEvWakeup::expire() @@ -396,20 +400,17 @@ void casStreamReadReg::callBack () // void casStreamOS::recvCB() { - inBufClient::fillCondition fillCond; - casProcCond procCond; - assert ( this->pRdReg ); // // copy in new messages // - fillCond = this->in.fill(); + inBufClient::fillCondition fillCond = this->in.fill(); if ( fillCond == casFillDisconnect ) { delete this; } else { - procCond = this->processInput(); + casProcCond procCond = this->processInput(); if (procCond == casProcDisconnect) { delete this; } @@ -438,8 +439,8 @@ void casStreamOS::recvCB() // void casStreamOS::sendBlockSignal() { - this->sendBlocked=TRUE; - this->armSend(); + this->sendBlocked = true; + this->armSend (); } // @@ -470,16 +471,13 @@ void casStreamWriteReg::callBack() // void casStreamOS::sendCB() { - outBufClient::flushCondition flushCond; - casProcCond procCond; - // // attempt to flush the output buffer // - flushCond = this->out.flush (); + outBufClient::flushCondition flushCond = this->out.flush (); if (flushCond==flushProgress) { - if (this->sendBlocked) { - this->sendBlocked = FALSE; + if ( this->sendBlocked ) { + this->sendBlocked = false; } } else if ( flushCond == outBufClient::flushDisconnect ) { @@ -506,8 +504,8 @@ void casStreamOS::sendCB() // we _are_ able to write to see if additional events // can be sent to the slow client. // - procCond = this->casEventSys::process(); - if (procCond != casProcOk) { + casEventSys::processStatus ps = this->eventSysProcess (); + if ( ps.cond != casProcOk ) { // // ok to delete the client here // because casStreamWriteReg::callBack() @@ -536,7 +534,7 @@ void casStreamOS::sendCB() // to process the input queue in case we were send // blocked. // - procCond = this->processInput(); + casProcCond procCond = this->processInput(); if (procCond == casProcDisconnect) { delete this; } diff --git a/src/cas/io/bsdSocket/caServerIO.cc b/src/cas/io/bsdSocket/caServerIO.cc index 807c55d82..3bbaa50a5 100644 --- a/src/cas/io/bsdSocket/caServerIO.cc +++ b/src/cas/io/bsdSocket/caServerIO.cc @@ -149,7 +149,7 @@ inline void caServerIO::staticInit() epicsSignalInstallSigPipeIgnore (); - caServerIO::staticInitialized = TRUE; + caServerIO::staticInitialized = true; } // diff --git a/src/cas/io/bsdSocket/casDGIntfIO.cc b/src/cas/io/bsdSocket/casDGIntfIO.cc index 04e1b3139..b3f29c02b 100644 --- a/src/cas/io/bsdSocket/casDGIntfIO.cc +++ b/src/cas/io/bsdSocket/casDGIntfIO.cc @@ -293,7 +293,7 @@ void casDGIntfIO::show (unsigned level) const void casDGIntfIO::xSetNonBlocking() { int status; - osiSockIoctl_t yes = TRUE; + osiSockIoctl_t yes = true; status = socket_ioctl(this->sock, FIONBIO, &yes); // X aCC 392 if (status<0) { @@ -544,7 +544,7 @@ bufSizeT casDGIntfIO::optimumOutBufferSize () // SOCKET casDGIntfIO::makeSockDG () { - int yes = TRUE; + int yes = true; int status; SOCKET newSock; diff --git a/src/cas/io/bsdSocket/casIntfIO.cc b/src/cas/io/bsdSocket/casIntfIO.cc index 45293b9ca..fcc411979 100644 --- a/src/cas/io/bsdSocket/casIntfIO.cc +++ b/src/cas/io/bsdSocket/casIntfIO.cc @@ -54,7 +54,7 @@ casIntfIO::casIntfIO (const caNetAddr &addrIn) : * they exit ( even if SO_REUSEADDR isnt set ). */ # ifndef SO_REUSEADDR_ALLOWS_SIMULTANEOUS_TCP_SERVERS_TO_USE_SAME_PORT - int yes = TRUE; + int yes = true; status = setsockopt ( this->sock, SOL_SOCKET, @@ -203,7 +203,7 @@ casStreamOS *casIntfIO::newStreamClient ( caServerI & cas, void casIntfIO::setNonBlocking() { int status; - osiSockIoctl_t yes = TRUE; + osiSockIoctl_t yes = true; status = socket_ioctl(this->sock, FIONBIO, &yes); // X aCC 392 if (status<0) { diff --git a/src/cas/io/bsdSocket/casStreamIO.cc b/src/cas/io/bsdSocket/casStreamIO.cc index 905e787dc..538f5966f 100644 --- a/src/cas/io/bsdSocket/casStreamIO.cc +++ b/src/cas/io/bsdSocket/casStreamIO.cc @@ -22,7 +22,7 @@ casStreamIO::casStreamIO ( caServerI & cas, clientBufMemoryManager & bufMgr, blockingFlag ( xIsBlocking ) { assert (sock>=0); - int yes = TRUE; + int yes = true; int status; /* @@ -129,16 +129,16 @@ outBufClient::flushCondition casStreamIO::osdSend ( const char *pInBuf, bufSizeT int anerrno = SOCKERRNO; if (anerrno != SOCK_EWOULDBLOCK) { - char buf[64]; int errnoCpy = SOCKERRNO; - - ipAddrToA (&this->addr, buf, sizeof(buf)); - if ( errnoCpy != SOCK_ECONNABORTED && errnoCpy != SOCK_ECONNRESET && errnoCpy != SOCK_EPIPE && errnoCpy != SOCK_ETIMEDOUT ) { + + char buf[64]; + ipAddrToA (&this->addr, buf, sizeof(buf)); + errlogPrintf( "CAS: TCP socket send to \"%s\" failed because \"%s\"\n", buf, SOCKERRSTR(errnoCpy)); @@ -215,7 +215,7 @@ void casStreamIO::osdShow (unsigned level) const void casStreamIO::xSetNonBlocking() { int status; - osiSockIoctl_t yes = TRUE; + osiSockIoctl_t yes = true; status = socket_ioctl(this->sock, FIONBIO, &yes); // X aCC 392 if (status>=0) {