KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > beehive > netui > util > internal > concurrent > Utils


1 /*
2  * Written by Dawid Kurzyniec, based on code written by Doug Lea with assistance
3  * from members of JCP JSR-166 Expert Group. Released to the public domain,
4  * as explained at http://creativecommons.org/licenses/publicdomain.
5  *
6  * Thanks to Craig Mattocks for suggesting to use <code>sun.misc.Perf</code>.
7  */

8
9 package org.apache.beehive.netui.util.internal.concurrent;
10
11 import java.security.AccessController JavaDoc;
12 import java.security.PrivilegedAction JavaDoc;
13
14 /**
15  * <p>
16  * This class groups together the functionality of java.util.concurrent that
17  * cannot be fully and reliably implemented in backport, but for which some
18  * form of emulation is possible.
19  * <p>
20  * Currently, this class contains methods related to nanosecond-precision
21  * timing, particularly via the {@link #nanoTime} method. To measure time
22  * accurately, this method by default uses <code>java.sun.Perf</code> on
23  * JDK1.4.2 and it falls back to <code>System.currentTimeMillis</code>
24  * on earlier JDKs.
25  *
26  * @author Dawid Kurzyniec
27  * @version 1.0
28  */

29 final class Utils {
30
31     private final static NanoTimer nanoTimer;
32     private final static String JavaDoc providerProp =
33         "org.apache.beehive.netui.util.concurrent.NanoTimerProvider";
34
35     static {
36         NanoTimer timer = null;
37         try {
38             String JavaDoc nanoTimerClassName = (String JavaDoc)
39                 AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
40                     public Object JavaDoc run() {
41                         return System.getProperty(providerProp);
42                     }
43                 });
44             if (nanoTimerClassName != null) {
45                 Class JavaDoc cls = Class.forName(nanoTimerClassName);
46                 timer = (NanoTimer) cls.newInstance();
47             }
48         }
49         catch (Exception JavaDoc e) {
50             System.err.println("WARNING: unable to load Perf provider; " +
51                                "switching to a default");
52             e.printStackTrace();
53         }
54
55         if (timer == null) {
56             try {
57                 timer = new SunPerfProvider();
58             }
59             catch (Throwable JavaDoc e) {}
60         }
61
62         if (timer == null) {
63             timer = new MillisProvider();
64         }
65
66         nanoTimer = timer;
67     }
68
69     private Utils() {}
70
71     /**
72      * Returns the current value of the most precise available system timer,
73      * in nanoseconds. This method can only be used to measure elapsed time and
74      * is not related to any other notion of system or wall-clock time. The
75      * value returned represents nanoseconds since some fixed but arbitrary
76      * time (perhaps in the future, so values may be negative). This method
77      * provides nanosecond precision, but not necessarily nanosecond accuracy.
78      * No guarantees are made about how frequently values change. Differences
79      * in successive calls that span greater than approximately 292 years
80      * (263 nanoseconds) will not accurately compute elapsed time due to
81      * numerical overflow.
82      * <p>
83      * <em>Implementation note:</em>By default, this method uses
84      * <code>sun.misc.Perf</code> on Java 1.4.2, and falls back to
85      * System.currentTimeMillis() emulation on earlier JDKs. Custom
86      * timer can be provided via the system property
87      * <code>org.apache.beehive.netui.util.concurrent.NanoTimerProvider</code>.
88      * The value of the property should name a class implementing
89      * {@link NanoTimer} interface.
90      * <p>
91      * Note: on JDK 1.4.2, <code>sun.misc.Perf</code> timer seems to have
92      * resolution of the order of 1 microsecond, measured on Linux.
93      *
94      * @return The current value of the system timer, in nanoseconds.
95      */

96     public static long nanoTime() {
97         return nanoTimer.nanoTime();
98     }
99
100     /**
101      * Causes the current thread to wait until it is signalled or interrupted,
102      * or the specified waiting time elapses. This method originally appears
103      * in the {@link Condition} interface, but it was moved to here since it
104      * can only be emulated, with very little accuracy guarantees: the
105      * efficient implementation requires accurate nanosecond timer and native
106      * support for nanosecond-precision wait queues, which are not usually
107      * present in JVMs prior to 1.5. Loss of precision may cause total waiting
108      * times to be systematically shorter than specified when re-waits occur.
109      *
110      * <p>The lock associated with this condition is atomically
111      * released and the current thread becomes disabled for thread scheduling
112      * purposes and lies dormant until <em>one</em> of five things happens:
113      * <ul>
114      * <li>Some other thread invokes the {@link
115      * org.apache.beehive.netui.util.concurrent.locks.Condition#signal}
116      * method for this
117      * <tt>Condition</tt> and the current thread happens to be chosen as the
118      * thread to be awakened; or
119      * <li>Some other thread invokes the {@link
120      * org.apache.beehive.netui.util.concurrent.locks.Condition#signalAll}
121      * method for this
122      * <tt>Condition</tt>; or
123      * <li>Some other thread {@link Thread#interrupt interrupts} the current
124      * thread, and interruption of thread suspension is supported; or
125      * <li>The specified waiting time elapses; or
126      * <li>A &quot;<em>spurious wakeup</em>&quot; occurs.
127      * </ul>
128      *
129      * <p>In all cases, before this method can return the current thread must
130      * re-acquire the lock associated with this condition. When the
131      * thread returns it is <em>guaranteed</em> to hold this lock.
132      *
133      * <p>If the current thread:
134      * <ul>
135      * <li>has its interrupted status set on entry to this method; or
136      * <li>is {@link Thread#interrupt interrupted} while waiting
137      * and interruption of thread suspension is supported,
138      * </ul>
139      * then {@link InterruptedException} is thrown and the current thread's
140      * interrupted status is cleared. It is not specified, in the first
141      * case, whether or not the test for interruption occurs before the lock
142      * is released.
143      *
144      * <p>The method returns an estimate of the number of nanoseconds
145      * remaining to wait given the supplied <tt>nanosTimeout</tt>
146      * value upon return, or a value less than or equal to zero if it
147      * timed out. Accuracy of this estimate is directly dependent on the
148      * accuracy of {@link #nanoTime}. This value can be used to determine
149      * whether and how long to re-wait in cases where the wait returns but an
150      * awaited condition still does not hold. Typical uses of this method take
151      * the following form:
152      *
153      * <pre>
154      * synchronized boolean aMethod(long timeout, TimeUnit unit) {
155      * long nanosTimeout = unit.toNanos(timeout);
156      * while (!conditionBeingWaitedFor) {
157      * if (nanosTimeout &gt; 0)
158      * nanosTimeout = theCondition.awaitNanos(nanosTimeout);
159      * else
160      * return false;
161      * }
162      * // ...
163      * }
164      * </pre>
165      *
166      * <p><b>Implementation Considerations</b>
167      * <p>The current thread is assumed to hold the lock associated with this
168      * <tt>Condition</tt> when this method is called.
169      * It is up to the implementation to determine if this is
170      * the case and if not, how to respond. Typically, an exception will be
171      * thrown (such as {@link IllegalMonitorStateException}) and the
172      * implementation must document that fact.
173      *
174      * <p>A condition implementation can favor responding to an interrupt over
175      * normal method return in response to a signal, or over indicating the
176      * elapse of the specified waiting time. In either case the implementation
177      * must ensure that the signal is redirected to another waiting thread, if
178      * there is one.
179      *
180      * @param cond the condition to wait for
181      * @param nanosTimeout the maximum time to wait, in nanoseconds
182      * @return A value less than or equal to zero if the wait has
183      * timed out; otherwise an estimate, that
184      * is strictly less than the <tt>nanosTimeout</tt> argument,
185      * of the time still remaining when this method returned.
186      *
187      * @throws InterruptedException if the current thread is interrupted (and
188      * interruption of thread suspension is supported).
189      */

190     public static long awaitNanos(Condition cond, long nanosTimeout)
191         throws InterruptedException JavaDoc
192     {
193         if (nanosTimeout <= 0) return nanosTimeout;
194         long now = nanoTime();
195         cond.await(nanosTimeout, TimeUnit.NANOSECONDS);
196         return nanosTimeout - (nanoTime() - now);
197     }
198
199     private static final class SunPerfProvider implements NanoTimer {
200         final sun.misc.Perf perf;
201         final long multiplier, divisor;
202         SunPerfProvider() {
203             perf = (sun.misc.Perf)
204                 AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
205                     public Object JavaDoc run() {
206                         return sun.misc.Perf.getPerf();
207                     }
208                 });
209             // trying to avoid BOTH overflow and rounding errors
210
long numerator = 1000000000;
211             long denominator = perf.highResFrequency();
212             long gcd = gcd(numerator, denominator);
213             this.multiplier = numerator / gcd;
214             this.divisor = denominator / gcd;
215         }
216         public long nanoTime() {
217             long ctr = perf.highResCounter();
218
219             // anything less sophisticated suffers either from rounding errors
220
// (FP arithmetics, backport v1.0) or overflow, when gcd is small
221
// (a bug in backport v1.0_01 reported by Ramesh Nethi)
222

223             return ((ctr / divisor) * multiplier) +
224                     (ctr % divisor) * multiplier / divisor;
225
226             // even the above can theoretically cause problems if your JVM is
227
// running for sufficiently long time, but "sufficiently" means 292
228
// years (worst case), or 30,000 years (common case).
229

230             // Details: when the ticks ctr overflows, there is no way to avoid
231
// discontinuity in computed nanos, even in infinite arithmetics,
232
// unless we count number of overflows that the ctr went through
233
// since the JVM started. This follows from the fact that
234
// (2^64*multiplier/divisor) mod (2^64) > 0 in general case.
235
// Theoretically we could find out the number of overflows by
236
// checking System.currentTimeMillis(), but this is unreliable
237
// since the system time can unpredictably change during the JVM
238
// lifetime.
239
// The time to overflow is 2^63 / ticks frequency. With current
240
// ticks frequencies of several MHz, it gives about 30,000 years
241
// before the problem happens. If ticks frequency reaches 1 GHz, the
242
// time to overflow is 292 years. It is unlikely that the frequency
243
// ever exceeds 1 GHz. We could double the time to overflow
244
// (to 2^64 / frequency) by using unsigned arithmetics, e.g. by
245
// adding the following correction whenever the ticks is negative:
246
// -2*((Long.MIN_VALUE / divisor) * multiplier +
247
// (Long.MIN_VALUE % divisor) * multiplier / divisor)
248
// But, with the worst case of as much as 292 years, it does not
249
// seem justified.
250
}
251     }
252
253     private static final class MillisProvider implements NanoTimer {
254         MillisProvider() {}
255         public long nanoTime() {
256             return System.currentTimeMillis() * 1000000;
257         }
258     }
259
260     private static long gcd(long a, long b) {
261         long r;
262         while (b>0) { r = a % b; a = b; b = r; }
263         return a;
264     }
265
266 }
267
Popular Tags