diff options
author | Mathias Gumz <akira at fluxbox dot org> | 2013-01-15 20:40:33 (GMT) |
---|---|---|
committer | Mathias Gumz <akira at fluxbox dot org> | 2013-01-15 20:40:33 (GMT) |
commit | 33161595f482d0dad950ce127b6016eefe8ea691 (patch) | |
tree | 27fa5588b2ddd7410eb083d7bf0c8811d72f8270 | |
parent | 239e895826b2f843bc50cc6fef8108db174c33e8 (diff) | |
download | fluxbox_pavel-33161595f482d0dad950ce127b6016eefe8ea691.zip fluxbox_pavel-33161595f482d0dad950ce127b6016eefe8ea691.tar.bz2 |
Simplifies and fix bugs in FbTk::Timer
* Calling Timer::setTimeout() from within Timer::start() might lead to ugly
behavior (as experienced in bugs #3590078, #3600143, etc; see commit
4d307dcd10af9d817ff5c05fc40ae7487564cb31, fixes the problem partially).
* Stop a timer first, then call the handler (via Timer::fireTimeout()). A
given handler might call Timer::start() again, which (re)adds the Timer
to the control list .. the following Timer::stop() would remove it again.
* Use 'm_start' as indicator if timer is running.
* Move the (now quite short) code of ::addTimer / ::removeTimer
into the Timer::start() and Timer::stop() functions.
-rw-r--r-- | src/FbTk/Timer.cc | 72 | ||||
-rw-r--r-- | src/FbTk/Timer.hh | 5 |
2 files changed, 36 insertions, 41 deletions
diff --git a/src/FbTk/Timer.cc b/src/FbTk/Timer.cc index eff3af4..2404773 100644 --- a/src/FbTk/Timer.cc +++ b/src/FbTk/Timer.cc | |||
@@ -55,7 +55,6 @@ | |||
55 | #include <vector> | 55 | #include <vector> |
56 | #include <set> | 56 | #include <set> |
57 | 57 | ||
58 | |||
59 | namespace { | 58 | namespace { |
60 | 59 | ||
61 | struct TimerCompare { | 60 | struct TimerCompare { |
@@ -64,51 +63,30 @@ struct TimerCompare { | |||
64 | } | 63 | } |
65 | }; | 64 | }; |
66 | typedef std::set<FbTk::Timer*, TimerCompare> TimerList; | 65 | typedef std::set<FbTk::Timer*, TimerCompare> TimerList; |
67 | |||
68 | TimerList s_timerlist; | 66 | TimerList s_timerlist; |
69 | 67 | ||
70 | |||
71 | /// add a timer to the static list | ||
72 | void addTimer(FbTk::Timer *timer) { | ||
73 | |||
74 | assert(timer); | ||
75 | int interval = timer->getInterval(); | ||
76 | |||
77 | // interval timers have their timeout change every time they are started! | ||
78 | if (interval != 0) { | ||
79 | timer->setTimeout(interval * FbTk::FbTime::IN_SECONDS); | ||
80 | } | ||
81 | |||
82 | s_timerlist.insert(timer); | ||
83 | } | ||
84 | |||
85 | /// remove a timer from the static list | ||
86 | void removeTimer(FbTk::Timer *timer) { | ||
87 | |||
88 | assert(timer); | ||
89 | s_timerlist.erase(timer); | ||
90 | } | ||
91 | |||
92 | |||
93 | } | 68 | } |
94 | 69 | ||
95 | 70 | ||
96 | namespace FbTk { | 71 | namespace FbTk { |
97 | 72 | ||
98 | Timer::Timer():m_timing(false), m_once(false), m_interval(0) { | 73 | Timer::Timer() : |
74 | m_once(false), | ||
75 | m_interval(0), | ||
76 | m_start(0) { | ||
99 | 77 | ||
100 | } | 78 | } |
101 | 79 | ||
102 | Timer::Timer(const RefCount<Slot<void> > &handler): | 80 | Timer::Timer(const RefCount<Slot<void> > &handler): |
103 | m_handler(handler), | 81 | m_handler(handler), |
104 | m_timing(false), | ||
105 | m_once(false), | 82 | m_once(false), |
106 | m_interval(0) { | 83 | m_interval(0), |
84 | m_start(0) { | ||
107 | } | 85 | } |
108 | 86 | ||
109 | 87 | ||
110 | Timer::~Timer() { | 88 | Timer::~Timer() { |
111 | if (isTiming()) stop(); | 89 | stop(); |
112 | } | 90 | } |
113 | 91 | ||
114 | 92 | ||
@@ -131,19 +109,31 @@ void Timer::setCommand(const RefCount<Slot<void> > &cmd) { | |||
131 | 109 | ||
132 | void Timer::start() { | 110 | void Timer::start() { |
133 | 111 | ||
134 | m_start = FbTk::FbTime::now(); | ||
135 | |||
136 | // only add Timers that actually DO something | 112 | // only add Timers that actually DO something |
137 | if ((! m_timing || m_interval != 0) && m_handler) { | 113 | if ( ( ! isTiming() || m_interval > 0 ) && m_handler) { |
138 | m_timing = true; | 114 | |
139 | ::addTimer(this); | 115 | // in case start() gets triggered on a started |
116 | // timer with 'm_interval != 0' we have to remove | ||
117 | // it from s_timerlist before restarting it | ||
118 | stop(); | ||
119 | |||
120 | m_start = FbTk::FbTime::now(); | ||
121 | |||
122 | // interval timers have their timeout change every | ||
123 | // time they are started! | ||
124 | if (m_interval != 0) { | ||
125 | m_timeout = m_interval * FbTk::FbTime::IN_SECONDS; | ||
126 | } | ||
127 | s_timerlist.insert(this); | ||
140 | } | 128 | } |
141 | } | 129 | } |
142 | 130 | ||
143 | 131 | ||
144 | void Timer::stop() { | 132 | void Timer::stop() { |
145 | m_timing = false; | 133 | if (isTiming()) { |
146 | ::removeTimer(this); | 134 | s_timerlist.erase(this); |
135 | m_start = 0; | ||
136 | } | ||
147 | } | 137 | } |
148 | 138 | ||
149 | uint64_t Timer::getEndTime() const { | 139 | uint64_t Timer::getEndTime() const { |
@@ -216,10 +206,16 @@ void Timer::updateTimers(int fd) { | |||
216 | 206 | ||
217 | FbTk::Timer& t = *timeouts[i]; | 207 | FbTk::Timer& t = *timeouts[i]; |
218 | 208 | ||
219 | t.fireTimeout(); | 209 | // first we stop the timer to remove it |
210 | // from s_timerlist | ||
220 | t.stop(); | 211 | t.stop(); |
221 | 212 | ||
222 | if (! t.doOnce()) { // restart the current timer | 213 | // then we call the handler which might (re)start 't' |
214 | // on it's own | ||
215 | t.fireTimeout(); | ||
216 | |||
217 | // restart 't' if needed | ||
218 | if (!t.doOnce() && !t.isTiming()) { | ||
223 | t.start(); | 219 | t.start(); |
224 | } | 220 | } |
225 | } | 221 | } |
diff --git a/src/FbTk/Timer.hh b/src/FbTk/Timer.hh index bdaf3b8..2e82f2a 100644 --- a/src/FbTk/Timer.hh +++ b/src/FbTk/Timer.hh | |||
@@ -61,7 +61,7 @@ public: | |||
61 | 61 | ||
62 | static void updateTimers(int file_descriptor); | 62 | static void updateTimers(int file_descriptor); |
63 | 63 | ||
64 | int isTiming() const { return m_timing; } | 64 | int isTiming() const { return (m_start > 0); } |
65 | int getInterval() const { return m_interval; } | 65 | int getInterval() const { return m_interval; } |
66 | 66 | ||
67 | int doOnce() const { return m_once; } | 67 | int doOnce() const { return m_once; } |
@@ -77,11 +77,10 @@ protected: | |||
77 | private: | 77 | private: |
78 | RefCount<Slot<void> > m_handler; ///< what to do on a timeout | 78 | RefCount<Slot<void> > m_handler; ///< what to do on a timeout |
79 | 79 | ||
80 | bool m_timing; ///< clock running? | ||
81 | bool m_once; ///< do timeout only once? | 80 | bool m_once; ///< do timeout only once? |
82 | int m_interval; ///< Is an interval-only timer (e.g. clock), in seconds | 81 | int m_interval; ///< Is an interval-only timer (e.g. clock), in seconds |
83 | 82 | ||
84 | uint64_t m_start; ///< start time in microseconds | 83 | uint64_t m_start; ///< start time in microseconds, 0 if not running |
85 | uint64_t m_timeout; ///< time length in microseconds | 84 | uint64_t m_timeout; ///< time length in microseconds |
86 | }; | 85 | }; |
87 | 86 | ||