using System;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Threading;
namespace lib
{
public class MicroStopwatch : System.Diagnostics.Stopwatch
{
readonly double _microSecPerTick
= 1000000D / System.Diagnostics.Stopwatch.Frequency;
public MicroStopwatch()
{
if( !System.Diagnostics.Stopwatch.IsHighResolution )
{
throw new Exception( "On this system the high-resolution " +
"performance counter is not available" );
}
}
public long ElapsedMicroseconds
{
get
{
return (long)( ElapsedTicks * _microSecPerTick );
}
}
}
///
/// MicroTimer class
///
public class MicroTimer
{
public delegate void MicroTimerElapsedEventHandler(
object sender,
MicroTimerEventArgs timerEventArgs );
public event MicroTimerElapsedEventHandler MicroTimerElapsed;
System.Threading.Thread _threadTimer = null;
long _ignoreEventIfLateBy = long.MaxValue;
long _timerIntervalInMicroSec = 0;
bool _stopTimer = true;
public MicroTimer()
{
}
public MicroTimer( long timerIntervalInMicroseconds )
{
Interval = timerIntervalInMicroseconds;
}
public long Interval
{
get
{
return System.Threading.Interlocked.Read(
ref _timerIntervalInMicroSec );
}
set
{
System.Threading.Interlocked.Exchange(
ref _timerIntervalInMicroSec, value );
}
}
public long IgnoreEventIfLateBy
{
get
{
return System.Threading.Interlocked.Read(
ref _ignoreEventIfLateBy );
}
set
{
System.Threading.Interlocked.Exchange(
ref _ignoreEventIfLateBy, value <= 0 ? long.MaxValue : value );
}
}
public bool Enabled
{
set
{
if( value )
{
Start();
}
else
{
Stop();
}
}
get
{
return ( _threadTimer != null && _threadTimer.IsAlive );
}
}
public void Start()
{
if( Enabled || Interval <= 0 )
{
return;
}
_stopTimer = false;
System.Threading.ThreadStart threadStart = delegate()
{
NotificationTimer(ref _timerIntervalInMicroSec,
ref _ignoreEventIfLateBy,
ref _stopTimer);
};
_threadTimer = new System.Threading.Thread( threadStart );
_threadTimer.Priority = System.Threading.ThreadPriority.Highest;
_threadTimer.Start();
}
public void Stop()
{
_stopTimer = true;
if( _threadTimer != null && _threadTimer.ManagedThreadId ==
System.Threading.Thread.CurrentThread.ManagedThreadId )
{
return;
}
while( Enabled )
{
System.Threading.Thread.SpinWait( 10 );
}
}
void NotificationTimer( ref long timerIntervalInMicroSec,
ref long ignoreEventIfLateBy,
ref bool stopTimer )
{
int timerCount = 0;
long nextNotification = 0;
MicroStopwatch microStopwatch = new MicroStopwatch();
microStopwatch.Start();
while( !stopTimer )
{
long callbackFunctionExecutionTime =
microStopwatch.ElapsedMicroseconds - nextNotification;
long timerIntervalInMicroSecCurrent =
System.Threading.Interlocked.Read(ref timerIntervalInMicroSec);
long ignoreEventIfLateByCurrent =
System.Threading.Interlocked.Read(ref ignoreEventIfLateBy);
nextNotification += timerIntervalInMicroSecCurrent;
timerCount++;
long elapsedMicroseconds = 0;
while( ( elapsedMicroseconds = microStopwatch.ElapsedMicroseconds )
< nextNotification )
{
System.Threading.Thread.SpinWait( 10 );
}
long timerLateBy = elapsedMicroseconds - nextNotification;
if( timerLateBy >= ignoreEventIfLateByCurrent )
{
continue;
}
MicroTimerEventArgs microTimerEventArgs =
new MicroTimerEventArgs(timerCount,
elapsedMicroseconds,
timerLateBy,
callbackFunctionExecutionTime);
MicroTimerElapsed( this, microTimerEventArgs );
}
microStopwatch.Stop();
}
}
///
/// MicroTimer Event Argument class
///
public class MicroTimerEventArgs : EventArgs
{
// Simple counter, number times timed event (callback function) executed
public int TimerCount { get; private set; }
// Time when timed event was called since timer started
public long ElapsedMicroseconds { get; private set; }
// How late the timer was compared to when it should have been called
public long TimerLateBy { get; private set; }
// Time it took to execute previous call to callback function (OnTimedEvent)
public long CallbackFunctionExecutionTime { get; private set; }
public MicroTimerEventArgs( int timerCount,
long elapsedMicroseconds,
long timerLateBy,
long callbackFunctionExecutionTime )
{
TimerCount = timerCount;
ElapsedMicroseconds = elapsedMicroseconds;
TimerLateBy = timerLateBy;
CallbackFunctionExecutionTime = callbackFunctionExecutionTime;
}
}
public class Timer
{
MicroStopwatch m_watch;
private long startTime;
private long stopTime;
private long freq;
private long freq_millis;
public Timer()
{
m_watch = new MicroStopwatch();
//startTime = m_watch.ElapsedMicroseconds;
//stopTime = m_watch.ElapsedMicroseconds;
freq = 1000 * 1000;
freq_millis = freq / 1000;
Start();
}
// Start the timer
public Timer Start()
{
m_watch.Start();
startTime = m_watch.ElapsedMicroseconds;
stopTime = m_watch.ElapsedMicroseconds;
return this;
}
// Stop the timer
public Timer Stop()
{
m_watch.Stop();
stopTime = m_watch.ElapsedMicroseconds;
return this;
}
public double Seconds
{
get
{
long current = m_watch.ElapsedMicroseconds;
return (double)( current - startTime ) / freq;
}
}
public long Current
{
get
{
long current = m_watch.ElapsedMicroseconds;
return ( current - startTime ) / freq_millis;
}
}
public double Duration
{
get
{
return (double)( stopTime - startTime ) / (double)freq;
}
}
public long DurationMS
{
get { return ( stopTime - startTime ) / freq_millis; }
}
}
public class TimerWin
{
[DllImport( "Kernel32.dll" )]
private static extern bool QueryPerformanceCounter(
out long lpPerformanceCount );
[DllImport( "Kernel32.dll" )]
private static extern bool QueryPerformanceFrequency(
out long lpFrequency );
private long startTime;
private long stopTime;
private long freq;
private long freq_millis;
// Constructor
public TimerWin()
{
startTime = 0;
stopTime = 0;
if( QueryPerformanceFrequency( out freq ) == false )
{
// high-performance counter not supported
throw new Win32Exception();
}
freq_millis = freq / 1000;
}
// Start the timer
public void Start()
{
// lets do the waiting threads there work
//Thread.Sleep(0);
QueryPerformanceCounter( out startTime );
}
// Stop the timer
public void Stop()
{
QueryPerformanceCounter( out stopTime );
}
public double Seconds
{
get
{
long current;
QueryPerformanceCounter( out current );
return (double)( current - startTime ) / freq;
}
}
public long Current
{
get
{
long current;
QueryPerformanceCounter( out current );
return ( current - startTime ) / freq_millis;
}
}
public double Duration
{
get
{
return (double)( stopTime - startTime ) / (double)freq;
}
}
public long DurationMS
{
get { return ( stopTime - startTime ) / freq_millis; }
}
}
}