diff --git a/src/db/dbCAC.h b/src/db/dbCAC.h index aa3c4f2ac..915a7a0e2 100644 --- a/src/db/dbCAC.h +++ b/src/db/dbCAC.h @@ -34,10 +34,12 @@ class dbPutNotifyBlocker; class dbPutNotifyIO : public cacNotifyIO { public: dbPutNotifyIO ( cacNotify &, dbPutNotifyBlocker & ); + void cancel (); int initiate ( struct dbAddr &addr, unsigned type, unsigned long count, const void *pValue); void completion (); - void destroy (); + void show ( unsigned level ) const; + //void destroy (); cacChannelIO & channelIO () const; void * operator new ( size_t size ); void operator delete ( void *pCadaver, size_t size ); @@ -47,6 +49,7 @@ private: putNotify pn; dbPutNotifyBlocker &blocker; static tsFreeList < dbPutNotifyIO > freeList; + static epicsMutex freeListMutex; }; extern "C" void dbSubscriptionEventCallback ( void *pPrivate, struct dbAddr *paddr, @@ -55,8 +58,9 @@ extern "C" void dbSubscriptionEventCallback ( void *pPrivate, struct dbAddr *pad class dbSubscriptionIO : public cacNotifyIO, public tsDLNode { public: dbSubscriptionIO ( dbChannelIO &chanIO, cacNotify &, unsigned type, unsigned long count ); + void cancel (); int begin ( struct dbAddr &addr, unsigned mask ); - void destroy (); + //void destroy (); void show ( unsigned level ) const; cacChannelIO & channelIO () const; void * operator new ( size_t size ); @@ -69,6 +73,7 @@ private: unsigned type; unsigned long count; static tsFreeList < dbSubscriptionIO > freeList; + static epicsMutex freeListMutex; friend void dbSubscriptionEventCallback ( void *pPrivate, struct dbAddr *paddr, int eventsRemaining, struct db_field_log *pfl ); }; @@ -92,9 +97,8 @@ private: epicsEvent block; dbPutNotifyIO *pPN; dbChannelIO &chan; - void lock () const; - void unlock () const; static tsFreeList < dbPutNotifyBlocker > freeList; + static epicsMutex freeListMutex; friend void putNotifyCompletion ( putNotify *ppn ); }; @@ -128,23 +132,37 @@ private: unsigned mask, cacNotify ¬ify, cacNotifyIO *& ); short nativeType () const; unsigned long nativeElementCount () const; - void lock () const; - void unlock () const; - void lockOutstandingIO () const; - void unlockOutstandingIO () const; static tsFreeList < dbChannelIO > freeList; + static epicsMutex freeListMutex; friend dbSubscriptionIO::dbSubscriptionIO ( dbChannelIO &chanIO, cacNotify &, unsigned type, unsigned long count ); friend dbSubscriptionIO::~dbSubscriptionIO (); - friend void dbPutNotifyBlocker::lock () const; - friend void dbPutNotifyBlocker::unlock () const; + friend class dbAutoScanLockCA; +}; + +class dbAutoScanLock { +public: + dbAutoScanLock ( dbCommon & ); + ~dbAutoScanLock (); +private: + dbAutoScanLock ( const dbAutoScanLock & ); + dbAutoScanLock & operator = ( const dbAutoScanLock & ); + dbCommon & rCommon; +}; + +class dbAutoScanLockCA : public dbAutoScanLock { +public: + dbAutoScanLockCA ( dbChannelIO & ); +private: + dbAutoScanLockCA ( const dbAutoScanLockCA & ); + dbAutoScanLockCA & operator = ( const dbAutoScanLockCA & ); }; class dbServiceIO : public cacServiceIO { public: dbServiceIO (); virtual ~dbServiceIO (); - cacChannelIO *createChannelIO ( const char *pName, cac &, cacChannelNotify & ); + cacChannelIO *createChannelIO ( const char *pName, cacChannelNotify & ); void subscriptionUpdate ( struct dbAddr &addr, unsigned type, unsigned long count, const struct db_field_log *pfl, dbSubscriptionIO ¬ify ); dbEventSubscription subscribe ( struct dbAddr &addr, dbSubscriptionIO &subscr, unsigned mask ); @@ -153,6 +171,21 @@ private: dbEventCtx ctx; char *pEventCallbackCache; unsigned long eventCallbackCacheSize; - epicsMutex mutex; + mutable epicsMutex mutex; }; +inline dbAutoScanLock :: dbAutoScanLock ( dbCommon & dbCommonIn ) : + rCommon ( dbCommonIn ) +{ + dbScanLock ( &this->rCommon ); +} + +inline dbAutoScanLock :: ~dbAutoScanLock () +{ + dbScanUnlock ( &this->rCommon ); +} + +inline dbAutoScanLockCA::dbAutoScanLockCA ( dbChannelIO &chan ) : + dbAutoScanLock ( *chan.addr.precord ) +{ +} \ No newline at end of file diff --git a/src/db/dbPutNotifyIOIL.h b/src/db/dbPutNotifyIOIL.h index d5560ab93..cfc8fb9ce 100644 --- a/src/db/dbPutNotifyIOIL.h +++ b/src/db/dbPutNotifyIOIL.h @@ -16,18 +16,15 @@ * 505 665 1831 */ -inline void dbPutNotifyIO::destroy () -{ - delete this; -} - inline void * dbPutNotifyIO::operator new ( size_t size ) { + epicsAutoMutex locker ( dbPutNotifyIO::freeListMutex ); return dbPutNotifyIO::freeList.allocate ( size ); } inline void dbPutNotifyIO::operator delete ( void *pCadaver, size_t size ) { + epicsAutoMutex locker ( dbPutNotifyIO::freeListMutex ); dbPutNotifyIO::freeList.release ( pCadaver, size ); } diff --git a/src/db/dbServiceIO.cpp b/src/db/dbServiceIO.cpp index f2fa2b32d..12cc4571b 100644 --- a/src/db/dbServiceIO.cpp +++ b/src/db/dbServiceIO.cpp @@ -61,8 +61,8 @@ dbServiceIO::~dbServiceIO () } } -cacChannelIO *dbServiceIO::createChannelIO ( - const char *pName, cac &cacCtx, cacChannelNotify ¬ify ) +cacChannelIO *dbServiceIO::createChannelIO ( + const char *pName, cacChannelNotify ¬ify ) { struct dbAddr addr; @@ -81,7 +81,8 @@ void dbServiceIO::subscriptionUpdate ( struct dbAddr &addr, { unsigned long size = dbr_size_n ( type, count ); - this->mutex.lock (); + epicsAutoMutex locker ( this->mutex ); + if ( this->eventCallbackCacheSize < size) { if ( this->pEventCallbackCache ) { delete [] this->pEventCallbackCache; @@ -89,7 +90,6 @@ void dbServiceIO::subscriptionUpdate ( struct dbAddr &addr, this->pEventCallbackCache = new char [size]; if ( ! this->pEventCallbackCache ) { this->eventCallbackCacheSize = 0ul; - this->mutex.unlock (); io.notify ().exceptionNotify ( io.channelIO (), ECA_ALLOCMEM, "unable to allocate callback cache" ); return; @@ -107,7 +107,6 @@ void dbServiceIO::subscriptionUpdate ( struct dbAddr &addr, io.notify ().completionNotify ( io.channelIO (), type, count, this->pEventCallbackCache ); } - this->mutex.unlock (); } extern "C" void cacAttachClientCtx ( void * pPrivate ) @@ -129,29 +128,29 @@ dbEventSubscription dbServiceIO::subscribe ( struct dbAddr &addr, dbSubscription return 0; } - this->mutex.lock (); - if ( ! this->ctx ) { - this->ctx = db_init_events (); + { + epicsAutoMutex locker ( this->mutex ); if ( ! this->ctx ) { - this->mutex.unlock (); - return 0; - } + this->ctx = db_init_events (); + if ( ! this->ctx ) { + return 0; + } - unsigned selfPriority = epicsThreadGetPrioritySelf (); - unsigned above; - epicsThreadBooleanStatus tbs = epicsThreadLowestPriorityLevelAbove (selfPriority, &above); - if ( tbs != epicsThreadBooleanStatusSuccess ) { - above = selfPriority; - } - status = db_start_events ( this->ctx, "CAC-event", - cacAttachClientCtx, clientCtx, above ); - if ( status ) { - db_close_events ( this->ctx ); - this->ctx = 0; - return 0; + unsigned selfPriority = epicsThreadGetPrioritySelf (); + unsigned above; + epicsThreadBooleanStatus tbs = epicsThreadLowestPriorityLevelAbove (selfPriority, &above); + if ( tbs != epicsThreadBooleanStatusSuccess ) { + above = selfPriority; + } + status = db_start_events ( this->ctx, "CAC-event", + cacAttachClientCtx, clientCtx, above ); + if ( status ) { + db_close_events ( this->ctx ); + this->ctx = 0; + return 0; + } } } - this->mutex.unlock (); es = db_add_event ( this->ctx, &addr, dbSubscriptionEventCallback, (void *) &subscr, mask ); @@ -164,7 +163,7 @@ dbEventSubscription dbServiceIO::subscribe ( struct dbAddr &addr, dbSubscription void dbServiceIO::show ( unsigned level ) const { - this->mutex.lock (); + epicsAutoMutex locker ( this->mutex ); printf ( "dbServiceIO at %p\n", static_cast ( this ) ); if (level > 0u ) { @@ -174,6 +173,5 @@ void dbServiceIO::show ( unsigned level ) const if ( level > 1u ) { this->mutex.show ( level - 2u ); } - this->mutex.unlock (); } diff --git a/src/db/dbSubscriptionIO.cpp b/src/db/dbSubscriptionIO.cpp index aa2f81242..46c151829 100644 --- a/src/db/dbSubscriptionIO.cpp +++ b/src/db/dbSubscriptionIO.cpp @@ -29,28 +29,29 @@ #include "db_access_routines.h" tsFreeList < dbSubscriptionIO > dbSubscriptionIO::freeList; +epicsMutex dbSubscriptionIO::freeListMutex; dbSubscriptionIO::dbSubscriptionIO ( dbChannelIO &chanIO, cacNotify ¬ifyIn, unsigned typeIn, unsigned long countIn ) : cacNotifyIO ( notifyIn ), chan ( chanIO ), es ( 0 ), type ( typeIn ), count ( countIn ) { - this->chan.lock (); + dbAutoScanLockCA locker ( this->chan ); this->chan.eventq.add ( *this ); - this->chan.unlock (); } dbSubscriptionIO::~dbSubscriptionIO () { - this->chan.lock (); - this->chan.eventq.remove ( *this ); - this->chan.unlock (); + { + dbAutoScanLockCA locker ( this->chan ); + this->chan.eventq.remove ( *this ); + } if ( this->es ) { db_cancel_event ( this->es ); } } -void dbSubscriptionIO::destroy () +void dbSubscriptionIO::cancel () { delete this; } @@ -62,11 +63,13 @@ cacChannelIO & dbSubscriptionIO::channelIO () const void * dbSubscriptionIO::operator new ( size_t size ) { + epicsAutoMutex locker ( dbSubscriptionIO::freeListMutex ); return dbSubscriptionIO::freeList.allocate ( size ); } void dbSubscriptionIO::operator delete ( void *pCadaver, size_t size ) { + epicsAutoMutex locker ( dbSubscriptionIO::freeListMutex ); dbSubscriptionIO::freeList.release ( pCadaver, size ); }