From f91be05cde3eefc15b23f22c01394c40c633e9c9 Mon Sep 17 00:00:00 2001 From: Jeff Hill Date: Tue, 27 Jun 2000 22:24:58 +0000 Subject: [PATCH] 1) users must now select between single threaded and multi threaded operation 2) default timer queue does not now have manager thread --- src/libCom/timer/osiTimer.cpp | 75 ++++++++++++++++++++++------------- src/libCom/timer/osiTimer.h | 33 ++++++++++----- 2 files changed, 71 insertions(+), 37 deletions(-) diff --git a/src/libCom/timer/osiTimer.cpp b/src/libCom/timer/osiTimer.cpp index 8ccd8a345..982f3c74b 100644 --- a/src/libCom/timer/osiTimer.cpp +++ b/src/libCom/timer/osiTimer.cpp @@ -49,7 +49,7 @@ private: // // default global timer queue // -osiTimerQueue osiDefaultTimerQueue; +osiTimerQueue osiDefaultTimerQueue ( osiTimerQueue::mtsNoManagerThread ); // // osiTimer::osiTimer () @@ -244,7 +244,7 @@ void osiTimer::arm (double initialDelay) // create manager thread on demand so we dont have threads hanging // around that are not used // - if ( this->queue.pMgrThread == NULL ) { + if ( ! this->queue.terminateFlag && this->queue.pMgrThread == NULL ) { this->queue.pMgrThread = new osiTimerThread (this->queue, this->queue.mgrThreadPriority); if ( this->queue.pMgrThread == NULL ) { this->queue.mutex.unlock (); @@ -410,10 +410,12 @@ double osiTimer::timeRemaining () const // // osiTimerQueue::osiTimerQueue () // -osiTimerQueue::osiTimerQueue (unsigned managerThreadPriority) : - pExpireTmr (0), pMgrThread(0), mgrThreadPriority(managerThreadPriority), - inProcess (false), terminateFlag (false), exitFlag (false) +epicsShareFunc osiTimerQueue::osiTimerQueue ( managerThreadSelect mts, + unsigned managerThreadPriority ) : + pExpireTmr (0), pMgrThread (0), mgrThreadPriority (managerThreadPriority), + inProcess (false), exitFlag (false) { + this->terminateFlag = ( mts != mtsCreateManagerThread ); } // @@ -423,25 +425,7 @@ osiTimerQueue::~osiTimerQueue() { osiTimer *pTmr; - if (this->pMgrThread) { - this->terminateFlag = true; - this->rescheduleEvent.signal (); - this->exitEvent.wait (0.1); - if ( ! this->exitFlag && ! this->pMgrThread->isSuspended () ) { - static const unsigned maxCount = 25; - static const double delay = 0.25; - unsigned count = 0; - printf ("waiting %f seconds for timer queue to shut down", - delay * maxCount); - while ( ! this->exitFlag && ! this->pMgrThread->isSuspended () && count < 10) { - this->exitEvent.wait (delay); - printf ("."); - count++; - } - printf ("\n"); - } - delete this->pMgrThread; - } + this->terminateManagerThread (); this->mutex.lock (); @@ -462,6 +446,34 @@ osiTimerQueue::~osiTimerQueue() } } +// +// osiTimerQueue::terminateManagerThread () +// +void osiTimerQueue::terminateManagerThread () +{ + // stop current thread if started and + // prevent launching of thread in the future + this->terminateFlag = true; + if ( this->pMgrThread ) { + + this->rescheduleEvent.signal (); + + while ( ! this->exitFlag && ! this->pMgrThread->isSuspended () ) { + this->exitEvent.wait ( 1.0 ); + } + + this->mutex.lock (); + if ( this->pMgrThread ) { + delete this->pMgrThread; + this->pMgrThread = 0; + } + this->mutex.unlock (); + + // in case other threads are waiting here also + this->exitEvent.signal (); + } +} + // // osiTimerThread::osiTimerThread () // @@ -479,7 +491,7 @@ void osiTimerThread::entryPoint () { queue.exitFlag = false; while ( ! queue.terminateFlag ) { - queue.process (); + queue.privateProcess (); double delay = queue.delayToFirstExpire (); queue.rescheduleEvent.wait ( delay ); } @@ -520,6 +532,13 @@ double osiTimerQueue::delayToFirstExpire () const // osiTimerQueue::process() // void osiTimerQueue::process () +{ + if ( this->terminateFlag ) { + this->privateProcess (); + } +} + +void osiTimerQueue::privateProcess () { osiTime cur ( osiTime::getCurrent () ); osiTimer *pTmr; @@ -616,9 +635,9 @@ void osiTimerQueue::show(unsigned level) const this->mutex.unlock(); } -extern "C" epicsShareFunc osiTimerQueueId epicsShareAPI osiTimerQueueCreate (unsigned managerThreadPriority) +extern "C" epicsShareFunc osiTimerQueueId epicsShareAPI osiTimerQueueCreate ( unsigned managerThreadPriority ) { - return (osiTimerQueueId) new osiTimerQueue (managerThreadPriority); + return (osiTimerQueueId) new osiTimerQueue ( osiTimerQueue::mtsCreateManagerThread, managerThreadPriority ); } class osiTimerForC : public osiTimer { @@ -694,4 +713,4 @@ extern "C" epicsShareFunc TS_STAMP epicsShareAPI osiTimerExpirationDate (osiTime osiTimerForC *pTmr = static_cast (idIn); assert (pTmr); return pTmr->expirationDate (); -} +} \ No newline at end of file diff --git a/src/libCom/timer/osiTimer.h b/src/libCom/timer/osiTimer.h index bf91468cc..bd1c3c33d 100644 --- a/src/libCom/timer/osiTimer.h +++ b/src/libCom/timer/osiTimer.h @@ -44,23 +44,24 @@ class osiTimerQueue; -epicsShareExtern osiTimerQueue osiDefaultTimerQueue; - /* * osiTimer */ -class osiTimer : public tsDLNode { +class osiTimer : public tsDLNode { public: class noDelaySpecified {}; /* exception */ class noMemory {}; /* exception */ /* - * create an active timer that will expire delay seconds after it is created - * or create an inactive timer respectively + * Create an active timer that will expire delay seconds after it is created + * or create an inactive timer respectively. + * + * ** Warning ** default timer queue has no manager thread and is typically + * processed by the file descriptor manager */ - epicsShareFunc osiTimer (double delay, osiTimerQueue & queueIn); - epicsShareFunc osiTimer (double delay); - epicsShareFunc osiTimer (osiTimerQueue & queueIn); + epicsShareFunc osiTimer ( double delay, osiTimerQueue & queueIn ); + epicsShareFunc osiTimer ( double delay); + epicsShareFunc osiTimer ( osiTimerQueue & queueIn ); epicsShareFunc osiTimer (); /* @@ -170,7 +171,12 @@ class osiTimerQueue { friend class osiTimer; friend class osiTimerThread; public: - epicsShareFunc osiTimerQueue (unsigned managerThreadPriority = threadPriorityMin); + enum managerThreadSelect { + mtsNoManagerThread, // you must call the process method (or the fdManager) to expire timers + mtsCreateManagerThread // manager thread expires timers asnychronously + }; + epicsShareFunc osiTimerQueue ( managerThreadSelect mts, + unsigned managerThreadPriority = threadPriorityMin ); epicsShareFunc virtual ~osiTimerQueue(); epicsShareFunc double delayToFirstExpire () const; /* returns seconds */ epicsShareFunc void process (); @@ -188,8 +194,17 @@ private: bool exitFlag; void install (osiTimer &tmr, double delay); + void privateProcess (); + void terminateManagerThread (); }; +/* + * ** Warning ** + * the default timer queue has no manager thread and is typically + * processed by the file descriptor manager + */ +epicsShareExtern osiTimerQueue osiDefaultTimerQueue; + inline osiTime osiTimer::expirationDate () const { return this->exp;