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