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.

1258 lines
35 KiB

  1. /******************************************************************************
  2. *
  3. * Copyright (C) 2001-2002 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: threadpoolclassfac.cpp
  6. *
  7. * Content: DirectPlay Thread Pool class factory functions.
  8. *
  9. * History:
  10. * Date By Reason
  11. * ======== ======== =========
  12. * 11/02/01 VanceO Created.
  13. *
  14. ******************************************************************************/
  15. #include "dpnthreadpooli.h"
  16. //=============================================================================
  17. // Function type definitions
  18. //=============================================================================
  19. #ifndef DPNBUILD_LIBINTERFACE
  20. typedef STDMETHODIMP UnknownQueryInterface(IUnknown * pInterface, REFIID riid, LPVOID *ppvObj);
  21. typedef STDMETHODIMP_(ULONG) UnknownAddRef(IUnknown * pInterface);
  22. typedef STDMETHODIMP_(ULONG) UnknownRelease(IUnknown * pInterface);
  23. #endif // ! DPNBUILD_LIBINTERFACE
  24. #ifndef DPNBUILD_ONLYONETHREAD
  25. typedef STDMETHODIMP ThreadPoolQueryInterface(IDirectPlay8ThreadPool * pInterface, DP8REFIID riid, LPVOID *ppvObj);
  26. typedef STDMETHODIMP_(ULONG) ThreadPoolAddRef(IDirectPlay8ThreadPool * pInterface);
  27. typedef STDMETHODIMP_(ULONG) ThreadPoolRelease(IDirectPlay8ThreadPool * pInterface);
  28. #endif // ! DPNBUILD_ONLYONETHREAD
  29. #if ((! defined(DPNBUILD_LIBINTERFACE)) || (! defined(DPNBUILD_ONLYONETHREAD)) || (defined(DPNBUILD_MULTIPLETHREADPOOLS)))
  30. typedef STDMETHODIMP ThreadPoolWorkQueryInterface(IDirectPlay8ThreadPoolWork * pInterface, DP8REFIID riid, LPVOID *ppvObj);
  31. typedef STDMETHODIMP_(ULONG) ThreadPoolWorkAddRef(IDirectPlay8ThreadPoolWork * pInterface);
  32. typedef STDMETHODIMP_(ULONG) ThreadPoolWorkRelease(IDirectPlay8ThreadPoolWork * pInterface);
  33. #endif // ! DPNBUILD_LIBINTERFACE or ! DPNBUILD_ONLYONETHREAD or DPNBUILD_MULTIPLETHREADPOOLS
  34. //=============================================================================
  35. // Function Prototypes
  36. //=============================================================================
  37. #ifndef DPNBUILD_LIBINTERFACE
  38. STDMETHODIMP DPTPCF_CreateInstance(IClassFactory * pInterface, LPUNKNOWN lpUnkOuter, REFIID riid, LPVOID * ppv);
  39. HRESULT DPTPCF_CreateInterface(OBJECT_DATA * pObject,
  40. REFIID riid,
  41. INTERFACE_LIST ** const ppv);
  42. HRESULT DPTPCF_CreateObject(IClassFactory * pInterface, LPVOID * ppv, REFIID riid);
  43. #endif // ! DPNBUILD_LIBINTERFACE
  44. HRESULT DPTPCF_FreeObject(PVOID pvObject);
  45. #ifndef DPNBUILD_LIBINTERFACE
  46. INTERFACE_LIST * DPTPCF_FindInterface(void * pvInterface,
  47. REFIID riid);
  48. #endif // ! DPNBUILD_LIBINTERFACE
  49. #if ((! defined(DPNBUILD_LIBINTERFACE)) || (! defined(DPNBUILD_ONLYONETHREAD) )|| (defined(DPNBUILD_MULTIPLETHREADPOOLS)))
  50. STDMETHODIMP DPTP_QueryInterface(void * pvInterface,
  51. DP8REFIID riid,
  52. void ** ppv);
  53. STDMETHODIMP_(ULONG) DPTP_AddRef(void * pvInterface);
  54. STDMETHODIMP_(ULONG) DPTP_Release(void * pvInterface);
  55. #endif // ! DPNBUILD_LIBINTERFACE or ! DPNBUILD_ONLYONETHREAD or DPNBUILD_MULTIPLETHREADPOOLS
  56. //=============================================================================
  57. // External globals
  58. //=============================================================================
  59. #ifndef DPNBUILD_LIBINTERFACE
  60. IUnknownVtbl DPTP_UnknownVtbl =
  61. {
  62. (UnknownQueryInterface*) DPTP_QueryInterface,
  63. (UnknownAddRef*) DPTP_AddRef,
  64. (UnknownRelease*) DPTP_Release
  65. };
  66. #endif // ! DPNBUILD_LIBINTERFACE
  67. #ifndef DPNBUILD_ONLYONETHREAD
  68. IDirectPlay8ThreadPoolVtbl DPTP_Vtbl =
  69. {
  70. (ThreadPoolQueryInterface*) DPTP_QueryInterface,
  71. (ThreadPoolAddRef*) DPTP_AddRef,
  72. (ThreadPoolRelease*) DPTP_Release,
  73. DPTP_Initialize,
  74. DPTP_Close,
  75. DPTP_GetThreadCount,
  76. DPTP_SetThreadCount,
  77. DPTP_DoWork,
  78. };
  79. #endif // ! DPNBUILD_ONLYONETHREAD
  80. IDirectPlay8ThreadPoolWorkVtbl DPTPW_Vtbl =
  81. {
  82. #if ((! defined(DPNBUILD_LIBINTERFACE)) || (! defined(DPNBUILD_ONLYONETHREAD)) || (defined(DPNBUILD_MULTIPLETHREADPOOLS)))
  83. (ThreadPoolWorkQueryInterface*) DPTP_QueryInterface,
  84. (ThreadPoolWorkAddRef*) DPTP_AddRef,
  85. (ThreadPoolWorkRelease*) DPTP_Release,
  86. #endif // ! DPNBUILD_LIBINTERFACE or ! DPNBUILD_ONLYONETHREAD or DPNBUILD_MULTIPLETHREADPOOLS
  87. DPTPW_QueueWorkItem,
  88. DPTPW_ScheduleTimer,
  89. DPTPW_StartTrackingFileIo,
  90. DPTPW_StopTrackingFileIo,
  91. DPTPW_CreateOverlapped,
  92. DPTPW_SubmitIoOperation,
  93. DPTPW_ReleaseOverlapped,
  94. DPTPW_CancelTimer,
  95. DPTPW_ResetCompletingTimer,
  96. DPTPW_WaitWhileWorking,
  97. DPTPW_SleepWhileWorking,
  98. DPTPW_RequestTotalThreadCount,
  99. DPTPW_GetThreadCount,
  100. DPTPW_GetWorkRecursionDepth,
  101. DPTPW_Preallocate,
  102. #ifdef DPNBUILD_MANDATORYTHREADS
  103. DPTPW_CreateMandatoryThread,
  104. #endif // DPNBUILD_MANDATORYTHREADS
  105. };
  106. #ifndef DPNBUILD_LIBINTERFACE
  107. IClassFactoryVtbl DPTPCF_Vtbl =
  108. {
  109. DPCF_QueryInterface, // dplay8\common\classfactory.cpp will implement the rest of these
  110. DPCF_AddRef,
  111. DPCF_Release,
  112. DPTPCF_CreateInstance,
  113. DPCF_LockServer
  114. };
  115. #undef DPF_MODNAME
  116. #define DPF_MODNAME "DPTPCF_CreateInstance"
  117. //=============================================================================
  118. // DPTPCF_CreateInstance
  119. //-----------------------------------------------------------------------------
  120. //
  121. // Description: Creates a new thread pool object COM instance.
  122. //
  123. // Arguments:
  124. // IClassFactory * pInterface - ?
  125. // LPUNKNOWN lpUnkOuter - ?
  126. // REFIID riid - ?
  127. // LPVOID * ppv - ?
  128. //
  129. // Returns: HRESULT
  130. //=============================================================================
  131. STDMETHODIMP DPTPCF_CreateInstance(IClassFactory * pInterface, LPUNKNOWN lpUnkOuter, REFIID riid, LPVOID * ppv)
  132. {
  133. HRESULT hResultCode;
  134. INTERFACE_LIST *pIntList;
  135. OBJECT_DATA *pObjectData;
  136. DPFX(DPFPREP, 6,"Parameters: pInterface [%p], lpUnkOuter [%p], riid [%p], ppv [%p]",pInterface,lpUnkOuter,&riid,ppv);
  137. if (pInterface == NULL)
  138. {
  139. DPFERR("Invalid COM interface specified");
  140. hResultCode = E_INVALIDARG;
  141. goto Exit;
  142. }
  143. if (lpUnkOuter != NULL)
  144. {
  145. hResultCode = CLASS_E_NOAGGREGATION;
  146. goto Exit;
  147. }
  148. if (ppv == NULL)
  149. {
  150. DPFERR("Invalid target interface pointer specified");
  151. hResultCode = E_INVALIDARG;
  152. goto Exit;
  153. }
  154. pObjectData = NULL;
  155. pIntList = NULL;
  156. if ((pObjectData = static_cast<OBJECT_DATA*>(DNMalloc(sizeof(OBJECT_DATA)))) == NULL)
  157. {
  158. DPFERR("Could not allocate object");
  159. hResultCode = E_OUTOFMEMORY;
  160. goto Failure;
  161. }
  162. // Object creation and initialization
  163. if ((hResultCode = DPTPCF_CreateObject(pInterface, &pObjectData->pvData,riid)) != S_OK)
  164. {
  165. DPFERR("Could not create object");
  166. goto Failure;
  167. }
  168. DPFX(DPFPREP, 7,"Created and initialized object");
  169. // Get requested interface
  170. if ((hResultCode = DPTPCF_CreateInterface(pObjectData,riid,&pIntList)) != S_OK)
  171. {
  172. DPTPCF_FreeObject(pObjectData->pvData);
  173. goto Failure;
  174. }
  175. DPFX(DPFPREP, 7,"Found interface");
  176. pObjectData->pIntList = pIntList;
  177. pObjectData->lRefCount = 1;
  178. DPTP_AddRef( pIntList );
  179. DNInterlockedIncrement(&g_lDPTPInterfaceCount);
  180. *ppv = pIntList;
  181. DPFX(DPFPREP, 7,"*ppv = [0x%p]",*ppv);
  182. hResultCode = S_OK;
  183. Exit:
  184. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  185. return(hResultCode);
  186. Failure:
  187. if (pObjectData)
  188. {
  189. DNFree(pObjectData);
  190. pObjectData = NULL;
  191. }
  192. goto Exit;
  193. } // DPTPCF_CreateInstance
  194. #undef DPF_MODNAME
  195. #define DPF_MODNAME "DPTPCF_CreateInterface"
  196. //=============================================================================
  197. // DPTPCF_CreateInterface
  198. //-----------------------------------------------------------------------------
  199. //
  200. // Description: Creates a new thread pool object interface.
  201. //
  202. // Arguments:
  203. // OBJECT_DATA * pObject - ?
  204. // REFIID riid - ?
  205. // INTERFACE_LIST ** ppv - ?
  206. //
  207. // Returns: HRESULT
  208. //=============================================================================
  209. HRESULT DPTPCF_CreateInterface(OBJECT_DATA * pObject,
  210. REFIID riid,
  211. INTERFACE_LIST ** const ppv)
  212. {
  213. INTERFACE_LIST *pIntNew;
  214. PVOID lpVtbl;
  215. HRESULT hResultCode;
  216. DPFX(DPFPREP, 6,"Parameters: pObject [%p], riid [%p], ppv [%p]",pObject,&riid,ppv);
  217. DNASSERT(pObject != NULL);
  218. DNASSERT(ppv != NULL);
  219. const DPTHREADPOOLOBJECT* pDPTPObject = ((DPTHREADPOOLOBJECT *)pObject->pvData);
  220. if (IsEqualIID(riid,IID_IUnknown))
  221. {
  222. DPFX(DPFPREP, 7,"riid = IID_IUnknown");
  223. lpVtbl = &DPTP_UnknownVtbl;
  224. }
  225. else if (IsEqualIID(riid,IID_IDirectPlay8ThreadPool))
  226. {
  227. DPFX(DPFPREP, 7,"riid = IID_IDirectPlay8ThreadPool");
  228. lpVtbl = &DPTP_Vtbl;
  229. }
  230. else if (IsEqualIID(riid,IID_IDirectPlay8ThreadPoolWork))
  231. {
  232. DPFX(DPFPREP, 7,"riid = IID_IDirectPlay8ThreadPoolWork");
  233. lpVtbl = &DPTPW_Vtbl;
  234. }
  235. else
  236. {
  237. DPFERR("riid not found !");
  238. hResultCode = E_NOINTERFACE;
  239. goto Exit;
  240. }
  241. if ((pIntNew = static_cast<INTERFACE_LIST*>(DNMalloc(sizeof(INTERFACE_LIST)))) == NULL)
  242. {
  243. DPFERR("Could not allocate interface");
  244. hResultCode = E_OUTOFMEMORY;
  245. goto Exit;
  246. }
  247. pIntNew->lpVtbl = lpVtbl;
  248. pIntNew->lRefCount = 0;
  249. pIntNew->pIntNext = NULL;
  250. DBG_CASSERT( sizeof( pIntNew->iid ) == sizeof( riid ) );
  251. memcpy( &(pIntNew->iid), &riid, sizeof( pIntNew->iid ) );
  252. pIntNew->pObject = pObject;
  253. *ppv = pIntNew;
  254. DPFX(DPFPREP, 7,"*ppv = [0x%p]",*ppv);
  255. hResultCode = S_OK;
  256. Exit:
  257. DPFX(DPFPREP, 6,"Returning: hResultCode = [%lx]",hResultCode);
  258. return(hResultCode);
  259. } // DPTPCF_CreateInterface
  260. #endif // ! DPNBUILD_LIBINTERFACE
  261. #undef DPF_MODNAME
  262. #define DPF_MODNAME "DPTPCF_CreateObject"
  263. //=============================================================================
  264. // DPTPCF_CreateObject
  265. //-----------------------------------------------------------------------------
  266. //
  267. // Description: Creates a new thread pool object.
  268. //
  269. // Arguments:
  270. // IClassFactory * pInterface - ?
  271. // PVOID * ppv - ?
  272. // REFIID riid - ?
  273. //
  274. // Returns: HRESULT
  275. //=============================================================================
  276. #ifdef DPNBUILD_LIBINTERFACE
  277. HRESULT DPTPCF_CreateObject(PVOID * ppv)
  278. #else // ! DPNBUILD_LIBINTERFACE
  279. HRESULT DPTPCF_CreateObject(IClassFactory * pInterface, PVOID * ppv, REFIID riid)
  280. #endif // ! DPNBUILD_LIBINTERFACE
  281. {
  282. HRESULT hr;
  283. DPTHREADPOOLOBJECT * pDPTPObject = NULL;
  284. #ifndef DPNBUILD_LIBINTERFACE
  285. const _IDirectPlayClassFactory * pDPClassFactory = (_IDirectPlayClassFactory*) pInterface;
  286. #endif // ! DPNBUILD_LIBINTERFACE
  287. BOOL fHaveGlobalThreadPoolLock = FALSE;
  288. BOOL fInittedLock = FALSE;
  289. #ifdef DPNBUILD_ONLYONEPROCESSOR
  290. BOOL fInittedWorkQueue = FALSE;
  291. #else // ! DPNBUILD_ONLYONEPROCESSOR
  292. SYSTEM_INFO SystemInfo;
  293. DWORD dwTemp;
  294. #endif // ! DPNBUILD_ONLYONEPROCESSOR
  295. #ifndef DPNBUILD_ONLYONETHREAD
  296. DWORD dwWorkerThreadTlsIndex = -1;
  297. #ifdef DBG
  298. DWORD dwError;
  299. #endif // DBG
  300. #endif // ! DPNBUILD_ONLYONETHREAD
  301. #ifndef DPNBUILD_LIBINTERFACE
  302. if ((riid != IID_IDirectPlay8ThreadPool) &&
  303. (riid != IID_IDirectPlay8ThreadPoolWork))
  304. {
  305. DPFX(DPFPREP, 0, "Requesting unknown interface from thread pool CLSID!");
  306. hr = E_NOINTERFACE;
  307. goto Failure;
  308. }
  309. #endif // ! DPNBUILD_LIBINTERFACE
  310. #ifndef DPNBUILD_MULTIPLETHREADPOOLS
  311. //
  312. // See if we've already allocated a thread pool object, because you only
  313. // get one per process.
  314. //
  315. DNEnterCriticalSection(&g_csGlobalThreadPoolLock);
  316. fHaveGlobalThreadPoolLock = TRUE;
  317. #if ((defined(DPNBUILD_LIBINTERFACE)) && (defined(DPNBUILD_ONLYONETHREAD)))
  318. DNASSERT(g_pDPTPObject == NULL);
  319. #else // ! DPNBUILD_LIBINTERFACE or ! DPNBUILD_ONLYONETHREAD
  320. if (g_pDPTPObject != NULL)
  321. {
  322. LONG lRefCount;
  323. #ifdef DPNBUILD_LIBINTERFACE
  324. DNASSERT(g_pDPTPObject->lRefCount >= 0);
  325. lRefCount = DNInterlockedIncrement(&g_pDPTPObject->lRefCount);
  326. #else // ! DPNBUILD_LIBINTERFACE
  327. lRefCount = ++g_dwDPTPRefCount;
  328. #endif // ! DPNBUILD_LIBINTERFACE
  329. DPFX(DPFPREP, 1, "Global thread pool object 0x%p already exists, ref count now %u.",
  330. g_pDPTPObject, lRefCount);
  331. (*ppv) = g_pDPTPObject;
  332. hr = S_OK;
  333. goto Exit;
  334. }
  335. #endif // ! DPNBUILD_LIBINTERFACE or ! DPNBUILD_ONLYONETHREAD
  336. #endif // ! DPNBUILD_MULTIPLETHREADPOOLS
  337. pDPTPObject = (DPTHREADPOOLOBJECT*) DNMalloc(sizeof(DPTHREADPOOLOBJECT));
  338. if (pDPTPObject == NULL)
  339. {
  340. DPFX(DPFPREP, 0, "Couldn't allocate memory for thread pool object!");
  341. hr = E_OUTOFMEMORY;
  342. goto Failure;
  343. }
  344. //
  345. // Zero out the entire structure to start.
  346. //
  347. memset(pDPTPObject, 0, sizeof(DPTHREADPOOLOBJECT));
  348. pDPTPObject->Sig[0] = 'D';
  349. pDPTPObject->Sig[1] = 'P';
  350. pDPTPObject->Sig[2] = 'T';
  351. pDPTPObject->Sig[3] = 'P';
  352. #ifndef DPNBUILD_NOPARAMVAL
  353. //
  354. // Start by assuming the user will want parameter validation.
  355. //
  356. pDPTPObject->dwFlags = DPTPOBJECTFLAG_USER_PARAMVALIDATION;
  357. #endif // ! DPNBUILD_NOPARAMVAL
  358. #ifndef DPNBUILD_ONLYONEPROCESSOR
  359. GetSystemInfo(&SystemInfo);
  360. pDPTPObject->dwNumCPUs = SystemInfo.dwNumberOfProcessors;
  361. #endif // ! DPNBUILD_ONLYONEPROCESSOR
  362. #ifndef DPNBUILD_ONLYONETHREAD
  363. pDPTPObject->dwTotalUserThreadCount = -1;
  364. pDPTPObject->dwTotalDesiredWorkThreadCount = -1;
  365. pDPTPObject->dwWorkRecursionCountTlsIndex = -1;
  366. pDPTPObject->lNumThreadCountChangeWaiters = 0;
  367. #if ((defined(DPNBUILD_MANDATORYTHREADS)) && (defined(DBG)))
  368. pDPTPObject->blMandatoryThreads.Initialize();
  369. #endif // DPNBUILD_MANDATORYTHREADS and DBG
  370. //
  371. // Allocate Thread Local Storage for tracking recursion on non-worker
  372. // threads.
  373. //
  374. pDPTPObject->dwWorkRecursionCountTlsIndex = TlsAlloc();
  375. if (pDPTPObject->dwWorkRecursionCountTlsIndex == -1)
  376. {
  377. #ifdef DBG
  378. dwError = GetLastError();
  379. DPFX(DPFPREP, 0, "Couldn't allocate Thread Local Storage slot for tracking recursion on non-worker threads (err = %u)!", dwError);
  380. #endif // DBG
  381. hr = E_OUTOFMEMORY;
  382. goto Failure;
  383. }
  384. //
  385. // Allocate Thread Local Storage for tracking worker threads.
  386. //
  387. dwWorkerThreadTlsIndex = TlsAlloc();
  388. if (dwWorkerThreadTlsIndex == -1)
  389. {
  390. #ifdef DBG
  391. dwError = GetLastError();
  392. DPFX(DPFPREP, 0, "Couldn't allocate Thread Local Storage slot for tracking worker threads (err = %u)!", dwError);
  393. #endif // DBG
  394. hr = E_OUTOFMEMORY;
  395. goto Failure;
  396. }
  397. //
  398. // Create a semaphore to release threads waiting on another thread changing
  399. // the thread count.
  400. //
  401. pDPTPObject->hThreadCountChangeComplete = DNCreateSemaphore(NULL, 0, 0xFFFF, NULL);
  402. if (pDPTPObject->hThreadCountChangeComplete == NULL)
  403. {
  404. #ifdef DBG
  405. dwError = GetLastError();
  406. DPFX(DPFPREP, 0, "Couldn't create thread count change complete semaphore (err = %u)!", dwError);
  407. #endif // DBG
  408. hr = E_OUTOFMEMORY;
  409. goto Failure;
  410. }
  411. #endif // ! DPNBUILD_ONLYONETHREAD
  412. #ifdef DPNBUILD_ONLYONEPROCESSOR
  413. #ifdef DPNBUILD_ONLYONETHREAD
  414. hr = InitializeWorkQueue(&pDPTPObject->WorkQueue);
  415. #else // ! DPNBUILD_ONLYONETHREAD
  416. hr = InitializeWorkQueue(&pDPTPObject->WorkQueue,
  417. NULL,
  418. NULL,
  419. dwWorkerThreadTlsIndex);
  420. #endif // ! DPNBUILD_ONLYONETHREAD
  421. if (hr != DPN_OK)
  422. {
  423. DPFX(DPFPREP, 0, "Couldn't initialize work queue!");
  424. goto Failure;
  425. }
  426. fInittedWorkQueue = TRUE;
  427. #else // ! DPNBUILD_ONLYONEPROCESSOR
  428. //
  429. // Allocate the array of work queues pointers, one for each processor.
  430. //
  431. pDPTPObject->papCPUWorkQueues = (DPTPWORKQUEUE**) DNMalloc(NUM_CPUS(pDPTPObject) * sizeof(DPTPWORKQUEUE*));
  432. if (pDPTPObject->papCPUWorkQueues == NULL)
  433. {
  434. DPFX(DPFPREP, 0, "Couldn't allocate memory for array of work queue pointers!");
  435. hr = E_OUTOFMEMORY;
  436. goto Failure;
  437. }
  438. //
  439. // Initialize each of the work queues.
  440. //
  441. for(dwTemp = 0; dwTemp < NUM_CPUS(pDPTPObject); dwTemp++)
  442. {
  443. #ifdef DPNBUILD_USEIOCOMPLETIONPORTS
  444. if (dwTemp > 0)
  445. {
  446. pDPTPObject->papCPUWorkQueues[dwTemp] = pDPTPObject->papCPUWorkQueues[0];
  447. }
  448. else
  449. #endif // DPNBUILD_USEIOCOMPLETIONPORTS
  450. {
  451. //
  452. // Allocate the actual work queues object.
  453. //
  454. pDPTPObject->papCPUWorkQueues[dwTemp] = (DPTPWORKQUEUE*) DNMalloc(sizeof(DPTPWORKQUEUE));
  455. if (pDPTPObject->papCPUWorkQueues[dwTemp] == NULL)
  456. {
  457. DPFX(DPFPREP, 0, "Couldn't allocate memory for work queue %u!", dwTemp);
  458. hr = E_OUTOFMEMORY;
  459. goto Failure;
  460. }
  461. #ifdef DPNBUILD_ONLYONETHREAD
  462. hr = InitializeWorkQueue(WORKQUEUE_FOR_CPU(pDPTPObject, dwTemp),
  463. dwTemp);
  464. #else // ! DPNBUILD_ONLYONETHREAD
  465. hr = InitializeWorkQueue(WORKQUEUE_FOR_CPU(pDPTPObject, dwTemp),
  466. dwTemp,
  467. NULL,
  468. NULL,
  469. dwWorkerThreadTlsIndex);
  470. #endif // ! DPNBUILD_ONLYONETHREAD
  471. if (hr != DPN_OK)
  472. {
  473. DPFX(DPFPREP, 0, "Couldn't intialize work queue %u!", dwTemp);
  474. DNFree(pDPTPObject->papCPUWorkQueues[dwTemp]);
  475. pDPTPObject->papCPUWorkQueues[dwTemp] = NULL;
  476. goto Failure;
  477. }
  478. }
  479. }
  480. #endif // ! DPNBUILD_ONLYONEPROCESSOR
  481. if (! DNInitializeCriticalSection(&pDPTPObject->csLock))
  482. {
  483. DPFX(DPFPREP, 0, "Couldn't initialize object lock!");
  484. hr = E_OUTOFMEMORY;
  485. goto Failure;
  486. }
  487. fInittedLock = TRUE;
  488. #ifdef DPNBUILD_LIBINTERFACE
  489. //
  490. // For lib interface builds, the Vtbl and reference are embedded in the
  491. // object directly.
  492. //
  493. #ifdef DPNBUILD_ONLYONETHREAD
  494. pDPTPObject->lpVtbl = &DPTPW_Vtbl;
  495. #ifdef DPNBUILD_MULTIPLETHREADPOOLS
  496. pDPTPObject->lRefCount = 1;
  497. #endif // DPNBUILD_MULTIPLETHREADPOOLS
  498. #else // ! DPNBUILD_ONLYONETHREAD
  499. // We assume only the work interface is created. The ID will have to be
  500. // passed in or something (see DNCF_CreateObject).
  501. #pragma error("Building with DPNBUILD_LIBINTERFACE but not DPNBUILD_ONLYONETHREAD requires minor changes")
  502. #endif // ! DPNBUILD_ONLYONETHREAD
  503. #endif // DPNBUILD_LIBINTERFACE
  504. #ifndef DPNBUILD_MULTIPLETHREADPOOLS
  505. //
  506. // Store this as the only object allowed in this process.
  507. //
  508. g_pDPTPObject = pDPTPObject;
  509. #ifndef DPNBUILD_LIBINTERFACE
  510. g_dwDPTPRefCount++;
  511. #endif // ! DPNBUILD_LIBINTERFACE
  512. #endif // ! DPNBUILD_MULTIPLETHREADPOOLS
  513. DPFX(DPFPREP, 2, "Created object 0x%p.", pDPTPObject);
  514. (*ppv) = pDPTPObject;
  515. Exit:
  516. #ifndef DPNBUILD_MULTIPLETHREADPOOLS
  517. //
  518. // See if we've already allocated a thread pool object, because you only
  519. // get one per process.
  520. //
  521. if (fHaveGlobalThreadPoolLock)
  522. {
  523. DNLeaveCriticalSection(&g_csGlobalThreadPoolLock);
  524. fHaveGlobalThreadPoolLock = FALSE;
  525. }
  526. #endif // ! DPNBUILD_MULTIPLETHREADPOOLS
  527. return hr;
  528. Failure:
  529. if (pDPTPObject != NULL)
  530. {
  531. if (fInittedLock)
  532. {
  533. DNDeleteCriticalSection(&pDPTPObject->csLock);
  534. fInittedLock = FALSE;
  535. }
  536. #ifdef DPNBUILD_ONLYONEPROCESSOR
  537. if (fInittedWorkQueue)
  538. {
  539. DeinitializeWorkQueue(&pDPTPObject->WorkQueue);
  540. fInittedWorkQueue = FALSE;
  541. }
  542. #else // ! DPNBUILD_ONLYONEPROCESSOR
  543. if (pDPTPObject->papCPUWorkQueues != NULL)
  544. {
  545. #ifdef DPNBUILD_USEIOCOMPLETIONPORTS
  546. dwTemp = 0;
  547. #else // ! DPNBUILD_USEIOCOMPLETIONPORTS
  548. for(dwTemp = 0; dwTemp < NUM_CPUS(pDPTPObject); dwTemp++)
  549. #endif // ! DPNBUILD_USEIOCOMPLETIONPORTS
  550. {
  551. if (WORKQUEUE_FOR_CPU(pDPTPObject, dwTemp) != NULL)
  552. {
  553. DeinitializeWorkQueue(WORKQUEUE_FOR_CPU(pDPTPObject, dwTemp));
  554. DNFree(pDPTPObject->papCPUWorkQueues[dwTemp]);
  555. }
  556. }
  557. DNFree(pDPTPObject->papCPUWorkQueues);
  558. pDPTPObject->papCPUWorkQueues = NULL;
  559. }
  560. #endif // ! DPNBUILD_ONLYONEPROCESSOR
  561. #ifndef DPNBUILD_ONLYONETHREAD
  562. if (pDPTPObject->hThreadCountChangeComplete != NULL)
  563. {
  564. DNCloseHandle(pDPTPObject->hThreadCountChangeComplete);
  565. pDPTPObject->hThreadCountChangeComplete = NULL;
  566. }
  567. if (dwWorkerThreadTlsIndex != -1)
  568. {
  569. TlsFree(dwWorkerThreadTlsIndex);
  570. dwWorkerThreadTlsIndex = -1;
  571. }
  572. if (pDPTPObject->dwWorkRecursionCountTlsIndex != -1)
  573. {
  574. TlsFree(pDPTPObject->dwWorkRecursionCountTlsIndex);
  575. pDPTPObject->dwWorkRecursionCountTlsIndex = -1;
  576. }
  577. #endif // ! DPNBUILD_ONLYONETHREAD
  578. DNFree(pDPTPObject);
  579. pDPTPObject = NULL;
  580. }
  581. goto Exit;
  582. } // DPTPCF_CreateObject
  583. #if ((defined(DPNBUILD_LIBINTERFACE)) && (defined(DPNBUILD_ONLYONETHREAD)) && (! defined(DPNBUILD_MULTIPLETHREADPOOLS)))
  584. #undef DPF_MODNAME
  585. #define DPF_MODNAME "DPTPCF_GetObject"
  586. //=============================================================================
  587. // DPTPCF_GetObject
  588. //-----------------------------------------------------------------------------
  589. //
  590. // Description: Gets a pointer to the global thread pool object.
  591. //
  592. // Arguments:
  593. // PVOID * ppv - ?
  594. //
  595. // Returns: None
  596. //=============================================================================
  597. void DPTPCF_GetObject(PVOID * ppv)
  598. {
  599. (*ppv) = g_pDPTPObject;
  600. } // DPTPCF_GetObject
  601. #endif // DPNBUILD_LIBINTERFACE DPNBUILD_ONLYONETHREAD and ! DPNBUILD_MULTIPLETHREADPOOLS
  602. #undef DPF_MODNAME
  603. #define DPF_MODNAME "DPTPCF_FreeObject"
  604. //=============================================================================
  605. // DPTPCF_FreeObject
  606. //-----------------------------------------------------------------------------
  607. //
  608. // Description: Frees an existing thread pool object.
  609. //
  610. // Arguments:
  611. // PVOID pvObject - ?
  612. //
  613. // Returns: HRESULT
  614. //=============================================================================
  615. HRESULT DPTPCF_FreeObject(PVOID pvObject)
  616. {
  617. DPTHREADPOOLOBJECT * pDPTPObject = (DPTHREADPOOLOBJECT*) pvObject;
  618. #ifndef DPNBUILD_ONLYONEPROCESSOR
  619. DWORD dwTemp;
  620. #endif // ! DPNBUILD_ONLYONEPROCESSOR
  621. #ifndef DPNBUILD_ONLYONETHREAD
  622. DWORD dwWorkerThreadTlsIndex;
  623. #endif // ! DPNBUILD_ONLYONETHREAD
  624. DPFX(DPFPREP, 4, "Parameters: (0x%p)", pvObject);
  625. #ifndef DPNBUILD_MULTIPLETHREADPOOLS
  626. DNEnterCriticalSection(&g_csGlobalThreadPoolLock);
  627. DNASSERT(pDPTPObject == g_pDPTPObject);
  628. #ifdef DPNBUILD_LIBINTERFACE
  629. #ifndef DPNBUILD_ONLYONETHREAD
  630. //
  631. // It's possible somebody just took a reference on the object, so we may
  632. // need to bail.
  633. //
  634. DNASSERT(pDPTPObject->lRefCount >= 0);
  635. if (pDPTPObject->lRefCount > 0)
  636. {
  637. DPFX(DPFPREP, 1, "Global thread pool object 0x%p just got referenced (refcount now %i), not destroying.",
  638. g_pDPTPObject, pDPTPObject->lRefCount);
  639. DNLeaveCriticalSection(&g_csGlobalThreadPoolLock);
  640. return S_OK;
  641. }
  642. #endif // ! DPNBUILD_ONLYONETHREAD
  643. #else // ! DPNBUILD_LIBINTERFACE
  644. //
  645. // Reduce the global object count. There might be other users, though.
  646. //
  647. g_dwDPTPRefCount--;
  648. if (g_dwDPTPRefCount != 0)
  649. {
  650. DPFX(DPFPREP, 1, "Global thread pool object 0x%p still has other users, refcount now %u.",
  651. g_pDPTPObject, g_dwDPTPRefCount);
  652. DNLeaveCriticalSection(&g_csGlobalThreadPoolLock);
  653. return S_OK;
  654. }
  655. #endif // ! DPNBUILD_LIBINTERFACE
  656. g_pDPTPObject = NULL;
  657. DNLeaveCriticalSection(&g_csGlobalThreadPoolLock);
  658. #endif // ! DPNBUILD_MULTIPLETHREADPOOLS
  659. //
  660. // Double check to make sure the object is closed.
  661. //
  662. if (pDPTPObject->dwFlags & DPTPOBJECTFLAG_USER_INITIALIZED)
  663. {
  664. DPFX(DPFPREP, 0, "User has not closed IDirectPlay8ThreadPool interface!");
  665. DNASSERT(FALSE);
  666. //
  667. // Forcefully mark the user's interface as no longer available.
  668. //
  669. pDPTPObject->dwFlags &= ~DPTPOBJECTFLAG_USER_INITIALIZED;
  670. }
  671. #ifdef DPNBUILD_LIBINTERFACE
  672. //
  673. // For lib interface builds, the reference is embedded in the object
  674. // directly.
  675. //
  676. #if ((! defined(DPNBUILD_ONLYONETHREAD)) || (defined(DPNBUILD_MULTIPLETHREADPOOLS)))
  677. DNASSERT(pDPTPObject->lRefCount == 0);
  678. #endif // ! DPNBUILD_ONLYONETHREAD or DPNBUILD_MULTIPLETHREADPOOLS
  679. #endif // DPNBUILD_LIBINTERFACE
  680. #ifndef DPNBUILD_ONLYONETHREAD
  681. //
  682. // Save the Thread Local Storage index value before cleaning up the work
  683. // queues. Since all work queues share the same TLS index, just use the
  684. // first CPU as representative of all of them.
  685. //
  686. dwWorkerThreadTlsIndex = (WORKQUEUE_FOR_CPU(pDPTPObject, 0))->dwWorkerThreadTlsIndex;
  687. #endif // ! DPNBUILD_ONLYONETHREAD
  688. DNDeleteCriticalSection(&pDPTPObject->csLock);
  689. #ifdef DPNBUILD_ONLYONEPROCESSOR
  690. DeinitializeWorkQueue(&pDPTPObject->WorkQueue);
  691. #else // ! DPNBUILD_ONLYONEPROCESSOR
  692. #ifdef DPNBUILD_USEIOCOMPLETIONPORTS
  693. dwTemp = 0;
  694. #else // ! DPNBUILD_USEIOCOMPLETIONPORTS
  695. for(dwTemp = 0; dwTemp < NUM_CPUS(pDPTPObject); dwTemp++)
  696. #endif // ! DPNBUILD_USEIOCOMPLETIONPORTS
  697. {
  698. DeinitializeWorkQueue(WORKQUEUE_FOR_CPU(pDPTPObject, dwTemp));
  699. DNFree(pDPTPObject->papCPUWorkQueues[dwTemp]);
  700. }
  701. DNFree(pDPTPObject->papCPUWorkQueues);
  702. pDPTPObject->papCPUWorkQueues = NULL;
  703. #endif // ! DPNBUILD_ONLYONEPROCESSOR
  704. #ifndef DPNBUILD_ONLYONETHREAD
  705. //
  706. // Close the thread count change complete semaphore.
  707. //
  708. DNASSERT(pDPTPObject->lNumThreadCountChangeWaiters == 0);
  709. DNCloseHandle(pDPTPObject->hThreadCountChangeComplete);
  710. pDPTPObject->hThreadCountChangeComplete = NULL;
  711. //
  712. // Free the Thread Local Storage slot for tracking worker threads.
  713. //
  714. TlsFree(dwWorkerThreadTlsIndex);
  715. dwWorkerThreadTlsIndex = -1;
  716. //
  717. // Free the Thread Local Storage slot for tracking recursion on non-worker
  718. // threads.
  719. //
  720. TlsFree(pDPTPObject->dwWorkRecursionCountTlsIndex);
  721. pDPTPObject->dwWorkRecursionCountTlsIndex = -1;
  722. #ifdef DPNBUILD_MANDATORYTHREADS
  723. DNASSERT(pDPTPObject->dwMandatoryThreadCount == 0);
  724. #endif // DPNBUILD_MANDATORYTHREADS
  725. #endif // ! DPNBUILD_ONLYONETHREAD
  726. //
  727. // Make sure there aren't any flags set except possibly
  728. // USER_PARAMVALIDATION.
  729. //
  730. DNASSERT(! (pDPTPObject->dwFlags & ~(DPTPOBJECTFLAG_USER_PARAMVALIDATION)));
  731. DNFree(pDPTPObject);
  732. pDPTPObject = NULL;
  733. DPFX(DPFPREP, 4, "Returning: [S_OK]");
  734. return S_OK;
  735. } // DPTPCF_FreeObject
  736. #ifdef DPNBUILD_LIBINTERFACE
  737. #if ((! defined(DPNBUILD_ONLYONETHREAD)) || (defined(DPNBUILD_MULTIPLETHREADPOOLS)))
  738. #undef DPF_MODNAME
  739. #define DPF_MODNAME "DPTP_QueryInterface"
  740. //=============================================================================
  741. // DPTP_QueryInterface
  742. //-----------------------------------------------------------------------------
  743. //
  744. // Description: Queries for a new interface for an existing object.
  745. //
  746. // Arguments:
  747. // void * pvInterface - ?
  748. // DP8REFIID riid - ?
  749. // void ** ppv - ?
  750. //
  751. // Returns: HRESULT
  752. //=============================================================================
  753. STDMETHODIMP DPTP_QueryInterface(void * pvInterface,
  754. DP8REFIID riid,
  755. void ** ppv)
  756. {
  757. HRESULT hResultCode;
  758. DPFX(DPFPREP, 2,"Parameters: pvInterface [0x%p], riid [0x%p], ppv [0x%p]",pvInterface,&riid,ppv);
  759. //
  760. // Get the object Vtbl and make sure it's one of ours
  761. //
  762. if (*((PVOID*) pvInterface) == (&DPTPW_Vtbl))
  763. {
  764. //
  765. // It is one of our objects. Assume the IID is not specified, so just
  766. // return a reference to the existing object.
  767. //
  768. DNASSERT(riid == 0);
  769. hResultCode = S_OK;
  770. DPTP_AddRef(pvInterface);
  771. *ppv = pvInterface;
  772. }
  773. else
  774. {
  775. DPFX(DPFPREP, 0, "Invalid object!");
  776. hResultCode = E_POINTER;
  777. }
  778. DPFX(DPFPREP, 2,"Returning: [0x%lx]",hResultCode);
  779. return(hResultCode);
  780. } // DPTP_QueryInterface
  781. #undef DPF_MODNAME
  782. #define DPF_MODNAME "DPTP_AddRef"
  783. //=============================================================================
  784. // DPTP_AddRef
  785. //-----------------------------------------------------------------------------
  786. //
  787. // Description: Adds a reference to a thread pool interface.
  788. //
  789. // Arguments:
  790. // void * pvInterface - ?
  791. //
  792. // Returns: ULONG
  793. //=============================================================================
  794. STDMETHODIMP_(ULONG) DPTP_AddRef(void * pvInterface)
  795. {
  796. DPTHREADPOOLOBJECT * pDPTPObject;
  797. LONG lRefCount;
  798. DPFX(DPFPREP, 2,"Parameters: pInterface [0x%p]",pvInterface);
  799. #ifndef DPNBUILD_NOPARAMVAL
  800. if (pvInterface == NULL)
  801. {
  802. DPFERR("Invalid COM interface specified");
  803. lRefCount = 0;
  804. goto Exit;
  805. }
  806. #endif // ! DPNBUILD_NOPARAMVAL
  807. pDPTPObject = static_cast<DPTHREADPOOLOBJECT*>(pvInterface);
  808. lRefCount = DNInterlockedIncrement(&pDPTPObject->lRefCount);
  809. DNASSERT(lRefCount > 0);
  810. DPFX(DPFPREP, 5,"New lRefCount [%ld]",lRefCount);
  811. #ifndef DPNBUILD_NOPARAMVAL
  812. Exit:
  813. #endif // ! DPNBUILD_NOPARAMVAL
  814. DPFX(DPFPREP, 2,"Returning: lRefCount [%ld]",lRefCount);
  815. return(lRefCount);
  816. } // DPTP_AddRef
  817. #undef DPF_MODNAME
  818. #define DPF_MODNAME "DPTP_Release"
  819. //=============================================================================
  820. // DPTP_Release
  821. //-----------------------------------------------------------------------------
  822. //
  823. // Description: Removes a reference from a thread pool interface. If it is
  824. // the last reference on the object, the object is destroyed.
  825. //
  826. // Arguments:
  827. // void * pvInterface - ?
  828. //
  829. // Returns: ULONG
  830. //=============================================================================
  831. STDMETHODIMP_(ULONG) DPTP_Release(void * pvInterface)
  832. {
  833. DPTHREADPOOLOBJECT * pDPTPObject;
  834. LONG lRefCount;
  835. DPFX(DPFPREP, 2,"Parameters: pInterface [%p]",pvInterface);
  836. #ifndef DPNBUILD_NOPARAMVAL
  837. if (pvInterface == NULL)
  838. {
  839. DPFERR("Invalid COM interface specified");
  840. lRefCount = 0;
  841. goto Exit;
  842. }
  843. #endif // ! DPNBUILD_NOPARAMVAL
  844. pDPTPObject = static_cast<DPTHREADPOOLOBJECT*>(pvInterface);
  845. DNASSERT(pDPTPObject->lRefCount > 0);
  846. lRefCount = DNInterlockedDecrement(&pDPTPObject->lRefCount);
  847. DPFX(DPFPREP, 5,"New lRefCount [%ld]",lRefCount);
  848. if (lRefCount == 0)
  849. {
  850. // Free object here
  851. DPFX(DPFPREP, 5,"Free object");
  852. DPTPCF_FreeObject(pvInterface);
  853. }
  854. #ifndef DPNBUILD_NOPARAMVAL
  855. Exit:
  856. #endif // ! DPNBUILD_NOPARAMVAL
  857. DPFX(DPFPREP, 2,"Returning: lRefCount [%ld]",lRefCount);
  858. return(lRefCount);
  859. } // DPTP_Release
  860. #endif // ! DPNBUILD_ONLYONETHREAD or DPNBUILD_MULTIPLETHREADPOOLS
  861. #else // ! DPNBUILD_LIBINTERFACE
  862. #undef DPF_MODNAME
  863. #define DPF_MODNAME "DPTPCF_FindInterface"
  864. //=============================================================================
  865. // DPTPCF_FindInterface
  866. //-----------------------------------------------------------------------------
  867. //
  868. // Description: Locates an interface for a given object.
  869. //
  870. // Initialize must have been called.
  871. //
  872. // Arguments:
  873. // void * pvInterface - ?
  874. // REFIID riid - ?
  875. //
  876. // Returns: HRESULT
  877. //=============================================================================
  878. INTERFACE_LIST * DPTPCF_FindInterface(void * pvInterface,
  879. REFIID riid)
  880. {
  881. INTERFACE_LIST * pInterfaceList;
  882. DPFX(DPFPREP, 6,"Parameters: (0x%p, 0x%p)", pvInterface, &riid);
  883. DNASSERT(pvInterface != NULL);
  884. pInterfaceList = (static_cast<INTERFACE_LIST*>(pvInterface))->pObject->pIntList; // Find first interface
  885. while (pInterfaceList != NULL)
  886. {
  887. if (IsEqualIID(riid, pInterfaceList->iid))
  888. {
  889. break;
  890. }
  891. pInterfaceList = pInterfaceList->pIntNext;
  892. }
  893. DPFX(DPFPREP, 6,"Returning: [0x%p]", pInterfaceList);
  894. return pInterfaceList;
  895. } // DPTPCF_FindInterface
  896. #undef DPF_MODNAME
  897. #define DPF_MODNAME "DPTP_QueryInterface"
  898. //=============================================================================
  899. // DPTP_QueryInterface
  900. //-----------------------------------------------------------------------------
  901. //
  902. // Description: Queries for a new interface for an existing object.
  903. //
  904. // Arguments:
  905. // void * pvInterface - ?
  906. // REFIID riid - ?
  907. // void ** ppv - ?
  908. //
  909. // Returns: HRESULT
  910. //=============================================================================
  911. STDMETHODIMP DPTP_QueryInterface(void * pvInterface,
  912. DP8REFIID riid,
  913. void ** ppv)
  914. {
  915. INTERFACE_LIST *pIntList;
  916. INTERFACE_LIST *pIntNew;
  917. HRESULT hResultCode;
  918. DPFX(DPFPREP, 2,"Parameters: pvInterface [0x%p], riid [0x%p], ppv [0x%p]",pvInterface,&riid,ppv);
  919. #ifndef DPNBUILD_NOPARAMVAL
  920. if (pvInterface == NULL)
  921. {
  922. DPFERR("Invalid COM interface specified");
  923. hResultCode = E_INVALIDARG;
  924. goto Exit;
  925. }
  926. if (ppv == NULL)
  927. {
  928. DPFERR("Invalid target interface pointer specified");
  929. hResultCode = E_POINTER;
  930. goto Exit;
  931. }
  932. #endif // ! DPNBUILD_NOPARAMVAL
  933. if ((pIntList = DPTPCF_FindInterface(pvInterface,riid)) == NULL)
  934. { // Interface must be created
  935. pIntList = (static_cast<INTERFACE_LIST*>(pvInterface))->pObject->pIntList;
  936. if ((hResultCode = DPTPCF_CreateInterface(pIntList->pObject,riid,&pIntNew)) != S_OK)
  937. {
  938. goto Exit;
  939. }
  940. pIntNew->pIntNext = pIntList;
  941. pIntList->pObject->pIntList = pIntNew;
  942. pIntList = pIntNew;
  943. }
  944. if (pIntList->lRefCount == 0) // New interface exposed
  945. {
  946. DNInterlockedIncrement(&pIntList->pObject->lRefCount);
  947. }
  948. DNInterlockedIncrement(&pIntList->lRefCount);
  949. *ppv = static_cast<void*>(pIntList);
  950. DPFX(DPFPREP, 5,"*ppv = [0x%p]", *ppv);
  951. hResultCode = S_OK;
  952. Exit:
  953. DPFX(DPFPREP, 2,"Returning: [0x%lx]",hResultCode);
  954. return(hResultCode);
  955. } // DPTP_QueryInterface
  956. #undef DPF_MODNAME
  957. #define DPF_MODNAME "DPTP_AddRef"
  958. //=============================================================================
  959. // DPTP_AddRef
  960. //-----------------------------------------------------------------------------
  961. //
  962. // Description: Adds a reference to a thread pool interface.
  963. //
  964. // Arguments:
  965. // void * pvInterface - ?
  966. //
  967. // Returns: ULONG
  968. //=============================================================================
  969. STDMETHODIMP_(ULONG) DPTP_AddRef(void * pvInterface)
  970. {
  971. INTERFACE_LIST *pIntList;
  972. LONG lRefCount;
  973. DPFX(DPFPREP, 2,"Parameters: pInterface [0x%p]",pvInterface);
  974. #ifndef DPNBUILD_NOPARAMVAL
  975. if (pvInterface == NULL)
  976. {
  977. DPFERR("Invalid COM interface specified");
  978. lRefCount = 0;
  979. goto Exit;
  980. }
  981. #endif // ! DPNBUILD_NOPARAMVAL
  982. pIntList = static_cast<INTERFACE_LIST*>(pvInterface);
  983. lRefCount = DNInterlockedIncrement(&pIntList->lRefCount);
  984. DPFX(DPFPREP, 5,"New lRefCount [%ld]",lRefCount);
  985. #ifndef DPNBUILD_NOPARAMVAL
  986. Exit:
  987. #endif // !DPNBUILD_NOPARAMVAL
  988. DPFX(DPFPREP, 2,"Returning: lRefCount [%ld]",lRefCount);
  989. return(lRefCount);
  990. } // DPTP_AddRef
  991. #undef DPF_MODNAME
  992. #define DPF_MODNAME "DPTP_Release"
  993. //=============================================================================
  994. // DPTP_Release
  995. //-----------------------------------------------------------------------------
  996. //
  997. // Description: Removes a reference from a thread pool interface. If it is
  998. // the last reference on the object, the object is destroyed.
  999. //
  1000. // Arguments:
  1001. // void * pvInterface - ?
  1002. //
  1003. // Returns: ULONG
  1004. //=============================================================================
  1005. STDMETHODIMP_(ULONG) DPTP_Release(void * pvInterface)
  1006. {
  1007. INTERFACE_LIST *pIntList;
  1008. INTERFACE_LIST *pIntCurrent;
  1009. LONG lRefCount;
  1010. LONG lObjRefCount;
  1011. DPFX(DPFPREP, 2,"Parameters: pInterface [%p]",pvInterface);
  1012. #ifndef DPNBUILD_NOPARAMVAL
  1013. if (pvInterface == NULL)
  1014. {
  1015. DPFERR("Invalid COM interface specified");
  1016. lRefCount = 0;
  1017. goto Exit;
  1018. }
  1019. #endif // ! DPNBUILD_NOPARAMVAL
  1020. pIntList = static_cast<INTERFACE_LIST*>(pvInterface);
  1021. lRefCount = DNInterlockedDecrement( &pIntList->lRefCount );
  1022. DPFX(DPFPREP, 5,"New lRefCount [%ld]",lRefCount);
  1023. if (lRefCount == 0)
  1024. {
  1025. //
  1026. // Decrease object's interface count
  1027. //
  1028. lObjRefCount = DNInterlockedDecrement( &pIntList->pObject->lRefCount );
  1029. //
  1030. // Free object and interfaces
  1031. //
  1032. if (lObjRefCount == 0)
  1033. {
  1034. // Free object here
  1035. DPFX(DPFPREP, 5,"Free object");
  1036. DPTPCF_FreeObject(pIntList->pObject->pvData);
  1037. pIntList = pIntList->pObject->pIntList; // Get head of interface list
  1038. DNFree(pIntList->pObject);
  1039. // Free Interfaces
  1040. DPFX(DPFPREP, 5,"Free interfaces");
  1041. while(pIntList != NULL)
  1042. {
  1043. pIntCurrent = pIntList;
  1044. pIntList = pIntList->pIntNext;
  1045. DNFree(pIntCurrent);
  1046. }
  1047. DNInterlockedDecrement(&g_lDPTPInterfaceCount);
  1048. }
  1049. }
  1050. #ifndef DPNBUILD_NOPARAMVAL
  1051. Exit:
  1052. #endif // ! DPNBUILD_NOPARAMVAL
  1053. DPFX(DPFPREP, 2,"Returning: lRefCount [%ld]",lRefCount);
  1054. return(lRefCount);
  1055. } // DPTP_Release
  1056. #endif // ! DPNBUILD_LIBINTERFACE