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.

332 lines
8.3 KiB

  1. ///////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright(C) 1997-1998 Microsoft Corporation all rights reserved.
  4. //
  5. // Module: iascompool.h
  6. //
  7. // Project: Everest
  8. //
  9. // Description: Object pool that uses CoTaskMemAlloc() / CoTaskMemFree()
  10. //
  11. // Author: TLP 11/11/97
  12. //
  13. ///////////////////////////////////////////////////////////////////////////
  14. #ifndef __IAS_COM_MEMPOOL_H_
  15. #define __IAS_COM_MEMPOOL_H_
  16. // Assume another include has #included ias.h
  17. #include <vector>
  18. #include <list>
  19. using namespace std;
  20. #define COM_MEMPOOL_INITIALIZED 1
  21. #define COM_MEMPOOL_UNINITIALIZED 0
  22. //
  23. // NOTE: m_lState must be aligned on 32 bit value or calls to
  24. // InterlockedExchange will fail on multi-processor x86 systems.
  25. template < class T, DWORD dwPerAllocT, bool bFixedSize >
  26. class CComMemPool
  27. {
  28. // State flag - 1 = mem pool initialized, 0 = mem pool uninitialized
  29. LONG m_lState;
  30. // Total number of items allocated
  31. DWORD m_dwCountTotal;
  32. // Number of items on the free list
  33. DWORD m_dwCountFree;
  34. // Highest number of outstanding allocations
  35. DWORD m_dwHighWater;
  36. // Number of objects per system memory allocation
  37. DWORD m_dwPerAllocT;
  38. // Fixed size pool flag
  39. bool m_bFixedSize;
  40. // Critical Section - serializes free item list access
  41. CRITICAL_SECTION m_CritSec;
  42. // Memory block list
  43. typedef list<PVOID> MemBlockList;
  44. typedef MemBlockList::iterator MemBlockListIterator;
  45. MemBlockList m_listMemBlocks;
  46. // Free item list
  47. typedef list<T*> FreeList;
  48. typedef FreeList::iterator FreeListIterator;
  49. FreeList m_listFreeT;
  50. // Disallow copy and assignment
  51. CComMemPool(const CComMemPool& theClass);
  52. CComMemPool& operator=(const CComMemPool& theClass);
  53. public:
  54. //
  55. // Constructor
  56. //
  57. CComMemPool()
  58. : m_listMemBlocks(0),
  59. m_listFreeT(0) // pre-alloc space for list nodes
  60. {
  61. m_lState = COM_MEMPOOL_UNINITIALIZED;
  62. m_dwPerAllocT = dwPerAllocT;
  63. m_bFixedSize = bFixedSize;
  64. m_dwCountTotal = 0;
  65. m_dwCountFree = 0;
  66. m_dwHighWater = 0;
  67. InitializeCriticalSection(&m_CritSec);
  68. }
  69. //
  70. // Destructor
  71. //
  72. ~CComMemPool()
  73. {
  74. _ASSERT( COM_MEMPOOL_UNINITIALIZED == m_lState );
  75. DeleteCriticalSection(&m_CritSec);
  76. }
  77. //////////////////////////////////////////////////////////////////////////
  78. // Init() - Initialize the memory pool
  79. //////////////////////////////////////////////////////////////////////////
  80. bool Init(void)
  81. {
  82. bool bReturn = false;
  83. if ( COM_MEMPOOL_UNINITIALIZED == InterlockedExchange(&m_lState, COM_MEMPOOL_INITIALIZED) )
  84. {
  85. if ( AllocateMemBlock() )
  86. {
  87. bReturn = true;
  88. }
  89. else
  90. {
  91. InterlockedExchange(&m_lState, COM_MEMPOOL_UNINITIALIZED);
  92. }
  93. }
  94. else
  95. {
  96. _ASSERTE(FALSE);
  97. }
  98. return bReturn;
  99. }
  100. //////////////////////////////////////////////////////////////////////////
  101. // Shutdown() - Shutdown the memory pool freeing any system resources used
  102. //////////////////////////////////////////////////////////////////////////
  103. void Shutdown(void)
  104. {
  105. MemBlockListIterator p;
  106. MemBlockListIterator q;
  107. if ( COM_MEMPOOL_INITIALIZED == InterlockedExchange(&m_lState, COM_MEMPOOL_UNINITIALIZED) )
  108. {
  109. if ( m_dwCountTotal != m_dwCountFree )
  110. {
  111. // Still have blocks outstanding...
  112. //
  113. _ASSERTE( FALSE );
  114. }
  115. if ( ! m_listMemBlocks.empty() )
  116. {
  117. p = m_listMemBlocks.begin();
  118. q = m_listMemBlocks.end();
  119. while ( p != q )
  120. {
  121. CoTaskMemFree(*p);
  122. p++;
  123. }
  124. m_listMemBlocks.clear();
  125. }
  126. m_dwCountTotal = 0;
  127. m_dwCountFree = 0;
  128. }
  129. else
  130. {
  131. // COM pool is not inititalized
  132. //
  133. _ASSERTE( FALSE );
  134. }
  135. }
  136. //////////////////////////////////////////////////////////////////////////
  137. // Alloc() - Allocate an unitialized object from the pool
  138. //////////////////////////////////////////////////////////////////////////
  139. T* Alloc(void)
  140. {
  141. T* pMemBlk = NULL;
  142. TraceFunctEnter("CComMemPool::Alloc()");
  143. if ( COM_MEMPOOL_INITIALIZED == m_lState )
  144. {
  145. EnterCriticalSection(&m_CritSec);
  146. if ( m_listFreeT.empty() )
  147. {
  148. if ( ! m_bFixedSize )
  149. {
  150. if ( AllocateMemBlock() )
  151. {
  152. pMemBlk = m_listFreeT.front();
  153. m_listFreeT.pop_front();
  154. m_dwCountFree--;
  155. if ( m_dwHighWater < (m_dwCountTotal - m_dwCountFree) )
  156. {
  157. m_dwHighWater++;
  158. }
  159. }
  160. else
  161. {
  162. ErrorTrace(0,"Could not allocate memory!");
  163. }
  164. }
  165. else
  166. {
  167. ErrorTrace(0,"Fixed size pool is exhausted!");
  168. }
  169. }
  170. else
  171. {
  172. pMemBlk = m_listFreeT.front();
  173. m_listFreeT.pop_front();
  174. m_dwCountFree--;
  175. if ( m_dwHighWater < (m_dwCountTotal - m_dwCountFree) )
  176. {
  177. m_dwHighWater++;
  178. }
  179. }
  180. LeaveCriticalSection(&m_CritSec);
  181. }
  182. else
  183. {
  184. ErrorTrace(0,"The memory pool is not initialized!");
  185. _ASSERTE( FALSE );
  186. }
  187. if ( pMemBlk )
  188. {
  189. memset(pMemBlk, 0, sizeof(T));
  190. new (pMemBlk) T(); // Placement new for class T - requires default contructor
  191. }
  192. TraceFunctLeave();
  193. return pMemBlk;
  194. }
  195. //////////////////////////////////////////////////////////////////////////
  196. // Free() - Return an object to the memory pool
  197. //////////////////////////////////////////////////////////////////////////
  198. void Free(T *pMemBlk)
  199. {
  200. TraceFunctEnter("CComMemPool::Free()");
  201. if ( COM_MEMPOOL_INITIALIZED == m_lState )
  202. {
  203. pMemBlk->~T(); // Explicit call to destructor due to placement new
  204. EnterCriticalSection(&m_CritSec);
  205. m_listFreeT.insert(m_listFreeT.begin(),pMemBlk);
  206. m_dwCountFree++;
  207. LeaveCriticalSection(&m_CritSec);
  208. }
  209. else
  210. {
  211. ErrorTrace(0,"The memory pool is not initialized!");
  212. _ASSERTE( FALSE );
  213. }
  214. TraceFunctLeave();
  215. }
  216. //////////////////////////////////////////////////////////////////////////
  217. // Dump() - Dump the contents of the memory pool - Debug Service
  218. //////////////////////////////////////////////////////////////////////////
  219. void Dump(void)
  220. {
  221. #ifdef DEBUG
  222. UINT i;
  223. MemBlockListIterator p;
  224. FreeListIterator r;
  225. FreeListIterator s;
  226. TraceFunctEnter("CComMemPool::Dump()");
  227. if ( COM_MEMPOOL_INITIALIZED == m_lState )
  228. {
  229. // Dump the counts
  230. EnterCriticalSection(&m_CritSec);
  231. DebugTrace(0,"m_dwCountTotal = %d", m_dwCountTotal);
  232. DebugTrace(0,"m_dwCountFree = %d", m_dwCountFree);
  233. DebugTrace(0,"m_dwHighWater = %d", m_dwHighWater);
  234. // Dump the pointers to memory blocks
  235. DebugTrace(0,"m_listMemBlocks.size() = %d", m_listMemBlocks.size());
  236. p = m_listMemBlocks.begin();
  237. i = 0;
  238. while ( p != m_listMemBlocks.end() )
  239. {
  240. DebugTrace(0,"m_listMemBlocks block %d = $%p", i, *p);
  241. i++;
  242. p++;
  243. }
  244. // Dump the pointers to items
  245. DebugTrace(0,"CComMemPool::Dump() - m_listFreeT.size() = %d", m_listFreeT.size());
  246. r = m_listFreeT.begin();
  247. i = 0;
  248. while ( r != m_listFreeT.end() )
  249. {
  250. DebugTrace(0,"CComMemPool::Dump() - m_listFreeT item %d = $%p", i, *r);
  251. i++;
  252. r++;
  253. }
  254. LeaveCriticalSection(&m_CritSec);
  255. }
  256. else
  257. {
  258. ErrorTrace(0,"The memory pool is not initialized!");
  259. _ASSERTE( FALSE );
  260. }
  261. TraceFunctLeave();
  262. #endif // DEBUG
  263. }
  264. private:
  265. //////////////////////////////////////////////////////////////////////////
  266. // AllocateMemBlock() - Allocate some system memory and chop it into
  267. // T sized blocks
  268. //////////////////////////////////////////////////////////////////////////
  269. bool AllocateMemBlock()
  270. {
  271. bool bReturn = false;
  272. UINT i;
  273. UINT uBlkSize;
  274. T* lpMemBlock;
  275. TraceFunctEnter("CComMemPool::AllocateMemBlock()");
  276. uBlkSize = m_dwPerAllocT * sizeof(T);
  277. lpMemBlock = (T*) CoTaskMemAlloc(uBlkSize);
  278. if ( lpMemBlock )
  279. {
  280. memset(lpMemBlock, 0, uBlkSize);
  281. m_listMemBlocks.insert(m_listMemBlocks.begin(), (PVOID)lpMemBlock);
  282. // Chop up the newly allocated memory block into sizeof(T) sized elements and place
  283. // the elements on the list of pointers to Ts.
  284. for ( i = 0; i < m_dwPerAllocT; i++ )
  285. {
  286. m_listFreeT.insert(m_listFreeT.end(),lpMemBlock);
  287. lpMemBlock++;
  288. }
  289. // Update the pool memory use variables
  290. m_dwCountTotal += m_dwPerAllocT;
  291. m_dwCountFree += m_dwPerAllocT;
  292. bReturn = true;
  293. }
  294. TraceFunctLeave();
  295. return bReturn;
  296. }
  297. }; // End of CComMemPool
  298. #endif // __IAS_COM_MEMPOOL_H_