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.

402 lines
7.5 KiB

  1. /*++
  2. Copyright (c) 1999-2002 Microsoft Corporation
  3. Module Name :
  4. lstentry.h
  5. Abstract:
  6. Declares CListEntry and other intrusive singly- and doubly-linked lists
  7. Author:
  8. George V. Reilly (GeorgeRe) 02-Mar-1999
  9. Environment:
  10. Win32 - User Mode
  11. Project:
  12. Internet Information Server RunTime Library
  13. Revision History:
  14. --*/
  15. #ifndef __LSTENTRY_H__
  16. #define __LSTENTRY_H__
  17. #ifndef __LOCKS_H__
  18. # include <locks.h>
  19. #endif // !__LOCKS_H__
  20. // TODO:
  21. // * Add STL-style iterators: begin(), end(), operator++(), etc
  22. // * Templatize the lists, so that you can avoid the CONTAINING_RECORD goo
  23. //--------------------------------------------------------------------
  24. // CSingleListEntry: a node in a singly-linked list. Usually embedded
  25. // within larger structures.
  26. //--------------------------------------------------------------------
  27. class CSingleListEntry
  28. {
  29. public:
  30. CSingleListEntry* Next; // forward link
  31. };
  32. //--------------------------------------------------------------------
  33. // A non-threadsafe singly linked list
  34. //--------------------------------------------------------------------
  35. class IRTL_DLLEXP CSingleList
  36. {
  37. protected:
  38. CSingleListEntry m_sleHead; // external head node
  39. public:
  40. CSingleList()
  41. {
  42. m_sleHead.Next = NULL;
  43. }
  44. ~CSingleList()
  45. {
  46. IRTLASSERT(IsEmpty());
  47. }
  48. bool
  49. IsEmpty() const
  50. {
  51. return m_sleHead.Next == NULL;
  52. }
  53. CSingleListEntry* const
  54. Pop()
  55. {
  56. CSingleListEntry* psle = m_sleHead.Next;
  57. if (psle != NULL)
  58. m_sleHead.Next = psle->Next;
  59. return psle;
  60. }
  61. void
  62. Push(
  63. CSingleListEntry* const psle)
  64. {
  65. psle->Next = m_sleHead.Next;
  66. m_sleHead.Next = psle;
  67. }
  68. };
  69. //--------------------------------------------------------------------
  70. // A threadsafe singly linked list
  71. //--------------------------------------------------------------------
  72. class IRTL_DLLEXP CLockedSingleList
  73. {
  74. protected:
  75. CSpinLock m_lock;
  76. CSingleList m_list;
  77. public:
  78. #ifdef LOCK_INSTRUMENTATION
  79. CLockedSingleList()
  80. : m_lock(NULL)
  81. {}
  82. #endif // LOCK_INSTRUMENTATION
  83. void
  84. Lock()
  85. {
  86. m_lock.WriteLock();
  87. }
  88. void
  89. Unlock()
  90. {
  91. m_lock.WriteUnlock();
  92. }
  93. bool
  94. IsLocked() const
  95. {
  96. return m_lock.IsWriteLocked();
  97. }
  98. bool
  99. IsUnlocked() const
  100. {
  101. return m_lock.IsWriteUnlocked();
  102. }
  103. bool
  104. IsEmpty() const
  105. {
  106. return m_list.IsEmpty();
  107. }
  108. CSingleListEntry* const
  109. Pop()
  110. {
  111. Lock();
  112. CSingleListEntry* const psle = m_list.Pop();
  113. Unlock();
  114. return psle;
  115. }
  116. void
  117. Push(
  118. CSingleListEntry* const psle)
  119. {
  120. Lock();
  121. m_list.Push(psle);
  122. Unlock();
  123. }
  124. };
  125. //--------------------------------------------------------------------
  126. // CListEntry: a node in a circular doubly-linked list. Usually embedded
  127. // within larger structures.
  128. //--------------------------------------------------------------------
  129. class CListEntry
  130. {
  131. public:
  132. CListEntry* Flink; // forward link
  133. CListEntry* Blink; // backward link
  134. };
  135. //--------------------------------------------------------------------
  136. // A non-threadsafe circular doubly linked list
  137. //--------------------------------------------------------------------
  138. class IRTL_DLLEXP CDoubleList
  139. {
  140. protected:
  141. CListEntry m_leHead; // external head node
  142. public:
  143. CDoubleList()
  144. {
  145. m_leHead.Flink = m_leHead.Blink = &m_leHead;
  146. }
  147. ~CDoubleList()
  148. {
  149. IRTLASSERT(m_leHead.Flink != NULL && m_leHead.Blink != NULL);
  150. IRTLASSERT(IsEmpty());
  151. }
  152. bool
  153. IsEmpty() const
  154. {
  155. return m_leHead.Flink == &m_leHead;
  156. }
  157. void
  158. InsertHead(
  159. CListEntry* const ple)
  160. {
  161. ple->Blink = &m_leHead;
  162. ple->Flink = m_leHead.Flink;
  163. ple->Flink->Blink = ple;
  164. m_leHead.Flink = ple;
  165. }
  166. void
  167. InsertTail(
  168. CListEntry* const ple)
  169. {
  170. ple->Flink = &m_leHead;
  171. ple->Blink = m_leHead.Blink;
  172. ple->Blink->Flink = ple;
  173. m_leHead.Blink = ple;
  174. }
  175. const CListEntry* const
  176. HeadNode() const
  177. {
  178. return &m_leHead;
  179. }
  180. CListEntry* const
  181. First() const
  182. {
  183. return m_leHead.Flink;
  184. }
  185. CListEntry* const
  186. RemoveHead()
  187. {
  188. CListEntry* ple = First();
  189. RemoveEntry(ple);
  190. return ple;
  191. }
  192. CListEntry* const
  193. Last() const
  194. {
  195. return m_leHead.Blink;
  196. }
  197. CListEntry* const
  198. RemoveTail()
  199. {
  200. CListEntry* ple = Last();
  201. RemoveEntry(ple);
  202. return ple;
  203. }
  204. static void
  205. RemoveEntry(
  206. CListEntry* const ple)
  207. {
  208. CListEntry* const pleOldBlink = ple->Blink;
  209. IRTLASSERT(pleOldBlink != NULL);
  210. CListEntry* const pleOldFlink = ple->Flink;
  211. IRTLASSERT(pleOldFlink != NULL);
  212. pleOldBlink->Flink = pleOldFlink;
  213. pleOldFlink->Blink = pleOldBlink;
  214. }
  215. };
  216. //--------------------------------------------------------------------
  217. // A threadsafe circular doubly linked list
  218. //--------------------------------------------------------------------
  219. class IRTL_DLLEXP CLockedDoubleList
  220. {
  221. protected:
  222. CSpinLock m_lock;
  223. CDoubleList m_list;
  224. public:
  225. #ifdef LOCK_INSTRUMENTATION
  226. CLockedDoubleList()
  227. : m_lock(NULL)
  228. {}
  229. #endif // LOCK_INSTRUMENTATION
  230. void
  231. Lock()
  232. {
  233. m_lock.WriteLock();
  234. }
  235. void
  236. Unlock()
  237. {
  238. m_lock.WriteUnlock();
  239. }
  240. bool
  241. IsLocked() const
  242. {
  243. return m_lock.IsWriteLocked();
  244. }
  245. bool
  246. IsUnlocked() const
  247. {
  248. return m_lock.IsWriteUnlocked();
  249. }
  250. bool
  251. IsEmpty() const
  252. {
  253. return m_list.IsEmpty();
  254. }
  255. void
  256. InsertHead(
  257. CListEntry* const ple)
  258. {
  259. Lock();
  260. m_list.InsertHead(ple);
  261. Unlock();
  262. }
  263. void
  264. InsertTail(
  265. CListEntry* const ple)
  266. {
  267. Lock();
  268. m_list.InsertTail(ple);
  269. Unlock();
  270. }
  271. // not threadsafe
  272. const CListEntry* const
  273. HeadNode() const
  274. {
  275. return m_list.HeadNode();
  276. }
  277. // not threadsafe
  278. CListEntry* const
  279. First()
  280. {
  281. return m_list.First();
  282. }
  283. CListEntry* const
  284. RemoveHead()
  285. {
  286. Lock();
  287. CListEntry* const ple = m_list.RemoveHead();
  288. Unlock();
  289. return ple;
  290. }
  291. // not threadsafe
  292. CListEntry* const
  293. Last()
  294. {
  295. return m_list.Last();
  296. }
  297. CListEntry* const
  298. RemoveTail()
  299. {
  300. Lock();
  301. CListEntry* const ple = m_list.RemoveTail();
  302. Unlock();
  303. return ple;
  304. }
  305. void
  306. RemoveEntry(
  307. CListEntry* const ple)
  308. {
  309. Lock();
  310. m_list.RemoveEntry(ple);
  311. Unlock();
  312. }
  313. };
  314. #ifndef CONTAINING_RECORD
  315. //
  316. // Calculate the address of the base of the structure given its type, and an
  317. // address of a field within the structure.
  318. //
  319. #define CONTAINING_RECORD(address, type, field) \
  320. ((type *)((PCHAR)(address) - (ULONG_PTR)(&((type *)0)->field)))
  321. #endif // !CONTAINING_RECORD
  322. #endif // __LSTENTRY_H__