diff options
Diffstat (limited to 'public/gcsdk/scheduledfunction.h')
| -rw-r--r-- | public/gcsdk/scheduledfunction.h | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/public/gcsdk/scheduledfunction.h b/public/gcsdk/scheduledfunction.h new file mode 100644 index 0000000..1522de7 --- /dev/null +++ b/public/gcsdk/scheduledfunction.h @@ -0,0 +1,205 @@ +//====== Copyright (c), Valve Corporation, All rights reserved. ======= +// +// Purpose: Provides a scheduled function manager that will bucket events into +// time chunks and execute them as time elapses +// +//============================================================================= + +#ifndef SCHEDULEDFUNCTION_H +#define SCHEDULEDFUNCTION_H +#ifdef _WIN32 +#pragma once +#endif + +namespace GCSDK +{ + +//interface for events that can be scheduled to run on the GC base +class IGCScheduledFunction +{ +public: + IGCScheduledFunction() : m_nAbsScheduleBucket( knInvalidBucket ) {} + virtual ~IGCScheduledFunction(); + //called in response to our event time elapsing + virtual void OnEvent() = 0; + + bool BIsScheduled() const { return m_nAbsScheduleBucket != IGCScheduledFunction::knInvalidBucket; } + +private: + //the absolute bucket that we were scheduled in (or invalid). Used to enable deregistering + friend class CScheduledFunctionMgr; + uint32 m_nAbsScheduleBucket; + uint32 m_nLLIndex; + static const uint32 knInvalidBucket = ( uint32 )-1; +}; + +//utility for scheduling a global function +class CGlobalScheduledFunction : + public IGCScheduledFunction +{ +public: + + CGlobalScheduledFunction(); + + typedef void ( *func_t )(); + + void ScheduleMS( func_t pfn, uint32 nDelayMS ); + void ScheduleSecond( func_t pfn, uint32 nDelaySecond ); + void ScheduleMinute( func_t pfn, uint32 nDelayMinute ); + void Cancel(); + + virtual void OnEvent() OVERRIDE; + +private: + func_t m_pfn; +}; + +//the same as the above, but automatically deletes the object once the event is fired +class CGlobalScheduledFunctionAutoDelete : + public CGlobalScheduledFunction +{ +public: + CGlobalScheduledFunctionAutoDelete() {} + + virtual void OnEvent() OVERRIDE + { + CGlobalScheduledFunction::OnEvent(); + delete this; + } +}; + +//utility for scheduling a member function +template< class T > +class CScheduledFunction : + public IGCScheduledFunction +{ +public: + CScheduledFunction() : m_pObj( NULL ), m_pfn( NULL ) {} + + typedef void ( T::*func_t )(); + + void ScheduleMS( T* pObj, func_t pfn, uint32 nDelayMS ) + { + m_pObj = pObj; + m_pfn = pfn; + GScheduledFunctionMgr().ScheduleMS( this, nDelayMS ); + } + + void ScheduleSecond( T* pObj, func_t pfn, uint32 nDelaySecond ) + { + m_pObj = pObj; + m_pfn = pfn; + GScheduledFunctionMgr().ScheduleSecond( this, nDelaySecond ); + } + + void ScheduleMinute( T* pObj, func_t pfn, uint32 nDelayMinute ) + { + m_pObj = pObj; + m_pfn = pfn; + GScheduledFunctionMgr().ScheduleMinute( this, nDelayMinute ); + } + + + void Cancel() + { + GScheduledFunctionMgr().Cancel( this ); + } + + virtual void OnEvent() OVERRIDE + { + ( m_pObj->*m_pfn )(); + } + +private: + T* m_pObj; + func_t m_pfn; +}; + +//similar to the above, but auto deletes once the event is fired +template< class T > +class CScheduledFunctionAutoDelete : + public CScheduledFunction< T > +{ +public: + typedef void ( T::*func_t )(); + + CScheduledFunctionAutoDelete() {} + CScheduledFunctionAutoDelete( T* pObj, func_t pfn, uint32 nDelayMS ) { Schedule( pObj, pfn, nDelayMS ); } + virtual void OnEvent() OVERRIDE + { + CScheduledFunction< T >::OnEvent(); + delete this; + } +}; + + +class CScheduledFunctionMgr +{ +public: + + CScheduledFunctionMgr(); + + //called to initialize the starting time for the scheduled function manager. It doesn't need to be globally absolute, just relative to the time values provided + //to the run function + void InitStartingTime(); + + //called to register a scheduled event for a certain period in the future, with the delay specified in milliseconds. This has resolution of an individual frame, and + //will unregister from any previously registered time slot + void ScheduleMS( IGCScheduledFunction* pEvent, uint32 nMSDelay ); + //similar to the above, but instead of having frame resolution, this has second level resolution, and should be used for low granularity tasks + void ScheduleSecond( IGCScheduledFunction* pEvent, uint32 nSDelay ); + //similar to the above but has minute level resolution which should be used for very low resolution tasks + void ScheduleMinute( IGCScheduledFunction* pEvent, uint32 nMinuteDelay ); + + //deregisters a previously registered event + void Cancel( IGCScheduledFunction* pEvent ); + + //called to run registered functions + void RunFunctions(); + +private: + + //called internally by the other schedule functions to schedule the event at the specified resolution in our resolution array + void InternalSchedule( uint32 nResolution, IGCScheduledFunction* pEvent, uint32 nMSDelay ); + + //the list type that we store all of the entries in. We use a single list to avoid the overhead of so many lists + typedef CUtlLinkedList< IGCScheduledFunction*, uint32 > TScheduleList; + + //all information tied to a specific resolution, including the time hash buckets, number of buckets, and which buckets it has executed + class CScheduleBucket + { + public: + CScheduleBucket(); + ~CScheduleBucket(); + void Init( TScheduleList& MasterList, uint32 nNumBuckets, uint32 nMicroSPerBucket ); + + //maps a micro second time to a bucket time + uint32 GetAbsScheduleBucketIndex( uint64 nMicroSTime ) const { return ( uint32 )( nMicroSTime / m_nMicroSPerBucket ); } + + //called to run registered functions + void RunFunctions( TScheduleList& MasterList, uint64 nMicroSTime ); + + //for each bucket, we insert a node into the master linked list, then our list runs from this node to the next empty node (or end) in the list + uint32* m_pBuckets; + //the number of buckets that we have + uint32 m_nNumBuckets; + //how many micro seconds each bucket represents + uint32 m_nMicroSPerBucket; + //the last bucket that we had executed + uint32 m_nAbsLastScheduleBucket; + }; + + //the list of all of our entries. We store bucket starts within here, and then insert the events in between them + TScheduleList m_ScheduleList; + + //the list of resolutions that we have + CScheduleBucket m_Resolutions[ 3 ]; +}; + +//global singleton access +CScheduledFunctionMgr& GScheduledFunctionMgr(); + + +} //namespace GCSDK + +#endif |