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.
440 lines
11 KiB
440 lines
11 KiB
#ifndef __THREAD_H
|
|
#define __THREAD_H
|
|
|
|
#include "Allocator.h"
|
|
#include "TPQueue.h"
|
|
#include "BasicTree.h"
|
|
#include <lockst.h>
|
|
/*
|
|
* Forwards:
|
|
*
|
|
* WmiTask
|
|
*
|
|
* Description:
|
|
*
|
|
* Provides abstraction above heap allocation functions
|
|
*
|
|
* Version:
|
|
*
|
|
* Initial
|
|
*
|
|
* Last Changed:
|
|
*
|
|
* See Source Depot for change history
|
|
*
|
|
*/
|
|
|
|
template <class WmiKey> class WmiTask ;
|
|
template <class WmiKey> class WmiThread ;
|
|
|
|
/*
|
|
* Class:
|
|
*
|
|
* WmiTask
|
|
*
|
|
* Description:
|
|
*
|
|
* Provides abstraction above heap allocation functions
|
|
*
|
|
* Version:
|
|
*
|
|
* Initial
|
|
*
|
|
* Last Changed:
|
|
*
|
|
* See Source Depot for change history
|
|
*
|
|
*/
|
|
|
|
template <class WmiKey>
|
|
class WmiTask
|
|
{
|
|
friend WmiThread <WmiKey>;
|
|
|
|
public:
|
|
|
|
enum WmiTaskEnqueueType
|
|
{
|
|
e_WmiTask_Enqueue ,
|
|
e_WmiTask_EnqueueAlertable ,
|
|
e_WmiTask_EnqueueInterruptable
|
|
} ;
|
|
|
|
enum WmiTaskState
|
|
{
|
|
e_WmiTask_UnInitialized ,
|
|
e_WmiTask_Initialized ,
|
|
e_WmiTask_EnQueued ,
|
|
e_WmiTask_DeQueued
|
|
} ;
|
|
|
|
private:
|
|
|
|
LONG m_ReferenceCount ;
|
|
|
|
WmiAllocator &m_Allocator ;
|
|
|
|
wchar_t *m_Name ;
|
|
wchar_t *m_CompletionName ;
|
|
|
|
HANDLE m_Event ;
|
|
HANDLE m_CompletionEvent ;
|
|
|
|
WmiStatusCode m_InitializationStatusCode ;
|
|
|
|
WmiTaskEnqueueType m_EnqueueType ;
|
|
WmiTaskState m_TaskState ;
|
|
|
|
private:
|
|
|
|
void SetTaskState ( WmiTaskState a_TaskState ) { m_TaskState = a_TaskState ; }
|
|
|
|
public:
|
|
|
|
WmiTask (
|
|
|
|
WmiAllocator &a_Allocator ,
|
|
const wchar_t *a_Name = NULL ,
|
|
const wchar_t *a_CompletionName = NULL
|
|
) ;
|
|
|
|
WmiTask (
|
|
|
|
WmiAllocator &a_Allocator ,
|
|
HANDLE a_Event ,
|
|
HANDLE a_CompletionEvent ,
|
|
const wchar_t *a_Name = NULL ,
|
|
const wchar_t *a_CompletionName = NULL
|
|
) ;
|
|
|
|
virtual ~WmiTask () ;
|
|
|
|
virtual ULONG STDMETHODCALLTYPE AddRef () ;
|
|
|
|
virtual ULONG STDMETHODCALLTYPE Release () ;
|
|
|
|
virtual WmiStatusCode Initialize () ;
|
|
|
|
virtual WmiStatusCode UnInitialize () ;
|
|
|
|
virtual WmiStatusCode Process ( WmiThread <WmiKey> &a_Thread ) ;
|
|
|
|
virtual WmiStatusCode Exec () ;
|
|
|
|
virtual WmiStatusCode Complete () ;
|
|
|
|
virtual WmiStatusCode Wait ( const ULONG &a_Timeout = INFINITE ) ;
|
|
|
|
virtual WmiStatusCode WaitInterruptable ( const ULONG &a_Timeout = INFINITE ) ;
|
|
|
|
virtual WmiStatusCode WaitAlertable ( const ULONG &a_Timeout = INFINITE ) ;
|
|
|
|
wchar_t *GetName () { return m_Name ; }
|
|
wchar_t *GetCompletionName () { return m_CompletionName ; }
|
|
|
|
HANDLE GetEvent () { return m_Event ; }
|
|
HANDLE GetCompletionEvent () { return m_CompletionEvent ; }
|
|
|
|
WmiAllocator &GetAllocator () { return m_Allocator ; }
|
|
|
|
WmiTaskState TaskState () { return m_TaskState ; }
|
|
|
|
WmiTaskEnqueueType EnqueuedAs () { return m_EnqueueType ; }
|
|
void EnqueueAs ( WmiTaskEnqueueType a_EnqueueType ) { m_EnqueueType = a_EnqueueType ; }
|
|
} ;
|
|
|
|
/*
|
|
* Class:
|
|
*
|
|
* WmiThread
|
|
*
|
|
* Description:
|
|
*
|
|
* Provides abstraction above heap allocation functions
|
|
*
|
|
* Version:
|
|
*
|
|
* Initial
|
|
*
|
|
* Last Changed:
|
|
*
|
|
* See Source Depot for change history
|
|
*
|
|
*/
|
|
|
|
template <class WmiKey>
|
|
class WmiThread
|
|
{
|
|
friend class WmiTask <WmiKey> ;
|
|
public:
|
|
|
|
class QueueKey
|
|
{
|
|
public:
|
|
|
|
WmiKey m_Key ;
|
|
INT64 m_Tick ;
|
|
|
|
QueueKey () { ; } ;
|
|
|
|
QueueKey ( const INT64 &a_Tick , const WmiKey &a_Key ) :
|
|
|
|
m_Key ( a_Key ) ,
|
|
m_Tick ( a_Tick )
|
|
{
|
|
|
|
}
|
|
|
|
~QueueKey () { ; }
|
|
|
|
INT64 GetTick () { return m_Tick ; }
|
|
void SetTick ( const INT64 &a_Tick ) { m_Tick = a_Tick ; }
|
|
WmiKey &GetKey () { return m_Key ; }
|
|
|
|
friend bool operator == ( const QueueKey &a_Arg1 , const QueueKey &a_Arg2 )
|
|
{
|
|
LONG t_Compare ;
|
|
if ( ( t_Compare = CompareElement ( a_Arg1.m_Key , a_Arg2.m_Key ) ) == 0 )
|
|
{
|
|
t_Compare = CompareElement ( a_Arg1.m_Tick , a_Arg2.m_Tick ) ;
|
|
}
|
|
return t_Compare == 0 ? true : false ;
|
|
}
|
|
|
|
friend bool operator < ( const QueueKey &a_Arg1 , const QueueKey &a_Arg2 )
|
|
{
|
|
LONG t_Compare ;
|
|
if ( ( t_Compare = CompareElement ( a_Arg1.m_Key , a_Arg2.m_Key ) ) == 0 )
|
|
{
|
|
t_Compare = CompareElement ( a_Arg1.m_Tick , a_Arg2.m_Tick ) ;
|
|
}
|
|
return t_Compare < 0 ? true : false ;
|
|
}
|
|
} ;
|
|
|
|
typedef WmiBasicTree <WmiTask <WmiKey> * , WmiThread <WmiKey> *> TaskContainer ;
|
|
typedef typename TaskContainer :: Iterator TaskContainerIterator ;
|
|
typedef WmiBasicTree <ULONG , WmiThread <WmiKey> *> ThreadContainer ;
|
|
typedef typename ThreadContainer :: Iterator ThreadContainerIterator ;
|
|
typedef WmiTreePriorityQueue <QueueKey,WmiTask <WmiKey> *> QueueContainer ;
|
|
typedef typename WmiTreePriorityQueue <QueueKey,WmiTask <WmiKey> *> :: Iterator QueueContainerIterator ;
|
|
|
|
private:
|
|
|
|
static ULONG ThreadProc ( void *a_Thread ) ;
|
|
|
|
static ThreadContainer *s_ThreadContainer ;
|
|
static TaskContainer *s_TaskContainer ;
|
|
static CriticalSection s_CriticalSection ;
|
|
static LONG s_InitializeReferenceCount ;
|
|
|
|
INT64 m_Key;
|
|
LONG m_ReferenceCount ;
|
|
LONG m_InternalReferenceCount ;
|
|
|
|
CriticalSection m_CriticalSection ;
|
|
|
|
WmiStatusCode m_InitializationStatusCode ;
|
|
|
|
// Determine change in queue state.
|
|
|
|
HANDLE m_Initialized ;
|
|
|
|
HANDLE m_QueueChange ;
|
|
|
|
HANDLE m_Terminate ;
|
|
|
|
// All allocations done via allocator
|
|
|
|
WmiAllocator &m_Allocator ;
|
|
|
|
// Useful debug information
|
|
|
|
wchar_t *m_Name ;
|
|
HANDLE m_Thread ;
|
|
ULONG m_Identifier ;
|
|
|
|
// Timeout period for internal event dispatch
|
|
|
|
ULONG m_Timeout ;
|
|
|
|
// Stack Size
|
|
|
|
DWORD m_StackSize ;
|
|
|
|
// All runnable tasks are placed in the queue in priority order,
|
|
// as task are executed, task can re-schedule itself, otherwise it is discarded.
|
|
// Priority is based on key compounded with insertion order ( ticks ), this implies
|
|
// tasks with same key are scheduled in FIFO order.
|
|
|
|
WmiTreePriorityQueue <QueueKey,WmiTask <WmiKey> *> m_TaskQueue ;
|
|
|
|
// All runnable tasks are placed in the queue in priority order,
|
|
// as task are executed, task can re-schedule itself, otherwise it is discarded.
|
|
// Priority is based on key compounded with insertion order ( ticks ), this implies
|
|
// tasks with same key are scheduled in FIFO order.
|
|
|
|
WmiTreePriorityQueue <QueueKey,WmiTask <WmiKey> *> m_InterruptableTaskQueue ;
|
|
|
|
// Alertable events are placed on the queue, as event is signalled they are transferred onto
|
|
// the regular queue where they are priority dispatched based on priority as inserted.
|
|
|
|
WmiTreePriorityQueue <QueueKey,WmiTask <WmiKey> *> m_AlertableTaskQueue ;
|
|
|
|
// a_EventCount [in] = Number of Predefined Dispatchable Events
|
|
|
|
static WmiStatusCode Static_Dispatch ( WmiTask <WmiKey> &a_Task , const ULONG &a_Timeout ) ;
|
|
|
|
static WmiStatusCode Static_Dispatch ( WmiTask <WmiKey> &a_Task , WmiThread <WmiKey> &a_Thread , const ULONG &a_Timeout ) ;
|
|
|
|
WmiStatusCode Dispatch ( WmiTask <WmiKey> &a_Task , const ULONG &a_Timeout ) ;
|
|
|
|
WmiStatusCode Wait ( WmiTask <WmiKey> &a_Task , const ULONG &a_Timeout ) ;
|
|
|
|
|
|
static WmiStatusCode Static_InterruptableDispatch ( WmiTask <WmiKey> &a_Task , const ULONG &a_Timeout ) ;
|
|
|
|
static WmiStatusCode Static_InterruptableDispatch ( WmiTask <WmiKey> &a_Task , WmiThread <WmiKey> &a_Thread , const ULONG &a_Timeout ) ;
|
|
|
|
WmiStatusCode InterruptableDispatch ( WmiTask <WmiKey> &a_Task , const ULONG &a_Timeout ) ;
|
|
|
|
WmiStatusCode InterruptableWait ( WmiTask <WmiKey> &a_Task , const ULONG &a_Timeout ) ;
|
|
|
|
|
|
WmiStatusCode Execute ( QueueContainer &a_Queue , QueueContainer &t_EnQueue ) ;
|
|
|
|
WmiStatusCode ShuffleTask (
|
|
|
|
const HANDLE &a_Event
|
|
) ;
|
|
|
|
WmiStatusCode FillHandleTable (
|
|
|
|
HANDLE *a_HandleTable ,
|
|
ULONG &a_Capacity
|
|
) ;
|
|
|
|
static WmiStatusCode Static_AlertableDispatch ( WmiTask <WmiKey> &a_Task , const ULONG &a_Timeout ) ;
|
|
|
|
static WmiStatusCode Static_AlertableDispatch ( WmiTask <WmiKey> &a_Task , WmiThread <WmiKey> &a_Thread , const ULONG &a_Timeout ) ;
|
|
|
|
WmiStatusCode AlertableDispatch ( WmiTask <WmiKey> &a_Task , const ULONG &a_Timeout ) ;
|
|
|
|
WmiStatusCode AlertableWait ( WmiTask <WmiKey> &a_Task , const ULONG &a_Timeout ) ;
|
|
|
|
// Dispatch code
|
|
|
|
WmiStatusCode ThreadDispatch () ;
|
|
WmiStatusCode ThreadWait () ;
|
|
|
|
WmiStatusCode CreateThread () ;
|
|
|
|
static WmiThread *GetThread () ;
|
|
|
|
static WmiThread *GetServicingThread ( WmiTask <WmiKey> &a_Task ) ;
|
|
|
|
HANDLE GetTerminateHandle () ;
|
|
|
|
public:
|
|
|
|
WmiThread (
|
|
|
|
WmiAllocator &a_Allocator ,
|
|
const wchar_t *a_Name = NULL ,
|
|
ULONG a_Timeout = INFINITE ,
|
|
DWORD a_StackSize = 0
|
|
) ;
|
|
|
|
virtual ~WmiThread () ;
|
|
|
|
virtual ULONG STDMETHODCALLTYPE AddRef () ;
|
|
|
|
virtual ULONG STDMETHODCALLTYPE Release () ;
|
|
|
|
virtual ULONG STDMETHODCALLTYPE InternalAddRef () ;
|
|
|
|
virtual ULONG STDMETHODCALLTYPE InternalRelease () ;
|
|
|
|
virtual WmiStatusCode Initialize_Callback () { return e_StatusCode_Success ; } ;
|
|
|
|
virtual WmiStatusCode UnInitialize_Callback () { return e_StatusCode_Success ; } ;
|
|
|
|
virtual void CallBackRelease () {} ;
|
|
|
|
virtual WmiStatusCode Initialize ( const ULONG &a_Timeout = INFINITE ) ;
|
|
|
|
virtual WmiStatusCode UnInitialize () ;
|
|
|
|
virtual WmiStatusCode PostShutdown () ;
|
|
|
|
virtual WmiStatusCode TimedOut () ;
|
|
|
|
// Queue a task to be executed immediately, a thread that calls a task procedure that
|
|
// executes a Wait or MsgWait will receive an indication in Queue status will not execute
|
|
// newly queued tasks.
|
|
|
|
virtual WmiStatusCode EnQueue (
|
|
|
|
const WmiKey &a_Key ,
|
|
WmiTask <WmiKey> &a_Task
|
|
) ;
|
|
|
|
virtual WmiStatusCode EnQueueAlertable (
|
|
|
|
const WmiKey &a_Key ,
|
|
WmiTask <WmiKey> &a_Task
|
|
) ;
|
|
|
|
// Queue a task to be executed immediately, a thread that calls a task procedure that
|
|
// executes a Wait or MsgWait will receive an indication of Queue status change will execute
|
|
// newly queued tasks. This is used for STA based execution where we need to interrupt the wait
|
|
// to execute a dependant request.
|
|
//
|
|
|
|
virtual WmiStatusCode EnQueueInterruptable (
|
|
|
|
const WmiKey &a_Key ,
|
|
WmiTask <WmiKey> &a_Task
|
|
) ;
|
|
|
|
virtual WmiStatusCode DeQueue (
|
|
|
|
const WmiKey &a_Key ,
|
|
WmiTask <WmiKey> &a_Task
|
|
) ;
|
|
|
|
virtual WmiStatusCode DeQueueAlertable (
|
|
|
|
const WmiKey &a_Key ,
|
|
WmiTask <WmiKey> &a_Task
|
|
) ;
|
|
|
|
virtual WmiStatusCode DeQueueInterruptable (
|
|
|
|
const WmiKey &a_Key ,
|
|
WmiTask <WmiKey> &a_Task
|
|
) ;
|
|
|
|
wchar_t *GetName () { return m_Name ; }
|
|
ULONG GetIdentifier () { return m_Identifier ; }
|
|
HANDLE GetHandle () { return m_Thread ; }
|
|
ULONG GetTimeout () { return m_Timeout ; }
|
|
DWORD GetStackSize () { return m_StackSize ; }
|
|
|
|
void SetTimeout ( const ULONG &a_Timeout ) { m_Timeout = a_Timeout ; }
|
|
void SetStackSize ( const DWORD &a_StackSize ) { m_StackSize = a_StackSize ; }
|
|
|
|
HANDLE GetTerminationEvent () { return m_Terminate ; }
|
|
HANDLE GetQueueChangeEvent () { return m_QueueChange ; }
|
|
|
|
WmiAllocator &GetAllocator () { return m_Allocator ; }
|
|
|
|
static WmiStatusCode Static_Initialize ( WmiAllocator &a_Allocator ) ;
|
|
static WmiStatusCode Static_UnInitialize ( WmiAllocator &a_Allocator ) ;
|
|
|
|
} ;
|
|
|
|
#include <Thread.cpp>
|
|
#include <tpwrap.h>
|
|
|
|
#endif __THREAD_H
|