diff --git a/src/libCom/timer/epicsTimer.cpp b/src/libCom/timer/epicsTimer.cpp index 01ae58c93..2364074ce 100644 --- a/src/libCom/timer/epicsTimer.cpp +++ b/src/libCom/timer/epicsTimer.cpp @@ -64,8 +64,10 @@ epicsTimerNotify::expireStatus epicsTimerForC::expire ( const epicsTime & ) return noRestart; } -epicsTimerQueueActiveForC::epicsTimerQueueActiveForC ( bool okToShare, unsigned priority ) : - timerQueueActive ( okToShare, priority ) +epicsTimerQueueActiveForC :: + epicsTimerQueueActiveForC ( RefMgr & refMgr, + bool okToShare, unsigned priority ) : + timerQueueActive ( refMgr, okToShare, priority ) { } @@ -75,9 +77,7 @@ epicsTimerQueueActiveForC::~epicsTimerQueueActiveForC () void epicsTimerQueueActiveForC::release () { - epicsSingleton < timerQueueActiveMgr >::reference pMgr = - timerQueueMgrEPICS.getReference (); - pMgr->release ( *this ); + _refMgr->release ( *this ); } epicsTimerQueuePassiveForC::epicsTimerQueuePassiveForC ( @@ -203,10 +203,10 @@ extern "C" epicsTimerQueueId epicsShareAPI epicsTimerQueueAllocate ( int okToShare, unsigned int threadPriority ) { try { - epicsSingleton < timerQueueActiveMgr >::reference ref = + epicsSingleton < timerQueueActiveMgr > :: reference ref = timerQueueMgrEPICS.getReference (); epicsTimerQueueActiveForC & tmr = - ref->allocate ( okToShare ? true : false, threadPriority ); + ref->allocate ( ref, okToShare ? true : false, threadPriority ); return &tmr; } catch ( ... ) { diff --git a/src/libCom/timer/timerPrivate.h b/src/libCom/timer/timerPrivate.h index 57d1c6ced..f673c891b 100644 --- a/src/libCom/timer/timerPrivate.h +++ b/src/libCom/timer/timerPrivate.h @@ -120,11 +120,14 @@ private: friend class timerQueueActiveMgr; }; +extern epicsSingleton < timerQueueActiveMgr > timerQueueMgrEPICS; + class timerQueueActive : public epicsTimerQueueActive, public epicsThreadRunable, public epicsTimerQueueNotify, public timerQueueActiveMgrPrivate { public: - timerQueueActive ( bool okToShare, unsigned priority ); + typedef epicsSingleton < timerQueueActiveMgr > :: reference RefMgr; + timerQueueActive ( RefMgr &, bool okToShare, unsigned priority ); epicsTimer & createTimer (); epicsTimerForC & createTimerForC ( epicsTimerCallback pCallback, void *pArg ); void show ( unsigned int level ) const; @@ -132,6 +135,7 @@ public: unsigned threadPriority () const; protected: ~timerQueueActive (); + RefMgr _refMgr; private: timerQueue queue; epicsEvent rescheduleEvent; @@ -151,9 +155,10 @@ private: class timerQueueActiveMgr { public: + typedef epicsSingleton < timerQueueActiveMgr > :: reference RefThis; timerQueueActiveMgr (); ~timerQueueActiveMgr (); - epicsTimerQueueActiveForC & allocate ( bool okToShare, + epicsTimerQueueActiveForC & allocate ( RefThis &, bool okToShare, unsigned threadPriority = epicsThreadPriorityMin + 10 ); void release ( epicsTimerQueueActiveForC & ); private: @@ -163,8 +168,6 @@ private: timerQueueActiveMgr & operator = ( const timerQueueActiveMgr & ); }; -extern epicsSingleton < timerQueueActiveMgr > timerQueueMgrEPICS; - class timerQueuePassive : public epicsTimerQueuePassive { public: timerQueuePassive ( epicsTimerQueueNotify & ); @@ -202,7 +205,7 @@ private: struct epicsTimerQueueActiveForC : public timerQueueActive, public tsDLNode < epicsTimerQueueActiveForC > { public: - epicsTimerQueueActiveForC ( bool okToShare, unsigned priority ); + epicsTimerQueueActiveForC ( RefMgr &, bool okToShare, unsigned priority ); void release (); void * operator new ( size_t ); void operator delete ( void * ); diff --git a/src/libCom/timer/timerQueueActive.cpp b/src/libCom/timer/timerQueueActive.cpp index aa6e83af0..c9db12043 100644 --- a/src/libCom/timer/timerQueueActive.cpp +++ b/src/libCom/timer/timerQueueActive.cpp @@ -38,11 +38,13 @@ epicsTimerQueueActive & epicsTimerQueueActive::allocate ( bool okToShare, unsign { epicsSingleton < timerQueueActiveMgr >::reference pMgr = timerQueueMgrEPICS.getReference (); - return pMgr->allocate ( okToShare, threadPriority ); + return pMgr->allocate ( pMgr, okToShare, threadPriority ); } -timerQueueActive::timerQueueActive ( bool okToShareIn, unsigned priority ) : - queue ( *this ), thread ( *this, "timerQueue", +timerQueueActive :: + timerQueueActive ( RefMgr & refMgr, + bool okToShareIn, unsigned priority ) : + _refMgr ( refMgr ), queue ( *this ), thread ( *this, "timerQueue", epicsThreadGetStackSize ( epicsThreadStackMedium ), priority ), sleepQuantum ( epicsThreadSleepQuantum() ), okToShare ( okToShareIn ), exitFlag ( false ), terminateFlag ( false ) diff --git a/src/libCom/timer/timerQueueActiveMgr.cpp b/src/libCom/timer/timerQueueActiveMgr.cpp index 8ccd0d09c..89288a6cb 100644 --- a/src/libCom/timer/timerQueueActiveMgr.cpp +++ b/src/libCom/timer/timerQueueActiveMgr.cpp @@ -30,8 +30,8 @@ timerQueueActiveMgr::~timerQueueActiveMgr () epicsGuard < epicsMutex > locker ( this->mutex ); } -epicsTimerQueueActiveForC & timerQueueActiveMgr::allocate ( - bool okToShare, unsigned threadPriority ) +epicsTimerQueueActiveForC & timerQueueActiveMgr :: + allocate ( RefThis & refThis, bool okToShare, unsigned threadPriority ) { epicsGuard < epicsMutex > locker ( this->mutex ); if ( okToShare ) { @@ -47,7 +47,7 @@ epicsTimerQueueActiveForC & timerQueueActiveMgr::allocate ( } epicsTimerQueueActiveForC & queue = - * new epicsTimerQueueActiveForC ( okToShare, threadPriority ); + * new epicsTimerQueueActiveForC ( refThis, okToShare, threadPriority ); queue.timerQueueActiveMgrPrivate::referenceCount = 1u; if ( okToShare ) { this->sharedQueueList.add ( queue ); @@ -55,18 +55,24 @@ epicsTimerQueueActiveForC & timerQueueActiveMgr::allocate ( return queue; } -void timerQueueActiveMgr::release ( epicsTimerQueueActiveForC &queue ) +void timerQueueActiveMgr :: + release ( epicsTimerQueueActiveForC & queue ) { - epicsGuard < epicsMutex > locker ( this->mutex ); - assert ( queue.timerQueueActiveMgrPrivate::referenceCount > 0u ); - queue.timerQueueActiveMgrPrivate::referenceCount--; - if ( queue.timerQueueActiveMgrPrivate::referenceCount == 0u ) { - if ( queue.sharingOK () ) { - this->sharedQueueList.remove ( queue ); + timerQueueActiveMgrPrivate * pPriv = & queue; + { + epicsGuard < epicsMutex > locker ( this->mutex ); + assert ( queue.timerQueueActiveMgrPrivate::referenceCount > 0u ); + queue.timerQueueActiveMgrPrivate::referenceCount--; + if ( queue.timerQueueActiveMgrPrivate::referenceCount == 0u ) { + if ( queue.sharingOK () ) { + this->sharedQueueList.remove ( queue ); + } } - timerQueueActiveMgrPrivate *pPriv = &queue; - delete pPriv; } + // delete only after we release the guard in case the embedded + // reference is the last one and this object is destroyed + // as a side effect + delete pPriv; } timerQueueActiveMgrPrivate::timerQueueActiveMgrPrivate () :