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