00001
00002
00003
00004
00005
00006
00007
00008 #include "ibrcommon/config.h"
00009 #include "ibrcommon/thread/Timer.h"
00010 #include "ibrcommon/thread/MutexLock.h"
00011
00012 #include <iostream>
00013 #include <queue>
00014 #include <utility>
00015 #include <sstream>
00016
00017 namespace ibrcommon
00018 {
00019 size_t Timer::get_current_time()
00020 {
00021 time_t rawtime = time(NULL);
00022 tm * ptm;
00023
00024 ptm = gmtime ( &rawtime );
00025
00026 return mktime(ptm);
00027 }
00028
00029 Timer::Timer(TimerCallback &callback, size_t timeout)
00030 : _state(TIMER_UNSET), _callback(callback), _timeout(timeout * 1000)
00031 {
00032 }
00033
00034 Timer::~Timer()
00035 {
00036 stop();
00037 }
00038
00039 void Timer::stop()
00040 {
00041 {
00042 MutexLock l(_state);
00043 _state.setState(TIMER_STOPPED);
00044 }
00045 join();
00046 }
00047
00048 void Timer::set(size_t timeout)
00049 {
00050 MutexLock l(_state);
00051 _timeout = timeout * 1000;
00052 _state.setState(TIMER_RESET);
00053 }
00054
00055 void Timer::reset()
00056 {
00057 MutexLock l(_state);
00058 _state.setState(TIMER_RESET);
00059 }
00060
00061 void Timer::run()
00062 {
00063 MutexLock l(_state);
00064 _state.setState(TIMER_RUNNING);
00065
00066 while (_state.ifState(TIMER_RUNNING))
00067 {
00068 if (_state.wait(_timeout))
00069 {
00070
00071 if (_state.ifState(TIMER_RESET))
00072 {
00073 _state.setState(TIMER_RUNNING);
00074 }
00075 else
00076 {
00077
00078 _state.setState(TIMER_STOPPED);
00079 }
00080 }
00081 else
00082 {
00083 if (_state.ifState(TIMER_STOPPED)) return;
00084
00085
00086 if (_callback.timeout(this))
00087 {
00088
00089 _state.setState(TIMER_RUNNING);
00090 }
00091 else
00092 {
00093
00094 _state.setState(TIMER_STOPPED);
00095 }
00096 }
00097 }
00098 }
00099
00100 SimpleTimer::SimpleTimer(SimpleTimerCallback &callback, size_t identifier)
00101 : _callback(callback), _identifier(identifier)
00102 {
00103 }
00104
00105 SimpleTimer::~SimpleTimer()
00106 {
00107 remove();
00108 }
00109
00110 void SimpleTimer::set(size_t timeout)
00111 {
00112 ibrcommon::MutexLock l(_timecond);
00113 _countdown = timeout;
00114 }
00115
00116 void SimpleTimer::remove()
00117 {
00118 {
00119 ibrcommon::MutexLock l(_timecond);
00120 _running = false;
00121 _timecond.signal(true);
00122 }
00123 join();
00124 }
00125
00126 void SimpleTimer::run()
00127 {
00128 ibrcommon::MutexLock l(_timecond);
00129 _running = true;
00130
00131 while (_running && _countdown > 0)
00132 {
00133 if (_timecond.wait(1000))
00134 {
00135
00136 _countdown = 0;
00137 _running = false;
00138 return;
00139 }
00140 else
00141 {
00142 _countdown--;
00143
00144 if (_countdown == 0)
00145 {
00146 _countdown = _callback.timeout(_identifier);
00147 }
00148 }
00149 }
00150
00151 }
00152
00153 MultiTimer::MultiTimer()
00154 : _running(true)
00155 {
00156 }
00157
00158 MultiTimer::~MultiTimer()
00159 {
00160 {
00161 ibrcommon::MutexLock l(_timecond);
00162 _running = false;
00163 _timecond.signal(true);
00164 }
00165 join();
00166 }
00167
00168 void MultiTimer::set(SimpleTimerCallback &callback, size_t identifier, size_t timeout)
00169 {
00170 size_t tt = Timer::get_current_time() + timeout;
00171 Eggtimer eggtimer(callback, identifier, tt);
00172
00173
00174
00175 ibrcommon::MutexLock l(_listlock);
00176
00177 for (std::multiset<Eggtimer>::iterator iter = _timers.begin(); iter != _timers.end(); iter++)
00178 {
00179 if ((*iter)._identifier == identifier)
00180 {
00181 if (&((*iter)._callback) == &callback)
00182 {
00183 _timers.erase(iter++);
00184 }
00185 }
00186 }
00187
00188 _timers.insert( eggtimer );
00189 }
00190
00191 void MultiTimer::remove(SimpleTimerCallback &callback, size_t identifier)
00192 {
00193
00194
00195
00196 ibrcommon::MutexLock l(_listlock);
00197
00198 for (std::multiset<Eggtimer>::iterator iter = _timers.begin(); iter != _timers.end(); iter++)
00199 {
00200 if ((*iter)._identifier == identifier)
00201 {
00202 if (&((*iter)._callback) == &callback)
00203 {
00204 _timers.erase(iter++);
00205 }
00206 }
00207 }
00208 }
00209
00210 void MultiTimer::removeAll()
00211 {
00212 {
00213 ibrcommon::MutexLock ll(_listlock);
00214 _timers.clear();
00215 }
00216
00217 {
00218 ibrcommon::MutexLock l(_timecond);
00219 _running = false;
00220 _timecond.signal();
00221 }
00222 join();
00223 }
00224
00225 void MultiTimer::run()
00226 {
00227 ibrcommon::MutexLock l(_timecond);
00228
00229 while (_running)
00230 {
00231 std::queue<Eggtimer> _timeouts;
00232
00233 if (_timecond.wait(100))
00234 {
00235
00236 _running = false;
00237 return;
00238 }
00239 else
00240 {
00241 ibrcommon::MutexLock l(_listlock);
00242 size_t current_time = Timer::get_current_time();
00243
00244
00245
00246
00247
00248
00249
00250
00251 for (std::multiset<Eggtimer>::const_iterator iter = _timers.begin(); iter != _timers.end(); iter++)
00252 {
00253 const Eggtimer &t = (*iter);
00254
00255 if (t < current_time)
00256 {
00257 _timeouts.push(t);
00258 _timers.erase(iter++);
00259 }
00260 else
00261 {
00262 break;
00263 }
00264 }
00265 }
00266
00267 while (!_timeouts.empty())
00268 {
00269 Eggtimer &t = _timeouts.front();
00270 size_t newvalue = t._callback.timeout(t._identifier);
00271 if (newvalue > 0)
00272 {
00273 set(t._callback, t._identifier, newvalue);
00274 }
00275 _timeouts.pop();
00276 }
00277 }
00278 }
00279
00280 MultiTimer::Eggtimer::Eggtimer(SimpleTimerCallback &callback, size_t identifier, size_t timeout)
00281 : _callback(callback), _timeout(timeout), _identifier(identifier)
00282 {
00283
00284 }
00285
00286 MultiTimer::Eggtimer::~Eggtimer()
00287 {
00288
00289 }
00290
00291 bool MultiTimer::Eggtimer::operator>(const size_t &obj) const
00292 {
00293 return (_timeout > obj);
00294 }
00295
00296 bool MultiTimer::Eggtimer::operator<(const size_t &obj) const
00297 {
00298 return (_timeout < obj);
00299 }
00300
00301 bool MultiTimer::Eggtimer::operator>(const MultiTimer::Eggtimer &obj) const
00302 {
00303 return (_timeout > obj._timeout);
00304 }
00305
00306 bool MultiTimer::Eggtimer::operator<(const MultiTimer::Eggtimer &obj) const
00307 {
00308 return (_timeout < obj._timeout);
00309 }
00310
00311 bool MultiTimer::Eggtimer::operator==(const MultiTimer::Eggtimer &obj) const
00312 {
00313 return (_timeout == obj._timeout);
00314 }
00315
00316 const std::string MultiTimer::Eggtimer::toString() const
00317 {
00318 std::stringstream ss;
00319 size_t current_time = Timer::get_current_time();
00320
00321 ss << "Eggtimer: " << (_timeout - current_time) << " seconds, identifier: " << _identifier;
00322
00323 return ss.str();
00324 }
00325 }