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.

317 lines
7.0 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2002.
  5. //
  6. // File: Worker.hxx
  7. //
  8. // Contents: Query queue
  9. //
  10. // History: 29-Dec-93 KyleP Created
  11. // 27-Sep-94 KyleP Generalized
  12. //
  13. //--------------------------------------------------------------------------
  14. #pragma once
  15. class CWorkQueue;
  16. class CWorkThread;
  17. //+---------------------------------------------------------------------------
  18. //
  19. // Class: PWorkItem
  20. //
  21. // Purpose: Pure virual class for work items
  22. //
  23. // History: 27-Sep-94 KyleP Created.
  24. //
  25. //----------------------------------------------------------------------------
  26. class PWorkItem
  27. {
  28. public:
  29. PWorkItem( LONGLONG eSigWorkItem ) : _eSigWorkItem(eSigWorkItem) {}
  30. virtual ~PWorkItem() {}
  31. //
  32. // Work function
  33. //
  34. virtual void DoIt( CWorkThread * pThread ) = 0;
  35. virtual void DeferredAPC() {}
  36. //
  37. // Refcounting
  38. //
  39. virtual void AddRef() = 0;
  40. virtual void Release() = 0;
  41. //
  42. // Linked list methods.
  43. //
  44. inline void Link( PWorkItem * pNext );
  45. inline PWorkItem * Next();
  46. protected:
  47. //-----------------------------------------------
  48. // This MUST be the first variable in this class.
  49. //-----------------------------------------------
  50. LONGLONG _eSigWorkItem;
  51. private:
  52. //
  53. // Link to next work item
  54. //
  55. PWorkItem * _pNext;
  56. };
  57. //+---------------------------------------------------------------------------
  58. //
  59. // Class: CWorkThread
  60. //
  61. // Purpose: Worker thread
  62. //
  63. // History: 27-Sep-94 KyleP Created.
  64. //
  65. //----------------------------------------------------------------------------
  66. class CWorkThread
  67. {
  68. public:
  69. CWorkThread( CWorkQueue & queue,
  70. CWorkThread * pNext,
  71. SHandle & hEvt1,
  72. SHandle & hEvt2
  73. );
  74. ~CWorkThread();
  75. void lokSetActiveItem( PWorkItem * pitem ) { _pitem = pitem; }
  76. PWorkItem * ActiveItem() { return _pitem; }
  77. void DeferAPC( PWorkItem * pItem );
  78. void Reset()
  79. {
  80. vqDebugOut(( DEB_RESULTS, "Worker: RESET available\n" ));
  81. _evtQueryAvailable.Reset();
  82. }
  83. void Wakeup()
  84. {
  85. vqDebugOut(( DEB_ITRACE, "Worker: SET available\n" ));
  86. _evtQueryAvailable.Set();
  87. }
  88. void Wait();
  89. void Done();
  90. void SetProcessingAPC( BOOL f );
  91. BOOL IsProcessingAPC() const { return _fProcessingAPC; }
  92. void WaitForCompletion( PWorkItem * pitem );
  93. void lokAbort() { _fAbort = TRUE; }
  94. BOOL lokShouldAbort() { return _fAbort; }
  95. void Link( CWorkThread * pNext ) { _pNext = pNext; }
  96. CWorkThread * Next() { return _pNext; }
  97. DWORD GetThreadId() { return _Thread.GetThreadId(); }
  98. HANDLE GetThreadHandle() { return _Thread.GetHandle(); }
  99. BOOL IsIdleFor( DWORD cmsIdle )
  100. {
  101. DWORD dwIdle = GetTickCount() - _dwLastUsed;
  102. return ( dwIdle >= cmsIdle );
  103. }
  104. #ifdef CIEXTMODE
  105. void CiExtDump(void *ciExtSelf);
  106. #endif
  107. private:
  108. friend CWorkQueue;
  109. inline void AddRef();
  110. inline void Release();
  111. inline BOOL IsReferenced();
  112. void ProcessDeferredAPCs();
  113. static DWORD WINAPI WorkerThread( void * self );
  114. long _cRef;
  115. PWorkItem * _pitem; // Current item in work queue
  116. PWorkItem * _pDeferredAPCs; // List of deferred APC items
  117. BOOL _fProcessingAPC; // TRUE if currently processing an APC
  118. DWORD _dwLastUsed; // GetTickCount() when last used
  119. CWorkQueue & _queue; // Queue of work items
  120. CWorkThread * _pNext; // Next thread in llist
  121. BOOL _fAbort;
  122. CThread _Thread; // This thread
  123. // NOTE: these CEventSem's must be declared after the CThread!
  124. CEventSem _evtQueryAvailable; // Signaled when there is work
  125. CEventSem _evtDone; // Signaled when query is complete
  126. };
  127. //+---------------------------------------------------------------------------
  128. //
  129. // Class: CWorkQueue
  130. //
  131. // Purpose: Queue of pending work items
  132. //
  133. // History: 27-Sep-94 KyleP Created.
  134. //
  135. //----------------------------------------------------------------------------
  136. class CWorkQueue
  137. {
  138. public:
  139. enum WorkQueueType { workQueueQuery=0xa,
  140. workQueueRequest,
  141. workQueueFrmwrkClient };
  142. CWorkQueue( unsigned cThread, WorkQueueType workQueue );
  143. void Init()
  144. {
  145. _mtxLock.Init();
  146. RefreshParams( 2, 0 );
  147. _fInit = TRUE;
  148. }
  149. ~CWorkQueue();
  150. void Add( PWorkItem * pitem );
  151. void Remove( PWorkItem * pitem );
  152. inline unsigned Count();
  153. void RefreshParams( ULONG cMaxActiveThread, ULONG cMinIdleThreads );
  154. void Shutdown();
  155. inline void AddRef( CWorkThread * pThread );
  156. void AddRefWorkThreads();
  157. void ReleaseWorkThreads();
  158. void Release( CWorkThread * pThread );
  159. # ifdef CIEXTMODE
  160. void CiExtDump(void *ciExtSelf);
  161. # endif
  162. void GetWorkQueueRegParams( ULONG & cMaxActiveThreads,
  163. ULONG & cMinIdleThreads );
  164. ULONG ThreadCount() { return _cWorker; }
  165. ULONG IdleThreadCount() { return _cIdle; }
  166. void IncrementAPC() { InterlockedIncrement( &_cInAPC ); }
  167. void DecrementAPC() { InterlockedDecrement( &_cInAPC ); }
  168. private:
  169. friend class CWorkThread;
  170. void Remove( CWorkThread & Worker );
  171. void lokAddThread();
  172. void RemoveThreads();
  173. //
  174. // Link fields
  175. //
  176. PWorkItem * _pHead;
  177. PWorkItem * _pTail;
  178. unsigned _cItems;
  179. //
  180. // Serialization
  181. //
  182. CMutexSem _mtxLock;
  183. //
  184. // Worker threads. Must be after semaphores.
  185. //
  186. CDynArray<CWorkThread> _apWorker;
  187. unsigned _cWorker;
  188. unsigned _cIdle;
  189. long _cInAPC;
  190. CWorkThread * _pIdle;
  191. BOOL _fInit;
  192. BOOL _fAbort;
  193. WorkQueueType _QueueType;
  194. ULONG _cMaxActiveThreads;
  195. ULONG _cMinIdleThreads;
  196. };
  197. inline unsigned CWorkQueue::Count()
  198. {
  199. return( _cItems );
  200. }
  201. inline void CWorkQueue::AddRef( CWorkThread * pThread )
  202. {
  203. pThread->AddRef();
  204. }
  205. inline void PWorkItem::Link( PWorkItem * pNext )
  206. {
  207. _pNext = pNext;
  208. }
  209. inline PWorkItem * PWorkItem::Next()
  210. {
  211. return( _pNext );
  212. }
  213. inline void CWorkThread::AddRef()
  214. {
  215. InterlockedIncrement( &_cRef );
  216. }
  217. inline void CWorkThread::Release()
  218. {
  219. InterlockedDecrement( &_cRef );
  220. }
  221. inline BOOL CWorkThread::IsReferenced()
  222. {
  223. return _cRef != 0;
  224. }
  225. //
  226. // Global work queue. All queries will use threads from here.
  227. //
  228. extern CWorkQueue TheWorkQueue;