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.

410 lines
7.4 KiB

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