1. /*
  2. * @(#)TimeUnit.java 1.6 04/02/09
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.util.concurrent;
  8. /**
  9. * A <tt>TimeUnit</tt> represents time durations at a given unit of
  10. * granularity and provides utility methods to convert across units,
  11. * and to perform timing and delay operations in these units. A
  12. * <tt>TimeUnit</tt> does not maintain time information, but only
  13. * helps organize and use time representations that may be maintained
  14. * separately across various contexts.
  15. *
  16. * <p>A <tt>TimeUnit</tt> is mainly used to inform time-based methods
  17. * how a given timing parameter should be interpreted. For example,
  18. * the following code will timeout in 50 milliseconds if the {@link
  19. * java.util.concurrent.locks.Lock lock} is not available:
  20. *
  21. * <pre> Lock lock = ...;
  22. * if ( lock.tryLock(50L, TimeUnit.MILLISECONDS) ) ...
  23. * </pre>
  24. * while this code will timeout in 50 seconds:
  25. * <pre>
  26. * Lock lock = ...;
  27. * if ( lock.tryLock(50L, TimeUnit.SECONDS) ) ...
  28. * </pre>
  29. *
  30. * Note however, that there is no guarantee that a particular timeout
  31. * implementation will be able to notice the passage of time at the
  32. * same granularity as the given <tt>TimeUnit</tt>.
  33. *
  34. * @since 1.5
  35. * @author Doug Lea
  36. */
  37. public enum TimeUnit {
  38. NANOSECONDS(0), MICROSECONDS(1), MILLISECONDS(2), SECONDS(3);
  39. /** the index of this unit */
  40. private final int index;
  41. /** Internal constructor */
  42. TimeUnit(int index) {
  43. this.index = index;
  44. }
  45. /** Lookup table for conversion factors */
  46. private static final int[] multipliers = {
  47. 1,
  48. 1000,
  49. 1000 * 1000,
  50. 1000 * 1000 * 1000
  51. };
  52. /**
  53. * Lookup table to check saturation. Note that because we are
  54. * dividing these down, we don't have to deal with asymmetry of
  55. * MIN/MAX values.
  56. */
  57. private static final long[] overflows = {
  58. 0, // unused
  59. Long.MAX_VALUE / 1000,
  60. Long.MAX_VALUE / (1000 * 1000),
  61. Long.MAX_VALUE / (1000 * 1000 * 1000)
  62. };
  63. /**
  64. * Perform conversion based on given delta representing the
  65. * difference between units
  66. * @param delta the difference in index values of source and target units
  67. * @param duration the duration
  68. * @return converted duration or saturated value
  69. */
  70. private static long doConvert(int delta, long duration) {
  71. if (delta == 0)
  72. return duration;
  73. if (delta < 0)
  74. return duration / multipliers[-delta];
  75. if (duration > overflows[delta])
  76. return Long.MAX_VALUE;
  77. if (duration < -overflows[delta])
  78. return Long.MIN_VALUE;
  79. return duration * multipliers[delta];
  80. }
  81. /**
  82. * Convert the given time duration in the given unit to this
  83. * unit. Conversions from finer to coarser granularities
  84. * truncate, so lose precision. For example converting
  85. * <tt>999</tt> milliseconds to seconds results in
  86. * <tt>0</tt>. Conversions from coarser to finer granularities
  87. * with arguments that would numerically overflow saturate to
  88. * <tt>Long.MIN_VALUE</tt> if negative or <tt>Long.MAX_VALUE</tt>
  89. * if positive.
  90. *
  91. * @param duration the time duration in the given <tt>unit</tt>
  92. * @param unit the unit of the <tt>duration</tt> argument
  93. * @return the converted duration in this unit,
  94. * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
  95. * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
  96. */
  97. public long convert(long duration, TimeUnit unit) {
  98. return doConvert(unit.index - index, duration);
  99. }
  100. /**
  101. * Equivalent to <tt>NANOSECONDS.convert(duration, this)</tt>.
  102. * @param duration the duration
  103. * @return the converted duration,
  104. * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
  105. * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
  106. * @see #convert
  107. */
  108. public long toNanos(long duration) {
  109. return doConvert(index, duration);
  110. }
  111. /**
  112. * Equivalent to <tt>MICROSECONDS.convert(duration, this)</tt>.
  113. * @param duration the duration
  114. * @return the converted duration,
  115. * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
  116. * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
  117. * @see #convert
  118. */
  119. public long toMicros(long duration) {
  120. return doConvert(index - MICROSECONDS.index, duration);
  121. }
  122. /**
  123. * Equivalent to <tt>MILLISECONDS.convert(duration, this)</tt>.
  124. * @param duration the duration
  125. * @return the converted duration,
  126. * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
  127. * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
  128. * @see #convert
  129. */
  130. public long toMillis(long duration) {
  131. return doConvert(index - MILLISECONDS.index, duration);
  132. }
  133. /**
  134. * Equivalent to <tt>SECONDS.convert(duration, this)</tt>.
  135. * @param duration the duration
  136. * @return the converted duration.
  137. * @see #convert
  138. */
  139. public long toSeconds(long duration) {
  140. return doConvert(index - SECONDS.index, duration);
  141. }
  142. /**
  143. * Utility method to compute the excess-nanosecond argument to
  144. * wait, sleep, join.
  145. */
  146. private int excessNanos(long time, long ms) {
  147. if (this == NANOSECONDS)
  148. return (int) (time - (ms * 1000 * 1000));
  149. if (this == MICROSECONDS)
  150. return (int) ((time * 1000) - (ms * 1000 * 1000));
  151. return 0;
  152. }
  153. /**
  154. * Perform a timed <tt>Object.wait</tt> using this time unit.
  155. * This is a convenience method that converts timeout arguments
  156. * into the form required by the <tt>Object.wait</tt> method.
  157. *
  158. * <p>For example, you could implement a blocking <tt>poll</tt>
  159. * method (see {@link BlockingQueue#poll BlockingQueue.poll})
  160. * using:
  161. *
  162. * <pre> public synchronized Object poll(long timeout, TimeUnit unit) throws InterruptedException {
  163. * while (empty) {
  164. * unit.timedWait(this, timeout);
  165. * ...
  166. * }
  167. * }</pre>
  168. *
  169. * @param obj the object to wait on
  170. * @param timeout the maximum time to wait.
  171. * @throws InterruptedException if interrupted while waiting.
  172. * @see Object#wait(long, int)
  173. */
  174. public void timedWait(Object obj, long timeout)
  175. throws InterruptedException {
  176. if (timeout > 0) {
  177. long ms = toMillis(timeout);
  178. int ns = excessNanos(timeout, ms);
  179. obj.wait(ms, ns);
  180. }
  181. }
  182. /**
  183. * Perform a timed <tt>Thread.join</tt> using this time unit.
  184. * This is a convenience method that converts time arguments into the
  185. * form required by the <tt>Thread.join</tt> method.
  186. * @param thread the thread to wait for
  187. * @param timeout the maximum time to wait
  188. * @throws InterruptedException if interrupted while waiting.
  189. * @see Thread#join(long, int)
  190. */
  191. public void timedJoin(Thread thread, long timeout)
  192. throws InterruptedException {
  193. if (timeout > 0) {
  194. long ms = toMillis(timeout);
  195. int ns = excessNanos(timeout, ms);
  196. thread.join(ms, ns);
  197. }
  198. }
  199. /**
  200. * Perform a <tt>Thread.sleep</tt> using this unit.
  201. * This is a convenience method that converts time arguments into the
  202. * form required by the <tt>Thread.sleep</tt> method.
  203. * @param timeout the minimum time to sleep
  204. * @throws InterruptedException if interrupted while sleeping.
  205. * @see Thread#sleep
  206. */
  207. public void sleep(long timeout) throws InterruptedException {
  208. if (timeout > 0) {
  209. long ms = toMillis(timeout);
  210. int ns = excessNanos(timeout, ms);
  211. Thread.sleep(ms, ns);
  212. }
  213. }
  214. }