summaryrefslogtreecommitdiff
path: root/otk
diff options
context:
space:
mode:
Diffstat (limited to 'otk')
-rw-r--r--otk/Makefile.am29
-rw-r--r--otk/application.cc9
-rw-r--r--otk/application.hh2
-rw-r--r--otk/image.hh9
-rw-r--r--otk/imagecontrol.cc22
-rw-r--r--otk/otk.hh2
-rw-r--r--otk/otk.i2
-rw-r--r--otk/timer.cc176
-rw-r--r--otk/timer.hh171
9 files changed, 202 insertions, 220 deletions
diff --git a/otk/Makefile.am b/otk/Makefile.am
index dc84e0e2..3677c2b6 100644
--- a/otk/Makefile.am
+++ b/otk/Makefile.am
@@ -10,7 +10,7 @@ noinst_LTLIBRARIES=libotk.la
libotk_la_SOURCES= color.cc display.cc font.cc gccache.cc image.cc \
property.cc imagecontrol.cc rect.cc screeninfo.cc \
- texture.cc timer.cc timerqueuemanager.cc style.cc \
+ texture.cc timer.cc style.cc \
configuration.cc util.cc widget.cc focuswidget.cc \
button.cc eventhandler.cc eventdispatcher.cc ustring.cc \
label.cc focuslabel.cc application.cc appwidget.cc
@@ -34,18 +34,17 @@ otk_test: libotk.a otk_test.cc
# local dependencies
application.o: application.cc application.hh eventdispatcher.hh \
- eventhandler.hh display.hh configuration.hh timerqueuemanager.hh \
- timerqueue.hh timer.hh image.hh color.hh screeninfo.hh rect.hh \
+ eventhandler.hh display.hh configuration.hh \
+ timer.hh image.hh color.hh screeninfo.hh rect.hh \
point.hh style.hh font.hh texture.hh util.hh widget.hh
appwidget.o: appwidget.cc appwidget.hh widget.hh rect.hh point.hh \
texture.hh color.hh util.hh style.hh font.hh image.hh screeninfo.hh \
timer.hh configuration.hh eventdispatcher.hh eventhandler.hh \
- application.hh display.hh timerqueuemanager.hh timerqueue.hh
+ application.hh display.hh
button.o: button.cc button.hh focuslabel.hh focuswidget.hh widget.hh \
rect.hh point.hh texture.hh color.hh util.hh style.hh font.hh \
image.hh screeninfo.hh timer.hh configuration.hh eventdispatcher.hh \
- eventhandler.hh application.hh display.hh timerqueuemanager.hh \
- timerqueue.hh
+ eventhandler.hh application.hh display.hh
color.o: color.cc color.hh display.hh screeninfo.hh rect.hh point.hh
configuration.o: configuration.cc configuration.hh util.hh
eventdispatcher.o: eventdispatcher.cc eventdispatcher.hh \
@@ -54,13 +53,11 @@ eventhandler.o: eventhandler.cc eventhandler.hh
focuslabel.o: focuslabel.cc focuslabel.hh focuswidget.hh widget.hh \
rect.hh point.hh texture.hh color.hh util.hh style.hh font.hh \
image.hh screeninfo.hh timer.hh configuration.hh eventdispatcher.hh \
- eventhandler.hh application.hh display.hh timerqueuemanager.hh \
- timerqueue.hh
+ eventhandler.hh application.hh display.hh
focuswidget.o: focuswidget.cc focuswidget.hh widget.hh rect.hh \
point.hh texture.hh color.hh util.hh style.hh font.hh image.hh \
screeninfo.hh timer.hh configuration.hh eventdispatcher.hh \
- eventhandler.hh application.hh display.hh timerqueuemanager.hh \
- timerqueue.hh
+ eventhandler.hh application.hh display.hh
font.o: font.cc font.hh util.hh display.hh color.hh screeninfo.hh \
rect.hh point.hh
gccache.o: gccache.cc gccache.hh display.hh color.hh assassin.hh \
@@ -72,10 +69,10 @@ imagecontrol.o: imagecontrol.cc display.hh color.hh image.hh \
label.o: label.cc label.hh widget.hh rect.hh point.hh texture.hh \
color.hh util.hh style.hh font.hh image.hh screeninfo.hh timer.hh \
configuration.hh eventdispatcher.hh eventhandler.hh application.hh \
- display.hh timerqueuemanager.hh timerqueue.hh
+ display.hh
otk_test.o: otk_test.cc application.hh eventdispatcher.hh \
- eventhandler.hh display.hh configuration.hh timerqueuemanager.hh \
- timerqueue.hh timer.hh image.hh color.hh screeninfo.hh rect.hh \
+ eventhandler.hh display.hh configuration.hh \
+ timer.hh image.hh color.hh screeninfo.hh rect.hh \
point.hh style.hh font.hh texture.hh util.hh focuswidget.hh widget.hh \
appwidget.hh button.hh focuslabel.hh
property.o: property.cc property.hh screeninfo.hh rect.hh point.hh \
@@ -88,11 +85,9 @@ style.o: style.cc display.hh util.hh style.hh color.hh font.hh \
configuration.hh
texture.o: texture.cc texture.hh color.hh util.hh display.hh image.hh \
screeninfo.hh rect.hh point.hh timer.hh
-timer.o: timer.cc timer.hh timerqueuemanager.hh timerqueue.hh
-timerqueuemanager.o: timerqueuemanager.cc timerqueuemanager.hh \
- timerqueue.hh timer.hh display.hh
+timer.o: timer.cc timer.hh
util.o: util.cc util.hh
widget.o: widget.cc widget.hh rect.hh point.hh texture.hh color.hh \
util.hh style.hh font.hh image.hh screeninfo.hh timer.hh \
configuration.hh eventdispatcher.hh eventhandler.hh application.hh \
- display.hh timerqueuemanager.hh timerqueue.hh assassin.hh
+ display.hh assassin.hh
diff --git a/otk/application.cc b/otk/application.cc
index 1c4a32a6..fd8689ee 100644
--- a/otk/application.cc
+++ b/otk/application.cc
@@ -7,6 +7,7 @@
#include "application.hh"
#include "eventhandler.hh"
#include "widget.hh"
+#include "timer.hh"
extern "C" {
#ifdef HAVE_STDLIB_H
@@ -29,8 +30,8 @@ Application::Application(int argc, char **argv)
const ScreenInfo *s_info = _display.screenInfo(DefaultScreen(*_display));
- _timer_manager = new TimerQueueManager();
- _img_ctrl = new ImageControl(_timer_manager, s_info, True, 4, 5, 200);
+ Timer::initialize();
+ _img_ctrl = new ImageControl(s_info, True, 4, 5, 200);
_style_conf = new Configuration(False);
_style = new Style(_img_ctrl);
@@ -41,8 +42,8 @@ Application::~Application()
{
delete _style_conf;
delete _img_ctrl;
- delete _timer_manager;
delete _style;
+ Timer::destroy();
}
void Application::loadStyle(void)
@@ -68,7 +69,7 @@ void Application::run(void)
while (_appwidget_count > 0) {
dispatchEvents();
- _timer_manager->fire(); // fire pending events
+ Timer::dispatchTimers(); // fire pending events
}
}
diff --git a/otk/application.hh b/otk/application.hh
index a0795acc..4d7b0d89 100644
--- a/otk/application.hh
+++ b/otk/application.hh
@@ -5,7 +5,6 @@
#include "eventdispatcher.hh"
#include "display.hh"
#include "configuration.hh"
-#include "timerqueuemanager.hh"
#include "image.hh"
#include "style.hh"
@@ -33,7 +32,6 @@ private:
void loadStyle(void);
Display _display;
- TimerQueueManager *_timer_manager;
ImageControl *_img_ctrl;
Configuration *_style_conf;
Style *_style;
diff --git a/otk/image.hh b/otk/image.hh
index d172a21e..225660cf 100644
--- a/otk/image.hh
+++ b/otk/image.hh
@@ -77,11 +77,10 @@ public:
};
#endif
- ImageControl(otk::TimerQueueManager *timermanager,
- const otk::ScreenInfo *scrn,
- bool _dither= False, int _cpc = 4,
- unsigned long cache_timeout = 300000l,
- unsigned long cmax = 200l);
+ ImageControl(const otk::ScreenInfo *scrn,
+ bool _dither= False, int _cpc = 4,
+ unsigned long cache_timeout = 300000l,
+ unsigned long cmax = 200l);
virtual ~ImageControl(void);
inline bool doDither(void) { return dither; }
diff --git a/otk/imagecontrol.cc b/otk/imagecontrol.cc
index 348e2343..ab8f5c50 100644
--- a/otk/imagecontrol.cc
+++ b/otk/imagecontrol.cc
@@ -41,11 +41,10 @@ static unsigned long bsqrt(unsigned long x) {
ImageControl *ctrl = 0;
-ImageControl::ImageControl(TimerQueueManager *timermanager,
- const ScreenInfo *scrn,
- bool _dither, int _cpc,
- unsigned long cache_timeout,
- unsigned long cmax) {
+ImageControl::ImageControl(const ScreenInfo *scrn,
+ bool _dither, int _cpc,
+ unsigned long cache_timeout,
+ unsigned long cmax) {
if (! ctrl) ctrl = this;
screeninfo = scrn;
@@ -53,13 +52,10 @@ ImageControl::ImageControl(TimerQueueManager *timermanager,
setColorsPerChannel(_cpc);
cache_max = cmax;
- if (cache_timeout) {
- timer = new Timer(timermanager, (TimeoutHandler)timeout, this);
- timer->setTimeout(cache_timeout);
- timer->start();
- } else {
+ if (cache_timeout)
+ timer = new Timer(cache_timeout, (Timer::TimeoutHandler)timeout, this);
+ else
timer = (Timer *) 0;
- }
colors = (XColor *) 0;
ncolors = 0;
@@ -350,10 +346,8 @@ ImageControl::~ImageControl(void) {
for (; it != end; ++it)
XFreePixmap(**display, it->pixmap);
}
- if (timer) {
- timer->stop();
+ if (timer)
delete timer;
- }
}
diff --git a/otk/otk.hh b/otk/otk.hh
index b06afcbf..23af8477 100644
--- a/otk/otk.hh
+++ b/otk/otk.hh
@@ -26,8 +26,6 @@
#include "style.hh"
#include "texture.hh"
#include "timer.hh"
-#include "timerqueue.hh"
-#include "timerqueuemanager.hh"
#include "util.hh"
#include "ustring.hh"
#include "widget.hh"
diff --git a/otk/otk.i b/otk/otk.i
index d0e4331d..bda7ce97 100644
--- a/otk/otk.i
+++ b/otk/otk.i
@@ -76,8 +76,6 @@ namespace otk {
%include "style.hh"
%include "texture.hh"
%include "timer.hh"
-%include "timerqueue.hh"
-%include "timerqueuemanager.hh"
%include "util.hh"
%include "widget.hh"
diff --git a/otk/timer.cc b/otk/timer.cc
index 3fe8c703..2d36c7a0 100644
--- a/otk/timer.cc
+++ b/otk/timer.cc
@@ -5,121 +5,127 @@
#endif // HAVE_CONFIG_H
#include "timer.hh"
-#include "timerqueuemanager.hh"
+#include "display.hh"
namespace otk {
-static timeval normalizeTimeval(const timeval &tm)
-{
- timeval ret = tm;
-
- while (ret.tv_usec < 0) {
- if (ret.tv_sec > 0) {
- --ret.tv_sec;
- ret.tv_usec += 1000000;
- } else {
- ret.tv_usec = 0;
- }
- }
-
- if (ret.tv_usec >= 1000000) {
- ret.tv_sec += ret.tv_usec / 1000000;
- ret.tv_usec %= 1000000;
- }
-
- if (ret.tv_sec < 0) ret.tv_sec = 0;
-
- return ret;
-}
-
+timeval Timer::_nearest_timeout, Timer::_now;
+Timer::TimerQ Timer::_q;
-Timer::Timer(TimerQueueManager *m, TimeoutHandler h, TimeoutData d)
+void Timer::timevalAdd(timeval &a, long msec)
{
- _manager = m;
- _handler = h;
- _data = d;
-
- _recur = _timing = false;
+ a.tv_sec += msec / 1000;
+ a.tv_usec += (msec % 1000) * 1000;
+ a.tv_sec += a.tv_usec / 1000000;
+ a.tv_usec %= 1000000;
}
-
-Timer::~Timer(void)
+bool Timer::nearestTimeout(struct timeval &tm)
{
- if (_timing) stop();
-}
-
+ if (_q.empty())
+ return false;
+ tm.tv_sec = _nearest_timeout.tv_sec - _now.tv_sec;
+ tm.tv_usec = _nearest_timeout.tv_usec - _now.tv_usec;
+
+ while (tm.tv_usec < 0) {
+ tm.tv_usec += 1000000;
+ tm.tv_sec--;
+ }
+ tm.tv_sec += tm.tv_usec / 1000000;
+ tm.tv_usec %= 1000000;
+ if (tm.tv_sec < 0)
+ tm.tv_sec = 0;
-void Timer::setTimeout(long t)
-{
- _timeout.tv_sec = t / 1000;
- _timeout.tv_usec = t % 1000;
- _timeout.tv_usec *= 1000;
+ return true;
}
-
-void Timer::setTimeout(const timeval &t)
+void Timer::dispatchTimers(bool wait)
{
- _timeout.tv_sec = t.tv_sec;
- _timeout.tv_usec = t.tv_usec;
-}
-
+ fd_set selset;
+ int fd;
+ timeval next;
+ Timer *curr;
+
+ gettimeofday(&_now, NULL);
+ _nearest_timeout = _now;
+ _nearest_timeout.tv_sec += 10000;
+
+ while (!_q.empty()) {
+ curr = _q.top();
+ /* since we overload the destructor to keep from removing from the middle of
+ the priority queue, set _del_me, we have to do our real delete in here.
+ */
+ if (curr->_del_me) {
+ _q.pop();
+ realDelete(curr);
+ continue;
+ }
-void Timer::start(void)
-{
- gettimeofday(&_start, 0);
+ // the queue is sorted, so if this timer shouldn't fire, none are ready
+ _nearest_timeout = curr->_timeout;
+ if (!timercmp(&_now, &_nearest_timeout, >))
+ break;
+
+ /* we set the last fired time to delay msec after the previous firing, then
+ re-insert. timers maintain their order and may trigger more than once if
+ they've waited more than one delay's worth of time.
+ */
+ _q.pop();
+ timevalAdd(curr->_last, curr->_delay);
+ curr->_action(curr->_data);
+ timevalAdd(curr->_timeout, curr->_delay);
+ _q.push(curr);
+ }
- if (! _timing) {
- _timing = true;
- _manager->addTimer(this);
+ if (wait) {
+ // wait for the nearest trigger, or for X to do something interesting
+ fd = ConnectionNumber(**display);
+ FD_ZERO(&selset);
+ FD_SET(fd, &selset);
+ if (nearestTimeout(next))
+ select(fd + 1, &selset, NULL, NULL, &next);
+ else
+ select(fd + 1, &selset, NULL, NULL, NULL);
}
}
-
-void Timer::stop(void)
+Timer::Timer(long delay, Timer::TimeoutHandler action, void *data)
+ : _delay(delay),
+ _action(action),
+ _data(data),
+ _del_me(false),
+ _last(_now),
+ _timeout(_now)
{
- if (_timing) {
- _timing = false;
-
- _manager->removeTimer(this);
- }
+ timevalAdd(_timeout, delay);
+ _q.push(this);
}
-
-void Timer::fire(void)
+void Timer::operator delete(void *self)
{
- if (_handler)
- _handler(_data);
+ Timer *t;
+ t = (Timer *)self;
+ t->_del_me = true;
}
-
-timeval Timer::remainingTime(const timeval &tm) const
+void Timer::realDelete(Timer *me)
{
- timeval ret = endTime();
-
- ret.tv_sec -= tm.tv_sec;
- ret.tv_usec -= tm.tv_usec;
-
- return normalizeTimeval(ret);
+ ::delete me;
}
-
-timeval Timer::endTime(void) const
+void Timer::initialize(void)
{
- timeval ret;
-
- ret.tv_sec = _start.tv_sec + _timeout.tv_sec;
- ret.tv_usec = _start.tv_usec + _timeout.tv_usec;
-
- return normalizeTimeval(ret);
+ gettimeofday(&_now, NULL);
+ _nearest_timeout.tv_sec = 100000;
+ _nearest_timeout.tv_usec = 0;
}
-
-bool Timer::shouldFire(const timeval &tm) const
+void Timer::destroy(void)
{
- timeval end = endTime();
-
- return ! ((tm.tv_sec < end.tv_sec) ||
- (tm.tv_sec == end.tv_sec && tm.tv_usec < end.tv_usec));
+ while(!_q.empty()) {
+ realDelete(_q.top());
+ _q.pop();
+ }
}
}
diff --git a/otk/timer.hh b/otk/timer.hh
index 7d3e726d..1d93f914 100644
--- a/otk/timer.hh
+++ b/otk/timer.hh
@@ -2,6 +2,10 @@
#ifndef __timer_hh
#define __timer_hh
+/*! @file timer.hh
+ @brief Contains the Timer class, used for timed callbacks.
+*/
+
extern "C" {
#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
@@ -13,120 +17,109 @@ extern "C" {
# include <time.h>
# endif // HAVE_SYS_TIME_H
#endif // TIME_WITH_SYS_TIME
+
+#ifdef HAVE_UNISTD_H
+# include <sys/types.h>
+# include <unistd.h>
+#endif // HAVE_UNISTD_H
}
-namespace otk {
+#include <queue>
+#include <vector>
-class TimerQueueManager;
+namespace otk {
-//! The data passed to the TimeoutHandler function.
+//! The Timer class implements timed callbacks.
/*!
- 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.
+ The Timer class can be used to have a callback fire after a given time
+ interval. A created Timer will fire repetitively until it is destroyed.
*/
-typedef void *TimeoutData;
-//! The type of function which can be set as the callback for a Timer firing
-typedef void (*TimeoutHandler)(TimeoutData);
-
-//! A Timer class which will fire a function when its time elapses
class Timer {
-private:
- //! The manager which to add ourself to and remove ourself after we are done
- TimerQueueManager *_manager;
- //! The function to call when the time elapses
- TimeoutHandler _handler;
- //! The data which gets passed along to the TimeoutHandler
- TimeoutData _data;
- //! Determines if the timer is currently started
- bool _timing;
- //! When this is true, the timer will reset itself to fire again every time
- bool _recur;
-
- //! The time at which the timer started
- timeval _start;
- //! The time at which the timer is going to fire
- timeval _timeout;
-
- //! Disallows copying of Timer objects
- Timer(const Timer&);
- //! Disallows copying of Timer objects
- Timer& operator=(const Timer&);
-
public:
- //! Constructs a new Timer object
- /*!
- @param m The TimerQueueManager with which to associate. The manager
- specified will be resposible for making this timer fire.
- @param h The function to call when the timer fires
- @param d The data to pass along to the function call when the timer fires
- */
- Timer(TimerQueueManager *m, TimeoutHandler h, TimeoutData d);
- //! Destroys the Timer object
- virtual ~Timer();
-
- //! Fires the timer, calling its TimeoutHandler
- void fire();
+ //! Data type of Timer callback
+ typedef void (*TimeoutHandler)(void *data);
- //! Returns if the Timer is started and timing
- inline bool timing() const { return _timing; }
- //! Returns if the Timer is going to repeat
- inline bool recurring() const { return _recur; }
-
- //! Gets the amount of time the Timer should last before firing
- inline const timeval &timeout() const { return _timeout; }
- //! Gets the time at which the Timer started
- inline const timeval &startTime() const { return _start; }
-
- //! Gets the amount of time left before the Timer fires
- timeval remainingTime(const timeval &tm) const;
- //! Returns if the Timer is past its timeout time, and should fire
- bool shouldFire(const timeval &tm) const;
-
- //! Gets the time at which the Timer will fire
- timeval endTime() const;
-
- //! Sets the Timer to repeat or not
+private:
+ //! Compares two timeval structs
+ struct TimerCompare {
+ //! Compares two timeval structs
+ inline bool operator()(const Timer *a, const Timer *b) const {
+ return timercmp(&a->_timeout, &b->_timeout, >);
+ }
+ };
+
+ typedef
+ std::priority_queue<Timer*, std::vector<Timer*>, TimerCompare> TimerQ;
+
+ //! Milliseconds between timer firings
+ long _delay;
+ //! Callback for timer expiry
+ TimeoutHandler _action;
+ //! Data sent to callback
+ void *_data;
+ //! We overload the delete operator to just set this to true
+ bool _del_me;
+ //! The time the last fire should've been at
+ struct timeval _last;
+ //! When this timer will next trigger
+ struct timeval _timeout;
+
+ //! Queue of pending timers
+ static TimerQ _q;
+ //! Time next timer will expire
+ static timeval _nearest_timeout;
+ //! Time at start of current processing loop
+ static timeval _now;
+
+ //! Really delete something (not just flag for later)
/*!
- @param b If true, the timer is set to repeat; otherwise, it will fire only
- once
+ @param self Timer to be deleted.
*/
- inline void setRecurring(bool b) { _recur = b; }
+ static void realDelete(Timer *self);
- //! Sets the amount of time for the Timer to last in milliseconds
+ //! Adds a millisecond delay to a timeval structure
/*!
- @param t The number of milliseconds the timer should last
+ @param a Amount of time to increment.
+ @param msec Number of milliseconds to increment by.
*/
- void setTimeout(long t);
- //! Sets the amount of time the Timer should last before firing
+ static void timevalAdd(timeval &a, long msec);
+
+public:
+ //! Constructs a new running timer and queues it
/*!
- @param t The amount of time the timer should last
+ @param delay Time in milliseconds between firings
+ @param cb The function to be called on fire.
+ @param data Data to be passed to the callback on fire.
*/
- void setTimeout(const timeval &t);
+ Timer(long delay, TimeoutHandler cb, void *data);
- //! Causes the timer to begin
+ //! Overloaded delete so we can leave deleted objects in queue for later reap
/*!
- The timer fires after the time in Timer::getTimeout has passed since this
- function was called.
- Calling this function while the timer is already started will cause it to
- restart its countdown.
+ @param self Pointer to current instance of Timer.
*/
- void start(); // manager acquires timer
- //! Causes the timer to stop
+ void operator delete(void *self);
+
+ //! Dispatches all elligible timers, then optionally waits for X events
/*!
- The timer will no longer fire once this function has been called.
- Calling this function more than once does not have any effect.
+ @param wait Whether to wait for X events after processing timers.
*/
- void stop(); // manager releases timer
+ static void dispatchTimers(bool wait = true);
- //! Determines if this Timer will fire before a second Timer object
+ //! Returns a relative timeval (to pass select) of the next timer
/*!
- @param other The second Timer with which to compare
- @return true if this Timer will fire before 'other'; otherwise, false
+ @param tm Changed to hold the time until next timer.
+ @return true if there are any timers queued, and the timeout is being
+ returned in 'tm'. false if there are no timers queued.
*/
- bool operator<(const Timer& other) const
- { return shouldFire(other.endTime()); }
+ static bool nearestTimeout(struct timeval &tm);
+
+ //! Initializes internal data before use
+ static void initialize(void);
+
+ //! Deletes all waiting timers
+ static void destroy(void);
};
}
-#endif // __timer_hh
+#endif // __timer.hh