OMK::Clock Class Reference

A clock to synchronize the time in simulation. More...

#include <OMKClock.h>

Inheritance diagram for OMK::Clock:

Inheritance graph
[legend]
Collaboration diagram for OMK::Clock:

Collaboration graph
[legend]
List of all members.

Public Member Functions

 DECLARE_OBJECT_FACTORY (Clock)
OpenMask inherited methods
virtual void init ()
 Init method inherited from SimulatedObject.
virtual void compute ()
 Compute method inherited from SimulatedObject.
virtual bool processEvent (Event *event)
 process an event for this object.
class methods
bool isSleepActive () const
 Get the clock active or passive sleep mode.
void setSleepActive (bool activeSleep)
 Set the clock active sleep mode.
bool isFreeRunning () const
 Get the clock in free run or controled mode.
void setFreeRunning (bool freeRun)
 Set the clock active sleep mode.
float getRealMultiplier () const
 Get the real clock ratio.
float getWantedMultiplier () const
 Get the wanted clock ratio.
void setWantedMultiplier (float m)
 Set the wanted clock ratio.

Protected Attributes

unsigned long _lastCallDate
 Last call date to compute in micro-secondes.
unsigned long _lastRealRefresh
 To regularly update simulated clock and ratio display.
unsigned long _firstRealDate
 Store the first date in secondes to calculate the elapsed real time Negative: time to catch up: time to spend.
long _timeToSpend
 Time during compute loop in micro-secondes.
unsigned long _simulFrequency
 Store frequency to avoid a call to object parameters.
float _wantedMult
 Wanted ratio between real time and simulated time.
float _realMult
 Real ratio between real time and simulated time. See Configuration parameters.
bool _freeRun
 Set to true if in free run mode.
bool _activeSleep
 The sleep mode.
bool _simulationStarted

Detailed Description

A clock to synchronize the time in simulation.

Author:
S�astien PARIS (& Beno� CHANCLOU ) (& Julien Bilavarn)
Date:
2005-05-31
Author:
Xavier Larrod�: base Clock on ExtensibleSimulatedObject for OMK 4.0
OpenMask version :
4.0
Module description :
This simulated object allows to constraint the simulation to a given speed ratio ("1" means real time is equal to simulated time, "2" means real time is equal to half of the simulated time, or the simulation runs twice faster than the real time).
The only thing to do is to add this simulated object to your simulation. The clock spend time to synchronize with the good ratio with the real time. You have to choose the frequency according to the object you want to control. Keep in mind that the clock waits each time its compute is called, so a too high frequency creates a performance issue.

Visualisable module :
no configurationParameters All the parameters have a default value (between parentheses), be careful with short keys. Example of configuration file
 clock
 {
   Class Clock
   Scheduling
   {
     Frequency 75
   }
   UserParams
   {
           FreeRun          FALSE
           SleepProcedure   ACTIVE
     InitCoeff        1.0
   }
 }

Definition at line 76 of file OMKClock.h.


Member Function Documentation

OMK::Clock::DECLARE_OBJECT_FACTORY ( Clock   ) 

void Clock::init (  )  [virtual]

Init method inherited from SimulatedObject.

Calls the loaders.
Most of the time it is not necessary to redefine this method in the children class. If you have to add some initialisations, redefine and call the inherited method to load parameters or call directly the loaders.

Reimplemented from OMK::ExtensibleSimulatedObject.

Definition at line 70 of file OMKClock.cpp.

References _activeSleep, _firstRealDate, _freeRun, _lastCallDate, _lastRealRefresh, _simulFrequency, _wantedMult, OMK::ParametersAccessor::get(), OMK::SimulatedObject::getConfigurationParameters(), OMK::ObjectDescriptor::getFrequency(), OMK::SimulatedObject::getObjectDescriptor(), OMK::ExtensibleSimulatedObject::init(), and setWantedMultiplier().

00071 {
00072   const ConfigurationParameterDescriptor* prm = getConfigurationParameters();
00073   
00074   std::string str;
00075   if( ParametersAccessor::get( prm, "SleepProcedure", str ) )
00076   {  
00077     std::transform( str.begin(), str.end(), str.begin(), toupper );
00078     _activeSleep = !( str == "PASSIVE" );
00079   }
00080 
00081   ParametersAccessor::get( prm, "FreeRun"     , _freeRun      );
00082   ParametersAccessor::get( prm, "InitCoeff"   , _wantedMult   );
00083   setWantedMultiplier( _wantedMult ) ;
00084 
00085 #ifdef _MSC_VER
00086   QueryPerformanceCounter( &_startSimulationDate ) ;
00087   _lastRealRefresh = _startSimulationDate ;
00088   _lastCallDate = _startSimulationDate ;
00089 #else
00090   timeval currentTime;
00091   gettimeofday( &currentTime, NULL );
00092   _firstRealDate = currentTime.tv_sec;
00093   // The filter is used to avoid numeric overflow
00094   _lastRealRefresh = _lastCallDate = ( currentTime.tv_sec & 0xfff ) * 1000000 + currentTime.tv_usec;
00095 #endif
00096 
00097   _simulFrequency = getObjectDescriptor().getFrequency();
00098   return ExtensibleSimulatedObject::init();
00099 }

void Clock::compute (  )  [virtual]

Compute method inherited from SimulatedObject.

The compute method is splitted in three main parts:

The second method computeParameters is a pure virtual method and must be defined in the child classes.
The inputs and outputs should work with associated data, you should use these associated data.

The extensions take place between each step :

So the extensions could modify the associated data, after they have been retrieved in the inputs, and before they have been copied in the outputs.

See Computing of simulated object for more details.

Reimplemented from OMK::ExtensibleSimulatedObject.

Definition at line 110 of file OMKClock.cpp.

References _activeSleep, _freeRun, _lastCallDate, _realMult, _simulationStarted, _simulFrequency, _timeToSpend, _wantedMult, and OMK::ExtensibleSimulatedObject::compute().

00111 {
00112         if(!_simulationStarted){
00113           _simulationStarted = true ;
00114 #ifdef _MSC_VER
00115           // current time in micro-sec
00116           LARGE_INTEGER firstDate ;
00117           QueryPerformanceCounter( &firstDate ) ;
00118           _startSimulationDate = firstDate ;
00119           _lastCallDate = firstDate ;
00120 #else
00121           timeval firstTime;
00122           gettimeofday( &firstTime, NULL );
00123           // current time in micro-sec
00124           _lastCallDate = ( firstTime.tv_sec & 0xfff ) * 1000000 + firstTime.tv_usec;
00125 #endif
00126         }
00127 
00128 #ifdef _MSC_VER
00129   // current time in micro-sec
00130   LARGE_INTEGER newCallDate ;
00131   QueryPerformanceCounter( &newCallDate ) ;
00132   LARGE_INTEGER currentDate = newCallDate ;
00133   // ratio of step duration by elapsed time since last call
00134   _realMult = (float)( ( 1/ _simulFrequency ) * (_processorFrequency.QuadPart / (newCallDate.QuadPart - _lastCallDate.QuadPart) ) ) ;
00135 #else
00136   timeval currentTime;
00137   gettimeofday( &currentTime, NULL );
00138   // current time in micro-sec
00139   unsigned long newCallDate = ( currentTime.tv_sec & 0xfff ) * 1000000 + currentTime.tv_usec;
00140   // ratio of step duration by elapsed time since last call
00141   _realMult = ( 1000000.0f / _simulFrequency ) / ( newCallDate - _lastCallDate );
00142 #endif
00143 
00144   if( _freeRun )
00145   {
00146     _timeToSpend = 0;
00147   }
00148   else
00149   {  
00150     // Controled time, sleep if necessary
00151     // step duration in micro-sec
00152     long stepDuration = (long)( 1000000.0f / ( _simulFrequency * _wantedMult ) );
00153     // sleep duration is the wanted step duration minus the time needed for simulation
00154     // negative: time to catch up, positive: time to spend
00155 #ifdef _MSC_VER
00156         _timeToSpend += (long)( stepDuration + ((_lastCallDate.QuadPart - newCallDate.QuadPart)*1000000/_processorFrequency.QuadPart) ) ;
00157 #else
00158     _timeToSpend += _lastCallDate - newCallDate + stepDuration ;
00159 #endif
00160     // never sleep more than step duration (to avoid numeric overflow on signed long)
00161     _timeToSpend = (stepDuration < _timeToSpend) ? stepDuration : _timeToSpend ;
00162     
00163     if( 0 < _timeToSpend )
00164     { 
00165       // Some time to spend
00166       if( _activeSleep )
00167       { 
00168         // Active sleep => loop
00169 #ifdef _MSC_VER
00170 
00171                 long currentStep = 0 ;
00172                 while( currentStep < _timeToSpend){
00173                         QueryPerformanceCounter( &currentDate ) ;
00174                         currentStep = (long)(( currentDate.QuadPart - newCallDate.QuadPart )*1000000/_processorFrequency.QuadPart); // Get step in micro-sec
00175 
00176                 }
00177 #else
00178         // Compute the date to reach with the dummy loop
00179         timeval targetDate;
00180         targetDate.tv_sec = currentTime.tv_sec ;
00181         targetDate.tv_usec = currentTime.tv_usec + _timeToSpend ;
00182         for( targetDate.tv_usec = currentTime.tv_usec + _timeToSpend ; 
00183              1000000l < targetDate.tv_usec ; 
00184              targetDate.tv_usec -= 1000000l )
00185         { // Add a seconde until targetDate.tv_usec is in range (< 10000000usec)
00186           targetDate.tv_sec++ ;
00187         }
00188 
00189         while( currentTime.tv_sec < targetDate.tv_sec
00190             || ( currentTime.tv_sec == targetDate.tv_sec
00191                && currentTime.tv_usec < targetDate.tv_usec ) )
00192         { // The dummy loop until date is reached
00193             gettimeofday( &currentTime, NULL );
00194         }
00195 #endif
00196 
00197       } 
00198       else
00199       { 
00200         // Passive sleep => nanosleep call
00201 #ifdef _MSC_VER
00202         // TODO / FIX Windows "Sleep" is not precise enough (~10ms), and current method is :
00203             // 1. First, make PASSIVE SLEEP as much as possible (milli-second granularity)
00204         Sleep(_timeToSpend/1000);
00205                 // 2. Then, spend the rest of time with active sleep
00206                 long currentStep = (long)(( currentDate.QuadPart - newCallDate.QuadPart )*1000000/_processorFrequency.QuadPart ) ; // Get step in micro-sec
00207                 while( currentStep < _timeToSpend){
00208                         QueryPerformanceCounter( &currentDate ) ;
00209                         currentStep = (long)( ( currentDate.QuadPart - newCallDate.QuadPart )*1000000/_processorFrequency.QuadPart ) ; // Get step in micro-sec
00210                 }
00211 #else
00212                 timespec sleepNanoTime;
00213         sleepNanoTime.tv_sec = 0;
00214         sleepNanoTime.tv_nsec = _timeToSpend * 1000l ;
00215         nanosleep( &sleepNanoTime, NULL );
00216 #endif
00217       }
00218     }
00219   }
00220   // store the call date for next call
00221   _lastCallDate = newCallDate;
00222 
00223   ExtensibleSimulatedObject::compute();
00224 }

bool Clock::processEvent ( Event event  )  [virtual]

process an event for this object.

the event will be automatically deleted if the return value of the call is true, otherwise deletion becomes the responsability of the object

Reimplemented from OMK::SimulatedObject.

Definition at line 103 of file OMKClock.cpp.

References OMK::SimulatedObject::processEvent().

00104 {
00105   return ExtensibleSimulatedObject::processEvent( event ) ;
00106 }

bool OMK::Clock::isSleepActive (  )  const [inline]

Get the clock active or passive sleep mode.

Returns:
true if the clock is in active sleep mode,
false if the clock is in passive sleep mode.

Definition at line 94 of file OMKClock.h.

00094 { return _activeSleep ; }

void OMK::Clock::setSleepActive ( bool  activeSleep  )  [inline]

Set the clock active sleep mode.

Parameters:
[in] activeSleep if true the clock is set in active sleep mode,
if false the clock is set in passive sleep mode.
This property can be set with SleepProcedure parameter. See Configuration parameters.

Definition at line 101 of file OMKClock.h.

00101 { _activeSleep = activeSleep ; }

bool OMK::Clock::isFreeRunning (  )  const [inline]

Get the clock in free run or controled mode.

Returns:
true if the clock is in free run mode,
false if the clock is in controled mode.

Definition at line 106 of file OMKClock.h.

00106 { return _freeRun; }

void OMK::Clock::setFreeRunning ( bool  freeRun  )  [inline]

Set the clock active sleep mode.

Parameters:
[in] freeRun if true the clock is set in free run mode,
if false the clock is set in controled mode.
This property can be set with FreeRun parameter. See Configuration parameters.

Definition at line 113 of file OMKClock.h.

00114   {  
00115     _freeRun = freeRun;
00116   }

float OMK::Clock::getRealMultiplier (  )  const [inline]

Get the real clock ratio.

Returns:
the real ratio between simulated time and real time.

Definition at line 120 of file OMKClock.h.

00120 { return _realMult; }

float OMK::Clock::getWantedMultiplier (  )  const [inline]

Get the wanted clock ratio.

Returns:
the wanted ratio between simulated time and real time.

Definition at line 124 of file OMKClock.h.

00124 { return _wantedMult; }

void OMK::Clock::setWantedMultiplier ( float  m  )  [inline]

Set the wanted clock ratio.

Parameters:
[in] m is the wanted ratio between simulated time and real time.
This property can be set with InitCoeff parameter. See Configuration parameters.

Definition at line 130 of file OMKClock.h.

Referenced by init().

00130 { if( 0 < m ) _wantedMult = m; }


Member Data Documentation

unsigned long OMK::Clock::_lastCallDate [protected]

Last call date to compute in micro-secondes.

Definition at line 140 of file OMKClock.h.

Referenced by compute(), and init().

unsigned long OMK::Clock::_lastRealRefresh [protected]

To regularly update simulated clock and ratio display.

Definition at line 141 of file OMKClock.h.

Referenced by init().

unsigned long OMK::Clock::_firstRealDate [protected]

Store the first date in secondes to calculate the elapsed real time Negative: time to catch up: time to spend.

Definition at line 143 of file OMKClock.h.

Referenced by init().

long OMK::Clock::_timeToSpend [protected]

Time during compute loop in micro-secondes.

Definition at line 145 of file OMKClock.h.

Referenced by compute().

unsigned long OMK::Clock::_simulFrequency [protected]

Store frequency to avoid a call to object parameters.

Definition at line 146 of file OMKClock.h.

Referenced by compute(), and init().

float OMK::Clock::_wantedMult [protected]

Wanted ratio between real time and simulated time.

This property can be set with InitCoeff parameter.

Definition at line 148 of file OMKClock.h.

Referenced by compute(), and init().

float OMK::Clock::_realMult [protected]

Real ratio between real time and simulated time. See Configuration parameters.

Definition at line 150 of file OMKClock.h.

Referenced by compute().

bool OMK::Clock::_freeRun [protected]

Set to true if in free run mode.

This property can be set with FreeRun parameter. See Configuration parameters.

Definition at line 152 of file OMKClock.h.

Referenced by compute(), and init().

bool OMK::Clock::_activeSleep [protected]

The sleep mode.

This property can be set with SleepProcedure parameter. See Configuration parameters.

Definition at line 155 of file OMKClock.h.

Referenced by compute(), and init().

bool OMK::Clock::_simulationStarted [protected]

Definition at line 158 of file OMKClock.h.

Referenced by compute().


logo OpenMask

Documentation generated on Mon Jun 9 11:46:02 2008

Generated with doxygen by Dimitri van Heesch ,   1997-2007