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