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.10 by dl, Sat Aug 30 14:52:52 2003 UTC vs.
Revision 1.27 by dl, Tue Mar 8 12:27:11 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>The <tt>TimeUnit</tt> class cannot be directly instantiated.
22 < * Use the {@link #SECONDS}, {@link #MILLISECONDS}, {@link #MICROSECONDS},
23 < * and {@link #NANOSECONDS} static instances that provide predefined
24 < * units of precision. If you use these frequently, consider
22 < * statically 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
41 * @spec JSR-166
42 * @revised $Date$
43 * @editor $Author$
40   * @author Doug Lea
41   */
42 < public final class TimeUnit implements java.io.Serializable {
43 <
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
157 <     * truncate, so lose precision. Conversions from coarser to finer
158 <     * granularities with arguments that would numerically overflow
159 <     * saturate to <tt>Long.MIN_VALUE</tt> if negative or
160 <     * <tt>Long>MAX_VALUE</tt> if positive.
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
160 >     * with arguments that would numerically overflow saturate to
161 >     * <tt>Long.MIN_VALUE</tt> if negative or <tt>Long.MAX_VALUE</tt>
162 >     * if positive.
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.
168 >     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
169       */
170 <    public long convert(long duration, TimeUnit unit) {
171 <        if (unit == this)
64 <            return duration;
65 <        else if (index > unit.index)
66 <            return duration / multipliers[index - unit.index];
67 <        else {
68 <            int i = unit.index - index;
69 <            if (duration > overflows[i])
70 <                return Long.MAX_VALUE;
71 <            if (duration < -overflows[i])
72 <                return Long.MIN_VALUE;
73 <            return duration * multipliers[i];
74 <        }
75 <    }
76 <
170 >    public abstract long convert(long duration, TimeUnit unit);
171 >    
172      /**
173 <     * Equivalent to <code>NANOSECONDS.convert(duration, this)</code>.
173 >     * Equivalent to <tt>NANOSECONDS.convert(duration, this)</tt>.
174       * @param duration the duration
175 <     * @return the converted duration.
175 >     * @return the converted duration,
176       * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
177 <     * overflow, or <tt>Long>MAX_VALUE</tt> if it would positively overflow.
178 <     **/
179 <    public long toNanos(long duration) {
180 <        if (index == NS)
181 <            return duration;
182 <        if (duration > overflows[index])
183 <            return Long.MAX_VALUE;
184 <        if (duration < -overflows[index])
185 <            return Long.MIN_VALUE;
186 <        return duration * multipliers[index];
187 <    }
188 <
177 >     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
178 >     * @see #convert
179 >     */
180 >    public abstract long toNanos(long duration);
181 >    
182 >    /**
183 >     * Equivalent to <tt>MICROSECONDS.convert(duration, this)</tt>.
184 >     * @param duration the duration
185 >     * @return the converted duration,
186 >     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
187 >     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
188 >     * @see #convert
189 >     */
190 >    public abstract long toMicros(long duration);
191 >    
192 >    /**
193 >     * Equivalent to <tt>MILLISECONDS.convert(duration, this)</tt>.
194 >     * @param duration the duration
195 >     * @return the converted duration,
196 >     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
197 >     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
198 >     * @see #convert
199 >     */
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,
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 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 >     * 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 <     * Perform a timed <tt>Object.wait</tt> using the current time unit.
251 <     * This is a convenience method that converts timeout arguments into the
252 <     * form required by the <tt>Object.wait</tt> method.
253 <     * <p>For example, you could implement a blocking <tt>poll</tt> method (see
254 <     * {@link BlockingQueue#poll BlockingQueue.poll} using:
250 >     * Perform 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.
267       * @throws InterruptedException if interrupted while waiting.
268       * @see Object#wait(long, int)
269       */
270      public void timedWait(Object obj, long timeout)
271 <        throws InterruptedException {
271 >    throws InterruptedException {
272          if (timeout > 0) {
273 <            long ms = MILLISECONDS.convert(timeout, this);
273 >            long ms = toMillis(timeout);
274              int ns = excessNanos(timeout, ms);
275              obj.wait(ms, ns);
276          }
277      }
278 <
278 >    
279      /**
280 <     * Perform a timed <tt>Thread.join</tt> using the current time unit.
280 >     * Perform a timed <tt>Thread.join</tt> using this time unit.
281       * This is a convenience method that converts time arguments into the
282       * form required by the <tt>Thread.join</tt> method.
283       * @param thread the thread to wait for
# Line 127 | Line 286 | public final class TimeUnit implements j
286       * @see Thread#join(long, int)
287       */
288      public void timedJoin(Thread thread, long timeout)
289 <        throws InterruptedException {
289 >    throws InterruptedException {
290          if (timeout > 0) {
291 <            long ms = MILLISECONDS.convert(timeout, this);
291 >            long ms = toMillis(timeout);
292              int ns = excessNanos(timeout, ms);
293              thread.join(ms, ns);
294          }
295      }
296 <
296 >    
297      /**
298 <     * Perform a <tt>Thread.sleep</tt> using the current time unit.
298 >     * Perform a <tt>Thread.sleep</tt> using this unit.
299       * This is a convenience method that converts time arguments into the
300       * form required by the <tt>Thread.sleep</tt> method.
301       * @param timeout the minimum time to sleep
# Line 145 | Line 304 | public final class TimeUnit implements j
304       */
305      public void sleep(long timeout) throws InterruptedException {
306          if (timeout > 0) {
307 <            long ms = MILLISECONDS.convert(timeout, this);
307 >            long ms = toMillis(timeout);
308              int ns = excessNanos(timeout, ms);
309              Thread.sleep(ms, ns);
310          }
311      }
312 <
154 <    /**
155 <     * Return the common name for this unit.
156 <     */
157 <    public String toString() {
158 <        return unitName;
159 <    }
160 <
161 <    private final String unitName;
162 <
163 <    /* ordered indices for each time unit */
164 <    private static final int NS = 0;
165 <    private static final int US = 1;
166 <    private static final int MS = 2;
167 <    private static final int S  = 3;
168 <
169 <    /** quick lookup table for conversion factors */
170 <    static final int[] multipliers = { 1,
171 <                                       1000,
172 <                                       1000*1000,
173 <                                       1000*1000*1000 };
174 <
175 <    /** lookup table to check saturation */
176 <    static final long[] overflows = {
177 <        // Note that because we are dividing these down anyway,
178 <        // we don't have to deal with asymmetry of MIN/MAX values.
179 <        0, // unused
180 <        Long.MAX_VALUE / 1000,
181 <        Long.MAX_VALUE / (1000 * 1000),
182 <        Long.MAX_VALUE / (1000 * 1000 * 1000) };
183 <
184 <    /** the index of this unit */
185 <    int index;
186 <
187 <    /** private constructor */
188 <    TimeUnit(int index, String name) {
189 <        this.index = index;
190 <        this.unitName = name;
191 <    }
192 <
193 <    /**
194 <     * Utility method to compute the excess-nanosecond argument to
195 <     * wait, sleep, join. The results may overflow, so public methods
196 <     * invoking this should document possible overflow unless
197 <     * overflow is known not to be possible for the given arguments.
198 <     */
199 <    private int excessNanos(long time, long ms) {
200 <        if (index == NS)
201 <            return (int) (time  - (ms * multipliers[MS-NS]));
202 <        else if (index == US)
203 <            return (int) ((time * multipliers[US-NS]) - (ms * multipliers[MS-NS]));
204 <        else
205 <            return 0;
206 <    }
207 <
208 <    /** Unit for one-second granularities. */
209 <    public static final TimeUnit SECONDS = new TimeUnit(S, "seconds");
210 <
211 <    /** Unit for one-millisecond granularities. */
212 <    public static final TimeUnit MILLISECONDS = new TimeUnit(MS, "milliseconds");
213 <
214 <    /** Unit for one-microsecond granularities. */
215 <    public static final TimeUnit MICROSECONDS = new TimeUnit(US, "microseconds");
216 <
217 <    /** Unit for one-nanosecond granularities. */
218 <    public static final TimeUnit NANOSECONDS = new TimeUnit(NS, "nanoseconds");
219 <
312 >    
313   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines