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.time.Duration;
39 import java.time.temporal.ChronoUnit;
40 import java.util.Objects;
41
42 /**
43  * A {@code TimeUnit} represents time durations at a given unit of
44  * granularity and provides utility methods to convert across units,
45  * and to perform timing and delay operations in these units.  A
46  * {@code TimeUnit} does not maintain time information, but only
47  * helps organize and use time representations that may be maintained
48  * separately across various contexts.  A nanosecond is defined as one
49  * thousandth of a microsecond, a microsecond as one thousandth of a
50  * millisecond, a millisecond as one thousandth of a second, a minute
51  * as sixty seconds, an hour as sixty minutes, and a day as twenty four
52  * hours.
53  *
54  * <p>A {@code TimeUnit} is mainly used to inform time-based methods
55  * how a given timing parameter should be interpreted. For example,
56  * the following code will timeout in 50 milliseconds if the {@link
57  * java.util.concurrent.locks.Lock lock} is not available:
58  *
59  * <pre> {@code
60  * Lock lock = ...;
61  * if (lock.tryLock(50L, TimeUnit.MILLISECONDS)) ...}</pre>
62  *
63  * while this code will timeout in 50 seconds:
64  * <pre> {@code
65  * Lock lock = ...;
66  * if (lock.tryLock(50L, TimeUnit.SECONDS)) ...}</pre>
67  *
68  * Note however, that there is no guarantee that a particular timeout
69  * implementation will be able to notice the passage of time at the
70  * same granularity as the given {@code TimeUnit}.
71  *
72  * @since 1.5
73  * @author Doug Lea
74  */

75 public enum TimeUnit {
76     /**
77      * Time unit representing one thousandth of a microsecond.
78      */

79     NANOSECONDS(TimeUnit.NANO_SCALE),
80     /**
81      * Time unit representing one thousandth of a millisecond.
82      */

83     MICROSECONDS(TimeUnit.MICRO_SCALE),
84     /**
85      * Time unit representing one thousandth of a second.
86      */

87     MILLISECONDS(TimeUnit.MILLI_SCALE),
88     /**
89      * Time unit representing one second.
90      */

91     SECONDS(TimeUnit.SECOND_SCALE),
92     /**
93      * Time unit representing sixty seconds.
94      * @since 1.6
95      */

96     MINUTES(TimeUnit.MINUTE_SCALE),
97     /**
98      * Time unit representing sixty minutes.
99      * @since 1.6
100      */

101     HOURS(TimeUnit.HOUR_SCALE),
102     /**
103      * Time unit representing twenty four hours.
104      * @since 1.6
105      */

106     DAYS(TimeUnit.DAY_SCALE);
107
108     // Scales as constants
109     private static final long NANO_SCALE   = 1L;
110     private static final long MICRO_SCALE  = 1000L * NANO_SCALE;
111     private static final long MILLI_SCALE  = 1000L * MICRO_SCALE;
112     private static final long SECOND_SCALE = 1000L * MILLI_SCALE;
113     private static final long MINUTE_SCALE = 60L * SECOND_SCALE;
114     private static final long HOUR_SCALE   = 60L * MINUTE_SCALE;
115     private static final long DAY_SCALE    = 24L * HOUR_SCALE;
116
117     /*
118      * Instances cache conversion ratios and saturation cutoffs for
119      * the units up through SECONDS. Other cases compute them, in
120      * method cvt.
121      */

122
123     private final long scale;
124     private final long maxNanos;
125     private final long maxMicros;
126     private final long maxMillis;
127     private final long maxSecs;
128     private final long microRatio;
129     private final int milliRatio;   // fits in 32 bits
130     private final int secRatio;     // fits in 32 bits
131
132     private TimeUnit(long s) {
133         this.scale = s;
134         this.maxNanos = Long.MAX_VALUE / s;
135         long ur = (s >= MICRO_SCALE) ? (s / MICRO_SCALE) : (MICRO_SCALE / s);
136         this.microRatio = ur;
137         this.maxMicros = Long.MAX_VALUE / ur;
138         long mr = (s >= MILLI_SCALE) ? (s / MILLI_SCALE) : (MILLI_SCALE / s);
139         this.milliRatio = (int)mr;
140         this.maxMillis = Long.MAX_VALUE / mr;
141         long sr = (s >= SECOND_SCALE) ? (s / SECOND_SCALE) : (SECOND_SCALE / s);
142         this.secRatio = (int)sr;
143         this.maxSecs = Long.MAX_VALUE / sr;
144     }
145
146     /**
147      * General conversion utility.
148      *
149      * @param d duration
150      * @param dst result unit scale
151      * @param src source unit scale
152      */

153     private static long cvt(long d, long dst, long src) {
154         long r, m;
155         if (src == dst)
156             return d;
157         else if (src < dst)
158             return d / (dst / src);
159         else if (d > (m = Long.MAX_VALUE / (r = src / dst)))
160             return Long.MAX_VALUE;
161         else if (d < -m)
162             return Long.MIN_VALUE;
163         else
164             return d * r;
165     }
166
167     /**
168      * Converts the given time duration in the given unit to this unit.
169      * Conversions from finer to coarser granularities truncate, so
170      * lose precision. For example, converting {@code 999} milliseconds
171      * to seconds results in {@code 0}. Conversions from coarser to
172      * finer granularities with arguments that would numerically
173      * overflow saturate to {@code Long.MIN_VALUE} if negative or
174      * {@code Long.MAX_VALUE} if positive.
175      *
176      * <p>For example, to convert 10 minutes to milliseconds, use:
177      * {@code TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)}
178      *
179      * @param sourceDuration the time duration in the given {@code sourceUnit}
180      * @param sourceUnit the unit of the {@code sourceDuration} argument
181      * @return the converted duration in this unit,
182      * or {@code Long.MIN_VALUE} if conversion would negatively overflow,
183      * or {@code Long.MAX_VALUE} if it would positively overflow.
184      */

185     public long convert(long sourceDuration, TimeUnit sourceUnit) {
186         switch (this) {
187         case NANOSECONDS:  return sourceUnit.toNanos(sourceDuration);
188         case MICROSECONDS: return sourceUnit.toMicros(sourceDuration);
189         case MILLISECONDS: return sourceUnit.toMillis(sourceDuration);
190         case SECONDS:      return sourceUnit.toSeconds(sourceDuration);
191         defaultreturn cvt(sourceDuration, scale, sourceUnit.scale);
192         }
193     }
194
195     /**
196      * Converts the given time duration to this unit.
197      *
198      * <p>For any TimeUnit {@code unit},
199      * {@code unit.convert(Duration.ofNanos(n))}
200      * is equivalent to
201      * {@code unit.convert(n, NANOSECONDS)}, and
202      * {@code unit.convert(Duration.of(n, unit.toChronoUnit()))}
203      * is equivalent to {@code n} (in the absence of overflow).
204      *
205      * @apiNote
206      * This method differs from {@link Duration#toNanos()} in that it
207      * does not throw {@link ArithmeticException} on numeric overflow.
208      *
209      * @param duration the time duration
210      * @return the converted duration in this unit,
211      * or {@code Long.MIN_VALUE} if conversion would negatively overflow,
212      * or {@code Long.MAX_VALUE} if it would positively overflow.
213      * @throws NullPointerException if {@code duration} is null
214      * @see Duration#of(long,TemporalUnit)
215      * @since 11
216      */

217     public long convert(Duration duration) {
218         long secs = duration.getSeconds();
219         int nano = duration.getNano();
220         if (secs < 0 && nano > 0) {
221             // use representation compatible with integer division
222             secs++;
223             nano -= (int) SECOND_SCALE;
224         }
225         final long s, nanoVal;
226         // Optimize for the common case - NANOSECONDS without overflow
227         if (this == NANOSECONDS)
228             nanoVal = nano;
229         else if ((s = scale) < SECOND_SCALE)
230             nanoVal = nano / s;
231         else if (this == SECONDS)
232             return secs;
233         else
234             return secs / secRatio;
235         long val = secs * secRatio + nanoVal;
236         return ((secs < maxSecs && secs > -maxSecs) ||
237                 (secs == maxSecs && val > 0) ||
238                 (secs == -maxSecs && val < 0))
239             ? val
240             : (secs > 0) ? Long.MAX_VALUE : Long.MIN_VALUE;
241     }
242
243     /**
244      * Equivalent to
245      * {@link #convert(long, TimeUnit) NANOSECONDS.convert(duration, this)}.
246      * @param duration the duration
247      * @return the converted duration,
248      * or {@code Long.MIN_VALUE} if conversion would negatively overflow,
249      * or {@code Long.MAX_VALUE} if it would positively overflow.
250      */

251     public long toNanos(long duration) {
252         long s, m;
253         if ((s = scale) == NANO_SCALE)
254             return duration;
255         else if (duration > (m = maxNanos))
256             return Long.MAX_VALUE;
257         else if (duration < -m)
258             return Long.MIN_VALUE;
259         else
260             return duration * s;
261     }
262
263     /**
264      * Equivalent to
265      * {@link #convert(long, TimeUnit) MICROSECONDS.convert(duration, this)}.
266      * @param duration the duration
267      * @return the converted duration,
268      * or {@code Long.MIN_VALUE} if conversion would negatively overflow,
269      * or {@code Long.MAX_VALUE} if it would positively overflow.
270      */

271     public long toMicros(long duration) {
272         long s, m;
273         if ((s = scale) <= MICRO_SCALE)
274             return (s == MICRO_SCALE) ? duration : duration / microRatio;
275         else if (duration > (m = maxMicros))
276             return Long.MAX_VALUE;
277         else if (duration < -m)
278             return Long.MIN_VALUE;
279         else
280             return duration * microRatio;
281     }
282
283     /**
284      * Equivalent to
285      * {@link #convert(long, TimeUnit) MILLISECONDS.convert(duration, this)}.
286      * @param duration the duration
287      * @return the converted duration,
288      * or {@code Long.MIN_VALUE} if conversion would negatively overflow,
289      * or {@code Long.MAX_VALUE} if it would positively overflow.
290      */

291     public long toMillis(long duration) {
292         long s, m;
293         if ((s = scale) <= MILLI_SCALE)
294             return (s == MILLI_SCALE) ? duration : duration / milliRatio;
295         else if (duration > (m = maxMillis))
296             return Long.MAX_VALUE;
297         else if (duration < -m)
298             return Long.MIN_VALUE;
299         else
300             return duration * milliRatio;
301     }
302
303     /**
304      * Equivalent to
305      * {@link #convert(long, TimeUnit) SECONDS.convert(duration, this)}.
306      * @param duration the duration
307      * @return the converted duration,
308      * or {@code Long.MIN_VALUE} if conversion would negatively overflow,
309      * or {@code Long.MAX_VALUE} if it would positively overflow.
310      */

311     public long toSeconds(long duration) {
312         long s, m;
313         if ((s = scale) <= SECOND_SCALE)
314             return (s == SECOND_SCALE) ? duration : duration / secRatio;
315         else if (duration > (m = maxSecs))
316             return Long.MAX_VALUE;
317         else if (duration < -m)
318             return Long.MIN_VALUE;
319         else
320             return duration * secRatio;
321     }
322
323     /**
324      * Equivalent to
325      * {@link #convert(long, TimeUnit) MINUTES.convert(duration, this)}.
326      * @param duration the duration
327      * @return the converted duration,
328      * or {@code Long.MIN_VALUE} if conversion would negatively overflow,
329      * or {@code Long.MAX_VALUE} if it would positively overflow.
330      * @since 1.6
331      */

332     public long toMinutes(long duration) {
333         return cvt(duration, MINUTE_SCALE, scale);
334     }
335
336     /**
337      * Equivalent to
338      * {@link #convert(long, TimeUnit) HOURS.convert(duration, this)}.
339      * @param duration the duration
340      * @return the converted duration,
341      * or {@code Long.MIN_VALUE} if conversion would negatively overflow,
342      * or {@code Long.MAX_VALUE} if it would positively overflow.
343      * @since 1.6
344      */

345     public long toHours(long duration) {
346         return cvt(duration, HOUR_SCALE, scale);
347     }
348
349     /**
350      * Equivalent to
351      * {@link #convert(long, TimeUnit) DAYS.convert(duration, this)}.
352      * @param duration the duration
353      * @return the converted duration
354      * @since 1.6
355      */

356     public long toDays(long duration) {
357         return cvt(duration, DAY_SCALE, scale);
358     }
359
360     /**
361      * Utility to compute the excess-nanosecond argument to wait,
362      * sleep, join.
363      * @param d the duration
364      * @param m the number of milliseconds
365      * @return the number of nanoseconds
366      */

367     private int excessNanos(long d, long m) {
368         long s;
369         if ((s = scale) == NANO_SCALE)
370             return (int)(d - (m * MILLI_SCALE));
371         else if (s == MICRO_SCALE)
372             return (int)((d * 1000L) - (m * MILLI_SCALE));
373         else
374             return 0;
375     }
376
377     /**
378      * Performs a timed {@link Object#wait(longint) Object.wait}
379      * using this time unit.
380      * This is a convenience method that converts timeout arguments
381      * into the form required by the {@code Object.wait} method.
382      *
383      * <p>For example, you could implement a blocking {@code poll} method
384      * (see {@link BlockingQueue#poll(long, TimeUnit) BlockingQueue.poll})
385      * using:
386      *
387      * <pre> {@code
388      * public E poll(long timeout, TimeUnit unit)
389      *     throws InterruptedException {
390      *   synchronized (lock) {
391      *     while (isEmpty()) {
392      *       unit.timedWait(lock, timeout);
393      *       ...
394      *     }
395      *   }
396      * }}</pre>
397      *
398      * @param obj the object to wait on
399      * @param timeout the maximum time to wait. If less than
400      * or equal to zero, do not wait at all.
401      * @throws InterruptedException if interrupted while waiting
402      */

403     public void timedWait(Object obj, long timeout)
404             throws InterruptedException {
405         if (timeout > 0) {
406             long ms = toMillis(timeout);
407             int ns = excessNanos(timeout, ms);
408             obj.wait(ms, ns);
409         }
410     }
411
412     /**
413      * Performs a timed {@link Thread#join(longint) Thread.join}
414      * using this time unit.
415      * This is a convenience method that converts time arguments into the
416      * form required by the {@code Thread.join} method.
417      *
418      * @param thread the thread to wait for
419      * @param timeout the maximum time to wait. If less than
420      * or equal to zero, do not wait at all.
421      * @throws InterruptedException if interrupted while waiting
422      */

423     public void timedJoin(Thread thread, long timeout)
424             throws InterruptedException {
425         if (timeout > 0) {
426             long ms = toMillis(timeout);
427             int ns = excessNanos(timeout, ms);
428             thread.join(ms, ns);
429         }
430     }
431
432     /**
433      * Performs a {@link Thread#sleep(longint) Thread.sleep} using
434      * this time unit.
435      * This is a convenience method that converts time arguments into the
436      * form required by the {@code Thread.sleep} method.
437      *
438      * @param timeout the minimum time to sleep. If less than
439      * or equal to zero, do not sleep at all.
440      * @throws InterruptedException if interrupted while sleeping
441      */

442     public void sleep(long timeout) throws InterruptedException {
443         if (timeout > 0) {
444             long ms = toMillis(timeout);
445             int ns = excessNanos(timeout, ms);
446             Thread.sleep(ms, ns);
447         }
448     }
449
450     /**
451      * Converts this {@code TimeUnit} to the equivalent {@code ChronoUnit}.
452      *
453      * @return the converted equivalent ChronoUnit
454      * @since 9
455      */

456     public ChronoUnit toChronoUnit() {
457         switch (this) {
458         case NANOSECONDS:  return ChronoUnit.NANOS;
459         case MICROSECONDS: return ChronoUnit.MICROS;
460         case MILLISECONDS: return ChronoUnit.MILLIS;
461         case SECONDS:      return ChronoUnit.SECONDS;
462         case MINUTES:      return ChronoUnit.MINUTES;
463         case HOURS:        return ChronoUnit.HOURS;
464         case DAYS:         return ChronoUnit.DAYS;
465         defaultthrow new AssertionError();
466         }
467     }
468
469     /**
470      * Converts a {@code ChronoUnit} to the equivalent {@code TimeUnit}.
471      *
472      * @param chronoUnit the ChronoUnit to convert
473      * @return the converted equivalent TimeUnit
474      * @throws IllegalArgumentException if {@code chronoUnit} has no
475      *         equivalent TimeUnit
476      * @throws NullPointerException if {@code chronoUnit} is null
477      * @since 9
478      */

479     public static TimeUnit of(ChronoUnit chronoUnit) {
480         switch (Objects.requireNonNull(chronoUnit, "chronoUnit")) {
481         case NANOS:   return TimeUnit.NANOSECONDS;
482         case MICROS:  return TimeUnit.MICROSECONDS;
483         case MILLIS:  return TimeUnit.MILLISECONDS;
484         case SECONDS: return TimeUnit.SECONDS;
485         case MINUTES: return TimeUnit.MINUTES;
486         case HOURS:   return TimeUnit.HOURS;
487         case DAYS:    return TimeUnit.DAYS;
488         default:
489             throw new IllegalArgumentException(
490                 "No TimeUnit equivalent for " + chronoUnit);
491         }
492     }
493
494 }
495