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.

394 lines
11 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. ***************************************************************************/
  17. #ifndef __CONTEXT_CLASS_FPM_H__
  18. #define __CONTEXT_CLASS_FPM_H__
  19. #undef DPF_SUBCOMP
  20. #define DPF_SUBCOMP DN_SUBCOMP_COMMON
  21. //**********************************************************************
  22. // Constant definitions
  23. //**********************************************************************
  24. #ifdef _WIN64
  25. #define BLANK_NODE_VALUE 0xAA55817E6D5C4B3A
  26. #else // _WIN64
  27. #define BLANK_NODE_VALUE 0xAA55817E
  28. #endif // _WIN64
  29. #define CHECK_FOR_DUPLICATE_LOCKEDCCFPM_RELEASE
  30. //**********************************************************************
  31. // Macro definitions
  32. //**********************************************************************
  33. #ifndef OFFSETOF
  34. // Macro to compute the offset of an element inside of a larger structure (copied from MSDEV's STDLIB.H)
  35. #define OFFSETOF(s,m) ( (INT_PTR) &(((s *)0)->m) )
  36. #define __LOCAL_OFFSETOF_DEFINED__
  37. #endif // OFFSETOF
  38. //**********************************************************************
  39. // Structure definitions
  40. //**********************************************************************
  41. //**********************************************************************
  42. // Variable definitions
  43. //**********************************************************************
  44. //**********************************************************************
  45. // Function prototypes
  46. //**********************************************************************
  47. //**********************************************************************
  48. // Class definitions
  49. //**********************************************************************
  50. // class to act as a link in the pool
  51. template< class T >
  52. class CLockedContextClassFPMPoolNode
  53. {
  54. public:
  55. CLockedContextClassFPMPoolNode() { m_pNext = NULL; }
  56. ~CLockedContextClassFPMPoolNode() {};
  57. CLockedContextClassFPMPoolNode *m_pNext;
  58. void *m_pContext;
  59. T m_Item;
  60. protected:
  61. private:
  62. };
  63. // class to manage the pool
  64. template< class T >
  65. class CLockedContextClassFixedPool
  66. {
  67. public:
  68. CLockedContextClassFixedPool();
  69. ~CLockedContextClassFixedPool();
  70. typedef BOOL (T::*PBOOLCALLBACK)( void *const pContext );
  71. typedef void (T::*PVOIDCALLBACK)( void *const pContext );
  72. BOOL Initialize( PBOOLCALLBACK pAllocFunction,
  73. PBOOLCALLBACK pInitFunction,
  74. PVOIDCALLBACK pReleaseFunction,
  75. PVOIDCALLBACK pDeallocFunction );
  76. void Deinitialize( void );
  77. T *Get( void *const pContext );
  78. void Release( T *const pItem );
  79. protected:
  80. private:
  81. DNCRITICAL_SECTION m_Lock;
  82. PBOOLCALLBACK m_pAllocFunction;
  83. PBOOLCALLBACK m_pInitFunction;
  84. PVOIDCALLBACK m_pReleaseFunction;
  85. PVOIDCALLBACK m_pDeallocFunction;
  86. CLockedContextClassFPMPoolNode< T > *volatile m_pPool; // pointer to list of available elements
  87. BOOL m_fInitialized; // Initialized ?
  88. DEBUG_ONLY( LONG volatile m_lOutstandingItemCount );
  89. };
  90. //**********************************************************************
  91. // Class function definitions
  92. //**********************************************************************
  93. //**********************************************************************
  94. // ------------------------------
  95. // CLockedContextClassFixedPool::CLockedContextClassFixedPool - constructor
  96. //
  97. // Entry: Nothing
  98. //
  99. // Exit: Nothing
  100. // ------------------------------
  101. template< class T >
  102. CLockedContextClassFixedPool< T >::CLockedContextClassFixedPool():
  103. m_pAllocFunction( NULL ),
  104. m_pInitFunction( NULL ),
  105. m_pReleaseFunction( NULL ),
  106. m_pDeallocFunction( NULL ),
  107. m_pPool( NULL ),
  108. m_fInitialized( FALSE )
  109. {
  110. DEBUG_ONLY( m_lOutstandingItemCount = 0 );
  111. }
  112. //**********************************************************************
  113. //**********************************************************************
  114. // ------------------------------
  115. // CLockedContextClassFixedPool::~CLockedContextClassFixedPool - destructor
  116. //
  117. // Entry: Nothing
  118. //
  119. // Exit: Nothing
  120. // ------------------------------
  121. #undef DPF_MODNAME
  122. #define DPF_MODNAME "CCFPM::CCFPM"
  123. template< class T >
  124. CLockedContextClassFixedPool< T >::~CLockedContextClassFixedPool()
  125. {
  126. DEBUG_ONLY( DNASSERT( m_lOutstandingItemCount == 0 ) );
  127. DEBUG_ONLY( DNASSERT( m_fInitialized == FALSE ) );
  128. }
  129. //**********************************************************************
  130. //**********************************************************************
  131. // ------------------------------
  132. // CLockedContextClassFixedPool::Initialize - initialize pool
  133. //
  134. // Entry: Pointer to function to call when a new entry is allocated
  135. // Pointer to function to call when a new entry is removed from the pool
  136. // Pointer to function to call when an entry is returned to the pool
  137. // Pointer to function to call when an entry is deallocated
  138. //
  139. // Exit: Nothing
  140. // ------------------------------
  141. #undef DPF_MODNAME
  142. #define DPF_MODNAME "CCFPM::Initialize"
  143. template< class T >
  144. BOOL CLockedContextClassFixedPool< T >::Initialize( PBOOLCALLBACK pAllocFunction, PBOOLCALLBACK pInitFunction, PVOIDCALLBACK pReleaseFunction, PVOIDCALLBACK pDeallocFunction )
  145. {
  146. BOOL fReturn;
  147. DNASSERT( m_fInitialized == FALSE );
  148. DNASSERT( pAllocFunction != NULL );
  149. DNASSERT( pInitFunction != NULL );
  150. DNASSERT( pReleaseFunction != NULL );
  151. DNASSERT( pDeallocFunction != NULL );
  152. fReturn = TRUE;
  153. if ( DNInitializeCriticalSection( &m_Lock ) == FALSE )
  154. {
  155. fReturn = FALSE;
  156. goto Exit;
  157. }
  158. m_pAllocFunction = pAllocFunction;
  159. m_pInitFunction = pInitFunction;
  160. m_pReleaseFunction = pReleaseFunction;
  161. m_pDeallocFunction = pDeallocFunction;
  162. m_fInitialized = TRUE;
  163. Exit:
  164. return fReturn;
  165. }
  166. //**********************************************************************
  167. //**********************************************************************
  168. // ------------------------------
  169. // CLockedContextClassFixedPool::Deinitialize - deinitialize pool
  170. //
  171. // Entry: Nothing
  172. //
  173. // Exit: Nothing
  174. // ------------------------------
  175. #undef DPF_MODNAME
  176. #define DPF_MODNAME "CCFPM::Deinitialize"
  177. template< class T >
  178. void CLockedContextClassFixedPool< T >::Deinitialize( void )
  179. {
  180. DNASSERT( m_fInitialized == TRUE );
  181. DNEnterCriticalSection(&m_Lock);
  182. DEBUG_ONLY( DNASSERT( m_lOutstandingItemCount == 0 ) );
  183. while ( m_pPool != NULL )
  184. {
  185. CLockedContextClassFPMPoolNode< T > *pNode;
  186. pNode = m_pPool;
  187. m_pPool = m_pPool->m_pNext;
  188. (pNode->m_Item.*this->m_pDeallocFunction)( pNode->m_pContext );
  189. delete pNode;
  190. }
  191. DNLeaveCriticalSection(&m_Lock);
  192. DNDeleteCriticalSection(&m_Lock);
  193. m_fInitialized = FALSE;
  194. }
  195. //**********************************************************************
  196. //**********************************************************************
  197. // ------------------------------
  198. // CLockedContextClassFixedPool::Get - get an item from the pool
  199. //
  200. // Entry: Pointer to user context
  201. //
  202. // Exit: Pointer to item
  203. // NULL = out of memory
  204. // ------------------------------
  205. #undef DPF_MODNAME
  206. #define DPF_MODNAME "CCFPM::Get"
  207. template< class T >
  208. T *CLockedContextClassFixedPool< T >::Get( void *const pContext )
  209. {
  210. CLockedContextClassFPMPoolNode< T > *pNode;
  211. T *pReturn;
  212. DEBUG_ONLY( DNASSERT( m_fInitialized != FALSE ) );
  213. //
  214. // initialize
  215. //
  216. pReturn = NULL;
  217. DNEnterCriticalSection(&m_Lock);
  218. //
  219. // if the pool is empty, try to allocate a new entry, otherwise grab
  220. // the first item from the pool
  221. //
  222. if ( m_pPool == NULL )
  223. {
  224. DNLeaveCriticalSection(&m_Lock);
  225. pNode = new CLockedContextClassFPMPoolNode< T >;
  226. if ( pNode != NULL )
  227. {
  228. if ( (pNode->m_Item.*this->m_pAllocFunction)( pContext ) == FALSE )
  229. {
  230. delete pNode;
  231. pNode = NULL;
  232. }
  233. }
  234. }
  235. else
  236. {
  237. pNode = m_pPool;
  238. m_pPool = m_pPool->m_pNext;
  239. DNLeaveCriticalSection(&m_Lock);
  240. }
  241. //
  242. // if we have an entry (it was freshly created, or removed from the pool),
  243. // attempt to initialize it before passing it to the user
  244. //
  245. if ( pNode != NULL )
  246. {
  247. if ( (pNode->m_Item.*this->m_pInitFunction)( pContext ) == FALSE )
  248. {
  249. DNEnterCriticalSection(&m_Lock);
  250. pNode->m_pNext = m_pPool;
  251. m_pPool = pNode;
  252. DNLeaveCriticalSection(&m_Lock);
  253. pNode = NULL;
  254. }
  255. else
  256. {
  257. pNode->m_pContext = pContext;
  258. pReturn = &pNode->m_Item;
  259. DEBUG_ONLY( pNode->m_pNext = (CLockedContextClassFPMPoolNode<T>*) BLANK_NODE_VALUE );
  260. DEBUG_ONLY( InterlockedIncrement(const_cast<LONG*>(&m_lOutstandingItemCount)) );
  261. }
  262. }
  263. return pReturn;
  264. }
  265. //**********************************************************************
  266. //**********************************************************************
  267. // ------------------------------
  268. // CLockedContextClassFixedPool::Release - return item to pool
  269. //
  270. // Entry: Pointer to item
  271. //
  272. // Exit: Nothing
  273. // ------------------------------
  274. #undef DPF_MODNAME
  275. #define DPF_MODNAME "CCFPM::Release"
  276. template< class T >
  277. void CLockedContextClassFixedPool< T >::Release( T *const pItem )
  278. {
  279. CLockedContextClassFPMPoolNode< T > *pNode;
  280. DEBUG_ONLY( DNASSERT( m_fInitialized != FALSE ) );
  281. DNASSERT( pItem != NULL );
  282. DBG_CASSERT( sizeof( BYTE* ) == sizeof( pItem ) );
  283. DBG_CASSERT( sizeof( CLockedContextClassFPMPoolNode< T >* ) == sizeof( BYTE* ) );
  284. pNode = reinterpret_cast<CLockedContextClassFPMPoolNode< T >*>( &reinterpret_cast<BYTE*>( pItem )[ -OFFSETOF( CLockedContextClassFPMPoolNode< T >, m_Item ) ] );
  285. DEBUG_ONLY( DNASSERT( pNode->m_pNext == (CLockedContextClassFPMPoolNode< T >*)BLANK_NODE_VALUE ) );
  286. (pNode->m_Item.*this->m_pReleaseFunction)( pNode->m_pContext );
  287. DNEnterCriticalSection(&m_Lock);
  288. #if defined(CHECK_FOR_DUPLICATE_LOCKEDCCFPM_RELEASE) && defined(DEBUG)
  289. {
  290. CLockedContextClassFPMPoolNode< T > *pTemp;
  291. pTemp = m_pPool;
  292. while ( pTemp != NULL )
  293. {
  294. DNASSERT( pTemp != pNode );
  295. pTemp = pTemp->m_pNext;
  296. }
  297. }
  298. #endif // CHECK_FOR_DUPLICATE_LOCKEDCCFPM_RELEASE
  299. #ifdef NO_POOLS
  300. (pNode->m_Item.*this->m_pDeallocFunction)( pNode->m_pContext );
  301. delete pNode;
  302. #else
  303. pNode->m_pNext = m_pPool;
  304. m_pPool = pNode;
  305. #endif
  306. DEBUG_ONLY( InterlockedDecrement(const_cast<LONG*>(&m_lOutstandingItemCount)) );
  307. DNLeaveCriticalSection(&m_Lock);
  308. }
  309. //**********************************************************************
  310. #ifdef __LOCAL_OFFSETOF_DEFINED__
  311. #undef __LOCAL_OFFSETOF_DEFINED__
  312. #undef OFFSETOF
  313. #endif // __LOCAL_OFFSETOF_DEFINED__
  314. #undef DPF_MODNAME
  315. #undef DPF_SUBCOMP
  316. #endif // __CONTEXT_CLASS_FPM_H__