STDMETHODIMP CBaseReferenceClock::SetTimeDelta(const REFERENCE_TIME & TimeDelta) { #ifdef DEBUG // Just break if passed an improper time delta value LONGLONG llDelta = TimeDelta > 0 ? TimeDelta : -TimeDelta; if (llDelta > UNITS * 1000) { DbgLog((LOG_TRACE, 0, TEXT("Bad Time Delta"))); //DebugBreak(); } // We're going to calculate a "severity" for the time change. Max -1 // min 8. We'll then use this as the debug logging level for a // debug log message. const LONG usDelta = LONG(TimeDelta/10); // Delta in micro-secs DWORD delta = abs(usDelta); // varying delta // Severity == 8 - ceil(log<base 8>(abs( micro-secs delta))) int Severity = 8; while ( delta > 0 ) { delta >>= 3; // div 8 Severity--; } // Sev == 0 => > 2 second delta! DbgLog((LOG_TIMING, Severity < 0 ? 0 : Severity, TEXT("Sev %2i: CSystemClock::SetTimeDelta(%8ld us) %lu -> %lu ms."), Severity, usDelta, DWORD(ConvertToMilliseconds(m_rtPrivateTime)), DWORD(ConvertToMilliseconds(TimeDelta+m_rtPrivateTime)) )); // Don't want the DbgBreak to fire when running stress on debug-builds. #ifdef BREAK_ON_SEVERE_TIME_DELTA if (Severity < 0) DbgBreakPoint(TEXT("SetTimeDelta > 16 seconds!"), TEXT(__FILE__),__LINE__); #endif #endif CAutoLock cObjectLock(this); m_rtPrivateTime += TimeDelta; // If time goes forwards, and we have advises, then we need to // trigger the thread so that it can re-evaluate its wait time. // Since we don't want the cost of the thread switches if the change // is really small, only do it if clock goes forward by more than // 0.5 millisecond. If the time goes backwards, the thread will // wake up "early" (relativly speaking) and will re-evaluate at // that time. if ( TimeDelta > 5000 && m_pSchedule->GetAdviseCount() > 0 ) TriggerThread(); return NOERROR; }
CBaseReferenceClock::~CBaseReferenceClock() { if(m_TimerResolution) timeEndPeriod(m_TimerResolution); m_pSchedule->DumpLinkedList(); if(m_hThread) { m_bAbort = TRUE; TriggerThread(); WaitForSingleObject(m_hThread, INFINITE); EXECUTE_ASSERT(CloseHandle(m_hThread)); m_hThread = 0; EXECUTE_ASSERT(CloseHandle(m_pSchedule->GetEvent())); delete m_pSchedule; } }
CBaseReferenceClock::~CBaseReferenceClock() { #ifdef DXMPERF PERFLOG_DTOR( L"CBaseReferenceClock", (IReferenceClock *) this ); #endif // DXMPERF if (m_TimerResolution) timeEndPeriod(m_TimerResolution); if (m_pSchedule) { m_pSchedule->DumpLinkedList(); } if (m_hThread) { m_bAbort = TRUE; TriggerThread(); WaitForSingleObject( m_hThread, INFINITE ); EXECUTE_ASSERT( CloseHandle(m_hThread) ); m_hThread = 0; EXECUTE_ASSERT( CloseHandle(m_pSchedule->GetEvent()) ); delete m_pSchedule; } }