diff --git a/src/libCom/timer/epicsTimer.cpp b/src/libCom/timer/epicsTimer.cpp index 900db4e39..e50e2e299 100644 --- a/src/libCom/timer/epicsTimer.cpp +++ b/src/libCom/timer/epicsTimer.cpp @@ -48,6 +48,20 @@ private: static tsFreeList < epicsTimerNotifyForC > freeList; }; +class epicsTimerQueueNotifyForC : public epicsTimerQueueNotify { +public: + epicsTimerQueueNotifyForC ( epicsTimerQueueReschedualCallback pCallback, void *pPrivate ); + void * operator new ( size_t size ); + void operator delete ( void *pCadaver, size_t size ); +protected: + virtual ~epicsTimerQueueNotifyForC (); +private: + epicsTimerQueueReschedualCallback pCallback; + void *pPrivate; + void reschedule (); + static tsFreeList < epicsTimerQueueNotifyForC > freeList; +}; + tsFreeList < epicsTimerNotifyForC > epicsTimerNotifyForC::freeList; inline void * epicsTimerNotifyForC::operator new ( size_t size ) @@ -63,7 +77,7 @@ inline void epicsTimerNotifyForC::operator delete ( void *pCadaver, size_t size epicsTimerNotifyForC::epicsTimerNotifyForC ( epicsTimerCallback pCBIn, void *pPrivateIn ) : pCallBack ( pCBIn ), pPrivate ( pPrivateIn ) {} - epicsTimerNotifyForC::~epicsTimerNotifyForC () {} +epicsTimerNotifyForC::~epicsTimerNotifyForC () {} epicsTimerNotify::expireStatus epicsTimerNotifyForC::expire () { @@ -71,12 +85,39 @@ epicsTimerNotify::expireStatus epicsTimerNotifyForC::expire () return noRestart; } -extern "C" epicsNonThreadedTimerQueueId epicsShareAPI - epicsNonThreadedTimerQueueAllocate () +tsFreeList < epicsTimerQueueNotifyForC > epicsTimerQueueNotifyForC::freeList; + +inline void * epicsTimerQueueNotifyForC::operator new ( size_t size ) +{ + return epicsTimerQueueNotifyForC::freeList.allocate ( size ); +} + +inline void epicsTimerQueueNotifyForC::operator delete ( void *pCadaver, size_t size ) +{ + epicsTimerQueueNotifyForC::freeList.release ( pCadaver, size ); +} + + +epicsTimerQueueNotifyForC::epicsTimerQueueNotifyForC ( epicsTimerQueueReschedualCallback pCallbackIn, void *pPrivateIn ) : + pCallback ( pCallbackIn ), pPrivate ( pPrivateIn ) {} + +epicsTimerQueueNotifyForC::~epicsTimerQueueNotifyForC () {} + +void epicsTimerQueueNotifyForC::reschedule () +{ + (*this->pCallback) ( this->pPrivate ); +} + +extern "C" epicsTimerQueueNonThreadedId epicsShareAPI + epicsTimerQueueNonThreadedCreate ( epicsTimerQueueReschedualCallback pCallbackIn, void *pPrivateIn ) { try { - epicsNonThreadedTimerQueue &queue = - epicsNonThreadedTimerQueue::allocate (); + epicsTimerQueueNotifyForC *pNotify = new epicsTimerQueueNotifyForC ( pCallbackIn, pPrivateIn ); + if ( ! pNotify ) { + throw timer::noMemory (); + } + epicsTimerQueueNonThreaded &queue = + epicsTimerQueueNonThreaded::create ( *pNotify ); return &queue; } catch ( ... ) { @@ -85,26 +126,26 @@ extern "C" epicsNonThreadedTimerQueueId epicsShareAPI } extern "C" void epicsShareAPI - epicsNonThreadedTimerQueueRelease ( epicsNonThreadedTimerQueueId pQueue ) + epicsTimerQueueNonThreadedDestroy ( epicsTimerQueueNonThreadedId pQueue ) { - pQueue->release (); + delete pQueue; } extern "C" void epicsShareAPI - epicsNonThreadedTimerQueueProcess ( epicsNonThreadedTimerQueueId pQueue ) + epicsTimerQueueNonThreadedProcess ( epicsTimerQueueNonThreadedId pQueue ) { pQueue->process (); } extern "C" double epicsShareAPI - epicsNonThreadedTimerQueueGetDelayToNextExpire ( - epicsNonThreadedTimerQueueId pQueue ) + epicsTimerQueueNonThreadedGetDelayToNextExpire ( + epicsTimerQueueNonThreadedId pQueue ) { return pQueue->getNextExpireDelay (); } -extern "C" epicsTimerId epicsShareAPI epicsNonThreadedTimerQueueCreateTimer ( - epicsNonThreadedTimerQueueId pQueue, +extern "C" epicsTimerId epicsShareAPI epicsTimerQueueNonThreadedCreateTimer ( + epicsTimerQueueNonThreadedId pQueue, epicsTimerCallback pCallback, void *pArg ) { try { @@ -120,18 +161,18 @@ extern "C" epicsTimerId epicsShareAPI epicsNonThreadedTimerQueueCreateTimer ( } } -extern "C" void epicsShareAPI epicsNonThreadedTimerQueueShow ( - epicsNonThreadedTimerQueueId pQueue, unsigned int level ) +extern "C" void epicsShareAPI epicsTimerQueueNonThreadedShow ( + epicsTimerQueueNonThreadedId pQueue, unsigned int level ) { pQueue->show ( level ); } -extern "C" epicsThreadedTimerQueueId epicsShareAPI - epicsThreadedTimerQueueCreate ( int okToShare, unsigned int threadPriority ) +extern "C" epicsTimerQueueThreadedId epicsShareAPI + epicsTimerQueueThreadedCreate ( int okToShare, unsigned int threadPriority ) { try { - epicsThreadedTimerQueue & queue = - epicsThreadedTimerQueue::allocate + epicsTimerQueueThreaded & queue = + epicsTimerQueueThreaded::allocate ( okToShare ? true : false, threadPriority ); return &queue; } @@ -140,13 +181,13 @@ extern "C" epicsThreadedTimerQueueId epicsShareAPI } } -extern "C" void epicsShareAPI epicsThreadedTimerQueueDelete ( epicsThreadedTimerQueueId pQueue ) +extern "C" void epicsShareAPI epicsTimerQueueThreadedDelete ( epicsTimerQueueThreadedId pQueue ) { pQueue->release (); } -extern "C" epicsTimerId epicsShareAPI epicsThreadedTimerQueueCreateTimer ( - epicsThreadedTimerQueueId pQueue, epicsTimerCallback pCallback, void *pArg ) +extern "C" epicsTimerId epicsShareAPI epicsTimerQueueThreadedCreateTimer ( + epicsTimerQueueThreadedId pQueue, epicsTimerCallback pCallback, void *pArg ) { try { epicsTimerNotifyForC *pNotify = new epicsTimerNotifyForC ( pCallback, pArg ); @@ -161,8 +202,8 @@ extern "C" epicsTimerId epicsShareAPI epicsThreadedTimerQueueCreateTimer ( } } -extern "C" void epicsShareAPI epicsThreadedTimerQueueShow ( - epicsThreadedTimerQueueId pQueue, unsigned int level ) +extern "C" void epicsShareAPI epicsTimerQueueThreadedShow ( + epicsTimerQueueThreadedId pQueue, unsigned int level ) { pQueue->show ( level ); } diff --git a/src/libCom/timer/epicsTimer.h b/src/libCom/timer/epicsTimer.h index c490554de..79afa353f 100644 --- a/src/libCom/timer/epicsTimer.h +++ b/src/libCom/timer/epicsTimer.h @@ -49,27 +49,32 @@ public: virtual void show ( unsigned int level ) const = 0; }; -struct epicsShareClass epicsThreadedTimerQueue { +struct epicsShareClass epicsTimerQueueThreaded { public: - static epicsThreadedTimerQueue & allocate ( + static epicsTimerQueueThreaded & allocate ( bool okToShare, int threadPriority = epicsThreadPriorityMin + 10 ); virtual void release () = 0; virtual epicsTimer & createTimer ( epicsTimerNotify & ) = 0; virtual void show ( unsigned int level ) const = 0; protected: - virtual ~epicsThreadedTimerQueue () = 0; + virtual ~epicsTimerQueueThreaded () = 0; }; -struct epicsShareClass epicsNonThreadedTimerQueue { +class epicsTimerQueueNotify { public: - static epicsNonThreadedTimerQueue & allocate (); - virtual void release () = 0; + // called when a new timer is inserted into the queue and the + // delay to the next expire has changed + virtual void reschedule () = 0; +}; + +struct epicsShareClass epicsTimerQueueNonThreaded { +public: + static epicsTimerQueueNonThreaded & create ( epicsTimerQueueNotify & ); + virtual ~epicsTimerQueueNonThreaded () = 0; virtual epicsTimer & createTimer ( epicsTimerNotify & ) = 0; virtual void process () = 0; virtual double getNextExpireDelay () const = 0; virtual void show ( unsigned int level ) const = 0; -protected: - virtual ~epicsNonThreadedTimerQueue () = 0; }; inline epicsTimerNotify::expireStatus::expireStatus ( restart_t restart ) : @@ -99,35 +104,38 @@ inline double epicsTimerNotify::expireStatus::expirationDelay () const extern "C" { #endif /* __cplusplus */ -typedef struct epicsNonThreadedTimerQueue * epicsNonThreadedTimerQueueId; -typedef struct epicsThreadedTimerQueue * epicsThreadedTimerQueueId; -typedef struct epicsTimer * epicsTimerId; -typedef void ( *epicsTimerCallback ) ( void * ); - -epicsShareFunc epicsNonThreadedTimerQueueId epicsShareAPI - epicsNonThreadedTimerQueueAttach (); +/* threaded timer queue management */ +typedef struct epicsTimerQueueThreaded * epicsTimerQueueThreadedId; +epicsShareFunc epicsTimerQueueThreadedId epicsShareAPI + epicsTimerQueueThreadedAllocate ( int okToShare, unsigned int threadPriority ); epicsShareFunc void epicsShareAPI - epicsNonThreadedTimerQueueRelease ( epicsNonThreadedTimerQueueId ); -epicsShareFunc void epicsShareAPI - epicsNonThreadedTimerQueueProcess ( epicsNonThreadedTimerQueueId ); -epicsShareFunc double epicsShareAPI - epicsNonThreadedTimerQueueGetDelayToNextExpire ( - epicsNonThreadedTimerQueueId ); -epicsShareFunc epicsTimerId epicsShareAPI epicsNonThreadedTimerQueueCreateTimer ( - epicsNonThreadedTimerQueueId queueid, epicsTimerCallback pCallback, void *pArg ); -epicsShareFunc void epicsShareAPI epicsNonThreadedTimerQueueShow ( - epicsNonThreadedTimerQueueId id, unsigned int level ); - -epicsShareFunc epicsThreadedTimerQueueId epicsShareAPI - epicsThreadedTimerQueueAttach ( int okToShare, unsigned int threadPriority ); -epicsShareFunc void epicsShareAPI - epicsThreadedTimerQueueRelease ( epicsThreadedTimerQueueId ); -epicsShareFunc epicsTimerId epicsShareAPI - epicsThreadedTimerQueueCreateTimer ( epicsThreadedTimerQueueId queueid, - epicsTimerCallback callback, void *arg ); + epicsTimerQueueThreadedRelease ( epicsTimerQueueThreadedId ); epicsShareFunc void epicsShareAPI - epicsThreadedTimerQueueShow ( epicsThreadedTimerQueueId id, unsigned int level ); + epicsTimerQueueThreadedShow ( epicsTimerQueueThreadedId id, unsigned int level ); +/* non-threaded timer queue management */ +typedef struct epicsTimerQueueNonThreaded * epicsTimerQueueNonThreadedId; +typedef void ( *epicsTimerQueueReschedualCallback ) ( void *pPrivate ); +epicsShareFunc epicsTimerQueueNonThreadedId epicsShareAPI + epicsTimerQueueNonThreadedCreate ( epicsTimerQueueReschedualCallback, void *pPrivate ); +epicsShareFunc void epicsShareAPI + epicsTimerQueueNonThreadedDestroy ( epicsTimerQueueNonThreadedId ); +epicsShareFunc void epicsShareAPI + epicsTimerQueueNonThreadedProcess ( epicsTimerQueueNonThreadedId ); +epicsShareFunc double epicsShareAPI + epicsTimerQueueNonThreadedGetDelayToNextExpire ( + epicsTimerQueueNonThreadedId ); +epicsShareFunc void epicsShareAPI epicsTimerQueueNonThreadedShow ( + epicsTimerQueueNonThreadedId id, unsigned int level ); + +/* timer management */ +typedef struct epicsTimer * epicsTimerId; +typedef void ( *epicsTimerCallback ) ( void *pPrivate ); +epicsShareFunc epicsTimerId epicsShareAPI + epicsTimerQueueThreadedCreateTimer ( epicsTimerQueueThreadedId queueid, + epicsTimerCallback callback, void *arg ); +epicsShareFunc epicsTimerId epicsShareAPI epicsTimerQueueNonThreadedCreateTimer ( + epicsTimerQueueNonThreadedId queueid, epicsTimerCallback pCallback, void *pArg ); epicsShareFunc void epicsShareAPI epicsTimerDestroy ( epicsTimerId id ); epicsShareFunc void epicsShareAPI diff --git a/src/libCom/timer/epicsTimerPrivate.h b/src/libCom/timer/epicsTimerPrivate.h index 322b9a787..924335dc3 100644 --- a/src/libCom/timer/epicsTimerPrivate.h +++ b/src/libCom/timer/epicsTimerPrivate.h @@ -67,14 +67,9 @@ private: friend class timerQueue; }; -class timerQueueNotify { -public: - virtual void reschedule () = 0; -}; - class timerQueue { public: - timerQueue ( timerQueueNotify ¬ify ); + timerQueue ( epicsTimerQueueNotify ¬ify ); ~timerQueue (); void process (); double delayToFirstExpire () const; @@ -83,7 +78,7 @@ private: mutable epicsMutex mutex; epicsEvent cancelBlockingEvent; tsDLList < timer > timerList; - timerQueueNotify ¬ify; + epicsTimerQueueNotify ¬ify; timer *pExpireTmr; epicsThreadId processThread; bool cancelPending; @@ -100,8 +95,8 @@ private: friend class timerQueueThreadedMgr; }; -class timerQueueThreaded : public epicsThreadedTimerQueue, - public epicsThreadRunable, public timerQueueNotify, +class timerQueueThreaded : public epicsTimerQueueThreaded, + public epicsThreadRunable, public epicsTimerQueueNotify, public timerQueueThreadedMgrPrivate, public tsDLNode < timerQueueThreaded > { public: @@ -139,10 +134,9 @@ private: tsDLList < timerQueueThreaded > sharedQueueList; }; -class timerQueueNonThreaded : public epicsNonThreadedTimerQueue, - public timerQueueNotify { +class timerQueueNonThreaded : public epicsTimerQueueNonThreaded { public: - timerQueueNonThreaded (); + timerQueueNonThreaded ( epicsTimerQueueNotify & ); ~timerQueueNonThreaded (); epicsTimer & createTimer ( epicsTimerNotify & ); void process (); @@ -150,12 +144,8 @@ public: void reschedule (); void show ( unsigned int level ) const; void release (); - static timerQueueNonThreaded & allocate (); private: timerQueue queue; - static epicsMutex mutex; - static timerQueueNonThreaded *pQueue; - static unsigned useCount; }; inline void * timer::operator new ( size_t size ) diff --git a/src/libCom/timer/timerQueue.cpp b/src/libCom/timer/timerQueue.cpp index 39cd665f1..29c0bb17b 100644 --- a/src/libCom/timer/timerQueue.cpp +++ b/src/libCom/timer/timerQueue.cpp @@ -31,7 +31,7 @@ #define epicsExportSharedSymbols #include "epicsTimerPrivate.h" -timerQueue::timerQueue ( timerQueueNotify ¬ifyIn ) : +timerQueue::timerQueue ( epicsTimerQueueNotify ¬ifyIn ) : notify ( notifyIn ), pExpireTmr ( 0 ), processThread ( 0 ), cancelPending ( false ) { diff --git a/src/libCom/timer/timerQueueNonThreaded.cpp b/src/libCom/timer/timerQueueNonThreaded.cpp index 787f632fc..5b4355e42 100644 --- a/src/libCom/timer/timerQueueNonThreaded.cpp +++ b/src/libCom/timer/timerQueueNonThreaded.cpp @@ -31,58 +31,25 @@ #define epicsExportSharedSymbols #include "epicsTimerPrivate.h" -unsigned timerQueueNonThreaded::useCount; -timerQueueNonThreaded * timerQueueNonThreaded::pQueue; -epicsMutex timerQueueNonThreaded::mutex; +epicsTimerQueueNonThreaded::~epicsTimerQueueNonThreaded () {} -epicsNonThreadedTimerQueue::~epicsNonThreadedTimerQueue () {} - -epicsNonThreadedTimerQueue &epicsNonThreadedTimerQueue::allocate () +epicsTimerQueueNonThreaded &epicsTimerQueueNonThreaded::create ( epicsTimerQueueNotify ¬ify ) { - return epicsNonThreadedTimerQueue::allocate (); -} - -timerQueueNonThreaded &timerQueueNonThreaded::allocate () -{ - epicsAutoMutex locker ( timerQueueNonThreaded::mutex ); - if ( timerQueueNonThreaded::pQueue ) { - timerQueueNonThreaded::useCount++; - return *timerQueueNonThreaded::pQueue; - } - else { - timerQueueNonThreaded::pQueue = new timerQueueNonThreaded (); - if ( ! timerQueueNonThreaded::pQueue ) { - throw timer::noMemory (); - } - timerQueueNonThreaded::useCount = 1u; - return *timerQueueNonThreaded::pQueue; + timerQueueNonThreaded *pQueue = new timerQueueNonThreaded ( notify ); + if ( ! pQueue ) { + throwWithLocation ( timer::noMemory () ); } + return *pQueue; } -timerQueueNonThreaded::timerQueueNonThreaded () : - queue ( *this ) -{ -} +timerQueueNonThreaded::timerQueueNonThreaded ( epicsTimerQueueNotify ¬ifyIn ) : + queue ( notifyIn ) {} -timerQueueNonThreaded::~timerQueueNonThreaded () -{ +timerQueueNonThreaded::~timerQueueNonThreaded () {} -} - -void timerQueueNonThreaded::release () +epicsTimer & timerQueueNonThreaded::createTimer ( epicsTimerNotify & notifyIn ) { - epicsAutoMutex locker ( timerQueueNonThreaded::mutex ); - assert ( timerQueueNonThreaded::useCount >= 1u ); - timerQueueNonThreaded::useCount--; - if ( timerQueueNonThreaded::useCount == 0u ) { - delete timerQueueNonThreaded::pQueue; - timerQueueNonThreaded::pQueue = 0; - } -} - -epicsTimer & timerQueueNonThreaded::createTimer ( epicsTimerNotify & notify ) -{ - timer *pTmr = new timer ( notify, this->queue ); + timer *pTmr = new timer ( notifyIn, this->queue ); if ( ! pTmr ) { throwWithLocation ( timer::noMemory () ); } diff --git a/src/libCom/timer/timerQueueThreaded.cpp b/src/libCom/timer/timerQueueThreaded.cpp index f45001ef2..f7ad8b0de 100644 --- a/src/libCom/timer/timerQueueThreaded.cpp +++ b/src/libCom/timer/timerQueueThreaded.cpp @@ -33,9 +33,9 @@ static timerQueueThreadedMgr queueMgr; -epicsThreadedTimerQueue::~epicsThreadedTimerQueue () {} +epicsTimerQueueThreaded::~epicsTimerQueueThreaded () {} -epicsThreadedTimerQueue &epicsThreadedTimerQueue::allocate ( bool okToShare, int threadPriority ) +epicsTimerQueueThreaded &epicsTimerQueueThreaded::allocate ( bool okToShare, int threadPriority ) { return queueMgr.allocate ( okToShare, threadPriority ); }