1 /*
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3  *
4  * This code is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 2 only, as
6  * published by the Free Software Foundation.  Oracle designates this
7  * particular file as subject to the "Classpath" exception as provided
8  * by Oracle in the LICENSE file that accompanied this code.
9  *
10  * This code is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * version 2 for more details (a copy is included in the LICENSE file that
14  * accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License version
17  * 2 along with this work; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21  * or visit www.oracle.com if you need additional information or have any
22  * questions.
23  */
24 
25 /*
26  * This file is available under and governed by the GNU General Public
27  * License version 2 only, as published by the Free Software Foundation.
28  * However, the following notice accompanied the original version of this
29  * file:
30  *
31  * Written by Doug Lea with assistance from members of JCP JSR-166
32  * Expert Group and released to the public domain, as explained at
33  * http://creativecommons.org/publicdomain/zero/1.0/
34  */
35 
36 package java.util.concurrent;
37 
38 import java.util.Objects;
39 
40 /**
41  * A {@code TimeUnit} represents time durations at a given unit of
42  * granularity and provides utility methods to convert across units,
43  * and to perform timing and delay operations in these units.  A
44  * {@code TimeUnit} does not maintain time information, but only
45  * helps organize and use time representations that may be maintained
46  * separately across various contexts.  A nanosecond is defined as one
47  * thousandth of a microsecond, a microsecond as one thousandth of a
48  * millisecond, a millisecond as one thousandth of a second, a minute
49  * as sixty seconds, an hour as sixty minutes, and a day as twenty four
50  * hours.
51  *
52  * <p>A {@code TimeUnit} is mainly used to inform time-based methods
53  * how a given timing parameter should be interpreted. For example,
54  * the following code will timeout in 50 milliseconds if the {@link
55  * java.util.concurrent.locks.Lock lock} is not available:
56  *
57  * <pre> {@code
58  * Lock lock = ...;
59  * if (lock.tryLock(50L, TimeUnit.MILLISECONDS)) ...}</pre>
60  *
61  * while this code will timeout in 50 seconds:
62  * <pre> {@code
63  * Lock lock = ...;
64  * if (lock.tryLock(50L, TimeUnit.SECONDS)) ...}</pre>
65  *
66  * Note however, that there is no guarantee that a particular timeout
67  * implementation will be able to notice the passage of time at the
68  * same granularity as the given {@code TimeUnit}.
69  *
70  * @since 1.5
71  * @author Doug Lea
72  */
73 public enum TimeUnit {
74     /**
75      * Time unit representing one thousandth of a microsecond.
76      */
77     NANOSECONDS {
toNanos(long d)78         public long toNanos(long d)   { return d; }
toMicros(long d)79         public long toMicros(long d)  { return d/(C1/C0); }
toMillis(long d)80         public long toMillis(long d)  { return d/(C2/C0); }
toSeconds(long d)81         public long toSeconds(long d) { return d/(C3/C0); }
toMinutes(long d)82         public long toMinutes(long d) { return d/(C4/C0); }
toHours(long d)83         public long toHours(long d)   { return d/(C5/C0); }
toDays(long d)84         public long toDays(long d)    { return d/(C6/C0); }
convert(long d, TimeUnit u)85         public long convert(long d, TimeUnit u) { return u.toNanos(d); }
excessNanos(long d, long m)86         int excessNanos(long d, long m) { return (int)(d - (m*C2)); }
87     },
88 
89     /**
90      * Time unit representing one thousandth of a millisecond.
91      */
92     MICROSECONDS {
toNanos(long d)93         public long toNanos(long d)   { return x(d, C1/C0, MAX/(C1/C0)); }
toMicros(long d)94         public long toMicros(long d)  { return d; }
toMillis(long d)95         public long toMillis(long d)  { return d/(C2/C1); }
toSeconds(long d)96         public long toSeconds(long d) { return d/(C3/C1); }
toMinutes(long d)97         public long toMinutes(long d) { return d/(C4/C1); }
toHours(long d)98         public long toHours(long d)   { return d/(C5/C1); }
toDays(long d)99         public long toDays(long d)    { return d/(C6/C1); }
convert(long d, TimeUnit u)100         public long convert(long d, TimeUnit u) { return u.toMicros(d); }
excessNanos(long d, long m)101         int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); }
102     },
103 
104     /**
105      * Time unit representing one thousandth of a second.
106      */
107     MILLISECONDS {
toNanos(long d)108         public long toNanos(long d)   { return x(d, C2/C0, MAX/(C2/C0)); }
toMicros(long d)109         public long toMicros(long d)  { return x(d, C2/C1, MAX/(C2/C1)); }
toMillis(long d)110         public long toMillis(long d)  { return d; }
toSeconds(long d)111         public long toSeconds(long d) { return d/(C3/C2); }
toMinutes(long d)112         public long toMinutes(long d) { return d/(C4/C2); }
toHours(long d)113         public long toHours(long d)   { return d/(C5/C2); }
toDays(long d)114         public long toDays(long d)    { return d/(C6/C2); }
convert(long d, TimeUnit u)115         public long convert(long d, TimeUnit u) { return u.toMillis(d); }
excessNanos(long d, long m)116         int excessNanos(long d, long m) { return 0; }
117     },
118 
119     /**
120      * Time unit representing one second.
121      */
122     SECONDS {
toNanos(long d)123         public long toNanos(long d)   { return x(d, C3/C0, MAX/(C3/C0)); }
toMicros(long d)124         public long toMicros(long d)  { return x(d, C3/C1, MAX/(C3/C1)); }
toMillis(long d)125         public long toMillis(long d)  { return x(d, C3/C2, MAX/(C3/C2)); }
toSeconds(long d)126         public long toSeconds(long d) { return d; }
toMinutes(long d)127         public long toMinutes(long d) { return d/(C4/C3); }
toHours(long d)128         public long toHours(long d)   { return d/(C5/C3); }
toDays(long d)129         public long toDays(long d)    { return d/(C6/C3); }
convert(long d, TimeUnit u)130         public long convert(long d, TimeUnit u) { return u.toSeconds(d); }
excessNanos(long d, long m)131         int excessNanos(long d, long m) { return 0; }
132     },
133 
134     /**
135      * Time unit representing sixty seconds.
136      * @since 1.6
137      */
138     MINUTES {
toNanos(long d)139         public long toNanos(long d)   { return x(d, C4/C0, MAX/(C4/C0)); }
toMicros(long d)140         public long toMicros(long d)  { return x(d, C4/C1, MAX/(C4/C1)); }
toMillis(long d)141         public long toMillis(long d)  { return x(d, C4/C2, MAX/(C4/C2)); }
toSeconds(long d)142         public long toSeconds(long d) { return x(d, C4/C3, MAX/(C4/C3)); }
toMinutes(long d)143         public long toMinutes(long d) { return d; }
toHours(long d)144         public long toHours(long d)   { return d/(C5/C4); }
toDays(long d)145         public long toDays(long d)    { return d/(C6/C4); }
convert(long d, TimeUnit u)146         public long convert(long d, TimeUnit u) { return u.toMinutes(d); }
excessNanos(long d, long m)147         int excessNanos(long d, long m) { return 0; }
148     },
149 
150     /**
151      * Time unit representing sixty minutes.
152      * @since 1.6
153      */
154     HOURS {
toNanos(long d)155         public long toNanos(long d)   { return x(d, C5/C0, MAX/(C5/C0)); }
toMicros(long d)156         public long toMicros(long d)  { return x(d, C5/C1, MAX/(C5/C1)); }
toMillis(long d)157         public long toMillis(long d)  { return x(d, C5/C2, MAX/(C5/C2)); }
toSeconds(long d)158         public long toSeconds(long d) { return x(d, C5/C3, MAX/(C5/C3)); }
toMinutes(long d)159         public long toMinutes(long d) { return x(d, C5/C4, MAX/(C5/C4)); }
toHours(long d)160         public long toHours(long d)   { return d; }
toDays(long d)161         public long toDays(long d)    { return d/(C6/C5); }
convert(long d, TimeUnit u)162         public long convert(long d, TimeUnit u) { return u.toHours(d); }
excessNanos(long d, long m)163         int excessNanos(long d, long m) { return 0; }
164     },
165 
166     /**
167      * Time unit representing twenty four hours.
168      * @since 1.6
169      */
170     DAYS {
toNanos(long d)171         public long toNanos(long d)   { return x(d, C6/C0, MAX/(C6/C0)); }
toMicros(long d)172         public long toMicros(long d)  { return x(d, C6/C1, MAX/(C6/C1)); }
toMillis(long d)173         public long toMillis(long d)  { return x(d, C6/C2, MAX/(C6/C2)); }
toSeconds(long d)174         public long toSeconds(long d) { return x(d, C6/C3, MAX/(C6/C3)); }
toMinutes(long d)175         public long toMinutes(long d) { return x(d, C6/C4, MAX/(C6/C4)); }
toHours(long d)176         public long toHours(long d)   { return x(d, C6/C5, MAX/(C6/C5)); }
toDays(long d)177         public long toDays(long d)    { return d; }
convert(long d, TimeUnit u)178         public long convert(long d, TimeUnit u) { return u.toDays(d); }
excessNanos(long d, long m)179         int excessNanos(long d, long m) { return 0; }
180     };
181 
182     // Handy constants for conversion methods
183     static final long C0 = 1L;
184     static final long C1 = C0 * 1000L;
185     static final long C2 = C1 * 1000L;
186     static final long C3 = C2 * 1000L;
187     static final long C4 = C3 * 60L;
188     static final long C5 = C4 * 60L;
189     static final long C6 = C5 * 24L;
190 
191     static final long MAX = Long.MAX_VALUE;
192 
193     /**
194      * Scale d by m, checking for overflow.
195      * This has a short name to make above code more readable.
196      */
x(long d, long m, long over)197     static long x(long d, long m, long over) {
198         if (d > +over) return Long.MAX_VALUE;
199         if (d < -over) return Long.MIN_VALUE;
200         return d * m;
201     }
202 
203     // To maintain full signature compatibility with 1.5, and to improve the
204     // clarity of the generated javadoc (see 6287639: Abstract methods in
205     // enum classes should not be listed as abstract), method convert
206     // etc. are not declared abstract but otherwise act as abstract methods.
207 
208     /**
209      * Converts the given time duration in the given unit to this unit.
210      * Conversions from finer to coarser granularities truncate, so
211      * lose precision. For example, converting {@code 999} milliseconds
212      * to seconds results in {@code 0}. Conversions from coarser to
213      * finer granularities with arguments that would numerically
214      * overflow saturate to {@code Long.MIN_VALUE} if negative or
215      * {@code Long.MAX_VALUE} if positive.
216      *
217      * <p>For example, to convert 10 minutes to milliseconds, use:
218      * {@code TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)}
219      *
220      * @param sourceDuration the time duration in the given {@code sourceUnit}
221      * @param sourceUnit the unit of the {@code sourceDuration} argument
222      * @return the converted duration in this unit,
223      * or {@code Long.MIN_VALUE} if conversion would negatively
224      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
225      */
convert(long sourceDuration, TimeUnit sourceUnit)226     public long convert(long sourceDuration, TimeUnit sourceUnit) {
227         throw new AbstractMethodError();
228     }
229 
230     /**
231      * Equivalent to
232      * {@link #convert(long, TimeUnit) NANOSECONDS.convert(duration, this)}.
233      * @param duration the duration
234      * @return the converted duration,
235      * or {@code Long.MIN_VALUE} if conversion would negatively
236      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
237      */
toNanos(long duration)238     public long toNanos(long duration) {
239         throw new AbstractMethodError();
240     }
241 
242     /**
243      * Equivalent to
244      * {@link #convert(long, TimeUnit) MICROSECONDS.convert(duration, this)}.
245      * @param duration the duration
246      * @return the converted duration,
247      * or {@code Long.MIN_VALUE} if conversion would negatively
248      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
249      */
toMicros(long duration)250     public long toMicros(long duration) {
251         throw new AbstractMethodError();
252     }
253 
254     /**
255      * Equivalent to
256      * {@link #convert(long, TimeUnit) MILLISECONDS.convert(duration, this)}.
257      * @param duration the duration
258      * @return the converted duration,
259      * or {@code Long.MIN_VALUE} if conversion would negatively
260      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
261      */
toMillis(long duration)262     public long toMillis(long duration) {
263         throw new AbstractMethodError();
264     }
265 
266     /**
267      * Equivalent to
268      * {@link #convert(long, TimeUnit) SECONDS.convert(duration, this)}.
269      * @param duration the duration
270      * @return the converted duration,
271      * or {@code Long.MIN_VALUE} if conversion would negatively
272      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
273      */
toSeconds(long duration)274     public long toSeconds(long duration) {
275         throw new AbstractMethodError();
276     }
277 
278     /**
279      * Equivalent to
280      * {@link #convert(long, TimeUnit) MINUTES.convert(duration, this)}.
281      * @param duration the duration
282      * @return the converted duration,
283      * or {@code Long.MIN_VALUE} if conversion would negatively
284      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
285      * @since 1.6
286      */
toMinutes(long duration)287     public long toMinutes(long duration) {
288         throw new AbstractMethodError();
289     }
290 
291     /**
292      * Equivalent to
293      * {@link #convert(long, TimeUnit) HOURS.convert(duration, this)}.
294      * @param duration the duration
295      * @return the converted duration,
296      * or {@code Long.MIN_VALUE} if conversion would negatively
297      * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
298      * @since 1.6
299      */
toHours(long duration)300     public long toHours(long duration) {
301         throw new AbstractMethodError();
302     }
303 
304     /**
305      * Equivalent to
306      * {@link #convert(long, TimeUnit) DAYS.convert(duration, this)}.
307      * @param duration the duration
308      * @return the converted duration
309      * @since 1.6
310      */
toDays(long duration)311     public long toDays(long duration) {
312         throw new AbstractMethodError();
313     }
314 
315     /**
316      * Utility to compute the excess-nanosecond argument to wait,
317      * sleep, join.
318      * @param d the duration
319      * @param m the number of milliseconds
320      * @return the number of nanoseconds
321      */
excessNanos(long d, long m)322     abstract int excessNanos(long d, long m);
323 
324     /**
325      * Performs a timed {@link Object#wait(long, int) Object.wait}
326      * using this time unit.
327      * This is a convenience method that converts timeout arguments
328      * into the form required by the {@code Object.wait} method.
329      *
330      * <p>For example, you could implement a blocking {@code poll}
331      * method (see {@link BlockingQueue#poll BlockingQueue.poll})
332      * using:
333      *
334      * <pre> {@code
335      * public synchronized Object poll(long timeout, TimeUnit unit)
336      *     throws InterruptedException {
337      *   while (empty) {
338      *     unit.timedWait(this, timeout);
339      *     ...
340      *   }
341      * }}</pre>
342      *
343      * @param obj the object to wait on
344      * @param timeout the maximum time to wait. If less than
345      * or equal to zero, do not wait at all.
346      * @throws InterruptedException if interrupted while waiting
347      */
timedWait(Object obj, long timeout)348     public void timedWait(Object obj, long timeout)
349             throws InterruptedException {
350         if (timeout > 0) {
351             long ms = toMillis(timeout);
352             int ns = excessNanos(timeout, ms);
353             obj.wait(ms, ns);
354         }
355     }
356 
357     /**
358      * Performs a timed {@link Thread#join(long, int) Thread.join}
359      * using this time unit.
360      * This is a convenience method that converts time arguments into the
361      * form required by the {@code Thread.join} method.
362      *
363      * @param thread the thread to wait for
364      * @param timeout the maximum time to wait. If less than
365      * or equal to zero, do not wait at all.
366      * @throws InterruptedException if interrupted while waiting
367      */
timedJoin(Thread thread, long timeout)368     public void timedJoin(Thread thread, long timeout)
369             throws InterruptedException {
370         if (timeout > 0) {
371             long ms = toMillis(timeout);
372             int ns = excessNanos(timeout, ms);
373             thread.join(ms, ns);
374         }
375     }
376 
377     /**
378      * Performs a {@link Thread#sleep(long, int) Thread.sleep} using
379      * this time unit.
380      * This is a convenience method that converts time arguments into the
381      * form required by the {@code Thread.sleep} method.
382      *
383      * @param timeout the minimum time to sleep. If less than
384      * or equal to zero, do not sleep at all.
385      * @throws InterruptedException if interrupted while sleeping
386      */
sleep(long timeout)387     public void sleep(long timeout) throws InterruptedException {
388         if (timeout > 0) {
389             long ms = toMillis(timeout);
390             int ns = excessNanos(timeout, ms);
391             Thread.sleep(ms, ns);
392         }
393     }
394 
395     // BEGIN Android-removed: OpenJDK 9 ChronoUnit related code.
396     /*
397     /**
398      * Converts this {@code TimeUnit} to the equivalent {@code ChronoUnit}.
399      *
400      * @return the converted equivalent ChronoUnit
401      * @since 9
402      *
403     public ChronoUnit toChronoUnit() {
404         switch (this) {
405         case NANOSECONDS:  return ChronoUnit.NANOS;
406         case MICROSECONDS: return ChronoUnit.MICROS;
407         case MILLISECONDS: return ChronoUnit.MILLIS;
408         case SECONDS:      return ChronoUnit.SECONDS;
409         case MINUTES:      return ChronoUnit.MINUTES;
410         case HOURS:        return ChronoUnit.HOURS;
411         case DAYS:         return ChronoUnit.DAYS;
412         default: throw new AssertionError();
413         }
414     }
415 
416     /**
417      * Converts a {@code ChronoUnit} to the equivalent {@code TimeUnit}.
418      *
419      * @param chronoUnit the ChronoUnit to convert
420      * @return the converted equivalent TimeUnit
421      * @throws IllegalArgumentException if {@code chronoUnit} has no
422      *         equivalent TimeUnit
423      * @throws NullPointerException if {@code chronoUnit} is null
424      * @since 9
425      *
426     public static TimeUnit of(ChronoUnit chronoUnit) {
427         switch (Objects.requireNonNull(chronoUnit, "chronoUnit")) {
428         case NANOS:   return TimeUnit.NANOSECONDS;
429         case MICROS:  return TimeUnit.MICROSECONDS;
430         case MILLIS:  return TimeUnit.MILLISECONDS;
431         case SECONDS: return TimeUnit.SECONDS;
432         case MINUTES: return TimeUnit.MINUTES;
433         case HOURS:   return TimeUnit.HOURS;
434         case DAYS:    return TimeUnit.DAYS;
435         default:
436             throw new IllegalArgumentException(
437                 "No TimeUnit equivalent for " + chronoUnit);
438         }
439     }
440     */
441     // END Android-removed: OpenJDK 9 ChronoUnit related code.
442 
443 }
444