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.

273 lines
8.3 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996.
  5. //
  6. // File: workq.cxx
  7. //
  8. // Contents: Definitions of CWorkQueue methods
  9. //
  10. // Classes:
  11. //
  12. // Functions: Constructor, destructor, AddItem, GetNextItem, Done
  13. //
  14. // Coupling:
  15. //
  16. // Notes: For use in uni- or multi-threaded applications
  17. //
  18. // History: 9-30-1996 ericne Created
  19. //
  20. //----------------------------------------------------------------------------
  21. #include "workq.hxx"
  22. //+---------------------------------------------------------------------------
  23. //
  24. // Member: ::CWorkQueue
  25. //
  26. // Synopsis: Initializes members
  27. //
  28. // Arguments: (none)
  29. //
  30. // Returns:
  31. //
  32. // History: 9-30-1996 ericne Created
  33. //
  34. // Notes:
  35. //
  36. //----------------------------------------------------------------------------
  37. template<class T, int I>
  38. CWorkQueue<T,I>::CWorkQueue()
  39. : m_iAddItemIndex( 0 ),
  40. m_iGetItemIndex( 0 ),
  41. m_hSemFull( NULL ),
  42. m_hSemEmpty( NULL ),
  43. m_hEventDone( NULL )
  44. {
  45. InitializeCriticalSection( &m_CriticalSection );
  46. // Create a semaphore with an initial count of 0. Each time
  47. // GetItem is called, this value is decrimented. Each time
  48. // AddItem is called, this value is incremented.
  49. while( 1 )
  50. {
  51. m_hSemFull = CreateSemaphore( NULL, // No security attributes
  52. 0, // Initial value of 0
  53. I, // Maximum value of I
  54. NULL ); // No name
  55. if( NULL != m_hSemFull )
  56. break;
  57. printf( "CreateSemaphore failed. Will try again in %d milliseconds.\r\n"
  58. "GetLastError() returned 0x%08x\r\n",
  59. dwSleepTime, GetLastError() );
  60. Sleep( dwSleepTime );
  61. }
  62. // Create a semaphore with an initial count of I. Each time
  63. // AddItem is called, this value is decrimented. Each time
  64. // GetItem is called, this value is incremented.
  65. while( 1 )
  66. {
  67. m_hSemEmpty = CreateSemaphore( NULL, // No security attributes
  68. I, // Initial value of I
  69. I, // Maximum value of I
  70. NULL ); // No name
  71. if( NULL != m_hSemEmpty )
  72. break;
  73. printf( "CreateSemaphore failed. Will try again in %d milliseconds.\r\n"
  74. "GetLastError() returned 0x%08x\r\n",
  75. dwSleepTime, GetLastError() );
  76. Sleep( dwSleepTime );
  77. }
  78. // This event is used by a producer thread to signal the consumer threads
  79. // that no additional work items will be placed in the queue
  80. while( 1 )
  81. {
  82. m_hEventDone = CreateEvent( NULL, // No security attributes
  83. TRUE, // Manual reset
  84. FALSE, // Initial state of non-signaled
  85. NULL ); // No name
  86. if( NULL != m_hEventDone )
  87. break;
  88. printf( "CreateEvent failed. Will try again in %d milliseconds.\r\n"
  89. "GetLastError() returned 0x%08x\r\n",
  90. dwSleepTime, GetLastError() );
  91. Sleep( dwSleepTime );
  92. }
  93. } //::CWorkQueue
  94. //+---------------------------------------------------------------------------
  95. //
  96. // Member: ::~CWorkQueue
  97. //
  98. // Synopsis: Closes the handles to the semaphores
  99. //
  100. // Arguments: (none)
  101. //
  102. // Returns:
  103. //
  104. // History: 9-30-1996 ericne Created
  105. //
  106. // Notes:
  107. //
  108. //----------------------------------------------------------------------------
  109. template<class T, int I>
  110. CWorkQueue<T,I>::~CWorkQueue()
  111. {
  112. if( ! CloseHandle( m_hSemFull ) )
  113. printf( "~CWorkQueue(): Could not close handle to semaphore."
  114. "GetLastError() returns 0x%08x", GetLastError() );
  115. if( ! CloseHandle( m_hSemEmpty ) )
  116. printf( "~CWorkQueue(): Could not close handle to semaphore."
  117. "GetLastError() returns 0x%08x", GetLastError() );
  118. if( ! CloseHandle( m_hEventDone ) )
  119. printf( "~CWorkQueue(): Could not close handle to event."
  120. "GetLastError() returns 0x%08x", GetLastError() );
  121. DeleteCriticalSection( &m_CriticalSection );
  122. } //::~CWorkQueue
  123. //+---------------------------------------------------------------------------
  124. //
  125. // Member: ::AddItem
  126. //
  127. // Synopsis: Adds an item to the queue
  128. //
  129. // Arguments: [ToAdd] -- The item to add
  130. //
  131. // Returns: none
  132. //
  133. // History: 9-30-1996 ericne Created
  134. //
  135. // Notes:
  136. //
  137. //----------------------------------------------------------------------------
  138. template<class T, int I>
  139. void CWorkQueue<T,I>::AddItem( const T &ToAdd )
  140. {
  141. // Wait until m_hSemEmpty is greater than zero, then decriment
  142. if( WAIT_OBJECT_0 != WaitForSingleObject( m_hSemEmpty, INFINITE ) )
  143. printf( "CWorkQueue::AddItem() : Wait for semaphore failed.\r\n"
  144. "GetLastError() returns 0x%08x\r\n", GetLastError() );
  145. // enter the critical section
  146. EnterCriticalSection( &m_CriticalSection );
  147. // Bit-wise copy the structure
  148. memcpy( (void*)&m_WorkItems[m_iAddItemIndex], (void*)&ToAdd, sizeof( T ) );
  149. // Increment the index
  150. m_iAddItemIndex = ( m_iAddItemIndex + 1 ) % I;
  151. // Leave the critical section
  152. LeaveCriticalSection( &m_CriticalSection );
  153. // Incriment m_hSemFull
  154. if( ! ReleaseSemaphore( m_hSemFull, 1, NULL ) )
  155. printf( "CWorkQueue::AddItem() : Could not release semaphore.\r\n"
  156. "GetLastError() returns 0x%08x\r\n", GetLastError() );
  157. } //::AddItem
  158. //+---------------------------------------------------------------------------
  159. //
  160. // Member: ::Done
  161. //
  162. // Synopsis: Called by a producer thread when it is finished adding stuff
  163. // to the queue
  164. //
  165. // Arguments: (none)
  166. //
  167. // Returns: void
  168. //
  169. // History: 10-01-1996 ericne Created
  170. //
  171. // Notes:
  172. //
  173. //----------------------------------------------------------------------------
  174. template<class T, int I>
  175. void CWorkQueue<T,I>::Done( )
  176. {
  177. // Since this is a manual-reset event, m_hEventDone stays signaled forever.
  178. SetEvent( m_hEventDone );
  179. } //::Done
  180. //+---------------------------------------------------------------------------
  181. //
  182. // Member: ::GetItem
  183. //
  184. // Synopsis: Gets the next work item from the queue.
  185. //
  186. // Arguments: [NextItem] -- Passed by reference. Item is filled in by
  187. // the function
  188. //
  189. // Returns: TRUE if an item was gotten from the queue
  190. // FALSE if queue is empty and m_hEventDone is signaled
  191. //
  192. // History: 9-30-1996 ericne Created
  193. //
  194. // Notes:
  195. //
  196. //----------------------------------------------------------------------------
  197. template<class T, int I>
  198. BOOL CWorkQueue<T,I>::GetItem( T &NextItem )
  199. {
  200. DWORD dwWait = 0;
  201. HANDLE pHandles[2] = { m_hSemFull, m_hEventDone };
  202. // wait until m_hSemFull is > 0 or until m_hEventDone is set
  203. dwWait = WaitForMultipleObjects( 2, pHandles, FALSE, INFINITE );
  204. if( WAIT_OBJECT_0 == dwWait )
  205. {
  206. // There are more work items in the list
  207. // ( done event may or may not be set )
  208. EnterCriticalSection( &m_CriticalSection );
  209. memcpy( (void*) &NextItem,
  210. (void*) &m_WorkItems[m_iGetItemIndex],
  211. sizeof( T ) );
  212. m_iGetItemIndex = ( m_iGetItemIndex + 1 ) % I;
  213. LeaveCriticalSection( &m_CriticalSection );
  214. if( ! ReleaseSemaphore( m_hSemEmpty, 1, NULL ) )
  215. printf( "CWorkQueue::GetItem() : Could not release semaphore.\r\n"
  216. "GetLastError() returns 0x%08x\r\n", GetLastError() );
  217. return( TRUE );
  218. }
  219. else if( WAIT_OBJECT_0 + 1 == dwWait )
  220. {
  221. // Nothing more in list and done event has been set
  222. }
  223. else
  224. {
  225. // An error occured
  226. printf( "CWorkQueue::GetItem() : Wait failed.\r\n"
  227. "GetLastError() returns 0x%08x\r\n", GetLastError() );
  228. }
  229. return( FALSE );
  230. } //::GetItem