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.

358 lines
7.5 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1992 - 1999
  6. //
  7. // File: queue.cxx
  8. //
  9. //--------------------------------------------------------------------------
  10. /*++
  11. --*/
  12. #include <precomp.hxx>
  13. #include <queue.hxx>
  14. QUEUE::QUEUE (
  15. )
  16. /*++
  17. Routine Description:
  18. We will construct an empty queue.
  19. --*/
  20. {
  21. ALLOCATE_THIS(QUEUE);
  22. QueueSlots = InitialQueueSlots;
  23. NumberOfQueueSlots = INITIALQUEUESLOTS;
  24. EndOfQueue = 0;
  25. }
  26. QUEUE::~QUEUE (
  27. )
  28. /*++
  29. Routine Desciption:
  30. We need to free up the queue slots if they have expanded beyond
  31. the initial ones.
  32. --*/
  33. {
  34. if (QueueSlots != InitialQueueSlots)
  35. delete QueueSlots;
  36. }
  37. int
  38. QUEUE::PutOnQueue (
  39. IN void * Item,
  40. IN unsigned int Length
  41. )
  42. /*++
  43. Routine Description:
  44. The item will be placed on the tail of the queue.
  45. Arguments:
  46. Item - Supplies the item to be placed on the queue.
  47. Length - Supplies the length of the item.
  48. Return Value:
  49. Zero will be returned if everything completes successfully; otherwise,
  50. non-zero will be returned indicating an out of memory error.
  51. --*/
  52. {
  53. QUEUE_ITEM * NewQueueSlots;
  54. int Count;
  55. if (EndOfQueue == NumberOfQueueSlots)
  56. {
  57. NewQueueSlots = (QUEUE_ITEM *) new char[
  58. sizeof(QUEUE_ITEM) * NumberOfQueueSlots * 2];
  59. if (NewQueueSlots == 0)
  60. return(1);
  61. memcpy(NewQueueSlots, QueueSlots,
  62. sizeof(QUEUE_ITEM) * NumberOfQueueSlots);
  63. if (QueueSlots != InitialQueueSlots)
  64. delete QueueSlots;
  65. QueueSlots = NewQueueSlots;
  66. NumberOfQueueSlots *= 2;
  67. }
  68. for (Count = EndOfQueue; Count > 0; Count--)
  69. {
  70. ASSERT(QueueSlots[Count-1].Buffer != Item);
  71. QueueSlots[Count] = QueueSlots[Count - 1];
  72. }
  73. EndOfQueue += 1;
  74. QueueSlots[0].Buffer = Item;
  75. QueueSlots[0].BufferLength = Length;
  76. return(0);
  77. }
  78. int
  79. QUEUE::PutOnFrontOfQueue (
  80. IN void * Item,
  81. IN unsigned int Length
  82. )
  83. /*++
  84. Routine Description:
  85. The item will be placed on the front of the queue.
  86. Arguments:
  87. Item - Supplies the item to be placed on the queue.
  88. Length - Supplies the length of the item.
  89. Return Value:
  90. Zero will be returned if everything completes successfully; otherwise,
  91. non-zero will be returned indicating an out of memory error.
  92. --*/
  93. {
  94. QUEUE_ITEM * NewQueueSlots;
  95. int Count;
  96. if (EndOfQueue == NumberOfQueueSlots)
  97. {
  98. NewQueueSlots = (QUEUE_ITEM *) new char[
  99. sizeof(QUEUE_ITEM) * NumberOfQueueSlots * 2];
  100. if (NewQueueSlots == 0)
  101. return(1);
  102. memcpy(NewQueueSlots, QueueSlots,
  103. sizeof(QUEUE_ITEM) * NumberOfQueueSlots);
  104. if (QueueSlots != InitialQueueSlots)
  105. delete QueueSlots;
  106. QueueSlots = NewQueueSlots;
  107. NumberOfQueueSlots *= 2;
  108. }
  109. QueueSlots[EndOfQueue].Buffer = Item;
  110. QueueSlots[EndOfQueue].BufferLength = Length;
  111. EndOfQueue += 1;
  112. return(0);
  113. }
  114. void *
  115. QUEUE::TakeOffQueue (
  116. OUT unsigned int * Length
  117. )
  118. /*++
  119. Routine Description:
  120. This routine will remove an item from the front of the queue and
  121. return it.
  122. Arguments:
  123. Length - Returns the length of the item in the queue.
  124. Return Value:
  125. If the queue is not empty, the last item in the queue will be
  126. returned; otherwise, zero will be returned.
  127. --*/
  128. {
  129. if (EndOfQueue == 0)
  130. return(0);
  131. EndOfQueue -= 1;
  132. *Length = QueueSlots[EndOfQueue].BufferLength;
  133. return(QueueSlots[EndOfQueue].Buffer);
  134. }
  135. void *
  136. QUEUE::TakeOffEndOfQueue (
  137. OUT unsigned int * Length
  138. )
  139. /*++
  140. Routine Description:
  141. This routine will remove an item from the tail of the queue and
  142. return it.
  143. Arguments:
  144. Length - Returns the length of the item in the queue.
  145. Return Value:
  146. If the queue is not empty, the last item in the queue will be
  147. returned; otherwise, zero will be returned.
  148. --*/
  149. {
  150. void *Buffer;
  151. int Count;
  152. if (EndOfQueue == 0)
  153. return(0);
  154. *Length = QueueSlots[0].BufferLength;
  155. Buffer = QueueSlots[0].Buffer;
  156. EndOfQueue -= 1;
  157. for (Count = 0; Count < EndOfQueue; Count++)
  158. {
  159. QueueSlots[Count] = QueueSlots[Count + 1];
  160. }
  161. return(Buffer);
  162. }
  163. int
  164. QUEUE::FindAndTakeOffQueue (
  165. IN void * Item
  166. )
  167. /*++
  168. Routine Description:
  169. Searches for a given element on the queue and removes it from the queue
  170. if found.
  171. Arguments:
  172. Return Value:
  173. 1 - If the element was found and removed.
  174. 0 - Otherwise.
  175. --*/
  176. {
  177. int Count;
  178. int fFound = 0;
  179. if (IsQueueEmpty())
  180. {
  181. return 0;
  182. }
  183. for (Count = 0; Count < EndOfQueue; Count++)
  184. {
  185. if (QueueSlots[Count].Buffer == Item)
  186. {
  187. fFound = 1;
  188. EndOfQueue -= 1;
  189. }
  190. if (fFound && Count < EndOfQueue)
  191. {
  192. QueueSlots[Count] = QueueSlots[Count + 1];
  193. }
  194. }
  195. return fFound;
  196. }
  197. int
  198. QUEUE::MergeWithQueue (
  199. IN QUEUE *pQueue
  200. )
  201. /*++
  202. Routine Description:
  203. Takes the contents of the second queue and merges it into the first queue. Does not check for
  204. duplicates. Does not implement transactional semantics - i.e. if merging fails halfway due to lack
  205. of memory, the operation is aborted, and the amount of elements that were transferred remain in
  206. the this queue. Appropriate synchronization must be taken care for by the caller.
  207. Arguments:
  208. pQueue - the queue that we want to merge from.
  209. Return Value:
  210. 0 - success
  211. !0 - failure - out of memory
  212. --*/
  213. {
  214. unsigned int nLength;
  215. void *pQueueElement;
  216. while (1)
  217. {
  218. pQueueElement = pQueue->TakeOffQueue(&nLength);
  219. if (pQueueElement == 0)
  220. break;
  221. if (PutOnQueue(pQueueElement, nLength) != 0)
  222. {
  223. // guaranteed to succeed since we never decrease buffers
  224. pQueue->PutOnFrontOfQueue(pQueueElement, nLength);
  225. return 1;
  226. }
  227. }
  228. return 0;
  229. }
  230. int
  231. QUEUE::MergeWithQueueInFront (
  232. IN QUEUE *SourceQueue
  233. )
  234. /*++
  235. Routine Description:
  236. Takes the contents of the second queue and merges it into the front of first queue. Does not check for
  237. duplicates. Does not implement transactional semantics - i.e. if merging fails halfway due to lack
  238. of memory, the operation is aborted, and the amount of elements that were transferred remain in
  239. the this queue. Appropriate synchronization must be taken care for by the caller.
  240. Arguments:
  241. SourceQueue - the queue that we want to merge from.
  242. Return Value:
  243. 0 - success
  244. !0 - failure - out of memory
  245. --*/
  246. {
  247. unsigned int nLength;
  248. void *pQueueElement;
  249. while (1)
  250. {
  251. pQueueElement = SourceQueue->TakeOffEndOfQueue(&nLength);
  252. if (pQueueElement == 0)
  253. break;
  254. if (PutOnFrontOfQueue(pQueueElement, nLength) != 0)
  255. {
  256. // guaranteed to succeed since we never decrease buffers
  257. SourceQueue->PutOnFrontOfQueue(pQueueElement, nLength);
  258. return 1;
  259. }
  260. }
  261. return 0;
  262. }