Leaked source code of windows server 2003
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.
 
 
 
 
 
 

3098 lines
64 KiB

#ifndef __THREAD_CPP
#define __THREAD_CPP
/*++
Copyright (C) 1996-2001 Microsoft Corporation
Module Name:
Thread.cpp
Abstract:
Enhancements to current functionality:
Timeout mechanism should track across waits.
AddRef/Release on task when scheduling.
Enhancement Ticker logic.
History:
--*/
#include <HelperFuncs.h>
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
__TYPENAME WmiThread <WmiKey> :: ThreadContainer *WmiThread <WmiKey> :: s_ThreadContainer = NULL ;
template <class WmiKey>
__TYPENAME WmiThread <WmiKey> :: TaskContainer *WmiThread <WmiKey> :: s_TaskContainer = NULL ;
template <class WmiKey>
CriticalSection WmiThread <WmiKey> :: s_CriticalSection(FALSE) ;
template <class WmiKey>
LONG WmiThread <WmiKey> :: s_InitializeReferenceCount = 0 ;
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: Static_Initialize ( WmiAllocator &a_Allocator )
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
if ( InterlockedIncrement ( & s_InitializeReferenceCount ) == 1 )
{
t_StatusCode = WmiHelper :: InitializeCriticalSection ( & s_CriticalSection ) ;
if ( t_StatusCode == e_StatusCode_Success )
{
if ( s_ThreadContainer == NULL )
{
t_StatusCode = a_Allocator.New (
( void ** ) & s_ThreadContainer ,
sizeof ( ThreadContainer )
) ;
if ( t_StatusCode == e_StatusCode_Success )
{
:: new ( ( void * ) s_ThreadContainer ) WmiThread <WmiKey> :: ThreadContainer ( a_Allocator ) ;
}
}
else
{
}
if ( s_TaskContainer == NULL )
{
t_StatusCode = a_Allocator.New (
( void ** ) & s_TaskContainer ,
sizeof ( TaskContainer )
) ;
if ( t_StatusCode == e_StatusCode_Success )
{
:: new ( ( void * ) s_TaskContainer ) WmiThread <WmiKey> :: TaskContainer ( a_Allocator ) ;
}
}
else
{
}
}
}
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: Static_UnInitialize ( WmiAllocator &a_Allocator )
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
if ( InterlockedDecrement ( & s_InitializeReferenceCount ) == 0 )
{
if ( s_ThreadContainer )
{
s_ThreadContainer->~WmiBasicTree () ;
t_StatusCode = a_Allocator.Delete (
( void * ) s_ThreadContainer
) ;
s_ThreadContainer = NULL ;
}
if ( s_TaskContainer )
{
s_TaskContainer->~WmiBasicTree () ;
t_StatusCode = a_Allocator.Delete (
( void * ) s_TaskContainer
) ;
s_TaskContainer = NULL ;
}
WmiHelper :: DeleteCriticalSection ( & s_CriticalSection );
}
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
ULONG WmiTask <WmiKey> :: AddRef ()
{
return InterlockedIncrement ( & m_ReferenceCount ) ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
ULONG WmiTask <WmiKey> :: Release ()
{
ULONG t_ReferenceCount = InterlockedDecrement ( & m_ReferenceCount ) ;
if ( t_ReferenceCount == 0 )
{
delete this ;
}
return t_ReferenceCount ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiTask <WmiKey> :: WmiTask (
WmiAllocator &a_Allocator ,
const wchar_t *a_Name ,
const wchar_t *a_CompletionName
) : m_Allocator ( a_Allocator ) ,
m_ReferenceCount ( 0 ) ,
m_Event ( NULL ) ,
m_CompletionEvent ( NULL ) ,
m_Name ( NULL ) ,
m_CompletionName ( NULL ) ,
m_InitializationStatusCode ( e_StatusCode_Success ) ,
m_TaskState ( e_WmiTask_UnInitialized )
{
if ( a_Name )
{
m_InitializationStatusCode = WmiHelper :: DuplicateString ( m_Allocator , a_Name , m_Name ) ;
}
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
if ( a_CompletionName )
{
m_InitializationStatusCode = WmiHelper :: DuplicateString ( m_Allocator , a_CompletionName , m_CompletionName ) ;
}
}
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
m_InitializationStatusCode = WmiHelper :: CreateNamedEvent ( m_Name , m_Event ) ;
}
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
m_InitializationStatusCode = WmiHelper :: CreateNamedEvent ( m_CompletionName , m_CompletionEvent ) ;
}
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiTask <WmiKey> :: WmiTask (
WmiAllocator &a_Allocator ,
HANDLE a_Event ,
HANDLE a_CompletionEvent ,
const wchar_t *a_Name ,
const wchar_t *a_CompletionName
) : m_Allocator ( a_Allocator ) ,
m_ReferenceCount ( 0 ) ,
m_Event ( NULL ) ,
m_CompletionEvent ( NULL ) ,
m_Name ( NULL ) ,
m_CompletionName ( NULL ) ,
m_InitializationStatusCode ( e_StatusCode_Success ) ,
m_TaskState ( e_WmiTask_UnInitialized )
{
if ( a_Name )
{
m_InitializationStatusCode = WmiHelper :: DuplicateString ( m_Allocator , a_Name , m_Name ) ;
}
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
if ( a_CompletionName )
{
m_InitializationStatusCode = WmiHelper :: DuplicateString ( m_Allocator , a_CompletionName , m_CompletionName ) ;
}
}
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
if ( a_Event )
{
m_InitializationStatusCode = WmiHelper :: DuplicateHandle ( a_Event , m_Event ) ;
}
}
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
if ( a_CompletionEvent )
{
m_InitializationStatusCode = WmiHelper :: DuplicateHandle ( a_CompletionEvent , m_CompletionEvent ) ;
}
}
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiTask <WmiKey> :: ~WmiTask ()
{
if ( m_Name )
{
m_Allocator.Delete ( ( void * ) m_Name ) ;
}
if ( m_CompletionName )
{
m_Allocator.Delete ( ( void * ) m_CompletionName ) ;
}
if ( m_Event )
{
CloseHandle ( m_Event ) ;
}
if ( m_CompletionEvent )
{
CloseHandle ( m_CompletionEvent ) ;
}
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiTask <WmiKey> :: Initialize ()
{
m_TaskState = e_WmiTask_Initialized ;
return m_InitializationStatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiTask <WmiKey> :: UnInitialize ()
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiTask <WmiKey> :: Process ( WmiThread <WmiKey> &a_Thread )
{
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
return Complete () ;
}
return e_StatusCode_NotInitialized ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiTask <WmiKey> :: Exec ()
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
if ( m_Event )
{
BOOL t_Status = SetEvent ( m_Event ) ;
if ( ! t_Status )
{
t_StatusCode = e_StatusCode_Unknown ;
}
}
}
else
{
t_StatusCode = e_StatusCode_NotInitialized ;
}
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiTask <WmiKey> :: Complete ()
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
BOOL t_Status = SetEvent ( m_CompletionEvent ) ;
if ( ! t_Status )
{
t_StatusCode = e_StatusCode_Unknown ;
}
}
else
{
t_StatusCode = e_StatusCode_NotInitialized ;
}
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiTask <WmiKey> :: Wait ( const ULONG &a_Timeout )
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
t_StatusCode = WmiThread <WmiKey> :: Static_Dispatch (
*this ,
a_Timeout
) ;
}
else
{
t_StatusCode = e_StatusCode_NotInitialized ;
}
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
// call static GetEvents on WmiThread to determine list of tasks to execute.
template <class WmiKey>
WmiStatusCode WmiTask <WmiKey> :: WaitAlertable ( const ULONG &a_Timeout )
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
t_StatusCode = WmiThread <WmiKey> :: Static_AlertableDispatch (
*this ,
a_Timeout
) ;
}
else
{
t_StatusCode = e_StatusCode_NotInitialized ;
}
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiTask <WmiKey> :: WaitInterruptable ( const ULONG &a_Timeout )
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
t_StatusCode = WmiThread <WmiKey> :: Static_InterruptableDispatch (
*this ,
a_Timeout
) ;
}
else
{
t_StatusCode = e_StatusCode_NotInitialized ;
}
return t_StatusCode ;
}
#if 0
"WmiKey" below is non-deducible because the actual supplied
is a nested type [ISO 14.8.2.4 para 4]. I'm moving these operator
functions to class WmiThread<WmiKey>::QueueKey itself.
[TGani]
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
bool operator == ( const typename WmiThread <WmiKey> :: QueueKey &a_Arg1 , const typename WmiThread <WmiKey> :: 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 ;
}
template <class WmiKey>
bool operator < ( const typename WmiThread <WmiKey> :: QueueKey &a_Arg1 , const typename WmiThread <WmiKey> :: 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 ;
}
#endif //0
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: PostShutdown ()
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
SetEvent ( m_Terminate ) ;
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
ULONG WmiThread <WmiKey> :: ThreadProc ( void *a_Thread )
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
WmiThread *t_Thread = ( WmiThread * ) a_Thread ;
if ( t_Thread )
{
t_StatusCode = t_Thread->Initialize_Callback () ;
if ( t_StatusCode == e_StatusCode_Success )
{
SetEvent ( t_Thread->m_Initialized ) ;
t_StatusCode = t_Thread->ThreadDispatch () ;
}
WmiHelper :: EnterCriticalSection ( & s_CriticalSection ) ;
t_StatusCode = t_Thread->UnInitialize_Callback () ;
t_Thread->InternalRelease () ;
WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
}
return ( ULONG ) t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
ULONG WmiThread <WmiKey> :: AddRef ()
{
ULONG t_ReferenceCount = InterlockedIncrement ( & m_ReferenceCount ) ;
if ( t_ReferenceCount == 1 )
{
InternalAddRef () ;
}
return t_ReferenceCount ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
ULONG WmiThread <WmiKey> :: Release ()
{
ULONG t_ReferenceCount = InterlockedDecrement ( & m_ReferenceCount ) ;
if ( t_ReferenceCount == 0 )
{
CallBackRelease () ;
PostShutdown () ;
return InternalRelease () ;
}
else
{
return t_ReferenceCount ;
}
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
ULONG WmiThread <WmiKey> :: InternalAddRef ()
{
return InterlockedIncrement ( & m_InternalReferenceCount ) ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
ULONG WmiThread <WmiKey> :: InternalRelease ()
{
ULONG t_ReferenceCount = InterlockedDecrement ( & m_InternalReferenceCount ) ;
if ( t_ReferenceCount == 0 )
{
WmiStatusCode t_StatusCode = s_ThreadContainer->Delete ( m_Identifier ) ;
delete this ;
return 0 ;
}
else
{
return t_ReferenceCount ;
}
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: CreateThread ()
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
InternalAddRef () ;
m_Thread = :: CreateThread (
NULL ,
m_StackSize ,
( LPTHREAD_START_ROUTINE ) ThreadProc ,
( void * ) this ,
0 ,
& m_Identifier
) ;
if ( m_Thread )
{
ThreadContainerIterator t_Iterator ;
WmiHelper :: EnterCriticalSection ( & s_CriticalSection ) ;
if ( ( t_StatusCode = s_ThreadContainer->Insert ( m_Identifier , this , t_Iterator ) ) == e_StatusCode_Success )
{
}
WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
}
else
{
InternalRelease () ;
t_StatusCode = e_StatusCode_OutOfResources ;
}
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiThread <WmiKey> :: WmiThread (
WmiAllocator &a_Allocator ,
const wchar_t *a_Name ,
ULONG a_Timeout ,
DWORD a_StackSize
) : m_Allocator ( a_Allocator ) ,
m_TaskQueue ( a_Allocator ) ,
m_AlertableTaskQueue ( a_Allocator ) ,
m_InterruptableTaskQueue ( a_Allocator ) ,
m_Thread ( NULL ) ,
m_Initialized ( NULL ) ,
m_Terminate ( NULL ) ,
m_QueueChange ( NULL ) ,
m_Identifier ( 0 ) ,
m_Name ( NULL ) ,
m_Timeout ( a_Timeout ) ,
m_StackSize ( a_StackSize ) ,
m_ReferenceCount ( 0 ) ,
m_InternalReferenceCount ( 0 ) ,
m_InitializationStatusCode ( e_StatusCode_Success ),
m_CriticalSection(NOTHROW_LOCK)
{
m_InitializationStatusCode = WmiHelper :: InitializeCriticalSection ( & m_CriticalSection ) ;
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
m_InitializationStatusCode = m_TaskQueue.Initialize () ;
}
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
m_InitializationStatusCode = m_InterruptableTaskQueue.Initialize () ;
}
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
m_InitializationStatusCode = m_AlertableTaskQueue.Initialize () ;
}
if ( a_Name )
{
m_InitializationStatusCode = WmiHelper :: DuplicateString ( m_Allocator , a_Name , m_Name ) ;
}
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
m_InitializationStatusCode = WmiHelper :: CreateUnNamedEvent ( m_Terminate ) ;
}
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
m_InitializationStatusCode = WmiHelper :: CreateUnNamedEvent ( m_Initialized ) ;
}
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
m_InitializationStatusCode = WmiHelper :: CreateUnNamedEvent ( m_QueueChange ) ;
}
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiThread <WmiKey> :: ~WmiThread ()
{
if ( m_Name )
{
m_Allocator.Delete ( ( void * ) m_Name ) ;
}
if ( m_Initialized )
{
CloseHandle ( m_Initialized ) ;
}
if ( m_Terminate )
{
CloseHandle ( m_Terminate ) ;
}
if ( m_QueueChange )
{
CloseHandle ( m_QueueChange ) ;
}
if ( m_Thread )
{
CloseHandle ( m_Thread ) ;
}
WmiHelper :: DeleteCriticalSection ( & m_CriticalSection ) ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: Initialize ( const ULONG &a_Timeout )
{
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
m_InitializationStatusCode = CreateThread () ;
}
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
ULONG t_Status = WaitForSingleObject ( m_Initialized , a_Timeout ) ;
switch ( t_Status )
{
case WAIT_TIMEOUT:
{
m_InitializationStatusCode = e_StatusCode_Success_Timeout ;
}
break ;
case WAIT_OBJECT_0:
{
m_InitializationStatusCode = e_StatusCode_Success ;
}
break ;
default :
{
m_InitializationStatusCode = e_StatusCode_Unknown ;
}
break ;
}
}
return m_InitializationStatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: UnInitialize ()
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
t_StatusCode = m_TaskQueue.UnInitialize () ;
if ( t_StatusCode == e_StatusCode_Success )
{
t_StatusCode = m_InterruptableTaskQueue.UnInitialize () ;
}
if ( t_StatusCode == e_StatusCode_Success )
{
t_StatusCode = m_AlertableTaskQueue.UnInitialize () ;
}
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: TimedOut ()
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
// 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.
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: EnQueue (
const WmiKey &a_Key ,
WmiTask <WmiKey> &a_Task
)
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
WmiHelper :: EnterCriticalSection ( & s_CriticalSection ) ;
TaskContainerIterator t_Iterator ;
if ( ( t_StatusCode = s_TaskContainer->Insert ( &a_Task , this , t_Iterator ) ) == e_StatusCode_Success )
{
a_Task.SetTaskState ( WmiTask < WmiKey > :: e_WmiTask_EnQueued ) ;
a_Task.AddRef () ;
WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
WmiHelper :: EnterCriticalSection ( & m_CriticalSection ) ;
QueueKey t_QueueKey ( m_Key++ , a_Key ) ;
t_StatusCode = m_TaskQueue.EnQueue ( t_QueueKey , & a_Task ) ;
if ( t_StatusCode == e_StatusCode_Success )
{
a_Task.EnqueueAs ( WmiTask <WmiKey> :: e_WmiTask_Enqueue ) ;
WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
BOOL t_Status = SetEvent ( m_QueueChange ) ;
if ( ! t_Status )
{
t_StatusCode = e_StatusCode_Failed ;
}
}
else
{
WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
WmiHelper :: EnterCriticalSection ( & s_CriticalSection ) ;
t_StatusCode = s_TaskContainer->Delete ( &a_Task ) ;
WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
a_Task.Release () ;
}
}
else
{
WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
}
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: EnQueueAlertable (
const WmiKey &a_Key ,
WmiTask <WmiKey> &a_Task
)
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
WmiHelper :: EnterCriticalSection ( & s_CriticalSection ) ;
TaskContainerIterator t_Iterator ;
if ( ( t_StatusCode = s_TaskContainer->Insert ( &a_Task , this , t_Iterator ) ) == e_StatusCode_Success )
{
a_Task.SetTaskState ( WmiTask < WmiKey > :: e_WmiTask_EnQueued ) ;
a_Task.AddRef () ;
WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
WmiHelper :: EnterCriticalSection ( & m_CriticalSection ) ;
QueueKey t_QueueKey ( m_Key++ , a_Key ) ;
t_StatusCode = m_AlertableTaskQueue.EnQueue ( t_QueueKey , & a_Task ) ;
if ( t_StatusCode == e_StatusCode_Success )
{
a_Task.EnqueueAs ( WmiTask <WmiKey> :: e_WmiTask_EnqueueAlertable ) ;
WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
BOOL t_Status = SetEvent ( m_QueueChange ) ;
if ( ! t_Status )
{
t_StatusCode = e_StatusCode_Failed ;
}
}
else
{
WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
WmiHelper :: EnterCriticalSection ( & s_CriticalSection , TRUE ) ;
t_StatusCode = s_TaskContainer->Delete ( &a_Task ) ;
WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
a_Task.Release () ;
}
}
else
{
WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
}
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
// 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.
//
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: EnQueueInterruptable (
const WmiKey &a_Key ,
WmiTask <WmiKey> &a_Task
)
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
WmiHelper :: EnterCriticalSection ( & s_CriticalSection ) ;
TaskContainerIterator t_Iterator ;
if ( ( t_StatusCode = s_TaskContainer->Insert ( &a_Task , this , t_Iterator ) ) == e_StatusCode_Success )
{
a_Task.SetTaskState ( WmiTask < WmiKey > :: e_WmiTask_EnQueued ) ;
a_Task.AddRef () ;
WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
WmiHelper :: EnterCriticalSection ( & m_CriticalSection ) ;
QueueKey t_QueueKey ( m_Key++ , a_Key ) ;
t_StatusCode = m_InterruptableTaskQueue.EnQueue ( t_QueueKey , & a_Task ) ;
if ( t_StatusCode == e_StatusCode_Success )
{
a_Task.EnqueueAs ( WmiTask <WmiKey> :: e_WmiTask_EnqueueInterruptable ) ;
WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
BOOL t_Status = SetEvent ( m_QueueChange ) ;
if ( ! t_Status )
{
t_StatusCode = e_StatusCode_Failed ;
}
}
else
{
WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
WmiHelper :: EnterCriticalSection ( & s_CriticalSection ) ;
t_StatusCode = s_TaskContainer->Delete ( &a_Task ) ;
WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
a_Task.Release () ;
}
}
else
{
WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
}
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: DeQueue (
const WmiKey &a_Key ,
WmiTask <WmiKey> &a_Task
)
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
a_Task.SetTaskState ( WmiTask < WmiKey > :: e_WmiTask_DeQueued ) ;
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: DeQueueAlertable (
const WmiKey &a_Key ,
WmiTask <WmiKey> &a_Task
)
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
a_Task.SetTaskState ( WmiTask < WmiKey > :: e_WmiTask_DeQueued ) ;
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: DeQueueInterruptable (
const WmiKey &a_Key ,
WmiTask <WmiKey> &a_Task
)
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
a_Task.SetTaskState ( WmiTask < WmiKey > :: e_WmiTask_DeQueued ) ;
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiThread <WmiKey> *WmiThread <WmiKey> :: GetThread ()
{
WmiThread *t_Thread = NULL ;
ULONG t_CurrentThreadId = GetCurrentThreadId () ;
ThreadContainerIterator t_Iterator ;
WmiHelper :: EnterCriticalSection ( & s_CriticalSection ) ;
WmiStatusCode t_StatusCode = s_ThreadContainer->Find ( t_CurrentThreadId , t_Iterator ) ;
if ( t_StatusCode == e_StatusCode_Success )
{
t_Thread = t_Iterator.GetElement () ;
}
WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
return t_Thread ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiThread <WmiKey> *WmiThread <WmiKey> :: GetServicingThread ( WmiTask <WmiKey> &a_Task )
{
WmiThread *t_Thread = NULL ;
TaskContainerIterator t_Iterator ;
WmiHelper :: EnterCriticalSection ( & s_CriticalSection ) ;
WmiStatusCode t_StatusCode = s_TaskContainer->Find ( &a_Task, t_Iterator ) ;
if ( t_StatusCode == e_StatusCode_Success )
{
t_Thread = t_Iterator.GetElement () ;
}
WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
return t_Thread ;
}
/*
Scheduling Action
Task None
Dispatch nothing
On Thread
Wait on Completion
Wait on Thread Termination
Wait on Servicing Thread Termination
Off Thread
Wait on Completion
Wait on Servicing Thread Termination
Task Altertable
Dispatch Alertable Queue
On Thread
MsgWait on Completion
MsgWait on Thread Termination
MsgWait on Servicing Thread Termination
Off Thread
MsgWait on Completion
MsgWait on Servicing Thread Termination
Task Interruptable
Dispatch Alertable Queue
Dispatch Normal Queue
On Thread
MsgWait on Completion
MsgWait on Thread Termination
MsgWait on Servicing Thread Termination
MsgWait on Alertables
Off Thread
MsgWait on Completion
MsgWait on Servicing Thread Termination
Thread Alertable
Dispatch Alertable Queue
Dispatch Normal Queue
MsgWait on Thread Termination
MsgWait on Alertables
*/
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: Static_Dispatch (
WmiTask <WmiKey> &a_Task ,
WmiThread <WmiKey> &a_Thread ,
const ULONG &a_Timeout
)
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
HANDLE t_Handles [ 3 ] ;
t_Handles [ 0 ] = a_Task.GetCompletionEvent () ;
t_Handles [ 1 ] = a_Thread.GetHandle () ;
t_Handles [ 2 ] = a_Thread.GetTerminationEvent () ;
ULONG t_Event = WaitForMultipleObjects (
3 ,
t_Handles ,
FALSE ,
a_Timeout
) ;
switch ( t_Event )
{
case WAIT_TIMEOUT:
{
t_StatusCode = e_StatusCode_Success_Timeout ;
}
break ;
case WAIT_OBJECT_0:
{
t_StatusCode = e_StatusCode_Success ;
}
break ;
case WAIT_OBJECT_0+1:
case WAIT_OBJECT_0+2:
{
t_StatusCode = e_StatusCode_ServicingThreadTerminated ;
#if DBG
DebugBreak();
#endif
}
break ;
case WAIT_FAILED:
{
if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY)
{
t_StatusCode = e_StatusCode_OutOfMemory;
break;
}
}
default:
{
t_StatusCode = e_StatusCode_Unknown ;
#if DBG
DebugBreak();
#endif
}
break ;
}
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: Static_Dispatch (
WmiTask <WmiKey> &a_Task ,
const ULONG &a_Timeout
)
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
WmiThread *t_Thread = GetThread () ;
if ( t_Thread )
{
t_StatusCode = t_Thread->Dispatch ( a_Task , a_Timeout ) ;
}
else
{
WmiThread *t_ServicingThread = GetServicingThread ( a_Task ) ;
if ( t_ServicingThread )
{
t_StatusCode = Static_Dispatch ( a_Task , *t_ServicingThread , a_Timeout ) ;
}
else
{
t_StatusCode = e_StatusCode_Success ;
}
}
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: Dispatch (
WmiTask <WmiKey> &a_Task ,
const ULONG &a_Timeout
)
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
do
{
}
while ( ( t_StatusCode = Wait ( a_Task , a_Timeout ) ) == e_StatusCode_Success ) ;
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: Wait (
WmiTask <WmiKey> &a_Task ,
const ULONG &a_Timeout
)
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
WmiThread *t_ServicingThread = GetServicingThread ( a_Task ) ;
if ( t_ServicingThread )
{
HANDLE t_Handles [ 4 ] ;
t_Handles [ 0 ] = a_Task.GetCompletionEvent () ;
t_Handles [ 1 ] = GetTerminationEvent () ;
t_Handles [ 2 ] = t_ServicingThread->GetHandle () ;
t_Handles [ 3 ] = t_ServicingThread->GetTerminationEvent () ;
ULONG t_Event = WaitForMultipleObjects (
4 ,
t_Handles ,
FALSE ,
a_Timeout
) ;
switch ( t_Event )
{
case WAIT_TIMEOUT:
{
t_StatusCode = e_StatusCode_Success_Timeout ;
}
break ;
case WAIT_OBJECT_0:
{
t_StatusCode = e_StatusCode_Success ;
}
break ;
case WAIT_OBJECT_0+1:
{
t_StatusCode = e_StatusCode_HostingThreadTerminated ;
#if DBG
DebugBreak();
#endif
}
break ;
case WAIT_OBJECT_0+2:
case WAIT_OBJECT_0+3:
{
t_StatusCode = e_StatusCode_ServicingThreadTerminated ;
#if DBG
DebugBreak();
#endif
}
break ;
case WAIT_FAILED:
{
if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY)
{
t_StatusCode = e_StatusCode_OutOfMemory;
break;
}
}
default:
{
t_StatusCode = e_StatusCode_Unknown ;
#if DBG
DebugBreak();
#endif
}
break ;
}
}
else
{
t_StatusCode = e_StatusCode_Success ;
}
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: Static_InterruptableDispatch (
WmiTask <WmiKey> &a_Task ,
WmiThread <WmiKey> &a_Thread ,
const ULONG &a_Timeout
)
{
int sleep_duration = 0;
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
HANDLE t_Handles [ 3 ] ;
t_Handles [ 0 ] = a_Task.GetCompletionEvent () ;
t_Handles [ 1 ] = a_Thread.GetHandle () ;
t_Handles [ 2 ] = a_Thread.GetTerminationEvent () ;
bool t_Continuing = true ;
while ( t_Continuing && t_StatusCode == e_StatusCode_Success )
{
ULONG t_Event = MsgWaitForMultipleObjects (
3 ,
t_Handles ,
FALSE ,
a_Timeout ,
QS_ALLINPUT
) ;
switch ( t_Event )
{
case WAIT_TIMEOUT:
{
t_StatusCode = e_StatusCode_Success_Timeout ;
}
break ;
case WAIT_OBJECT_0:
{
t_StatusCode = e_StatusCode_Success ;
t_Continuing = false ;
}
break ;
case WAIT_OBJECT_0+1:
case WAIT_OBJECT_0+2:
{
t_StatusCode = e_StatusCode_ServicingThreadTerminated ;
#if DBG
DebugBreak();
#endif
}
break ;
case WAIT_OBJECT_0+3:
{
BOOL t_DispatchStatus ;
MSG t_Msg ;
while ( ( t_DispatchStatus = PeekMessage ( & t_Msg , NULL , 0 , 0 , PM_NOREMOVE ) ) == TRUE )
{
if ( ( t_DispatchStatus = GetMessage ( & t_Msg , NULL , 0 , 0 ) ) == TRUE )
{
TranslateMessage ( & t_Msg ) ;
DispatchMessage ( & t_Msg ) ;
}
}
ULONG t_Event = WaitForMultipleObjects (
3 ,
t_Handles ,
FALSE ,
0
) ;
switch ( t_Event )
{
case WAIT_TIMEOUT:
{
t_StatusCode = e_StatusCode_Success_Timeout ;
}
break ;
case WAIT_OBJECT_0:
{
t_StatusCode = e_StatusCode_Success ;
t_Continuing = true ;
}
break ;
case WAIT_OBJECT_0+1:
case WAIT_OBJECT_0+2:
{
t_StatusCode = e_StatusCode_ServicingThreadTerminated ;
#if DBG
DebugBreak();
#endif
}
break ;
case WAIT_FAILED:
{
if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY)
{
Sleep(sleep_duration?10:0);
sleep_duration^=1;
continue;
}
}
default:
{
t_StatusCode = e_StatusCode_Unknown ;
#if DBG
DebugBreak();
#endif
}
break ;
}
}
break ;
case WAIT_FAILED:
{
if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY)
{
Sleep(sleep_duration?10:0);
sleep_duration^=1;
continue;
}
}
default:
{
t_StatusCode = e_StatusCode_Unknown ;
#if DBG
DebugBreak();
#endif
}
break ;
}
}
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: Static_InterruptableDispatch (
WmiTask <WmiKey> &a_Task ,
const ULONG &a_Timeout
)
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
WmiThread *t_Thread = GetThread () ;
if ( t_Thread )
{
t_StatusCode = t_Thread->InterruptableDispatch ( a_Task , a_Timeout ) ;
}
else
{
WmiThread *t_ServicingThread = GetServicingThread ( a_Task ) ;
if ( t_ServicingThread )
{
t_StatusCode = Static_InterruptableDispatch ( a_Task , *t_ServicingThread , a_Timeout ) ;
}
else
{
t_StatusCode = e_StatusCode_Success ;
}
}
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: InterruptableDispatch (
WmiTask <WmiKey> &a_Task ,
const ULONG &a_Timeout
)
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
QueueContainer t_EnQueue ( m_Allocator ) ;
t_StatusCode = t_EnQueue.Initialize () ;
if ( t_StatusCode == e_StatusCode_Success )
{
do
{
do
{
t_StatusCode = Execute ( m_InterruptableTaskQueue , t_EnQueue ) ;
} while ( t_StatusCode == e_StatusCode_Success ) ;
if ( t_StatusCode == e_StatusCode_NotInitialized )
{
WmiHelper :: EnterCriticalSection ( & m_CriticalSection ) ;
t_StatusCode = m_InterruptableTaskQueue.Merge ( t_EnQueue ) ;
WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
if ( t_StatusCode == e_StatusCode_Success )
{
t_StatusCode = InterruptableWait ( a_Task , a_Timeout ) ;
}
}
}
while ( t_StatusCode == e_StatusCode_Success || t_StatusCode == e_StatusCode_Change ) ;
}
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: InterruptableWait (
WmiTask <WmiKey> &a_Task ,
const ULONG &a_Timeout
)
{
int sleep_duration = 0;
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
WmiThread *t_ServicingThread = GetServicingThread ( a_Task ) ;
if ( t_ServicingThread )
{
HANDLE t_Handles [ 5 ] ;
t_Handles [ 0 ] = a_Task.GetCompletionEvent () ;
t_Handles [ 1 ] = GetTerminationEvent () ;
t_Handles [ 2 ] = t_ServicingThread->GetHandle () ;
t_Handles [ 3 ] = t_ServicingThread->GetTerminationEvent () ;
t_Handles [ 4 ] = t_ServicingThread->GetQueueChangeEvent () ;
bool t_Continuing = true ;
while ( t_Continuing && t_StatusCode == e_StatusCode_Success )
{
ULONG t_Event = MsgWaitForMultipleObjects (
5 ,
t_Handles ,
FALSE ,
a_Timeout ,
QS_ALLINPUT
) ;
switch ( t_Event )
{
case WAIT_TIMEOUT:
{
t_StatusCode = e_StatusCode_Success_Timeout ;
}
break ;
case WAIT_OBJECT_0:
{
t_StatusCode = e_StatusCode_Success ;
t_Continuing = false ;
}
break ;
case WAIT_OBJECT_0+1:
{
t_StatusCode = e_StatusCode_HostingThreadTerminated ;
#if DBG
DebugBreak();
#endif
}
break ;
case WAIT_OBJECT_0+2:
case WAIT_OBJECT_0+3:
{
t_StatusCode = e_StatusCode_ServicingThreadTerminated ;
#if DBG
DebugBreak();
#endif
}
break ;
case WAIT_OBJECT_0+4:
{
t_StatusCode = e_StatusCode_Change ;
}
break ;
case WAIT_OBJECT_0+5:
{
BOOL t_DispatchStatus ;
MSG t_Msg ;
while ( ( t_DispatchStatus = PeekMessage ( & t_Msg , NULL , 0 , 0 , PM_NOREMOVE ) ) == TRUE )
{
if ( ( t_DispatchStatus = GetMessage ( & t_Msg , NULL , 0 , 0 ) ) == TRUE )
{
TranslateMessage ( & t_Msg ) ;
DispatchMessage ( & t_Msg ) ;
}
}
ULONG t_Event = WaitForMultipleObjects (
5 ,
t_Handles ,
FALSE ,
0
) ;
switch ( t_Event )
{
case WAIT_TIMEOUT:
{
t_StatusCode = e_StatusCode_Success_Timeout ;
}
break ;
case WAIT_OBJECT_0:
{
t_StatusCode = e_StatusCode_Success ;
t_Continuing = false ;
}
break ;
case WAIT_OBJECT_0+1:
{
t_StatusCode = e_StatusCode_HostingThreadTerminated ;
#if DBG
DebugBreak();
#endif
}
break ;
case WAIT_OBJECT_0+2:
case WAIT_OBJECT_0+3:
{
t_StatusCode = e_StatusCode_ServicingThreadTerminated ;
#if DBG
DebugBreak();
#endif
}
break ;
case WAIT_OBJECT_0+4:
{
t_StatusCode = e_StatusCode_Change ;
}
break ;
case WAIT_FAILED:
{
if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY)
{
Sleep(sleep_duration?10:0);
sleep_duration^=1;
continue;
}
}
default:
{
t_StatusCode = e_StatusCode_Unknown ;
#if DBG
DebugBreak();
#endif
}
break ;
}
}
break ;
case WAIT_FAILED:
{
if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY)
{
Sleep(sleep_duration?10:0);
sleep_duration^=1;
continue;
}
}
default:
{
t_StatusCode = e_StatusCode_Unknown ;
#if DBG
DebugBreak();
#endif
}
break ;
}
}
}
else
{
t_StatusCode = e_StatusCode_Success ;
}
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: Static_AlertableDispatch (
WmiTask <WmiKey> &a_Task ,
WmiThread <WmiKey> &a_Thread ,
const ULONG &a_Timeout
)
{
int sleep_duration = 0;
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
HANDLE t_Handles [ 3 ] ;
t_Handles [ 0 ] = a_Task.GetCompletionEvent () ;
t_Handles [ 1 ] = a_Thread.GetHandle () ;
t_Handles [ 2 ] = a_Thread.GetTerminationEvent () ;
bool t_Continuing = true ;
while ( t_StatusCode == e_StatusCode_Success && t_Continuing )
{
ULONG t_Event = MsgWaitForMultipleObjects (
3 ,
t_Handles ,
FALSE ,
a_Timeout ,
QS_ALLINPUT
) ;
switch ( t_Event )
{
case WAIT_TIMEOUT:
{
t_StatusCode = e_StatusCode_Success_Timeout ;
}
break ;
case WAIT_OBJECT_0:
{
t_StatusCode = e_StatusCode_Success ;
t_Continuing = false ;
}
break ;
case WAIT_OBJECT_0+1:
case WAIT_OBJECT_0+2:
{
t_StatusCode = e_StatusCode_HostingThreadTerminated ;
#if DBG
DebugBreak();
#endif
}
break ;
case WAIT_OBJECT_0+3:
{
BOOL t_DispatchStatus ;
MSG t_Msg ;
while ( ( t_DispatchStatus = PeekMessage ( & t_Msg , NULL , 0 , 0 , PM_NOREMOVE ) ) == TRUE )
{
if ( ( t_DispatchStatus = GetMessage ( & t_Msg , NULL , 0 , 0 ) ) == TRUE )
{
TranslateMessage ( & t_Msg ) ;
DispatchMessage ( & t_Msg ) ;
}
}
ULONG t_Event = WaitForMultipleObjects (
3 ,
t_Handles ,
FALSE ,
0
) ;
switch ( t_Event )
{
case WAIT_TIMEOUT:
{
t_StatusCode = e_StatusCode_Success_Timeout ;
}
break ;
case WAIT_OBJECT_0:
{
t_StatusCode = e_StatusCode_Success ;
t_Continuing = false ;
}
break ;
case WAIT_OBJECT_0+1:
case WAIT_OBJECT_0+2:
{
t_StatusCode = e_StatusCode_ServicingThreadTerminated ;
}
break ;
case WAIT_FAILED:
{
if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY)
{
Sleep(sleep_duration?10:0);
sleep_duration^=1;
continue;
}
}
default:
{
t_StatusCode = e_StatusCode_Unknown ;
#if DBG
DebugBreak();
#endif
}
break ;
}
}
break ;
case WAIT_FAILED:
{
if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY)
{
Sleep(sleep_duration?10:0);
sleep_duration^=1;
continue;
}
}
default:
{
t_StatusCode = e_StatusCode_Unknown ;
#if DBG
DebugBreak();
#endif
}
break ;
}
}
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: Static_AlertableDispatch (
WmiTask <WmiKey> &a_Task ,
const ULONG &a_Timeout
)
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
WmiThread *t_Thread = GetThread () ;
if ( t_Thread )
{
t_StatusCode = t_Thread->AlertableDispatch ( a_Task , a_Timeout ) ;
}
else
{
WmiThread *t_ServicingThread = GetServicingThread ( a_Task ) ;
if ( t_ServicingThread )
{
t_StatusCode = Static_AlertableDispatch ( a_Task , *t_ServicingThread , a_Timeout ) ;
}
else
{
t_StatusCode = e_StatusCode_Success ;
}
}
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: AlertableDispatch (
WmiTask <WmiKey> &a_Task ,
const ULONG &a_Timeout
)
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
QueueContainer t_EnQueue ( m_Allocator ) ;
t_StatusCode = t_EnQueue.Initialize () ;
if ( t_StatusCode == e_StatusCode_Success )
{
do
{
do
{
t_StatusCode = Execute ( m_InterruptableTaskQueue , t_EnQueue ) ;
} while ( t_StatusCode == e_StatusCode_Success ) ;
if ( t_StatusCode == e_StatusCode_NotInitialized )
{
WmiHelper :: EnterCriticalSection ( & m_CriticalSection ) ;
t_StatusCode = m_InterruptableTaskQueue.Merge ( t_EnQueue ) ;
WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
if ( t_StatusCode == e_StatusCode_Success )
{
do
{
t_StatusCode = Execute ( m_TaskQueue , t_EnQueue ) ;
} while ( t_StatusCode == e_StatusCode_Success ) ;
}
}
if ( t_StatusCode == e_StatusCode_NotInitialized )
{
WmiHelper :: EnterCriticalSection ( & m_CriticalSection ) ;
t_StatusCode = m_TaskQueue.Merge ( t_EnQueue ) ;
WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
if ( t_StatusCode == e_StatusCode_Success )
{
t_StatusCode = AlertableWait ( a_Task , a_Timeout ) ;
}
}
}
while ( t_StatusCode == e_StatusCode_Success || t_StatusCode == e_StatusCode_Change ) ;
}
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: Execute ( QueueContainer &a_Queue , QueueContainer &a_EnQueue )
{
QueueKey t_TopKey ;
WmiTask < WmiKey > *t_TopTask ;
WmiHelper :: EnterCriticalSection ( & m_CriticalSection ) ;
WmiStatusCode t_StatusCode = a_Queue.Top ( t_TopKey , t_TopTask ) ;
if ( t_StatusCode == e_StatusCode_Success )
{
t_StatusCode = a_Queue.DeQueue () ;
if ( t_StatusCode == e_StatusCode_Success )
{
WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
if ( t_TopTask->TaskState () == WmiTask < WmiKey > :: e_WmiTask_EnQueued )
{
t_StatusCode = t_TopTask->Process ( *this ) ;
if ( t_StatusCode != e_StatusCode_EnQueue )
{
WmiHelper :: EnterCriticalSection ( & s_CriticalSection ) ;
if ( ( t_StatusCode = s_TaskContainer->Delete ( t_TopTask ) ) == e_StatusCode_NotFound )
{
WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
t_StatusCode = e_StatusCode_Success ;
}
else
{
WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
t_TopTask->Release () ;
}
}
else
{
WmiHelper :: EnterCriticalSection ( & m_CriticalSection ) ;
switch ( t_TopTask->EnqueuedAs () )
{
case WmiTask <WmiKey> :: e_WmiTask_Enqueue:
{
t_StatusCode = a_EnQueue.EnQueue ( t_TopKey , t_TopTask ) ;
}
break ;
case WmiTask <WmiKey> :: e_WmiTask_EnqueueAlertable:
{
t_StatusCode = m_AlertableTaskQueue.EnQueue ( t_TopKey , t_TopTask ) ;
}
break ;
case WmiTask <WmiKey> :: e_WmiTask_EnqueueInterruptable:
{
t_StatusCode = m_InterruptableTaskQueue.EnQueue ( t_TopKey , t_TopTask ) ;
}
break ;
default:
{
}
break ;
}
WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
SetEvent ( m_QueueChange ) ;
}
}
else
{
WmiHelper :: EnterCriticalSection ( & s_CriticalSection ) ;
if ( ( t_StatusCode = s_TaskContainer->Delete ( t_TopTask ) ) == e_StatusCode_NotFound )
{
WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
t_StatusCode = e_StatusCode_Success ;
}
else
{
WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
}
t_TopTask->Complete () ;
t_TopTask->Release () ;
}
}
else
{
WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
}
}
else
{
WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
}
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: ShuffleTask (
const HANDLE &a_Event
)
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
WmiHelper :: EnterCriticalSection ( & m_CriticalSection ) ;
ULONG t_Index = m_AlertableTaskQueue.Size () ;
while ( ( t_StatusCode == e_StatusCode_Success ) && ( t_Index ) )
{
QueueKey t_TopKey ;
WmiTask < WmiKey > *t_TopTask ;
t_StatusCode = m_AlertableTaskQueue.Top ( t_TopKey , t_TopTask ) ;
if ( t_StatusCode == e_StatusCode_Success )
{
t_StatusCode = m_AlertableTaskQueue.DeQueue () ;
if ( t_StatusCode == e_StatusCode_Success )
{
if ( t_TopTask->GetEvent () == a_Event )
{
if ( t_TopTask->TaskState () == WmiTask < WmiKey > :: e_WmiTask_EnQueued )
{
t_StatusCode = m_TaskQueue.EnQueue ( t_TopKey , t_TopTask ) ;
if ( t_StatusCode == e_StatusCode_Success )
{
SetEvent ( m_QueueChange ) ;
break ;
}
}
else
{
WmiHelper :: EnterCriticalSection ( & s_CriticalSection ) ;
if ( ( t_StatusCode = s_TaskContainer->Delete ( t_TopTask ) ) == e_StatusCode_NotFound )
{
WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
t_StatusCode = e_StatusCode_Success ;
}
else
{
WmiHelper :: LeaveCriticalSection ( & s_CriticalSection ) ;
}
t_TopTask->Complete () ;
t_TopTask->Release () ;
}
}
else
{
t_TopKey.SetTick ( m_Key++ ) ;
t_StatusCode = m_AlertableTaskQueue.EnQueue ( t_TopKey , t_TopTask ) ;
if ( t_StatusCode == e_StatusCode_Success )
{
}
}
}
}
t_Index -- ;
}
WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: FillHandleTable (
HANDLE *a_HandleTable ,
ULONG &a_Capacity
)
{
ULONG t_Index = 0 ;
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
WmiHelper :: EnterCriticalSection ( & m_CriticalSection ) ;
QueueContainerIterator t_Iterator ;
t_Iterator = m_AlertableTaskQueue.End () ;
while ( ( t_StatusCode == e_StatusCode_Success ) && ( t_Index < a_Capacity ) && ! t_Iterator.Null () )
{
if ( t_Iterator.GetElement ()->GetEvent () )
{
a_HandleTable [ t_Index ] = t_Iterator.GetElement ()->GetEvent () ;
}
else
{
t_StatusCode = e_StatusCode_InvalidArgs ;
}
t_Iterator.Decrement () ;
t_Index ++ ;
}
if ( t_StatusCode == e_StatusCode_NotInitialized )
{
t_StatusCode = e_StatusCode_Success ;
}
a_Capacity = t_Index ;
WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: AlertableWait (
WmiTask <WmiKey> &a_Task ,
const ULONG &a_Timeout
)
{
int sleep_duration = 0;
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
WmiThread *t_ServicingThread = GetServicingThread ( a_Task ) ;
if ( t_ServicingThread )
{
HANDLE t_Handles [ MAXIMUM_WAIT_OBJECTS - 1 ] ;
t_Handles [ 0 ] = a_Task.GetCompletionEvent () ;
t_Handles [ 1 ] = GetTerminationEvent () ;
t_Handles [ 2 ] = t_ServicingThread->GetHandle () ;
t_Handles [ 3 ] = t_ServicingThread->GetTerminationEvent () ;
t_Handles [ 4 ] = t_ServicingThread->GetQueueChangeEvent () ;
ULONG t_Capacity = MAXIMUM_WAIT_OBJECTS - 6 ;
t_StatusCode = FillHandleTable ( & t_Handles [ 5 ] , t_Capacity ) ;
bool t_Continuing = true ;
while ( t_Continuing && t_StatusCode == e_StatusCode_Success )
{
ULONG t_Event = MsgWaitForMultipleObjects (
5 + t_Capacity ,
t_Handles ,
FALSE ,
a_Timeout ,
QS_ALLINPUT
) ;
switch ( t_Event )
{
case WAIT_TIMEOUT:
{
t_StatusCode = e_StatusCode_Success_Timeout ;
}
break ;
case WAIT_OBJECT_0:
{
t_StatusCode = e_StatusCode_Success ;
t_Continuing = false ;
}
break ;
case WAIT_OBJECT_0+1:
{
t_StatusCode = e_StatusCode_HostingThreadTerminated ;
#if DBG
DebugBreak();
#endif
}
break ;
case WAIT_OBJECT_0+2:
case WAIT_OBJECT_0+3:
{
t_StatusCode = e_StatusCode_ServicingThreadTerminated ;
#if DBG
DebugBreak();
#endif
}
break ;
case WAIT_OBJECT_0+4:
{
t_StatusCode = e_StatusCode_Change ;
}
break ;
case WAIT_FAILED:
{
if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY)
{
Sleep(sleep_duration?10:0);
sleep_duration^=1;
continue;
}
}
default:
{
if ( t_Event == t_Capacity + 5 )
{
BOOL t_DispatchStatus ;
MSG t_Msg ;
while ( ( t_DispatchStatus = PeekMessage ( & t_Msg , NULL , 0 , 0 , PM_NOREMOVE ) ) == TRUE )
{
if ( ( t_DispatchStatus = GetMessage ( & t_Msg , NULL , 0 , 0 ) ) == TRUE )
{
TranslateMessage ( & t_Msg ) ;
DispatchMessage ( & t_Msg ) ;
}
}
ULONG t_Event = WaitForMultipleObjects (
5 + t_Capacity ,
t_Handles ,
FALSE ,
0
) ;
switch ( t_Event )
{
case WAIT_TIMEOUT:
{
t_StatusCode = e_StatusCode_Success_Timeout ;
}
break ;
case WAIT_OBJECT_0:
{
t_StatusCode = e_StatusCode_Success ;
t_Continuing = false ;
}
break ;
case WAIT_OBJECT_0+1:
{
t_StatusCode = e_StatusCode_HostingThreadTerminated ;
#if DBG
DebugBreak();
#endif
}
break ;
case WAIT_OBJECT_0+2:
case WAIT_OBJECT_0+3:
{
t_StatusCode = e_StatusCode_ServicingThreadTerminated ;
#if DBG
DebugBreak();
#endif
}
break ;
case WAIT_OBJECT_0+4:
{
t_StatusCode = e_StatusCode_Change ;
}
break ;
case WAIT_FAILED:
{
if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY)
{
Sleep(sleep_duration?10:0);
sleep_duration^=1;
continue;
}
}
default:
{
if ( t_Event < t_Capacity + 5 )
{
t_StatusCode = ShuffleTask ( t_Handles [ t_Event ] ) ;
}
else
{
t_StatusCode = e_StatusCode_InvalidArgs ;
#if DBG
DebugBreak();
#endif
}
}
}
}
else if ( t_Event < t_Capacity + 5 )
{
t_StatusCode = ShuffleTask ( t_Handles [ t_Event ] ) ;
}
else
{
t_StatusCode = e_StatusCode_InvalidArgs ;
#if DBG
DebugBreak();
#endif
}
}
break ;
}
}
}
else
{
t_StatusCode = e_StatusCode_Success ;
}
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: ThreadDispatch ()
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
QueueContainer t_EnQueue ( m_Allocator ) ;
t_StatusCode = t_EnQueue.Initialize () ;
if ( t_StatusCode == e_StatusCode_Success )
{
do
{
do
{
t_StatusCode = Execute ( m_InterruptableTaskQueue , t_EnQueue ) ;
} while ( t_StatusCode == e_StatusCode_Success ) ;
if ( t_StatusCode == e_StatusCode_NotInitialized )
{
WmiHelper :: EnterCriticalSection ( & m_CriticalSection ) ;
t_StatusCode = m_InterruptableTaskQueue.Merge ( t_EnQueue ) ;
WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
if ( t_StatusCode == e_StatusCode_Success )
{
do
{
t_StatusCode = Execute ( m_TaskQueue , t_EnQueue ) ;
} while ( t_StatusCode == e_StatusCode_Success ) ;
}
}
if ( t_StatusCode == e_StatusCode_NotInitialized )
{
WmiHelper :: EnterCriticalSection ( & m_CriticalSection ) ;
t_StatusCode = m_TaskQueue.Merge ( t_EnQueue ) ;
WmiHelper :: LeaveCriticalSection ( & m_CriticalSection ) ;
if ( t_StatusCode == e_StatusCode_Success )
{
t_StatusCode = ThreadWait () ;
}
}
}
while ( t_StatusCode == e_StatusCode_Success || t_StatusCode == e_StatusCode_Change ) ;
}
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
template <class WmiKey>
WmiStatusCode WmiThread <WmiKey> :: ThreadWait ()
{
int sleep_duration = 0;
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
HANDLE t_Handles [ MAXIMUM_WAIT_OBJECTS - 1 ] ;
t_Handles [ 0 ] = GetTerminationEvent () ;
t_Handles [ 1 ] = GetQueueChangeEvent () ;
ULONG t_Capacity = MAXIMUM_WAIT_OBJECTS - 3 ;
t_StatusCode = FillHandleTable ( & t_Handles [ 2 ] , t_Capacity ) ;
bool t_Continuing = true ;
while ( t_Continuing && t_StatusCode == e_StatusCode_Success )
{
ULONG t_Event = MsgWaitForMultipleObjectsEx (
2 + t_Capacity ,
t_Handles ,
m_Timeout ,
QS_ALLINPUT ,
MWMO_ALERTABLE
) ;
switch ( t_Event )
{
case WAIT_TIMEOUT:
{
t_StatusCode = TimedOut () ;
}
break ;
case WAIT_OBJECT_0:
{
t_StatusCode = e_StatusCode_HostingThreadTerminated ;
#if DBG
OutputDebugStringA ("\nWmiThread - Thread Terminating") ;
#endif
}
break ;
case WAIT_OBJECT_0+1:
{
t_StatusCode = e_StatusCode_Change ;
}
break ;
case WAIT_IO_COMPLETION:
{
t_StatusCode = e_StatusCode_Success;
}
break ;
case WAIT_FAILED:
{
if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY)
{
Sleep(sleep_duration?10:0);
sleep_duration^=1;
continue;
}
}
default:
{
if ( t_Event == t_Capacity + 2 )
{
BOOL t_DispatchStatus ;
MSG t_Msg ;
while ( ( t_DispatchStatus = PeekMessage ( & t_Msg , NULL , 0 , 0 , PM_NOREMOVE ) ) == TRUE )
{
if ( ( t_DispatchStatus = GetMessage ( & t_Msg , NULL , 0 , 0 ) ) == TRUE )
{
TranslateMessage ( & t_Msg ) ;
DispatchMessage ( & t_Msg ) ;
}
}
ULONG t_Event = WaitForMultipleObjects (
2 + t_Capacity ,
t_Handles ,
FALSE ,
0
) ;
switch ( t_Event )
{
case WAIT_TIMEOUT:
{
t_StatusCode = TimedOut () ;
}
break ;
case WAIT_OBJECT_0:
{
t_StatusCode = e_StatusCode_HostingThreadTerminated ;
#if DBG
OutputDebugStringA ( "\nWmiThread - Thread Terminating") ;
#endif
}
break ;
case WAIT_OBJECT_0+1:
{
t_StatusCode = e_StatusCode_Change ;
}
break ;
case WAIT_FAILED:
{
if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY)
{
Sleep(sleep_duration?10:0);
sleep_duration^=1;
continue;
}
}
default:
{
if ( t_Event < t_Capacity + 2 )
{
t_StatusCode = ShuffleTask ( t_Handles [ t_Event ] ) ;
}
else
{
t_StatusCode = e_StatusCode_InvalidArgs ;
#if DBG
DebugBreak();
#endif
}
}
}
}
else if ( t_Event < t_Capacity + 2 )
{
t_StatusCode = ShuffleTask ( t_Handles [ t_Event ] ) ;
}
else
{
t_StatusCode = e_StatusCode_InvalidArgs ;
#if DBG
DebugBreak();
#endif
}
}
break ;
}
}
return t_StatusCode ;
}
#endif __THREAD_CPP