TimeoutHelper.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //-----------------------------------------------------------------------------
  4. namespace System.Runtime
  5. {
  6. using System;
  7. using System.Threading;
  8. struct TimeoutHelper
  9. {
  10. DateTime deadline;
  11. bool deadlineSet;
  12. TimeSpan originalTimeout;
  13. public static readonly TimeSpan MaxWait = TimeSpan.FromMilliseconds(Int32.MaxValue);
  14. public TimeoutHelper(TimeSpan timeout)
  15. {
  16. Fx.Assert(timeout >= TimeSpan.Zero, "timeout must be non-negative");
  17. this.originalTimeout = timeout;
  18. this.deadline = DateTime.MaxValue;
  19. this.deadlineSet = (timeout == TimeSpan.MaxValue);
  20. }
  21. public TimeSpan OriginalTimeout
  22. {
  23. get { return this.originalTimeout; }
  24. }
  25. public static bool IsTooLarge(TimeSpan timeout)
  26. {
  27. return (timeout > TimeoutHelper.MaxWait) && (timeout != TimeSpan.MaxValue);
  28. }
  29. public static TimeSpan FromMilliseconds(int milliseconds)
  30. {
  31. if (milliseconds == Timeout.Infinite)
  32. {
  33. return TimeSpan.MaxValue;
  34. }
  35. else
  36. {
  37. return TimeSpan.FromMilliseconds(milliseconds);
  38. }
  39. }
  40. public static int ToMilliseconds(TimeSpan timeout)
  41. {
  42. if (timeout == TimeSpan.MaxValue)
  43. {
  44. return Timeout.Infinite;
  45. }
  46. else
  47. {
  48. long ticks = Ticks.FromTimeSpan(timeout);
  49. if (ticks / TimeSpan.TicksPerMillisecond > int.MaxValue)
  50. {
  51. return int.MaxValue;
  52. }
  53. return Ticks.ToMilliseconds(ticks);
  54. }
  55. }
  56. public static TimeSpan Min(TimeSpan val1, TimeSpan val2)
  57. {
  58. if (val1 > val2)
  59. {
  60. return val2;
  61. }
  62. else
  63. {
  64. return val1;
  65. }
  66. }
  67. public static TimeSpan Add(TimeSpan timeout1, TimeSpan timeout2)
  68. {
  69. return Ticks.ToTimeSpan(Ticks.Add(Ticks.FromTimeSpan(timeout1), Ticks.FromTimeSpan(timeout2)));
  70. }
  71. public static DateTime Add(DateTime time, TimeSpan timeout)
  72. {
  73. if (timeout >= TimeSpan.Zero && DateTime.MaxValue - time <= timeout)
  74. {
  75. return DateTime.MaxValue;
  76. }
  77. if (timeout <= TimeSpan.Zero && DateTime.MinValue - time >= timeout)
  78. {
  79. return DateTime.MinValue;
  80. }
  81. return time + timeout;
  82. }
  83. public static DateTime Subtract(DateTime time, TimeSpan timeout)
  84. {
  85. return Add(time, TimeSpan.Zero - timeout);
  86. }
  87. public static TimeSpan Divide(TimeSpan timeout, int factor)
  88. {
  89. if (timeout == TimeSpan.MaxValue)
  90. {
  91. return TimeSpan.MaxValue;
  92. }
  93. return Ticks.ToTimeSpan((Ticks.FromTimeSpan(timeout) / factor) + 1);
  94. }
  95. public TimeSpan RemainingTime()
  96. {
  97. if (!this.deadlineSet)
  98. {
  99. this.SetDeadline();
  100. return this.originalTimeout;
  101. }
  102. else if (this.deadline == DateTime.MaxValue)
  103. {
  104. return TimeSpan.MaxValue;
  105. }
  106. else
  107. {
  108. TimeSpan remaining = this.deadline - DateTime.UtcNow;
  109. if (remaining <= TimeSpan.Zero)
  110. {
  111. return TimeSpan.Zero;
  112. }
  113. else
  114. {
  115. return remaining;
  116. }
  117. }
  118. }
  119. public TimeSpan ElapsedTime()
  120. {
  121. return this.originalTimeout - this.RemainingTime();
  122. }
  123. void SetDeadline()
  124. {
  125. Fx.Assert(!deadlineSet, "TimeoutHelper deadline set twice.");
  126. this.deadline = DateTime.UtcNow + this.originalTimeout;
  127. this.deadlineSet = true;
  128. }
  129. public static void ThrowIfNegativeArgument(TimeSpan timeout)
  130. {
  131. ThrowIfNegativeArgument(timeout, "timeout");
  132. }
  133. public static void ThrowIfNegativeArgument(TimeSpan timeout, string argumentName)
  134. {
  135. if (timeout < TimeSpan.Zero)
  136. {
  137. throw Fx.Exception.ArgumentOutOfRange(argumentName, timeout, InternalSR.TimeoutMustBeNonNegative(argumentName, timeout));
  138. }
  139. }
  140. public static void ThrowIfNonPositiveArgument(TimeSpan timeout)
  141. {
  142. ThrowIfNonPositiveArgument(timeout, "timeout");
  143. }
  144. public static void ThrowIfNonPositiveArgument(TimeSpan timeout, string argumentName)
  145. {
  146. if (timeout <= TimeSpan.Zero)
  147. {
  148. throw Fx.Exception.ArgumentOutOfRange(argumentName, timeout, InternalSR.TimeoutMustBePositive(argumentName, timeout));
  149. }
  150. }
  151. [Fx.Tag.Blocking]
  152. public static bool WaitOne(WaitHandle waitHandle, TimeSpan timeout)
  153. {
  154. ThrowIfNegativeArgument(timeout);
  155. if (timeout == TimeSpan.MaxValue)
  156. {
  157. waitHandle.WaitOne();
  158. return true;
  159. }
  160. else
  161. {
  162. return waitHandle.WaitOne(timeout, false);
  163. }
  164. }
  165. }
  166. }