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.21 by dl, Mon Feb 9 00:23:55 2004 UTC vs.
Revision 1.22 by dl, Thu Dec 30 13:04:46 2004 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, as explained at
4 < * http://creativecommons.org/licenses/publicdomain
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.  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.
16 < *
17 < * <p>A <tt>TimeUnit</tt> is mainly used to inform time-based methods
18 < * how a given timing parameter should be interpreted. For example,
19 < * the following code will timeout in 50 milliseconds if the {@link
20 < * java.util.concurrent.locks.Lock lock} is not available:
21 < *
22 < * <pre>  Lock lock = ...;
23 < *  if ( lock.tryLock(50L, TimeUnit.MILLISECONDS) ) ...
24 < * </pre>
25 < * while this code will timeout in 50 seconds:
26 < * <pre>
27 < *  Lock lock = ...;
28 < *  if ( lock.tryLock(50L, TimeUnit.SECONDS) ) ...
29 < * </pre>
30 < *
31 < * Note however, that there is no guarantee that a particular timeout
32 < * implementation will be able to notice the passage of time at the
33 < * same granularity as the given <tt>TimeUnit</tt>.
34 < *
35 < * @since 1.5
36 < * @author Doug Lea
37 < */
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.  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
16 >  * one-billionth of a second, a microsecond is one-millionth of a
17 >  * second, a millisecond is one-thousandth of a second, a minute is
18 >  * sixty seconds, an hour is sixty minutes, and a day is twenty four
19 >  * hours.
20 >  *
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 >  *
26 >  * <pre>  Lock lock = ...;
27 >  *  if ( lock.tryLock(50L, TimeUnit.MILLISECONDS) ) ...
28 >  * </pre>
29 >  * while this code will timeout in 50 seconds:
30 >  * <pre>
31 >  *  Lock lock = ...;
32 >  *  if ( lock.tryLock(50L, TimeUnit.SECONDS) ) ...
33 >  * </pre>
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 enum TimeUnit {
43 <    NANOSECONDS(0), MICROSECONDS(1), MILLISECONDS(2), SECONDS(3);
44 <
45 <    /** the index of this unit */
46 <    private final int index;
47 <
48 <    /** Internal constructor */
49 <    TimeUnit(int index) {
50 <        this.index = index;
51 <    }
52 <
53 <    /** Lookup table for conversion factors */
54 <    private static final int[] multipliers = {
55 <        1,
56 <        1000,
57 <        1000 * 1000,
58 <        1000 * 1000 * 1000
59 <    };
60 <    
61 <    /**
62 <     * Lookup table to check saturation.  Note that because we are
63 <     * dividing these down, we don't have to deal with asymmetry of
64 <     * MIN/MAX values.
65 <     */
66 <    private static final long[] overflows = {
67 <        0, // unused
68 <        Long.MAX_VALUE / 1000,
69 <        Long.MAX_VALUE / (1000 * 1000),
70 <        Long.MAX_VALUE / (1000 * 1000 * 1000)
71 <    };
72 <
73 <    /**
74 <     * Perform conversion based on given delta representing the
75 <     * difference between units
76 <     * @param delta the difference in index values of source and target units
77 <     * @param duration the duration
78 <     * @return converted duration or saturated value
79 <     */
80 <    private static long doConvert(int delta, long duration) {
81 <        if (delta == 0)
82 <            return duration;
83 <        if (delta < 0)
84 <            return duration / multipliers[-delta];
85 <        if (duration > overflows[delta])
86 <            return Long.MAX_VALUE;
87 <        if (duration < -overflows[delta])
88 <            return Long.MIN_VALUE;
89 <        return duration * multipliers[delta];
90 <    }
91 <
92 <    /**
93 <     * Convert the given time duration in the given unit to this
94 <     * unit.  Conversions from finer to coarser granularities
95 <     * truncate, so lose precision. For example converting
96 <     * <tt>999</tt> milliseconds to seconds results in
97 <     * <tt>0</tt>. Conversions from coarser to finer granularities
98 <     * with arguments that would numerically overflow saturate to
99 <     * <tt>Long.MIN_VALUE</tt> if negative or <tt>Long.MAX_VALUE</tt>
100 <     * if positive.
101 <     *
102 <     * @param duration the time duration in the given <tt>unit</tt>
103 <     * @param unit the unit of the <tt>duration</tt> argument
104 <     * @return the converted duration in this unit,
105 <     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
106 <     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
107 <     */
108 <    public long convert(long duration, TimeUnit unit) {
109 <        return doConvert(unit.index - index, duration);
110 <    }
111 <
112 <    /**
113 <     * Equivalent to <tt>NANOSECONDS.convert(duration, this)</tt>.
114 <     * @param duration the duration
115 <     * @return the converted duration,
116 <     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
117 <     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
118 <     * @see #convert
119 <     */
120 <    public long toNanos(long duration) {
121 <        return doConvert(index, duration);
122 <    }
123 <
124 <    /**
125 <     * Equivalent to <tt>MICROSECONDS.convert(duration, this)</tt>.
126 <     * @param duration the duration
127 <     * @return the converted duration,
128 <     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
129 <     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
130 <     * @see #convert
131 <     */
132 <    public long toMicros(long duration) {
133 <        return doConvert(index - MICROSECONDS.index, duration);
134 <    }
135 <
136 <    /**
137 <     * Equivalent to <tt>MILLISECONDS.convert(duration, this)</tt>.
138 <     * @param duration the duration
139 <     * @return the converted duration,
140 <     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
141 <     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
142 <     * @see #convert
143 <     */
144 <    public long toMillis(long duration) {
145 <        return doConvert(index - MILLISECONDS.index, duration);
146 <    }
147 <
148 <    /**
149 <     * Equivalent to <tt>SECONDS.convert(duration, this)</tt>.
150 <     * @param duration the duration
151 <     * @return the converted duration.
152 <     * @see #convert
153 <     */
154 <    public long toSeconds(long duration) {
155 <        return doConvert(index - SECONDS.index, duration);
156 <    }
157 <
158 <
159 <    /**
160 <     * Utility method to compute the excess-nanosecond argument to
161 <     * wait, sleep, join.
162 <     */
163 <    private int excessNanos(long time, long ms) {
164 <        if (this == NANOSECONDS)
165 <            return (int) (time  - (ms * 1000 * 1000));
166 <        if (this == MICROSECONDS)
167 <            return (int) ((time * 1000) - (ms * 1000 * 1000));
168 <        return 0;
169 <    }
170 <
171 <    /**
172 <     * Perform a timed <tt>Object.wait</tt> using this time unit.
173 <     * This is a convenience method that converts timeout arguments
174 <     * into the form required by the <tt>Object.wait</tt> method.
175 <     *
176 <     * <p>For example, you could implement a blocking <tt>poll</tt>
177 <     * method (see {@link BlockingQueue#poll BlockingQueue.poll})
178 <     * using:
179 <     *
180 <     * <pre>  public synchronized  Object poll(long timeout, TimeUnit unit) throws InterruptedException {
181 <     *    while (empty) {
182 <     *      unit.timedWait(this, timeout);
183 <     *      ...
184 <     *    }
185 <     *  }</pre>
186 <     *
187 <     * @param obj the object to wait on
188 <     * @param timeout the maximum time to wait.
189 <     * @throws InterruptedException if interrupted while waiting.
190 <     * @see Object#wait(long, int)
191 <     */
192 <    public void timedWait(Object obj, long timeout)
193 <        throws InterruptedException {
194 <        if (timeout > 0) {
195 <            long ms = toMillis(timeout);
196 <            int ns = excessNanos(timeout, ms);
197 <            obj.wait(ms, ns);
198 <        }
199 <    }
200 <
201 <    /**
202 <     * Perform a timed <tt>Thread.join</tt> using this time unit.
203 <     * This is a convenience method that converts time arguments into the
204 <     * form required by the <tt>Thread.join</tt> method.
205 <     * @param thread the thread to wait for
206 <     * @param timeout the maximum time to wait
207 <     * @throws InterruptedException if interrupted while waiting.
208 <     * @see Thread#join(long, int)
209 <     */
210 <    public void timedJoin(Thread thread, long timeout)
211 <        throws InterruptedException {
212 <        if (timeout > 0) {
213 <            long ms = toMillis(timeout);
214 <            int ns = excessNanos(timeout, ms);
215 <            thread.join(ms, ns);
216 <        }
217 <    }
218 <
219 <    /**
220 <     * Perform a <tt>Thread.sleep</tt> using this unit.
221 <     * This is a convenience method that converts time arguments into the
222 <     * form required by the <tt>Thread.sleep</tt> method.
223 <     * @param timeout the minimum time to sleep
224 <     * @throws InterruptedException if interrupted while sleeping.
225 <     * @see Thread#sleep
226 <     */
227 <    public void sleep(long timeout) throws InterruptedException {
228 <        if (timeout > 0) {
229 <            long ms = toMillis(timeout);
230 <            int ns = excessNanos(timeout, ms);
231 <            Thread.sleep(ms, ns);
232 <        }
233 <    }
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 = 1;
135 >     static final long C1 = C0 * 1000;
136 >     static final long C2 = C1 * 1000;
137 >     static final long C3 = C2 * 1000;
138 >     static final long C4 = C3 * 60;
139 >     static final long C5 = C4 * 60;
140 >     static final long C6 = C5 * 24;
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 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 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 abstract long convert(long duration, TimeUnit unit);
171 >
172 >     /**
173 >      * Equivalent to <tt>NANOSECONDS.convert(duration, this)</tt>.
174 >      * @param duration the 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 >      * @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 >      * @see #convert
207 >      */
208 >     public abstract long toSeconds(long duration);
209 >
210 >     /**
211 >      * Equivalent to <tt>MINUTES.convert(duration, this)</tt>.
212 >      * @param duration the duration
213 >      * @return the converted duration.
214 >      * @see #convert
215 >      */
216 >     public abstract long toMinutes(long duration);
217 >
218 >     /**
219 >      * Equivalent to <tt>HOURS.convert(duration, this)</tt>.
220 >      * @param duration the duration
221 >      * @return the converted duration.
222 >      * @see #convert
223 >      */
224 >     public abstract long toHours(long duration);
225 >
226 >     /**
227 >      * Equivalent to <tt>DAYS.convert(duration, this)</tt>.
228 >      * @param duration the duration
229 >      * @return the converted duration.
230 >      * @see #convert
231 >      */
232 >     public abstract long toDays(long duration);
233 >
234 >     /**
235 >      * Utility to compute the excess-nanosecond argument to wait,
236 >      * sleep, join.
237 >      * @param d the duration
238 >      * @param m the number of millisecondss
239 >      * @return the number of nanoseconds
240 >      */
241 >     abstract int excessNanos(long d, long m);
242 >
243 >     /**
244 >      * Perform a timed <tt>Object.wait</tt> using this time unit.
245 >      * This is a convenience method that converts timeout arguments
246 >      * into the form required by the <tt>Object.wait</tt> method.
247 >      *
248 >      * <p>For example, you could implement a blocking <tt>poll</tt>
249 >      * method (see {@link BlockingQueue#poll BlockingQueue.poll})
250 >      * using:
251 >      *
252 >      * <pre>  public synchronized  Object poll(long timeout, TimeUnit unit) throws InterruptedException {
253 >      *    while (empty) {
254 >      *      unit.timedWait(this, timeout);
255 >      *      ...
256 >      *    }
257 >      *  }</pre>
258 >      *
259 >      * @param obj the object to wait on
260 >      * @param timeout the maximum time to wait.
261 >      * @throws InterruptedException if interrupted while waiting.
262 >      * @see Object#wait(long, int)
263 >      */
264 >     public void timedWait(Object obj, long timeout)
265 >         throws InterruptedException {
266 >         if (timeout > 0) {
267 >             long ms = toMillis(timeout);
268 >             int ns = excessNanos(timeout, ms);
269 >             obj.wait(ms, ns);
270 >         }
271 >     }
272 >
273 >     /**
274 >      * Perform a timed <tt>Thread.join</tt> using this time unit.
275 >      * This is a convenience method that converts time arguments into the
276 >      * form required by the <tt>Thread.join</tt> method.
277 >      * @param thread the thread to wait for
278 >      * @param timeout the maximum time to wait
279 >      * @throws InterruptedException if interrupted while waiting.
280 >      * @see Thread#join(long, int)
281 >      */
282 >     public void timedJoin(Thread thread, long timeout)
283 >         throws InterruptedException {
284 >         if (timeout > 0) {
285 >             long ms = toMillis(timeout);
286 >             int ns = excessNanos(timeout, ms);
287 >             thread.join(ms, ns);
288 >         }
289 >     }
290 >
291 >     /**
292 >      * Perform a <tt>Thread.sleep</tt> using this unit.
293 >      * This is a convenience method that converts time arguments into the
294 >      * form required by the <tt>Thread.sleep</tt> method.
295 >      * @param timeout the minimum time to sleep
296 >      * @throws InterruptedException if interrupted while sleeping.
297 >      * @see Thread#sleep
298 >      */
299 >     public void sleep(long timeout) throws InterruptedException {
300 >         if (timeout > 0) {
301 >             long ms = toMillis(timeout);
302 >             int ns = excessNanos(timeout, ms);
303 >             Thread.sleep(ms, ns);
304 >         }
305 >     }
306  
307   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines