MinimumQueue.cs 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
  2. using System;
  3. using System.Runtime.CompilerServices;
  4. namespace Cysharp.Threading.Tasks.Internal
  5. {
  6. // optimized version of Standard Queue<T>.
  7. internal class MinimumQueue<T>
  8. {
  9. const int MinimumGrow = 4;
  10. const int GrowFactor = 200;
  11. T[] array;
  12. int head;
  13. int tail;
  14. int size;
  15. public MinimumQueue(int capacity)
  16. {
  17. if (capacity < 0) throw new ArgumentOutOfRangeException("capacity");
  18. array = new T[capacity];
  19. head = tail = size = 0;
  20. }
  21. public int Count
  22. {
  23. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  24. get { return size; }
  25. }
  26. public T Peek()
  27. {
  28. if (size == 0) ThrowForEmptyQueue();
  29. return array[head];
  30. }
  31. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  32. public void Enqueue(T item)
  33. {
  34. if (size == array.Length)
  35. {
  36. Grow();
  37. }
  38. array[tail] = item;
  39. MoveNext(ref tail);
  40. size++;
  41. }
  42. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  43. public T Dequeue()
  44. {
  45. if (size == 0) ThrowForEmptyQueue();
  46. int head = this.head;
  47. T[] array = this.array;
  48. T removed = array[head];
  49. array[head] = default(T);
  50. MoveNext(ref this.head);
  51. size--;
  52. return removed;
  53. }
  54. void Grow()
  55. {
  56. int newcapacity = (int)((long)array.Length * (long)GrowFactor / 100);
  57. if (newcapacity < array.Length + MinimumGrow)
  58. {
  59. newcapacity = array.Length + MinimumGrow;
  60. }
  61. SetCapacity(newcapacity);
  62. }
  63. void SetCapacity(int capacity)
  64. {
  65. T[] newarray = new T[capacity];
  66. if (size > 0)
  67. {
  68. if (head < tail)
  69. {
  70. Array.Copy(array, head, newarray, 0, size);
  71. }
  72. else
  73. {
  74. Array.Copy(array, head, newarray, 0, array.Length - head);
  75. Array.Copy(array, 0, newarray, array.Length - head, tail);
  76. }
  77. }
  78. array = newarray;
  79. head = 0;
  80. tail = (size == capacity) ? 0 : size;
  81. }
  82. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  83. void MoveNext(ref int index)
  84. {
  85. int tmp = index + 1;
  86. if (tmp == array.Length)
  87. {
  88. tmp = 0;
  89. }
  90. index = tmp;
  91. }
  92. void ThrowForEmptyQueue()
  93. {
  94. throw new InvalidOperationException("EmptyQueue");
  95. }
  96. }
  97. }