#include <timer.h>
Data Structures | |
struct | TimerEntry |
Public Types | |
typedef void(* | callback_t )(void *callbackparm) |
Public Member Functions | |
void | Handler (void) |
CTimer () | |
~CTimer () | |
int | Initialize (const int nTimers) |
int | Stop () |
int | GetTimer (callback_t callback) |
int | FreeTimer (const int TimerId) |
int | StartTimer (const int TimerId, struct timeval Interval, TimerType Type, void *Param) |
int | StopTimer (const int TimerId) |
struct timeval | CurrentTime () |
Private Types | |
enum | TimerStatus { TimerStatusFree = 0, TimerStatusInactive = 1, TimerStatusActive = 2 } |
Private Member Functions | |
void | TimerThread () |
void | InitTimerSignalAction (void) |
void | ProgramTimer (struct timeval Time) |
void | Remove (int TimerId) |
void | Insert (int TimerId) |
void | ProcessExpiredTimers () |
void | ReprogramTimer () |
Static Private Member Functions | |
static void * | Thread (void *param) |
Private Attributes | |
TimerEntry * | m_Table |
int | m_Free |
int | m_First |
int | m_nTimers |
struct timeval | m_StartTime |
bool | m_Initialized |
bool | m_StopThread |
CvsiMutex | m_Mutex |
CvsiThread | m_Thread |
Definition at line 40 of file timer.h.
typedef void(* CTimer::callback_t)(void *callbackparm) |
enum CTimer::TimerStatus [private] |
Definition at line 46 of file timer.h.
00047 { 00048 TimerStatusFree = 0, 00049 TimerStatusInactive = 1, 00050 TimerStatusActive = 2 00051 } TimerStatus;
CTimer::CTimer | ( | ) |
Definition at line 62 of file timer.cpp.
00063 { 00064 m_Table = NULL; 00065 m_Free = -1; 00066 m_First = -1; 00067 m_nTimers = 0; 00068 00069 m_StartTime.tv_sec = 0; 00070 m_StartTime.tv_usec = 0; 00071 00072 m_Initialized = false; 00073 m_StopThread = false; 00074 // m_Mutex does not need to be initialized 00075 // m_Thread does not need to be initialized 00076 }
CTimer::~CTimer | ( | ) |
struct timeval CTimer::CurrentTime | ( | ) | [read] |
Definition at line 463 of file timer.cpp.
00464 { 00465 struct timeval val, current_time; 00466 00467 gettimeofday( &val, 0 ); 00468 00469 current_time.tv_sec = val.tv_sec - m_StartTime.tv_sec; 00470 current_time.tv_usec = val.tv_usec - m_StartTime.tv_usec; 00471 if( current_time.tv_usec < 0 ) 00472 { 00473 current_time.tv_sec -= 1; 00474 current_time.tv_usec += 1000000; 00475 } 00476 00477 return ( current_time ); 00478 }
int CTimer::FreeTimer | ( | const int | TimerId | ) |
Definition at line 236 of file timer.cpp.
00237 { 00238 00239 // Get exclusive access to timer control structures 00240 m_Mutex.Wait(); 00241 00242 // Check if initialized 00243 if( !m_Initialized ) 00244 { 00245 m_Mutex.Release(); 00246 return ERROR5; 00247 } 00248 00249 // Check if Timer Id is valid 00250 if( ( TimerId < 0 ) || ( TimerId >= m_nTimers ) ) 00251 { 00252 m_Mutex.Release(); 00253 return ERROR7; 00254 } 00255 00256 // Check if the Timer is not already free 00257 if( m_Table[TimerId].Status == TimerStatusFree ) 00258 { 00259 m_Mutex.Release(); 00260 return ERROR8; 00261 } 00262 00263 // Remove timer from list of active timers if needed 00264 if( m_Table[TimerId].Status == TimerStatusActive ) 00265 { 00266 Remove( TimerId ); 00267 } 00268 00269 // update timer status 00270 m_Table[TimerId].Status = TimerStatusFree; 00271 00272 // Include timer on free list 00273 m_Table[TimerId].Previous = -1; 00274 m_Table[TimerId].Next = m_Free; 00275 if( m_Free >= 0 ) 00276 { 00277 m_Table[m_Free].Previous = TimerId; 00278 } 00279 m_Free = TimerId; 00280 00281 // release access to timer control structures 00282 m_Mutex.Release(); 00283 00284 return 0; 00285 }
int CTimer::GetTimer | ( | callback_t | callback | ) |
Definition at line 197 of file timer.cpp.
00198 { 00199 int Id; 00200 00201 // Get exclusive access to timer control structures 00202 m_Mutex.Wait(); 00203 00204 // Check if initialized 00205 if( !m_Initialized ) 00206 { 00207 m_Mutex.Release(); 00208 return ERROR5; 00209 } 00210 00211 if( m_Free == -1 ) 00212 { 00213 m_Mutex.Release(); 00214 return ERROR6; 00215 } 00216 00217 Id = m_Free; 00218 00219 m_Free = m_Table[Id].Next; 00220 00221 if( m_Free >= 0 ) 00222 { 00223 m_Table[m_Free].Previous = -1; 00224 } 00225 00226 m_Table[Id].Status = TimerStatusInactive; 00227 m_Table[Id].Callback = callback; 00228 00229 // release access to timer control structures 00230 m_Mutex.Release(); 00231 00232 return Id; 00233 }
void CTimer::Handler | ( | void | ) |
int CTimer::Initialize | ( | const int | nTimers | ) |
Definition at line 88 of file timer.cpp.
00089 { 00090 00091 // Check if parameter is valid 00092 if( nTimers < 1 ) 00093 return (ERROR3); 00094 00095 // Check if mutex was opened successfully 00096 if( !m_Mutex.IsOpen() ) 00097 return (ERROR1); 00098 00099 // Check if semaphore was opened successfully 00100 if( !m_Mutex.IsOpen() ) 00101 return (ERROR9); 00102 00103 // Get exclusive access to timer control structures 00104 m_Mutex.Wait(); 00105 00106 if( m_First >= 0 ) 00107 { 00108 m_Mutex.Release(); 00109 return (ERROR2); 00110 } 00111 00112 if( m_Thread.IsActive() ) 00113 { 00114 m_StopThread = true; 00115 Semaphore.V(); 00116 m_Mutex.Release(); 00117 m_Thread.Join(0); 00118 m_Mutex.Wait(); 00119 } 00120 00121 if( m_Table != 0 ) 00122 { 00123 delete[] m_Table; 00124 m_Table = 0; 00125 } 00126 00127 m_nTimers = nTimers; 00128 m_Table = new TimerEntry[nTimers]; 00129 00130 for( int i = 0; i < nTimers; i++ ) 00131 { 00132 m_Table[i].Next = i+1; 00133 m_Table[i].Previous = i-1; 00134 m_Table[i].Status = TimerStatusFree; 00135 } 00136 00137 m_Table[nTimers-1].Next = -1; 00138 m_Free = 0; 00139 00140 int result = 0; 00141 if( m_Thread.Create( Thread, (void*)this ) < 0 ) 00142 result = ERROR4; 00143 00144 // Initialize zero reference time 00145 gettimeofday( &m_StartTime, 0 ); 00146 00147 m_Initialized = true; 00148 00149 // release access to timer control structures 00150 m_Mutex.Release(); 00151 00152 return result; 00153 }
void CTimer::InitTimerSignalAction | ( | void | ) | [private] |
Definition at line 481 of file timer.cpp.
00482 { 00483 struct sigaction action; 00484 action.sa_handler = TimerSignalHandler; 00485 action.sa_flags = SA_RESTART; 00486 sigemptyset( &action.sa_mask ); 00487 sigaction( SIGALRM, &action, NULL ); 00488 }
void CTimer::Insert | ( | int | TimerId | ) | [private] |
Definition at line 420 of file timer.cpp.
00421 { 00422 int Next = m_First; 00423 int Previous = -1; 00424 00425 struct timeval Time = m_Table[TimerId].Time; 00426 00427 // Find right place to insert new Timer. Timers are ordered in 00428 // decreasing order of time; i.e. the first in the list will 00429 // be the first to expire 00430 while( Next >= 0 ) 00431 { 00432 if( ( m_Table[Next].Time.tv_sec > Time.tv_sec ) || 00433 (( m_Table[Next].Time.tv_sec == Time.tv_sec ) && 00434 ( m_Table[Next].Time.tv_usec > Time.tv_usec ))) 00435 break; 00436 Previous = Next; 00437 Next = m_Table[Next].Next; 00438 } 00439 00440 // Update new timer links 00441 m_Table[TimerId].Next = Next; 00442 m_Table[TimerId].Previous = Previous; 00443 00444 // Update previous and next timers links 00445 if( Previous >= 0 ) 00446 { 00447 m_Table[Previous].Next = TimerId; 00448 } 00449 else 00450 { 00451 m_First = TimerId; 00452 } 00453 if( Next >= 0 ) 00454 { 00455 m_Table[Next].Previous = TimerId; 00456 } 00457 00458 m_Table[TimerId].Status = TimerStatusActive; 00459 return; 00460 }
void CTimer::ProcessExpiredTimers | ( | ) | [private] |
Definition at line 571 of file timer.cpp.
00572 { 00573 int Current = m_First; 00574 int Next; 00575 00576 struct timeval current_time, time; 00577 00578 Current = m_First; 00579 while( Current >= 0 ) 00580 { 00581 Next = m_Table[Current].Next; 00582 00583 time.tv_sec = m_Table[Current].Time.tv_sec; 00584 time.tv_usec = m_Table[Current].Time.tv_usec; 00585 00586 time.tv_usec -= TIMER_PRECISION; 00587 if( time.tv_usec < 0 ) 00588 { 00589 time.tv_sec -= 1; 00590 time.tv_usec += 1000000; 00591 } 00592 00593 current_time = CurrentTime(); 00594 00595 if( ( current_time.tv_sec > time.tv_sec) || 00596 (( current_time.tv_sec == time.tv_sec ) && 00597 ( current_time.tv_usec > time.tv_usec ))) 00598 { 00599 Remove( Current ); 00600 // Release mutex while excuting caller's callback function 00601 m_Mutex.Release(); 00602 (m_Table[Current].Callback)(m_Table[Current].Param); 00603 m_Mutex.Wait(); 00604 if( m_Table[Current].Type == TimerTypePeriodic ) 00605 { 00606 m_Table[Current].Time.tv_sec += m_Table[Current].Interval.tv_sec; 00607 m_Table[Current].Time.tv_usec += m_Table[Current].Interval.tv_usec; 00608 if( m_Table[Current].Time.tv_usec > 1000000 ) 00609 { 00610 m_Table[Current].Time.tv_sec += 1; 00611 m_Table[Current].Time.tv_usec -= 1000000; 00612 } 00613 Insert( Current ); 00614 } 00615 } 00616 else 00617 { 00618 return; 00619 } 00620 Current = Next; 00621 } 00622 }
void CTimer::ProgramTimer | ( | struct timeval | Time | ) | [private] |
Definition at line 491 of file timer.cpp.
00492 { 00493 struct itimerval TimerValue; 00494 struct timeval current_time, timer; 00495 00496 TimerValue.it_interval.tv_sec = 0; 00497 TimerValue.it_interval.tv_usec = 0; 00498 00499 current_time = CurrentTime(); 00500 00501 timer.tv_sec = Time.tv_sec - current_time.tv_sec; 00502 timer.tv_usec = Time.tv_usec - current_time.tv_usec; 00503 if( timer.tv_usec < 0 ) 00504 { 00505 timer.tv_sec -= 1; 00506 timer.tv_usec += 1000000; 00507 } 00508 00509 if( ( timer.tv_sec < 0 ) || (( timer.tv_sec == 0 )&&( timer.tv_usec <= 0 )) ) 00510 { 00511 timer.tv_sec = 0; 00512 timer.tv_usec = 1; 00513 } 00514 00515 if( ( timer.tv_sec == 0 ) && ( timer.tv_usec < 1000000 ) ) 00516 { 00517 TimerValue.it_value.tv_sec = 0; 00518 TimerValue.it_value.tv_usec = timer.tv_usec; 00519 } 00520 else 00521 { 00522 TimerValue.it_value.tv_sec = timer.tv_sec; 00523 TimerValue.it_value.tv_usec = timer.tv_usec; 00524 00525 } 00526 setitimer( ITIMER_REAL, &TimerValue, NULL ); 00527 }
void CTimer::Remove | ( | int | TimerId | ) | [private] |
Definition at line 394 of file timer.cpp.
00395 { 00396 int Next = m_Table[TimerId].Next; 00397 int Previous = m_Table[TimerId].Previous; 00398 00399 if( Next >= 0 ) 00400 { 00401 m_Table[Next].Previous = Previous; 00402 } 00403 00404 if( Previous >= 0 ) 00405 { 00406 m_Table[Previous].Next = Next; 00407 } 00408 else 00409 { 00410 m_First = Next; 00411 } 00412 00413 m_Table[TimerId].Status = TimerStatusInactive; 00414 return; 00415 }
void CTimer::ReprogramTimer | ( | ) | [private] |
int CTimer::StartTimer | ( | const int | TimerId, | |
struct timeval | Interval, | |||
TimerType | Type, | |||
void * | Param | |||
) |
Definition at line 288 of file timer.cpp.
00290 { 00291 // Get exclusive access to timer control structures 00292 m_Mutex.Wait(); 00293 00294 // Check if initialized 00295 if( !m_Initialized ) 00296 { 00297 m_Mutex.Release(); 00298 return ERROR5; 00299 } 00300 00301 // Check if Timer Id is valid 00302 if( ( TimerId < 0 ) || ( TimerId >= m_nTimers ) ) 00303 { 00304 m_Mutex.Release(); 00305 return ERROR7; 00306 } 00307 00308 // Check if the Timer is not free 00309 if( m_Table[TimerId].Status == TimerStatusFree ) 00310 { 00311 m_Mutex.Release(); 00312 return ERROR8; 00313 } 00314 00315 // Remove timer from list of active timers if needed 00316 if( m_Table[TimerId].Status == TimerStatusActive ) 00317 { 00318 Remove(TimerId); 00319 } 00320 00321 // Update timer entry 00322 m_Table[TimerId].Interval = Interval; 00323 m_Table[TimerId].Type = Type; 00324 00325 struct timeval initial_time, current_time; 00326 current_time = CurrentTime(); 00327 initial_time.tv_sec = current_time.tv_sec + Interval.tv_sec; 00328 initial_time.tv_usec = current_time.tv_usec + Interval.tv_usec; 00329 if( initial_time.tv_usec > 1000000 ) 00330 { 00331 initial_time.tv_sec += 1; 00332 initial_time.tv_usec -= 1000000; 00333 } 00334 m_Table[TimerId].Time = initial_time; 00335 // ------------------------------------------------------------------------ 00336 00337 m_Table[TimerId].Param = Param; 00338 00339 Insert( TimerId ); 00340 00341 // If new timer is the first to expire may have to change 00342 // Unix Timer programming. Signal timer process to 00343 // reprogram UNIX timer to right value 00344 if( m_First == TimerId ) 00345 { 00346 ReprogramTimer(); 00347 } 00348 // release access to timer control structures 00349 m_Mutex.Release(); 00350 return 0; 00351 }
int CTimer::Stop | ( | void | ) |
Definition at line 156 of file timer.cpp.
00157 { 00158 // Get exclusive access to timer control structures 00159 m_Mutex.Wait(); 00160 00161 // Check if initialized 00162 if( !m_Initialized ) 00163 { 00164 m_Mutex.Release(); 00165 return ERROR5; 00166 } 00167 00168 // Abort thread 00169 m_StopThread = true; 00170 Semaphore.V(); 00171 m_Mutex.Release(); 00172 m_Thread.Join(0); 00173 00174 // Clean Table 00175 m_Mutex.Wait(); 00176 if( m_Table != 0 ) 00177 { 00178 delete[] m_Table; 00179 m_Table = 0; 00180 } 00181 00182 // Reset member variables 00183 m_Free = -1; 00184 m_First = -1; 00185 m_nTimers = 0; 00186 m_Initialized = false; 00187 m_StopThread = false; 00188 00189 // release access to timer control structures 00190 m_Mutex.Release(); 00191 00192 return 0; 00193 00194 }
int CTimer::StopTimer | ( | const int | TimerId | ) |
Definition at line 354 of file timer.cpp.
00355 { 00356 // Get exclusive access to timer control structures 00357 m_Mutex.Wait(); 00358 00359 // Check if initialized 00360 if( !m_Initialized ) 00361 { 00362 m_Mutex.Release(); 00363 return ERROR5; 00364 } 00365 00366 // Check if Timer Id is valid 00367 if( ( TimerId < 0 ) || ( TimerId >= m_nTimers ) ) 00368 { 00369 m_Mutex.Release(); 00370 return ERROR7; 00371 } 00372 00373 // Check if the Timer is not free 00374 if( m_Table[TimerId].Status == TimerStatusFree ) 00375 { 00376 m_Mutex.Release(); 00377 return ERROR8; 00378 } 00379 00380 // Remove timer from list of active timers if in fact active 00381 if( m_Table[TimerId].Status == TimerStatusActive ) 00382 { 00383 Remove( TimerId ); 00384 } 00385 00386 // release access to timer control structures 00387 m_Mutex.Release(); 00388 00389 return 0; 00390 }
void * CTimer::Thread | ( | void * | param | ) | [static, private] |
void CTimer::TimerThread | ( | ) | [private] |
Definition at line 539 of file timer.cpp.
00540 { 00541 00542 RioErr << "TIMERTHREADID " << syscall( SYS_gettid ) << endl; 00543 00544 InitTimerSignalAction(); 00545 while( 1 ) 00546 { 00547 // Check if thread should exit 00548 if( m_StopThread ) 00549 { 00550 return; 00551 } 00552 00553 // Wait for Unix Timer to expire 00554 Semaphore.P(); 00555 // Check if thread should exit 00556 if( m_StopThread ) 00557 { 00558 return; 00559 } 00560 00561 m_Mutex.Wait(); 00562 00563 ProcessExpiredTimers(); 00564 ReprogramTimer(); 00565 00566 m_Mutex.Release(); 00567 } 00568 }
int CTimer::m_First [private] |
int CTimer::m_Free [private] |
bool CTimer::m_Initialized [private] |
CvsiMutex CTimer::m_Mutex [private] |
int CTimer::m_nTimers [private] |
struct timeval CTimer::m_StartTime [private] |
bool CTimer::m_StopThread [private] |
TimerEntry* CTimer::m_Table [private] |
CvsiThread CTimer::m_Thread [private] |