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.

1060 lines
24 KiB

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