From adb0b5d9eb4c4e26edd81d17a018d4f9fd8384e6 Mon Sep 17 00:00:00 2001 From: Jeff Hill Date: Wed, 8 Jan 2003 23:22:08 +0000 Subject: [PATCH] redesigned mutex locking --- src/cas/generic/caServerI.cc | 2 +- src/cas/generic/caServerIIL.h | 4 +- src/cas/generic/casAsyncIOI.cc | 59 +++-------- src/cas/generic/casAsyncReadIO.cc | 17 ++-- src/cas/generic/casAsyncWriteIO.cc | 1 - src/cas/generic/casChannelI.cc | 46 +++------ src/cas/generic/casChannelIIL.h | 23 ++--- src/cas/generic/casCoreClient.cc | 154 ++++++++++++++++++++++++++--- src/cas/generic/casCoreClientIL.h | 60 ----------- src/cas/generic/casCtxIL.h | 2 +- src/cas/generic/casEventSys.cc | 61 ++++-------- src/cas/generic/casEventSysIL.h | 8 +- src/cas/generic/casInternal.h | 37 ++++--- src/cas/generic/casMonitor.cc | 10 +- src/cas/generic/casPV.cc | 4 +- src/cas/generic/casPVListChan.cc | 7 -- src/cas/generic/casStrmClient.cc | 42 ++++---- src/cas/generic/server.h | 29 ++++-- src/cas/generic/st/casStreamOS.cc | 6 +- 19 files changed, 270 insertions(+), 302 deletions(-) diff --git a/src/cas/generic/caServerI.cc b/src/cas/generic/caServerI.cc index c867445d8..9c085f4bb 100644 --- a/src/cas/generic/caServerI.cc +++ b/src/cas/generic/caServerI.cc @@ -79,7 +79,7 @@ caServerI::~caServerI() // // destructor takes client out of list // - iter->destroy (); + delete iter.pointer (); iter = tmp; } diff --git a/src/cas/generic/caServerIIL.h b/src/cas/generic/caServerIIL.h index 9bba6019c..956230b91 100644 --- a/src/cas/generic/caServerIIL.h +++ b/src/cas/generic/caServerIIL.h @@ -151,12 +151,12 @@ inline void caServerI::casMonEventDestroy ( casMonEvent & monEvent ) inline casMonitor & caServerI::casMonitorFactory ( casChannelI & chan, caResId clientId, const unsigned long count, const unsigned type, - const casEventMask & mask, epicsMutex & mutexIn, + const casEventMask & mask, casMonitorCallbackInterface & cb ) { casMonitor * pMon = new ( this->casMonitorFreeList ) casMonitor - ( clientId, chan, count, type, mask, mutexIn, cb ); + ( clientId, chan, count, type, mask, cb ); this->installItem ( *pMon ); return *pMon; } diff --git a/src/cas/generic/casAsyncIOI.cc b/src/cas/generic/casAsyncIOI.cc index ab895135f..017c99c78 100644 --- a/src/cas/generic/casAsyncIOI.cc +++ b/src/cas/generic/casAsyncIOI.cc @@ -84,30 +84,20 @@ casAsyncIOI::~casAsyncIOI() "WARNING: by deleting the async IO object.\n"); } - epicsGuard < casCoreClient > guard ( this->client ); - // // pulls itself out of the event queue - // if it is installed there + // if it is installed there. // - if ( this->inTheEventQueue ) { - this->client.removeFromEventQueue ( *this ); - } + this->client.removeFromEventQueue ( *this ); } // // casAsyncIOI::cbFunc() -// (called when IO completion event reaches top of event queue) +// o called when IO completion event reaches top of event queue +// o clients lock is applied when calling this // caStatus casAsyncIOI::cbFunc ( casCoreClient & ) { - // - // Use the client's lock here (which is the same as the - // asynch IO's lock) here because we need to leave the lock - // applied around the destroy() call here. - // - epicsGuard < casCoreClient > guard ( this->client ); - this->inTheEventQueue = false; caStatus status = this->cbFuncAsyncIO(); @@ -140,9 +130,9 @@ void casAsyncIOI::eventSysDestroyNotify ( casCoreClient & ) } // -// casAsyncIOI::postIOCompletionI() +// casAsyncIOI::postIOCompletionI () // -caStatus casAsyncIOI::postIOCompletionI() +caStatus casAsyncIOI::postIOCompletionI () { // // detect the case where the server called destroy(), @@ -154,10 +144,10 @@ caStatus casAsyncIOI::postIOCompletionI() return S_cas_redundantPost; } - epicsGuard < casCoreClient > guard ( this->client ); - - if (this->duplicate) { - errMessage(S_cas_badParameter, + // this is only touched in the constructor so its + // ok not to not take a lock here + if ( this->duplicate ) { + errMessage ( S_cas_badParameter, "- duplicate async IO"); // // dont use "this" after potentially destroying the @@ -167,24 +157,12 @@ caStatus casAsyncIOI::postIOCompletionI() return S_cas_redundantPost; } - // - // verify that they dont post completion more than once - // - if ( this->posted ) { - return S_cas_redundantPost; - } - - // - // dont call the server tool's cancel() when this object deletes - // - this->posted = true; - // // place this event in the event queue - // (this also signals the event consumer) + // o this also signals the event consumer + // o clients lock protects list and flag // - this->inTheEventQueue = true; - this->client.addToEventQueue ( *this ); + return this->client.addToEventQueue ( *this, this->inTheEventQueue, this->posted ); return S_cas_success; } @@ -211,16 +189,11 @@ bool casAsyncIOI::readOP() const // // casAsyncIOI::serverDestroyIfReadOP() +// o clients lock is held when this is called // void casAsyncIOI::serverDestroyIfReadOP() -{ - // - // client lock used because this object's - // lock may be destroyed - // - epicsGuard < casCoreClient > guard ( this->client ); - - if (this->readOP()) { +{ + if ( this->readOP() ) { this->serverDestroy(); } diff --git a/src/cas/generic/casAsyncReadIO.cc b/src/cas/generic/casAsyncReadIO.cc index 50c77fbf8..8070970a5 100644 --- a/src/cas/generic/casAsyncReadIO.cc +++ b/src/cas/generic/casAsyncReadIO.cc @@ -37,29 +37,24 @@ casAsyncReadIO::casAsyncReadIO ( const casCtx & ctx ) : // casAsyncReadIO::~casAsyncReadIO () { - epicsGuard < casCoreClient > guard ( this->client ); this->chan.removeAsyncIO ( *this ); } // // casAsyncReadIO::postIOCompletion() // -caStatus casAsyncReadIO::postIOCompletion (caStatus completionStatusIn, - const gdd &valueRead) +caStatus casAsyncReadIO::postIOCompletion ( caStatus completionStatusIn, + const gdd & valueRead) { - { - epicsGuard < casCoreClient > guard ( this->client ); - this->pDD = & valueRead; - this->completionStatus = completionStatusIn; - } - - return this->postIOCompletionI(); + this->pDD = & valueRead; + this->completionStatus = completionStatusIn; + return this->postIOCompletionI (); } // // casAsyncReadIO::readOP() // -bool casAsyncReadIO::readOP() const +bool casAsyncReadIO::readOP () const { return true; // it is a read op } diff --git a/src/cas/generic/casAsyncWriteIO.cc b/src/cas/generic/casAsyncWriteIO.cc index 1ef9c2fb4..3769c2ca7 100644 --- a/src/cas/generic/casAsyncWriteIO.cc +++ b/src/cas/generic/casAsyncWriteIO.cc @@ -38,7 +38,6 @@ casAsyncWriteIO::casAsyncWriteIO ( const casCtx & ctx ) : // casAsyncWriteIO::~casAsyncWriteIO() { - epicsGuard < casCoreClient > guard ( this->client ); this->chan.removeAsyncIO ( *this ); } diff --git a/src/cas/generic/casChannelI.cc b/src/cas/generic/casChannelI.cc index c8b655665..71034a492 100644 --- a/src/cas/generic/casChannelI.cc +++ b/src/cas/generic/casChannelI.cc @@ -23,29 +23,17 @@ // // casChannelI::casChannelI() // -casChannelI::casChannelI ( const casCtx & ) : - pClient ( 0 ), pPV ( 0 ), cid ( 0xffffffff ), - accessRightsEvPending ( false ) +casChannelI::casChannelI ( const casCtx & ctx ) : + pClient ( ctx.getClient() ), pPV ( ctx.getPV() ), + cid ( ctx.getMsg()->m_cid ), accessRightsEvPending ( false ) { } -void casChannelI::bindToClientI ( - casCoreClient & client, casPVI & pv, caResId cidIn ) -{ - this->pClient = & client; - this->pPV = & pv; - this->cid = cidIn; - client.installChannel ( *this ); -} - // // casChannelI::~casChannelI() // casChannelI::~casChannelI() -{ - epicsGuard < casCoreClient > - guard ( * this->pClient ); - +{ // // cancel any pending asynchronous IO // @@ -80,8 +68,6 @@ casChannelI::~casChannelI() // void casChannelI::clearOutstandingReads() { - epicsGuard < casCoreClient > guard ( * this->pClient ); - // // cancel any pending asynchronous IO // @@ -102,20 +88,14 @@ void casChannelI::clearOutstandingReads() // void casChannelI::show ( unsigned level ) const { - epicsGuard < casCoreClient > guard ( * this->pClient ); - - tsDLIterConst < casMonitor > iter = - this->monitorList.firstIter (); - if ( iter.valid () ) { - printf("List of CA events (monitors) for \"%s\".\n", - this->pPV->getName()); - } - while ( iter.valid () ) { - iter->show ( level ); - ++iter; - } - - this->show ( level ); + printf ( "casChannelI: client id %u PV %s\n", + this->cid, this->pPV->getName() ); + if ( this->monitorList.count() ) { + printf ( "List of subscriptions attached\n" ); + // use the client's lock to protect the list + this->pClient->showMonitorsInList ( + this->monitorList, level ); + } } // @@ -189,7 +169,6 @@ void casChannelI::destroyClientNotify () 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 @@ -216,7 +195,6 @@ void casChannelI::installMonitor ( 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 d268607ff..93ab882a7 100644 --- a/src/cas/generic/casChannelIIL.h +++ b/src/cas/generic/casChannelIIL.h @@ -25,14 +25,9 @@ // // casChannelI::postEvent() // -inline void casChannelI::postEvent (const casEventMask &select, const gdd &event) +inline void casChannelI::postEvent ( const casEventMask &select, const gdd &event ) { - epicsGuard < casCoreClient > guard ( *this->pClient ); - tsDLIter iter = this->monitorList.firstIter (); - while ( iter.valid () ) { - iter->post (select, event); - ++iter; - } + this->pClient->postEvent ( this->monitorList, select, event ); } // @@ -52,10 +47,11 @@ inline void casChannelI::destroyNoClientNotify() // // casChannelI::installAsyncIO() // -inline void casChannelI::installAsyncIO(casAsyncIOI &io) +inline void casChannelI::installAsyncIO ( casAsyncIOI & io ) { - epicsGuard < casCoreClient > guard ( *this->pClient ); - this->ioInProgList.add(io); + // install through the client so that we can + // use its lock to protect the list + this->pClient->installChannelsAsynchIO ( this->ioInProgList, io ); } // @@ -63,9 +59,10 @@ inline void casChannelI::installAsyncIO(casAsyncIOI &io) // inline void casChannelI::removeAsyncIO ( casAsyncIOI & io ) { - epicsGuard < casCoreClient > guard ( *this->pClient ); - this->ioInProgList.remove(io); - this->pPV->unregisterIO(); + // uninstall through the client so that we can + // use its lock to protect the list + this->pClient->uninstallChannelsAsynchIO ( this->ioInProgList, io ); + this->pPV->unregisterIO (); } // diff --git a/src/cas/generic/casCoreClient.cc b/src/cas/generic/casCoreClient.cc index 12aa871e6..0004d7468 100644 --- a/src/cas/generic/casCoreClient.cc +++ b/src/cas/generic/casCoreClient.cc @@ -62,14 +62,6 @@ casCoreClient::~casCoreClient() } } -// -// casCoreClient::destroy() -// -void casCoreClient::destroy() -{ - delete this; -} - // // casCoreClient::disconnectChan() // @@ -82,6 +74,7 @@ caStatus casCoreClient::disconnectChan(caResId) void casCoreClient::show ( unsigned level ) const { printf ( "Core client\n" ); + epicsGuard < epicsMutex > guard ( this->mutex ); this->eventSys.show ( level ); printf ( "\t%d io ops in progess\n", this->ioInProgList.count() ); this->ctx.show ( level ); @@ -203,20 +196,151 @@ casMonitor & casCoreClient::monitorFactory ( const casEventMask & mask ) { casMonitor & mon = this->ctx.getServer()->casMonitorFactory ( - chan, clientId, count, - type, mask, - this->mutex, - *this ); - this->eventSys.installMonitor (); + chan, clientId, count, type, mask, *this ); + { + epicsGuard < epicsMutex > guard ( this->mutex ); + this->eventSys.installMonitor (); + } return mon; } void casCoreClient::destroyMonitor ( casMonitor & mon ) { - this->eventSys.removeMonitor (); + { + epicsGuard < epicsMutex > guard ( this->mutex ); + this->eventSys.removeMonitor (); + } this->ctx.getServer()->casMonitorDestroy ( mon ); } - +void casCoreClient::postEvent ( tsDLList < casMonitor > & monitorList, + const casEventMask & select, const gdd & event ) +{ + epicsGuard < epicsMutex > guard ( this->mutex ); + tsDLIter < casMonitor > iter = monitorList.firstIter (); + while ( iter.valid () ) { + iter->postEvent ( select, event ); + ++iter; + } +} + +void casCoreClient::showMonitorsInList ( + const tsDLList < casMonitor > & monitorList, unsigned level ) const +{ + epicsGuard < epicsMutex > guard ( this->mutex ); + tsDLIterConst < casMonitor > iter = monitorList.firstIter (); + while ( iter.valid () ) { + iter->show ( level ); + ++iter; + } +} + +void casCoreClient::installChannelsAsynchIO ( + tsDLList < casAsyncIOI > & list, casAsyncIOI & io ) +{ + epicsGuard < epicsMutex > guard ( this->mutex ); + list.add ( io ); +} + +void casCoreClient::uninstallChannelsAsynchIO ( + tsDLList < casAsyncIOI > & list, casAsyncIOI & io ) +{ + epicsGuard < epicsMutex > guard ( this->mutex ); + list.remove ( io ); +} + +// +// casCoreClient::installAsyncIO() +// +void casCoreClient::installAsyncIO(casAsyncIOI &ioIn) +{ + epicsGuard < epicsMutex > guard ( this->mutex ); + this->ioInProgList.add ( ioIn ); +} + +// +// casCoreClient::removeAsyncIO() +// +void casCoreClient::removeAsyncIO(casAsyncIOI &ioIn) +{ + epicsGuard < epicsMutex > guard ( this->mutex ); + this->ioInProgList.remove ( ioIn ); + this->ctx.getServer()->ioBlockedList::signal (); +} + +casEventSys::processStatus casCoreClient::eventSysProcess () +{ + epicsGuard < epicsMutex > guard ( this->mutex ); + return this->eventSys.process (); +} + +void casCoreClient::addToEventQueue ( casEvent & ev ) +{ + epicsGuard < epicsMutex > guard ( this->mutex ); + this->eventSys.addToEventQueue ( ev ); +} + +// clients lock protects the event list and the +// flags in the asynch IO object +caStatus casCoreClient::addToEventQueue ( casAsyncIOI & io, + bool & onTheQueue, bool & posted ) +{ + epicsGuard < epicsMutex > guard ( this->mutex ); + // dont allow them to post completion more than once + if ( posted || onTheQueue ) { + return S_cas_redundantPost; + } + posted = true; + onTheQueue = true; + this->eventSys.addToEventQueue ( io ); + return S_cas_success; +} + +void casCoreClient::insertEventQueue ( casEvent & insert, casEvent & prevEvent ) +{ + epicsGuard < epicsMutex > guard ( this->mutex ); + this->eventSys.insertEventQueue ( insert, prevEvent ); +} + +void casCoreClient::removeFromEventQueue ( casEvent & ev ) +{ + epicsGuard < epicsMutex > guard ( this->mutex ); + this->eventSys.removeFromEventQueue ( ev ); +} + +void casCoreClient::removeFromEventQueue ( casAsyncIOI & io ) +{ + epicsGuard < epicsMutex > guard ( this->mutex ); + if ( io.onTheEventQueue () ) { + this->eventSys.removeFromEventQueue ( io ); + } +} + +void casCoreClient::enableEvents () +{ + { + epicsGuard < epicsMutex > guard ( this->mutex ); + this->eventSys.eventsOn (); + } + this->eventSignal (); // wake up the event queue consumer +} + +void casCoreClient::disableEvents () +{ + epicsGuard < epicsMutex > guard ( this->mutex ); + this->eventSys.eventsOff (); +} + +void casCoreClient::setDestroyPending () +{ + epicsGuard < epicsMutex > guard ( this->mutex ); + this->eventSys.setDestroyPending (); +} + +bool casCoreClient::eventSysIsFull () +{ + epicsGuard < epicsMutex > guard ( this->mutex ); + return this->eventSys.full (); +} diff --git a/src/cas/generic/casCoreClientIL.h b/src/cas/generic/casCoreClientIL.h index 569107c95..c250bc8dc 100644 --- a/src/cas/generic/casCoreClientIL.h +++ b/src/cas/generic/casCoreClientIL.h @@ -41,25 +41,6 @@ inline caServerI &casCoreClient::getCAS() const return *this->ctx.getServer(); } -// -// casCoreClient::installAsyncIO() -// -inline void casCoreClient::installAsyncIO(casAsyncIOI &ioIn) -{ - epicsGuard < epicsMutex > guard ( this->mutex ); - this->ioInProgList.add ( ioIn ); -} - -// -// casCoreClient::removeAsyncIO() -// -inline void casCoreClient::removeAsyncIO(casAsyncIOI &ioIn) -{ - epicsGuard < epicsMutex > guard ( this->mutex ); - this->ioInProgList.remove ( ioIn ); - this->ctx.getServer()->ioBlockedList::signal (); -} - inline bool casCoreClient::okToStartAsynchIO () { if ( ! this->asyncIOFlag ) { @@ -80,47 +61,6 @@ 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 casMonitor * casCoreClient::lookupMonitor ( const caResId & idIn ) { return this->ctx.getServer()->lookupMonitor ( idIn ); diff --git a/src/cas/generic/casCtxIL.h b/src/cas/generic/casCtxIL.h index 3b8b5c086..b0c89fe98 100644 --- a/src/cas/generic/casCtxIL.h +++ b/src/cas/generic/casCtxIL.h @@ -74,7 +74,7 @@ inline casChannelI * casCtx::getChannel() const // // casCtx::setMsg() // -inline void casCtx::setMsg ( caHdrLargeArray &msgIn, void * pBody ) +inline void casCtx::setMsg ( const caHdrLargeArray & msgIn, void * pBody ) { this->msg = msgIn; this->pData = pBody; diff --git a/src/cas/generic/casEventSys.cc b/src/cas/generic/casEventSys.cc index 538273717..1a39c67de 100644 --- a/src/cas/generic/casEventSys.cc +++ b/src/cas/generic/casEventSys.cc @@ -49,8 +49,6 @@ void casEventSys::show(unsigned level) const // casEventSys::~casEventSys() { - epicsGuard < epicsMutex > guard ( this->mutex ); - if ( this->pPurgeEvent != NULL ) { this->eventLogQue.remove ( *this->pPurgeEvent ); delete this->pPurgeEvent; @@ -64,7 +62,6 @@ casEventSys::~casEventSys() while ( casEvent * pE = this->eventLogQue.get () ) { pE->eventSysDestroyNotify ( this->client ); } - } // @@ -72,7 +69,6 @@ casEventSys::~casEventSys() // void casEventSys::installMonitor() { - epicsGuard < epicsMutex > guard ( this->mutex ); this->numEventBlocks++; this->maxLogEntries += averageEventEntries; } @@ -82,7 +78,6 @@ void casEventSys::installMonitor() // void casEventSys::removeMonitor () { - epicsGuard < epicsMutex > guard ( this->mutex ); assert (this->numEventBlocks>=1u); this->numEventBlocks--; this->maxLogEntries -= averageEventEntries; @@ -100,16 +95,12 @@ casEventSys::processStatus casEventSys::process () while ( ! this->dontProcess ) { casEvent * pEvent; - { - epicsGuard < epicsMutex > guard ( this->mutex ); - pEvent = this->eventLogQue.get (); - } + pEvent = this->eventLogQue.get (); if ( pEvent == NULL ) { break; } - // lock must remain on until the event is called caStatus status = pEvent->cbFunc ( this->client ); if ( status == S_cas_success ) { ps.nAccepted++; @@ -117,10 +108,7 @@ casEventSys::processStatus casEventSys::process () else if ( status == S_cas_sendBlocked ) { // not accepted so return to the head of the list // (we will try again later) - { - epicsGuard < epicsMutex > guard ( this->mutex ); - this->pushOnToEventQueue ( *pEvent ); - } + this->pushOnToEventQueue ( *pEvent ); ps.cond = casProcOk; break; } @@ -157,28 +145,24 @@ casEventSys::processStatus casEventSys::process () // void casEventSys::eventsOn() { - { - epicsGuard < epicsMutex > guard ( this->mutex ); + // + // allow multiple events for each monitor + // + this->replaceEvents = false; - // - // allow multiple events for each monitor - // - this->replaceEvents = false; + // + // allow the event queue to be processed + // + this->dontProcess = false; - // - // allow the event queue to be processed - // - this->dontProcess = false; - - // - // remove purge event if it is still pending - // - if ( this->pPurgeEvent != NULL ) { - this->eventLogQue.remove ( *this->pPurgeEvent ); - delete this->pPurgeEvent; - this->pPurgeEvent = NULL; - } - } + // + // remove purge event if it is still pending + // + if ( this->pPurgeEvent != NULL ) { + this->eventLogQue.remove ( *this->pPurgeEvent ); + delete this->pPurgeEvent; + this->pPurgeEvent = NULL; + } } // @@ -186,8 +170,6 @@ void casEventSys::eventsOn() // void casEventSys::eventsOff() { - epicsGuard < epicsMutex > guard ( this->mutex ); - // // new events will replace the last event on // the queue for a particular monitor @@ -228,11 +210,8 @@ casEventPurgeEv::casEventPurgeEv ( casEventSys & evSysIn ) : // caStatus casEventPurgeEv::cbFunc ( casCoreClient & ) { - { - epicsGuard < epicsMutex > guard ( this->evSys.mutex ); - this->evSys.dontProcess = true; - this->evSys.pPurgeEvent = NULL; - } + this->evSys.dontProcess = true; + this->evSys.pPurgeEvent = NULL; delete this; diff --git a/src/cas/generic/casEventSysIL.h b/src/cas/generic/casEventSysIL.h index 8f952db3a..5ddf1b574 100644 --- a/src/cas/generic/casEventSysIL.h +++ b/src/cas/generic/casEventSysIL.h @@ -38,10 +38,7 @@ inline casEventSys::casEventSys ( casCoreClient & clientIn ) : // inline void casEventSys::addToEventQueue ( casEvent & event ) { - { - epicsGuard < epicsMutex > guard ( this->mutex ); - this->eventLogQue.add ( event ); - } + this->eventLogQue.add ( event ); // // wake up the event queue consumer only if @@ -70,7 +67,6 @@ inline void casEventSys::setDestroyPending() // inline void casEventSys::insertEventQueue( casEvent & insert, casEvent & prevEvent ) { - epicsGuard < epicsMutex > guard ( this->mutex ); this->eventLogQue.insertAfter ( insert, prevEvent ); } @@ -79,7 +75,6 @@ inline void casEventSys::insertEventQueue( casEvent & insert, casEvent & prevEve // inline void casEventSys::pushOnToEventQueue ( casEvent & event ) { - epicsGuard < epicsMutex > guard ( this->mutex ); this->eventLogQue.push ( event ); } @@ -88,7 +83,6 @@ inline void casEventSys::pushOnToEventQueue ( casEvent & event ) // inline void casEventSys::removeFromEventQueue ( casEvent & event ) { - epicsGuard < epicsMutex > guard ( this->mutex ); this->eventLogQue.remove ( event ); } diff --git a/src/cas/generic/casInternal.h b/src/cas/generic/casInternal.h index 47e5f82e4..8652c3bce 100644 --- a/src/cas/generic/casInternal.h +++ b/src/cas/generic/casInternal.h @@ -79,7 +79,7 @@ public: ioBlocked (); virtual ~ioBlocked (); private: - ioBlockedList *pList; + ioBlockedList * pList; virtual void ioBlockedSignal (); }; @@ -137,7 +137,7 @@ class casMonitor : public: casMonitor ( caResId clientIdIn, casChannelI & chan, unsigned long nElem, unsigned dbrType, - const casEventMask & maskIn, epicsMutex & mutexIn, + const casEventMask & maskIn, casMonitorCallbackInterface & ); virtual ~casMonitor(); @@ -145,7 +145,7 @@ public: caStatus executeEvent ( casMonEvent & ); - void post ( const casEventMask & select, const smartConstGDDPointer & pValue ); + void postEvent ( const casEventMask & select, const smartConstGDDPointer & pValue ); caResId getClientId () const { @@ -174,7 +174,6 @@ public: private: casMonEvent overFlowEvent; unsigned long const nElem; - epicsMutex & mutex; casChannelI & ciu; casMonitorCallbackInterface & callBackIntf; const casEventMask mask; @@ -194,10 +193,10 @@ private: }; // -// casMonitor::post() +// casMonitor::postEvent() // (check for NOOP case in line) // -inline void casMonitor::post (const casEventMask &select, const smartConstGDDPointer &pValue) +inline void casMonitor::postEvent (const casEventMask &select, const smartConstGDDPointer &pValue) { casEventMask result (select&this->mask); // @@ -233,6 +232,11 @@ public: caServer *getCAS () const; + bool onTheEventQueue () const + { + return this->inTheEventQueue; + } + protected: casCoreClient & client; @@ -242,11 +246,11 @@ protected: caStatus postIOCompletionI(); private: - bool inTheEventQueue:1; - bool posted:1; - bool ioComplete:1; - bool serverDelete:1; - bool duplicate:1; + bool inTheEventQueue; + bool posted; + bool ioComplete; + bool serverDelete; + bool duplicate; // // casEvent virtual call back function @@ -286,9 +290,6 @@ public: casChannelI ( const casCtx & ctx ); epicsShareFunc virtual ~casChannelI (); - void bindToClientI ( class casCoreClient & client, - casPVI & pv, caResId cid ); - class casCoreClient & getClient () const { return *this->pClient; @@ -347,7 +348,7 @@ protected: class casCoreClient * pClient; casPVI * pPV; caResId cid; // client id - bool accessRightsEvPending:1; + bool accessRightsEvPending; epicsShareFunc virtual void destroy (); epicsShareFunc caStatus cbFunc ( casCoreClient & ); // access rights event call back @@ -363,8 +364,6 @@ class casPVListChan : public casChannelI, public tsDLNode { public: casPVListChan ( const casCtx &ctx ); - void bindToClient ( casCoreClient & client, - casPVI & pv, caResId cidIn ); epicsShareFunc virtual ~casPVListChan(); private: casPVListChan ( const casPVListChan & ); @@ -414,12 +413,12 @@ public: epicsShareFunc virtual void endTransaction () = 0; epicsShareFunc virtual caStatus read ( const casCtx & ctx, gdd & prototype ) = 0; epicsShareFunc virtual caStatus write ( const casCtx & ctx, const gdd & value ) = 0; - epicsShareFunc virtual casChannel *createChannel (const casCtx & ctx, + epicsShareFunc virtual casChannel * createChannel ( const casCtx & ctx, const char * const pUserName, const char * const pHostName ) = 0; epicsShareFunc virtual aitEnum bestExternalType () const = 0; epicsShareFunc virtual unsigned maxDimension () const = 0; epicsShareFunc virtual aitIndex maxBound ( unsigned dimension ) const = 0; - epicsShareFunc virtual const char *getName () const = 0; + epicsShareFunc virtual const char * getName () const = 0; epicsShareFunc casPV *apiPointer (); //retuns NULL if casPVI isnt a base of casPV private: diff --git a/src/cas/generic/casMonitor.cc b/src/cas/generic/casMonitor.cc index a5d75ee5e..fb5db7f94 100644 --- a/src/cas/generic/casMonitor.cc +++ b/src/cas/generic/casMonitor.cc @@ -32,10 +32,8 @@ casMonitor::casMonitor ( unsigned long nElemIn, unsigned dbrTypeIn, const casEventMask & maskIn, - epicsMutex & mutexIn, casMonitorCallbackInterface & cb ) : nElem ( nElemIn ), - mutex ( mutexIn ), ciu ( chan ), callBackIntf ( cb ), mask ( maskIn ), @@ -55,7 +53,6 @@ casMonitor::casMonitor ( // casMonitor::~casMonitor() { - epicsGuard < epicsMutex > guard ( this->mutex ); this->disable(); if ( this->ovf ) { casCoreClient &client = this->ciu.getClient(); @@ -68,7 +65,6 @@ casMonitor::~casMonitor() // void casMonitor::enable() { - epicsGuard < epicsMutex > guard ( this->mutex ); if ( ! this->enabled && this->ciu.readAccess() ) { this->enabled = true; caStatus status = this->ciu.getPVI().registerEvent(); @@ -84,7 +80,6 @@ void casMonitor::enable() // void casMonitor::disable() { - epicsGuard < epicsMutex > guard ( this->mutex ); if ( this->enabled ) { this->enabled = false; this->ciu.getPVI().unregisterEvent(); @@ -95,9 +90,7 @@ void casMonitor::disable() // casMonitor::push() // void casMonitor::push ( const smartConstGDDPointer & pNewValue ) -{ - epicsGuard < epicsMutex > guard ( this->mutex ); - +{ casCoreClient & client = this->ciu.getClient (); client.getCAS().incrEventsPostedCounter (); @@ -174,7 +167,6 @@ caStatus casMonitor::executeEvent ( casMonEvent & ev ) caStatus status; { - epicsGuard < epicsMutex > guard ( this->mutex ); status = this->callBackIntf. casMonitorCallBack ( *this, *pVal ); diff --git a/src/cas/generic/casPV.cc b/src/cas/generic/casPV.cc index a006d59a6..0becab6a7 100644 --- a/src/cas/generic/casPV.cc +++ b/src/cas/generic/casPV.cc @@ -56,9 +56,9 @@ void casPV::destroy () // casPV::createChannel() // casChannel *casPV::createChannel (const casCtx &ctx, const char * const, - const char * const) + const char * const ) { - return new casChannel (ctx); + return new casChannel ( ctx ); } // diff --git a/src/cas/generic/casPVListChan.cc b/src/cas/generic/casPVListChan.cc index 2d25abfb7..90edf175a 100644 --- a/src/cas/generic/casPVListChan.cc +++ b/src/cas/generic/casPVListChan.cc @@ -27,13 +27,6 @@ casPVListChan::casPVListChan (const casCtx &ctx) : { } -void casPVListChan::bindToClient ( - casCoreClient & client, casPVI & pv, caResId cidIn ) -{ - this->bindToClientI ( client, pv, cidIn ); - this->pPV->installChannel ( *this ); -} - // // casPVListChan::~casPVListChan() // diff --git a/src/cas/generic/casStrmClient.cc b/src/cas/generic/casStrmClient.cc index 1cab065ed..90535d8dd 100644 --- a/src/cas/generic/casStrmClient.cc +++ b/src/cas/generic/casStrmClient.cc @@ -40,16 +40,13 @@ casStrmClient::casStrmClient ( caServerI & cas, clientBufMemoryManager & memMgr this->pHostName = new char [1u]; *this->pHostName = '\0'; - epicsGuard < casCoreClient > guard ( * this ); - - this->ctx.getServer()->installClient ( this ); - this->pUserName = new ( std::nothrow ) char [1u]; if ( ! this->pUserName ) { free ( this->pHostName ); throw std::bad_alloc(); } *this->pUserName= '\0'; + this->ctx.getServer()->installClient ( this ); } // @@ -57,19 +54,14 @@ casStrmClient::casStrmClient ( caServerI & cas, clientBufMemoryManager & memMgr // casStrmClient::~casStrmClient() { - epicsGuard < casCoreClient > guard ( * this ); - - // - // remove this from the list of connected clients - // - this->ctx.getServer()->removeClient(this); + this->ctx.getServer()->removeClient ( this ); delete [] this->pUserName; delete [] this->pHostName; // - // delete all channel attached + // delete all channels attached // tsDLIter iter = this->chanList.firstIter (); while ( iter.valid () ) { @@ -821,7 +813,7 @@ caStatus casStrmClient::hostNameAction() size-1); pMalloc[size-1]='\0'; - epicsGuard < casCoreClient > guard ( * this ); + epicsGuard < epicsMutex > guard ( this->mutex ); if (this->pHostName) { delete [] this->pHostName; @@ -867,7 +859,7 @@ caStatus casStrmClient::clientNameAction() size-1); pMalloc[size-1]='\0'; - epicsGuard < casCoreClient > guard ( * this ); + epicsGuard < epicsMutex > guard ( this->mutex ); if (this->pUserName) { delete [] this->pUserName; @@ -940,7 +932,7 @@ caStatus casStrmClient::claimChannelAction() // prevent problems such as the PV being deleted before the // channel references it // - epicsGuard < casCoreClient > guard ( * this ); + epicsGuard < epicsMutex > guard ( this->mutex ); this->asyncIOFlag = false; // @@ -1017,18 +1009,21 @@ caStatus casStrmClient::createChanResponse ( const caHdrLargeArray & hdr, const // // create server tool XXX derived from casChannel + // (use temp context because this can be caled asynchronously) // - this->ctx.setPV ( pPV ); + casCtx tmpCtx; + tmpCtx.setClient ( this ); + tmpCtx.setPV ( pPV ); + tmpCtx.setMsg ( hdr, 0 ); casChannel * pChan = pPV->createChannel ( - this->ctx, this->pUserName, this->pHostName ); + tmpCtx, this->pUserName, this->pHostName ); if ( ! pChan ) { pPV->deleteSignal(); return this->channelCreateFailedResp ( hdr, S_cas_noMemory ); } - pChan->bindToClient ( *this, *pPV, hdr.m_cid ); - - casChannelI * pChanI = (casChannelI *) pChan; + this->installChannel ( *pChan ); + pPV->installChannel ( *pChan ); // // check to see if the enum table is empty and therefore @@ -1038,7 +1033,7 @@ caStatus casStrmClient::createChanResponse ( const caHdrLargeArray & hdr, const // if ( nativeTypeDBR == DBR_ENUM ) { this->ctx.setPV ( pPV ); - this->ctx.setChannel ( pChanI ); + this->ctx.setChannel ( pChan ); this->asyncIOFlag = false; status = pPV->updateEnumStringTable ( this->ctx ); if ( this->asyncIOFlag ) { @@ -1302,6 +1297,7 @@ caStatus casStrmClient::eventAddAction () } if ( status == S_cas_success ) { + epicsGuard < epicsMutex > guard ( this->mutex ); pciu->installMonitor ( mp->m_available, mp->m_count, mp->m_dataType, mask ); @@ -1474,7 +1470,7 @@ caStatus casStrmClient::readSyncAction() const caHdrLargeArray *mp = this->ctx.getMsg(); int status; - epicsGuard < casCoreClient > guard ( * this ); + epicsGuard < epicsMutex > guard ( this->mutex ); // // This messages indicates that the client @@ -1857,7 +1853,7 @@ inline bool caServerI::roomForNewChannel() const // void casStrmClient::installChannel(casChannelI &chan) { - epicsGuard < casCoreClient > guard ( * this ); + epicsGuard < epicsMutex > guard ( this->mutex ); this->getCAS().installItem (chan); this->chanList.add(chan); } @@ -1867,7 +1863,7 @@ void casStrmClient::installChannel(casChannelI &chan) // void casStrmClient::removeChannel(casChannelI &chan) { - epicsGuard < casCoreClient > guard ( * this ); + epicsGuard < epicsMutex > guard ( this->mutex ); casRes * pRes = this->getCAS().removeItem(chan); assert (&chan == (casChannelI *)pRes); this->chanList.remove(chan); diff --git a/src/cas/generic/server.h b/src/cas/generic/server.h index 2ed8db6ed..47f832e6a 100644 --- a/src/cas/generic/server.h +++ b/src/cas/generic/server.h @@ -110,7 +110,7 @@ public: casPVI * getPV () const; casChannelI * getChannel () const; - void setMsg ( caHdrLargeArray &, void * pBody ); + void setMsg ( const caHdrLargeArray &, void * pBody ); void setServer ( caServerI * p ); @@ -382,7 +382,6 @@ public: private: tsDLList < casEvent > eventLogQue; - epicsMutex mutex; casCoreClient & client; class casEventPurgeEv * pPurgeEvent; // flow control purge complete event unsigned numEventBlocks; // N event blocks installed @@ -421,21 +420,20 @@ class casCoreClient : public ioBlocked, public: 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 removeAsyncIO ( casAsyncIOI & ioIn ); + void installChannelsAsynchIO ( + tsDLList < casAsyncIOI > & list, casAsyncIOI & io ); + void uninstallChannelsAsynchIO ( + tsDLList < casAsyncIOI > & list, casAsyncIOI & io ); caServerI & getCAS () const; - void lock (); - void unlock (); - // // one virtual function for each CA request type that has // asynchronous completion @@ -479,9 +477,12 @@ public: casEventSys::processStatus eventSysProcess(); void addToEventQueue ( casEvent & ); + caStatus addToEventQueue ( casAsyncIOI &, + bool & onTheQueue, bool & posted ); void insertEventQueue ( casEvent & insert, casEvent & prevEvent ); void removeFromEventQueue ( casEvent & ); + void removeFromEventQueue ( casAsyncIOI & ); void enableEvents (); void disableEvents (); bool eventSysIsFull (); @@ -498,12 +499,20 @@ public: caStatus casMonitorCallBack ( casMonitor &, const smartConstGDDPointer & ); casMonitor * lookupMonitor ( const caResId &idIn ); + void postEvent ( tsDLList &, + const casEventMask &select, const gdd &event ); + void showMonitorsInList ( + const tsDLList < casMonitor > & monitorList, + unsigned level ) const; protected: - epicsMutex mutex; + mutable epicsMutex mutex; casCtx ctx; bool asyncIOFlag; + void lock (); + void unlock (); + private: casEventSys eventSys; tsDLList < casAsyncIOI > ioInProgList; @@ -916,7 +925,7 @@ public: casMonitor & casMonitorFactory ( casChannelI &, caResId clientId, const unsigned long count, const unsigned type, const casEventMask &, - epicsMutex & , casMonitorCallbackInterface & ); + casMonitorCallbackInterface & ); void casMonitorDestroy ( casMonitor & ); private: diff --git a/src/cas/generic/st/casStreamOS.cc b/src/cas/generic/st/casStreamOS.cc index 9909d57cd..4f8cc7093 100644 --- a/src/cas/generic/st/casStreamOS.cc +++ b/src/cas/generic/st/casStreamOS.cc @@ -165,7 +165,7 @@ epicsTimerNotify::expireStatus casStreamEvWakeup::expire ( const epicsTime & /* // called from a client member function // higher up on the stack // - os.destroy(); + delete & os; // // must not touch the "this" pointer @@ -482,7 +482,7 @@ void casStreamOS::sendCB() // called from a client member function // higher up on the stack // - this->destroy(); + delete this; // // must _not_ touch "this" pointer // after the destroy @@ -507,7 +507,7 @@ void casStreamOS::sendCB() // called from a client member function // higher up on the stack // - this->destroy(); + delete this; // // must _not_ touch "this" pointer // after the destroy