IBR-DTNSuite 0.6

ibrcommon/ibrcommon/thread/Timer.cpp

Go to the documentation of this file.
00001 /*
00002  * Timer.cpp
00003  *
00004  *  Created on: 29.09.2009
00005  *      Author: morgenro
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         bool Timer::__cancellation()
00040         {
00041                 {
00042                         MutexLock l(_state);
00043                         _state.setState(TIMER_STOPPED);
00044                         _state.abort();
00045                 }
00046                 join();
00047 
00048                 return true;
00049         }
00050 
00051         void Timer::set(size_t timeout)
00052         {
00053                 MutexLock l(_state);
00054                 _timeout = timeout * 1000;
00055                 _state.setState(TIMER_RESET);
00056         }
00057 
00058         void Timer::reset()
00059         {
00060                 MutexLock l(_state);
00061                 _state.setState(TIMER_RESET);
00062         }
00063 
00064         void Timer::run()
00065         {
00066                 MutexLock l(_state);
00067                 _state.setState(TIMER_RUNNING);
00068 
00069                 while (_state.ifState(TIMER_RUNNING))
00070                 {
00071                         try {
00072                                 _state.wait(_timeout);
00073 
00074                                 // got signal, check for reset request
00075                                 if (_state.ifState(TIMER_RESET))
00076                                 {
00077                                         _state.setState(TIMER_RUNNING);
00078                                 }
00079                                 else
00080                                 {
00081                                         // stop the timer
00082                                         _state.setState(TIMER_STOPPED);
00083                                 }
00084                         }
00085                         catch (const ibrcommon::Conditional::ConditionalAbortException &ex)
00086                         {
00087                                 switch (ex.reason)
00088                                 {
00089                                         case ibrcommon::Conditional::ConditionalAbortException::COND_TIMEOUT:
00090                                         {
00091                                                 // timeout exceeded, call callback method
00092                                                 if (_callback.timeout(this))
00093                                                 {
00094                                                         // reset the timer
00095                                                         _state.setState(TIMER_RUNNING);
00096                                                 }
00097                                                 else
00098                                                 {
00099                                                         // stop the timer
00100                                                         _state.setState(TIMER_STOPPED);
00101                                                 }
00102                                                 break;
00103                                         }
00104 
00105                                         case ibrcommon::Conditional::ConditionalAbortException::COND_ABORT:
00106                                         {
00107                                                 if (_state.ifState(TIMER_STOPPED)) return;
00108                                                 break;
00109                                         }
00110 
00111                                         case ibrcommon::Conditional::ConditionalAbortException::COND_ERROR:
00112                                                 break;
00113                                 }
00114                         }
00115 
00116                         yield();
00117                 }
00118         }
00119 
00120         SimpleTimer::SimpleTimer(SimpleTimerCallback &callback, size_t identifier)
00121          : _callback(callback), _identifier(identifier)
00122         {
00123         }
00124 
00125         SimpleTimer::~SimpleTimer()
00126         {
00127                 stop();
00128                 join();
00129         }
00130 
00131         void SimpleTimer::set(size_t timeout)
00132         {
00133                 ibrcommon::MutexLock l(_timercond);
00134                 _timeout = timeout * 1000;
00135         }
00136 
00137         bool SimpleTimer::__cancellation()
00138         {
00139                 {
00140                         ibrcommon::MutexLock l(_timercond);
00141                         _timercond.abort();
00142                 }
00143 
00144                 return true;
00145         }
00146 
00147         void SimpleTimer::remove()
00148         {
00149                 stop();
00150         }
00151 
00152         void SimpleTimer::run()
00153         {
00154                 ibrcommon::MutexLock l(_timercond);
00155 
00156                 // create
00157                 struct timespec ts;
00158                 ibrcommon::Conditional::gettimeout(_timeout, &ts);
00159 
00160                 while (true)
00161                 {
00162                         try {
00163                                 // wait for the timeout or abort signal
00164                                 _timercond.wait(&ts);
00165                         } catch (const ibrcommon::Conditional::ConditionalAbortException &ex) {
00166                                 switch (ex.reason)
00167                                 {
00168                                 case ibrcommon::Conditional::ConditionalAbortException::COND_TIMEOUT:
00169                                         // on timeout call the callback method
00170                                         _timeout = _callback.timeout(_identifier) * 1000;
00171 
00172                                         // set the new timeout value
00173                                         ibrcommon::Conditional::gettimeout(_timeout, &ts);
00174                                         break;
00175 
00176                                 case ibrcommon::Conditional::ConditionalAbortException::COND_ERROR:
00177                                 case ibrcommon::Conditional::ConditionalAbortException::COND_ABORT:
00178                                         return;
00179                                 }
00180                         }
00181 
00182                         yield();
00183                 }
00184         }
00185 }