Source code of Windows XP (NT5)
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
/*
Copyright (c) 1998-1999 Microsoft Corporation
*/
#ifndef __TIMER_QUEUE__
#define __TIMER_QUEUE__
#include "meterf.h"
// we don't allow timeouts greater than 1 day
// this ensures that we don't get multiple wraparounds in the timerqueue,
// which has a wraparound time of 49 days
const DWORD MAX_TIMEOUT = 1000 * 60 * 60 * 24;
const DWORD MAX_DWORD = DWORD(-1);
class CTimerQueue; class CMediaPump;
class CFilterInfo { friend CTimerQueue; friend CMediaPump;
public:
// null entries
inline CFilterInfo( IN CMediaTerminalFilter *pFilter = NULL, IN HANDLE hWaitEvent = NULL );
inline BOOL InQueue();
inline void ScheduleNextTimeout( IN CTimerQueue &TimerQueue, IN DWORD TimeOut );
LONG AddRef() { return InterlockedIncrement(&m_lRefCount); }
LONG Release() { LONG l = InterlockedDecrement(&m_lRefCount);
if (0 == l) { delete this; }
return l; }
private:
LONG m_lRefCount;
protected:
//
// the only way to destroy filterinfo is through Release()
//
inline ~CFilterInfo();
// m_pFilter holds a refcnt.
// the wait event is signaled when a new sample
// is available
CMediaTerminalFilter *m_pFilter; HANDLE m_hWaitEvent;
// contains the absolute time to trigger the timeout event
// this is based upon the value returned by timeGetTime()
DWORD m_WaitTime;
// prev and next ptrs in an intrusive doubly linked list
CFilterInfo *m_pPrev; CFilterInfo *m_pNext; };
// null entries
inline CFilterInfo::CFilterInfo( IN CMediaTerminalFilter *pFilter, /* = NULL */ IN HANDLE hWaitEvent /* = NULL */ ) : m_pFilter(pFilter), m_hWaitEvent(hWaitEvent), m_pPrev(NULL), m_pNext(NULL), m_lRefCount(0)
{ // either both pFilter and hWaitEvent are null, or both are non-null
// enough to assert on this
TM_ASSERT((NULL == pFilter) == (NULL == hWaitEvent));
if (NULL != m_pFilter) m_pFilter->GetControllingUnknown()->AddRef(); }
CFilterInfo::~CFilterInfo( ) { // release refcnt on the filter
if (NULL != m_pFilter) m_pFilter->GetControllingUnknown()->Release(); }
inline BOOL CFilterInfo::InQueue( ) { // either both prev/next are null or both are not null
TM_ASSERT((NULL == m_pPrev) == (NULL == m_pNext));
return (NULL != m_pPrev) ? TRUE : FALSE; }
// ScheduleNextTimeout(2 params) - declared at the end of the file
// as it uses CTimerQueue::Insert and has to be inline
// CTimerQueue is a doubly linked intrusive list of CFilterInfo
// the wait time values in the entries represents the absolute time at which
// they must be fired.
// we assume that the timeout values are small (<=MAX_TIMEOUT) and,
// therefore, we can have atmost one wrap around in the list at a time.
// to deal with a wrap around, when computing the time difference between two
// time values, we use the least time to get to one time from the other
// ex. MAX_DWORD-1, 5 - the difference is (MAX_DWORD - (MAX_DWORD-1) + 5)
// this is quite reasonable as the value range is 49.1 days (MAX_DWORD)
class CTimerQueue { public:
inline CTimerQueue() { m_Head.m_pNext = m_Head.m_pPrev = &m_Head; }
inline BOOL IsEmpty();
DWORD GetTimeToTimeout();
inline CFilterInfo *RemoveFirst();
void Insert( IN CFilterInfo *pNewFilterInfo );
BOOL Remove( IN CFilterInfo *pFilterInfo );
protected:
// no need to call Init
CFilterInfo m_Head;
inline BOOL IsHead( IN const CFilterInfo *pFilterInfo ) { return (&m_Head == pFilterInfo) ? TRUE : FALSE; }
// to deal with a wrap around, when computing the time difference
// between two time values, we use the least time to get to one time
// from the other - ex. MAX_DWORD-1, 5 - the difference is
// (MAX_DWORD - (MAX_DWORD-1) + 5). this is quite reasonable as the
// value range is 49.1 days (MAX_DWORD)
DWORD GetMinDiff( IN DWORD Time1, IN DWORD Time2, OUT BOOL &bIsWrap ); };
inline BOOL CTimerQueue::IsEmpty( ) { return IsHead(m_Head.m_pNext); }
CFilterInfo * CTimerQueue::RemoveFirst( ) { TM_ASSERT(!IsEmpty());
CFilterInfo *ToReturn = m_Head.m_pNext; Remove(ToReturn);
return ToReturn; }
// this method has to be declared after the CTimerQueue declaration as it
// uses its Insert method
// this is called after returning from GetFilledBuffer. the filter suggests
// a timeout offset for the next call into GetFilledBuffer, but the timer
// puts a limit on the time out value to a max of MAX_TIMEOUT
inline void CFilterInfo::ScheduleNextTimeout( IN CTimerQueue &TimerQueue, IN DWORD TimeOut ) { TM_ASSERT(!InQueue());
if (MAX_TIMEOUT < TimeOut) TimeOut = MAX_TIMEOUT; m_WaitTime = TimeOut + timeGetTime(); TimerQueue.Insert(this); }
#endif // __TIMER_QUEUE__
|