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.

257 lines
5.7 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Copyright (c) 1997-1999 Microsoft Corporation
  4. //
  5. // File:
  6. //
  7. // Contents:
  8. //
  9. // History:
  10. //
  11. //---------------------------------------------------------------------------
  12. #ifndef __HANDLE_POOL_H__
  13. #define __HANDLE_POOL_H__
  14. #include <windows.h>
  15. #include <limits.h>
  16. #include "locks.h"
  17. /////////////////////////////////////////////////////////////////////////////
  18. //
  19. // handle pool template class
  20. //
  21. // Note that STL's LIST class is used instead of VECTOR
  22. //
  23. /////////////////////////////////////////////////////////////////////////////
  24. template<class T, DWORD max=ULONG_MAX>
  25. class CHandlePool
  26. {
  27. private:
  28. long m_NumWaiting;
  29. // HUEIWANG 1/23/98
  30. // C++ compiler 10.00.5256 can't compile STL
  31. // _STD list<T> m_Handles; // STL's list
  32. typedef struct _HandleList {
  33. BOOL bAvailable;
  34. T m_Value;
  35. struct _HandleList *next;
  36. } HandleList, *LPHandleList;
  37. //
  38. // List of handles in the pool
  39. //
  40. LPHandleList m_Handles;
  41. DWORD m_TotalHandles;
  42. //
  43. // Semaphore for available handles
  44. //
  45. CTSemaphore<0, LONG_MAX> m_Available;
  46. // critical section guarding m_Handles.
  47. CCriticalSection m_CS;
  48. //DWORD m_MaxHandles;
  49. public:
  50. CHandlePool();
  51. ~CHandlePool();
  52. HRESULT
  53. AcquireHandle(
  54. T* pHandle,
  55. DWORD dwWaitFile=INFINITE
  56. );
  57. BOOL
  58. AcquireHandleEx(
  59. IN HANDLE hWaitHandle,
  60. IN OUT T* pHandle,
  61. IN DWORD dwWaitFime=INFINITE
  62. );
  63. void
  64. ReleaseHandle(
  65. T pRetHandle
  66. );
  67. DWORD
  68. GetNumberAvailable();
  69. DWORD
  70. GetMaxHandles() {
  71. return max;
  72. }
  73. };
  74. //--------------------------------------------------------------------------------
  75. template<class T, DWORD max>
  76. inline CHandlePool<T, max>::CHandlePool()
  77. {
  78. // m_MaxHandles=max;
  79. m_NumWaiting=0;
  80. m_Handles=NULL;
  81. m_TotalHandles=0;
  82. }
  83. //--------------------------------------------------------------------------------
  84. template<class T, DWORD max>
  85. inline CHandlePool<T, max>::~CHandlePool()
  86. {
  87. // delete all handles still in cache
  88. // might result in handle leak.
  89. //for(_STD list<T>::iterator it=m_Handles.begin(); it != m_Handles.end(); it++)
  90. // delete it;
  91. while(m_Handles)
  92. {
  93. LPHandleList ptr;
  94. ptr=m_Handles;
  95. m_Handles = m_Handles->next;
  96. delete ptr;
  97. }
  98. }
  99. //--------------------------------------------------------------------------------
  100. template<class T, DWORD max>
  101. inline BOOL
  102. CHandlePool<T, max>::AcquireHandleEx(
  103. IN HANDLE hWaitHandle,
  104. IN OUT T* pHandle,
  105. IN DWORD dwWaitFime /* infinite */
  106. )
  107. /*
  108. */
  109. {
  110. BOOL bSuccess;
  111. InterlockedIncrement(&m_NumWaiting);
  112. bSuccess = m_Available.AcquireEx(
  113. hWaitHandle,
  114. dwWaitFime,
  115. FALSE
  116. );
  117. // Available is a semaphore not mutex object.
  118. if(bSuccess == TRUE)
  119. {
  120. // Object Constructor will lock critical section and
  121. // destructor will unlock critical section
  122. CCriticalSectionLocker locker(m_CS);
  123. //assert(m_Handles.size());
  124. //*pHandle = m_Handles.front();
  125. //m_Handles.pop_front();
  126. LPHandleList ptr;
  127. assert(m_Handles != NULL);
  128. *pHandle = m_Handles->m_Value;
  129. ptr=m_Handles;
  130. m_Handles = m_Handles->next;
  131. delete ptr;
  132. m_TotalHandles--;
  133. }
  134. InterlockedDecrement(&m_NumWaiting);
  135. return bSuccess;
  136. }
  137. //--------------------------------------------------------------------------------
  138. template<class T, DWORD max>
  139. inline HRESULT CHandlePool<T, max>::AcquireHandle(
  140. IN OUT T* pHandle,
  141. IN DWORD dwWaitFime /* infinite */
  142. )
  143. /*
  144. */
  145. {
  146. DWORD status;
  147. InterlockedIncrement(&m_NumWaiting);
  148. status = m_Available.Acquire(dwWaitFime, FALSE);
  149. // Available is a semaphore not mutex object.
  150. if(status == WAIT_OBJECT_0)
  151. {
  152. // Object Constructor will lock critical section and
  153. // destructor will unlock critical section
  154. CCriticalSectionLocker locker(m_CS);
  155. //assert(m_Handles.size());
  156. //*pHandle = m_Handles.front();
  157. //m_Handles.pop_front();
  158. LPHandleList ptr;
  159. assert(m_Handles != NULL);
  160. *pHandle = m_Handles->m_Value;
  161. ptr=m_Handles;
  162. m_Handles = m_Handles->next;
  163. delete ptr;
  164. m_TotalHandles--;
  165. status = ERROR_SUCCESS;
  166. }
  167. InterlockedDecrement(&m_NumWaiting);
  168. return status;
  169. }
  170. //--------------------------------------------------------------------------------
  171. template<class T, DWORD max>
  172. inline void CHandlePool<T, max>::ReleaseHandle(
  173. T pRetHandle
  174. )
  175. /*
  176. */
  177. {
  178. if(pRetHandle)
  179. {
  180. CCriticalSectionLocker lock(m_CS);
  181. if( InterlockedExchange(&m_NumWaiting, m_NumWaiting) > 0 ||
  182. m_TotalHandles < max)
  183. {
  184. //m_Handles.push_back(pRetHandle);
  185. LPHandleList ptr;
  186. ptr = new HandleList;
  187. ptr->m_Value = pRetHandle;
  188. ptr->next = m_Handles;
  189. m_Handles = ptr;
  190. m_TotalHandles++;
  191. m_Available.Release(1);
  192. }
  193. else
  194. {
  195. // only cache so many handles.
  196. delete pRetHandle;
  197. }
  198. }
  199. return;
  200. }
  201. //--------------------------------------------------------------------------------
  202. template<class T, DWORD max>
  203. inline DWORD CHandlePool<T, max>::GetNumberAvailable()
  204. {
  205. UINT numAvailable;
  206. m_CS.Lock();
  207. // numAvailable = m_Handles.size();
  208. numAvailable = m_TotalHandles;
  209. m_CS.UnLock();
  210. return numAvailable;
  211. }
  212. #endif