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.

480 lines
10 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. tpsclass.h
  5. Abstract:
  6. Basic classes for Win32 thread pool services functions
  7. Contents:
  8. CCriticalSection_NoCtor
  9. CCriticalSection
  10. CDoubleLinkedListEntry
  11. CDoubleLinkedList
  12. CTimedListEntry
  13. CTimedList
  14. CPrioritizedListEntry
  15. CPrioritizedList
  16. Author:
  17. Richard L Firth (rfirth) 11-Feb-1998
  18. Notes:
  19. Some of these classes have no constructor so that we avoid requiring global
  20. object initialization (via main() e.g.) Therefore, these objects must be
  21. explicitly initialized through the Init() member
  22. Revision History:
  23. 11-Feb-1998 rfirth
  24. Created
  25. --*/
  26. // These linked-list helper macros and types are taken from
  27. // ntdef.h and ntrtl.h. We don't want to include those because
  28. // we have no other reason, and including the nt headers as a
  29. // win32 component causes compilation conflicts.
  30. //
  31. // VOID
  32. // InitializeListHead(
  33. // PLIST_ENTRY ListHead
  34. // );
  35. //
  36. #define InitializeListHead(ListHead) (\
  37. (ListHead)->Flink = (ListHead)->Blink = (ListHead))
  38. //
  39. // BOOLEAN
  40. // IsListEmpty(
  41. // PLIST_ENTRY ListHead
  42. // );
  43. //
  44. #define IsListEmpty(ListHead) \
  45. ((ListHead)->Flink == (ListHead))
  46. //
  47. // PLIST_ENTRY
  48. // RemoveHeadList(
  49. // PLIST_ENTRY ListHead
  50. // );
  51. //
  52. #define RemoveHeadList(ListHead) \
  53. (ListHead)->Flink;\
  54. {RemoveEntryList((ListHead)->Flink)}
  55. //
  56. // PLIST_ENTRY
  57. // RemoveTailList(
  58. // PLIST_ENTRY ListHead
  59. // );
  60. //
  61. #define RemoveTailList(ListHead) \
  62. (ListHead)->Blink;\
  63. {RemoveEntryList((ListHead)->Blink)}
  64. //
  65. // VOID
  66. // RemoveEntryList(
  67. // PLIST_ENTRY Entry
  68. // );
  69. //
  70. #define RemoveEntryList(Entry) {\
  71. PLIST_ENTRY _EX_Blink;\
  72. PLIST_ENTRY _EX_Flink;\
  73. _EX_Flink = (Entry)->Flink;\
  74. _EX_Blink = (Entry)->Blink;\
  75. _EX_Blink->Flink = _EX_Flink;\
  76. _EX_Flink->Blink = _EX_Blink;\
  77. }
  78. //
  79. // VOID
  80. // InsertTailList(
  81. // PLIST_ENTRY ListHead,
  82. // PLIST_ENTRY Entry
  83. // );
  84. //
  85. #define InsertTailList(ListHead,Entry) {\
  86. PLIST_ENTRY _EX_Blink;\
  87. PLIST_ENTRY _EX_ListHead;\
  88. _EX_ListHead = (ListHead);\
  89. _EX_Blink = _EX_ListHead->Blink;\
  90. (Entry)->Flink = _EX_ListHead;\
  91. (Entry)->Blink = _EX_Blink;\
  92. _EX_Blink->Flink = (Entry);\
  93. _EX_ListHead->Blink = (Entry);\
  94. }
  95. //
  96. // VOID
  97. // InsertHeadList(
  98. // PLIST_ENTRY ListHead,
  99. // PLIST_ENTRY Entry
  100. // );
  101. //
  102. #define InsertHeadList(ListHead,Entry) {\
  103. PLIST_ENTRY _EX_Flink;\
  104. PLIST_ENTRY _EX_ListHead;\
  105. _EX_ListHead = (ListHead);\
  106. _EX_Flink = _EX_ListHead->Flink;\
  107. (Entry)->Flink = _EX_Flink;\
  108. (Entry)->Blink = _EX_ListHead;\
  109. _EX_Flink->Blink = (Entry);\
  110. _EX_ListHead->Flink = (Entry);\
  111. }
  112. //
  113. // data
  114. //
  115. extern const char g_cszShlwapi[];
  116. extern DWORD g_ActiveRequests;
  117. extern DWORD g_dwTerminationThreadId;
  118. extern BOOL g_bTpsTerminating;
  119. extern BOOL g_bDeferredWorkerTermination;
  120. extern BOOL g_bDeferredWaiterTermination;
  121. extern BOOL g_bDeferredTimerTermination;
  122. EXTERN_C DWORD g_TpsTls;
  123. EXTERN_C BOOL g_bDllTerminating;
  124. //
  125. // macros
  126. //
  127. #if !defined(ARRAY_ELEMENTS)
  128. #define ARRAY_ELEMENTS(array) (sizeof(array)/sizeof(array[0]))
  129. #endif
  130. #if !defined(LAST_ELEMENT)
  131. #define LAST_ELEMENT(array) (ARRAY_ELEMENTS(array) - 1)
  132. #endif
  133. #if !defined(FT2LL)
  134. #define FT2LL(x) (*(LONGLONG *)&(x))
  135. #endif
  136. //
  137. // classes
  138. //
  139. //
  140. // CCriticalSection_NoCtor - critical section class without constructor or
  141. // destructor for use in global variables
  142. //
  143. class CCriticalSection_NoCtor {
  144. private:
  145. CRITICAL_SECTION m_critsec;
  146. public:
  147. VOID Init(VOID) {
  148. InitializeCriticalSection(&m_critsec);
  149. }
  150. VOID Terminate(VOID) {
  151. DeleteCriticalSection(&m_critsec);
  152. }
  153. VOID Acquire(VOID) {
  154. EnterCriticalSection(&m_critsec);
  155. }
  156. VOID Release(VOID) {
  157. LeaveCriticalSection(&m_critsec);
  158. }
  159. };
  160. //
  161. // CCriticalSection
  162. //
  163. class CCriticalSection : public CCriticalSection_NoCtor {
  164. public:
  165. CCriticalSection() {
  166. Init();
  167. }
  168. ~CCriticalSection() {
  169. Terminate();
  170. }
  171. };
  172. //
  173. // CDoubleLinkedListEntry/CDoubleLinkedList
  174. //
  175. #define CDoubleLinkedList CDoubleLinkedListEntry
  176. class CDoubleLinkedListEntry {
  177. private:
  178. LIST_ENTRY m_List;
  179. public:
  180. VOID Init(VOID) {
  181. InitializeListHead(&m_List);
  182. }
  183. CDoubleLinkedListEntry * Head(VOID) {
  184. return (CDoubleLinkedListEntry *)&m_List;
  185. }
  186. CDoubleLinkedListEntry * Next(VOID) {
  187. return (CDoubleLinkedListEntry *)m_List.Flink;
  188. }
  189. CDoubleLinkedListEntry * Prev(VOID) {
  190. return (CDoubleLinkedListEntry *)m_List.Blink;
  191. }
  192. BOOL IsHead(CDoubleLinkedListEntry * pEntry) {
  193. return pEntry == Head();
  194. }
  195. VOID InsertHead(CDoubleLinkedList * pList) {
  196. InsertHeadList(&pList->m_List, &m_List);
  197. }
  198. VOID InsertTail(CDoubleLinkedList * pList) {
  199. InsertTailList(&pList->m_List, &m_List);
  200. }
  201. VOID Remove(VOID) {
  202. RemoveEntryList(&m_List);
  203. }
  204. CDoubleLinkedListEntry * RemoveHead(VOID) {
  205. //
  206. // APPCOMPAT - (compiler?) for some reason, the line:
  207. //
  208. // return (CDoubleLinkedListEntry *)RemoveHeadList(&List);
  209. //
  210. // returns the Flink pointer, but doesn't remove it from List
  211. //
  212. PLIST_ENTRY pEntry = RemoveHeadList(&m_List);
  213. return (CDoubleLinkedListEntry *)pEntry;
  214. }
  215. CDoubleLinkedListEntry * RemoveTail(VOID) {
  216. //
  217. // APPCOMPAT - see RemoveHead()
  218. //
  219. PLIST_ENTRY pEntry = RemoveTailList(&m_List);
  220. return (CDoubleLinkedListEntry *)pEntry;
  221. }
  222. BOOL IsEmpty(VOID) {
  223. return IsListEmpty(&m_List);
  224. }
  225. CDoubleLinkedListEntry * FindEntry(CDoubleLinkedListEntry * pEntry) {
  226. for (CDoubleLinkedListEntry * p = Next(); p != Head(); p = p->Next()) {
  227. if (p == pEntry) {
  228. return pEntry;
  229. }
  230. }
  231. return NULL;
  232. }
  233. };
  234. //
  235. // CTimedListEntry/CTimedList
  236. //
  237. #define CTimedList CTimedListEntry
  238. class CTimedListEntry : public CDoubleLinkedListEntry {
  239. private:
  240. DWORD m_dwTimeStamp;
  241. DWORD m_dwWaitTime;
  242. public:
  243. CTimedListEntry() {
  244. }
  245. CTimedListEntry(DWORD dwWaitTime) {
  246. m_dwTimeStamp = GetTickCount();
  247. m_dwWaitTime = dwWaitTime;
  248. }
  249. VOID Init(VOID) {
  250. CDoubleLinkedListEntry::Init();
  251. m_dwTimeStamp = 0;
  252. m_dwWaitTime = 0;
  253. }
  254. DWORD GetTimeStamp(VOID) const {
  255. return m_dwTimeStamp;
  256. }
  257. VOID SetTimeStamp(DWORD dwTimeStamp = GetTickCount()) {
  258. m_dwTimeStamp = dwTimeStamp;
  259. }
  260. DWORD GetWaitTime(VOID) const {
  261. return m_dwWaitTime;
  262. }
  263. VOID SetWaitTime(DWORD dwWaitTime) {
  264. m_dwWaitTime = dwWaitTime;
  265. }
  266. VOID SetExpirationTime(DWORD dwWaitTime) {
  267. SetTimeStamp();
  268. SetWaitTime(dwWaitTime);
  269. }
  270. BOOL IsTimedOut(DWORD dwTimeNow = GetTickCount()) const {
  271. return (m_dwWaitTime != INFINITE)
  272. ? (dwTimeNow >= (m_dwTimeStamp + m_dwWaitTime))
  273. : FALSE;
  274. }
  275. BOOL IsInfiniteTimeout(VOID) const {
  276. return (m_dwWaitTime == INFINITE);
  277. }
  278. DWORD ExpiryTime(VOID) const {
  279. return m_dwTimeStamp + m_dwWaitTime;
  280. }
  281. DWORD TimeToWait(DWORD dwTimeNow = GetTickCount()) {
  282. DWORD expiryTime = ExpiryTime();
  283. return IsInfiniteTimeout()
  284. ? INFINITE
  285. : ((dwTimeNow >= expiryTime)
  286. ? 0
  287. : expiryTime - dwTimeNow);
  288. }
  289. //BOOL InsertFront(CDoubleLinkedList * pList) {
  290. //
  291. // DWORD dwExpiryTime = ExpiryTime();
  292. // CTimedListEntry * pEntry;
  293. //
  294. // for (pEntry = (CTimedListEntry *)pList->Next();
  295. // pEntry != (CTimedListEntry *)pList->Head();
  296. // pEntry = (CTimedListEntry *)pEntry->Next()) {
  297. // if (dwExpiryTime < pEntry->ExpiryTime()) {
  298. // break;
  299. // }
  300. // }
  301. // InsertTail(pEntry);
  302. // return this == pList->Next();
  303. //}
  304. BOOL InsertBack(CDoubleLinkedList * pList) {
  305. DWORD dwExpiryTime = ExpiryTime();
  306. CTimedListEntry * pEntry;
  307. for (pEntry = (CTimedListEntry *)pList->Prev();
  308. pEntry != (CTimedListEntry *)pList->Head();
  309. pEntry = (CTimedListEntry *)pEntry->Prev()) {
  310. if (dwExpiryTime >= pEntry->ExpiryTime()) {
  311. break;
  312. }
  313. }
  314. InsertTail(pEntry);
  315. return this == pList->Next();
  316. }
  317. };
  318. //
  319. // CPrioritizedListEntry
  320. //
  321. class CPrioritizedListEntry : public CDoubleLinkedListEntry {
  322. private:
  323. LONG m_lPriority;
  324. public:
  325. CPrioritizedListEntry(LONG lPriority) {
  326. m_lPriority = lPriority;
  327. }
  328. LONG GetPriority(VOID) const {
  329. return m_lPriority;
  330. }
  331. VOID SetPriority(LONG lPriority) {
  332. m_lPriority = lPriority;
  333. }
  334. };
  335. //
  336. // CPrioritizedList
  337. //
  338. class CPrioritizedList : public CDoubleLinkedList {
  339. //
  340. // PERF: this really needs to be a btree of list anchors
  341. //
  342. public:
  343. VOID
  344. insert(
  345. IN CPrioritizedListEntry * pEntry,
  346. IN LONG lPriority
  347. ) {
  348. pEntry->SetPriority(lPriority);
  349. insert(pEntry);
  350. }
  351. VOID
  352. insert(
  353. IN CPrioritizedListEntry * pEntry
  354. ) {
  355. CPrioritizedListEntry * pCur;
  356. for (pCur = (CPrioritizedListEntry *)Next();
  357. pCur != (CPrioritizedListEntry *)Head();
  358. pCur = (CPrioritizedListEntry *)pCur->Next()) {
  359. if (pCur->GetPriority() < pEntry->GetPriority()) {
  360. break;
  361. }
  362. }
  363. pEntry->InsertHead((CDoubleLinkedListEntry *)pCur->Prev());
  364. }
  365. };