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.

449 lines
11 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1995 - 2000 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: LockedContextFixedPool.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 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. ***************************************************************************/
  19. #ifndef __LOCKED_CONTEXT_FIXED_POOL__
  20. #define __LOCKED_CONTEXT_FIXED_POOL__
  21. #undef DPF_SUBCOMP
  22. #define DPF_SUBCOMP DN_SUBCOMP_COMMON
  23. //**********************************************************************
  24. // Constant definitions
  25. //**********************************************************************
  26. #define CHECK_FOR_DUPLICATE_LOCKED_CONTEXT_FPM_RELEASE
  27. //**********************************************************************
  28. // Macro definitions
  29. //**********************************************************************
  30. #ifndef OFFSETOF
  31. // Macro to compute the offset of an element inside of a larger structure (copied from MSDEV's STDLIB.H)
  32. #define OFFSETOF(s,m) ( (INT_PTR) &(((s *)0)->m) )
  33. #define __LOCAL_OFFSETOF_DEFINED__
  34. #endif // OFFSETOF
  35. //**********************************************************************
  36. // Structure definitions
  37. //**********************************************************************
  38. //
  39. // forward reference
  40. //
  41. template< class S > class CLockedContextFixedPoolItem;
  42. template< class T, class S > class CLockedContextFixedPool;
  43. //**********************************************************************
  44. // Variable definitions
  45. //**********************************************************************
  46. //**********************************************************************
  47. // Function prototypes
  48. //**********************************************************************
  49. //**********************************************************************
  50. // Class definitions
  51. //**********************************************************************
  52. //
  53. // class to act as a link in the pool
  54. //
  55. template< class S >
  56. class CLockedContextFixedPoolItem
  57. {
  58. public:
  59. #undef DPF_MODNAME
  60. #define DPF_MODNAME "CLockedContextFixedPoolItem::CLockedContextFixedPoolItem"
  61. CLockedContextFixedPoolItem()
  62. {
  63. m_iRefCount = 0;
  64. m_pNext = NULL;
  65. }
  66. #undef DPF_MODNAME
  67. #define DPF_MODNAME "CLockedContextFixedPoolItem::~CLockedContextFixedPoolItem"
  68. virtual ~CLockedContextFixedPoolItem() { DNASSERT( m_iRefCount == 0 ); }
  69. #undef DPF_MODNAME
  70. #define DPF_MODNAME "CLockedContextFixedPoolItem::AddRef"
  71. void AddRef( void )
  72. {
  73. DNASSERT( m_iRefCount != -1 );
  74. InterlockedIncrement( const_cast<LONG*>( &m_iRefCount ) );
  75. }
  76. #undef DPF_MODNAME
  77. #define DPF_MODNAME "CLockedContextFixedPoolItem::DecRef"
  78. void DecRef( void )
  79. {
  80. DNASSERT( m_iRefCount != 0 );
  81. if ( InterlockedDecrement( const_cast<LONG*>( &m_iRefCount ) ) == 0 )
  82. {
  83. ReturnSelfToPool();
  84. }
  85. }
  86. CLockedContextFixedPoolItem *GetNext( void ) const { return m_pNext; }
  87. void InvalidateNext( void ) { m_pNext = NULL; }
  88. #undef DPF_MODNAME
  89. #define DPF_MODNAME "CLockedContextFixedPoolItem::LinkToPool"
  90. void LinkToPool( CLockedContextFixedPoolItem *volatile *const ppPoolItems )
  91. {
  92. DNASSERT( ppPoolItems != NULL );
  93. m_pNext = *ppPoolItems;
  94. *ppPoolItems = this;
  95. }
  96. //
  97. // Default initialization and deinitialization functions. These can
  98. // be overridden by the derived classes.
  99. //
  100. virtual BOOL PoolAllocFunction( S Context ){ return TRUE; }
  101. virtual BOOL PoolInitFunction( S Context ){ return TRUE; }
  102. virtual void PoolReleaseFunction( void ){};
  103. virtual void PoolDeallocFunction( void ){};
  104. protected:
  105. private:
  106. //
  107. // reference count used to return this item to the pool
  108. //
  109. volatile LONG m_iRefCount;
  110. //
  111. // pointer used to link this item to the rest of the pool
  112. //
  113. CLockedContextFixedPoolItem *m_pNext;
  114. virtual void ReturnSelfToPool( void ) = 0;
  115. //
  116. // prevent unwarranted copies
  117. //
  118. CLockedContextFixedPoolItem< S >( const CLockedContextFixedPoolItem< S > & );
  119. CLockedContextFixedPoolItem< S >& operator=( const CLockedContextFixedPoolItem< S > & );
  120. };
  121. //
  122. // class to manage the pool
  123. //
  124. template< class T, class S >
  125. class CLockedContextFixedPool
  126. {
  127. public:
  128. CLockedContextFixedPool();
  129. ~CLockedContextFixedPool();
  130. void Lock( void ) { DNEnterCriticalSection( &m_Lock ); }
  131. void Unlock( void ) { DNLeaveCriticalSection( &m_Lock ); }
  132. BOOL Initialize( void );
  133. void Deinitialize( void );
  134. T *Get( S Context );
  135. void Release( T *const pItem );
  136. protected:
  137. private:
  138. DNCRITICAL_SECTION m_Lock;
  139. CLockedContextFixedPoolItem< S > *volatile m_pPool; // pointer to list of available elements
  140. DEBUG_ONLY( BOOL m_fInitialized );
  141. DEBUG_ONLY( volatile LONG m_lOutstandingItemCount );
  142. T *RemoveNode( void )
  143. {
  144. T *pReturn;
  145. if ( m_pPool != NULL )
  146. {
  147. pReturn = static_cast<T*>( m_pPool );
  148. m_pPool = m_pPool->GetNext();
  149. DEBUG_ONLY( pReturn->InvalidateNext() );
  150. }
  151. else
  152. {
  153. pReturn = NULL;
  154. }
  155. return pReturn;
  156. }
  157. //
  158. // prevent unwarranted copies
  159. //
  160. CLockedContextFixedPool< T, S >( const CLockedContextFixedPool< T, S > & );
  161. CLockedContextFixedPool< T, S >& operator=( const CLockedContextFixedPool< T, S > & );
  162. };
  163. //**********************************************************************
  164. // Class function definitions
  165. //**********************************************************************
  166. //**********************************************************************
  167. // ------------------------------
  168. // CLockedContextFixedPool::CLockedContextFixedPool - constructor
  169. //
  170. // Entry: Nothing
  171. //
  172. // Exit: Nothing
  173. // ------------------------------
  174. template< class T, class S >
  175. CLockedContextFixedPool< T, S >::CLockedContextFixedPool():
  176. m_pPool( NULL )
  177. {
  178. DEBUG_ONLY( m_fInitialized = FALSE );
  179. DEBUG_ONLY( m_lOutstandingItemCount = 0 );
  180. }
  181. //**********************************************************************
  182. //**********************************************************************
  183. // ------------------------------
  184. // CLockedContextFixedPool::~CLockedContextFixedPool - destructor
  185. //
  186. // Entry: Nothing
  187. //
  188. // Exit: Nothing
  189. // ------------------------------
  190. template< class T, class S >
  191. CLockedContextFixedPool< T, S >::~CLockedContextFixedPool()
  192. {
  193. DEBUG_ONLY( DNASSERT( m_lOutstandingItemCount == 0 ) );
  194. DEBUG_ONLY( DNASSERT( m_fInitialized == FALSE ) );
  195. }
  196. //**********************************************************************
  197. //**********************************************************************
  198. // ------------------------------
  199. // CLockedContextFixedPool::Initialize - initialize pool
  200. //
  201. // Entry: Nothing
  202. // Pointer to function to call when a new entry is removed from the pool
  203. // Pointer to function to call when an entry is returned to the pool
  204. // Pointer to function to call when an entry is deallocated
  205. //
  206. // Exit: Boolean indicating success
  207. // TRUE = initialization succeeded
  208. // FALSE = initialization failed
  209. // ------------------------------
  210. template< class T, class S >
  211. BOOL CLockedContextFixedPool< T, S >::Initialize( void )
  212. {
  213. BOOL fReturn;
  214. DEBUG_ONLY( DNASSERT( m_fInitialized == FALSE ) );
  215. fReturn = TRUE;
  216. if ( DNInitializeCriticalSection( &m_Lock ) == FALSE )
  217. {
  218. fReturn = FALSE;
  219. goto Exit;
  220. }
  221. DebugSetCriticalSectionRecursionCount( &m_Lock, 0 );
  222. DEBUG_ONLY( m_fInitialized = TRUE );
  223. Exit:
  224. return fReturn;
  225. }
  226. //**********************************************************************
  227. //**********************************************************************
  228. // ------------------------------
  229. // CLockedContextFixedPool::Deinitialize - deinitialize pool
  230. //
  231. // Entry: Nothing
  232. //
  233. // Exit: Nothing
  234. // ------------------------------
  235. template< class T, class S >
  236. void CLockedContextFixedPool< T, S >::Deinitialize( void )
  237. {
  238. DEBUG_ONLY( DNASSERT( m_fInitialized != FALSE ) );
  239. Lock();
  240. DEBUG_ONLY( DNASSERT( m_lOutstandingItemCount == 0 ) );
  241. while ( m_pPool != NULL )
  242. {
  243. CLockedContextFixedPoolItem< S > *pNode;
  244. pNode = RemoveNode();
  245. pNode->PoolDeallocFunction();
  246. delete pNode;
  247. }
  248. Unlock();
  249. DNDeleteCriticalSection( &m_Lock );
  250. DEBUG_ONLY( m_fInitialized = FALSE );
  251. }
  252. //**********************************************************************
  253. //**********************************************************************
  254. // ------------------------------
  255. // CLockedContextFixedPool::Get - get an item from the pool
  256. //
  257. // Entry: Pointer to user context
  258. //
  259. // Exit: Pointer to item
  260. // NULL = out of memory
  261. // ------------------------------
  262. template< class T, class S >
  263. T *CLockedContextFixedPool< T, S >::Get( S Context )
  264. {
  265. T *pReturn;
  266. DEBUG_ONLY( DNASSERT( m_fInitialized != FALSE ) );
  267. //
  268. // initialize
  269. //
  270. pReturn = NULL;
  271. Lock();
  272. //
  273. // if the pool is empty, try to allocate a new entry, otherwise grab
  274. // the first item from the pool
  275. //
  276. if ( m_pPool == NULL )
  277. {
  278. Unlock();
  279. pReturn = new T;
  280. if ( pReturn != NULL )
  281. {
  282. if ( pReturn->PoolAllocFunction( Context ) == FALSE )
  283. {
  284. delete pReturn;
  285. pReturn = NULL;
  286. }
  287. }
  288. }
  289. else
  290. {
  291. pReturn = RemoveNode();
  292. Unlock();
  293. }
  294. //
  295. // if we have an entry (it was freshly created, or removed from the pool),
  296. // attempt to initialize it before passing it to the user
  297. //
  298. if ( pReturn != NULL )
  299. {
  300. if ( pReturn->PoolInitFunction( Context ) == FALSE )
  301. {
  302. Lock();
  303. pReturn->LinkToPool( &m_pPool );
  304. Unlock();
  305. pReturn = NULL;
  306. }
  307. else
  308. {
  309. pReturn->SetOwningPool( this );
  310. pReturn->AddRef();
  311. DEBUG_ONLY( InterlockedIncrement( const_cast<LONG*>( &m_lOutstandingItemCount ) ) );
  312. }
  313. }
  314. return pReturn;
  315. }
  316. //**********************************************************************
  317. //**********************************************************************
  318. // ------------------------------
  319. // CLockedContextFixedPool::Release - return item to pool
  320. //
  321. // Entry: Pointer to item
  322. //
  323. // Exit: Nothing
  324. // ------------------------------
  325. template< class T, class S >
  326. void CLockedContextFixedPool< T, S >::Release( T *const pItem )
  327. {
  328. DEBUG_ONLY( DNASSERT( m_fInitialized != FALSE ) );
  329. DNASSERT( pItem != NULL );
  330. DEBUG_ONLY( DNASSERT( pItem->GetNext() == NULL ) );
  331. pItem->PoolReleaseFunction();
  332. Lock();
  333. #if defined(CHECK_FOR_DUPLICATE_LOCKED_CONTEXT_FPM_RELEASE) && defined(DEBUG)
  334. {
  335. CLockedContextFixedPoolItem< S > *pTemp;
  336. pTemp = m_pPool;
  337. while ( pTemp != NULL )
  338. {
  339. DNASSERT( pTemp != pItem );
  340. pTemp = pTemp->GetNext();
  341. }
  342. }
  343. #endif // CHECK_FOR_DUPLICATE_LOCKED_CONTEXT_FPM_RELEASE
  344. DEBUG_ONLY( pItem->SetOwningPool( NULL ) );
  345. #ifdef NO_POOLS
  346. pItem->PoolDeallocFunction();
  347. delete pItem;
  348. #else
  349. pItem->LinkToPool( &m_pPool );
  350. #endif
  351. Unlock();
  352. DEBUG_ONLY( InterlockedDecrement( const_cast<LONG*>( &m_lOutstandingItemCount ) ) );
  353. }
  354. //**********************************************************************
  355. #ifdef __LOCAL_OFFSETOF_DEFINED__
  356. #undef __LOCAL_OFFSETOF_DEFINED__
  357. #undef OFFSETOF
  358. #endif // __LOCAL_OFFSETOF_DEFINED__
  359. #undef DPF_SUBCOMP
  360. #undef DPF_MODNAME
  361. #endif // __LOCKED_CONTEXT_FIXED_POOL__