Source code of Windows XP (NT5)
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.

916 lines
24 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1995 - 2000 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: ContextCFPM.h
  6. * Content: fixed pool manager for classes that takes into account contexts
  7. *
  8. * History:
  9. * Date By Reason
  10. * ====== == ======
  11. * 12-18-97 aarono Original
  12. * 11-06-98 ejs Add custom handler for Release function
  13. * 04-12-99 jtk Trimmed unused functions and parameters, added size assert
  14. * 01-31-2000 jtk Added code to check for items already being in the pool on Release().
  15. * 02-08-2000 jtk Derived from ClassFPM.h
  16. * 03-20-2001 vanceo Added thread-local versions
  17. ***************************************************************************/
  18. #ifndef __CONTEXT_CLASS_FPM_H__
  19. #define __CONTEXT_CLASS_FPM_H__
  20. #undef DPF_SUBCOMP
  21. #define DPF_SUBCOMP DN_SUBCOMP_COMMON
  22. #define TRACK_POOL_STATS
  23. //**********************************************************************
  24. // Constant definitions
  25. //**********************************************************************
  26. #define CONTEXTCFPM_BLANK_NODE_VALUE 0x5AA5817E
  27. #define CHECK_FOR_DUPLICATE_CONTEXTCFPM_RELEASE
  28. //**********************************************************************
  29. // Macro definitions
  30. //**********************************************************************
  31. #ifndef OFFSETOF
  32. // Macro to compute the offset of an element inside of a larger structure (copied from MSDEV's STDLIB.H)
  33. #define OFFSETOF(s,m) ( (INT_PTR) &(((s *)0)->m) )
  34. #define __LOCAL_OFFSETOF_DEFINED__
  35. #endif // OFFSETOF
  36. #ifndef CONTAINING_OBJECT
  37. #define CONTAINING_OBJECT(b,t,m) (reinterpret_cast<t*>(&reinterpret_cast<BYTE*>(b)[-OFFSETOF(t,m)]))
  38. #endif
  39. //**********************************************************************
  40. // Structure definitions
  41. //**********************************************************************
  42. //**********************************************************************
  43. // Variable definitions
  44. //**********************************************************************
  45. //**********************************************************************
  46. // Function prototypes
  47. //**********************************************************************
  48. //**********************************************************************
  49. // Class definitions
  50. //**********************************************************************
  51. // class to act as a link in the pool
  52. template< class T >
  53. class CContextClassFPMPoolNode
  54. {
  55. public:
  56. CContextClassFPMPoolNode() { m_pNext = NULL; }
  57. ~CContextClassFPMPoolNode() {};
  58. CContextClassFPMPoolNode *m_pNext;
  59. T m_Item;
  60. protected:
  61. private:
  62. };
  63. // class to manage the pool
  64. template< class T, class S >
  65. class CContextFixedPool
  66. {
  67. public:
  68. CContextFixedPool();
  69. ~CContextFixedPool();
  70. typedef BOOL (T::*PBOOLCALLBACK)( S *const pContext );
  71. typedef void (T::*PVOIDCONTEXTCALLBACK)( S *const pContext );
  72. typedef void (T::*PVOIDCALLBACK)( void );
  73. BOOL Initialize( PBOOLCALLBACK pAllocFunction, PVOIDCONTEXTCALLBACK pInitFunction, PVOIDCALLBACK pReleaseFunction, PVOIDCALLBACK pDeallocFunction );
  74. void Deinitialize( void ) { DEBUG_ONLY( m_fInitialized = FALSE ); }
  75. T *Get( S *const pContext );
  76. void Release( T *const pItem );
  77. protected:
  78. private:
  79. PBOOLCALLBACK m_pAllocFunction;
  80. PVOIDCONTEXTCALLBACK m_pInitFunction;
  81. PVOIDCALLBACK m_pReleaseFunction;
  82. PVOIDCALLBACK m_pDeallocFunction;
  83. CContextClassFPMPoolNode< T > *m_pPool; // pointer to list of available elements
  84. DEBUG_ONLY( BOOL m_fInitialized );
  85. DEBUG_ONLY( UINT_PTR m_uOutstandingItemCount );
  86. };
  87. //**********************************************************************
  88. // Class function definitions
  89. //**********************************************************************
  90. //**********************************************************************
  91. // ------------------------------
  92. // CContextFixedPool::CContextFixedPool - constructor
  93. //
  94. // Entry: Nothing
  95. //
  96. // Exit: Nothing
  97. // ------------------------------
  98. #undef DPF_MODNAME
  99. #define DPF_MODNAME "CContextFixedPool::CContextFixedPool"
  100. template< class T, class S >
  101. CContextFixedPool< T, S >::CContextFixedPool():
  102. m_pAllocFunction( NULL ),
  103. m_pInitFunction( NULL ),
  104. m_pReleaseFunction( NULL ),
  105. m_pDeallocFunction( NULL ),
  106. m_pPool( NULL )
  107. {
  108. DEBUG_ONLY( m_uOutstandingItemCount = 0 );
  109. DEBUG_ONLY( m_fInitialized = FALSE );
  110. }
  111. //**********************************************************************
  112. //**********************************************************************
  113. // ------------------------------
  114. // CContextFixedPool::~CContextFixedPool - destructor
  115. //
  116. // Entry: Nothing
  117. //
  118. // Exit: Nothing
  119. // ------------------------------
  120. #undef DPF_MODNAME
  121. #define DPF_MODNAME "CContextFixedPool::~CContextFixedPool"
  122. template< class T, class S >
  123. CContextFixedPool< T, S >::~CContextFixedPool()
  124. {
  125. DEBUG_ONLY( DNASSERT( m_uOutstandingItemCount == 0 ) );
  126. while ( m_pPool != NULL )
  127. {
  128. CContextClassFPMPoolNode< T > *pNode;
  129. DEBUG_ONLY( DNASSERT( m_fInitialized == FALSE ) );
  130. pNode = m_pPool;
  131. m_pPool = m_pPool->m_pNext;
  132. (pNode->m_Item.*m_pDeallocFunction)();
  133. delete pNode;
  134. }
  135. DEBUG_ONLY( DNASSERT( m_fInitialized == FALSE ) );
  136. }
  137. //**********************************************************************
  138. //**********************************************************************
  139. // ------------------------------
  140. // CContextFixedPool::Initialize - initialize pool
  141. //
  142. // Entry: Pointer to function to call when a new entry is allocated
  143. // Pointer to function to call when a new entry is removed from the pool
  144. // Pointer to function to call when an entry is returned to the pool
  145. // Pointer to function to call when an entry is deallocated
  146. //
  147. // Exit: Nothing
  148. // ------------------------------
  149. #undef DPF_MODNAME
  150. #define DPF_MODNAME "CContextFixedPool::Initialize"
  151. template< class T, class S >
  152. BOOL CContextFixedPool< T, S >::Initialize( PBOOLCALLBACK pAllocFunction, PVOIDCONTEXTCALLBACK pInitFunction, PVOIDCALLBACK pReleaseFunction, PVOIDCALLBACK pDeallocFunction )
  153. {
  154. BOOL fReturn;
  155. DNASSERT( pAllocFunction != NULL );
  156. DNASSERT( pInitFunction != NULL );
  157. DNASSERT( pReleaseFunction != NULL );
  158. DNASSERT( pDeallocFunction != NULL );
  159. fReturn = TRUE;
  160. m_pAllocFunction = pAllocFunction;
  161. m_pInitFunction = pInitFunction;
  162. m_pReleaseFunction = pReleaseFunction;
  163. m_pDeallocFunction = pDeallocFunction;
  164. DEBUG_ONLY( DNASSERT( m_fInitialized == FALSE ) );
  165. DEBUG_ONLY( m_fInitialized = TRUE );
  166. return fReturn;
  167. }
  168. //**********************************************************************
  169. //**********************************************************************
  170. // ------------------------------
  171. // CContextFixedPool::Get - get an item from the pool
  172. //
  173. // Entry: Pointer to user context
  174. //
  175. // Exit: Pointer to item
  176. // NULL = out of memory
  177. // ------------------------------
  178. #undef DPF_MODNAME
  179. #define DPF_MODNAME "CContextFixedPool::Get"
  180. template< class T, class S >
  181. T *CContextFixedPool< T, S >::Get( S *const pContext )
  182. {
  183. CContextClassFPMPoolNode< T > *pNode;
  184. T *pReturn;
  185. DEBUG_ONLY( DNASSERT( m_fInitialized != FALSE ) );
  186. //
  187. // initialize
  188. //
  189. pReturn = NULL;
  190. //
  191. // if the pool is empty, try to allocate a new entry, otherwise grab
  192. // the first item from the pool
  193. //
  194. if ( m_pPool == NULL )
  195. {
  196. pNode = new CContextClassFPMPoolNode< T >;
  197. if ( pNode != NULL )
  198. {
  199. if ( (pNode->m_Item.*m_pAllocFunction)( pContext ) == FALSE )
  200. {
  201. delete pNode;
  202. pNode = NULL;
  203. }
  204. }
  205. }
  206. else
  207. {
  208. pNode = m_pPool;
  209. m_pPool = m_pPool->m_pNext;
  210. }
  211. //
  212. // if we have an entry (it was freshly created, or removed from the pool),
  213. // attempt to initialize it before passing it to the user
  214. //
  215. if ( pNode != NULL )
  216. {
  217. (pNode->m_Item.*m_pInitFunction)( pContext );
  218. pReturn = &pNode->m_Item;
  219. DEBUG_ONLY( pNode->m_pNext = (CContextClassFPMPoolNode<T>*) CONTEXTCFPM_BLANK_NODE_VALUE );
  220. DEBUG_ONLY( m_uOutstandingItemCount++ );
  221. }
  222. return pReturn;
  223. }
  224. //**********************************************************************
  225. //**********************************************************************
  226. // ------------------------------
  227. // CContextFixedPool::Release - return item to pool
  228. //
  229. // Entry: Pointer to item
  230. //
  231. // Exit: Nothing
  232. // ------------------------------
  233. #undef DPF_MODNAME
  234. #define DPF_MODNAME "CContextFixedPool::Release"
  235. template< class T, class S >
  236. void CContextFixedPool< T, S >::Release( T *const pItem )
  237. {
  238. CContextClassFPMPoolNode< T > *pNode;
  239. DEBUG_ONLY( DNASSERT( m_fInitialized != FALSE ) );
  240. DNASSERT( pItem != NULL );
  241. DBG_CASSERT( sizeof( BYTE* ) == sizeof( pItem ) );
  242. DBG_CASSERT( sizeof( CContextClassFPMPoolNode< T >* ) == sizeof( BYTE* ) );
  243. pNode = reinterpret_cast<CContextClassFPMPoolNode< T >*>( &reinterpret_cast<BYTE*>( pItem )[ -OFFSETOF( CContextClassFPMPoolNode< T >, m_Item ) ] );
  244. #if defined(CHECK_FOR_DUPLICATE_CONTEXTCFPM_RELEASE) && defined(DEBUG)
  245. {
  246. CContextClassFPMPoolNode< T > *pTemp;
  247. pTemp = m_pPool;
  248. while ( pTemp != NULL )
  249. {
  250. DNASSERT( pTemp != pNode );
  251. pTemp = pTemp->m_pNext;
  252. }
  253. }
  254. #endif // CHECK_FOR_DUPLICATE_CONTEXTCFPM_RELEASE
  255. DEBUG_ONLY( DNASSERT( pNode->m_pNext == (CContextClassFPMPoolNode< T >*)CONTEXTCFPM_BLANK_NODE_VALUE ) );
  256. (pNode->m_Item.*m_pReleaseFunction)();
  257. #ifdef NO_POOLS
  258. (pNode->m_Item.*m_pDeallocFunction)();
  259. delete pNode;
  260. #else
  261. pNode->m_pNext = m_pPool;
  262. m_pPool = pNode;
  263. #endif
  264. DEBUG_ONLY( m_uOutstandingItemCount-- );
  265. }
  266. //**********************************************************************
  267. // class to act as a link in the pool
  268. template< class T >
  269. class CContextClassFPMTLPoolNode
  270. {
  271. public:
  272. CContextClassFPMTLPoolNode()
  273. {
  274. m_blList.Initialize();
  275. #ifdef TRACK_POOL_STATS
  276. m_dwSourceThreadID = 0;
  277. #endif // TRACK_POOL_STATS
  278. };
  279. #undef DPF_MODNAME
  280. #define DPF_MODNAME "CContextClassFPMTLPoolNode::~CContextClassFPMTLPoolNode"
  281. ~CContextClassFPMTLPoolNode()
  282. {
  283. DNASSERT(m_blList.IsEmpty());
  284. };
  285. CBilink m_blList;
  286. T m_Item;
  287. #ifdef TRACK_POOL_STATS
  288. DWORD m_dwSourceThreadID;
  289. #endif // TRACK_POOL_STATS
  290. protected:
  291. private:
  292. };
  293. // class to manage the pool
  294. template< class T, class S >
  295. class CContextFixedTLPool
  296. {
  297. public:
  298. CContextFixedTLPool();
  299. ~CContextFixedTLPool();
  300. typedef BOOL (T::*PBOOLCALLBACK)( S *const pContext );
  301. typedef void (T::*PVOIDCONTEXTCALLBACK)( S *const pContext );
  302. typedef void (T::*PVOIDCALLBACK)( void );
  303. BOOL Initialize( CContextFixedTLPool< T, S > * pGlobalPool, PBOOLCALLBACK pAllocFunction, PVOIDCONTEXTCALLBACK pInitFunction, PVOIDCALLBACK pReleaseFunction, PVOIDCALLBACK pDeallocFunction );
  304. void Deinitialize( void );
  305. T *Get( S *const pContext );
  306. void Release( T *const pItem );
  307. static void ReleaseWithoutPool( T *const pItem, PVOIDCALLBACK pReleaseFunction, PVOIDCALLBACK pDeallocFunction );
  308. protected:
  309. private:
  310. PBOOLCALLBACK m_pAllocFunction;
  311. PVOIDCONTEXTCALLBACK m_pInitFunction;
  312. PVOIDCALLBACK m_pReleaseFunction;
  313. PVOIDCALLBACK m_pDeallocFunction;
  314. CBilink m_blItems; // bilink list of available elements
  315. CContextFixedTLPool< T, S > * m_pGlobalPool; // pointer to global pool, or NULL if this is the global pool
  316. DNCRITICAL_SECTION * m_pcsLock; // pointer to pool critical section, or NULL if this is not the global pool
  317. DWORD m_dwNumItems; // number of items currently in this pool
  318. DEBUG_ONLY( BOOL m_fInitialized );
  319. #ifdef TRACK_POOL_STATS
  320. DWORD m_dwAllocations; // how many objects were allocated by this pool
  321. DWORD m_dwSlurpsFromGlobal; // how many times some items were taken from the global pool
  322. DWORD m_dwLargestSlurpFromGlobal; // most number of items taken from the global pool at one time
  323. DWORD m_dwRetrievals; // how many times objects were pulled out of this pool
  324. DWORD m_dwReturnsOnSameThread; // how many times objects that were pulled out of this pool were returned to this pool
  325. DWORD m_dwReturnsOnDifferentThread; // how many times objects that were pulled out of another thread's pool were returned to this pool
  326. DWORD m_dwDumpsToGlobal; // how many times some items were dumped into the global pool
  327. DWORD m_dwDeallocations; // how many objects were freed by this pool
  328. #endif // TRACK_POOL_STATS
  329. };
  330. //**********************************************************************
  331. // Class function definitions
  332. //**********************************************************************
  333. //**********************************************************************
  334. // ------------------------------
  335. // CContextFixedTLPool::CContextFixedTLPool - constructor
  336. //
  337. // Entry: Nothing
  338. //
  339. // Exit: Nothing
  340. // ------------------------------
  341. #undef DPF_MODNAME
  342. #define DPF_MODNAME "CContextFixedTLPool::CContextFixedTLPool"
  343. template< class T, class S >
  344. CContextFixedTLPool< T, S >::CContextFixedTLPool():
  345. m_pAllocFunction( NULL ),
  346. m_pInitFunction( NULL ),
  347. m_pReleaseFunction( NULL ),
  348. m_pDeallocFunction( NULL ),
  349. m_pGlobalPool( NULL ),
  350. m_pcsLock( NULL ),
  351. m_dwNumItems( 0 )
  352. {
  353. m_blItems.Initialize();
  354. DEBUG_ONLY( m_fInitialized = FALSE );
  355. #ifdef TRACK_POOL_STATS
  356. m_dwAllocations = 0;
  357. m_dwSlurpsFromGlobal = 0;
  358. m_dwLargestSlurpFromGlobal = 0;
  359. m_dwRetrievals = 0;
  360. m_dwReturnsOnSameThread = 0;
  361. m_dwReturnsOnDifferentThread = 0;
  362. m_dwDumpsToGlobal = 0;
  363. m_dwDeallocations = 0;
  364. #endif // TRACK_POOL_STATS
  365. }
  366. //**********************************************************************
  367. //**********************************************************************
  368. // ------------------------------
  369. // CContextFixedTLPool::~CContextFixedTLPool - destructor
  370. //
  371. // Entry: Nothing
  372. //
  373. // Exit: Nothing
  374. // ------------------------------
  375. #undef DPF_MODNAME
  376. #define DPF_MODNAME "CContextFixedTLPool::~CContextFixedTLPool"
  377. template< class T, class S >
  378. CContextFixedTLPool< T, S >::~CContextFixedTLPool()
  379. {
  380. CBilink * pBilink;
  381. CContextClassFPMTLPoolNode< T > * pNode;
  382. pBilink = m_blItems.GetNext();
  383. while ( pBilink != &m_blItems )
  384. {
  385. pNode = CONTAINING_OBJECT(pBilink, CContextClassFPMTLPoolNode< T >, m_blList);
  386. pBilink = pBilink->GetNext();
  387. pNode->m_blList.RemoveFromList();
  388. (pNode->m_Item.*m_pDeallocFunction)();
  389. delete pNode;
  390. #ifdef TRACK_POOL_STATS
  391. m_dwDeallocations++;
  392. #endif // TRACK_POOL_STATS
  393. DEBUG_ONLY( m_dwNumItems-- );
  394. }
  395. DNASSERT( m_fInitialized == FALSE );
  396. DNASSERT( m_dwNumItems == 0 );
  397. DNASSERT( m_blItems.IsEmpty() );
  398. DNASSERT( m_pcsLock == NULL );
  399. #ifdef TRACK_POOL_STATS
  400. DPFX(DPFPREP, 9, "Pool 0x%p information:", this);
  401. DPFX(DPFPREP, 9, "\tAllocations = %u", m_dwAllocations);
  402. DPFX(DPFPREP, 9, "\tSlurpsFromGlobal = %u", m_dwSlurpsFromGlobal);
  403. DPFX(DPFPREP, 9, "\tLargestSlurpFromGlobal = %u", m_dwLargestSlurpFromGlobal);
  404. DPFX(DPFPREP, 9, "\tRetrievals = %u", m_dwRetrievals);
  405. DPFX(DPFPREP, 9, "\tReturnsOnSameThread = %u", m_dwReturnsOnSameThread);
  406. DPFX(DPFPREP, 9, "\tReturnsOnDifferentThread = %u", m_dwReturnsOnDifferentThread);
  407. DPFX(DPFPREP, 9, "\tDumpsToGlobal = %u", m_dwDumpsToGlobal);
  408. DPFX(DPFPREP, 9, "\tDeallocations = %u", m_dwDeallocations);
  409. #endif // TRACK_POOL_STATS
  410. }
  411. //**********************************************************************
  412. //**********************************************************************
  413. // ------------------------------
  414. // CContextFixedTLPool::Initialize - initialize pool
  415. //
  416. // Entry: Pointer to global pool, or NULL if this is the global pool
  417. // Pointer to function to call when a new entry is allocated
  418. // Pointer to function to call when a new entry is removed from the pool
  419. // Pointer to function to call when an entry is returned to the pool
  420. // Pointer to function to call when an entry is deallocated
  421. //
  422. // Exit: TRUE if successful, FALSE otherwise.
  423. // ------------------------------
  424. #undef DPF_MODNAME
  425. #define DPF_MODNAME "CContextFixedTLPool::Initialize"
  426. template< class T, class S >
  427. BOOL CContextFixedTLPool< T, S >::Initialize( CContextFixedTLPool< T, S > * pGlobalPool, PBOOLCALLBACK pAllocFunction, PVOIDCONTEXTCALLBACK pInitFunction, PVOIDCALLBACK pReleaseFunction, PVOIDCALLBACK pDeallocFunction )
  428. {
  429. BOOL fReturn;
  430. DNASSERT( pAllocFunction != NULL );
  431. DNASSERT( pInitFunction != NULL );
  432. DNASSERT( pReleaseFunction != NULL );
  433. DNASSERT( pDeallocFunction != NULL );
  434. fReturn = TRUE;
  435. m_pAllocFunction = pAllocFunction;
  436. m_pInitFunction = pInitFunction;
  437. m_pReleaseFunction = pReleaseFunction;
  438. m_pDeallocFunction = pDeallocFunction;
  439. m_pGlobalPool = pGlobalPool;
  440. if (pGlobalPool == NULL)
  441. {
  442. //DPFX(DPFPREP, 9, "Initializing global pool 0x%p.", this);
  443. m_pcsLock = (DNCRITICAL_SECTION*) DNMalloc( sizeof(DNCRITICAL_SECTION) );
  444. if (m_pcsLock == NULL)
  445. {
  446. fReturn = FALSE;
  447. goto Exit;
  448. }
  449. if (! DNInitializeCriticalSection( m_pcsLock ))
  450. {
  451. DNFree( m_pcsLock );
  452. DEBUG_ONLY( m_pcsLock = NULL );
  453. fReturn = FALSE;
  454. goto Exit;
  455. }
  456. }
  457. DEBUG_ONLY( DNASSERT( m_fInitialized == FALSE ) );
  458. DEBUG_ONLY( m_fInitialized = TRUE );
  459. Exit:
  460. return fReturn;
  461. }
  462. //**********************************************************************
  463. //**********************************************************************
  464. // ------------------------------
  465. // CContextFixedTLPool::Deinitialize - deinitialize pool
  466. //
  467. // Entry: None.
  468. //
  469. // Exit: Nothing
  470. // ------------------------------
  471. #undef DPF_MODNAME
  472. #define DPF_MODNAME "CContextFixedTLPool::Deinitialize"
  473. template< class T, class S >
  474. void CContextFixedTLPool< T, S >::Deinitialize( void )
  475. {
  476. DEBUG_ONLY( DNASSERT( m_fInitialized != FALSE ) );
  477. DEBUG_ONLY( m_fInitialized = FALSE );
  478. if (m_pcsLock != NULL)
  479. {
  480. //DPFX(DPFPREP, 9, "Deinitializing global pool 0x%p.", this);
  481. DNDeleteCriticalSection( m_pcsLock );
  482. DNFree( m_pcsLock );
  483. DEBUG_ONLY( m_pcsLock = NULL );
  484. }
  485. }
  486. //**********************************************************************
  487. //**********************************************************************
  488. // ------------------------------
  489. // CContextFixedTLPool::Get - get an item from the pool
  490. //
  491. // Entry: Pointer to user context
  492. //
  493. // Exit: Pointer to item
  494. // NULL = out of memory
  495. // ------------------------------
  496. #undef DPF_MODNAME
  497. #define DPF_MODNAME "CContextFixedTLPool::Get"
  498. template< class T, class S >
  499. T *CContextFixedTLPool< T, S >::Get( S *const pContext )
  500. {
  501. CBilink * pBilink;
  502. CContextClassFPMTLPoolNode< T > * pNode;
  503. T * pReturn;
  504. DNASSERT( m_fInitialized != FALSE );
  505. DNASSERT( m_pGlobalPool != NULL );
  506. //
  507. // If the pool is empty, steal the ones in the global pool.
  508. //
  509. pBilink = m_blItems.GetNext();
  510. if ( pBilink == &m_blItems )
  511. {
  512. DNEnterCriticalSection( m_pGlobalPool->m_pcsLock );
  513. pBilink = m_pGlobalPool->m_blItems.GetNext();
  514. if ( pBilink == &m_pGlobalPool->m_blItems )
  515. {
  516. //
  517. // No items. Drop global pool lock and allocate a new one.
  518. //
  519. DNLeaveCriticalSection( m_pGlobalPool->m_pcsLock );
  520. pNode = new CContextClassFPMTLPoolNode< T >;
  521. if ( pNode != NULL )
  522. {
  523. if ( (pNode->m_Item.*m_pAllocFunction)( pContext ) == FALSE )
  524. {
  525. delete pNode;
  526. pReturn = NULL;
  527. goto Exit;
  528. }
  529. #ifdef TRACK_POOL_STATS
  530. else
  531. {
  532. //
  533. // Update counter.
  534. //
  535. m_dwAllocations++;
  536. }
  537. #endif // TRACK_POOL_STATS
  538. }
  539. else
  540. {
  541. pReturn = NULL;
  542. goto Exit;
  543. }
  544. }
  545. else
  546. {
  547. //
  548. // Separate all the items from the global list.
  549. // We still have a pointer to the orphaned items (pBilink).
  550. //
  551. m_pGlobalPool->m_blItems.RemoveFromList();
  552. DNASSERT(m_pGlobalPool->m_dwNumItems > 0);
  553. #ifdef TRACK_POOL_STATS
  554. m_dwSlurpsFromGlobal++;
  555. if ( m_pGlobalPool->m_dwNumItems > m_dwLargestSlurpFromGlobal )
  556. {
  557. m_dwLargestSlurpFromGlobal = m_pGlobalPool->m_dwNumItems;
  558. }
  559. #endif // TRACK_POOL_STATS
  560. m_dwNumItems = m_pGlobalPool->m_dwNumItems - 1; // -1 because we need one right now
  561. m_pGlobalPool->m_dwNumItems = 0;
  562. //
  563. // Drop the lock since we don't need the global pool anymore.
  564. //
  565. DNLeaveCriticalSection( m_pGlobalPool->m_pcsLock );
  566. //
  567. // Get the first item from the orphaned list.
  568. //
  569. pNode = CONTAINING_OBJECT(pBilink, CContextClassFPMTLPoolNode< T >, m_blList);
  570. //
  571. // If there was more than one item in the global pool, transfer
  572. // the remaining orphaned items (after the first) to this pool.
  573. //
  574. if (pBilink != pBilink->GetNext())
  575. {
  576. pBilink = pBilink->GetNext();
  577. pNode->m_blList.RemoveFromList();
  578. m_blItems.InsertBefore(pBilink);
  579. }
  580. }
  581. }
  582. else
  583. {
  584. pNode = CONTAINING_OBJECT(pBilink, CContextClassFPMTLPoolNode< T >, m_blList);
  585. pBilink->RemoveFromList();
  586. DNASSERT( m_dwNumItems > 0 );
  587. m_dwNumItems--;
  588. }
  589. //
  590. // If we're here, we have an entry (it was freshly created, or removed from
  591. // some pool). Attempt to initialize it before passing it to the user.
  592. //
  593. (pNode->m_Item.*m_pInitFunction)( pContext );
  594. pReturn = &pNode->m_Item;
  595. #ifdef TRACK_POOL_STATS
  596. //
  597. // Update status counts.
  598. //
  599. m_dwRetrievals++;
  600. pNode->m_dwSourceThreadID = GetCurrentThreadId();
  601. #endif // TRACK_POOL_STATS
  602. Exit:
  603. return pReturn;
  604. }
  605. //**********************************************************************
  606. //**********************************************************************
  607. // ------------------------------
  608. // CContextFixedTLPool::Release - return item to pool
  609. //
  610. // Entry: Pointer to item
  611. //
  612. // Exit: Nothing
  613. // ------------------------------
  614. #undef DPF_MODNAME
  615. #define DPF_MODNAME "CContextFixedTLPool::Release"
  616. template< class T, class S >
  617. void CContextFixedTLPool< T, S >::Release( T *const pItem )
  618. {
  619. CContextClassFPMTLPoolNode< T > *pNode;
  620. DNASSERT( m_fInitialized != FALSE );
  621. DNASSERT( m_pGlobalPool != NULL );
  622. DNASSERT( pItem != NULL );
  623. DBG_CASSERT( sizeof( BYTE* ) == sizeof( pItem ) );
  624. DBG_CASSERT( sizeof( CContextClassFPMTLPoolNode< T >* ) == sizeof( BYTE* ) );
  625. pNode = reinterpret_cast<CContextClassFPMTLPoolNode< T >*>( &reinterpret_cast<BYTE*>( pItem )[ -OFFSETOF( CContextClassFPMTLPoolNode< T >, m_Item ) ] );
  626. #if defined(CHECK_FOR_DUPLICATE_CONTEXTCFPM_RELEASE) && defined(DEBUG)
  627. DNASSERT( ! pNode->m_blList.IsListMember( &m_blItems ));
  628. #endif // CHECK_FOR_DUPLICATE_CONTEXTCFPM_RELEASE
  629. (pNode->m_Item.*m_pReleaseFunction)();
  630. #ifdef TRACK_POOL_STATS
  631. //
  632. // Update status counts.
  633. //
  634. if (pNode->m_dwSourceThreadID == GetCurrentThreadId())
  635. {
  636. m_dwReturnsOnSameThread++;
  637. }
  638. else
  639. {
  640. m_dwReturnsOnDifferentThread++;
  641. }
  642. #endif // TRACK_POOL_STATS
  643. #ifdef NO_POOLS
  644. (pNode->m_Item.*m_pDeallocFunction)();
  645. delete pNode;
  646. #ifdef TRACK_POOL_STATS
  647. m_dwDeallocations++;
  648. #endif // TRACK_POOL_STATS
  649. #else // ! NO_POOLS
  650. pNode->m_blList.InsertAfter( &m_blItems );
  651. m_dwNumItems++;
  652. //
  653. // If this pool has built up some extra items, return them to the
  654. // global pool.
  655. //
  656. if ( m_dwNumItems >= 25 )
  657. {
  658. CBilink * pFirstItem;
  659. //
  660. // Save a pointer to the first item.
  661. //
  662. pFirstItem = m_blItems.GetNext();
  663. DNASSERT( pFirstItem != &m_blItems );
  664. //
  665. // Orphan the items.
  666. //
  667. m_blItems.RemoveFromList();
  668. //
  669. // Take the lock and transfer the list to the global pool.
  670. //
  671. DNEnterCriticalSection( m_pGlobalPool->m_pcsLock );
  672. m_pGlobalPool->m_blItems.AttachListBefore(pFirstItem);
  673. m_pGlobalPool->m_dwNumItems += m_dwNumItems;
  674. DNLeaveCriticalSection( m_pGlobalPool->m_pcsLock );
  675. m_dwNumItems = 0;
  676. #ifdef TRACK_POOL_STATS
  677. m_dwDumpsToGlobal++;
  678. #endif // TRACK_POOL_STATS
  679. }
  680. #endif // ! NO_POOLS
  681. }
  682. //**********************************************************************
  683. //**********************************************************************
  684. // ------------------------------
  685. // CContextFixedTLPool::ReleaseWithoutPool - destroy an item without returning it
  686. // to a pool
  687. // NOTE: this is a static function
  688. // and cannot use the 'this' pointer!
  689. //
  690. // Entry: Pointer to item
  691. //
  692. // Exit: Nothing
  693. // ------------------------------
  694. #undef DPF_MODNAME
  695. #define DPF_MODNAME "CContextFixedTLPool::ReleaseWithoutPool"
  696. template< class T, class S >
  697. void CContextFixedTLPool< T, S >::ReleaseWithoutPool( T *const pItem, PVOIDCALLBACK pReleaseFunction, PVOIDCALLBACK pDeallocFunction )
  698. {
  699. CContextClassFPMTLPoolNode< T > *pNode;
  700. DNASSERT( pItem != NULL );
  701. DBG_CASSERT( sizeof( BYTE* ) == sizeof( pItem ) );
  702. DBG_CASSERT( sizeof( CContextClassFPMTLPoolNode< T >* ) == sizeof( BYTE* ) );
  703. pNode = reinterpret_cast<CContextClassFPMTLPoolNode< T >*>( &reinterpret_cast<BYTE*>( pItem )[ -OFFSETOF( CContextClassFPMTLPoolNode< T >, m_Item ) ] );
  704. DNASSERT( pNode->m_blList.IsEmpty() );
  705. (pNode->m_Item.*pReleaseFunction)();
  706. (pNode->m_Item.*pDeallocFunction)();
  707. delete pNode;
  708. }
  709. //**********************************************************************
  710. #ifdef __LOCAL_OFFSETOF_DEFINED__
  711. #undef __LOCAL_OFFSETOF_DEFINED__
  712. #undef OFFSETOF
  713. #endif // __LOCAL_OFFSETOF_DEFINED__
  714. #undef DPF_SUBCOMP
  715. #undef DPF_MODNAME
  716. #endif // __CONTEXT_CLASS_FPM_H__