diff --git a/pvDataApp/misc/timer.cpp b/pvDataApp/misc/timer.cpp index dd5483f..083cbf8 100644 --- a/pvDataApp/misc/timer.cpp +++ b/pvDataApp/misc/timer.cpp @@ -26,82 +26,66 @@ namespace epics { namespace pvData { PVDATA_REFCOUNT_MONITOR_DEFINE(timerNode); PVDATA_REFCOUNT_MONITOR_DEFINE(timer); -class TimerNodePvt; +typedef LinkedListNode TimerListNode; +typedef LinkedList TimerList; -typedef LinkedListNode TimerListNode; -typedef LinkedList TimerList; - -class TimerNodePvt { +class TimerNode::Pvt { public: TimerNode *timerNode; TimerCallback *callback; - TimerListNode *timerListNode; + TimerListNode timerListNode; TimeStamp timeToRun; - TimerPvt *timerPvt; + Timer::Pvt *timerPvt; double period; - TimerNodePvt(TimerNode *timerNode,TimerCallback *callback); - ~TimerNodePvt(); + Pvt(TimerNode *timerNode,TimerCallback *callback); }; -TimerNodePvt::TimerNodePvt(TimerNode *timerNode,TimerCallback *callback) +TimerNode::Pvt::Pvt(TimerNode *timerNode,TimerCallback *callback) : timerNode(timerNode),callback(callback), - timerListNode(new TimerListNode(this)),timeToRun(TimeStamp()), + timerListNode(this),timeToRun(), timerPvt(0), period(0.0) {} -TimerNodePvt::~TimerNodePvt() -{ - delete timerListNode; -} - -struct TimerPvt : public Runnable{ +struct Timer::Pvt : public Runnable{ public: - TimerPvt(String threadName,ThreadPriority priority); - ~TimerPvt(); + Pvt(String threadName,ThreadPriority priority); virtual void run(); public: // only used by this source module - TimerList *timerList; + TimerList timerList; Mutex mutex; - Event *waitForWork; - Event *waitForDone; + Event waitForWork; + Event waitForDone; volatile bool alive; - Thread *thread; + Thread thread; + + void addElement(TimerNode::Pvt *node); }; -TimerPvt::TimerPvt(String threadName,ThreadPriority priority) -: timerList(new TimerList()), +Timer::Pvt::Pvt(String threadName,ThreadPriority priority) +: timerList(), mutex(Mutex()), - waitForWork(new Event(false)), - waitForDone(new Event(false)), + waitForWork(false), + waitForDone(false), alive(true), - thread(new Thread(threadName,priority,this)) + thread(threadName,priority,this) {} -TimerPvt::~TimerPvt() +void Timer::Pvt::addElement(TimerNode::Pvt *node) { - delete thread; - delete waitForDone; - delete waitForWork; - delete timerList; -} - -static void addElement(TimerPvt *timer,TimerNodePvt *node) -{ - TimerList *timerList = timer->timerList; - TimerListNode *nextNode = timerList->getHead(); + TimerListNode *nextNode = timerList.getHead(); if(nextNode==0) { - timerList->addTail(node->timerListNode); + timerList.addTail(&node->timerListNode); return; } while(true) { - TimerNodePvt *timerListNode = nextNode->getObject(); + TimerNode::Pvt *timerListNode = nextNode->getObject(); if((node->timeToRun)<(timerListNode->timeToRun)) { - timerList->insertBefore(timerListNode->timerListNode,node->timerListNode); + timerList.insertBefore(&timerListNode->timerListNode,&node->timerListNode); return; } - nextNode = timerList->getNext(timerListNode->timerListNode); + nextNode = timerList.getNext(&timerListNode->timerListNode); if(nextNode==0) { - timerList->addTail(node->timerListNode); + timerList.addTail(&node->timerListNode); return; } } @@ -109,7 +93,7 @@ static void addElement(TimerPvt *timer,TimerNodePvt *node) TimerNode::TimerNode(TimerCallback *callback) -: pImpl(new TimerNodePvt(this,callback)) +: pImpl(new Pvt(this,callback)) { PVDATA_REFCOUNT_MONITOR_CONSTRUCT(timerNode); } @@ -118,56 +102,55 @@ TimerNode::TimerNode(TimerCallback *callback) TimerNode::~TimerNode() { cancel(); - delete pImpl; PVDATA_REFCOUNT_MONITOR_DESTRUCT(timerNode); } void TimerNode::cancel() { - TimerPvt *timerPvt = pImpl->timerPvt; + Timer::Pvt *timerPvt = pImpl->timerPvt; if(timerPvt==0) return; Lock xx(&timerPvt->mutex); if(pImpl->timerPvt==0) return; - pImpl->timerPvt->timerList->remove(pImpl); + pImpl->timerPvt->timerList.remove(pImpl.get()); pImpl->timerPvt = 0; } bool TimerNode::isScheduled() { - TimerPvt *pvt = pImpl->timerPvt; + Timer::Pvt *pvt = pImpl->timerPvt; if(pvt==0) return false; Lock xx(&pvt->mutex); - return pImpl->timerListNode->isOnList(); + return pImpl->timerListNode.isOnList(); } -void TimerPvt::run() +void Timer::Pvt::run() { TimeStamp currentTime; while(alive) { currentTime.getCurrent(); TimeStamp *timeToRun = 0; double period = 0.0; - TimerNodePvt *nodeToCall = 0; + TimerNode::Pvt *nodeToCall = 0; { Lock xx(&mutex); - TimerListNode *timerListNode = timerList->getHead(); + TimerListNode *timerListNode = timerList.getHead(); if(timerListNode!=0) { - TimerNodePvt *timerNodePvt = timerListNode->getObject(); + TimerNode::Pvt *timerNodePvt = timerListNode->getObject(); timeToRun = &timerNodePvt->timeToRun; double diff = TimeStamp::diff( *timeToRun,currentTime); if(diff<=0.0) { nodeToCall = timerNodePvt; - timerList->removeHead(); + timerList.removeHead(); period = timerNodePvt->period; if(period>0.0) { timerNodePvt->timeToRun += period; - addElement(this,timerNodePvt); + addElement(timerNodePvt); } else { timerNodePvt->timerPvt = 0; } - timerListNode = timerList->getHead(); + timerListNode = timerList.getHead(); if(timerListNode!=0) { timerNodePvt = timerListNode->getObject(); timeToRun = &timerNodePvt->timeToRun; @@ -182,17 +165,17 @@ void TimerPvt::run() } if(!alive) break; if(timeToRun==0) { - waitForWork->wait(); + waitForWork.wait(); } else { double delay = TimeStamp::diff(*timeToRun,currentTime); - waitForWork->wait(delay); + waitForWork.wait(delay); } } - waitForDone->signal(); + waitForDone.signal(); } Timer::Timer(String threadName, ThreadPriority priority) -: pImpl(new TimerPvt(threadName,priority)) +: pImpl(new Pvt(threadName,priority)) { PVDATA_REFCOUNT_MONITOR_CONSTRUCT(timer); } @@ -202,14 +185,12 @@ Timer::~Timer() { Lock xx(&pImpl->mutex); pImpl->alive = false; } - pImpl->waitForWork->signal(); - pImpl->waitForDone->wait(); - TimerList *timerList = pImpl->timerList; + pImpl->waitForWork.signal(); + pImpl->waitForDone.wait(); TimerListNode *node = 0; - while((node = timerList->removeHead())!=0) { + while((node = pImpl->timerList.removeHead())!=0) { node->getObject()->callback->timerStopped(); } - delete pImpl; PVDATA_REFCOUNT_MONITOR_DESTRUCT(timer); } @@ -219,8 +200,8 @@ void Timer::scheduleAfterDelay(TimerNode *timerNode,double delay) } void Timer::schedulePeriodic(TimerNode *timerNode,double delay,double period) { - TimerNodePvt *timerNodePvt = timerNode->pImpl; - if(timerNodePvt->timerListNode->isOnList()) { + TimerNode::Pvt *timerNodePvt = timerNode->pImpl.get(); + if(timerNodePvt->timerListNode.isOnList()) { throw std::logic_error(String("already queued")); } if(!pImpl->alive) { @@ -234,12 +215,12 @@ void Timer::schedulePeriodic(TimerNode *timerNode,double delay,double period) bool isFirst = false; { Lock xx(&pImpl->mutex); - timerNodePvt->timerPvt = pImpl; - addElement(pImpl,timerNodePvt); - TimerNodePvt *first = pImpl->timerList->getHead()->getObject(); + timerNodePvt->timerPvt = pImpl.get(); + pImpl->addElement(timerNodePvt); + TimerNode::Pvt *first = pImpl->timerList.getHead()->getObject(); if(first==timerNodePvt) isFirst = true; } - if(isFirst) pImpl->waitForWork->signal(); + if(isFirst) pImpl->waitForWork.signal(); } }} diff --git a/pvDataApp/misc/timer.h b/pvDataApp/misc/timer.h index 36fe4d8..63aa495 100644 --- a/pvDataApp/misc/timer.h +++ b/pvDataApp/misc/timer.h @@ -6,6 +6,7 @@ */ #ifndef TIMER_H #define TIMER_H +#include #include #include #include @@ -18,6 +19,8 @@ namespace epics { namespace pvData { +class Timer; + class TimerCallback { public: virtual void callback() = 0; @@ -30,8 +33,10 @@ public: ~TimerNode(); void cancel(); bool isScheduled(); + + class Pvt; private: - class TimerNodePvt *pImpl; + std::auto_ptr pImpl; friend class Timer; }; @@ -41,9 +46,10 @@ public: ~Timer(); void scheduleAfterDelay(TimerNode *timerNode,double delay); void schedulePeriodic(TimerNode *timerNode,double delay,double period); + + class Pvt; private: - class TimerPvt *pImpl; - friend class TimerNode; + std::auto_ptr pImpl; }; }}