Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "Timer.hpp"
00040 #include "MutexLock.hpp"
00041 #include "../Activity.hpp"
00042 #include "../Logger.hpp"
00043 #include "../os/fosi.h"
00044 #include <limits>
00045
00046 namespace RTT {
00047 using namespace base;
00048 using namespace os;
00049
00050 bool Timer::initialize() {
00051 mdo_quit = false;
00052
00053 return this->getThread()->getPeriod() == 0;
00054 }
00055 void Timer::finalize() {}
00056
00057 void Timer::step() {
00058
00059 }
00060
00061 void Timer::loop()
00062 {
00063
00064 while (!mdo_quit) {
00065 Time wake_up_time;
00066 TimerId next_timer_id = 0;
00067
00068
00069 {
00070
00071
00072 MutexLock locker(m);
00073
00074
00075 wake_up_time = 1000000000LL * std::numeric_limits<int32_t>::max();
00076 for (TimerIds::iterator it = mtimers.begin(); it != mtimers.end(); ++it) {
00077 if ( it->expires != 0 && it->expires < wake_up_time ) {
00078 wake_up_time = it->expires;
00079 next_timer_id = it - mtimers.begin();
00080 }
00081 }
00082 }
00083
00084
00085 int ret = 0;
00086 Time now = rtos_get_time_ns();
00087 if ( wake_up_time > now )
00088 ret = msem.waitUntil( wake_up_time );
00089 else
00090 ret = -1;
00091
00092
00093 if (ret == -1) {
00094
00095
00096 {
00097 MutexLock locker(m);
00098
00099 if ( next_timer_id < int(mtimers.size()) ) {
00100
00101 TimerIds::iterator tim = mtimers.begin() + next_timer_id;
00102 if ( tim->period ) {
00103
00104
00105 int maxDelayInPeriods = 4;
00106 if (now - tim->expires > tim->period*maxDelayInPeriods) {
00107 tim->expires += tim->period*((now - tim->expires) / tim->period);
00108 }
00109 tim->expires += tim->period;
00110 } else {
00111
00112 tim->expires = 0;
00113 }
00114 }
00115 }
00116
00117
00118 {
00119 MutexLock locker(m);
00120 mtimers[next_timer_id].expired.broadcast();
00121 }
00122
00123
00124
00125
00126
00127 timeout( next_timer_id );
00128 }
00129 }
00130 }
00131
00132 bool Timer::breakLoop()
00133 {
00134 mdo_quit = true;
00135 msem.signal();
00136
00137 for (TimerId i = 0; i < (int) mtimers.size(); ++i) {
00138 killTimer(i);
00139 }
00140 return true;
00141 }
00142
00143 Timer::Timer(TimerId max_timers, int scheduler, int priority)
00144 : mThread(0), msem(0), mdo_quit(false)
00145 {
00146 mtimers.resize(max_timers);
00147 if (scheduler != -1) {
00148 mThread = new Activity(scheduler, priority, 0.0, this, "Timer");
00149 mThread->start();
00150 }
00151 }
00152
00153 Timer::~Timer()
00154 {
00155 delete mThread;
00156 }
00157
00158
00159 void Timer::timeout(TimerId timer_id)
00160 {
00161
00162 }
00163
00164 void Timer::setMaxTimers(TimerId max)
00165 {
00166 MutexLock locker(m);
00167 mtimers.resize(max, TimerInfo() );
00168 }
00169
00170 bool Timer::startTimer(TimerId timer_id, double period)
00171 {
00172 if ( timer_id < 0 || timer_id >= int(mtimers.size()) || period < 0.0)
00173 {
00174 log(Error) << "Invalid timer id or period" << endlog();
00175 return false;
00176 }
00177
00178 Time due_time = rtos_get_time_ns() + Seconds_to_nsecs( period );
00179
00180 {
00181 MutexLock locker(m);
00182 mtimers[timer_id].expires = due_time;
00183 mtimers[timer_id].period = Seconds_to_nsecs( period );
00184 }
00185 msem.signal();
00186 return true;
00187 }
00188
00189 bool Timer::arm(TimerId timer_id, double wait_time)
00190 {
00191 if ( timer_id < 0 || timer_id >= int(mtimers.size()) || wait_time < 0.0)
00192 {
00193 log(Error) << "Invalid timer id or wait time" << endlog();
00194 return false;
00195 }
00196
00197 Time now = rtos_get_time_ns();
00198 Time due_time = now + Seconds_to_nsecs( wait_time );
00199
00200 {
00201 MutexLock locker(m);
00202 mtimers[timer_id].expires = due_time;
00203 mtimers[timer_id].period = 0;
00204 }
00205 msem.signal();
00206 return true;
00207 }
00208
00209 bool Timer::isArmed(TimerId timer_id) const
00210 {
00211 MutexLock locker(m);
00212 if (timer_id < 0 || timer_id >= int(mtimers.size()) )
00213 {
00214 log(Error) << "Invalid timer id" << endlog();
00215 return false;
00216 }
00217 return mtimers[timer_id].expires != 0;
00218 }
00219
00220 double Timer::timeRemaining(TimerId timer_id) const
00221 {
00222 MutexLock locker(m);
00223 if (timer_id < 0 || timer_id >= int(mtimers.size()) )
00224 {
00225 log(Error) << "Invalid timer id" << endlog();
00226 return 0.0;
00227 }
00228 Time now = rtos_get_time_ns();
00229 Time result = mtimers[timer_id].expires - now;
00230
00231 if ( result < 0 )
00232 return 0.0;
00233 return nsecs_to_Seconds( result );
00234 }
00235
00236 bool Timer::killTimer(TimerId timer_id)
00237 {
00238 MutexLock locker(m);
00239 if (timer_id < 0 || timer_id >= int(mtimers.size()) )
00240 {
00241 log(Error) << "Invalid timer id" << endlog();
00242 return false;
00243 }
00244 mtimers[timer_id].expires = 0;
00245 mtimers[timer_id].period = 0;
00246 mtimers[timer_id].expired.broadcast();
00247 return true;
00248 }
00249
00250 bool Timer::waitFor(TimerId timer_id)
00251 {
00252 MutexLock locker(m);
00253 if (timer_id < 0 || timer_id >= int(mtimers.size()) )
00254 {
00255 log(Error) << "Invalid timer id" << endlog();
00256 return false;
00257 }
00258 if (mtimers[timer_id].expires == 0) return false;
00259
00260 return mtimers[timer_id].expired.wait(m);
00261 }
00262
00263 bool Timer::waitForUntil(TimerId timer_id, nsecs abs_time)
00264 {
00265 MutexLock locker(m);
00266 if (timer_id < 0 || timer_id >= int(mtimers.size()) )
00267 {
00268 log(Error) << "Invalid timer id" << endlog();
00269 return false;
00270 }
00271 if (mtimers[timer_id].expires == 0) return false;
00272
00273 return mtimers[timer_id].expired.wait_until(m, abs_time);
00274 }
00275
00276
00277
00278 }