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.
1258 lines
35 KiB
1258 lines
35 KiB
/******************************************************************************
|
|
*
|
|
* Copyright (C) 2001-2002 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: threadpoolclassfac.cpp
|
|
*
|
|
* Content: DirectPlay Thread Pool class factory functions.
|
|
*
|
|
* History:
|
|
* Date By Reason
|
|
* ======== ======== =========
|
|
* 11/02/01 VanceO Created.
|
|
*
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
#include "dpnthreadpooli.h"
|
|
|
|
|
|
|
|
//=============================================================================
|
|
// Function type definitions
|
|
//=============================================================================
|
|
#ifndef DPNBUILD_LIBINTERFACE
|
|
typedef STDMETHODIMP UnknownQueryInterface(IUnknown * pInterface, REFIID riid, LPVOID *ppvObj);
|
|
typedef STDMETHODIMP_(ULONG) UnknownAddRef(IUnknown * pInterface);
|
|
typedef STDMETHODIMP_(ULONG) UnknownRelease(IUnknown * pInterface);
|
|
#endif // ! DPNBUILD_LIBINTERFACE
|
|
|
|
#ifndef DPNBUILD_ONLYONETHREAD
|
|
typedef STDMETHODIMP ThreadPoolQueryInterface(IDirectPlay8ThreadPool * pInterface, DP8REFIID riid, LPVOID *ppvObj);
|
|
typedef STDMETHODIMP_(ULONG) ThreadPoolAddRef(IDirectPlay8ThreadPool * pInterface);
|
|
typedef STDMETHODIMP_(ULONG) ThreadPoolRelease(IDirectPlay8ThreadPool * pInterface);
|
|
#endif // ! DPNBUILD_ONLYONETHREAD
|
|
|
|
#if ((! defined(DPNBUILD_LIBINTERFACE)) || (! defined(DPNBUILD_ONLYONETHREAD)) || (defined(DPNBUILD_MULTIPLETHREADPOOLS)))
|
|
typedef STDMETHODIMP ThreadPoolWorkQueryInterface(IDirectPlay8ThreadPoolWork * pInterface, DP8REFIID riid, LPVOID *ppvObj);
|
|
typedef STDMETHODIMP_(ULONG) ThreadPoolWorkAddRef(IDirectPlay8ThreadPoolWork * pInterface);
|
|
typedef STDMETHODIMP_(ULONG) ThreadPoolWorkRelease(IDirectPlay8ThreadPoolWork * pInterface);
|
|
#endif // ! DPNBUILD_LIBINTERFACE or ! DPNBUILD_ONLYONETHREAD or DPNBUILD_MULTIPLETHREADPOOLS
|
|
|
|
|
|
|
|
|
|
//=============================================================================
|
|
// Function Prototypes
|
|
//=============================================================================
|
|
#ifndef DPNBUILD_LIBINTERFACE
|
|
STDMETHODIMP DPTPCF_CreateInstance(IClassFactory * pInterface, LPUNKNOWN lpUnkOuter, REFIID riid, LPVOID * ppv);
|
|
|
|
HRESULT DPTPCF_CreateInterface(OBJECT_DATA * pObject,
|
|
REFIID riid,
|
|
INTERFACE_LIST ** const ppv);
|
|
|
|
HRESULT DPTPCF_CreateObject(IClassFactory * pInterface, LPVOID * ppv, REFIID riid);
|
|
#endif // ! DPNBUILD_LIBINTERFACE
|
|
|
|
HRESULT DPTPCF_FreeObject(PVOID pvObject);
|
|
|
|
#ifndef DPNBUILD_LIBINTERFACE
|
|
INTERFACE_LIST * DPTPCF_FindInterface(void * pvInterface,
|
|
REFIID riid);
|
|
#endif // ! DPNBUILD_LIBINTERFACE
|
|
|
|
#if ((! defined(DPNBUILD_LIBINTERFACE)) || (! defined(DPNBUILD_ONLYONETHREAD) )|| (defined(DPNBUILD_MULTIPLETHREADPOOLS)))
|
|
STDMETHODIMP DPTP_QueryInterface(void * pvInterface,
|
|
DP8REFIID riid,
|
|
void ** ppv);
|
|
|
|
STDMETHODIMP_(ULONG) DPTP_AddRef(void * pvInterface);
|
|
|
|
STDMETHODIMP_(ULONG) DPTP_Release(void * pvInterface);
|
|
#endif // ! DPNBUILD_LIBINTERFACE or ! DPNBUILD_ONLYONETHREAD or DPNBUILD_MULTIPLETHREADPOOLS
|
|
|
|
|
|
|
|
|
|
//=============================================================================
|
|
// External globals
|
|
//=============================================================================
|
|
#ifndef DPNBUILD_LIBINTERFACE
|
|
IUnknownVtbl DPTP_UnknownVtbl =
|
|
{
|
|
(UnknownQueryInterface*) DPTP_QueryInterface,
|
|
(UnknownAddRef*) DPTP_AddRef,
|
|
(UnknownRelease*) DPTP_Release
|
|
};
|
|
#endif // ! DPNBUILD_LIBINTERFACE
|
|
|
|
#ifndef DPNBUILD_ONLYONETHREAD
|
|
IDirectPlay8ThreadPoolVtbl DPTP_Vtbl =
|
|
{
|
|
(ThreadPoolQueryInterface*) DPTP_QueryInterface,
|
|
(ThreadPoolAddRef*) DPTP_AddRef,
|
|
(ThreadPoolRelease*) DPTP_Release,
|
|
DPTP_Initialize,
|
|
DPTP_Close,
|
|
DPTP_GetThreadCount,
|
|
DPTP_SetThreadCount,
|
|
DPTP_DoWork,
|
|
};
|
|
#endif // ! DPNBUILD_ONLYONETHREAD
|
|
|
|
IDirectPlay8ThreadPoolWorkVtbl DPTPW_Vtbl =
|
|
{
|
|
#if ((! defined(DPNBUILD_LIBINTERFACE)) || (! defined(DPNBUILD_ONLYONETHREAD)) || (defined(DPNBUILD_MULTIPLETHREADPOOLS)))
|
|
(ThreadPoolWorkQueryInterface*) DPTP_QueryInterface,
|
|
(ThreadPoolWorkAddRef*) DPTP_AddRef,
|
|
(ThreadPoolWorkRelease*) DPTP_Release,
|
|
#endif // ! DPNBUILD_LIBINTERFACE or ! DPNBUILD_ONLYONETHREAD or DPNBUILD_MULTIPLETHREADPOOLS
|
|
DPTPW_QueueWorkItem,
|
|
DPTPW_ScheduleTimer,
|
|
DPTPW_StartTrackingFileIo,
|
|
DPTPW_StopTrackingFileIo,
|
|
DPTPW_CreateOverlapped,
|
|
DPTPW_SubmitIoOperation,
|
|
DPTPW_ReleaseOverlapped,
|
|
DPTPW_CancelTimer,
|
|
DPTPW_ResetCompletingTimer,
|
|
DPTPW_WaitWhileWorking,
|
|
DPTPW_SleepWhileWorking,
|
|
DPTPW_RequestTotalThreadCount,
|
|
DPTPW_GetThreadCount,
|
|
DPTPW_GetWorkRecursionDepth,
|
|
DPTPW_Preallocate,
|
|
#ifdef DPNBUILD_MANDATORYTHREADS
|
|
DPTPW_CreateMandatoryThread,
|
|
#endif // DPNBUILD_MANDATORYTHREADS
|
|
};
|
|
|
|
#ifndef DPNBUILD_LIBINTERFACE
|
|
IClassFactoryVtbl DPTPCF_Vtbl =
|
|
{
|
|
DPCF_QueryInterface, // dplay8\common\classfactory.cpp will implement the rest of these
|
|
DPCF_AddRef,
|
|
DPCF_Release,
|
|
DPTPCF_CreateInstance,
|
|
DPCF_LockServer
|
|
};
|
|
|
|
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DPTPCF_CreateInstance"
|
|
//=============================================================================
|
|
// DPTPCF_CreateInstance
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Description: Creates a new thread pool object COM instance.
|
|
//
|
|
// Arguments:
|
|
// IClassFactory * pInterface - ?
|
|
// LPUNKNOWN lpUnkOuter - ?
|
|
// REFIID riid - ?
|
|
// LPVOID * ppv - ?
|
|
//
|
|
// Returns: HRESULT
|
|
//=============================================================================
|
|
STDMETHODIMP DPTPCF_CreateInstance(IClassFactory * pInterface, LPUNKNOWN lpUnkOuter, REFIID riid, LPVOID * ppv)
|
|
{
|
|
HRESULT hResultCode;
|
|
INTERFACE_LIST *pIntList;
|
|
OBJECT_DATA *pObjectData;
|
|
|
|
DPFX(DPFPREP, 6,"Parameters: pInterface [%p], lpUnkOuter [%p], riid [%p], ppv [%p]",pInterface,lpUnkOuter,&riid,ppv);
|
|
|
|
if (pInterface == NULL)
|
|
{
|
|
DPFERR("Invalid COM interface specified");
|
|
hResultCode = E_INVALIDARG;
|
|
goto Exit;
|
|
}
|
|
if (lpUnkOuter != NULL)
|
|
{
|
|
hResultCode = CLASS_E_NOAGGREGATION;
|
|
goto Exit;
|
|
}
|
|
if (ppv == NULL)
|
|
{
|
|
DPFERR("Invalid target interface pointer specified");
|
|
hResultCode = E_INVALIDARG;
|
|
goto Exit;
|
|
}
|
|
|
|
pObjectData = NULL;
|
|
pIntList = NULL;
|
|
|
|
if ((pObjectData = static_cast<OBJECT_DATA*>(DNMalloc(sizeof(OBJECT_DATA)))) == NULL)
|
|
{
|
|
DPFERR("Could not allocate object");
|
|
hResultCode = E_OUTOFMEMORY;
|
|
goto Failure;
|
|
}
|
|
|
|
// Object creation and initialization
|
|
if ((hResultCode = DPTPCF_CreateObject(pInterface, &pObjectData->pvData,riid)) != S_OK)
|
|
{
|
|
DPFERR("Could not create object");
|
|
goto Failure;
|
|
}
|
|
DPFX(DPFPREP, 7,"Created and initialized object");
|
|
|
|
// Get requested interface
|
|
if ((hResultCode = DPTPCF_CreateInterface(pObjectData,riid,&pIntList)) != S_OK)
|
|
{
|
|
DPTPCF_FreeObject(pObjectData->pvData);
|
|
goto Failure;
|
|
}
|
|
DPFX(DPFPREP, 7,"Found interface");
|
|
|
|
pObjectData->pIntList = pIntList;
|
|
pObjectData->lRefCount = 1;
|
|
DPTP_AddRef( pIntList );
|
|
DNInterlockedIncrement(&g_lDPTPInterfaceCount);
|
|
*ppv = pIntList;
|
|
|
|
DPFX(DPFPREP, 7,"*ppv = [0x%p]",*ppv);
|
|
hResultCode = S_OK;
|
|
|
|
Exit:
|
|
DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
|
|
return(hResultCode);
|
|
|
|
Failure:
|
|
if (pObjectData)
|
|
{
|
|
DNFree(pObjectData);
|
|
pObjectData = NULL;
|
|
}
|
|
goto Exit;
|
|
} // DPTPCF_CreateInstance
|
|
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DPTPCF_CreateInterface"
|
|
//=============================================================================
|
|
// DPTPCF_CreateInterface
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Description: Creates a new thread pool object interface.
|
|
//
|
|
// Arguments:
|
|
// OBJECT_DATA * pObject - ?
|
|
// REFIID riid - ?
|
|
// INTERFACE_LIST ** ppv - ?
|
|
//
|
|
// Returns: HRESULT
|
|
//=============================================================================
|
|
HRESULT DPTPCF_CreateInterface(OBJECT_DATA * pObject,
|
|
REFIID riid,
|
|
INTERFACE_LIST ** const ppv)
|
|
{
|
|
INTERFACE_LIST *pIntNew;
|
|
PVOID lpVtbl;
|
|
HRESULT hResultCode;
|
|
|
|
DPFX(DPFPREP, 6,"Parameters: pObject [%p], riid [%p], ppv [%p]",pObject,&riid,ppv);
|
|
|
|
DNASSERT(pObject != NULL);
|
|
DNASSERT(ppv != NULL);
|
|
|
|
const DPTHREADPOOLOBJECT* pDPTPObject = ((DPTHREADPOOLOBJECT *)pObject->pvData);
|
|
|
|
if (IsEqualIID(riid,IID_IUnknown))
|
|
{
|
|
DPFX(DPFPREP, 7,"riid = IID_IUnknown");
|
|
lpVtbl = &DPTP_UnknownVtbl;
|
|
}
|
|
else if (IsEqualIID(riid,IID_IDirectPlay8ThreadPool))
|
|
{
|
|
DPFX(DPFPREP, 7,"riid = IID_IDirectPlay8ThreadPool");
|
|
lpVtbl = &DPTP_Vtbl;
|
|
}
|
|
else if (IsEqualIID(riid,IID_IDirectPlay8ThreadPoolWork))
|
|
{
|
|
DPFX(DPFPREP, 7,"riid = IID_IDirectPlay8ThreadPoolWork");
|
|
lpVtbl = &DPTPW_Vtbl;
|
|
}
|
|
else
|
|
{
|
|
DPFERR("riid not found !");
|
|
hResultCode = E_NOINTERFACE;
|
|
goto Exit;
|
|
}
|
|
|
|
if ((pIntNew = static_cast<INTERFACE_LIST*>(DNMalloc(sizeof(INTERFACE_LIST)))) == NULL)
|
|
{
|
|
DPFERR("Could not allocate interface");
|
|
hResultCode = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
pIntNew->lpVtbl = lpVtbl;
|
|
pIntNew->lRefCount = 0;
|
|
pIntNew->pIntNext = NULL;
|
|
DBG_CASSERT( sizeof( pIntNew->iid ) == sizeof( riid ) );
|
|
memcpy( &(pIntNew->iid), &riid, sizeof( pIntNew->iid ) );
|
|
pIntNew->pObject = pObject;
|
|
|
|
*ppv = pIntNew;
|
|
DPFX(DPFPREP, 7,"*ppv = [0x%p]",*ppv);
|
|
|
|
hResultCode = S_OK;
|
|
|
|
Exit:
|
|
DPFX(DPFPREP, 6,"Returning: hResultCode = [%lx]",hResultCode);
|
|
return(hResultCode);
|
|
} // DPTPCF_CreateInterface
|
|
|
|
#endif // ! DPNBUILD_LIBINTERFACE
|
|
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DPTPCF_CreateObject"
|
|
//=============================================================================
|
|
// DPTPCF_CreateObject
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Description: Creates a new thread pool object.
|
|
//
|
|
// Arguments:
|
|
// IClassFactory * pInterface - ?
|
|
// PVOID * ppv - ?
|
|
// REFIID riid - ?
|
|
//
|
|
// Returns: HRESULT
|
|
//=============================================================================
|
|
#ifdef DPNBUILD_LIBINTERFACE
|
|
HRESULT DPTPCF_CreateObject(PVOID * ppv)
|
|
#else // ! DPNBUILD_LIBINTERFACE
|
|
HRESULT DPTPCF_CreateObject(IClassFactory * pInterface, PVOID * ppv, REFIID riid)
|
|
#endif // ! DPNBUILD_LIBINTERFACE
|
|
{
|
|
HRESULT hr;
|
|
DPTHREADPOOLOBJECT * pDPTPObject = NULL;
|
|
#ifndef DPNBUILD_LIBINTERFACE
|
|
const _IDirectPlayClassFactory * pDPClassFactory = (_IDirectPlayClassFactory*) pInterface;
|
|
#endif // ! DPNBUILD_LIBINTERFACE
|
|
BOOL fHaveGlobalThreadPoolLock = FALSE;
|
|
BOOL fInittedLock = FALSE;
|
|
#ifdef DPNBUILD_ONLYONEPROCESSOR
|
|
BOOL fInittedWorkQueue = FALSE;
|
|
#else // ! DPNBUILD_ONLYONEPROCESSOR
|
|
SYSTEM_INFO SystemInfo;
|
|
DWORD dwTemp;
|
|
#endif // ! DPNBUILD_ONLYONEPROCESSOR
|
|
#ifndef DPNBUILD_ONLYONETHREAD
|
|
DWORD dwWorkerThreadTlsIndex = -1;
|
|
#ifdef DBG
|
|
DWORD dwError;
|
|
#endif // DBG
|
|
#endif // ! DPNBUILD_ONLYONETHREAD
|
|
|
|
|
|
#ifndef DPNBUILD_LIBINTERFACE
|
|
if ((riid != IID_IDirectPlay8ThreadPool) &&
|
|
(riid != IID_IDirectPlay8ThreadPoolWork))
|
|
{
|
|
DPFX(DPFPREP, 0, "Requesting unknown interface from thread pool CLSID!");
|
|
hr = E_NOINTERFACE;
|
|
goto Failure;
|
|
}
|
|
#endif // ! DPNBUILD_LIBINTERFACE
|
|
|
|
|
|
#ifndef DPNBUILD_MULTIPLETHREADPOOLS
|
|
//
|
|
// See if we've already allocated a thread pool object, because you only
|
|
// get one per process.
|
|
//
|
|
DNEnterCriticalSection(&g_csGlobalThreadPoolLock);
|
|
fHaveGlobalThreadPoolLock = TRUE;
|
|
|
|
#if ((defined(DPNBUILD_LIBINTERFACE)) && (defined(DPNBUILD_ONLYONETHREAD)))
|
|
DNASSERT(g_pDPTPObject == NULL);
|
|
#else // ! DPNBUILD_LIBINTERFACE or ! DPNBUILD_ONLYONETHREAD
|
|
if (g_pDPTPObject != NULL)
|
|
{
|
|
LONG lRefCount;
|
|
|
|
|
|
#ifdef DPNBUILD_LIBINTERFACE
|
|
DNASSERT(g_pDPTPObject->lRefCount >= 0);
|
|
lRefCount = DNInterlockedIncrement(&g_pDPTPObject->lRefCount);
|
|
#else // ! DPNBUILD_LIBINTERFACE
|
|
lRefCount = ++g_dwDPTPRefCount;
|
|
#endif // ! DPNBUILD_LIBINTERFACE
|
|
DPFX(DPFPREP, 1, "Global thread pool object 0x%p already exists, ref count now %u.",
|
|
g_pDPTPObject, lRefCount);
|
|
(*ppv) = g_pDPTPObject;
|
|
hr = S_OK;
|
|
goto Exit;
|
|
}
|
|
#endif // ! DPNBUILD_LIBINTERFACE or ! DPNBUILD_ONLYONETHREAD
|
|
#endif // ! DPNBUILD_MULTIPLETHREADPOOLS
|
|
|
|
pDPTPObject = (DPTHREADPOOLOBJECT*) DNMalloc(sizeof(DPTHREADPOOLOBJECT));
|
|
if (pDPTPObject == NULL)
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't allocate memory for thread pool object!");
|
|
hr = E_OUTOFMEMORY;
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// Zero out the entire structure to start.
|
|
//
|
|
memset(pDPTPObject, 0, sizeof(DPTHREADPOOLOBJECT));
|
|
|
|
pDPTPObject->Sig[0] = 'D';
|
|
pDPTPObject->Sig[1] = 'P';
|
|
pDPTPObject->Sig[2] = 'T';
|
|
pDPTPObject->Sig[3] = 'P';
|
|
|
|
|
|
#ifndef DPNBUILD_NOPARAMVAL
|
|
//
|
|
// Start by assuming the user will want parameter validation.
|
|
//
|
|
pDPTPObject->dwFlags = DPTPOBJECTFLAG_USER_PARAMVALIDATION;
|
|
#endif // ! DPNBUILD_NOPARAMVAL
|
|
|
|
|
|
#ifndef DPNBUILD_ONLYONEPROCESSOR
|
|
GetSystemInfo(&SystemInfo);
|
|
pDPTPObject->dwNumCPUs = SystemInfo.dwNumberOfProcessors;
|
|
#endif // ! DPNBUILD_ONLYONEPROCESSOR
|
|
|
|
#ifndef DPNBUILD_ONLYONETHREAD
|
|
pDPTPObject->dwTotalUserThreadCount = -1;
|
|
pDPTPObject->dwTotalDesiredWorkThreadCount = -1;
|
|
pDPTPObject->dwWorkRecursionCountTlsIndex = -1;
|
|
pDPTPObject->lNumThreadCountChangeWaiters = 0;
|
|
|
|
#if ((defined(DPNBUILD_MANDATORYTHREADS)) && (defined(DBG)))
|
|
pDPTPObject->blMandatoryThreads.Initialize();
|
|
#endif // DPNBUILD_MANDATORYTHREADS and DBG
|
|
|
|
|
|
//
|
|
// Allocate Thread Local Storage for tracking recursion on non-worker
|
|
// threads.
|
|
//
|
|
pDPTPObject->dwWorkRecursionCountTlsIndex = TlsAlloc();
|
|
if (pDPTPObject->dwWorkRecursionCountTlsIndex == -1)
|
|
{
|
|
#ifdef DBG
|
|
dwError = GetLastError();
|
|
DPFX(DPFPREP, 0, "Couldn't allocate Thread Local Storage slot for tracking recursion on non-worker threads (err = %u)!", dwError);
|
|
#endif // DBG
|
|
hr = E_OUTOFMEMORY;
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// Allocate Thread Local Storage for tracking worker threads.
|
|
//
|
|
dwWorkerThreadTlsIndex = TlsAlloc();
|
|
if (dwWorkerThreadTlsIndex == -1)
|
|
{
|
|
#ifdef DBG
|
|
dwError = GetLastError();
|
|
DPFX(DPFPREP, 0, "Couldn't allocate Thread Local Storage slot for tracking worker threads (err = %u)!", dwError);
|
|
#endif // DBG
|
|
hr = E_OUTOFMEMORY;
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// Create a semaphore to release threads waiting on another thread changing
|
|
// the thread count.
|
|
//
|
|
pDPTPObject->hThreadCountChangeComplete = DNCreateSemaphore(NULL, 0, 0xFFFF, NULL);
|
|
if (pDPTPObject->hThreadCountChangeComplete == NULL)
|
|
{
|
|
#ifdef DBG
|
|
dwError = GetLastError();
|
|
DPFX(DPFPREP, 0, "Couldn't create thread count change complete semaphore (err = %u)!", dwError);
|
|
#endif // DBG
|
|
hr = E_OUTOFMEMORY;
|
|
goto Failure;
|
|
}
|
|
#endif // ! DPNBUILD_ONLYONETHREAD
|
|
|
|
|
|
#ifdef DPNBUILD_ONLYONEPROCESSOR
|
|
#ifdef DPNBUILD_ONLYONETHREAD
|
|
hr = InitializeWorkQueue(&pDPTPObject->WorkQueue);
|
|
#else // ! DPNBUILD_ONLYONETHREAD
|
|
hr = InitializeWorkQueue(&pDPTPObject->WorkQueue,
|
|
NULL,
|
|
NULL,
|
|
dwWorkerThreadTlsIndex);
|
|
#endif // ! DPNBUILD_ONLYONETHREAD
|
|
if (hr != DPN_OK)
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't initialize work queue!");
|
|
goto Failure;
|
|
}
|
|
fInittedWorkQueue = TRUE;
|
|
#else // ! DPNBUILD_ONLYONEPROCESSOR
|
|
//
|
|
// Allocate the array of work queues pointers, one for each processor.
|
|
//
|
|
pDPTPObject->papCPUWorkQueues = (DPTPWORKQUEUE**) DNMalloc(NUM_CPUS(pDPTPObject) * sizeof(DPTPWORKQUEUE*));
|
|
if (pDPTPObject->papCPUWorkQueues == NULL)
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't allocate memory for array of work queue pointers!");
|
|
hr = E_OUTOFMEMORY;
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// Initialize each of the work queues.
|
|
//
|
|
for(dwTemp = 0; dwTemp < NUM_CPUS(pDPTPObject); dwTemp++)
|
|
{
|
|
#ifdef DPNBUILD_USEIOCOMPLETIONPORTS
|
|
if (dwTemp > 0)
|
|
{
|
|
pDPTPObject->papCPUWorkQueues[dwTemp] = pDPTPObject->papCPUWorkQueues[0];
|
|
}
|
|
else
|
|
#endif // DPNBUILD_USEIOCOMPLETIONPORTS
|
|
{
|
|
//
|
|
// Allocate the actual work queues object.
|
|
//
|
|
pDPTPObject->papCPUWorkQueues[dwTemp] = (DPTPWORKQUEUE*) DNMalloc(sizeof(DPTPWORKQUEUE));
|
|
if (pDPTPObject->papCPUWorkQueues[dwTemp] == NULL)
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't allocate memory for work queue %u!", dwTemp);
|
|
hr = E_OUTOFMEMORY;
|
|
goto Failure;
|
|
}
|
|
|
|
|
|
#ifdef DPNBUILD_ONLYONETHREAD
|
|
hr = InitializeWorkQueue(WORKQUEUE_FOR_CPU(pDPTPObject, dwTemp),
|
|
dwTemp);
|
|
#else // ! DPNBUILD_ONLYONETHREAD
|
|
hr = InitializeWorkQueue(WORKQUEUE_FOR_CPU(pDPTPObject, dwTemp),
|
|
dwTemp,
|
|
NULL,
|
|
NULL,
|
|
dwWorkerThreadTlsIndex);
|
|
#endif // ! DPNBUILD_ONLYONETHREAD
|
|
if (hr != DPN_OK)
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't intialize work queue %u!", dwTemp);
|
|
|
|
DNFree(pDPTPObject->papCPUWorkQueues[dwTemp]);
|
|
pDPTPObject->papCPUWorkQueues[dwTemp] = NULL;
|
|
goto Failure;
|
|
}
|
|
}
|
|
}
|
|
#endif // ! DPNBUILD_ONLYONEPROCESSOR
|
|
|
|
if (! DNInitializeCriticalSection(&pDPTPObject->csLock))
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't initialize object lock!");
|
|
hr = E_OUTOFMEMORY;
|
|
goto Failure;
|
|
}
|
|
fInittedLock = TRUE;
|
|
|
|
|
|
#ifdef DPNBUILD_LIBINTERFACE
|
|
//
|
|
// For lib interface builds, the Vtbl and reference are embedded in the
|
|
// object directly.
|
|
//
|
|
#ifdef DPNBUILD_ONLYONETHREAD
|
|
pDPTPObject->lpVtbl = &DPTPW_Vtbl;
|
|
#ifdef DPNBUILD_MULTIPLETHREADPOOLS
|
|
pDPTPObject->lRefCount = 1;
|
|
#endif // DPNBUILD_MULTIPLETHREADPOOLS
|
|
#else // ! DPNBUILD_ONLYONETHREAD
|
|
// We assume only the work interface is created. The ID will have to be
|
|
// passed in or something (see DNCF_CreateObject).
|
|
#pragma error("Building with DPNBUILD_LIBINTERFACE but not DPNBUILD_ONLYONETHREAD requires minor changes")
|
|
#endif // ! DPNBUILD_ONLYONETHREAD
|
|
#endif // DPNBUILD_LIBINTERFACE
|
|
|
|
#ifndef DPNBUILD_MULTIPLETHREADPOOLS
|
|
//
|
|
// Store this as the only object allowed in this process.
|
|
//
|
|
g_pDPTPObject = pDPTPObject;
|
|
#ifndef DPNBUILD_LIBINTERFACE
|
|
g_dwDPTPRefCount++;
|
|
#endif // ! DPNBUILD_LIBINTERFACE
|
|
#endif // ! DPNBUILD_MULTIPLETHREADPOOLS
|
|
|
|
DPFX(DPFPREP, 2, "Created object 0x%p.", pDPTPObject);
|
|
(*ppv) = pDPTPObject;
|
|
|
|
Exit:
|
|
|
|
#ifndef DPNBUILD_MULTIPLETHREADPOOLS
|
|
//
|
|
// See if we've already allocated a thread pool object, because you only
|
|
// get one per process.
|
|
//
|
|
if (fHaveGlobalThreadPoolLock)
|
|
{
|
|
DNLeaveCriticalSection(&g_csGlobalThreadPoolLock);
|
|
fHaveGlobalThreadPoolLock = FALSE;
|
|
}
|
|
#endif // ! DPNBUILD_MULTIPLETHREADPOOLS
|
|
|
|
return hr;
|
|
|
|
|
|
Failure:
|
|
|
|
if (pDPTPObject != NULL)
|
|
{
|
|
if (fInittedLock)
|
|
{
|
|
DNDeleteCriticalSection(&pDPTPObject->csLock);
|
|
fInittedLock = FALSE;
|
|
}
|
|
|
|
#ifdef DPNBUILD_ONLYONEPROCESSOR
|
|
if (fInittedWorkQueue)
|
|
{
|
|
DeinitializeWorkQueue(&pDPTPObject->WorkQueue);
|
|
fInittedWorkQueue = FALSE;
|
|
}
|
|
#else // ! DPNBUILD_ONLYONEPROCESSOR
|
|
if (pDPTPObject->papCPUWorkQueues != NULL)
|
|
{
|
|
#ifdef DPNBUILD_USEIOCOMPLETIONPORTS
|
|
dwTemp = 0;
|
|
#else // ! DPNBUILD_USEIOCOMPLETIONPORTS
|
|
for(dwTemp = 0; dwTemp < NUM_CPUS(pDPTPObject); dwTemp++)
|
|
#endif // ! DPNBUILD_USEIOCOMPLETIONPORTS
|
|
{
|
|
if (WORKQUEUE_FOR_CPU(pDPTPObject, dwTemp) != NULL)
|
|
{
|
|
DeinitializeWorkQueue(WORKQUEUE_FOR_CPU(pDPTPObject, dwTemp));
|
|
DNFree(pDPTPObject->papCPUWorkQueues[dwTemp]);
|
|
}
|
|
}
|
|
|
|
DNFree(pDPTPObject->papCPUWorkQueues);
|
|
pDPTPObject->papCPUWorkQueues = NULL;
|
|
}
|
|
#endif // ! DPNBUILD_ONLYONEPROCESSOR
|
|
|
|
#ifndef DPNBUILD_ONLYONETHREAD
|
|
if (pDPTPObject->hThreadCountChangeComplete != NULL)
|
|
{
|
|
DNCloseHandle(pDPTPObject->hThreadCountChangeComplete);
|
|
pDPTPObject->hThreadCountChangeComplete = NULL;
|
|
}
|
|
|
|
if (dwWorkerThreadTlsIndex != -1)
|
|
{
|
|
TlsFree(dwWorkerThreadTlsIndex);
|
|
dwWorkerThreadTlsIndex = -1;
|
|
}
|
|
|
|
if (pDPTPObject->dwWorkRecursionCountTlsIndex != -1)
|
|
{
|
|
TlsFree(pDPTPObject->dwWorkRecursionCountTlsIndex);
|
|
pDPTPObject->dwWorkRecursionCountTlsIndex = -1;
|
|
}
|
|
#endif // ! DPNBUILD_ONLYONETHREAD
|
|
|
|
DNFree(pDPTPObject);
|
|
pDPTPObject = NULL;
|
|
}
|
|
|
|
goto Exit;
|
|
} // DPTPCF_CreateObject
|
|
|
|
|
|
|
|
|
|
|
|
#if ((defined(DPNBUILD_LIBINTERFACE)) && (defined(DPNBUILD_ONLYONETHREAD)) && (! defined(DPNBUILD_MULTIPLETHREADPOOLS)))
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DPTPCF_GetObject"
|
|
//=============================================================================
|
|
// DPTPCF_GetObject
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Description: Gets a pointer to the global thread pool object.
|
|
//
|
|
// Arguments:
|
|
// PVOID * ppv - ?
|
|
//
|
|
// Returns: None
|
|
//=============================================================================
|
|
void DPTPCF_GetObject(PVOID * ppv)
|
|
{
|
|
(*ppv) = g_pDPTPObject;
|
|
} // DPTPCF_GetObject
|
|
#endif // DPNBUILD_LIBINTERFACE DPNBUILD_ONLYONETHREAD and ! DPNBUILD_MULTIPLETHREADPOOLS
|
|
|
|
|
|
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DPTPCF_FreeObject"
|
|
//=============================================================================
|
|
// DPTPCF_FreeObject
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Description: Frees an existing thread pool object.
|
|
//
|
|
// Arguments:
|
|
// PVOID pvObject - ?
|
|
//
|
|
// Returns: HRESULT
|
|
//=============================================================================
|
|
HRESULT DPTPCF_FreeObject(PVOID pvObject)
|
|
{
|
|
DPTHREADPOOLOBJECT * pDPTPObject = (DPTHREADPOOLOBJECT*) pvObject;
|
|
#ifndef DPNBUILD_ONLYONEPROCESSOR
|
|
DWORD dwTemp;
|
|
#endif // ! DPNBUILD_ONLYONEPROCESSOR
|
|
#ifndef DPNBUILD_ONLYONETHREAD
|
|
DWORD dwWorkerThreadTlsIndex;
|
|
#endif // ! DPNBUILD_ONLYONETHREAD
|
|
|
|
|
|
DPFX(DPFPREP, 4, "Parameters: (0x%p)", pvObject);
|
|
|
|
|
|
#ifndef DPNBUILD_MULTIPLETHREADPOOLS
|
|
DNEnterCriticalSection(&g_csGlobalThreadPoolLock);
|
|
DNASSERT(pDPTPObject == g_pDPTPObject);
|
|
#ifdef DPNBUILD_LIBINTERFACE
|
|
#ifndef DPNBUILD_ONLYONETHREAD
|
|
//
|
|
// It's possible somebody just took a reference on the object, so we may
|
|
// need to bail.
|
|
//
|
|
DNASSERT(pDPTPObject->lRefCount >= 0);
|
|
if (pDPTPObject->lRefCount > 0)
|
|
{
|
|
DPFX(DPFPREP, 1, "Global thread pool object 0x%p just got referenced (refcount now %i), not destroying.",
|
|
g_pDPTPObject, pDPTPObject->lRefCount);
|
|
DNLeaveCriticalSection(&g_csGlobalThreadPoolLock);
|
|
return S_OK;
|
|
}
|
|
#endif // ! DPNBUILD_ONLYONETHREAD
|
|
#else // ! DPNBUILD_LIBINTERFACE
|
|
//
|
|
// Reduce the global object count. There might be other users, though.
|
|
//
|
|
g_dwDPTPRefCount--;
|
|
if (g_dwDPTPRefCount != 0)
|
|
{
|
|
DPFX(DPFPREP, 1, "Global thread pool object 0x%p still has other users, refcount now %u.",
|
|
g_pDPTPObject, g_dwDPTPRefCount);
|
|
DNLeaveCriticalSection(&g_csGlobalThreadPoolLock);
|
|
return S_OK;
|
|
}
|
|
#endif // ! DPNBUILD_LIBINTERFACE
|
|
g_pDPTPObject = NULL;
|
|
DNLeaveCriticalSection(&g_csGlobalThreadPoolLock);
|
|
#endif // ! DPNBUILD_MULTIPLETHREADPOOLS
|
|
|
|
//
|
|
// Double check to make sure the object is closed.
|
|
//
|
|
if (pDPTPObject->dwFlags & DPTPOBJECTFLAG_USER_INITIALIZED)
|
|
{
|
|
DPFX(DPFPREP, 0, "User has not closed IDirectPlay8ThreadPool interface!");
|
|
DNASSERT(FALSE);
|
|
|
|
//
|
|
// Forcefully mark the user's interface as no longer available.
|
|
//
|
|
pDPTPObject->dwFlags &= ~DPTPOBJECTFLAG_USER_INITIALIZED;
|
|
}
|
|
|
|
|
|
#ifdef DPNBUILD_LIBINTERFACE
|
|
//
|
|
// For lib interface builds, the reference is embedded in the object
|
|
// directly.
|
|
//
|
|
#if ((! defined(DPNBUILD_ONLYONETHREAD)) || (defined(DPNBUILD_MULTIPLETHREADPOOLS)))
|
|
DNASSERT(pDPTPObject->lRefCount == 0);
|
|
#endif // ! DPNBUILD_ONLYONETHREAD or DPNBUILD_MULTIPLETHREADPOOLS
|
|
#endif // DPNBUILD_LIBINTERFACE
|
|
|
|
|
|
#ifndef DPNBUILD_ONLYONETHREAD
|
|
//
|
|
// Save the Thread Local Storage index value before cleaning up the work
|
|
// queues. Since all work queues share the same TLS index, just use the
|
|
// first CPU as representative of all of them.
|
|
//
|
|
dwWorkerThreadTlsIndex = (WORKQUEUE_FOR_CPU(pDPTPObject, 0))->dwWorkerThreadTlsIndex;
|
|
#endif // ! DPNBUILD_ONLYONETHREAD
|
|
|
|
|
|
DNDeleteCriticalSection(&pDPTPObject->csLock);
|
|
|
|
#ifdef DPNBUILD_ONLYONEPROCESSOR
|
|
DeinitializeWorkQueue(&pDPTPObject->WorkQueue);
|
|
#else // ! DPNBUILD_ONLYONEPROCESSOR
|
|
#ifdef DPNBUILD_USEIOCOMPLETIONPORTS
|
|
dwTemp = 0;
|
|
#else // ! DPNBUILD_USEIOCOMPLETIONPORTS
|
|
for(dwTemp = 0; dwTemp < NUM_CPUS(pDPTPObject); dwTemp++)
|
|
#endif // ! DPNBUILD_USEIOCOMPLETIONPORTS
|
|
{
|
|
DeinitializeWorkQueue(WORKQUEUE_FOR_CPU(pDPTPObject, dwTemp));
|
|
DNFree(pDPTPObject->papCPUWorkQueues[dwTemp]);
|
|
}
|
|
|
|
DNFree(pDPTPObject->papCPUWorkQueues);
|
|
pDPTPObject->papCPUWorkQueues = NULL;
|
|
#endif // ! DPNBUILD_ONLYONEPROCESSOR
|
|
|
|
#ifndef DPNBUILD_ONLYONETHREAD
|
|
//
|
|
// Close the thread count change complete semaphore.
|
|
//
|
|
DNASSERT(pDPTPObject->lNumThreadCountChangeWaiters == 0);
|
|
DNCloseHandle(pDPTPObject->hThreadCountChangeComplete);
|
|
pDPTPObject->hThreadCountChangeComplete = NULL;
|
|
|
|
//
|
|
// Free the Thread Local Storage slot for tracking worker threads.
|
|
//
|
|
TlsFree(dwWorkerThreadTlsIndex);
|
|
dwWorkerThreadTlsIndex = -1;
|
|
|
|
//
|
|
// Free the Thread Local Storage slot for tracking recursion on non-worker
|
|
// threads.
|
|
//
|
|
TlsFree(pDPTPObject->dwWorkRecursionCountTlsIndex);
|
|
pDPTPObject->dwWorkRecursionCountTlsIndex = -1;
|
|
|
|
#ifdef DPNBUILD_MANDATORYTHREADS
|
|
DNASSERT(pDPTPObject->dwMandatoryThreadCount == 0);
|
|
#endif // DPNBUILD_MANDATORYTHREADS
|
|
#endif // ! DPNBUILD_ONLYONETHREAD
|
|
|
|
|
|
//
|
|
// Make sure there aren't any flags set except possibly
|
|
// USER_PARAMVALIDATION.
|
|
//
|
|
DNASSERT(! (pDPTPObject->dwFlags & ~(DPTPOBJECTFLAG_USER_PARAMVALIDATION)));
|
|
|
|
DNFree(pDPTPObject);
|
|
pDPTPObject = NULL;
|
|
|
|
DPFX(DPFPREP, 4, "Returning: [S_OK]");
|
|
|
|
return S_OK;
|
|
} // DPTPCF_FreeObject
|
|
|
|
|
|
|
|
|
|
#ifdef DPNBUILD_LIBINTERFACE
|
|
|
|
|
|
#if ((! defined(DPNBUILD_ONLYONETHREAD)) || (defined(DPNBUILD_MULTIPLETHREADPOOLS)))
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DPTP_QueryInterface"
|
|
//=============================================================================
|
|
// DPTP_QueryInterface
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Description: Queries for a new interface for an existing object.
|
|
//
|
|
// Arguments:
|
|
// void * pvInterface - ?
|
|
// DP8REFIID riid - ?
|
|
// void ** ppv - ?
|
|
//
|
|
// Returns: HRESULT
|
|
//=============================================================================
|
|
STDMETHODIMP DPTP_QueryInterface(void * pvInterface,
|
|
DP8REFIID riid,
|
|
void ** ppv)
|
|
{
|
|
HRESULT hResultCode;
|
|
|
|
|
|
DPFX(DPFPREP, 2,"Parameters: pvInterface [0x%p], riid [0x%p], ppv [0x%p]",pvInterface,&riid,ppv);
|
|
|
|
|
|
//
|
|
// Get the object Vtbl and make sure it's one of ours
|
|
//
|
|
if (*((PVOID*) pvInterface) == (&DPTPW_Vtbl))
|
|
{
|
|
//
|
|
// It is one of our objects. Assume the IID is not specified, so just
|
|
// return a reference to the existing object.
|
|
//
|
|
DNASSERT(riid == 0);
|
|
hResultCode = S_OK;
|
|
DPTP_AddRef(pvInterface);
|
|
*ppv = pvInterface;
|
|
}
|
|
else
|
|
{
|
|
DPFX(DPFPREP, 0, "Invalid object!");
|
|
hResultCode = E_POINTER;
|
|
}
|
|
|
|
DPFX(DPFPREP, 2,"Returning: [0x%lx]",hResultCode);
|
|
return(hResultCode);
|
|
} // DPTP_QueryInterface
|
|
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DPTP_AddRef"
|
|
//=============================================================================
|
|
// DPTP_AddRef
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Description: Adds a reference to a thread pool interface.
|
|
//
|
|
// Arguments:
|
|
// void * pvInterface - ?
|
|
//
|
|
// Returns: ULONG
|
|
//=============================================================================
|
|
STDMETHODIMP_(ULONG) DPTP_AddRef(void * pvInterface)
|
|
{
|
|
DPTHREADPOOLOBJECT * pDPTPObject;
|
|
LONG lRefCount;
|
|
|
|
DPFX(DPFPREP, 2,"Parameters: pInterface [0x%p]",pvInterface);
|
|
|
|
#ifndef DPNBUILD_NOPARAMVAL
|
|
if (pvInterface == NULL)
|
|
{
|
|
DPFERR("Invalid COM interface specified");
|
|
lRefCount = 0;
|
|
goto Exit;
|
|
}
|
|
#endif // ! DPNBUILD_NOPARAMVAL
|
|
|
|
pDPTPObject = static_cast<DPTHREADPOOLOBJECT*>(pvInterface);
|
|
lRefCount = DNInterlockedIncrement(&pDPTPObject->lRefCount);
|
|
DNASSERT(lRefCount > 0);
|
|
DPFX(DPFPREP, 5,"New lRefCount [%ld]",lRefCount);
|
|
|
|
#ifndef DPNBUILD_NOPARAMVAL
|
|
Exit:
|
|
#endif // ! DPNBUILD_NOPARAMVAL
|
|
DPFX(DPFPREP, 2,"Returning: lRefCount [%ld]",lRefCount);
|
|
return(lRefCount);
|
|
} // DPTP_AddRef
|
|
|
|
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DPTP_Release"
|
|
//=============================================================================
|
|
// DPTP_Release
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Description: Removes a reference from a thread pool interface. If it is
|
|
// the last reference on the object, the object is destroyed.
|
|
//
|
|
// Arguments:
|
|
// void * pvInterface - ?
|
|
//
|
|
// Returns: ULONG
|
|
//=============================================================================
|
|
STDMETHODIMP_(ULONG) DPTP_Release(void * pvInterface)
|
|
{
|
|
DPTHREADPOOLOBJECT * pDPTPObject;
|
|
LONG lRefCount;
|
|
|
|
DPFX(DPFPREP, 2,"Parameters: pInterface [%p]",pvInterface);
|
|
|
|
#ifndef DPNBUILD_NOPARAMVAL
|
|
if (pvInterface == NULL)
|
|
{
|
|
DPFERR("Invalid COM interface specified");
|
|
lRefCount = 0;
|
|
goto Exit;
|
|
}
|
|
#endif // ! DPNBUILD_NOPARAMVAL
|
|
|
|
pDPTPObject = static_cast<DPTHREADPOOLOBJECT*>(pvInterface);
|
|
DNASSERT(pDPTPObject->lRefCount > 0);
|
|
lRefCount = DNInterlockedDecrement(&pDPTPObject->lRefCount);
|
|
DPFX(DPFPREP, 5,"New lRefCount [%ld]",lRefCount);
|
|
|
|
if (lRefCount == 0)
|
|
{
|
|
// Free object here
|
|
DPFX(DPFPREP, 5,"Free object");
|
|
DPTPCF_FreeObject(pvInterface);
|
|
}
|
|
|
|
#ifndef DPNBUILD_NOPARAMVAL
|
|
Exit:
|
|
#endif // ! DPNBUILD_NOPARAMVAL
|
|
DPFX(DPFPREP, 2,"Returning: lRefCount [%ld]",lRefCount);
|
|
return(lRefCount);
|
|
} // DPTP_Release
|
|
|
|
#endif // ! DPNBUILD_ONLYONETHREAD or DPNBUILD_MULTIPLETHREADPOOLS
|
|
|
|
|
|
#else // ! DPNBUILD_LIBINTERFACE
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DPTPCF_FindInterface"
|
|
//=============================================================================
|
|
// DPTPCF_FindInterface
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Description: Locates an interface for a given object.
|
|
//
|
|
// Initialize must have been called.
|
|
//
|
|
// Arguments:
|
|
// void * pvInterface - ?
|
|
// REFIID riid - ?
|
|
//
|
|
// Returns: HRESULT
|
|
//=============================================================================
|
|
INTERFACE_LIST * DPTPCF_FindInterface(void * pvInterface,
|
|
REFIID riid)
|
|
{
|
|
INTERFACE_LIST * pInterfaceList;
|
|
|
|
|
|
DPFX(DPFPREP, 6,"Parameters: (0x%p, 0x%p)", pvInterface, &riid);
|
|
|
|
DNASSERT(pvInterface != NULL);
|
|
|
|
pInterfaceList = (static_cast<INTERFACE_LIST*>(pvInterface))->pObject->pIntList; // Find first interface
|
|
while (pInterfaceList != NULL)
|
|
{
|
|
if (IsEqualIID(riid, pInterfaceList->iid))
|
|
{
|
|
break;
|
|
}
|
|
pInterfaceList = pInterfaceList->pIntNext;
|
|
}
|
|
|
|
DPFX(DPFPREP, 6,"Returning: [0x%p]", pInterfaceList);
|
|
|
|
return pInterfaceList;
|
|
} // DPTPCF_FindInterface
|
|
|
|
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DPTP_QueryInterface"
|
|
//=============================================================================
|
|
// DPTP_QueryInterface
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Description: Queries for a new interface for an existing object.
|
|
//
|
|
// Arguments:
|
|
// void * pvInterface - ?
|
|
// REFIID riid - ?
|
|
// void ** ppv - ?
|
|
//
|
|
// Returns: HRESULT
|
|
//=============================================================================
|
|
STDMETHODIMP DPTP_QueryInterface(void * pvInterface,
|
|
DP8REFIID riid,
|
|
void ** ppv)
|
|
{
|
|
INTERFACE_LIST *pIntList;
|
|
INTERFACE_LIST *pIntNew;
|
|
HRESULT hResultCode;
|
|
|
|
DPFX(DPFPREP, 2,"Parameters: pvInterface [0x%p], riid [0x%p], ppv [0x%p]",pvInterface,&riid,ppv);
|
|
|
|
#ifndef DPNBUILD_NOPARAMVAL
|
|
if (pvInterface == NULL)
|
|
{
|
|
DPFERR("Invalid COM interface specified");
|
|
hResultCode = E_INVALIDARG;
|
|
goto Exit;
|
|
}
|
|
if (ppv == NULL)
|
|
{
|
|
DPFERR("Invalid target interface pointer specified");
|
|
hResultCode = E_POINTER;
|
|
goto Exit;
|
|
}
|
|
#endif // ! DPNBUILD_NOPARAMVAL
|
|
|
|
if ((pIntList = DPTPCF_FindInterface(pvInterface,riid)) == NULL)
|
|
{ // Interface must be created
|
|
pIntList = (static_cast<INTERFACE_LIST*>(pvInterface))->pObject->pIntList;
|
|
if ((hResultCode = DPTPCF_CreateInterface(pIntList->pObject,riid,&pIntNew)) != S_OK)
|
|
{
|
|
goto Exit;
|
|
}
|
|
pIntNew->pIntNext = pIntList;
|
|
pIntList->pObject->pIntList = pIntNew;
|
|
pIntList = pIntNew;
|
|
}
|
|
if (pIntList->lRefCount == 0) // New interface exposed
|
|
{
|
|
DNInterlockedIncrement(&pIntList->pObject->lRefCount);
|
|
}
|
|
DNInterlockedIncrement(&pIntList->lRefCount);
|
|
*ppv = static_cast<void*>(pIntList);
|
|
DPFX(DPFPREP, 5,"*ppv = [0x%p]", *ppv);
|
|
|
|
hResultCode = S_OK;
|
|
|
|
Exit:
|
|
DPFX(DPFPREP, 2,"Returning: [0x%lx]",hResultCode);
|
|
return(hResultCode);
|
|
} // DPTP_QueryInterface
|
|
|
|
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DPTP_AddRef"
|
|
//=============================================================================
|
|
// DPTP_AddRef
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Description: Adds a reference to a thread pool interface.
|
|
//
|
|
// Arguments:
|
|
// void * pvInterface - ?
|
|
//
|
|
// Returns: ULONG
|
|
//=============================================================================
|
|
STDMETHODIMP_(ULONG) DPTP_AddRef(void * pvInterface)
|
|
{
|
|
INTERFACE_LIST *pIntList;
|
|
LONG lRefCount;
|
|
|
|
DPFX(DPFPREP, 2,"Parameters: pInterface [0x%p]",pvInterface);
|
|
|
|
#ifndef DPNBUILD_NOPARAMVAL
|
|
if (pvInterface == NULL)
|
|
{
|
|
DPFERR("Invalid COM interface specified");
|
|
lRefCount = 0;
|
|
goto Exit;
|
|
}
|
|
#endif // ! DPNBUILD_NOPARAMVAL
|
|
|
|
pIntList = static_cast<INTERFACE_LIST*>(pvInterface);
|
|
lRefCount = DNInterlockedIncrement(&pIntList->lRefCount);
|
|
DPFX(DPFPREP, 5,"New lRefCount [%ld]",lRefCount);
|
|
|
|
#ifndef DPNBUILD_NOPARAMVAL
|
|
Exit:
|
|
#endif // !DPNBUILD_NOPARAMVAL
|
|
DPFX(DPFPREP, 2,"Returning: lRefCount [%ld]",lRefCount);
|
|
return(lRefCount);
|
|
} // DPTP_AddRef
|
|
|
|
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DPTP_Release"
|
|
//=============================================================================
|
|
// DPTP_Release
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Description: Removes a reference from a thread pool interface. If it is
|
|
// the last reference on the object, the object is destroyed.
|
|
//
|
|
// Arguments:
|
|
// void * pvInterface - ?
|
|
//
|
|
// Returns: ULONG
|
|
//=============================================================================
|
|
STDMETHODIMP_(ULONG) DPTP_Release(void * pvInterface)
|
|
{
|
|
INTERFACE_LIST *pIntList;
|
|
INTERFACE_LIST *pIntCurrent;
|
|
LONG lRefCount;
|
|
LONG lObjRefCount;
|
|
|
|
DPFX(DPFPREP, 2,"Parameters: pInterface [%p]",pvInterface);
|
|
|
|
#ifndef DPNBUILD_NOPARAMVAL
|
|
if (pvInterface == NULL)
|
|
{
|
|
DPFERR("Invalid COM interface specified");
|
|
lRefCount = 0;
|
|
goto Exit;
|
|
}
|
|
#endif // ! DPNBUILD_NOPARAMVAL
|
|
|
|
pIntList = static_cast<INTERFACE_LIST*>(pvInterface);
|
|
lRefCount = DNInterlockedDecrement( &pIntList->lRefCount );
|
|
DPFX(DPFPREP, 5,"New lRefCount [%ld]",lRefCount);
|
|
|
|
if (lRefCount == 0)
|
|
{
|
|
//
|
|
// Decrease object's interface count
|
|
//
|
|
lObjRefCount = DNInterlockedDecrement( &pIntList->pObject->lRefCount );
|
|
|
|
//
|
|
// Free object and interfaces
|
|
//
|
|
if (lObjRefCount == 0)
|
|
{
|
|
// Free object here
|
|
DPFX(DPFPREP, 5,"Free object");
|
|
DPTPCF_FreeObject(pIntList->pObject->pvData);
|
|
|
|
pIntList = pIntList->pObject->pIntList; // Get head of interface list
|
|
DNFree(pIntList->pObject);
|
|
|
|
// Free Interfaces
|
|
DPFX(DPFPREP, 5,"Free interfaces");
|
|
while(pIntList != NULL)
|
|
{
|
|
pIntCurrent = pIntList;
|
|
pIntList = pIntList->pIntNext;
|
|
DNFree(pIntCurrent);
|
|
}
|
|
|
|
DNInterlockedDecrement(&g_lDPTPInterfaceCount);
|
|
}
|
|
}
|
|
|
|
#ifndef DPNBUILD_NOPARAMVAL
|
|
Exit:
|
|
#endif // ! DPNBUILD_NOPARAMVAL
|
|
DPFX(DPFPREP, 2,"Returning: lRefCount [%ld]",lRefCount);
|
|
return(lRefCount);
|
|
} // DPTP_Release
|
|
|
|
#endif // ! DPNBUILD_LIBINTERFACE
|