129 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			129 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|  | //------------------------------------------------------------------------------
 | ||
|  | // File: Schedule.h
 | ||
|  | //
 | ||
|  | // Desc: DirectShow base classes.
 | ||
|  | //
 | ||
|  | // Copyright (c) 1996-2001 Microsoft Corporation.  All rights reserved.
 | ||
|  | //------------------------------------------------------------------------------
 | ||
|  | 
 | ||
|  | 
 | ||
|  | #ifndef __CAMSchedule__
 | ||
|  | #define __CAMSchedule__
 | ||
|  | 
 | ||
|  | class CAMSchedule : private CBaseObject | ||
|  | { | ||
|  | public: | ||
|  |     virtual ~CAMSchedule(); | ||
|  |     // ev is the event we should fire if the advise time needs re-evaluating
 | ||
|  |     CAMSchedule( HANDLE ev ); | ||
|  | 
 | ||
|  |     DWORD GetAdviseCount(); | ||
|  |     REFERENCE_TIME GetNextAdviseTime(); | ||
|  | 
 | ||
|  |     // We need a method for derived classes to add advise packets, we return the cookie
 | ||
|  |     DWORD_PTR AddAdvisePacket( const REFERENCE_TIME & time1, const REFERENCE_TIME & time2, HANDLE h, BOOL periodic ); | ||
|  |     // And a way to cancel
 | ||
|  |     HRESULT Unadvise(DWORD_PTR dwAdviseCookie); | ||
|  | 
 | ||
|  |     // Tell us the time please, and we'll dispatch the expired events.  We return the time of the next event.
 | ||
|  |     // NB: The time returned will be "useless" if you start adding extra Advises.  But that's the problem of
 | ||
|  |     // whoever is using this helper class (typically a clock).
 | ||
|  |     REFERENCE_TIME Advise( const REFERENCE_TIME & rtTime ); | ||
|  | 
 | ||
|  |     // Get the event handle which will be set if advise time requires re-evaluation.
 | ||
|  |     HANDLE GetEvent() const { return m_ev; } | ||
|  | 
 | ||
|  | private: | ||
|  |     // We define the nodes that will be used in our singly linked list
 | ||
|  |     // of advise packets.  The list is ordered by time, with the
 | ||
|  |     // elements that will expire first at the front.
 | ||
|  |     class CAdvisePacket | ||
|  |     { | ||
|  |     public: | ||
|  |         CAdvisePacket() | ||
|  |         {} | ||
|  | 
 | ||
|  |         CAdvisePacket * m_next; | ||
|  |         DWORD_PTR       m_dwAdviseCookie; | ||
|  |         REFERENCE_TIME  m_rtEventTime;      // Time at which event should be set
 | ||
|  |         REFERENCE_TIME  m_rtPeriod;         // Periodic time
 | ||
|  |         HANDLE          m_hNotify;          // Handle to event or semephore
 | ||
|  |         BOOL            m_bPeriodic;        // TRUE => Periodic event
 | ||
|  | 
 | ||
|  |         CAdvisePacket( __inout_opt CAdvisePacket * next, LONGLONG time ) : m_next(next), m_rtEventTime(time) | ||
|  |         {} | ||
|  | 
 | ||
|  |         void InsertAfter( __inout CAdvisePacket * p ) | ||
|  |         { | ||
|  |             p->m_next = m_next; | ||
|  |             m_next    = p; | ||
|  |         } | ||
|  | 
 | ||
|  |         int IsZ() const // That is, is it the node that represents the end of the list
 | ||
|  |         { return m_next == 0; } | ||
|  | 
 | ||
|  |         CAdvisePacket * RemoveNext() | ||
|  |         { | ||
|  |             CAdvisePacket *const next = m_next; | ||
|  |             CAdvisePacket *const new_next = next->m_next; | ||
|  |             m_next = new_next; | ||
|  |             return next; | ||
|  |         } | ||
|  | 
 | ||
|  |         void DeleteNext() | ||
|  |         { | ||
|  |             delete RemoveNext(); | ||
|  |         } | ||
|  | 
 | ||
|  |         CAdvisePacket * Next() const | ||
|  |         { | ||
|  |             CAdvisePacket * result = m_next; | ||
|  |             if (result->IsZ()) result = 0; | ||
|  |             return result; | ||
|  |         } | ||
|  | 
 | ||
|  |         DWORD_PTR Cookie() const | ||
|  |         { return m_dwAdviseCookie; } | ||
|  |     }; | ||
|  | 
 | ||
|  |     // Structure is:
 | ||
|  |     // head -> elmt1 -> elmt2 -> z -> null
 | ||
|  |     // So an empty list is:       head -> z -> null
 | ||
|  |     // Having head & z as links makes insertaion,
 | ||
|  |     // deletion and shunting much easier.
 | ||
|  |     CAdvisePacket   head, z;            // z is both a tail and a sentry
 | ||
|  | 
 | ||
|  |     volatile DWORD_PTR  m_dwNextCookie;     // Strictly increasing
 | ||
|  |     volatile DWORD  m_dwAdviseCount;    // Number of elements on list
 | ||
|  | 
 | ||
|  |     CCritSec        m_Serialize; | ||
|  | 
 | ||
|  |     // AddAdvisePacket: adds the packet, returns the cookie (0 if failed)
 | ||
|  |     DWORD_PTR AddAdvisePacket( __inout CAdvisePacket * pPacket ); | ||
|  |     // Event that we should set if the packed added above will be the next to fire.
 | ||
|  |     const HANDLE m_ev; | ||
|  | 
 | ||
|  |     // A Shunt is where we have changed the first element in the
 | ||
|  |     // list and want it re-evaluating (i.e. repositioned) in
 | ||
|  |     // the list.
 | ||
|  |     void ShuntHead(); | ||
|  | 
 | ||
|  |     // Rather than delete advise packets, we cache them for future use
 | ||
|  |     CAdvisePacket * m_pAdviseCache; | ||
|  |     DWORD           m_dwCacheCount; | ||
|  |     enum { dwCacheMax = 5 };             // Don't bother caching more than five
 | ||
|  | 
 | ||
|  |     void Delete( __inout CAdvisePacket * pLink );// This "Delete" will cache the Link
 | ||
|  | 
 | ||
|  | // Attributes and methods for debugging
 | ||
|  | public: | ||
|  | #ifdef DEBUG
 | ||
|  |     void DumpLinkedList(); | ||
|  | #else
 | ||
|  |     void DumpLinkedList() {} | ||
|  | #endif
 | ||
|  | 
 | ||
|  | }; | ||
|  | 
 | ||
|  | #endif // __CAMSchedule__
 |