1   /*
2    * %W% %E%
3    *
4    * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
5    * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6    */
7   
8   package java.util.concurrent;
9   
10  /**
11   * A <tt>TimeUnit</tt> represents time durations at a given unit of
12   * granularity and provides utility methods to convert across units,
13   * and to perform timing and delay operations in these units.  A
14   * <tt>TimeUnit</tt> does not maintain time information, but only
15   * helps organize and use time representations that may be maintained
16   * separately across various contexts.  A nanosecond is defined as one
17   * thousandth of a microsecond, a microsecond as one thousandth of a
18   * millisecond, a millisecond as one thousandth of a second, a minute
19   * as sixty seconds, an hour as sixty minutes, and a day as twenty four
20   * hours.
21   *
22   * <p>A <tt>TimeUnit</tt> is mainly used to inform time-based methods
23   * how a given timing parameter should be interpreted. For example,
24   * the following code will timeout in 50 milliseconds if the {@link
25   * java.util.concurrent.locks.Lock lock} is not available:
26   *
27   * <pre>  Lock lock = ...;
28   *  if ( lock.tryLock(50L, TimeUnit.MILLISECONDS) ) ...
29   * </pre>
30   * while this code will timeout in 50 seconds:
31   * <pre>
32   *  Lock lock = ...;
33   *  if ( lock.tryLock(50L, TimeUnit.SECONDS) ) ...
34   * </pre>
35   *
36   * Note however, that there is no guarantee that a particular timeout
37   * implementation will be able to notice the passage of time at the
38   * same granularity as the given <tt>TimeUnit</tt>.
39   *
40   * @since 1.5
41   * @author Doug Lea
42   */
43  public enum TimeUnit {
44      NANOSECONDS {
45          public long toNanos(long d)   { return d; }
46          public long toMicros(long d)  { return d/(C1/C0); }
47          public long toMillis(long d)  { return d/(C2/C0); }
48          public long toSeconds(long d) { return d/(C3/C0); }
49          public long toMinutes(long d) { return d/(C4/C0); }
50          public long toHours(long d)   { return d/(C5/C0); }
51          public long toDays(long d)    { return d/(C6/C0); }
52          public long convert(long d, TimeUnit u) { return u.toNanos(d); }
53          int excessNanos(long d, long m) { return (int)(d - (m*C2)); }
54      },
55      MICROSECONDS {
56          public long toNanos(long d)   { return x(d, C1/C0, MAX/(C1/C0)); }
57          public long toMicros(long d)  { return d; }
58          public long toMillis(long d)  { return d/(C2/C1); }
59          public long toSeconds(long d) { return d/(C3/C1); }
60          public long toMinutes(long d) { return d/(C4/C1); }
61          public long toHours(long d)   { return d/(C5/C1); }
62          public long toDays(long d)    { return d/(C6/C1); }
63          public long convert(long d, TimeUnit u) { return u.toMicros(d); }
64          int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); }
65      },
66      MILLISECONDS {
67          public long toNanos(long d)   { return x(d, C2/C0, MAX/(C2/C0)); }
68          public long toMicros(long d)  { return x(d, C2/C1, MAX/(C2/C1)); }
69          public long toMillis(long d)  { return d; }
70          public long toSeconds(long d) { return d/(C3/C2); }
71          public long toMinutes(long d) { return d/(C4/C2); }
72          public long toHours(long d)   { return d/(C5/C2); }
73          public long toDays(long d)    { return d/(C6/C2); }
74          public long convert(long d, TimeUnit u) { return u.toMillis(d); }
75          int excessNanos(long d, long m) { return 0; }
76      },
77      SECONDS {
78          public long toNanos(long d)   { return x(d, C3/C0, MAX/(C3/C0)); }
79          public long toMicros(long d)  { return x(d, C3/C1, MAX/(C3/C1)); }
80          public long toMillis(long d)  { return x(d, C3/C2, MAX/(C3/C2)); }
81          public long toSeconds(long d) { return d; }
82          public long toMinutes(long d) { return d/(C4/C3); }
83          public long toHours(long d)   { return d/(C5/C3); }
84          public long toDays(long d)    { return d/(C6/C3); }
85          public long convert(long d, TimeUnit u) { return u.toSeconds(d); }
86          int excessNanos(long d, long m) { return 0; }
87      },
88      MINUTES {
89          public long toNanos(long d)   { return x(d, C4/C0, MAX/(C4/C0)); }
90          public long toMicros(long d)  { return x(d, C4/C1, MAX/(C4/C1)); }
91          public long toMillis(long d)  { return x(d, C4/C2, MAX/(C4/C2)); }
92          public long toSeconds(long d) { return x(d, C4/C3, MAX/(C4/C3)); }
93          public long toMinutes(long d) { return d; }
94          public long toHours(long d)   { return d/(C5/C4); }
95          public long toDays(long d)    { return d/(C6/C4); }
96          public long convert(long d, TimeUnit u) { return u.toMinutes(d); }
97          int excessNanos(long d, long m) { return 0; }
98      },
99      HOURS {
100         public long toNanos(long d)   { return x(d, C5/C0, MAX/(C5/C0)); }
101         public long toMicros(long d)  { return x(d, C5/C1, MAX/(C5/C1)); }
102         public long toMillis(long d)  { return x(d, C5/C2, MAX/(C5/C2)); }
103         public long toSeconds(long d) { return x(d, C5/C3, MAX/(C5/C3)); }
104         public long toMinutes(long d) { return x(d, C5/C4, MAX/(C5/C4)); }
105         public long toHours(long d)   { return d; }
106         public long toDays(long d)    { return d/(C6/C5); }
107         public long convert(long d, TimeUnit u) { return u.toHours(d); }
108         int excessNanos(long d, long m) { return 0; }
109     },
110     DAYS {
111         public long toNanos(long d)   { return x(d, C6/C0, MAX/(C6/C0)); }
112         public long toMicros(long d)  { return x(d, C6/C1, MAX/(C6/C1)); }
113         public long toMillis(long d)  { return x(d, C6/C2, MAX/(C6/C2)); }
114         public long toSeconds(long d) { return x(d, C6/C3, MAX/(C6/C3)); }
115         public long toMinutes(long d) { return x(d, C6/C4, MAX/(C6/C4)); }
116         public long toHours(long d)   { return x(d, C6/C5, MAX/(C6/C5)); }
117         public long toDays(long d)    { return d; }
118         public long convert(long d, TimeUnit u) { return u.toDays(d); }
119         int excessNanos(long d, long m) { return 0; }
120     };
121 
122     // Handy constants for conversion methods
123     static final long C0 = 1L;
124     static final long C1 = C0 * 1000L;
125     static final long C2 = C1 * 1000L;
126     static final long C3 = C2 * 1000L;
127     static final long C4 = C3 * 60L;
128     static final long C5 = C4 * 60L;
129     static final long C6 = C5 * 24L;
130 
131     static final long MAX = Long.MAX_VALUE;
132 
133     /**
134      * Scale d by m, checking for overflow.
135      * This has a short name to make above code more readable.
136      */
137     static long x(long d, long m, long over) {
138         if (d >  over) return Long.MAX_VALUE;
139         if (d < -over) return Long.MIN_VALUE;
140         return d * m;
141     }
142 
143     // To maintain full signature compatibility with 1.5, and to improve the
144     // clarity of the generated javadoc (see 6287639: Abstract methods in
145     // enum classes should not be listed as abstract), method convert
146     // etc. are not declared abstract but otherwise act as abstract methods.
147 
148     /**
149      * Convert the given time duration in the given unit to this
150      * unit.  Conversions from finer to coarser granularities
151      * truncate, so lose precision. For example converting
152      * <tt>999</tt> milliseconds to seconds results in
153      * <tt>0</tt>. Conversions from coarser to finer granularities
154      * with arguments that would numerically overflow saturate to
155      * <tt>Long.MIN_VALUE</tt> if negative or <tt>Long.MAX_VALUE</tt>
156      * if positive.
157      *
158      * <p>For example, to convert 10 minutes to milliseconds, use:
159      * <tt>TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)</tt>
160      *
161      * @param sourceDuration the time duration in the given <tt>sourceUnit</tt>
162      * @param sourceUnit the unit of the <tt>sourceDuration</tt> argument
163      * @return the converted duration in this unit,
164      * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
165      * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
166      */
167     public long convert(long sourceDuration, TimeUnit sourceUnit) {
168         throw new AbstractMethodError();
169     }
170 
171     /**
172      * Equivalent to <tt>NANOSECONDS.convert(duration, this)</tt>.
173      * @param duration the duration
174      * @return the converted duration,
175      * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
176      * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
177      * @see #convert
178      */
179     public long toNanos(long duration) {
180         throw new AbstractMethodError();
181     }
182 
183     /**
184      * Equivalent to <tt>MICROSECONDS.convert(duration, this)</tt>.
185      * @param duration the duration
186      * @return the converted duration,
187      * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
188      * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
189      * @see #convert
190      */
191     public long toMicros(long duration) {
192         throw new AbstractMethodError();
193     }
194 
195     /**
196      * Equivalent to <tt>MILLISECONDS.convert(duration, this)</tt>.
197      * @param duration the duration
198      * @return the converted duration,
199      * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
200      * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
201      * @see #convert
202      */
203     public long toMillis(long duration) {
204         throw new AbstractMethodError();
205     }
206 
207     /**
208      * Equivalent to <tt>SECONDS.convert(duration, this)</tt>.
209      * @param duration the duration
210      * @return the converted duration,
211      * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
212      * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
213      * @see #convert
214      */
215     public long toSeconds(long duration) {
216         throw new AbstractMethodError();
217     }
218 
219     /**
220      * Equivalent to <tt>MINUTES.convert(duration, this)</tt>.
221      * @param duration the duration
222      * @return the converted duration,
223      * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
224      * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
225      * @see #convert
226      * @since 1.6
227      */
228     public long toMinutes(long duration) {
229         throw new AbstractMethodError();
230     }
231 
232     /**
233      * Equivalent to <tt>HOURS.convert(duration, this)</tt>.
234      * @param duration the duration
235      * @return the converted duration,
236      * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
237      * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
238      * @see #convert
239      * @since 1.6
240      */
241     public long toHours(long duration) {
242         throw new AbstractMethodError();
243     }
244 
245     /**
246      * Equivalent to <tt>DAYS.convert(duration, this)</tt>.
247      * @param duration the duration
248      * @return the converted duration
249      * @see #convert
250      * @since 1.6
251      */
252     public long toDays(long duration) {
253         throw new AbstractMethodError();
254     }
255 
256     /**
257      * Utility to compute the excess-nanosecond argument to wait,
258      * sleep, join.
259      * @param d the duration
260      * @param m the number of milliseconds
261      * @return the number of nanoseconds
262      */
263     abstract int excessNanos(long d, long m);
264 
265     /**
266      * Performs a timed <tt>Object.wait</tt> using this time unit.
267      * This is a convenience method that converts timeout arguments
268      * into the form required by the <tt>Object.wait</tt> method.
269      *
270      * <p>For example, you could implement a blocking <tt>poll</tt>
271      * method (see {@link BlockingQueue#poll BlockingQueue.poll})
272      * using:
273      *
274      * <pre>  public synchronized Object poll(long timeout, TimeUnit unit) throws InterruptedException {
275      *    while (empty) {
276      *      unit.timedWait(this, timeout);
277      *      ...
278      *    }
279      *  }</pre>
280      *
281      * @param obj the object to wait on
282      * @param timeout the maximum time to wait. If less than
283      * or equal to zero, do not wait at all.
284      * @throws InterruptedException if interrupted while waiting.
285      * @see Object#wait(long, int)
286      */
287     public void timedWait(Object obj, long timeout)
288     throws InterruptedException {
289         if (timeout > 0) {
290             long ms = toMillis(timeout);
291             int ns = excessNanos(timeout, ms);
292             obj.wait(ms, ns);
293         }
294     }
295 
296     /**
297      * Performs a timed <tt>Thread.join</tt> using this time unit.
298      * This is a convenience method that converts time arguments into the
299      * form required by the <tt>Thread.join</tt> method.
300      * @param thread the thread to wait for
301      * @param timeout the maximum time to wait. If less than
302      * or equal to zero, do not wait at all.
303      * @throws InterruptedException if interrupted while waiting.
304      * @see Thread#join(long, int)
305      */
306     public void timedJoin(Thread thread, long timeout)
307     throws InterruptedException {
308         if (timeout > 0) {
309             long ms = toMillis(timeout);
310             int ns = excessNanos(timeout, ms);
311             thread.join(ms, ns);
312         }
313     }
314 
315     /**
316      * Performs a <tt>Thread.sleep</tt> using this unit.
317      * This is a convenience method that converts time arguments into the
318      * form required by the <tt>Thread.sleep</tt> method.
319      * @param timeout the minimum time to sleep. If less than
320      * or equal to zero, do not sleep at all.
321      * @throws InterruptedException if interrupted while sleeping.
322      * @see Thread#sleep
323      */
324     public void sleep(long timeout) throws InterruptedException {
325         if (timeout > 0) {
326             long ms = toMillis(timeout);
327             int ns = excessNanos(timeout, ms);
328             Thread.sleep(ms, ns);
329         }
330     }
331 
332 }
333