split the OBTimerQueueManager and TimerQueue into their own files
This commit is contained in:
parent
d4d89ce0bb
commit
b0a532db8a
6 changed files with 180 additions and 139 deletions
|
@ -5,7 +5,8 @@ INCLUDES= -I../src
|
||||||
noinst_LIBRARIES=libotk.a
|
noinst_LIBRARIES=libotk.a
|
||||||
|
|
||||||
libotk_a_SOURCES= color.cc display.cc font.cc gccache.cc image.cc \
|
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
|
MAINTAINERCLEANFILES= Makefile.in
|
||||||
|
|
||||||
|
|
67
otk/timer.cc
67
otk/timer.cc
|
@ -5,8 +5,7 @@
|
||||||
#endif // HAVE_CONFIG_H
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
#include "timer.hh"
|
#include "timer.hh"
|
||||||
#include "display.hh"
|
#include "timerqueuemanager.hh"
|
||||||
#include "util.hh"
|
|
||||||
|
|
||||||
namespace otk {
|
namespace otk {
|
||||||
|
|
||||||
|
@ -40,7 +39,7 @@ OBTimer::OBTimer(OBTimerQueueManager *m, OBTimeoutHandler h, OBTimeoutData d)
|
||||||
handler = h;
|
handler = h;
|
||||||
data = d;
|
data = d;
|
||||||
|
|
||||||
recur = timing = False;
|
recur = timing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -70,7 +69,7 @@ void OBTimer::start(void)
|
||||||
gettimeofday(&_start, 0);
|
gettimeofday(&_start, 0);
|
||||||
|
|
||||||
if (! timing) {
|
if (! timing) {
|
||||||
timing = True;
|
timing = true;
|
||||||
manager->addTimer(this);
|
manager->addTimer(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,7 +77,7 @@ void OBTimer::start(void)
|
||||||
|
|
||||||
void OBTimer::stop(void)
|
void OBTimer::stop(void)
|
||||||
{
|
{
|
||||||
timing = False;
|
timing = false;
|
||||||
|
|
||||||
manager->removeTimer(this);
|
manager->removeTimer(this);
|
||||||
}
|
}
|
||||||
|
@ -86,7 +85,7 @@ void OBTimer::stop(void)
|
||||||
|
|
||||||
void OBTimer::halt(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));
|
(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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
85
otk/timer.hh
85
otk/timer.hh
|
@ -1,6 +1,6 @@
|
||||||
// -*- mode: C++; indent-tabs-mode: nil; -*-
|
// -*- mode: C++; indent-tabs-mode: nil; -*-
|
||||||
#ifndef _BLACKBOX_Timer_hh
|
#ifndef __timer_hh
|
||||||
#define _BLACKBOX_Timer_hh
|
#define __timer_hh
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#ifdef TIME_WITH_SYS_TIME
|
#ifdef TIME_WITH_SYS_TIME
|
||||||
|
@ -15,16 +15,17 @@ extern "C" {
|
||||||
#endif // TIME_WITH_SYS_TIME
|
#endif // TIME_WITH_SYS_TIME
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <queue>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace otk {
|
namespace otk {
|
||||||
|
|
||||||
// forward declaration
|
|
||||||
class OBTimerQueueManager;
|
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;
|
typedef void *OBTimeoutData;
|
||||||
|
//! The type of function which can be set as the callback for an OBTimer firing
|
||||||
typedef void (*OBTimeoutHandler)(OBTimeoutData);
|
typedef void (*OBTimeoutHandler)(OBTimeoutData);
|
||||||
|
|
||||||
class OBTimer {
|
class OBTimer {
|
||||||
|
@ -68,74 +69,6 @@ public:
|
||||||
{ return shouldFire(other.endpoint()); }
|
{ return shouldFire(other.endpoint()); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <class _Tp, class _Sequence, class _Compare>
|
|
||||||
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<OBTimer*,
|
|
||||||
std::vector<OBTimer*>, 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
|
||||||
|
|
52
otk/timerqueue.hh
Normal file
52
otk/timerqueue.hh
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
// -*- mode: C++; indent-tabs-mode: nil; -*-
|
||||||
|
#ifndef __timerqueue_hh
|
||||||
|
#define __timerqueue_hh
|
||||||
|
|
||||||
|
#ifndef DOXYGEN_IGNORE
|
||||||
|
|
||||||
|
#include "timer.hh"
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace otk {
|
||||||
|
|
||||||
|
template <class _Tp, class _Sequence, class _Compare>
|
||||||
|
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<OBTimer*,
|
||||||
|
std::vector<OBTimer*>, TimerLessThan> TimerQueue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DOXYGEN_IGNORE
|
||||||
|
|
||||||
|
#endif // __timerqueue_hh
|
67
otk/timerqueuemanager.cc
Normal file
67
otk/timerqueuemanager.cc
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
45
otk/timerqueuemanager.hh
Normal file
45
otk/timerqueuemanager.hh
Normal file
|
@ -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
|
Loading…
Reference in a new issue