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.
305 lines
12 KiB
305 lines
12 KiB
/*==========================================================================
|
|
*
|
|
* Copyright (C) 1999-2002 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: ThreadPool.h
|
|
* Content: Functions to manage a thread pool
|
|
*
|
|
* History:
|
|
* Date By Reason
|
|
* ==== == ======
|
|
* 03/01/1999 jtk Derived from Utils.h
|
|
***************************************************************************/
|
|
|
|
#ifndef __THREAD_POOL_H__
|
|
#define __THREAD_POOL_H__
|
|
|
|
//**********************************************************************
|
|
// Constant definitions
|
|
//**********************************************************************
|
|
|
|
//**********************************************************************
|
|
// Macro definitions
|
|
//**********************************************************************
|
|
|
|
//**********************************************************************
|
|
// Structure definitions
|
|
//**********************************************************************
|
|
|
|
//
|
|
// forward class and structure references
|
|
//
|
|
class CSocketPort;
|
|
class CThreadPool;
|
|
|
|
typedef void TIMER_EVENT_CALLBACK( void *const pContext );
|
|
typedef void TIMER_EVENT_COMPLETE( const HRESULT hCompletionCode, void *const pContext );
|
|
|
|
typedef struct _TIMER_OPERATION_ENTRY
|
|
{
|
|
CBilink Linkage; // list links
|
|
void *pContext; // user context passed back in timer events
|
|
|
|
//
|
|
// timer information
|
|
//
|
|
UINT_PTR uRetryCount; // number of times to retry this event
|
|
BOOL fRetryForever; // Boolean for retrying forever
|
|
DWORD dwRetryInterval; // time between enums (milliseconds)
|
|
DWORD dwIdleTimeout; // time at which the command sits idle after all retrys are complete
|
|
BOOL fIdleWaitForever; // Boolean for waiting forever in idle state
|
|
DWORD dwNextRetryTime; // time at which this event will fire next (milliseconds)
|
|
|
|
TIMER_EVENT_CALLBACK *pTimerCallback; // callback for when this event fires
|
|
TIMER_EVENT_COMPLETE *pTimerComplete; // callback for when this event is complete
|
|
|
|
CThreadPool * pThreadPool; // handle to owning thread pool
|
|
PVOID pvTimerData; // cancellable handle to timer, or NULL if not scheduled
|
|
UINT uiTimerUnique; // uniqueness value for timer
|
|
BOOL fCancelling; // boolean denoting whether the timer is cancelling or not
|
|
#ifndef DPNBUILD_ONLYONEPROCESSOR
|
|
DWORD dwCPU; // CPU on which timer is scheduled
|
|
#endif // ! DPNBUILD_ONLYONEPROCESSOR
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "_TIMER_OPERATION_ENTRY::TimerOperationFromLinkage"
|
|
static _TIMER_OPERATION_ENTRY *TimerOperationFromLinkage( CBilink *const pLinkage )
|
|
{
|
|
DNASSERT( pLinkage != NULL );
|
|
DBG_CASSERT( OFFSETOF( _TIMER_OPERATION_ENTRY, Linkage ) == 0 );
|
|
return reinterpret_cast<_TIMER_OPERATION_ENTRY*>( pLinkage );
|
|
}
|
|
|
|
} TIMER_OPERATION_ENTRY;
|
|
|
|
|
|
#ifndef DPNBUILD_ONLYONETHREAD
|
|
|
|
typedef void BLOCKING_JOB_CALLBACK( void *const pvContext );
|
|
|
|
typedef struct _BLOCKING_JOB
|
|
{
|
|
CBilink Linkage; // list links
|
|
void *pvContext; // user context passed back in job callback
|
|
BLOCKING_JOB_CALLBACK *pfnBlockingJobCallback; // callback for when this job is processed
|
|
} BLOCKING_JOB;
|
|
|
|
#endif // ! DPNBUILD_ONLYONETHREAD
|
|
|
|
|
|
//**********************************************************************
|
|
// Variable definitions
|
|
//**********************************************************************
|
|
|
|
//**********************************************************************
|
|
// Function prototypes
|
|
//**********************************************************************
|
|
|
|
typedef BOOL (CSocketPort::*PSOCKET_SERVICE_FUNCTION)( void );
|
|
typedef void DIALOG_FUNCTION( void *const pDialogContext );
|
|
|
|
//
|
|
// functions for managing the timer data pool
|
|
//
|
|
BOOL TimerEntry_Alloc( void *pItem, void* pvContext );
|
|
void TimerEntry_Get( void *pItem, void* pvContext );
|
|
void TimerEntry_Release( void *pItem );
|
|
void TimerEntry_Dealloc( void *pItem );
|
|
|
|
//**********************************************************************
|
|
// Class prototypes
|
|
//**********************************************************************
|
|
|
|
//
|
|
// class for thread pool
|
|
//
|
|
class CThreadPool
|
|
{
|
|
public:
|
|
static BOOL PoolAllocFunction( void* pvItem, void* pvContext );
|
|
static void PoolDeallocFunction( void* pvItem );
|
|
|
|
void Lock( void ) { DNEnterCriticalSection( &m_Lock ); }
|
|
void Unlock( void ) { DNLeaveCriticalSection( &m_Lock ); }
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CThreadPool::AddRef"
|
|
void AddRef( void )
|
|
{
|
|
DNInterlockedIncrement( const_cast<LONG*>(&m_iRefCount) );
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CThreadPool::DecRef"
|
|
void DecRef( void )
|
|
{
|
|
DNASSERT( m_iRefCount != 0 );
|
|
if ( DNInterlockedDecrement( const_cast<LONG*>(&m_iRefCount) ) == 0 )
|
|
{
|
|
Deinitialize();
|
|
g_ThreadPoolPool.Release( this );
|
|
}
|
|
}
|
|
|
|
|
|
HRESULT Initialize( void );
|
|
void Deinitialize( void );
|
|
|
|
#if ((! defined(DPNBUILD_NOWINSOCK2)) && (! defined(DPNBUILD_ONLYWINSOCK2)))
|
|
CReadIOData * GetNewReadIOData(READ_IO_DATA_POOL_CONTEXT * const pContext, const BOOL fNeedOverlapped );
|
|
#else // DPNBUILD_NOWINSOCK2 or DPNBUILD_ONLYWINSOCK2
|
|
CReadIOData * GetNewReadIOData(READ_IO_DATA_POOL_CONTEXT * const pContext);
|
|
#endif // DPNBUILD_NOWINSOCK2 or DPNBUILD_ONLYWINSOCK2
|
|
|
|
static void ReturnReadIOData(CReadIOData *const pReadIOData);
|
|
|
|
#ifndef DPNBUILD_ONLYWINSOCK2
|
|
HRESULT AddSocketPort( CSocketPort *const pSocketPort );
|
|
|
|
void RemoveSocketPort( CSocketPort *const pSocketPort );
|
|
|
|
BOOL CheckWinsock1IO( FD_SET *const pWinsock1Sockets );
|
|
|
|
BOOL ServiceWinsock1Sockets( FD_SET *pSocketSet, PSOCKET_SERVICE_FUNCTION pServiceFunction );
|
|
|
|
static void WINAPI CheckWinsock1IOCallback( void * const pvContext,
|
|
void * const pvTimerData,
|
|
const UINT uiTimerUnique );
|
|
#endif // ! DPNBUILD_ONLYWINSOCK2
|
|
|
|
#ifdef DPNBUILD_ONLYONEPROCESSOR
|
|
HRESULT SubmitDelayedCommand( const PFNDPTNWORKCALLBACK pFunction,
|
|
void *const pContext );
|
|
#else // ! DPNBUILD_ONLYONEPROCESSOR
|
|
HRESULT SubmitDelayedCommand( const DWORD dwCPU,
|
|
const PFNDPTNWORKCALLBACK pFunction,
|
|
void *const pContext );
|
|
#endif // ! DPNBUILD_ONLYONEPROCESSOR
|
|
|
|
static void WINAPI GenericTimerCallback( void * const pvContext,
|
|
void * const pvTimerData,
|
|
const UINT uiTimerUnique );
|
|
|
|
#ifdef DPNBUILD_ONLYONEPROCESSOR
|
|
HRESULT SubmitTimerJob( const BOOL fPerformImmediately,
|
|
const UINT_PTR uRetryCount,
|
|
const BOOL fRetryForever,
|
|
const DWORD dwRetryInterval,
|
|
const BOOL fIdleWaitForever,
|
|
const DWORD dwIdleTimeout,
|
|
TIMER_EVENT_CALLBACK *const pTimerCallbackFunction,
|
|
TIMER_EVENT_COMPLETE *const pTimerCompleteFunction,
|
|
void *const pContext );
|
|
#else // ! DPNBUILD_ONLYONEPROCESSOR
|
|
HRESULT SubmitTimerJob( const DWORD dwCPU,
|
|
const BOOL fPerformImmediately,
|
|
const UINT_PTR uRetryCount,
|
|
const BOOL fRetryForever,
|
|
const DWORD dwRetryInterval,
|
|
const BOOL fIdleWaitForever,
|
|
const DWORD dwIdleTimeout,
|
|
TIMER_EVENT_CALLBACK *const pTimerCallbackFunction,
|
|
TIMER_EVENT_COMPLETE *const pTimerCompleteFunction,
|
|
void *const pContext );
|
|
#endif // ! DPNBUILD_ONLYONEPROCESSOR
|
|
|
|
BOOL StopTimerJob( void *const pContext, const HRESULT hCommandResult );
|
|
|
|
BOOL ModifyTimerJobNextRetryTime( void *const pContext,
|
|
DWORD const dwNextRetryTime );
|
|
|
|
void LockTimerData( void ) { DNEnterCriticalSection( &m_TimerDataLock ); }
|
|
void UnlockTimerData( void ) { DNLeaveCriticalSection( &m_TimerDataLock ); }
|
|
|
|
#ifndef DPNBUILD_ONLYONETHREAD
|
|
HRESULT SubmitBlockingJob( BLOCKING_JOB_CALLBACK *const pfnBlockingJobCallback,
|
|
void *const pvContext );
|
|
|
|
void DoBlockingJobs( void );
|
|
#endif // ! DPNBUILD_ONLYONETHREAD
|
|
|
|
|
|
#ifndef DPNBUILD_NOSPUI
|
|
HRESULT SpawnDialogThread( DIALOG_FUNCTION *const pDialogFunction,
|
|
void *const pDialogContext );
|
|
|
|
static DWORD WINAPI DialogThreadProc( void *pParam );
|
|
#endif // ! DPNBUILD_NOSPUI
|
|
|
|
#ifndef DPNBUILD_ONLYONETHREAD
|
|
LONG GetIntendedThreadCount( void ) const { return m_iIntendedThreadCount; }
|
|
void SetIntendedThreadCount( const LONG iIntendedThreadCount ) { m_iIntendedThreadCount = iIntendedThreadCount; }
|
|
HRESULT GetIOThreadCount( LONG *const piThreadCount );
|
|
HRESULT SetIOThreadCount( const LONG iMaxThreadCount );
|
|
#endif // ! DPNBUILD_ONLYONETHREAD
|
|
BOOL IsThreadCountReductionAllowed( void ) const { return m_fAllowThreadCountReduction; }
|
|
HRESULT PreventThreadPoolReduction( void );
|
|
#if ((! defined(DPNBUILD_NOMULTICAST)) && (defined(WINNT)))
|
|
BOOL EnsureMadcapLoaded( void );
|
|
#endif // ! DPNBUILD_MULTICAST and WINNT
|
|
#ifndef DPNBUILD_NONATHELP
|
|
void EnsureNATHelpLoaded( void );
|
|
#endif // ! DPNBUILD_NONATHELP
|
|
|
|
IDirectPlay8ThreadPoolWork* GetDPThreadPoolWork( void ) const { return m_pDPThreadPoolWork; }
|
|
|
|
#ifndef DPNBUILD_NONATHELP
|
|
BOOL IsNATHelpLoaded( void ) const { return m_fNATHelpLoaded; }
|
|
BOOL IsNATHelpTimerJobSubmitted( void ) const { return m_fNATHelpTimerJobSubmitted; }
|
|
void SetNATHelpTimerJobSubmitted( BOOL fValue ) { m_fNATHelpTimerJobSubmitted = fValue; }
|
|
|
|
void HandleNATHelpUpdate( DWORD * const pdwTimerInterval );
|
|
|
|
static void PerformSubsequentNATHelpGetCaps( void * const pvContext );
|
|
static void NATHelpTimerComplete( const HRESULT hResult, void * const pContext );
|
|
static void NATHelpTimerFunction( void * const pContext );
|
|
#endif // DPNBUILD_NONATHELP
|
|
|
|
#if ((defined(WINNT)) && (! defined(DPNBUILD_NOMULTICAST)))
|
|
BOOL IsMadcapLoaded( void ) const { return m_fMadcapLoaded; }
|
|
#endif // WINNT and not DPNBUILD_NOMULTICAST
|
|
|
|
|
|
private:
|
|
BYTE m_Sig[4]; // debugging signature ('THPL')
|
|
volatile LONG m_iRefCount; // reference count
|
|
IDirectPlay8ThreadPoolWork * m_pDPThreadPoolWork; // pointer to DirectPlay Thread Pool Work interface
|
|
BOOL m_fAllowThreadCountReduction; // boolean indicating that the thread count is locked from being reduced
|
|
#ifndef DPNBUILD_ONLYONETHREAD
|
|
DNCRITICAL_SECTION m_Lock; // local object lock
|
|
LONG m_iIntendedThreadCount; // how many threads will be started
|
|
DNCRITICAL_SECTION m_TimerDataLock; // lock protecting timer data
|
|
#endif // ! DPNBUILD_ONLYONETHREAD
|
|
CBilink m_TimerJobList; // list of current active timer jobs
|
|
#ifndef DPNBUILD_NONATHELP
|
|
BOOL m_fNATHelpLoaded; // boolean indicating whether the NAT Help interface has been loaded
|
|
BOOL m_fNATHelpTimerJobSubmitted; // whether the NAT Help refresh timer has been submitted or not
|
|
DWORD m_dwNATHelpUpdateThreadID; // ID of current thread updating NAT Help status, or 0 if none
|
|
#endif // DPNBUILD_NONATHELP
|
|
#if ((defined(WINNT)) && (! defined(DPNBUILD_NOMULTICAST)))
|
|
BOOL m_fMadcapLoaded; // boolean indicating whether the MADCAP API has been loaded
|
|
#endif // WINNT and not DPNBUILD_NOMULTICAST
|
|
|
|
#ifndef DPNBUILD_ONLYWINSOCK2
|
|
UINT_PTR m_uReservedSocketCount; // count of sockets that are 'reserved' for use
|
|
FD_SET m_SocketSet; // set of all sockets in use
|
|
CSocketPort * m_pSocketPorts[FD_SETSIZE]; // set of corresponding socket ports
|
|
PVOID m_pvTimerDataWinsock1IO; // cancellable handle to Winsock 1 I/O poll timer
|
|
UINT m_uiTimerUniqueWinsock1IO; // uniqueness value for Winsock 1 I/O poll timer
|
|
BOOL m_fCancelWinsock1IO; // whether the Winsock 1 I/O poll timer should be cancelled or not
|
|
#endif // ! DPNBUILD_ONLYWINSOCK2
|
|
|
|
#ifndef DPNBUILD_ONLYONETHREAD
|
|
DNCRITICAL_SECTION m_csBlockingJobLock; // lock protecting blocking job queue information
|
|
CBilink m_blBlockingJobQueue; // queue of blocking jobs
|
|
DNHANDLE m_hBlockingJobThread; // handle to blocking job thread
|
|
DNHANDLE m_hBlockingJobEvent; // handle to event used to signal blocking job thread
|
|
#endif // ! DPNBUILD_ONLYONETHREAD
|
|
};
|
|
|
|
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
|
|
#endif // __THREAD_POOL_H__
|