001 /*
002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
003 *
004 * This code is free software; you can redistribute it and/or modify it
005 * under the terms of the GNU General Public License version 2 only, as
006 * published by the Free Software Foundation. Sun designates this
007 * particular file as subject to the "Classpath" exception as provided
008 * by Sun in the LICENSE file that accompanied this code.
009 *
010 * This code is distributed in the hope that it will be useful, but WITHOUT
011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
013 * version 2 for more details (a copy is included in the LICENSE file that
014 * accompanied this code).
015 *
016 * You should have received a copy of the GNU General Public License version
017 * 2 along with this work; if not, write to the Free Software Foundation,
018 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
019 *
020 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
021 * CA 95054 USA or visit www.sun.com if you need additional information or
022 * have any questions.
023 */
024
025 /*
026 * This file is available under and governed by the GNU General Public
027 * License version 2 only, as published by the Free Software Foundation.
028 * However, the following notice accompanied the original version of this
029 * file:
030 *
031 * Written by Doug Lea with assistance from members of JCP JSR-166
032 * Expert Group and released to the public domain, as explained at
033 * http://creativecommons.org/licenses/publicdomain
034 */
035
036 package java.util.concurrent;
037
038 /**
039 * A <tt>TimeUnit</tt> represents time durations at a given unit of
040 * granularity and provides utility methods to convert across units,
041 * and to perform timing and delay operations in these units. A
042 * <tt>TimeUnit</tt> does not maintain time information, but only
043 * helps organize and use time representations that may be maintained
044 * separately across various contexts. A nanosecond is defined as one
045 * thousandth of a microsecond, a microsecond as one thousandth of a
046 * millisecond, a millisecond as one thousandth of a second, a minute
047 * as sixty seconds, an hour as sixty minutes, and a day as twenty four
048 * hours.
049 *
050 * <p>A <tt>TimeUnit</tt> is mainly used to inform time-based methods
051 * how a given timing parameter should be interpreted. For example,
052 * the following code will timeout in 50 milliseconds if the {@link
053 * java.util.concurrent.locks.Lock lock} is not available:
054 *
055 * <pre> Lock lock = ...;
056 * if ( lock.tryLock(50L, TimeUnit.MILLISECONDS) ) ...
057 * </pre>
058 * while this code will timeout in 50 seconds:
059 * <pre>
060 * Lock lock = ...;
061 * if ( lock.tryLock(50L, TimeUnit.SECONDS) ) ...
062 * </pre>
063 *
064 * Note however, that there is no guarantee that a particular timeout
065 * implementation will be able to notice the passage of time at the
066 * same granularity as the given <tt>TimeUnit</tt>.
067 *
068 * @since 1.5
069 * @author Doug Lea
070 */
071 public enum TimeUnit {
072 NANOSECONDS {
073 public long toNanos(long d) {
074 return d;
075 }
076
077 public long toMicros(long d) {
078 return d / (C1 / C0);
079 }
080
081 public long toMillis(long d) {
082 return d / (C2 / C0);
083 }
084
085 public long toSeconds(long d) {
086 return d / (C3 / C0);
087 }
088
089 public long toMinutes(long d) {
090 return d / (C4 / C0);
091 }
092
093 public long toHours(long d) {
094 return d / (C5 / C0);
095 }
096
097 public long toDays(long d) {
098 return d / (C6 / C0);
099 }
100
101 public long convert(long d, TimeUnit u) {
102 return u.toNanos(d);
103 }
104
105 int excessNanos(long d, long m) {
106 return (int) (d - (m * C2));
107 }
108 },
109 MICROSECONDS {
110 public long toNanos(long d) {
111 return x(d, C1 / C0, MAX / (C1 / C0));
112 }
113
114 public long toMicros(long d) {
115 return d;
116 }
117
118 public long toMillis(long d) {
119 return d / (C2 / C1);
120 }
121
122 public long toSeconds(long d) {
123 return d / (C3 / C1);
124 }
125
126 public long toMinutes(long d) {
127 return d / (C4 / C1);
128 }
129
130 public long toHours(long d) {
131 return d / (C5 / C1);
132 }
133
134 public long toDays(long d) {
135 return d / (C6 / C1);
136 }
137
138 public long convert(long d, TimeUnit u) {
139 return u.toMicros(d);
140 }
141
142 int excessNanos(long d, long m) {
143 return (int) ((d * C1) - (m * C2));
144 }
145 },
146 MILLISECONDS {
147 public long toNanos(long d) {
148 return x(d, C2 / C0, MAX / (C2 / C0));
149 }
150
151 public long toMicros(long d) {
152 return x(d, C2 / C1, MAX / (C2 / C1));
153 }
154
155 public long toMillis(long d) {
156 return d;
157 }
158
159 public long toSeconds(long d) {
160 return d / (C3 / C2);
161 }
162
163 public long toMinutes(long d) {
164 return d / (C4 / C2);
165 }
166
167 public long toHours(long d) {
168 return d / (C5 / C2);
169 }
170
171 public long toDays(long d) {
172 return d / (C6 / C2);
173 }
174
175 public long convert(long d, TimeUnit u) {
176 return u.toMillis(d);
177 }
178
179 int excessNanos(long d, long m) {
180 return 0;
181 }
182 },
183 SECONDS {
184 public long toNanos(long d) {
185 return x(d, C3 / C0, MAX / (C3 / C0));
186 }
187
188 public long toMicros(long d) {
189 return x(d, C3 / C1, MAX / (C3 / C1));
190 }
191
192 public long toMillis(long d) {
193 return x(d, C3 / C2, MAX / (C3 / C2));
194 }
195
196 public long toSeconds(long d) {
197 return d;
198 }
199
200 public long toMinutes(long d) {
201 return d / (C4 / C3);
202 }
203
204 public long toHours(long d) {
205 return d / (C5 / C3);
206 }
207
208 public long toDays(long d) {
209 return d / (C6 / C3);
210 }
211
212 public long convert(long d, TimeUnit u) {
213 return u.toSeconds(d);
214 }
215
216 int excessNanos(long d, long m) {
217 return 0;
218 }
219 },
220 MINUTES {
221 public long toNanos(long d) {
222 return x(d, C4 / C0, MAX / (C4 / C0));
223 }
224
225 public long toMicros(long d) {
226 return x(d, C4 / C1, MAX / (C4 / C1));
227 }
228
229 public long toMillis(long d) {
230 return x(d, C4 / C2, MAX / (C4 / C2));
231 }
232
233 public long toSeconds(long d) {
234 return x(d, C4 / C3, MAX / (C4 / C3));
235 }
236
237 public long toMinutes(long d) {
238 return d;
239 }
240
241 public long toHours(long d) {
242 return d / (C5 / C4);
243 }
244
245 public long toDays(long d) {
246 return d / (C6 / C4);
247 }
248
249 public long convert(long d, TimeUnit u) {
250 return u.toMinutes(d);
251 }
252
253 int excessNanos(long d, long m) {
254 return 0;
255 }
256 },
257 HOURS {
258 public long toNanos(long d) {
259 return x(d, C5 / C0, MAX / (C5 / C0));
260 }
261
262 public long toMicros(long d) {
263 return x(d, C5 / C1, MAX / (C5 / C1));
264 }
265
266 public long toMillis(long d) {
267 return x(d, C5 / C2, MAX / (C5 / C2));
268 }
269
270 public long toSeconds(long d) {
271 return x(d, C5 / C3, MAX / (C5 / C3));
272 }
273
274 public long toMinutes(long d) {
275 return x(d, C5 / C4, MAX / (C5 / C4));
276 }
277
278 public long toHours(long d) {
279 return d;
280 }
281
282 public long toDays(long d) {
283 return d / (C6 / C5);
284 }
285
286 public long convert(long d, TimeUnit u) {
287 return u.toHours(d);
288 }
289
290 int excessNanos(long d, long m) {
291 return 0;
292 }
293 },
294 DAYS {
295 public long toNanos(long d) {
296 return x(d, C6 / C0, MAX / (C6 / C0));
297 }
298
299 public long toMicros(long d) {
300 return x(d, C6 / C1, MAX / (C6 / C1));
301 }
302
303 public long toMillis(long d) {
304 return x(d, C6 / C2, MAX / (C6 / C2));
305 }
306
307 public long toSeconds(long d) {
308 return x(d, C6 / C3, MAX / (C6 / C3));
309 }
310
311 public long toMinutes(long d) {
312 return x(d, C6 / C4, MAX / (C6 / C4));
313 }
314
315 public long toHours(long d) {
316 return x(d, C6 / C5, MAX / (C6 / C5));
317 }
318
319 public long toDays(long d) {
320 return d;
321 }
322
323 public long convert(long d, TimeUnit u) {
324 return u.toDays(d);
325 }
326
327 int excessNanos(long d, long m) {
328 return 0;
329 }
330 };
331
332 // Handy constants for conversion methods
333 static final long C0 = 1L;
334 static final long C1 = C0 * 1000L;
335 static final long C2 = C1 * 1000L;
336 static final long C3 = C2 * 1000L;
337 static final long C4 = C3 * 60L;
338 static final long C5 = C4 * 60L;
339 static final long C6 = C5 * 24L;
340
341 static final long MAX = Long.MAX_VALUE;
342
343 /**
344 * Scale d by m, checking for overflow.
345 * This has a short name to make above code more readable.
346 */
347 static long x(long d, long m, long over) {
348 if (d > over)
349 return Long.MAX_VALUE;
350 if (d < -over)
351 return Long.MIN_VALUE;
352 return d * m;
353 }
354
355 // To maintain full signature compatibility with 1.5, and to improve the
356 // clarity of the generated javadoc (see 6287639: Abstract methods in
357 // enum classes should not be listed as abstract), method convert
358 // etc. are not declared abstract but otherwise act as abstract methods.
359
360 /**
361 * Convert the given time duration in the given unit to this
362 * unit. Conversions from finer to coarser granularities
363 * truncate, so lose precision. For example converting
364 * <tt>999</tt> milliseconds to seconds results in
365 * <tt>0</tt>. Conversions from coarser to finer granularities
366 * with arguments that would numerically overflow saturate to
367 * <tt>Long.MIN_VALUE</tt> if negative or <tt>Long.MAX_VALUE</tt>
368 * if positive.
369 *
370 * <p>For example, to convert 10 minutes to milliseconds, use:
371 * <tt>TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)</tt>
372 *
373 * @param sourceDuration the time duration in the given <tt>sourceUnit</tt>
374 * @param sourceUnit the unit of the <tt>sourceDuration</tt> argument
375 * @return the converted duration in this unit,
376 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
377 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
378 */
379 public long convert(long sourceDuration, TimeUnit sourceUnit) {
380 throw new AbstractMethodError();
381 }
382
383 /**
384 * Equivalent to <tt>NANOSECONDS.convert(duration, this)</tt>.
385 * @param duration the duration
386 * @return the converted duration,
387 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
388 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
389 * @see #convert
390 */
391 public long toNanos(long duration) {
392 throw new AbstractMethodError();
393 }
394
395 /**
396 * Equivalent to <tt>MICROSECONDS.convert(duration, this)</tt>.
397 * @param duration the duration
398 * @return the converted duration,
399 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
400 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
401 * @see #convert
402 */
403 public long toMicros(long duration) {
404 throw new AbstractMethodError();
405 }
406
407 /**
408 * Equivalent to <tt>MILLISECONDS.convert(duration, this)</tt>.
409 * @param duration the duration
410 * @return the converted duration,
411 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
412 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
413 * @see #convert
414 */
415 public long toMillis(long duration) {
416 throw new AbstractMethodError();
417 }
418
419 /**
420 * Equivalent to <tt>SECONDS.convert(duration, this)</tt>.
421 * @param duration the duration
422 * @return the converted duration,
423 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
424 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
425 * @see #convert
426 */
427 public long toSeconds(long duration) {
428 throw new AbstractMethodError();
429 }
430
431 /**
432 * Equivalent to <tt>MINUTES.convert(duration, this)</tt>.
433 * @param duration the duration
434 * @return the converted duration,
435 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
436 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
437 * @see #convert
438 * @since 1.6
439 */
440 public long toMinutes(long duration) {
441 throw new AbstractMethodError();
442 }
443
444 /**
445 * Equivalent to <tt>HOURS.convert(duration, this)</tt>.
446 * @param duration the duration
447 * @return the converted duration,
448 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
449 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
450 * @see #convert
451 * @since 1.6
452 */
453 public long toHours(long duration) {
454 throw new AbstractMethodError();
455 }
456
457 /**
458 * Equivalent to <tt>DAYS.convert(duration, this)</tt>.
459 * @param duration the duration
460 * @return the converted duration
461 * @see #convert
462 * @since 1.6
463 */
464 public long toDays(long duration) {
465 throw new AbstractMethodError();
466 }
467
468 /**
469 * Utility to compute the excess-nanosecond argument to wait,
470 * sleep, join.
471 * @param d the duration
472 * @param m the number of milliseconds
473 * @return the number of nanoseconds
474 */
475 abstract int excessNanos(long d, long m);
476
477 /**
478 * Performs a timed <tt>Object.wait</tt> using this time unit.
479 * This is a convenience method that converts timeout arguments
480 * into the form required by the <tt>Object.wait</tt> method.
481 *
482 * <p>For example, you could implement a blocking <tt>poll</tt>
483 * method (see {@link BlockingQueue#poll BlockingQueue.poll})
484 * using:
485 *
486 * <pre> public synchronized Object poll(long timeout, TimeUnit unit) throws InterruptedException {
487 * while (empty) {
488 * unit.timedWait(this, timeout);
489 * ...
490 * }
491 * }</pre>
492 *
493 * @param obj the object to wait on
494 * @param timeout the maximum time to wait. If less than
495 * or equal to zero, do not wait at all.
496 * @throws InterruptedException if interrupted while waiting.
497 * @see Object#wait(long, int)
498 */
499 public void timedWait(Object obj, long timeout)
500 throws InterruptedException {
501 if (timeout > 0) {
502 long ms = toMillis(timeout);
503 int ns = excessNanos(timeout, ms);
504 obj.wait(ms, ns);
505 }
506 }
507
508 /**
509 * Performs a timed <tt>Thread.join</tt> using this time unit.
510 * This is a convenience method that converts time arguments into the
511 * form required by the <tt>Thread.join</tt> method.
512 * @param thread the thread to wait for
513 * @param timeout the maximum time to wait. If less than
514 * or equal to zero, do not wait at all.
515 * @throws InterruptedException if interrupted while waiting.
516 * @see Thread#join(long, int)
517 */
518 public void timedJoin(Thread thread, long timeout)
519 throws InterruptedException {
520 if (timeout > 0) {
521 long ms = toMillis(timeout);
522 int ns = excessNanos(timeout, ms);
523 thread.join(ms, ns);
524 }
525 }
526
527 /**
528 * Performs a <tt>Thread.sleep</tt> using this unit.
529 * This is a convenience method that converts time arguments into the
530 * form required by the <tt>Thread.sleep</tt> method.
531 * @param timeout the minimum time to sleep. If less than
532 * or equal to zero, do not sleep at all.
533 * @throws InterruptedException if interrupted while sleeping.
534 * @see Thread#sleep
535 */
536 public void sleep(long timeout) throws InterruptedException {
537 if (timeout > 0) {
538 long ms = toMillis(timeout);
539 int ns = excessNanos(timeout, ms);
540 Thread.sleep(ms, ns);
541 }
542 }
543
544 }
|