You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pc...@apache.org on 2006/07/01 00:37:29 UTC
svn commit: r418401 [17/32] - in /incubator/openjpa/trunk: openjpa-lib/
openjpa-lib/src/main/java/org/apache/openjpa/lib/ant/
openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/
openjpa-lib/src/main/java/org/apache/openjpa/lib/jdbc/ openjpa-lib/src/...
Modified: incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/ReentrantLock.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/ReentrantLock.java?rev=418401&r1=418400&r2=418401&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/ReentrantLock.java (original)
+++ incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/ReentrantLock.java Fri Jun 30 15:37:18 2006
@@ -1,19 +1,15 @@
/*
* Copyright 2006 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
/*
* Written by Doug Lea with assistance from members of JCP JSR-166
* Expert Group and released to the public domain, as explained at
@@ -23,72 +19,53 @@
import java.util.*;
-
/**
* A reentrant mutual exclusion {@link Lock} with the same basic
* behavior and semantics as the implicit monitor lock accessed using
- * <tt>synchronized</tt> methods and statements, but with extended
- * capabilities.
- *
- * <p> A <tt>ReentrantLock</tt> is <em>owned</em> by the thread last
+ * <tt>synchronized</tt> methods and statements, but with extended capabilities.
+ * A <tt>ReentrantLock</tt> is <em>owned</em> by the thread last
* successfully locking, but not yet unlocking it. A thread invoking
* <tt>lock</tt> will return, successfully acquiring the lock, when
* the lock is not owned by another thread. The method will return
* immediately if the current thread already owns the lock. This can
* be checked using methods {@link #isHeldByCurrentThread}, and {@link
* #getHoldCount}.
- *
- * <p> The constructor for this class accepts an optional
- * <em>fairness</em> parameter. When set <tt>true</tt>, under
+ * The constructor for this class accepts an optional
+ * <em>fairness</em> parameter. When set <tt>true</tt>, under
* contention, locks favor granting access to the longest-waiting
- * thread. Otherwise this lock does not guarantee any particular
- * access order. Programs using fair locks accessed by many threads
- * may display lower overall throughput (i.e., are slower; often much
+ * thread. Otherwise this lock does not guarantee any particular
+ * access order. Programs using fair locks accessed by many threads
+ * may display lower overall throughput(i.e., are slower; often much
* slower) than those using the default setting, but have smaller
* variances in times to obtain locks and guarantee lack of
* starvation. Note however, that fairness of locks does not guarantee
* fairness of thread scheduling. Thus, one of many threads using a
* fair lock may obtain it multiple times in succession while other
- * active threads are not progressing and not currently holding the
- * lock.
+ * active threads are not progressing and not currently holding the lock.
* Also note that the untimed {@link #tryLock() tryLock} method does not
* honor the fairness setting. It will succeed if the lock
* is available even if other threads are waiting.
- *
- * <p> It is recommended practice to <em>always</em> immediately
+ * It is recommended practice to <em>always</em> immediately
* follow a call to <tt>lock</tt> with a <tt>try</tt> block, most
* typically in a before/after construction such as:
- *
- * <pre>
- * class X {
- * private final ReentrantLock lock = new ReentrantLock();
- * // ...
- *
- * public void m() {
- * lock.lock(); // block until condition holds
- * try {
- * // ... method body
- * } finally {
- * lock.unlock()
- * }
- * }
- * }
+ *
+ * <pre> class X { private final ReentrantLock lock = new ReentrantLock();
+ * // ...
+ * public void m() { lock.lock(); // block until condition holds try {
+ * // ... method body } finally { lock.unlock() } } }
* </pre>
- *
- * <p>In addition to implementing the {@link Lock} interface, this
+ * In addition to implementing the {@link Lock} interface, this
* class defines methods <tt>isLocked</tt> and
* <tt>getLockQueueLength</tt>, as well as some associated
* <tt>protected</tt> access methods that may be useful for
* instrumentation and monitoring.
- *
- * <p> Serialization of this class behaves in the same way as built-in
+ * Serialization of this class behaves in the same way as built-in
* locks: a deserialized lock is in the unlocked state, regardless of
* its state when serialized.
- *
- * <p> This lock supports a maximum of 2147483647 recursive locks by
+ * This lock supports a maximum of 2147483647 recursive locks by
* the same thread. Attempts to exceed this limit result in
* {@link Error} throws from locking methods.
- *
+ *
* @since 1.5
* @author Doug Lea
* @author Dawid Kurzyniec
@@ -96,584 +73,60 @@
public class ReentrantLock implements Lock, java.io.Serializable,
CondVar.ExclusiveLock {
private static final long serialVersionUID = 7373984872572414699L;
+
private final Sync sync;
- /**
- * Creates an instance of <tt>ReentrantLock</tt>.
- * This is equivalent to using <tt>ReentrantLock(false)</tt>.
- */
- public ReentrantLock() {
- sync = new NonfairSync();
- }
+ static abstract class Sync implements java.io.Serializable {
+ private static final long serialVersionUID = -5179523762034025860L;
- /**
- * Creates an instance of <tt>ReentrantLock</tt> with the
- * given fairness policy.
- * @param fair true if this lock will be fair; else false
- */
- public ReentrantLock(boolean fair) {
- sync = (fair) ? (Sync) new FairSync() : new NonfairSync();
- }
+ protected transient Thread owner_ = null;
+ protected transient int holds_ = 0;
- /**
- * Acquires the lock.
- *
- * <p>Acquires the lock if it is not held by another thread and returns
- * immediately, setting the lock hold count to one.
- *
- * <p>If the current thread
- * already holds the lock then the hold count is incremented by one and
- * the method returns immediately.
- *
- * <p>If the lock is held by another thread then the
- * current thread becomes disabled for thread scheduling
- * purposes and lies dormant until the lock has been acquired,
- * at which time the lock hold count is set to one.
- */
- public void lock() {
- sync.lock();
- }
+ protected Sync() {}
- /**
- * Acquires the lock unless the current thread is
- * {@link Thread#interrupt interrupted}.
- *
- * <p>Acquires the lock if it is not held by another thread and returns
- * immediately, setting the lock hold count to one.
- *
- * <p>If the current thread already holds this lock then the hold count
- * is incremented by one and the method returns immediately.
- *
- * <p>If the lock is held by another thread then the
- * current thread becomes disabled for thread scheduling
- * purposes and lies dormant until one of two things happens:
- *
- * <ul>
- *
- * <li>The lock is acquired by the current thread; or
- *
- * <li>Some other thread {@link Thread#interrupt interrupts} the current
- * thread.
- *
- * </ul>
- *
- * <p>If the lock is acquired by the current thread then the lock hold
- * count is set to one.
- *
- * <p>If the current thread:
- *
- * <ul>
- *
- * <li>has its interrupted status set on entry to this method; or
- *
- * <li>is {@link Thread#interrupt interrupted} while acquiring
- * the lock,
- *
- * </ul>
- *
- * then {@link InterruptedException} is thrown and the current thread's
- * interrupted status is cleared.
- *
- * <p>In this implementation, as this method is an explicit interruption
- * point, preference is
- * given to responding to the interrupt over normal or reentrant
- * acquisition of the lock.
- *
- * @throws InterruptedException if the current thread is interrupted
- */
- public void lockInterruptibly() throws InterruptedException {
- sync.lockInterruptibly();
- }
+ public abstract void lock();
- /**
- * Acquires the lock only if it is not held by another thread at the time
- * of invocation.
- *
- * <p>Acquires the lock if it is not held by another thread and
- * returns immediately with the value <tt>true</tt>, setting the
- * lock hold count to one. Even when this lock has been set to use a
- * fair ordering policy, a call to <tt>tryLock()</tt> <em>will</em>
- * immediately acquire the lock if it is available, whether or not
- * other threads are currently waiting for the lock.
- * This "barging" behavior can be useful in certain
- * circumstances, even though it breaks fairness. If you want to honor
- * the fairness setting for this lock, then use
- * {@link #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
- * which is almost equivalent (it also detects interruption).
- *
- * <p> If the current thread
- * already holds this lock then the hold count is incremented by one and
- * the method returns <tt>true</tt>.
- *
- * <p>If the lock is held by another thread then this method will return
- * immediately with the value <tt>false</tt>.
- *
- * @return <tt>true</tt> if the lock was free and was acquired by the
- * current thread, or the lock was already held by the current thread; and
- * <tt>false</tt> otherwise.
- */
- public boolean tryLock() {
- return sync.tryLock();
- }
+ public abstract void lockInterruptibly() throws InterruptedException;
- /**
- * Acquires the lock if it is not held by another thread within the given
- * waiting time and the current thread has not been
- * {@link Thread#interrupt interrupted}.
- *
- * <p>Acquires the lock if it is not held by another thread and returns
- * immediately with the value <tt>true</tt>, setting the lock hold count
- * to one. If this lock has been set to use a fair ordering policy then
- * an available lock <em>will not</em> be acquired if any other threads
- * are waiting for the lock. This is in contrast to the {@link #tryLock()}
- * method. If you want a timed <tt>tryLock</tt> that does permit barging on
- * a fair lock then combine the timed and un-timed forms together:
- *
- * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
- * </pre>
- *
- * <p>If the current thread
- * already holds this lock then the hold count is incremented by one and
- * the method returns <tt>true</tt>.
- *
- * <p>If the lock is held by another thread then the
- * current thread becomes disabled for thread scheduling
- * purposes and lies dormant until one of three things happens:
- *
- * <ul>
- *
- * <li>The lock is acquired by the current thread; or
- *
- * <li>Some other thread {@link Thread#interrupt interrupts} the current
- * thread; or
- *
- * <li>The specified waiting time elapses
- *
- * </ul>
- *
- * <p>If the lock is acquired then the value <tt>true</tt> is returned and
- * the lock hold count is set to one.
- *
- * <p>If the current thread:
- *
- * <ul>
- *
- * <li>has its interrupted status set on entry to this method; or
- *
- * <li>is {@link Thread#interrupt interrupted} while acquiring
- * the lock,
- *
- * </ul>
- * then {@link InterruptedException} is thrown and the current thread's
- * interrupted status is cleared.
- *
- * <p>If the specified waiting time elapses then the value <tt>false</tt>
- * is returned.
- * If the time is
- * less than or equal to zero, the method will not wait at all.
- *
- * <p>In this implementation, as this method is an explicit interruption
- * point, preference is
- * given to responding to the interrupt over normal or reentrant
- * acquisition of the lock, and over reporting the elapse of the waiting
- * time.
- *
- * @param timeout the time to wait for the lock
- * @param unit the time unit of the timeout argument
- *
- * @return <tt>true</tt> if the lock was free and was acquired by the
- * current thread, or the lock was already held by the current thread; and
- * <tt>false</tt> if the waiting time elapsed before the lock could be
- * acquired.
- *
- * @throws InterruptedException if the current thread is interrupted
- * @throws NullPointerException if unit is null
- *
- */
- public boolean tryLock(long timeout, TimeUnit unit)
- throws InterruptedException {
- return sync.tryLock(unit.toNanos(timeout));
- }
+ final void incHolds() {
+ int nextHolds = ++holds_;
+ if (nextHolds < 0)
+ throw new Error("Maximum lock count exceeded");
+ holds_ = nextHolds;
+ }
- /**
- * Attempts to release this lock.
- *
- * <p>If the current thread is the
- * holder of this lock then the hold count is decremented. If the
- * hold count is now zero then the lock is released. If the
- * current thread is not the holder of this lock then {@link
- * IllegalMonitorStateException} is thrown.
- * @throws IllegalMonitorStateException if the current thread does not
- * hold this lock.
- */
- public void unlock() {
- sync.unlock();
- }
+ public boolean tryLock() {
+ Thread caller = Thread.currentThread();
+ synchronized (this) {
+ if (owner_ == null) {
+ owner_ = caller;
+ holds_ = 1;
+ return true;
+ } else if (caller == owner_) {
+ incHolds();
+ return true;
+ }
+ }
+ return false;
+ }
- /**
- * Returns a {@link Condition} instance for use with this
- * {@link Lock} instance.
- *
- * <p>The returned {@link Condition} instance supports the same
- * usages as do the {@link Object} monitor methods ({@link
- * Object#wait() wait}, {@link Object#notify notify}, and {@link
- * Object#notifyAll notifyAll}) when used with the built-in
- * monitor lock.
- *
- * <ul>
- *
- * <li>If this lock is not held when any of the {@link Condition}
- * {@link Condition#await() waiting} or {@link Condition#signal
- * signalling} methods are called, then an {@link
- * IllegalMonitorStateException} is thrown.
- *
- * <li>When the condition {@link Condition#await() waiting}
- * methods are called the lock is released and, before they
- * return, the lock is reacquired and the lock hold count restored
- * to what it was when the method was called.
- *
- * <li>If a thread is {@link Thread#interrupt interrupted} while
- * waiting then the wait will terminate, an {@link
- * InterruptedException} will be thrown, and the thread's
- * interrupted status will be cleared.
- *
- * <li> Waiting threads are signalled in FIFO order
- *
- * <li>The ordering of lock reacquisition for threads returning
- * from waiting methods is the same as for threads initially
- * acquiring the lock, which is in the default case not specified,
- * but for <em>fair</em> locks favors those threads that have been
- * waiting the longest.
- *
- * </ul>
- *
- * @return the Condition object
- */
- public Condition newCondition() {
- return isFair() ? new FIFOCondVar(this) : new CondVar(this);
- }
+ public abstract boolean tryLock(long nanos) throws InterruptedException;
- /**
- * Queries the number of holds on this lock by the current thread.
- *
- * <p>A thread has a hold on a lock for each lock action that is not
- * matched by an unlock action.
- *
- * <p>The hold count information is typically only used for testing and
- * debugging purposes. For example, if a certain section of code should
- * not be entered with the lock already held then we can assert that
- * fact:
- *
- * <pre>
- * class X {
- * ReentrantLock lock = new ReentrantLock();
- * // ...
- * public void m() {
- * assert lock.getHoldCount() == 0;
- * lock.lock();
- * try {
- * // ... method body
- * } finally {
- * lock.unlock();
- * }
- * }
- * }
- * </pre>
- *
- * @return the number of holds on this lock by the current thread,
- * or zero if this lock is not held by the current thread.
- */
- public int getHoldCount() {
- return sync.getHoldCount();
- }
+ public abstract void unlock();
- /**
- * Queries if this lock is held by the current thread.
- *
- * <p>Analogous to the {@link Thread#holdsLock} method for built-in
- * monitor locks, this method is typically used for debugging and
- * testing. For example, a method that should only be called while
- * a lock is held can assert that this is the case:
- *
- * <pre>
- * class X {
- * ReentrantLock lock = new ReentrantLock();
- * // ...
- *
- * public void m() {
- * assert lock.isHeldByCurrentThread();
- * // ... method body
- * }
- * }
- * </pre>
- *
- * <p>It can also be used to ensure that a reentrant lock is used
- * in a non-reentrant manner, for example:
- *
- * <pre>
- * class X {
- * ReentrantLock lock = new ReentrantLock();
- * // ...
- *
- * public void m() {
- * assert !lock.isHeldByCurrentThread();
- * lock.lock();
- * try {
- * // ... method body
- * } finally {
- * lock.unlock();
- * }
- * }
- * }
- * </pre>
- * @return <tt>true</tt> if current thread holds this lock and
- * <tt>false</tt> otherwise.
- */
- public boolean isHeldByCurrentThread() {
- return sync.isHeldByCurrentThread();
- }
+ public synchronized int getHoldCount() {
+ return isHeldByCurrentThread() ? holds_ : 0;
+ }
- /**
- * Queries if this lock is held by any thread. This method is
- * designed for use in monitoring of the system state,
- * not for synchronization control.
- * @return <tt>true</tt> if any thread holds this lock and
- * <tt>false</tt> otherwise.
- */
- public boolean isLocked() {
- return sync.isLocked();
- }
+ public synchronized boolean isHeldByCurrentThread() {
+ return holds_ > 0 && Thread.currentThread() == owner_;
+ }
- /**
- * Returns true if this lock has fairness set true.
- * @return true if this lock has fairness set true.
- */
- public final boolean isFair() {
- return sync.isFair();
- }
+ public synchronized boolean isLocked() {
+ return owner_ != null;
+ }
- /**
- * <tt>null</tt> if not owned. When this method is called by a
- * thread that is not the owner, the return value reflects a
- * best-effort approximation of current lock status. For example,
- * the owner may be momentarily <tt>null</tt> even if there are
- * threads trying to acquire the lock but have not yet done so.
- * This method is designed to facilitate construction of
- * subclasses that provide more extensive lock monitoring
- * facilities.
- *
- * @return the owner, or <tt>null</tt> if not owned
- */
- protected Thread getOwner() {
- return sync.getOwner();
- }
-
- /**
- * Queries whether any threads are waiting to acquire this lock. Note that
- * because cancellations may occur at any time, a <tt>true</tt>
- * return does not guarantee that any other thread will ever
- * acquire this lock. This method is designed primarily for use in
- * monitoring of the system state.
- *
- * @return true if there may be other threads waiting to acquire
- * the lock.
- */
- public final boolean hasQueuedThreads() {
- return sync.hasQueuedThreads();
- }
-
- /**
- * Queries whether the given thread is waiting to acquire this
- * lock. Note that because cancellations may occur at any time, a
- * <tt>true</tt> return does not guarantee that this thread
- * will ever acquire this lock. This method is designed primarily for use
- * in monitoring of the system state.
- *
- * @param thread the thread
- * @return true if the given thread is queued waiting for this lock.
- * @throws NullPointerException if thread is null
- */
- public final boolean hasQueuedThread(Thread thread) {
- return sync.isQueued(thread);
- }
-
- /**
- * Returns an estimate of the number of threads waiting to
- * acquire this lock. The value is only an estimate because the number of
- * threads may change dynamically while this method traverses
- * internal data structures. This method is designed for use in
- * monitoring of the system state, not for synchronization
- * control.
- * @return the estimated number of threads waiting for this lock
- */
- public final int getQueueLength() {
- return sync.getQueueLength();
- }
-
- /**
- * Returns a collection containing threads that may be waiting to
- * acquire this lock. Because the actual set of threads may change
- * dynamically while constructing this result, the returned
- * collection is only a best-effort estimate. The elements of the
- * returned collection are in no particular order. This method is
- * designed to facilitate construction of subclasses that provide
- * more extensive monitoring facilities.
- * @return the collection of threads
- */
- protected Collection getQueuedThreads() {
- return sync.getQueuedThreads();
- }
-
- /**
- * Queries whether any threads are waiting on the given condition
- * associated with this lock. Note that because timeouts and
- * interrupts may occur at any time, a <tt>true</tt> return does
- * not guarantee that a future <tt>signal</tt> will awaken any
- * threads. This method is designed primarily for use in
- * monitoring of the system state.
- * @param condition the condition
- * @return <tt>true</tt> if there are any waiting threads.
- * @throws IllegalMonitorStateException if this lock
- * is not held
- * @throws IllegalArgumentException if the given condition is
- * not associated with this lock
- * @throws NullPointerException if condition null
- */
- public boolean hasWaiters(Condition condition) {
- return asCondVar(condition).hasWaiters();
- }
-
- /**
- * Returns an estimate of the number of threads waiting on the
- * given condition associated with this lock. Note that because
- * timeouts and interrupts may occur at any time, the estimate
- * serves only as an upper bound on the actual number of waiters.
- * This method is designed for use in monitoring of the system
- * state, not for synchronization control.
- * @param condition the condition
- * @return the estimated number of waiting threads.
- * @throws IllegalMonitorStateException if this lock
- * is not held
- * @throws IllegalArgumentException if the given condition is
- * not associated with this lock
- * @throws NullPointerException if condition null
- */
- public int getWaitQueueLength(Condition condition) {
- return asCondVar(condition).getWaitQueueLength();
- }
-
- /**
- * Returns a collection containing those threads that may be
- * waiting on the given condition associated with this lock.
- * Because the actual set of threads may change dynamically while
- * constructing this result, the returned collection is only a
- * best-effort estimate. The elements of the returned collection
- * are in no particular order. This method is designed to
- * facilitate construction of subclasses that provide more
- * extensive condition monitoring facilities.
- * @param condition the condition
- * @return the collection of threads
- * @throws IllegalMonitorStateException if this lock
- * is not held
- * @throws IllegalArgumentException if the given condition is
- * not associated with this lock
- * @throws NullPointerException if condition null
- */
- protected Collection getWaitingThreads(Condition condition) {
- return asCondVar(condition).getWaitingThreads();
- }
-
- /**
- * Returns a string identifying this lock, as well as its lock
- * state. The state, in brackets, includes either the String
- * "Unlocked" or the String "Locked by"
- * followed by the {@link Thread#getName} of the owning thread.
- * @return a string identifying this lock, as well as its lock state.
- */
- public String toString() {
- Thread o = getOwner();
-
- return super.toString() +
- ((o == null) ? "[Unlocked]" : ("[Locked by thread " + o.getName() +
- "]"));
- }
-
- private CondVar asCondVar(Condition condition) {
- if (condition == null) {
- throw new NullPointerException();
- }
-
- if (!(condition instanceof CondVar)) {
- throw new IllegalArgumentException("not owner");
- }
-
- CondVar condVar = (CondVar) condition;
-
- if (condVar.lock != this) {
- throw new IllegalArgumentException("not owner");
- }
-
- return condVar;
- }
-
- static abstract class Sync implements java.io.Serializable {
- private static final long serialVersionUID = -5179523762034025860L;
- protected transient Thread owner_ = null;
- protected transient int holds_ = 0;
-
- protected Sync() {
- }
-
- public abstract void lock();
-
- public abstract void lockInterruptibly() throws InterruptedException;
-
- final void incHolds() {
- int nextHolds = ++holds_;
-
- if (nextHolds < 0) {
- throw new Error("Maximum lock count exceeded");
- }
-
- holds_ = nextHolds;
- }
-
- public boolean tryLock() {
- Thread caller = Thread.currentThread();
-
- synchronized (this) {
- if (owner_ == null) {
- owner_ = caller;
- holds_ = 1;
-
- return true;
- } else if (caller == owner_) {
- incHolds();
-
- return true;
- }
- }
-
- return false;
- }
-
- public abstract boolean tryLock(long nanos) throws InterruptedException;
-
- public abstract void unlock();
-
- public synchronized int getHoldCount() {
- return isHeldByCurrentThread() ? holds_ : 0;
- }
-
- public synchronized boolean isHeldByCurrentThread() {
- return (holds_ > 0) && (Thread.currentThread() == owner_);
- }
-
- public synchronized boolean isLocked() {
- return owner_ != null;
- }
-
- public abstract boolean isFair();
+ public abstract boolean isFair();
protected synchronized Thread getOwner() {
return owner_;
@@ -699,85 +152,63 @@
final static class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
- NonfairSync() {
- }
+ NonfairSync() {}
public void lock() {
Thread caller = Thread.currentThread();
-
synchronized (this) {
if (owner_ == null) {
owner_ = caller;
holds_ = 1;
-
return;
} else if (caller == owner_) {
incHolds();
-
return;
} else {
boolean wasInterrupted = Thread.interrupted();
-
try {
while (true) {
try {
wait();
} catch (InterruptedException e) {
wasInterrupted = true;
-
// no need to notify; if we were signalled, we
// will act as signalled, ignoring the
// interruption
}
-
if (owner_ == null) {
owner_ = caller;
holds_ = 1;
-
return;
}
}
- } finally {
- if (wasInterrupted) {
- Thread.currentThread().interrupt();
- }
+ }
+ finally {
+ if (wasInterrupted) Thread.currentThread().interrupt();
}
}
}
}
public void lockInterruptibly() throws InterruptedException {
- if (Thread.interrupted()) {
- throw new InterruptedException();
- }
-
+ if (Thread.interrupted()) throw new InterruptedException();
Thread caller = Thread.currentThread();
-
synchronized (this) {
if (owner_ == null) {
owner_ = caller;
holds_ = 1;
-
return;
} else if (caller == owner_) {
incHolds();
-
return;
} else {
try {
- do {
- wait();
- } while (owner_ != null);
-
+ do { wait(); } while (owner_ != null);
owner_ = caller;
holds_ = 1;
-
return;
} catch (InterruptedException ex) {
- if (owner_ == null) {
- notify();
- }
-
+ if (owner_ == null) notify();
throw ex;
}
}
@@ -785,53 +216,39 @@
}
public boolean tryLock(long nanos) throws InterruptedException {
- if (Thread.interrupted()) {
- throw new InterruptedException();
- }
-
+ if (Thread.interrupted()) throw new InterruptedException();
Thread caller = Thread.currentThread();
synchronized (this) {
if (owner_ == null) {
owner_ = caller;
holds_ = 1;
-
return true;
} else if (caller == owner_) {
incHolds();
-
return true;
- } else if (nanos <= 0) {
+ } else if (nanos <= 0)
return false;
- } else {
+ else {
long deadline = Utils.nanoTime() + nanos;
-
try {
- for (;;) {
+ for (; ; ) {
TimeUnit.NANOSECONDS.timedWait(this, nanos);
-
if (caller == owner_) {
incHolds();
-
return true;
} else if (owner_ == null) {
owner_ = caller;
holds_ = 1;
-
return true;
} else {
nanos = deadline - Utils.nanoTime();
-
- if (nanos <= 0) {
+ if (nanos <= 0)
return false;
- }
}
}
} catch (InterruptedException ex) {
- if (owner_ == null) {
- notify();
- }
-
+ if (owner_ == null) notify();
throw ex;
}
}
@@ -839,9 +256,8 @@
}
public synchronized void unlock() {
- if (Thread.currentThread() != owner_) {
+ if (Thread.currentThread() != owner_)
throw new IllegalMonitorStateException("Not owner");
- }
if (--holds_ == 0) {
owner_ = null;
@@ -856,140 +272,103 @@
final static class FairSync extends Sync implements WaitQueue.QueuedSync {
private static final long serialVersionUID = -3000897897090466540L;
+
private transient WaitQueue wq_ = new FIFOWaitQueue();
- FairSync() {
- }
+ FairSync() {}
public synchronized boolean recheck(WaitQueue.WaitNode node) {
Thread caller = Thread.currentThread();
-
if (owner_ == null) {
owner_ = caller;
holds_ = 1;
-
return true;
} else if (caller == owner_) {
incHolds();
-
return true;
}
-
wq_.insert(node);
-
return false;
}
public synchronized void takeOver(WaitQueue.WaitNode node) {
- // assert (holds_ == 1 && owner_ == Thread.currentThread()
+ // assert(holds_ == 1 && owner_ == Thread.currentThread()
owner_ = node.getOwner();
}
public void lock() {
Thread caller = Thread.currentThread();
-
synchronized (this) {
if (owner_ == null) {
owner_ = caller;
holds_ = 1;
-
return;
} else if (caller == owner_) {
incHolds();
-
return;
}
}
-
WaitQueue.WaitNode n = new WaitQueue.WaitNode();
n.doWaitUninterruptibly(this);
}
public void lockInterruptibly() throws InterruptedException {
- if (Thread.interrupted()) {
- throw new InterruptedException();
- }
-
+ if (Thread.interrupted()) throw new InterruptedException();
Thread caller = Thread.currentThread();
-
synchronized (this) {
if (owner_ == null) {
owner_ = caller;
holds_ = 1;
-
return;
} else if (caller == owner_) {
incHolds();
-
return;
}
}
-
WaitQueue.WaitNode n = new WaitQueue.WaitNode();
n.doWait(this);
}
public boolean tryLock(long nanos) throws InterruptedException {
- if (Thread.interrupted()) {
- throw new InterruptedException();
- }
-
+ if (Thread.interrupted()) throw new InterruptedException();
Thread caller = Thread.currentThread();
-
synchronized (this) {
if (owner_ == null) {
owner_ = caller;
holds_ = 1;
-
return true;
} else if (caller == owner_) {
incHolds();
-
return true;
}
}
-
WaitQueue.WaitNode n = new WaitQueue.WaitNode();
-
return n.doTimedWait(this, nanos);
}
protected synchronized WaitQueue.WaitNode getSignallee(Thread caller) {
- if (caller != owner_) {
+ if (caller != owner_)
throw new IllegalMonitorStateException("Not owner");
- }
-
- // assert (holds_ > 0)
+ // assert(holds_ > 0)
if (holds_ >= 2) { // current thread will keep the lock
--holds_;
-
return null;
}
-
- // assert (holds_ == 1)
+ // assert(holds_ == 1)
WaitQueue.WaitNode w = wq_.extract();
-
if (w == null) { // if none, clear for new arrivals
owner_ = null;
holds_ = 0;
}
-
return w;
}
public void unlock() {
Thread caller = Thread.currentThread();
-
for (;;) {
WaitQueue.WaitNode w = getSignallee(caller);
-
- if (w == null) {
- return; // no one to signal
- }
-
- if (w.signal(this)) {
- return; // notify if still waiting, or skip
- }
+ if (w == null) return; // no one to signal
+ if (w.signal(this)) return; // notify if still waiting, or skip
}
}
@@ -1014,12 +393,453 @@
}
private void readObject(java.io.ObjectInputStream in)
- throws java.io.IOException, ClassNotFoundException {
+ throws java.io.IOException, ClassNotFoundException {
in.defaultReadObject();
-
synchronized (this) {
wq_ = new FIFOWaitQueue();
}
}
+ }
+
+ /**
+ * Creates an instance of <tt>ReentrantLock</tt>.
+ * This is equivalent to using <tt>ReentrantLock(false)</tt>.
+ */
+ public ReentrantLock() {
+ sync = new NonfairSync();
+ }
+
+ /**
+ * Creates an instance of <tt>ReentrantLock</tt> with the
+ * given fairness policy.
+ * @param fair true if this lock will be fair; else false
+ */
+ public ReentrantLock(boolean fair) {
+ sync = (fair)? (Sync)new FairSync() : new NonfairSync();
+ }
+
+ /**
+ * Acquires the lock.
+ * Acquires the lock if it is not held by another thread and returns
+ * immediately, setting the lock hold count to one.
+ * If the current thread
+ * already holds the lock then the hold count is incremented by one and
+ * the method returns immediately.
+ * If the lock is held by another thread then the
+ * current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until the lock has been acquired,
+ * at which time the lock hold count is set to one.
+ */
+ public void lock() {
+ sync.lock();
+ }
+
+ /**
+ * Acquires the lock unless the current thread is
+ * {@link Thread#interrupt interrupted}.
+ * Acquires the lock if it is not held by another thread and returns
+ * immediately, setting the lock hold count to one.
+ * If the current thread already holds this lock then the hold count
+ * is incremented by one and the method returns immediately.
+ * If the lock is held by another thread then the
+ * current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until one of two things happens:
+ *
+ * <ul>
+ *
+ * <li>The lock is acquired by the current thread; or
+ *
+ * <li>Some other thread {@link Thread#interrupt interrupts} the current
+ * thread.
+ *
+ * </ul>
+ * If the lock is acquired by the current thread then the lock hold
+ * count is set to one.
+ * If the current thread:
+ *
+ * <ul>
+ *
+ * <li>has its interrupted status set on entry to this method; or
+ *
+ * <li>is {@link Thread#interrupt interrupted} while acquiring the lock,
+ *
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ * In this implementation, as this method is an explicit interruption
+ * point, preference is
+ * given to responding to the interrupt over normal or reentrant
+ * acquisition of the lock.
+ *
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public void lockInterruptibly() throws InterruptedException {
+ sync.lockInterruptibly();
+ }
+
+ /**
+ * Acquires the lock only if it is not held by another thread at the time
+ * of invocation.
+ * Acquires the lock if it is not held by another thread and
+ * returns immediately with the value <tt>true</tt>, setting the
+ * lock hold count to one. Even when this lock has been set to use a
+ * fair ordering policy, a call to <tt>tryLock()</tt> <em>will</em>
+ * immediately acquire the lock if it is available, whether or not
+ * other threads are currently waiting for the lock.
+ * This "barging" behavior can be useful in certain
+ * circumstances, even though it breaks fairness. If you want to honor
+ * the fairness setting for this lock, then use
+ * {@link #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
+ * which is almost equivalent(it also detects interruption).
+ * If the current thread
+ * already holds this lock then the hold count is incremented by one and
+ * the method returns <tt>true</tt>.
+ * If the lock is held by another thread then this method will return
+ * immediately with the value <tt>false</tt>.
+ *
+ * @return <tt>true</tt> if the lock was free and was acquired by the
+ * current thread, or the lock was already held by the current thread; and
+ * <tt>false</tt> otherwise.
+ */
+ public boolean tryLock() {
+ return sync.tryLock();
+ }
+
+ /**
+ * Acquires the lock if it is not held by another thread within the given
+ * waiting time and the current thread has not been
+ * {@link Thread#interrupt interrupted}.
+ * Acquires the lock if it is not held by another thread and returns
+ * immediately with the value <tt>true</tt>, setting the lock hold count
+ * to one. If this lock has been set to use a fair ordering policy then
+ * an available lock <em>will not</em> be acquired if any other threads
+ * are waiting for the lock. This is in contrast to the {@link #tryLock()}
+ * method. If you want a timed <tt>tryLock</tt> that does permit barging on
+ * a fair lock then combine the timed and un-timed forms together:
+ *
+ * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
+ * </pre>
+ * If the current thread
+ * already holds this lock then the hold count is incremented by one and
+ * the method returns <tt>true</tt>.
+ * If the lock is held by another thread then the
+ * current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until one of three things happens:
+ *
+ * <ul>
+ *
+ * <li>The lock is acquired by the current thread; or
+ *
+ * <li>Some other thread {@link Thread#interrupt interrupts} the current
+ * thread; or
+ *
+ * <li>The specified waiting time elapses
+ *
+ * </ul>
+ * If the lock is acquired then the value <tt>true</tt> is returned and
+ * the lock hold count is set to one.
+ * If the current thread:
+ *
+ * <ul>
+ *
+ * <li>has its interrupted status set on entry to this method; or
+ *
+ * <li>is {@link Thread#interrupt interrupted} while acquiring the lock,
+ *
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ * If the specified waiting time elapses then the value <tt>false</tt>
+ * is returned. If the time is
+ * less than or equal to zero, the method will not wait at all.
+ * In this implementation, as this method is an explicit interruption
+ * point, preference is
+ * given to responding to the interrupt over normal or reentrant
+ * acquisition of the lock, and over reporting the elapse of the waiting
+ * time.
+ *
+ * @param timeout the time to wait for the lock
+ * @param unit the time unit of the timeout argument
+ *
+ * @return <tt>true</tt> if the lock was free and was acquired by the
+ * current thread, or the lock was already held by the current thread; and
+ * <tt>false</tt> if the waiting time elapsed before the lock could be
+ * acquired.
+ *
+ * @throws InterruptedException if the current thread is interrupted
+ * @throws NullPointerException if unit is null
+ *
+ */
+ public boolean tryLock(long timeout, TimeUnit unit)
+ throws InterruptedException {
+ return sync.tryLock(unit.toNanos(timeout));
+ }
+
+ /**
+ * Attempts to release this lock.
+ * If the current thread is the
+ * holder of this lock then the hold count is decremented. If the
+ * hold count is now zero then the lock is released. If the
+ * current thread is not the holder of this lock then {@link
+ * IllegalMonitorStateException} is thrown.
+ * @throws IllegalMonitorStateException if the current thread does not
+ * hold this lock.
+ */
+ public void unlock() {
+ sync.unlock();
+ }
+
+ /**
+ * Returns a {@link Condition} instance for use with this
+ * {@link Lock} instance.
+ * The returned {@link Condition} instance supports the same
+ * usages as do the {@link Object} monitor methods({@link
+ * Object#wait() wait}, {@link Object#notify notify}, and {@link
+ * Object#notifyAll notifyAll}) when used with the built-in monitor lock.
+ *
+ * <ul>
+ *
+ * <li>If this lock is not held when any of the {@link Condition}
+ * {@link Condition#await() waiting} or {@link Condition#signal
+ * signalling} methods are called, then an {@link
+ * IllegalMonitorStateException} is thrown.
+ *
+ * <li>When the condition {@link Condition#await() waiting}
+ * methods are called the lock is released and, before they
+ * return, the lock is reacquired and the lock hold count restored
+ * to what it was when the method was called.
+ *
+ * <li>If a thread is {@link Thread#interrupt interrupted} while
+ * waiting then the wait will terminate, an {@link
+ * InterruptedException} will be thrown, and the thread's
+ * interrupted status will be cleared.
+ *
+ * <li> Waiting threads are signalled in FIFO order
+ *
+ * <li>The ordering of lock reacquisition for threads returning
+ * from waiting methods is the same as for threads initially
+ * acquiring the lock, which is in the default case not specified,
+ * but for <em>fair</em> locks favors those threads that have been
+ * waiting the longest.
+ *
+ * </ul>
+ *
+ * @return the Condition object
+ */
+ public Condition newCondition() {
+ return isFair() ? new FIFOCondVar(this) : new CondVar(this);
+ }
+
+ /**
+ * Queries the number of holds on this lock by the current thread.
+ * A thread has a hold on a lock for each lock action that is not
+ * matched by an unlock action.
+ * The hold count information is typically only used for testing and
+ * debugging purposes. For example, if a certain section of code should
+ * not be entered with the lock already held then we can assert that fact:
+ *
+ * <pre> class X { ReentrantLock lock = new ReentrantLock(); // ...
+ * public void m() { assert lock.getHoldCount() == 0; lock.lock(); try {
+ * // ... method body } finally { lock.unlock(); } } }
+ * </pre>
+ *
+ * @return the number of holds on this lock by the current thread,
+ * or zero if this lock is not held by the current thread.
+ */
+ public int getHoldCount() {
+ return sync.getHoldCount();
+ }
+
+ /**
+ * Queries if this lock is held by the current thread.
+ * Analogous to the {@link Thread#holdsLock} method for built-in
+ * monitor locks, this method is typically used for debugging and
+ * testing. For example, a method that should only be called while
+ * a lock is held can assert that this is the case:
+ *
+ * <pre> class X { ReentrantLock lock = new ReentrantLock(); // ...
+ * public void m() { assert lock.isHeldByCurrentThread();
+ * // ... method body } }
+ * </pre>
+ * It can also be used to ensure that a reentrant lock is used
+ * in a non-reentrant manner, for example:
+ *
+ * <pre> class X { ReentrantLock lock = new ReentrantLock(); // ...
+ * public void m() { assert !lock.isHeldByCurrentThread(); lock.lock();
+ * try { // ... method body } finally { lock.unlock(); } } }
+ * </pre>
+ * @return <tt>true</tt> if current thread holds this lock and
+ * <tt>false</tt> otherwise.
+ */
+ public boolean isHeldByCurrentThread() {
+ return sync.isHeldByCurrentThread();
+ }
+
+ /**
+ * Queries if this lock is held by any thread. This method is
+ * designed for use in monitoring of the system state,
+ * not for synchronization control.
+ * @return <tt>true</tt> if any thread holds this lock and
+ * <tt>false</tt> otherwise.
+ */
+ public boolean isLocked() {
+ return sync.isLocked();
+ }
+
+ /**
+ * Returns true if this lock has fairness set true.
+ * @return true if this lock has fairness set true.
+ */
+ public final boolean isFair() {
+ return sync.isFair();
+ }
+
+ /**
+ * <tt>null</tt> if not owned. When this method is called by a
+ * thread that is not the owner, the return value reflects a
+ * best-effort approximation of current lock status. For example,
+ * the owner may be momentarily <tt>null</tt> even if there are
+ * threads trying to acquire the lock but have not yet done so.
+ * This method is designed to facilitate construction of
+ * subclasses that provide more extensive lock monitoring facilities.
+ *
+ * @return the owner, or <tt>null</tt> if not owned
+ */
+ protected Thread getOwner() {
+ return sync.getOwner();
+ }
+
+ /**
+ * Queries whether any threads are waiting to acquire this lock. Note that
+ * because cancellations may occur at any time, a <tt>true</tt>
+ * return does not guarantee that any other thread will ever
+ * acquire this lock. This method is designed primarily for use in
+ * monitoring of the system state.
+ *
+ * @return true if there may be other threads waiting to acquire the lock.
+ */
+ public final boolean hasQueuedThreads() {
+ return sync.hasQueuedThreads();
+ }
+
+ /**
+ * Queries whether the given thread is waiting to acquire this
+ * lock. Note that because cancellations may occur at any time, a
+ * <tt>true</tt> return does not guarantee that this thread
+ * will ever acquire this lock. This method is designed primarily for use
+ * in monitoring of the system state.
+ *
+ * @param thread the thread
+ * @return true if the given thread is queued waiting for this lock.
+ * @throws NullPointerException if thread is null
+ */
+ public final boolean hasQueuedThread(Thread thread) {
+ return sync.isQueued(thread);
+ }
+
+ /**
+ * Returns an estimate of the number of threads waiting to
+ * acquire this lock. The value is only an estimate because the number of
+ * threads may change dynamically while this method traverses
+ * internal data structures. This method is designed for use in
+ * monitoring of the system state, not for synchronization control.
+ * @return the estimated number of threads waiting for this lock
+ */
+ public final int getQueueLength() {
+ return sync.getQueueLength();
+ }
+
+ /**
+ * Returns a collection containing threads that may be waiting to
+ * acquire this lock. Because the actual set of threads may change
+ * dynamically while constructing this result, the returned
+ * collection is only a best-effort estimate. The elements of the
+ * returned collection are in no particular order. This method is
+ * designed to facilitate construction of subclasses that provide
+ * more extensive monitoring facilities.
+ * @return the collection of threads
+ */
+ protected Collection getQueuedThreads() {
+ return sync.getQueuedThreads();
+ }
+
+ /**
+ * Queries whether any threads are waiting on the given condition
+ * associated with this lock. Note that because timeouts and
+ * interrupts may occur at any time, a <tt>true</tt> return does
+ * not guarantee that a future <tt>signal</tt> will awaken any
+ * threads. This method is designed primarily for use in
+ * monitoring of the system state.
+ * @param condition the condition
+ * @return <tt>true</tt> if there are any waiting threads.
+ * @throws IllegalMonitorStateException if this lock is not held
+ * @throws IllegalArgumentException if the given condition is
+ * not associated with this lock
+ * @throws NullPointerException if condition null
+ */
+ public boolean hasWaiters(Condition condition) {
+ return asCondVar(condition).hasWaiters();
+ }
+
+ /**
+ * Returns an estimate of the number of threads waiting on the
+ * given condition associated with this lock. Note that because
+ * timeouts and interrupts may occur at any time, the estimate
+ * serves only as an upper bound on the actual number of waiters.
+ * This method is designed for use in monitoring of the system
+ * state, not for synchronization control.
+ * @param condition the condition
+ * @return the estimated number of waiting threads.
+ * @throws IllegalMonitorStateException if this lock is not held
+ * @throws IllegalArgumentException if the given condition is
+ * not associated with this lock
+ * @throws NullPointerException if condition null
+ */
+ public int getWaitQueueLength(Condition condition) {
+ return asCondVar(condition).getWaitQueueLength();
+ }
+
+ /**
+ * Returns a collection containing those threads that may be
+ * waiting on the given condition associated with this lock.
+ * Because the actual set of threads may change dynamically while
+ * constructing this result, the returned collection is only a
+ * best-effort estimate. The elements of the returned collection
+ * are in no particular order. This method is designed to
+ * facilitate construction of subclasses that provide more
+ * extensive condition monitoring facilities.
+ * @param condition the condition
+ * @return the collection of threads
+ * @throws IllegalMonitorStateException if this lock is not held
+ * @throws IllegalArgumentException if the given condition is
+ * not associated with this lock
+ * @throws NullPointerException if condition null
+ */
+ protected Collection getWaitingThreads(Condition condition) {
+ return asCondVar(condition).getWaitingThreads();
+ }
+
+ /**
+ * Returns a string identifying this lock, as well as its lock
+ * state. The state, in brackets, includes either the String
+ * "Unlocked" or the String "Locked by"
+ * followed by the {@link Thread#getName} of the owning thread.
+ * @return a string identifying this lock, as well as its lock state.
+ */
+ public String toString() {
+ Thread o = getOwner();
+ return super.toString() + ((o == null) ? "[Unlocked]"
+ : "[Locked by thread " + o.getName() + "]");
+ }
+
+ private CondVar asCondVar(Condition condition) {
+ if (condition == null)
+ throw new NullPointerException();
+ if (!(condition instanceof CondVar))
+ throw new IllegalArgumentException("not owner");
+ CondVar condVar = (CondVar)condition;
+ if (condVar.lock != this)
+ throw new IllegalArgumentException("not owner");
+ return condVar;
}
}
Modified: incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/TimeUnit.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/TimeUnit.java?rev=418401&r1=418400&r2=418401&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/TimeUnit.java (original)
+++ incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/TimeUnit.java Fri Jun 30 15:37:18 2006
@@ -1,19 +1,15 @@
/*
* Copyright 2006 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
/*
* Written by Doug Lea with assistance from members of JCP JSR-166
* Expert Group and released to the public domain, as explained at
@@ -21,337 +17,133 @@
*/
package org.apache.openjpa.lib.util.concurrent;
-
/**
* A <tt>TimeUnit</tt> represents time durations at a given unit of
* granularity and provides utility methods to convert across units,
- * and to perform timing and delay operations in these units. A
+ * and to perform timing and delay operations in these units. A
* <tt>TimeUnit</tt> does not maintain time information, but only
* helps organize and use time representations that may be maintained
- * separately across various contexts. A nanosecond is defined as one
+ * separately across various contexts. A nanosecond is defined as one
* thousandth of a microsecond, a microsecond as one thousandth of a
* millisecond, a millisecond as one thousandth of a second, a minute
- * as sixty seconds, an hour as sixty minutes, and a day as twenty four
- * hours.
- *
- * <p>A <tt>TimeUnit</tt> is mainly used to inform time-based methods
+ * as sixty seconds, an hour as sixty minutes, and a day as twenty four hours.
+ * A <tt>TimeUnit</tt> is mainly used to inform time-based methods
* how a given timing parameter should be interpreted. For example,
* the following code will timeout in 50 milliseconds if the {@link
* edu.emory.mathcs.backport.java.util.concurrent.locks.Lock lock} is not
* available:
- *
- * <pre>
- * Lock lock = ...;
- * if ( lock.tryLock(50L, TimeUnit.MILLISECONDS) ) ...
- * </pre>
- * while this code will timeout in 50 seconds:
- * <pre>
- * Lock lock = ...;
- * if ( lock.tryLock(50L, TimeUnit.SECONDS) ) ...
+ *
+ * <pre> Lock lock = ...; if ( lock.tryLock(50L, TimeUnit.MILLISECONDS) ) ...
+ * </pre> while this code will timeout in 50 seconds:
+ * <pre> Lock lock = ...; if ( lock.tryLock(50L, TimeUnit.SECONDS) ) ...
* </pre>
- *
- * Note however, that there is no guarantee that a particular timeout
+ * Note however, that there is no guarantee that a particular timeout
* implementation will be able to notice the passage of time at the
* same granularity as the given <tt>TimeUnit</tt>.
- *
+ *
* @since 1.5
* @author Doug Lea
*/
public abstract class TimeUnit implements java.io.Serializable {
- public static final TimeUnit NANOSECONDS = new TimeUnit(0, "NANOSECONDS") {
- private final static long serialVersionUID = 535148490883208361L;
- public long toNanos(long d) {
- return d;
- }
-
- public long toMicros(long d) {
- return d / (C1 / C0);
- }
-
- public long toMillis(long d) {
- return d / (C2 / C0);
- }
-
- public long toSeconds(long d) {
- return d / (C3 / C0);
- }
-
- public long toMinutes(long d) {
- return d / (C4 / C0);
- }
-
- public long toHours(long d) {
- return d / (C5 / C0);
- }
-
- public long toDays(long d) {
- return d / (C6 / C0);
- }
-
- public long convert(long d, TimeUnit u) {
- return u.toNanos(d);
- }
-
- int excessNanos(long d, long m) {
- return (int) (d - (m * C2));
- }
- };
-
- public static final TimeUnit MICROSECONDS = new TimeUnit(1, "MICROSECONDS") {
- private final static long serialVersionUID = 2185906575929579108L;
-
- public long toNanos(long d) {
- return x(d, C1 / C0, MAX / (C1 / C0));
- }
-
- public long toMicros(long d) {
- return d;
- }
-
- public long toMillis(long d) {
- return d / (C2 / C1);
- }
-
- public long toSeconds(long d) {
- return d / (C3 / C1);
- }
-
- public long toMinutes(long d) {
- return d / (C4 / C1);
- }
-
- public long toHours(long d) {
- return d / (C5 / C1);
- }
-
- public long toDays(long d) {
- return d / (C6 / C1);
- }
-
- public long convert(long d, TimeUnit u) {
- return u.toMicros(d);
- }
-
- int excessNanos(long d, long m) {
- return (int) ((d * C1) - (m * C2));
- }
- };
-
- public static final TimeUnit MILLISECONDS = new TimeUnit(2, "MILLISECONDS") {
- private final static long serialVersionUID = 9032047794123325184L;
-
- public long toNanos(long d) {
- return x(d, C2 / C0, MAX / (C2 / C0));
- }
-
- public long toMicros(long d) {
- return x(d, C2 / C1, MAX / (C2 / C1));
- }
-
- public long toMillis(long d) {
- return d;
- }
-
- public long toSeconds(long d) {
- return d / (C3 / C2);
- }
-
- public long toMinutes(long d) {
- return d / (C4 / C2);
- }
-
- public long toHours(long d) {
- return d / (C5 / C2);
- }
-
- public long toDays(long d) {
- return d / (C6 / C2);
- }
-
- public long convert(long d, TimeUnit u) {
- return u.toMillis(d);
- }
-
- int excessNanos(long d, long m) {
- return 0;
- }
- };
+ public static final TimeUnit NANOSECONDS = new TimeUnit(0, "NANOSECONDS") {
+ private final static long serialVersionUID = 535148490883208361L;
+ public long toNanos(long d) { return d; }
+ public long toMicros(long d) { return d/(C1/C0); }
+ public long toMillis(long d) { return d/(C2/C0); }
+ public long toSeconds(long d) { return d/(C3/C0); }
+ public long toMinutes(long d) { return d/(C4/C0); }
+ public long toHours(long d) { return d/(C5/C0); }
+ public long toDays(long d) { return d/(C6/C0); }
+ public long convert(long d, TimeUnit u) { return u.toNanos(d); }
+ int excessNanos(long d, long m) { return(int)(d - (m*C2)); }
+ };
+
+ public static final TimeUnit MICROSECONDS = new TimeUnit(1, "MICROSECONDS"){
+ private final static long serialVersionUID = 2185906575929579108L;
+ public long toNanos(long d) { return x(d, C1/C0, MAX/(C1/C0)); }
+ public long toMicros(long d) { return d; }
+ public long toMillis(long d) { return d/(C2/C1); }
+ public long toSeconds(long d) { return d/(C3/C1); }
+ public long toMinutes(long d) { return d/(C4/C1); }
+ public long toHours(long d) { return d/(C5/C1); }
+ public long toDays(long d) { return d/(C6/C1); }
+ public long convert(long d, TimeUnit u) { return u.toMicros(d); }
+ int excessNanos(long d, long m) { return(int)((d*C1) - (m*C2)); }
+ };
+
+ public static final TimeUnit MILLISECONDS = new TimeUnit(2, "MILLISECONDS"){
+ private final static long serialVersionUID = 9032047794123325184L;
+ public long toNanos(long d) { return x(d, C2/C0, MAX/(C2/C0)); }
+ public long toMicros(long d) { return x(d, C2/C1, MAX/(C2/C1)); }
+ public long toMillis(long d) { return d; }
+ public long toSeconds(long d) { return d/(C3/C2); }
+ public long toMinutes(long d) { return d/(C4/C2); }
+ public long toHours(long d) { return d/(C5/C2); }
+ public long toDays(long d) { return d/(C6/C2); }
+ public long convert(long d, TimeUnit u) { return u.toMillis(d); }
+ int excessNanos(long d, long m) { return 0; }
+ };
public static final TimeUnit SECONDS = new TimeUnit(3, "SECONDS") {
- private final static long serialVersionUID = 227755028449378390L;
-
- public long toNanos(long d) {
- return x(d, C3 / C0, MAX / (C3 / C0));
- }
-
- public long toMicros(long d) {
- return x(d, C3 / C1, MAX / (C3 / C1));
- }
-
- public long toMillis(long d) {
- return x(d, C3 / C2, MAX / (C3 / C2));
- }
-
- public long toSeconds(long d) {
- return d;
- }
-
- public long toMinutes(long d) {
- return d / (C4 / C3);
- }
-
- public long toHours(long d) {
- return d / (C5 / C3);
- }
-
- public long toDays(long d) {
- return d / (C6 / C3);
- }
-
- public long convert(long d, TimeUnit u) {
- return u.toSeconds(d);
- }
-
- int excessNanos(long d, long m) {
- return 0;
- }
- };
+ private final static long serialVersionUID = 227755028449378390L;
+ public long toNanos(long d) { return x(d, C3/C0, MAX/(C3/C0)); }
+ public long toMicros(long d) { return x(d, C3/C1, MAX/(C3/C1)); }
+ public long toMillis(long d) { return x(d, C3/C2, MAX/(C3/C2)); }
+ public long toSeconds(long d) { return d; }
+ public long toMinutes(long d) { return d/(C4/C3); }
+ public long toHours(long d) { return d/(C5/C3); }
+ public long toDays(long d) { return d/(C6/C3); }
+ public long convert(long d, TimeUnit u) { return u.toSeconds(d); }
+ int excessNanos(long d, long m) { return 0; }
+ };
public static final TimeUnit MINUTES = new TimeUnit(4, "MINUTES") {
- private final static long serialVersionUID = 1827351566402609187L;
-
- public long toNanos(long d) {
- return x(d, C4 / C0, MAX / (C4 / C0));
- }
-
- public long toMicros(long d) {
- return x(d, C4 / C1, MAX / (C4 / C1));
- }
-
- public long toMillis(long d) {
- return x(d, C4 / C2, MAX / (C4 / C2));
- }
-
- public long toSeconds(long d) {
- return x(d, C4 / C3, MAX / (C4 / C3));
- }
-
- public long toMinutes(long d) {
- return d;
- }
-
- public long toHours(long d) {
- return d / (C5 / C4);
- }
-
- public long toDays(long d) {
- return d / (C6 / C4);
- }
-
- public long convert(long d, TimeUnit u) {
- return u.toMinutes(d);
- }
-
- int excessNanos(long d, long m) {
- return 0;
- }
- };
+ private final static long serialVersionUID = 1827351566402609187L;
+ public long toNanos(long d) { return x(d, C4/C0, MAX/(C4/C0)); }
+ public long toMicros(long d) { return x(d, C4/C1, MAX/(C4/C1)); }
+ public long toMillis(long d) { return x(d, C4/C2, MAX/(C4/C2)); }
+ public long toSeconds(long d) { return x(d, C4/C3, MAX/(C4/C3)); }
+ public long toMinutes(long d) { return d; }
+ public long toHours(long d) { return d/(C5/C4); }
+ public long toDays(long d) { return d/(C6/C4); }
+ public long convert(long d, TimeUnit u) { return u.toMinutes(d); }
+ int excessNanos(long d, long m) { return 0; }
+ };
public static final TimeUnit HOURS = new TimeUnit(5, "HOURS") {
- private final static long serialVersionUID = -6438436134732089810L;
-
- public long toNanos(long d) {
- return x(d, C5 / C0, MAX / (C5 / C0));
- }
-
- public long toMicros(long d) {
- return x(d, C5 / C1, MAX / (C5 / C1));
- }
-
- public long toMillis(long d) {
- return x(d, C5 / C2, MAX / (C5 / C2));
- }
-
- public long toSeconds(long d) {
- return x(d, C5 / C3, MAX / (C5 / C3));
- }
-
- public long toMinutes(long d) {
- return x(d, C5 / C4, MAX / (C5 / C4));
- }
-
- public long toHours(long d) {
- return d;
- }
-
- public long toDays(long d) {
- return d / (C6 / C5);
- }
-
- public long convert(long d, TimeUnit u) {
- return u.toHours(d);
- }
-
- int excessNanos(long d, long m) {
- return 0;
- }
- };
+ private final static long serialVersionUID = -6438436134732089810L;
+ public long toNanos(long d) { return x(d, C5/C0, MAX/(C5/C0)); }
+ public long toMicros(long d) { return x(d, C5/C1, MAX/(C5/C1)); }
+ public long toMillis(long d) { return x(d, C5/C2, MAX/(C5/C2)); }
+ public long toSeconds(long d) { return x(d, C5/C3, MAX/(C5/C3)); }
+ public long toMinutes(long d) { return x(d, C5/C4, MAX/(C5/C4)); }
+ public long toHours(long d) { return d; }
+ public long toDays(long d) { return d/(C6/C5); }
+ public long convert(long d, TimeUnit u) { return u.toHours(d); }
+ int excessNanos(long d, long m) { return 0; }
+ };
public static final TimeUnit DAYS = new TimeUnit(6, "DAYS") {
- private final static long serialVersionUID = 567463171959674600L;
-
- public long toNanos(long d) {
- return x(d, C6 / C0, MAX / (C6 / C0));
- }
-
- public long toMicros(long d) {
- return x(d, C6 / C1, MAX / (C6 / C1));
- }
-
- public long toMillis(long d) {
- return x(d, C6 / C2, MAX / (C6 / C2));
- }
-
- public long toSeconds(long d) {
- return x(d, C6 / C3, MAX / (C6 / C3));
- }
-
- public long toMinutes(long d) {
- return x(d, C6 / C4, MAX / (C6 / C4));
- }
-
- public long toHours(long d) {
- return x(d, C6 / C5, MAX / (C6 / C5));
- }
-
- public long toDays(long d) {
- return d;
- }
-
- public long convert(long d, TimeUnit u) {
- return u.toDays(d);
- }
-
- int excessNanos(long d, long m) {
- return 0;
- }
- };
+ private final static long serialVersionUID = 567463171959674600L;
+ public long toNanos(long d) { return x(d, C6/C0, MAX/(C6/C0)); }
+ public long toMicros(long d) { return x(d, C6/C1, MAX/(C6/C1)); }
+ public long toMillis(long d) { return x(d, C6/C2, MAX/(C6/C2)); }
+ public long toSeconds(long d) { return x(d, C6/C3, MAX/(C6/C3)); }
+ public long toMinutes(long d) { return x(d, C6/C4, MAX/(C6/C4)); }
+ public long toHours(long d) { return x(d, C6/C5, MAX/(C6/C5)); }
+ public long toDays(long d) { return d; }
+ public long convert(long d, TimeUnit u) { return u.toDays(d); }
+ int excessNanos(long d, long m) { return 0; }
+ };
private static final TimeUnit[] values = new TimeUnit[] {
- NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, HOURS,
- DAYS
- };
+ NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS
+ };
- // Handy constants for conversion methods
- static final long C0 = 1;
- static final long C1 = C0 * 1000;
- static final long C2 = C1 * 1000;
- static final long C3 = C2 * 1000;
- static final long C4 = C3 * 60;
- static final long C5 = C4 * 60;
- static final long C6 = C5 * 24;
- static final long MAX = Long.MAX_VALUE;
+ public static TimeUnit[] values() {
+ return(TimeUnit[])values.clone();
+ }
/**
* The index of this unit. This value is no longer used in this
@@ -361,47 +153,46 @@
private final int index;
/** name of this unit */
- private final String name;
+ private final String name;
- /** Internal constructor */
- TimeUnit(int index, String name) {
+ /** Internal constructor */ TimeUnit(int index, String name) {
this.index = index;
this.name = name;
}
- public static TimeUnit[] values() {
- return (TimeUnit[]) values.clone();
- }
+ // Handy constants for conversion methods
+ static final long C0 = 1;
+ static final long C1 = C0 * 1000;
+ static final long C2 = C1 * 1000;
+ static final long C3 = C2 * 1000;
+ static final long C4 = C3 * 60;
+ static final long C5 = C4 * 60;
+ static final long C6 = C5 * 24;
+
+ static final long MAX = Long.MAX_VALUE;
/**
* Scale d by m, checking for overflow.
* This has a short name to make above code more readable.
*/
static long x(long d, long m, long over) {
- if (d > over) {
- return Long.MAX_VALUE;
- }
-
- if (d < -over) {
- return Long.MIN_VALUE;
- }
-
+ if (d > over) return Long.MAX_VALUE;
+ if (d < -over) return Long.MIN_VALUE;
return d * m;
}
/**
* Convert the given time duration in the given unit to this
- * unit. Conversions from finer to coarser granularities
+ * unit. Conversions from finer to coarser granularities
* truncate, so lose precision. For example converting
* <tt>999</tt> milliseconds to seconds results in
* <tt>0</tt>. Conversions from coarser to finer granularities
* with arguments that would numerically overflow saturate to
* <tt>Long.MIN_VALUE</tt> if negative or <tt>Long.MAX_VALUE</tt>
* if positive.
- *
- * <p>For example, to convert 10 minutes to milliseconds, use:
+ * For example, to convert 10 minutes to milliseconds, use:
* <tt>TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)</tt>
- *
+ *
* @param sourceDuration the time duration in the given <tt>sourceUnit</tt>
* @param sourceUnit the unit of the <tt>sourceDuration</tt> argument
* @return the converted duration in this unit,
@@ -482,8 +273,7 @@
public abstract long toDays(long duration);
/**
- * Utility to compute the excess-nanosecond argument to wait,
- * sleep, join.
+ * Utility to compute the excess-nanosecond argument to wait, sleep, join.
* @param d the duration
* @param m the number of milliseconds
* @return the number of nanoseconds
@@ -494,27 +284,21 @@
* Performs a timed <tt>Object.wait</tt> using this time unit.
* This is a convenience method that converts timeout arguments
* into the form required by the <tt>Object.wait</tt> method.
- *
- * <p>For example, you could implement a blocking <tt>poll</tt>
- * method (see {@link BlockingQueue#poll BlockingQueue.poll})
- * using:
- *
- * <pre>
- * public synchronized Object poll(long timeout, TimeUnit unit)
- * throws InterruptedException {
- * while (empty) {
- * unit.timedWait(this, timeout);
- * ...
- * }
- * }</pre>
- *
+ * For example, you could implement a blocking <tt>poll</tt>
+ * method(see {@link BlockingQueue#poll BlockingQueue.poll}) using:
+ *
+ * <pre> public synchronized Object poll(long timeout, TimeUnit unit)
+ * throws InterruptedException { while (empty) {
+ * unit.timedWait(this, timeout); ... } }</pre>
+ *
* @param obj the object to wait on
* @param timeout the maximum time to wait. If less than
* or equal to zero, do not wait at all.
* @throws InterruptedException if interrupted while waiting.
* @see java.lang.Object#wait(long, int)
*/
- public void timedWait(Object obj, long timeout) throws InterruptedException {
+ public void timedWait(Object obj, long timeout)
+ throws InterruptedException {
if (timeout > 0) {
long ms = toMillis(timeout);
int ns = excessNanos(timeout, ms);