001: /*
002: * Written by Dawid Kurzyniec, based on code written by Doug Lea with assistance
003: * from members of JCP JSR-166 Expert Group. Released to the public domain,
004: * as explained at http://creativecommons.org/licenses/publicdomain.
005: *
006: * Thanks to Craig Mattocks for suggesting to use <code>sun.misc.Perf</code>.
007: */
008:
009: package org.apache.beehive.netui.util.internal.concurrent;
010:
011: import java.security.AccessController;
012: import java.security.PrivilegedAction;
013:
014: /**
015: * <p>
016: * This class groups together the functionality of java.util.concurrent that
017: * cannot be fully and reliably implemented in backport, but for which some
018: * form of emulation is possible.
019: * <p>
020: * Currently, this class contains methods related to nanosecond-precision
021: * timing, particularly via the {@link #nanoTime} method. To measure time
022: * accurately, this method by default uses <code>java.sun.Perf</code> on
023: * JDK1.4.2 and it falls back to <code>System.currentTimeMillis</code>
024: * on earlier JDKs.
025: *
026: * @author Dawid Kurzyniec
027: * @version 1.0
028: */
029: final class Utils {
030:
031: private final static NanoTimer nanoTimer;
032: private final static String providerProp = "org.apache.beehive.netui.util.concurrent.NanoTimerProvider";
033:
034: static {
035: NanoTimer timer = null;
036: try {
037: String nanoTimerClassName = (String) AccessController
038: .doPrivileged(new PrivilegedAction() {
039: public Object run() {
040: return System.getProperty(providerProp);
041: }
042: });
043: if (nanoTimerClassName != null) {
044: Class cls = Class.forName(nanoTimerClassName);
045: timer = (NanoTimer) cls.newInstance();
046: }
047: } catch (Exception e) {
048: System.err
049: .println("WARNING: unable to load Perf provider; "
050: + "switching to a default");
051: e.printStackTrace();
052: }
053:
054: if (timer == null) {
055: try {
056: timer = new SunPerfProvider();
057: } catch (Throwable e) {
058: }
059: }
060:
061: if (timer == null) {
062: timer = new MillisProvider();
063: }
064:
065: nanoTimer = timer;
066: }
067:
068: private Utils() {
069: }
070:
071: /**
072: * Returns the current value of the most precise available system timer,
073: * in nanoseconds. This method can only be used to measure elapsed time and
074: * is not related to any other notion of system or wall-clock time. The
075: * value returned represents nanoseconds since some fixed but arbitrary
076: * time (perhaps in the future, so values may be negative). This method
077: * provides nanosecond precision, but not necessarily nanosecond accuracy.
078: * No guarantees are made about how frequently values change. Differences
079: * in successive calls that span greater than approximately 292 years
080: * (263 nanoseconds) will not accurately compute elapsed time due to
081: * numerical overflow.
082: * <p>
083: * <em>Implementation note:</em>By default, this method uses
084: * <code>sun.misc.Perf</code> on Java 1.4.2, and falls back to
085: * System.currentTimeMillis() emulation on earlier JDKs. Custom
086: * timer can be provided via the system property
087: * <code>org.apache.beehive.netui.util.concurrent.NanoTimerProvider</code>.
088: * The value of the property should name a class implementing
089: * {@link NanoTimer} interface.
090: * <p>
091: * Note: on JDK 1.4.2, <code>sun.misc.Perf</code> timer seems to have
092: * resolution of the order of 1 microsecond, measured on Linux.
093: *
094: * @return The current value of the system timer, in nanoseconds.
095: */
096: public static long nanoTime() {
097: return nanoTimer.nanoTime();
098: }
099:
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 "<em>spurious wakeup</em>" 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 > 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 {
192: if (nanosTimeout <= 0)
193: 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:
203: SunPerfProvider() {
204: perf = (sun.misc.Perf) AccessController
205: .doPrivileged(new PrivilegedAction() {
206: public Object run() {
207: return sun.misc.Perf.getPerf();
208: }
209: });
210: // trying to avoid BOTH overflow and rounding errors
211: long numerator = 1000000000;
212: long denominator = perf.highResFrequency();
213: long gcd = gcd(numerator, denominator);
214: this .multiplier = numerator / gcd;
215: this .divisor = denominator / gcd;
216: }
217:
218: public long nanoTime() {
219: long ctr = perf.highResCounter();
220:
221: // anything less sophisticated suffers either from rounding errors
222: // (FP arithmetics, backport v1.0) or overflow, when gcd is small
223: // (a bug in backport v1.0_01 reported by Ramesh Nethi)
224:
225: return ((ctr / divisor) * multiplier) + (ctr % divisor)
226: * multiplier / divisor;
227:
228: // even the above can theoretically cause problems if your JVM is
229: // running for sufficiently long time, but "sufficiently" means 292
230: // years (worst case), or 30,000 years (common case).
231:
232: // Details: when the ticks ctr overflows, there is no way to avoid
233: // discontinuity in computed nanos, even in infinite arithmetics,
234: // unless we count number of overflows that the ctr went through
235: // since the JVM started. This follows from the fact that
236: // (2^64*multiplier/divisor) mod (2^64) > 0 in general case.
237: // Theoretically we could find out the number of overflows by
238: // checking System.currentTimeMillis(), but this is unreliable
239: // since the system time can unpredictably change during the JVM
240: // lifetime.
241: // The time to overflow is 2^63 / ticks frequency. With current
242: // ticks frequencies of several MHz, it gives about 30,000 years
243: // before the problem happens. If ticks frequency reaches 1 GHz, the
244: // time to overflow is 292 years. It is unlikely that the frequency
245: // ever exceeds 1 GHz. We could double the time to overflow
246: // (to 2^64 / frequency) by using unsigned arithmetics, e.g. by
247: // adding the following correction whenever the ticks is negative:
248: // -2*((Long.MIN_VALUE / divisor) * multiplier +
249: // (Long.MIN_VALUE % divisor) * multiplier / divisor)
250: // But, with the worst case of as much as 292 years, it does not
251: // seem justified.
252: }
253: }
254:
255: private static final class MillisProvider implements NanoTimer {
256: MillisProvider() {
257: }
258:
259: public long nanoTime() {
260: return System.currentTimeMillis() * 1000000;
261: }
262: }
263:
264: private static long gcd(long a, long b) {
265: long r;
266: while (b > 0) {
267: r = a % b;
268: a = b;
269: b = r;
270: }
271: return a;
272: }
273:
274: }
|