Queue.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. //
  2. // System.Collections.Queue
  3. //
  4. // Author:
  5. // Ricardo Fernández Pascual
  6. //
  7. // (C) 2001 Ricardo Fernández Pascual
  8. //
  9. using System;
  10. using System.Collections;
  11. namespace System.Collections {
  12. [Serializable]
  13. public class Queue : ICollection, IEnumerable, ICloneable {
  14. private object[] contents;
  15. private int head = 0; // points to the first used slot
  16. private int count = 0;
  17. private int capacity;
  18. private float growFactor;
  19. private int modCount = 0;
  20. public Queue () : this (32, 2.0F) {}
  21. public Queue (int initialCapacity) : this (initialCapacity, 2.0F) {}
  22. public Queue(ICollection col) : this (col == null ? 32 : col.Count)
  23. {
  24. if (col == null)
  25. throw new ArgumentNullException ("col");
  26. count = capacity;
  27. col.CopyTo (contents, 0);
  28. }
  29. public Queue (int initialCapacity, float growFactor) {
  30. if (initialCapacity < 0)
  31. throw new ArgumentOutOfRangeException("capacity", "Needs a non-negative number");
  32. if (!(growFactor >= 1.0F && growFactor <= 10.0F))
  33. throw new ArgumentOutOfRangeException("growFactor", "Queue growth factor must be between 1.0 and 10.0, inclusive");
  34. capacity = initialCapacity;
  35. contents = new object[capacity];
  36. this.growFactor = growFactor;
  37. }
  38. // from ICollection
  39. public virtual int Count {
  40. get { return count; }
  41. }
  42. public virtual bool IsSynchronized {
  43. get { return false; }
  44. }
  45. public virtual object SyncRoot {
  46. get { return this; }
  47. }
  48. public virtual void CopyTo (Array array, int index)
  49. {
  50. if (array == null)
  51. throw new ArgumentNullException ("array");
  52. if (index < 0)
  53. throw new ArgumentOutOfRangeException ("index");
  54. if (array.Rank > 1
  55. || (index != 0 && index >= array.Length)
  56. || count > array.Length - index)
  57. throw new ArgumentException ();
  58. int contents_length = contents.Length;
  59. int length_from_head = contents_length - head;
  60. // copy the contents of the circular array
  61. Array.Copy (contents, head, array, index,
  62. Math.Min (count, length_from_head));
  63. if (count > length_from_head)
  64. Array.Copy (contents, 0, array,
  65. index + length_from_head,
  66. count - length_from_head);
  67. }
  68. // from IEnumerable
  69. public virtual IEnumerator GetEnumerator () {
  70. return new QueueEnumerator (this);
  71. }
  72. // from ICloneable
  73. public virtual object Clone () {
  74. Queue newQueue;
  75. newQueue = new Queue (); // FIXME: improve this...
  76. newQueue.contents = new object[this.contents.Length];
  77. Array.Copy (this.contents, 0, newQueue.contents, 0,
  78. this.contents.Length);
  79. newQueue.head = this.head;
  80. newQueue.count = this.count;
  81. newQueue.capacity = this.capacity;
  82. newQueue.growFactor = this.growFactor;
  83. return newQueue;
  84. }
  85. // FIXME: should override Equals?
  86. // from Queue spec
  87. /*
  88. public virtual bool IsReadOnly {
  89. get { return false; }
  90. }
  91. */
  92. public virtual void Clear () {
  93. modCount++;
  94. head = 0;
  95. count = 0;
  96. // FIXME: Should allocate a new contents array?
  97. // Should null the current array?
  98. }
  99. public virtual bool Contains (object obj) {
  100. int tail = head + count;
  101. if (obj == null) {
  102. for (int i = head; i < tail; i++) {
  103. if (contents[i % capacity] == null)
  104. return true;
  105. }
  106. } else {
  107. for (int i = head; i < tail; i++) {
  108. if (obj.Equals (contents[i % capacity]))
  109. return true;
  110. }
  111. }
  112. return false;
  113. }
  114. public virtual object Dequeue ()
  115. {
  116. modCount++;
  117. if (count < 1)
  118. throw new InvalidOperationException ();
  119. object result = contents[head];
  120. contents [head] = null;
  121. head = (head + 1) % capacity;
  122. count--;
  123. return result;
  124. }
  125. public virtual void Enqueue (object obj) {
  126. modCount++;
  127. if (count == capacity)
  128. grow ();
  129. contents[(head + count) % capacity] = obj;
  130. count++;
  131. }
  132. public virtual object Peek () {
  133. if (count < 1)
  134. throw new InvalidOperationException ();
  135. return contents[head];
  136. }
  137. public static Queue Synchronized (Queue queue) {
  138. if (queue == null) {
  139. throw new ArgumentNullException ();
  140. }
  141. return new SyncQueue (queue);
  142. }
  143. public virtual object[] ToArray () {
  144. object[] ret = new object[count];
  145. CopyTo (ret, 0);
  146. return ret;
  147. }
  148. public virtual void TrimToSize() {
  149. object[] trimmed = new object [count];
  150. CopyTo (trimmed, 0);
  151. contents = trimmed;
  152. }
  153. // private methods
  154. private void grow () {
  155. int newCapacity = (int) Math.Ceiling
  156. (contents.Length * growFactor);
  157. object[] newContents = new object[newCapacity];
  158. CopyTo (newContents, 0);
  159. contents = newContents;
  160. capacity = newCapacity;
  161. head = 0;
  162. }
  163. // private classes
  164. private class SyncQueue : Queue {
  165. Queue queue;
  166. internal SyncQueue (Queue queue) {
  167. this.queue = queue;
  168. }
  169. public override int Count {
  170. get {
  171. lock (queue) {
  172. return queue.count;
  173. }
  174. }
  175. }
  176. public override bool IsSynchronized {
  177. get {
  178. return true;
  179. }
  180. }
  181. public override object SyncRoot {
  182. get {
  183. return queue.SyncRoot;
  184. }
  185. }
  186. public override void CopyTo (Array array, int index) {
  187. lock (queue) {
  188. queue.CopyTo (array, index);
  189. }
  190. }
  191. public override IEnumerator GetEnumerator () {
  192. lock (queue) {
  193. return queue.GetEnumerator ();
  194. }
  195. }
  196. public override object Clone () {
  197. lock (queue) {
  198. return queue.Clone ();
  199. }
  200. }
  201. /*
  202. public override bool IsReadOnly {
  203. get {
  204. lock (queue) {
  205. return queue.IsReadOnly;
  206. }
  207. }
  208. }
  209. */
  210. public override void Clear () {
  211. lock (queue) {
  212. queue.Clear ();
  213. }
  214. }
  215. public override bool Contains (object obj) {
  216. lock (queue) {
  217. return queue.Contains (obj);
  218. }
  219. }
  220. public override object Dequeue () {
  221. lock (queue) {
  222. return queue.Dequeue ();
  223. }
  224. }
  225. public override void Enqueue (object obj) {
  226. lock (queue) {
  227. queue.Enqueue (obj);
  228. }
  229. }
  230. public override object Peek () {
  231. lock (queue) {
  232. return queue.Peek ();
  233. }
  234. }
  235. public override object[] ToArray () {
  236. lock (queue) {
  237. return queue.ToArray ();
  238. }
  239. }
  240. }
  241. [Serializable]
  242. private class QueueEnumerator : IEnumerator, ICloneable {
  243. Queue queue;
  244. private int modCount;
  245. private int current;
  246. internal QueueEnumerator (Queue q) {
  247. queue = q;
  248. modCount = q.modCount;
  249. current = -1; // one element before the head
  250. }
  251. public object Clone ()
  252. {
  253. QueueEnumerator q = new QueueEnumerator (queue);
  254. q.modCount = modCount;
  255. q.current = current;
  256. return q;
  257. }
  258. public virtual object Current {
  259. get {
  260. if (modCount != queue.modCount
  261. || current < 0
  262. || current >= queue.count)
  263. throw new InvalidOperationException ();
  264. return queue.contents[(queue.head + current) % queue.contents.Length];
  265. }
  266. }
  267. public virtual bool MoveNext () {
  268. if (modCount != queue.modCount) {
  269. throw new InvalidOperationException ();
  270. }
  271. if (current >= queue.count - 1) {
  272. return false;
  273. } else {
  274. current++;
  275. return true;
  276. }
  277. }
  278. public virtual void Reset () {
  279. if (modCount != queue.modCount) {
  280. throw new InvalidOperationException();
  281. }
  282. current = -1;
  283. }
  284. }
  285. }
  286. }