00001 #ifndef OSCL_TIMER_H_INCLUDED
00002 #define OSCL_TIMER_H_INCLUDED
00003
00004 #ifndef OSCL_BASE_H_INCLUDED
00005 #include "oscl_base.h"
00006 #endif
00007
00008 #ifndef OSCLCONFIG_UTIL_H_INCLUDED
00009 #include "osclconfig_util.h"
00010 #endif
00011
00012 #ifndef OSCL_VECTOR_H_INCLUDED
00013 #include "oscl_vector.h"
00014 #endif
00015
00016 #ifndef OSCL_TICKCOUNT_H_INCLUDED
00017 #include "oscl_tickcount.h"
00018 #endif
00019
00020 #ifndef OSCL_RAND_H_INCLUDED
00021 #include "oscl_rand.h"
00022 #endif
00023
00024 #ifndef OSCL_SCHEDULER_AO_H_INCLUDED
00025 #include "oscl_scheduler_ao.h"
00026 #endif
00027
00028
00032 class OsclTimerObserver
00033 {
00034 public:
00043 virtual void TimeoutOccurred(int32 timerID, int32 timeoutInfo) = 0;
00044
00045 virtual ~OsclTimerObserver() {}
00046 };
00047
00053 template<class Alloc>
00054 class OsclTimer ;
00055
00056 class CallbackTimerObserver
00057 {
00058 public:
00059 virtual void TimerBaseElapsed() = 0;
00060 virtual ~CallbackTimerObserver() {}
00061 };
00062
00063 template<class Alloc>
00064 class CallbackTimer: public OsclTimerObject
00065 {
00066 public:
00067 CallbackTimer(CallbackTimerObserver& aContainer, const char *name, int32 aPriority = OsclActiveObject::EPriorityNominal)
00068 : OsclTimerObject(aPriority, name)
00069 {
00070 iContainer = &aContainer;
00071 AddToScheduler();
00072 }
00073 ~CallbackTimer()
00074 {
00075 RemoveFromScheduler();
00076 }
00077 void Run()
00078 {
00079 if (Status() == OSCL_REQUEST_ERR_NONE)
00080 iContainer->TimerBaseElapsed();
00081 }
00082 private:
00083 CallbackTimerObserver *iContainer;
00084 };
00085
00086
00087 template<class Alloc>
00088 class OsclTimer : public CallbackTimerObserver
00089 {
00090 public:
00091
00092 typedef CallbackTimer<Alloc> callback_timer_type;
00093
00100 OsclTimer(const char *name, uint32 frequency = 1, int32 priority = OsclActiveObject::EPriorityNominal);
00101 virtual ~OsclTimer();
00102
00109 void SetObserver(OsclTimerObserver *obs)
00110 {
00111 iObserver = obs;
00112 }
00119 void SetFrequency(uint32 frequency);
00120
00127 void SetExactFrequency(uint32 frequency);
00128
00142 void Request(int32 timerID, int32 timeoutInfo, int32 cycles, OsclTimerObserver *obs = 0, bool recurring = 0);
00151 void Cancel(int32 timerID, int32 timeoutInfo = -1);
00155 void Clear();
00156
00157 private:
00158
00159
00160 callback_timer_type *iTimer;
00161
00162 typedef struct _TimerEntry
00163 {
00164 int32 iCounter ;
00165 int32 iTimerID ;
00166 int32 iParam ;
00167 OsclTimerObserver *iObserver;
00168 bool iRecurring;
00169 int32 iOrigCounter;
00170 } TimerEntry;
00171
00172 typedef TimerEntry entry_type;
00173 typedef Oscl_Vector<entry_type*, Alloc> entries_type;
00174 typedef typename entries_type::iterator entries_type_iterator;
00175
00176 OsclTimerObserver *iObserver;
00177 entries_type iEntries;
00178 entries_type iEntriesWaitingToAdd;
00179 entries_type iEntriesWaitingToCancel;
00180 Oscl_TAlloc<entry_type, Alloc> iEntryAllocator;
00181
00182 bool iInCallback;
00183
00184 uint32 iCyclePeriod;
00185 uint32 iTickCountPeriod;
00186 uint32 iExpectedTimeout;
00187
00188 protected:
00189 void TimerBaseElapsed();
00190 friend class CallbackTimer<Alloc>;
00191 };
00192
00193 template<class Alloc>
00194 OsclTimer<Alloc>::OsclTimer(const char *name, uint32 frequency, int32 priority) :
00195 iObserver(0)
00196 , iInCallback(false)
00197 , iTickCountPeriod(0)
00198 , iExpectedTimeout(0)
00199 {
00200 if (frequency == 0)
00201 {
00202 OSCL_LEAVE(OsclErrArgument);
00203 }
00204 else
00205 {
00206
00207 Alloc alloc;
00208 iTimer = OSCL_PLACEMENT_NEW(alloc.ALLOCATE(sizeof(CallbackTimer<Alloc>)), CallbackTimer<Alloc>(*this, name, priority));
00209 SetFrequency(frequency);
00210 }
00211 }
00212
00213 template<class Alloc>
00214 OsclTimer<Alloc>::~OsclTimer()
00215 {
00216
00217 if (iTimer)
00218 iTimer->Cancel();
00219 if (iTimer)
00220 {
00221 iTimer->OSCL_TEMPLATED_DESTRUCTOR_CALL(callback_timer_type, CallbackTimer);
00222 Alloc alloc;
00223 alloc.deallocate(iTimer);
00224 }
00225 iTimer = NULL;
00226
00227 for (entries_type_iterator it = iEntries.begin(); it != iEntries.end(); it++)
00228 {
00229 iEntryAllocator.deallocate(*it);
00230 }
00231 }
00232
00233 template<class Alloc>
00234 void OsclTimer<Alloc>::SetFrequency(uint32 frequency)
00235 {
00236
00237 iCyclePeriod = 1000000 / frequency;
00238
00239 iTickCountPeriod = OsclTickCount::TickCountPeriod();
00240 }
00241
00242 template<class Alloc>
00243 void OsclTimer<Alloc>::SetExactFrequency(uint32 frequency)
00244 {
00245
00246 iCyclePeriod = frequency;
00247
00248 iTickCountPeriod = OsclTickCount::TickCountPeriod();
00249 }
00250
00251
00252 template<class Alloc>
00253 void OsclTimer<Alloc>::Request(int32 timerID, int32 param, int32 cycles, OsclTimerObserver *obs, bool recurring)
00254 {
00255
00256
00257 entry_type *entry = iEntryAllocator.ALLOCATE(1);
00258 entry->iTimerID = timerID;
00259 entry->iParam = param;
00260 entry->iCounter = cycles;
00261 entry->iObserver = obs;
00262 entry->iRecurring = recurring;
00263 entry->iOrigCounter = entry->iCounter;
00264
00265
00266 if (iInCallback)
00267 {
00268 iEntriesWaitingToAdd.push_back(entry);
00269 return;
00270 }
00271
00272 iEntries.push_back(entry);
00273
00274 if (iTimer)
00275 {
00276 iTimer->RunIfNotReady(iCyclePeriod);
00277 }
00278
00279 if (iExpectedTimeout == 0)
00280 {
00281 iExpectedTimeout = (OsclTickCount::TickCount() * iTickCountPeriod) + iCyclePeriod;
00282 }
00283 }
00284
00285
00286 template<class Alloc>
00287 void OsclTimer<Alloc>::Cancel(int32 timerID, int32 param)
00288 {
00289
00290 if (iInCallback)
00291 {
00292
00293 entry_type *entry = iEntryAllocator.ALLOCATE(1);
00294 entry->iTimerID = timerID;
00295 entry->iParam = param;
00296
00297 iEntriesWaitingToCancel.push_back(entry);
00298 return;
00299 }
00300
00301
00302 for (entries_type_iterator it = iEntries.begin(); it != iEntries.end(); it++)
00303 {
00304 if ((*it)->iTimerID == timerID)
00305 {
00306
00307 if ((*it)->iParam == param || param == -1)
00308 {
00309 iEntryAllocator.deallocate(*it);
00310 iEntries.erase(it);
00311 return;
00312 }
00313 }
00314 }
00315 }
00316
00317
00318 template<class Alloc>
00319 void OsclTimer<Alloc>::Clear()
00320 {
00321 for (entries_type_iterator it = iEntries.begin(); it != iEntries.end(); it++)
00322 {
00323 iEntryAllocator.deallocate(*it);
00324 }
00325 iEntries.clear();
00326 }
00327
00328 template<class Alloc>
00329 void OsclTimer<Alloc>::TimerBaseElapsed()
00330 {
00331 uint8 expiredFound = 0;
00332
00333 {
00334
00335 for (entries_type_iterator it = iEntries.begin(); it != iEntries.end(); it++)
00336 {
00337 entry_type *entry = (*it);
00338 if (--(entry->iCounter) <= 0)
00339 {
00340 if (!entry->iRecurring) expiredFound = 1;
00341 if (entry->iRecurring) entry->iCounter = entry->iOrigCounter;
00342
00343
00344 OsclTimerObserver *obs = (entry->iObserver ? entry->iObserver : iObserver);
00345 if (obs)
00346 {
00347 iInCallback = true;
00348 obs->TimeoutOccurred(entry->iTimerID, entry->iParam);
00349 iInCallback = false;
00350 }
00351 }
00352 }
00353 }
00354
00355
00356 while (expiredFound)
00357 {
00358 expiredFound = 0;
00359 for (entries_type_iterator it = iEntries.begin(); it != iEntries.end(); it++)
00360 {
00361 entry_type *entry = (*it);
00362 if (entry->iCounter <= 0)
00363 {
00364 expiredFound = 1;
00365 iEntryAllocator.deallocate(entry);
00366 iEntries.erase(it);
00367 break;
00368 }
00369 }
00370 }
00371
00372 {
00373
00374 for (entries_type_iterator it = iEntriesWaitingToCancel.begin(); it != iEntriesWaitingToCancel.end(); it++)
00375 {
00376 entry_type *entry = (*it);
00377 Cancel(entry->iTimerID, entry->iParam);
00378 iEntryAllocator.deallocate(entry);
00379 }
00380 iEntriesWaitingToCancel.clear();
00381 }
00382
00383 {
00384
00385 for (entries_type_iterator it = iEntriesWaitingToAdd.begin(); it != iEntriesWaitingToAdd.end(); it++)
00386 {
00387 entry_type *entry = (*it);
00388 Request(entry->iTimerID, entry->iParam, entry->iCounter, entry->iObserver);
00389 iEntryAllocator.deallocate(entry);
00390 }
00391 iEntriesWaitingToAdd.clear();
00392 }
00393
00394 if (!iEntries.empty())
00395 {
00396
00397 uint32 time = OsclTickCount::TickCount() * iTickCountPeriod;
00398 int32 jitter = time - iExpectedTimeout;
00399 int32 waitperiod = iCyclePeriod - jitter;
00400
00401
00402
00403
00404 if ((uint)OSCL_ABS(jitter) > iCyclePeriod)
00405 {
00406 iExpectedTimeout = time;
00407 }
00408 else
00409 {
00410 iExpectedTimeout += iCyclePeriod;
00411 }
00412
00413 waitperiod = OSCL_MAX(waitperiod, 0);
00414
00415 if (iTimer)
00416 {
00417 iTimer->RunIfNotReady(waitperiod);
00418 }
00419 }
00420 else
00421 {
00422 iExpectedTimeout = 0;
00423 }
00424 }
00425
00426
00427
00428 #endif