|
|
/*==========================================================================
* * 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__
|