ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/TimeUnit.java
Revision: 1.13
Committed: Fri Sep 12 15:40:10 2003 UTC (20 years, 8 months ago) by dl
Branch: MAIN
Changes since 1.12: +85 -23 lines
Log Message:
Adapt AbstractQueue changes; Conditionalize CancellableTask.reset; new TimeUnit methods

File Contents

# User Rev Content
1 dl 1.2 /*
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     */
6    
7 tim 1.1 package java.util.concurrent;
8    
9     /**
10 tim 1.6 * 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 tim 1.1 * various contexts.
17     *
18 dl 1.12 * <p>This class cannot be directly instantiated. Use the {@link
19     * #SECONDS}, {@link #MILLISECONDS}, {@link #MICROSECONDS}, and {@link
20     * #NANOSECONDS} static instances that provide predefined units of
21     * precision. If you use these frequently, consider statically
22     * importing this class.
23 tim 1.1 *
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 tim 1.6 * the following code will timeout in 50 milliseconds if the {@link java.util.concurrent.locks.Lock lock}
27 tim 1.1 * is not available:
28     * <pre> Lock lock = ...;
29     * if ( lock.tryLock(50L, TimeUnit.MILLISECONDS) ) ...
30     * </pre>
31     * while this code will timeout in 50 seconds:
32 tim 1.6 * <pre>
33 tim 1.1 * Lock lock = ...;
34     * if ( lock.tryLock(50L, TimeUnit.SECONDS) ) ...
35     * </pre>
36     * Note however, that there is no guarantee that a particular lock, in this
37     * case, will be able to notice the passage of time at the same granularity
38     * as the given <tt>TimeUnit</tt>.
39     *
40     * @since 1.5
41 dl 1.4 * @author Doug Lea
42 tim 1.1 */
43     public final class TimeUnit implements java.io.Serializable {
44    
45     /**
46 dl 1.13 * Perform the conversion based on given index representing the
47     * difference between units
48     * @param delta the difference in index values of source and target units
49     * @param duration the duration
50     * @return converted duration or saturated value
51     */
52     private static long doConvert(int delta, long duration) {
53     if (delta == 0)
54     return duration;
55     if (delta < 0)
56     return duration / multipliers[-delta];
57     if (duration > overflows[delta])
58     return Long.MAX_VALUE;
59     if (duration < -overflows[delta])
60     return Long.MIN_VALUE;
61     return duration * multipliers[delta];
62     }
63    
64     /**
65 tim 1.1 * Convert the given time duration in the given unit to the
66     * current unit. Conversions from finer to coarser granulaties
67 dl 1.13 * truncate, so lose precision. For example converting
68     * <tt>999</tt> milliseconds to seconds results in
69     * <tt>0</tt>. Conversions from coarser to finer granularities
70     * with arguments that would numerically overflow saturate to
71     * <tt>Long.MIN_VALUE</tt> if negative or <tt>Long.MAX_VALUE</tt>
72     * if positive.
73 tim 1.1 *
74     * @param duration the time duration in the given <tt>unit</tt>
75     * @param unit the unit of the <tt>duration</tt> argument
76 dl 1.10 * @return the converted duration in the current unit,
77     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
78 dl 1.11 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
79 tim 1.1 */
80     public long convert(long duration, TimeUnit unit) {
81 dl 1.13 return doConvert(unit.index - index, duration);
82 dl 1.2 }
83    
84     /**
85 dl 1.12 * Equivalent to <tt>NANOSECONDS.convert(duration, this)</tt>.
86 dl 1.2 * @param duration the duration
87 dl 1.13 * @return the converted duration,
88 dl 1.10 * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
89 dl 1.11 * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
90 dl 1.13 * @see #convert
91     */
92 dl 1.2 public long toNanos(long duration) {
93 dl 1.13 return doConvert(index, duration);
94     }
95    
96     /**
97     * Equivalent to <tt>MICROSECONDS.convert(duration, this)</tt>.
98     * @param duration the duration
99     * @return the converted duration,
100     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
101     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
102     * @see #convert
103     */
104     public long toMicros(long duration) {
105     return doConvert(index - US, duration);
106     }
107    
108     /**
109     * Equivalent to <tt>MILLISECONDS.convert(duration, this)</tt>.
110     * @param duration the duration
111     * @return the converted duration,
112     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
113     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
114     * @see #convert
115     */
116     public long toMillis(long duration) {
117     return doConvert(index - MS, duration);
118     }
119    
120     /**
121     * Equivalent to <tt>SECONDS.convert(duration, this)</tt>.
122     * @param duration the duration
123     * @return the converted duration.
124     * @see #convert
125     */
126     public long toSeconds(long duration) {
127     return doConvert(index - S, duration);
128 tim 1.1 }
129 tim 1.6
130 tim 1.1 /**
131 tim 1.6 * Perform a timed <tt>Object.wait</tt> using the current time unit.
132 tim 1.1 * This is a convenience method that converts timeout arguments into the
133 dl 1.7 * form required by the <tt>Object.wait</tt> method.
134 tim 1.1 * <p>For example, you could implement a blocking <tt>poll</tt> method (see
135     * {@link BlockingQueue#poll BlockingQueue.poll} using:
136     * <pre> public synchronized Object poll(long timeout, TimeUnit unit) throws InterruptedException {
137     * while (empty) {
138     * unit.timedWait(this, timeout);
139     * ...
140     * }
141     * }</pre>
142     * @param obj the object to wait on
143 dl 1.10 * @param timeout the maximum time to wait.
144 tim 1.1 * @throws InterruptedException if interrupted while waiting.
145     * @see Object#wait(long, int)
146     */
147     public void timedWait(Object obj, long timeout)
148     throws InterruptedException {
149 dl 1.10 if (timeout > 0) {
150     long ms = MILLISECONDS.convert(timeout, this);
151     int ns = excessNanos(timeout, ms);
152     obj.wait(ms, ns);
153     }
154 tim 1.1 }
155    
156     /**
157     * Perform a timed <tt>Thread.join</tt> using the current time unit.
158     * This is a convenience method that converts time arguments into the
159     * form required by the <tt>Thread.join</tt> method.
160     * @param thread the thread to wait for
161     * @param timeout the maximum time to wait
162     * @throws InterruptedException if interrupted while waiting.
163     * @see Thread#join(long, int)
164     */
165     public void timedJoin(Thread thread, long timeout)
166     throws InterruptedException {
167 dl 1.10 if (timeout > 0) {
168     long ms = MILLISECONDS.convert(timeout, this);
169     int ns = excessNanos(timeout, ms);
170     thread.join(ms, ns);
171     }
172 tim 1.1 }
173 tim 1.6
174 tim 1.1 /**
175     * Perform a <tt>Thread.sleep</tt> using the current time unit.
176     * This is a convenience method that converts time arguments into the
177     * form required by the <tt>Thread.sleep</tt> method.
178 tim 1.6 * @param timeout the minimum time to sleep
179 tim 1.1 * @throws InterruptedException if interrupted while sleeping.
180     * @see Thread#sleep
181     */
182     public void sleep(long timeout) throws InterruptedException {
183 dl 1.10 if (timeout > 0) {
184     long ms = MILLISECONDS.convert(timeout, this);
185     int ns = excessNanos(timeout, ms);
186     Thread.sleep(ms, ns);
187     }
188 tim 1.1 }
189    
190 dl 1.9 /**
191     * Return the common name for this unit.
192     */
193     public String toString() {
194     return unitName;
195 dl 1.13 }
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 dl 1.9 }
217    
218     private final String unitName;
219    
220 tim 1.1 /* 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 dl 1.4 /** quick lookup table for conversion factors */
227 dl 1.10 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 tim 1.1
241 dl 1.4 /** the index of this unit */
242 tim 1.1 int index;
243    
244     /** private constructor */
245 dl 1.9 TimeUnit(int index, String name) {
246     this.index = index;
247     this.unitName = name;
248     }
249 tim 1.1
250 tim 1.6 /**
251 tim 1.1 * Utility method to compute the excess-nanosecond argument to
252 dl 1.7 * 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 tim 1.1 */
256     private int excessNanos(long time, long ms) {
257 tim 1.6 if (index == NS)
258 tim 1.1 return (int) (time - (ms * multipliers[MS-NS]));
259 tim 1.6 else if (index == US)
260 tim 1.1 return (int) ((time * multipliers[US-NS]) - (ms * multipliers[MS-NS]));
261 tim 1.6 else
262 tim 1.1 return 0;
263     }
264    
265 tim 1.8 /** Unit for one-second granularities. */
266 dl 1.9 public static final TimeUnit SECONDS = new TimeUnit(S, "seconds");
267 tim 1.1
268 tim 1.8 /** Unit for one-millisecond granularities. */
269 dl 1.9 public static final TimeUnit MILLISECONDS = new TimeUnit(MS, "milliseconds");
270 tim 1.1
271 tim 1.8 /** Unit for one-microsecond granularities. */
272 dl 1.9 public static final TimeUnit MICROSECONDS = new TimeUnit(US, "microseconds");
273 tim 1.1
274 tim 1.8 /** Unit for one-nanosecond granularities. */
275 dl 1.9 public static final TimeUnit NANOSECONDS = new TimeUnit(NS, "nanoseconds");
276 tim 1.1
277     }