ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/TimeUnit.java
(Generate patch)

Comparing jsr166/src/main/java/util/concurrent/TimeUnit.java (file contents):
Revision 1.13 by dl, Fri Sep 12 15:40:10 2003 UTC vs.
Revision 1.29 by jsr166, Tue Apr 26 01:17:18 2005 UTC

# Line 1 | Line 1
1   /*
2 < * Written by Doug Lea with assistance from members of JCP JSR-166
3 < * Expert Group and released to the public domain. Use, modify, and
4 < * redistribute this code in any way without acknowledgement.
5 < */
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/licenses/publicdomain
5 >  */
6  
7   package java.util.concurrent;
8  
9   /**
10   * A <tt>TimeUnit</tt> 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.
13 < * <tt>TimeUnit</tt> is a &quot;featherweight&quot; class.
14 < * It does not maintain time information, but only helps organize and
15 < * use time representations that may be maintained separately across
16 < * various contexts.
12 > * and to perform timing and delay operations in these units.  A
13 > * <tt>TimeUnit</tt> 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>This class cannot be directly instantiated.  Use the {@link
22 < * #SECONDS}, {@link #MILLISECONDS}, {@link #MICROSECONDS}, and {@link
23 < * #NANOSECONDS} static instances that provide predefined units of
24 < * precision. If you use these frequently, consider statically
22 < * importing this class.
21 > * <p>A <tt>TimeUnit</tt> 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   *
24 * <p>A <tt>TimeUnit</tt> is mainly used to inform blocking methods which
25 * can timeout, how the timeout parameter should be interpreted. For example,
26 * the following code will timeout in 50 milliseconds if the {@link java.util.concurrent.locks.Lock lock}
27 * is not available:
26   * <pre>  Lock lock = ...;
27   *  if ( lock.tryLock(50L, TimeUnit.MILLISECONDS) ) ...
28   * </pre>
# Line 33 | Line 31 | package java.util.concurrent;
31   *  Lock lock = ...;
32   *  if ( lock.tryLock(50L, TimeUnit.SECONDS) ) ...
33   * </pre>
34 < * Note however, that there is no guarantee that a particular lock, in this
35 < * case, will be able to notice the passage of time at the same granularity
36 < * as the given <tt>TimeUnit</tt>.
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 <tt>TimeUnit</tt>.
38   *
39   * @since 1.5
40   * @author Doug Lea
41   */
42 < public final class TimeUnit implements java.io.Serializable {
43 <
44 <    /**
45 <     * Perform the conversion based on given index representing the
46 <     * difference between units
47 <     * @param delta the difference in index values of source and target units
48 <     * @param duration the duration
49 <     * @return converted duration or saturated value
50 <     */
51 <    private static long doConvert(int delta, long duration) {
52 <        if (delta == 0)
53 <            return duration;
54 <        if (delta < 0)
55 <            return duration / multipliers[-delta];
56 <        if (duration > overflows[delta])
57 <            return Long.MAX_VALUE;
58 <        if (duration < -overflows[delta])
59 <            return Long.MIN_VALUE;
60 <        return duration * multipliers[delta];
42 > public enum TimeUnit {
43 >    NANOSECONDS (0) {
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 (1) {
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 (2) {
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 (3) {
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 (4) {
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 (5) {
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 (6) {
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 >    /**
122 >     * The index of this unit. This value is no longer used in this
123 >     * version of this class, but is retained for serialization
124 >     * compatibility with previous version.
125 >     */
126 >    private final int index;
127 >
128 >    /** Internal constructor */
129 >    TimeUnit(int index) {
130 >        this.index = index;
131 >    }
132 >
133 >    // Handy constants for conversion methods
134 >    static final long C0 = 1L;
135 >    static final long C1 = C0 * 1000L;
136 >    static final long C2 = C1 * 1000L;
137 >    static final long C3 = C2 * 1000L;
138 >    static final long C4 = C3 * 60L;
139 >    static final long C5 = C4 * 60L;
140 >    static final long C6 = C5 * 24L;
141 >
142 >    static final long MAX = Long.MAX_VALUE;
143 >
144 >    /**
145 >     * Scale d by m, checking for overflow.
146 >     * This has a short name to make above code more readable.
147 >     */
148 >    static long x(long d, long m, long over) {
149 >        if (d >  over) return Long.MAX_VALUE;
150 >        if (d < -over) return Long.MIN_VALUE;
151 >        return d * m;
152      }
153  
154      /**
155 <     * Convert the given time duration in the given unit to the
156 <     * current unit.  Conversions from finer to coarser granulaties
155 >     * Convert the given time duration in the given unit to this
156 >     * unit.  Conversions from finer to coarser granularities
157       * truncate, so lose precision. For example converting
158       * <tt>999</tt> milliseconds to seconds results in
159       * <tt>0</tt>. Conversions from coarser to finer granularities
# Line 73 | Line 163 | public final class TimeUnit implements j
163       *
164       * @param duration the time duration in the given <tt>unit</tt>
165       * @param unit the unit of the <tt>duration</tt> argument
166 <     * @return the converted duration in the current unit,
166 >     * @return the converted duration in this unit,
167       * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
168       * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
169       */
170 <    public long convert(long duration, TimeUnit unit) {
81 <        return doConvert(unit.index - index, duration);
82 <    }
170 >    public abstract long convert(long duration, TimeUnit unit);
171  
172      /**
173       * Equivalent to <tt>NANOSECONDS.convert(duration, this)</tt>.
# Line 89 | Line 177 | public final class TimeUnit implements j
177       * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
178       * @see #convert
179       */
180 <    public long toNanos(long duration) {
93 <        return doConvert(index, duration);
94 <    }
180 >    public abstract long toNanos(long duration);
181  
182      /**
183       * Equivalent to <tt>MICROSECONDS.convert(duration, this)</tt>.
# Line 101 | Line 187 | public final class TimeUnit implements j
187       * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
188       * @see #convert
189       */
190 <    public long toMicros(long duration) {
105 <        return doConvert(index - US, duration);
106 <    }
190 >    public abstract long toMicros(long duration);
191  
192      /**
193       * Equivalent to <tt>MILLISECONDS.convert(duration, this)</tt>.
# Line 113 | Line 197 | public final class TimeUnit implements j
197       * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
198       * @see #convert
199       */
200 <    public long toMillis(long duration) {
117 <        return doConvert(index - MS, duration);
118 <    }
200 >    public abstract long toMillis(long duration);
201  
202      /**
203       * Equivalent to <tt>SECONDS.convert(duration, this)</tt>.
204       * @param duration the duration
205 <     * @return the converted duration.
205 >     * @return the converted duration,
206 >     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
207 >     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
208       * @see #convert
209       */
210 <    public long toSeconds(long duration) {
211 <        return doConvert(index - S, duration);
212 <    }
210 >    public abstract long toSeconds(long duration);
211 >
212 >    /**
213 >     * Equivalent to <tt>MINUTES.convert(duration, this)</tt>.
214 >     * @param duration the duration
215 >     * @return the converted duration,
216 >     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
217 >     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
218 >     * @see #convert
219 >     */
220 >    public abstract long toMinutes(long duration);
221 >
222 >    /**
223 >     * Equivalent to <tt>HOURS.convert(duration, this)</tt>.
224 >     * @param duration the duration
225 >     * @return the converted duration,
226 >     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
227 >     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
228 >     * @see #convert
229 >     */
230 >    public abstract long toHours(long duration);
231  
232      /**
233 <     * Perform a timed <tt>Object.wait</tt> using the current time unit.
234 <     * This is a convenience method that converts timeout arguments into the
235 <     * form required by the <tt>Object.wait</tt> method.
236 <     * <p>For example, you could implement a blocking <tt>poll</tt> method (see
237 <     * {@link BlockingQueue#poll BlockingQueue.poll} using:
233 >     * Equivalent to <tt>DAYS.convert(duration, this)</tt>.
234 >     * @param duration the duration
235 >     * @return the converted duration
236 >     * @see #convert
237 >     */
238 >    public abstract long toDays(long duration);
239 >
240 >    /**
241 >     * Utility to compute the excess-nanosecond argument to wait,
242 >     * sleep, join.
243 >     * @param d the duration
244 >     * @param m the number of milliseconds
245 >     * @return the number of nanoseconds
246 >     */
247 >    abstract int excessNanos(long d, long m);
248 >
249 >    /**
250 >     * Performs a timed <tt>Object.wait</tt> using this time unit.
251 >     * This is a convenience method that converts timeout arguments
252 >     * into the form required by the <tt>Object.wait</tt> method.
253 >     *
254 >     * <p>For example, you could implement a blocking <tt>poll</tt>
255 >     * method (see {@link BlockingQueue#poll BlockingQueue.poll})
256 >     * using:
257 >     *
258       * <pre>  public synchronized  Object poll(long timeout, TimeUnit unit) throws InterruptedException {
259       *    while (empty) {
260       *      unit.timedWait(this, timeout);
261       *      ...
262       *    }
263       *  }</pre>
264 +     *
265       * @param obj the object to wait on
266 <     * @param timeout the maximum time to wait.
266 >     * @param timeout the maximum time to wait. If less than
267 >     * or equal to zero, do not wait at all.
268       * @throws InterruptedException if interrupted while waiting.
269       * @see Object#wait(long, int)
270       */
271      public void timedWait(Object obj, long timeout)
272 <        throws InterruptedException {
272 >    throws InterruptedException {
273          if (timeout > 0) {
274 <            long ms = MILLISECONDS.convert(timeout, this);
274 >            long ms = toMillis(timeout);
275              int ns = excessNanos(timeout, ms);
276              obj.wait(ms, ns);
277          }
278      }
279  
280      /**
281 <     * Perform a timed <tt>Thread.join</tt> using the current time unit.
281 >     * Performs a timed <tt>Thread.join</tt> using this time unit.
282       * This is a convenience method that converts time arguments into the
283       * form required by the <tt>Thread.join</tt> method.
284       * @param thread the thread to wait for
285 <     * @param timeout the maximum time to wait
285 >     * @param timeout the maximum time to wait. If less than
286 >     * or equal to zero, do not wait at all.
287       * @throws InterruptedException if interrupted while waiting.
288       * @see Thread#join(long, int)
289       */
290      public void timedJoin(Thread thread, long timeout)
291 <        throws InterruptedException {
291 >    throws InterruptedException {
292          if (timeout > 0) {
293 <            long ms = MILLISECONDS.convert(timeout, this);
293 >            long ms = toMillis(timeout);
294              int ns = excessNanos(timeout, ms);
295              thread.join(ms, ns);
296          }
297      }
298  
299      /**
300 <     * Perform a <tt>Thread.sleep</tt> using the current time unit.
300 >     * Performs a <tt>Thread.sleep</tt> using this unit.
301       * This is a convenience method that converts time arguments into the
302       * form required by the <tt>Thread.sleep</tt> method.
303 <     * @param timeout the minimum time to sleep
303 >     * @param timeout the minimum time to sleep. If less than
304 >     * or equal to zero, do not sleep at all.
305       * @throws InterruptedException if interrupted while sleeping.
306       * @see Thread#sleep
307       */
308      public void sleep(long timeout) throws InterruptedException {
309          if (timeout > 0) {
310 <            long ms = MILLISECONDS.convert(timeout, this);
310 >            long ms = toMillis(timeout);
311              int ns = excessNanos(timeout, ms);
312              Thread.sleep(ms, ns);
313          }
314      }
315  
190    /**
191     * Return the common name for this unit.
192     */
193    public String toString() {
194        return unitName;
195    }
196
197
198    /**
199     * Returns true if the given object is a TimeUnit representing
200     * the same unit as this TimeUnit.
201     * @param x the object to compare
202     * @return true if equal
203     */
204    public boolean equals(Object x) {
205        if (!(x instanceof TimeUnit))
206            return false;
207        return ((TimeUnit)x).index == index;
208    }
209
210    /**
211     * Returns a hash code for this TimeUnit.
212     * @return the hash code
213     */
214    public int hashCode() {
215        return unitName.hashCode();
216    }
217
218    private final String unitName;
219
220    /* ordered indices for each time unit */
221    private static final int NS = 0;
222    private static final int US = 1;
223    private static final int MS = 2;
224    private static final int S  = 3;
225
226    /** quick lookup table for conversion factors */
227    static final int[] multipliers = { 1,
228                                       1000,
229                                       1000*1000,
230                                       1000*1000*1000 };
231
232    /** lookup table to check saturation */
233    static final long[] overflows = {
234        // Note that because we are dividing these down anyway,
235        // we don't have to deal with asymmetry of MIN/MAX values.
236        0, // unused
237        Long.MAX_VALUE / 1000,
238        Long.MAX_VALUE / (1000 * 1000),
239        Long.MAX_VALUE / (1000 * 1000 * 1000) };
240
241    /** the index of this unit */
242    int index;
243
244    /** private constructor */
245    TimeUnit(int index, String name) {
246        this.index = index;
247        this.unitName = name;
248    }
249
250    /**
251     * Utility method to compute the excess-nanosecond argument to
252     * wait, sleep, join. The results may overflow, so public methods
253     * invoking this should document possible overflow unless
254     * overflow is known not to be possible for the given arguments.
255     */
256    private int excessNanos(long time, long ms) {
257        if (index == NS)
258            return (int) (time  - (ms * multipliers[MS-NS]));
259        else if (index == US)
260            return (int) ((time * multipliers[US-NS]) - (ms * multipliers[MS-NS]));
261        else
262            return 0;
263    }
264
265    /** Unit for one-second granularities. */
266    public static final TimeUnit SECONDS = new TimeUnit(S, "seconds");
267
268    /** Unit for one-millisecond granularities. */
269    public static final TimeUnit MILLISECONDS = new TimeUnit(MS, "milliseconds");
270
271    /** Unit for one-microsecond granularities. */
272    public static final TimeUnit MICROSECONDS = new TimeUnit(US, "microseconds");
273
274    /** Unit for one-nanosecond granularities. */
275    public static final TimeUnit NANOSECONDS = new TimeUnit(NS, "nanoseconds");
276
316   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines