|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 2000.
//
// File: T I M E R . C P P
//
// Contents: Timer queue helper class
//
// Notes:
//
// Author: mbend 3 Nov 2000
//
//----------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
#include "timer.h"
#include "ncdefine.h"
#include "ncbase.h"
CTimerQueue CTimerQueue::s_instance;
CTimerQueue::CTimerQueue() : m_hTimerQueue(NULL), m_nRefCount(0) { }
CTimerQueue::~CTimerQueue() { if (!m_hTimerQueue) { TraceError("CTimerQueue::~CTimerQueue", E_FAIL); } }
CTimerQueue & CTimerQueue::Instance() { return s_instance; }
HRESULT CTimerQueue::HrInitialize() { CLock lock(m_critSec);
++m_nRefCount;
if(m_nRefCount > 1) { return S_OK; }
HRESULT hr = S_OK; m_hTimerQueue = CreateTimerQueue(); if(!m_hTimerQueue) { hr = HrFromLastWin32Error(); } TraceHr(ttidSsdpTimer, FAL, hr, FALSE, "CTimerQueue::HrInitialize"); return hr; }
HRESULT CTimerQueue::HrShutdown(HANDLE hCompletionEvent) { HRESULT hr = S_OK;
HANDLE hTimerQueue = NULL;
{ CLock lock(m_critSec);
if(!m_nRefCount) { hr = E_UNEXPECTED; TraceHr(ttidSsdpTimer, FAL, hr, FALSE, "CTimerQueue::HrShutdown - Can't call SsdpCleanup without calling SsdpStartup"); }
if(SUCCEEDED(hr)) { --m_nRefCount; if(!m_nRefCount) { Assert(m_hTimerQueue); hTimerQueue = m_hTimerQueue; m_hTimerQueue = NULL; } } }
if(SUCCEEDED(hr) && hTimerQueue) { if(!DeleteTimerQueueEx(hTimerQueue, hCompletionEvent)) { hr = HrFromLastWin32Error(); } }
TraceHr(ttidSsdpTimer, FAL, hr, FALSE, "CTimerQueue::HrShutdown"); return hr; }
HRESULT CTimerQueue::HrGetHandle(HANDLE * phTimerQueue) { CLock lock(m_critSec);
HRESULT hr = S_OK;
if(phTimerQueue) { *phTimerQueue = m_hTimerQueue; } else { hr = E_POINTER; }
TraceHr(ttidSsdpTimer, FAL, hr, FALSE, "CTimerQueue::HrGetHandle"); return hr; }
#ifdef DBG
long CTimerBase::s_nCallbackEnter = 0; long CTimerBase::s_nCallbackExit = 0; #endif // DBG
CTimerBase::CTimerBase() : m_bShutdown(FALSE), m_hTimerQueueTimer(NULL) { #ifdef DBG
m_nSetTimer = 0; m_nSetTimerSuccess = 0; m_nDeleteTimer = 0; m_nDeleteTimerActual = 0; m_nTimerFiredEnter = 0; m_nTimerFiredExit = 0; m_nCallbackEnter = 0; #endif // DBG
}
CTimerBase::~CTimerBase() { HRESULT hr = S_OK; if(m_hTimerQueueTimer) { HANDLE hTimerQueue = NULL; hr = CTimerQueue::Instance().HrGetHandle(&hTimerQueue); if(SUCCEEDED(hr)) { if(!DeleteTimerQueueTimer(hTimerQueue, m_hTimerQueueTimer, NULL)) { hr = HrFromLastWin32Error(); } else { m_hTimerQueueTimer = NULL; } } } }
HRESULT CTimerBase::HrSetTimer( DWORD dwIntervalInMillis) { HRESULT hr = E_FAIL;
CLock lock(m_critSec);
Assert(!m_hTimerQueueTimer);
#ifdef DBG
InterlockedIncrement(&m_nSetTimer); #endif // DBG
// Check for shutdown
if(!m_bShutdown) { HANDLE hTimerQueue = NULL; hr = CTimerQueue::Instance().HrGetHandle(&hTimerQueue); if(SUCCEEDED(hr)) { if(!CreateTimerQueueTimer(&m_hTimerQueueTimer, hTimerQueue, &CTimerBase::Callback, this, dwIntervalInMillis, 0, 0)) { hr = HrFromLastWin32Error(); } } }
#ifdef DBG
if(SUCCEEDED(hr)) { InterlockedIncrement(&m_nSetTimerSuccess); } #endif // DBG
TraceHr(ttidSsdpTimer, FAL, hr, FALSE, "CTimerBase::HrSetTimer"); return hr; }
HRESULT CTimerBase::HrSetTimerInFired( DWORD dwIntervalInMillis) { HRESULT hr = E_FAIL;
CLock lock(m_critSec); if(!m_bShutdown) { if(m_hTimerQueueTimer) { HrDelete(NULL); m_bShutdown = FALSE; } hr = HrSetTimer(dwIntervalInMillis); }
TraceHr(ttidSsdpTimer, FAL, hr, FALSE, "CTimerBase::HrSetTimerInFired"); return hr; }
HRESULT CTimerBase::HrDelete(HANDLE hCompletionEvent) { HRESULT hr = S_OK;
#ifdef DBG
InterlockedIncrement(&m_nDeleteTimer); #endif // DBG
HANDLE hTimerQueueTimer = NULL; { CLock lock(m_critSec);
m_bShutdown = TRUE;
hTimerQueueTimer = m_hTimerQueueTimer; m_hTimerQueueTimer = NULL; }
if(hTimerQueueTimer) { HANDLE hTimerQueue = NULL; hr = CTimerQueue::Instance().HrGetHandle(&hTimerQueue); if(SUCCEEDED(hr)) { if(!DeleteTimerQueueTimer(hTimerQueue, hTimerQueueTimer, hCompletionEvent)) { hr = HrFromLastWin32Error(); if (HRESULT_FROM_WIN32(ERROR_IO_PENDING) == hr) { hr = S_OK; } } #ifdef DBG
if(SUCCEEDED(hr)) { InterlockedIncrement(&m_nDeleteTimerActual); } #endif // DBG
} } else { if(hCompletionEvent != NULL && hCompletionEvent != INVALID_HANDLE_VALUE) { SetEvent(hCompletionEvent); } }
TraceHr(ttidSsdpTimer, FAL, hr, FALSE, "CTimerBase::HrDelete"); return hr; }
HRESULT CTimerBase::HrResetTimer( DWORD dwIntervalInMillis) { HRESULT hr = S_OK;
// Can't hold lock during whole operation or this can deadlock waiting for timer to exit
HrDelete(INVALID_HANDLE_VALUE); m_bShutdown = FALSE; hr = HrSetTimer(dwIntervalInMillis);
TraceHr(ttidSsdpTimer, FAL, hr, FALSE, "CTimerBase::HrResetTimer"); return hr; }
void CALLBACK CTimerBase::Callback(void * pvParam, BOOLEAN) { CTimerBase * pTimer = reinterpret_cast<CTimerBase*>(pvParam);
#ifdef DBG
InterlockedIncrement(&s_nCallbackEnter); InterlockedIncrement(&pTimer->m_nCallbackEnter); #endif // DBG
while(true) { CLock lock(pTimer->m_critSec); if(pTimer->m_bShutdown) { break; } if(pTimer->OnTryToLock()) { pTimer->OnExecute(); pTimer->OnUnlock(); break; } Sleep(1); }
#ifdef DBG
InterlockedIncrement(&s_nCallbackExit); #endif // DBG
}
VOID FileTimeToString(FILETIME FileTime, CHAR *szBuf, INT BufSize) { SYSTEMTIME SystemTime; INT Size;
FileTimeToLocalFileTime(&FileTime, &FileTime);
FileTimeToSystemTime(&FileTime,&SystemTime);
Size = GetDateFormatA(LOCALE_SYSTEM_DEFAULT, 0, &SystemTime, NULL, szBuf, BufSize-1 );
if (Size > 0) { szBuf[Size-1] = ' '; }
GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, 0, &SystemTime, NULL, szBuf+Size, BufSize-Size); }
|