CTimer Class Reference

#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

TimerEntrym_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

Detailed Description

Definition at line 40 of file timer.h.


Member Typedef Documentation

typedef void(* CTimer::callback_t)(void *callbackparm)

Definition at line 43 of file timer.h.


Member Enumeration Documentation

enum CTimer::TimerStatus [private]
Enumerator:
TimerStatusFree 
TimerStatusInactive 
TimerStatusActive 

Definition at line 46 of file timer.h.

00047         {
00048             TimerStatusFree     = 0,
00049             TimerStatusInactive = 1,
00050             TimerStatusActive   = 2
00051         } TimerStatus;


Constructor & Destructor Documentation

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 (  ) 

Definition at line 78 of file timer.cpp.

00079 {
00080     if( m_Table != 0 )
00081     {
00082         delete[] m_Table;
00083         m_Table = 0;
00084     }
00085 }


Member Function Documentation

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]

Definition at line 625 of file timer.cpp.

00626 {
00627     if( m_First >= 0 )
00628         ProgramTimer( m_Table[m_First].Time );
00629 }

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]

Definition at line 531 of file timer.cpp.

00532 {
00533     CTimer* Timer= (CTimer*) param;
00534     Timer->TimerThread();
00535     return 0;
00536 }

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 }


Field Documentation

int CTimer::m_First [private]

Definition at line 66 of file timer.h.

int CTimer::m_Free [private]

Definition at line 65 of file timer.h.

bool CTimer::m_Initialized [private]

Definition at line 71 of file timer.h.

Definition at line 74 of file timer.h.

int CTimer::m_nTimers [private]

Definition at line 67 of file timer.h.

struct timeval CTimer::m_StartTime [private]

Definition at line 69 of file timer.h.

bool CTimer::m_StopThread [private]

Definition at line 72 of file timer.h.

Definition at line 64 of file timer.h.

Definition at line 75 of file timer.h.


The documentation for this class was generated from the following files:
Generated on Wed Jul 4 16:03:34 2012 for RIO by  doxygen 1.6.3