From b0a532db8adeb909fa2cd8e518ca6917a2d7df0a Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Mon, 4 Nov 2002 03:59:09 +0000 Subject: [PATCH] split the OBTimerQueueManager and TimerQueue into their own files --- otk/Makefile.am | 3 +- otk/timer.cc | 67 +++---------------------------- otk/timer.hh | 85 +++++----------------------------------- otk/timerqueue.hh | 52 ++++++++++++++++++++++++ otk/timerqueuemanager.cc | 67 +++++++++++++++++++++++++++++++ otk/timerqueuemanager.hh | 45 +++++++++++++++++++++ 6 files changed, 180 insertions(+), 139 deletions(-) create mode 100644 otk/timerqueue.hh create mode 100644 otk/timerqueuemanager.cc create mode 100644 otk/timerqueuemanager.hh diff --git a/otk/Makefile.am b/otk/Makefile.am index ada95b7f..694fa25e 100644 --- a/otk/Makefile.am +++ b/otk/Makefile.am @@ -5,7 +5,8 @@ INCLUDES= -I../src noinst_LIBRARIES=libotk.a libotk_a_SOURCES= color.cc display.cc font.cc gccache.cc image.cc \ - imagecontrol.cc rect.cc screeninfo.cc texture.cc timer.cc + imagecontrol.cc rect.cc screeninfo.cc texture.cc timer.cc \ + timerqueuemanager.cc MAINTAINERCLEANFILES= Makefile.in diff --git a/otk/timer.cc b/otk/timer.cc index b2b85a66..bde95f89 100644 --- a/otk/timer.cc +++ b/otk/timer.cc @@ -5,8 +5,7 @@ #endif // HAVE_CONFIG_H #include "timer.hh" -#include "display.hh" -#include "util.hh" +#include "timerqueuemanager.hh" namespace otk { @@ -40,7 +39,7 @@ OBTimer::OBTimer(OBTimerQueueManager *m, OBTimeoutHandler h, OBTimeoutData d) handler = h; data = d; - recur = timing = False; + recur = timing = false; } @@ -70,7 +69,7 @@ void OBTimer::start(void) gettimeofday(&_start, 0); if (! timing) { - timing = True; + timing = true; manager->addTimer(this); } } @@ -78,7 +77,7 @@ void OBTimer::start(void) void OBTimer::stop(void) { - timing = False; + timing = false; manager->removeTimer(this); } @@ -86,7 +85,7 @@ void OBTimer::stop(void) void OBTimer::halt(void) { - timing = False; + timing = false; } @@ -127,60 +126,4 @@ bool OBTimer::shouldFire(const timeval &tm) const (tm.tv_sec == end.tv_sec && tm.tv_usec < end.tv_usec)); } - -void OBTimerQueueManager::fire() -{ - fd_set rfds; - timeval now, tm, *timeout = (timeval *) 0; - - const int xfd = ConnectionNumber(otk::OBDisplay::display); - - FD_ZERO(&rfds); - FD_SET(xfd, &rfds); // break on any x events - - if (! timerList.empty()) { - const OBTimer* const timer = timerList.top(); - - gettimeofday(&now, 0); - tm = timer->timeRemaining(now); - - timeout = &tm; - } - - select(xfd + 1, &rfds, 0, 0, timeout); - - // check for timer timeout - gettimeofday(&now, 0); - - // there is a small chance for deadlock here: - // *IF* the timer list keeps getting refreshed *AND* the time between - // timer->start() and timer->shouldFire() is within the timer's period - // then the timer will keep firing. This should be VERY near impossible. - while (! timerList.empty()) { - OBTimer *timer = timerList.top(); - if (! timer->shouldFire(now)) - break; - - timerList.pop(); - - timer->fireTimeout(); - timer->halt(); - if (timer->isRecurring()) - timer->start(); - } -} - - -void OBTimerQueueManager::addTimer(OBTimer *timer) -{ - assert(timer); - timerList.push(timer); -} - -void OBTimerQueueManager::removeTimer(OBTimer* timer) -{ - assert(timer); - timerList.release(timer); -} - } diff --git a/otk/timer.hh b/otk/timer.hh index 0bc38e1b..610a02e6 100644 --- a/otk/timer.hh +++ b/otk/timer.hh @@ -1,6 +1,6 @@ // -*- mode: C++; indent-tabs-mode: nil; -*- -#ifndef _BLACKBOX_Timer_hh -#define _BLACKBOX_Timer_hh +#ifndef __timer_hh +#define __timer_hh extern "C" { #ifdef TIME_WITH_SYS_TIME @@ -15,16 +15,17 @@ extern "C" { #endif // TIME_WITH_SYS_TIME } -#include -#include -#include - namespace otk { -// forward declaration class OBTimerQueueManager; +//! The data passed to the OBTimeoutHandler function. +/*! + Note: this is a very useful place to put an object instance, and set the + event handler to a static function in the same class. +*/ typedef void *OBTimeoutData; +//! The type of function which can be set as the callback for an OBTimer firing typedef void (*OBTimeoutHandler)(OBTimeoutData); class OBTimer { @@ -68,74 +69,6 @@ public: { return shouldFire(other.endpoint()); } }; - -template -class _timer_queue: protected std::priority_queue<_Tp, _Sequence, _Compare> { -public: - typedef std::priority_queue<_Tp, _Sequence, _Compare> _Base; - - _timer_queue(): _Base() {} - ~_timer_queue() {} - - void release(const _Tp& value) { - c.erase(std::remove(c.begin(), c.end(), value), c.end()); - // after removing the item we need to make the heap again - std::make_heap(c.begin(), c.end(), comp); - } - bool empty() const { return _Base::empty(); } - size_t size() const { return _Base::size(); } - void push(const _Tp& value) { _Base::push(value); } - void pop() { _Base::pop(); } - const _Tp& top() const { return _Base::top(); } -private: - // no copying! - _timer_queue(const _timer_queue&) {} - _timer_queue& operator=(const _timer_queue&) {} -}; - -struct TimerLessThan { - bool operator()(const OBTimer* const l, const OBTimer* const r) const { - return *r < *l; - } -}; - -typedef _timer_queue, TimerLessThan> TimerQueue; - -//! Manages a queue of OBTimer objects -/*! - All OBTimer objects add themself to an OBTimerQueueManager. The manager is - what fires the timers when their time has elapsed. This is done by having the - application call the OBTimerQueueManager::fire class in its main event loop. -*/ -class OBTimerQueueManager { -private: - //! A priority queue of all timers being managed by this class. - TimerQueue timerList; -public: - //! Constructs a new OBTimerQueueManager - OBTimerQueueManager() {} - //! Destroys the OBTimerQueueManager - virtual ~OBTimerQueueManager() {} - - //! Will wait for and fire the next timer in the queue. - /*! - The function will stop waiting if an event is received from the X server. - */ - virtual void fire(); - - //! Adds a new timer to the queue - /*! - @param timer An OBTimer to add to the queue - */ - virtual void addTimer(OBTimer* timer); - //! Removes a timer from the queue - /*! - @param timer An OBTimer already in the queue to remove - */ - virtual void removeTimer(OBTimer* timer); -}; - } -#endif // _BLACKBOX_Timer_hh +#endif // __timer_hh diff --git a/otk/timerqueue.hh b/otk/timerqueue.hh new file mode 100644 index 00000000..f9237a67 --- /dev/null +++ b/otk/timerqueue.hh @@ -0,0 +1,52 @@ +// -*- mode: C++; indent-tabs-mode: nil; -*- +#ifndef __timerqueue_hh +#define __timerqueue_hh + +#ifndef DOXYGEN_IGNORE + +#include "timer.hh" + +#include +#include +#include + +namespace otk { + +template +class _timer_queue: protected std::priority_queue<_Tp, _Sequence, _Compare> { +public: + typedef std::priority_queue<_Tp, _Sequence, _Compare> _Base; + + _timer_queue(): _Base() {} + ~_timer_queue() {} + + void release(const _Tp& value) { + c.erase(std::remove(c.begin(), c.end(), value), c.end()); + // after removing the item we need to make the heap again + std::make_heap(c.begin(), c.end(), comp); + } + bool empty() const { return _Base::empty(); } + size_t size() const { return _Base::size(); } + void push(const _Tp& value) { _Base::push(value); } + void pop() { _Base::pop(); } + const _Tp& top() const { return _Base::top(); } +private: + // no copying! + _timer_queue(const _timer_queue&) {} + _timer_queue& operator=(const _timer_queue&) {} +}; + +struct TimerLessThan { + bool operator()(const OBTimer* const l, const OBTimer* const r) const { + return *r < *l; + } +}; + +typedef _timer_queue, TimerLessThan> TimerQueue; + +} + +#endif // DOXYGEN_IGNORE + +#endif // __timerqueue_hh diff --git a/otk/timerqueuemanager.cc b/otk/timerqueuemanager.cc new file mode 100644 index 00000000..0d7d4983 --- /dev/null +++ b/otk/timerqueuemanager.cc @@ -0,0 +1,67 @@ +// -*- mode: C++; indent-tabs-mode: nil; -*- + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif // HAVE_CONFIG_H + +#include "timerqueuemanager.hh" +#include "display.hh" + +namespace otk { + +void OBTimerQueueManager::fire() +{ + fd_set rfds; + timeval now, tm, *timeout = (timeval *) 0; + + const int xfd = ConnectionNumber(otk::OBDisplay::display); + + FD_ZERO(&rfds); + FD_SET(xfd, &rfds); // break on any x events + + if (! timerList.empty()) { + const OBTimer* const timer = timerList.top(); + + gettimeofday(&now, 0); + tm = timer->timeRemaining(now); + + timeout = &tm; + } + + select(xfd + 1, &rfds, 0, 0, timeout); + + // check for timer timeout + gettimeofday(&now, 0); + + // there is a small chance for deadlock here: + // *IF* the timer list keeps getting refreshed *AND* the time between + // timer->start() and timer->shouldFire() is within the timer's period + // then the timer will keep firing. This should be VERY near impossible. + while (! timerList.empty()) { + OBTimer *timer = timerList.top(); + if (! timer->shouldFire(now)) + break; + + timerList.pop(); + + timer->fireTimeout(); + timer->halt(); + if (timer->isRecurring()) + timer->start(); + } +} + + +void OBTimerQueueManager::addTimer(OBTimer *timer) +{ + assert(timer); + timerList.push(timer); +} + +void OBTimerQueueManager::removeTimer(OBTimer* timer) +{ + assert(timer); + timerList.release(timer); +} + +} diff --git a/otk/timerqueuemanager.hh b/otk/timerqueuemanager.hh new file mode 100644 index 00000000..48e15e5b --- /dev/null +++ b/otk/timerqueuemanager.hh @@ -0,0 +1,45 @@ +// -*- mode: C++; indent-tabs-mode: nil; -*- +#ifndef __timerqueuemanager_hh +#define __timerqueuemanager_hh + +#include "timerqueue.hh" + +namespace otk { + +//! Manages a queue of OBTimer objects +/*! + All OBTimer objects add themself to an OBTimerQueueManager. The manager is + what fires the timers when their time has elapsed. This is done by having the + application call the OBTimerQueueManager::fire class in its main event loop. +*/ +class OBTimerQueueManager { +private: + //! A priority queue of all timers being managed by this class. + TimerQueue timerList; +public: + //! Constructs a new OBTimerQueueManager + OBTimerQueueManager() {} + //! Destroys the OBTimerQueueManager + virtual ~OBTimerQueueManager() {} + + //! Will wait for and fire the next timer in the queue. + /*! + The function will stop waiting if an event is received from the X server. + */ + virtual void fire(); + + //! Adds a new timer to the queue + /*! + @param timer An OBTimer to add to the queue + */ + virtual void addTimer(OBTimer* timer); + //! Removes a timer from the queue + /*! + @param timer An OBTimer already in the queue to remove + */ + virtual void removeTimer(OBTimer* timer); +}; + +} + +#endif // __timerqueuemanager_hh -- 2.39.2