|
|
#ifndef _TTIMER_HXX_
#define _TTIMER_HXX_
template < class TEnum > TEnum operator ++ ( TEnum &sub_phase, int ) { TEnum old = sub_phase; sub_phase = static_cast<TEnum>( static_cast<int>(sub_phase) + 1 ); return( old ); }
class CTimerTest : public PTimerCallback {
public:
CTimerTest() { _fInitialized = FALSE; _cftExpected = 0; _hEvent = NULL; _ptszName = NULL; }
virtual ~CTimerTest() { UnInitialize(); }
public:
void Initialize(PTimerCallback *pTimerCallback, const TCHAR *ptszName, ULONG ulTimerContext, ULONG ulPeriodInSeconds, CNewTimer::TimerRetryType retrytype, ULONG ulLowerRetryTime, ULONG ulUpperRetryTime, ULONG ulMaxLifetime );
void UnInitialize() { if( _fInitialized ) { _timer.Cancel(); _timer.UnInitialize();
_fInitialized = FALSE; } }
public:
void WaitForTestToComplete() { if( 0xffffffff == WaitForSingleObjectEx( _hEvent, INFINITE, FALSE )) { TrkLog(( TRKDBG_ERROR, TEXT("Couldn't wait for event"))); TrkRaiseLastError( ); } }
void MarkTestCompleted() { if( !SetEvent( _hEvent )) TrkRaiseLastError( ); }
void EnsureTimerIsStopped( ) { _tprintf( TEXT(" Verifying that timer is stopped (%ds)\n"), g_ulDefaultPeriod * 2 ); VerifyRegistryDataRemoved(); Sleep( g_ulDefaultPeriod * 2 * 1000 ); }
void SetTimerRegistryValue( const TCHAR *ptszName, const CFILETIME &cftSet, const CFILETIME cftDue, ULONG ulRetry );
void VerifyRegistryDataCorrect(); void VerifyRegistryDataRemoved();
public:
void SetSingleShot( const CFILETIME &cftExpected = 0 ) { if( 0 != cftExpected ) _cftExpected = cftExpected; else { _cftExpected = CFILETIME(); _cftExpected.IncrementSeconds( _ulPeriod ); } _timer.SetSingleShot(); TrkLog(( TRKDBG_TIMER, TEXT("%s"), CDebugString( _timer )._tsz ));
if( _ptszName ) VerifyRegistryDataCorrect(); }
void SetRecurring( const CFILETIME &cftExpected = 0 ) { if( 0 != cftExpected ) _cftExpected = cftExpected; else { _cftExpected = CFILETIME(); _cftExpected.IncrementSeconds( _ulPeriod ); }
_timer.SetRecurring();
if( _ptszName ) VerifyRegistryDataCorrect(); }
protected:
BOOL _fInitialized; CNewTimer _timer; ULONG _ulPeriod; const TCHAR * _ptszName;
CFILETIME _cftExpected; HANDLE _hEvent;
};
class CTimerTest0 : public CTimerTest {
public:
CTimerTest0() { }
~CTimerTest0() { UnInitialize(); }
public:
void Initialize() { _tprintf( TEXT("Starting a timer with a given due time (%ds)\n"), g_ulDefaultPeriod );
_ulPeriod = g_ulDefaultPeriod; CTimerTest::Initialize( this, NULL, 0, _ulPeriod, CNewTimer::NO_RETRY, 0, 0, 0 );
}
public:
void Set() { SetSingleShot(); }
private:
TimerContinuation Timer( ULONG ulTimerContext );
}; // class CTimerTest0
class CTimerTest1 : public CTimerTest {
private:
enum SUB_PHASE_ENUM { INITIAL = 1, FIRST_RECURRENCE = 2, FIRST_RETRY = 3, SECOND_RETRY = 4, THIRD_RETRY = 5, FOURTH_RETRY = 6, SECOND_RECURRENCE = 7, LAST_RETRY = 8, FINAL = 9 };
public:
CTimerTest1() { _SubPhase = INITIAL; }
~CTimerTest1() { UnInitialize(); }
public:
void Initialize() { _tprintf( TEXT("Starting a persistent, recurring, backoff-retry (%d-%ds) timer (%ds)\n"), g_ulMinRetry, g_ulMaxRetry, g_ulDefaultPeriod );
_ulPeriod = g_ulDefaultPeriod; CTimerTest::Initialize( this, L"Timer1", 1, _ulPeriod, CNewTimer::RETRY_WITH_BACKOFF, g_ulMinRetry, g_ulMaxRetry, 0 );
}
public:
void Set() { SetRecurring(); }
private:
TimerContinuation Timer( ULONG ulTimerContext );
private:
SUB_PHASE_ENUM _SubPhase;
}; // class CTimerTest1
class CTimerTest2 : public CTimerTest {
private:
enum SUB_PHASE_ENUM { INITIAL = 1, RESET = 2, FINAL = 3 };
public:
CTimerTest2() { _SubPhase = INITIAL; }
~CTimerTest2() { UnInitialize(); }
public:
void Initialize() { _tprintf( TEXT("Starting a persistent, recurring, non-retrying timer (%ds)\n"), g_ulDefaultPeriod );
_ulPeriod = g_ulDefaultPeriod; CTimerTest::Initialize( this, L"Timer2", 2, _ulPeriod, CNewTimer::NO_RETRY, 0, 0, 0 );
}
public:
void Set() { SetRecurring(); }
private:
TimerContinuation Timer( ULONG ulTimerContext );
private:
SUB_PHASE_ENUM _SubPhase;
}; // class CTimerTest1
class CTimerTest3 : public CTimerTest {
private:
enum SUB_PHASE_ENUM { INITIAL = 1, FINAL = 2 };
public:
CTimerTest3() { _SubPhase = INITIAL; }
~CTimerTest3() { UnInitialize(); }
public:
void Initialize() { CFILETIME cftNow; LONG lRet;
_tprintf( TEXT("Continuing a persistent timer (0s)\n") );
SetTimerRegistryValue( TEXT("Timer3"), 0, cftNow-1, 0 );
// We set a period, but it should really go off immediately because
// of the registry value we just set.
_ulPeriod = g_ulDefaultPeriod; CTimerTest::Initialize( this, // PTimerCallback
L"Timer3", // Timer name
3, // Timer context
_ulPeriod, // Period in seconds
CNewTimer::NO_RETRY, 0, 0, 0 ); // Lower, upper, max retry times.
}
public:
void Set() { SetSingleShot( CFILETIME() - 1 ); }
private:
TimerContinuation Timer( ULONG ulTimerContext );
private:
SUB_PHASE_ENUM _SubPhase;
}; // class CTimerTest1
class CTimerTest4 : public CTimerTest {
private:
enum SUB_PHASE_ENUM { INITIAL = 1, SECOND = 2, THIRD = 3, FOURTH = 4, FINAL = 5 };
public:
CTimerTest4() { _SubPhase = INITIAL; }
~CTimerTest4() { UnInitialize(); }
public:
void Initialize() { _tprintf( TEXT("Starting a non-persistent timer with max lifetime\n") );
_ulPeriod = g_ulDefaultPeriod; CTimerTest::Initialize( this, // PTimerCallback
NULL, // Timer name
4, // Timer context
_ulPeriod, // Period in seconds
CNewTimer::RETRY_WITH_BACKOFF, g_ulDefaultPeriod/2, // Min retry
g_ulDefaultPeriod * 2, // Max retry
// Max lifetime
g_ulDefaultPeriod + g_ulDefaultPeriod/2 + g_ulDefaultPeriod + 2*g_ulDefaultPeriod + g_ulDefaultPeriod/4 );
}
public:
void Set() { SetSingleShot(); }
private:
TimerContinuation Timer( ULONG ulTimerContext );
private:
SUB_PHASE_ENUM _SubPhase;
}; // class CTimerTest4
class CTimerTest5 : public CTimerTest {
private:
enum SUB_PHASE_ENUM { INITIAL = 1 };
public:
CTimerTest5() { _SubPhase = INITIAL; }
~CTimerTest5() { UnInitialize(); }
public:
void Initialize() { _tprintf( TEXT("Starting a generic timer (%ds)\n"), g_ulDefaultPeriod * 2 );
_ulPeriod = g_ulDefaultPeriod * 2; CTimerTest::Initialize( this, // PTimerCallback
NULL, // Timer name
5, // Timer context
_ulPeriod, // Period in seconds
CNewTimer::NO_RETRY, 0, 0, 0 ); // Min, max retry, max lifetime
}
public:
void Set() { SetSingleShot(); }
private:
TimerContinuation Timer( ULONG ulTimerContext );
private:
SUB_PHASE_ENUM _SubPhase;
}; // class CTimerTest4
class CTimerTest6 : public CTimerTest {
private:
enum SUB_PHASE_ENUM { INITIAL = 1, FIRST_RECURRENCE = 2, FIRST_RETRY = 3, SECOND_RETRY = 4, THIRD_RETRY = 5, FOURTH_RETRY = 6, FINAL = 7 };
public:
CTimerTest6() { _cftLower = 0; _cftUpper = 0; _cftLastSet = 0; _SubPhase = INITIAL; }
~CTimerTest6() { UnInitialize(); }
public:
void Initialize() { _tprintf( TEXT("Continuing a persistent, recurring, random-retry (%d-%ds) timer (%ds)\n"), g_ulMinRetry, g_ulMaxRetry, g_ulDefaultPeriod );
_ulPeriod = g_ulDefaultPeriod;
CFILETIME cftDue; cftDue.IncrementSeconds( _ulPeriod ); SetTimerRegistryValue( TEXT("Timer6"), 0, cftDue, 0 ); TrkLog(( TRKDBG_ERROR, TEXT("Timer6 due at %x"), cftDue.LowDateTime() ));
CTimerTest::Initialize( this, TEXT("Timer6"), 6, _ulPeriod, CNewTimer::RETRY_RANDOMLY, g_ulMinRetry, g_ulMaxRetry, 0 ); // No max lifetime
}
public:
void Set() { CFILETIME cftExpected; cftExpected.IncrementSeconds( _ulPeriod ); TrkLog(( TRKDBG_ERROR, TEXT("Timer6 due at %x"), cftExpected.LowDateTime() )); SetRecurring( cftExpected ); }
private:
TimerContinuation Timer( ULONG ulTimerContext );
private:
CFILETIME _cftLower, _cftUpper, _cftLastSet; SUB_PHASE_ENUM _SubPhase;
};
class CTimerTest7 : public CTimerTest {
private:
enum SUB_PHASE_ENUM { INITIAL = 1, FINAL = 2, };
public:
CTimerTest7() { _SubPhase = INITIAL; }
~CTimerTest7() { UnInitialize(); }
public:
void Initialize() { _ulPeriod = g_ulDefaultPeriod; _tprintf( TEXT("Starting a retrying (%d-%ds) timer (%ds)\n"), _ulPeriod*2, _ulPeriod*4, _ulPeriod );
CTimerTest::Initialize( this, // PTimerCallback
NULL, // Timer name
7, // Timer context
_ulPeriod, // Period in seconds
CNewTimer::RETRY_WITH_BACKOFF, _ulPeriod*2, _ulPeriod*4, // Min/max retry
0 ); // No max lifetime
}
public:
void Set() { SetSingleShot(); }
private:
TimerContinuation Timer( ULONG ulTimerContext );
private:
SUB_PHASE_ENUM _SubPhase;
}; // class CTimerTest7
class CTimerTest8 : public CTimerTest {
private:
enum SUB_PHASE_ENUM { INITIAL = 1, FIRST_RETRY = 2, FINAL = 3 };
public:
CTimerTest8() { _SubPhase = INITIAL; }
~CTimerTest8() { UnInitialize(); }
public:
void Initialize() { _ulPeriod = g_ulDefaultPeriod; _tprintf( TEXT("Continuing a retrying timer which was already in retry mode\n") );
CFILETIME cftDue, cftSet; cftSet.DecrementSeconds( _ulPeriod * 2 ); // A regular period, and have the first retry, have already passed
cftDue.IncrementSeconds( _ulPeriod ); SetTimerRegistryValue( TEXT("Timer8"), cftSet, cftDue, _ulPeriod*2 );
CTimerTest::Initialize( this, // PTimerCallback
TEXT("Timer8"), // Timer name
8, // Timer context
_ulPeriod, // Period in seconds
CNewTimer::RETRY_WITH_BACKOFF, _ulPeriod*2, _ulPeriod*4, // Min/max retry
// The original period, two retries (2/4) and a retry up to the max lifetime
_ulPeriod*(1+2+4+1) );
}
public:
void Set() { CFILETIME cftExpected; cftExpected.IncrementSeconds( _ulPeriod ); SetSingleShot( cftExpected ); }
private:
TimerContinuation Timer( ULONG ulTimerContext );
private:
SUB_PHASE_ENUM _SubPhase;
}; // class CTimerTest8
#endif // #ifndef _TTIMER_HXX_
|