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.

399 lines
7.0 KiB

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