You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by nd...@apache.org on 2006/08/24 05:42:33 UTC
svn commit: r434296 [10/19] - in /incubator/harmony/enhanced/classlib/trunk:
make/ modules/concurrent/ modules/concurrent/.settings/
modules/concurrent/META-INF/ modules/concurrent/make/
modules/concurrent/src/ modules/concurrent/src/main/ modules/conc...
Added: incubator/harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java?rev=434296&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java Wed Aug 23 20:42:25 2006
@@ -0,0 +1,1117 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.locks;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+import java.util.*;
+
+/**
+ * An implementation of {@link ReadWriteLock} supporting similar
+ * semantics to {@link ReentrantLock}.
+ * <p>This class has the following properties:
+ *
+ * <ul>
+ * <li><b>Acquisition order</b>
+ *
+ * <p> This class does not impose a reader or writer preference
+ * ordering for lock access. However, it does support an optional
+ * <em>fairness</em> policy. When constructed as fair, threads
+ * contend for entry using an approximately arrival-order policy. When
+ * the write lock is released either the longest-waiting single writer
+ * will be assigned the write lock, or if there is a reader waiting
+ * longer than any writer, the set of readers will be assigned the
+ * read lock. When constructed as non-fair, the order of entry to the
+ * lock need not be in arrival order. In either case, if readers are
+ * active and a writer enters the lock then no subsequent readers will
+ * be granted the read lock until after that writer has acquired and
+ * released the write lock.
+ *
+ * <li><b>Reentrancy</b>
+ * <p>This lock allows both readers and writers to reacquire read or
+ * write locks in the style of a {@link ReentrantLock}. Readers are not
+ * allowed until all write locks held by the writing thread have been
+ * released.
+ * <p>Additionally, a writer can acquire the read lock - but not vice-versa.
+ * Among other applications, reentrancy can be useful when
+ * write locks are held during calls or callbacks to methods that
+ * perform reads under read locks.
+ * If a reader tries to acquire the write lock it will never succeed.
+ *
+ * <li><b>Lock downgrading</b>
+ * <p>Reentrancy also allows downgrading from the write lock to a read lock,
+ * by acquiring the write lock, then the read lock and then releasing the
+ * write lock. However, upgrading from a read lock to the write lock, is
+ * <b>not</b> possible.
+ *
+ * <li><b>Interruption of lock acquisition</b>
+ * <p>The read lock and write lock both support interruption during lock
+ * acquisition.
+ *
+ * <li><b>{@link Condition} support</b>
+ * <p>The write lock provides a {@link Condition} implementation that
+ * behaves in the same way, with respect to the write lock, as the
+ * {@link Condition} implementation provided by
+ * {@link ReentrantLock#newCondition} does for {@link ReentrantLock}.
+ * This {@link Condition} can, of course, only be used with the write lock.
+ * <p>The read lock does not support a {@link Condition} and
+ * <tt>readLock().newCondition()</tt> throws
+ * <tt>UnsupportedOperationException</tt>.
+ *
+ * <li><b>Instrumentation</b>
+ * <P> This class supports methods to determine whether locks
+ * are held or contended. These methods are designed for monitoring
+ * system state, not for synchronization control.
+ * </ul>
+ *
+ * <p> 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><b>Sample usages</b>. Here is a code sketch showing how to exploit
+ * reentrancy to perform lock downgrading after updating a cache (exception
+ * handling is elided for simplicity):
+ * <pre>
+ * class CachedData {
+ * Object data;
+ * volatile boolean cacheValid;
+ * ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
+ *
+ * void processCachedData() {
+ * rwl.readLock().lock();
+ * if (!cacheValid) {
+ * // upgrade lock manually
+ * rwl.readLock().unlock(); // must unlock first to obtain writelock
+ * rwl.writeLock().lock();
+ * if (!cacheValid) { // recheck
+ * data = ...
+ * cacheValid = true;
+ * }
+ * // downgrade lock
+ * rwl.readLock().lock(); // reacquire read without giving up write lock
+ * rwl.writeLock().unlock(); // unlock write, still hold read
+ * }
+ *
+ * use(data);
+ * rwl.readLock().unlock();
+ * }
+ * }
+ * </pre>
+ *
+ * ReentrantReadWriteLocks can be used to improve concurrency in some
+ * uses of some kinds of Collections. This is typically worthwhile
+ * only when the collections are expected to be large, accessed by
+ * more reader threads than writer threads, and entail operations with
+ * overhead that outweighs synchronization overhead. For example, here
+ * is a class using a TreeMap that is expected to be large and
+ * concurrently accessed.
+ *
+ * <pre>
+ * class RWDictionary {
+ * private final Map<String, Data> m = new TreeMap<String, Data>();
+ * private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
+ * private final Lock r = rwl.readLock();
+ * private final Lock w = rwl.writeLock();
+ *
+ * public Data get(String key) {
+ * r.lock(); try { return m.get(key); } finally { r.unlock(); }
+ * }
+ * public String[] allKeys() {
+ * r.lock(); try { return m.keySet().toArray(); } finally { r.unlock(); }
+ * }
+ * public Data put(String key, Data value) {
+ * w.lock(); try { return m.put(key, value); } finally { w.unlock(); }
+ * }
+ * public void clear() {
+ * w.lock(); try { m.clear(); } finally { w.unlock(); }
+ * }
+ * }
+ * </pre>
+ *
+ *
+ * <h3>Implementation Notes</h3>
+ *
+ * <p>A reentrant write lock intrinsically defines an owner and can
+ * only be released by the thread that acquired it. In contrast, in
+ * this implementation, the read lock has no concept of ownership, and
+ * there is no requirement that the thread releasing a read lock is
+ * the same as the one that acquired it. However, this property is
+ * not guaranteed to hold in future implementations of this class.
+ *
+ * <p> This lock supports a maximum of 65536 recursive write locks
+ * and 65536 read locks. Attempts to exceed these limits result in
+ * {@link Error} throws from locking methods.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ *
+ */
+public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable {
+ private static final long serialVersionUID = -6992448646407690164L;
+ /** Inner class providing readlock */
+ private final ReentrantReadWriteLock.ReadLock readerLock;
+ /** Inner class providing writelock */
+ private final ReentrantReadWriteLock.WriteLock writerLock;
+ /** Performs all synchronization mechanics */
+ private final Sync sync;
+
+ /**
+ * Creates a new <tt>ReentrantReadWriteLock</tt> with
+ * default ordering properties.
+ */
+ public ReentrantReadWriteLock() {
+ sync = new NonfairSync();
+ readerLock = new ReadLock(this);
+ writerLock = new WriteLock(this);
+ }
+
+ /**
+ * Creates a new <tt>ReentrantReadWriteLock</tt> with
+ * the given fairness policy.
+ *
+ * @param fair true if this lock should use a fair ordering policy
+ */
+ public ReentrantReadWriteLock(boolean fair) {
+ sync = (fair)? new FairSync() : new NonfairSync();
+ readerLock = new ReadLock(this);
+ writerLock = new WriteLock(this);
+ }
+
+ public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }
+ public ReentrantReadWriteLock.ReadLock readLock() { return readerLock; }
+
+ /*
+ * Read vs write count extraction constants and functions.
+ * Lock state is logically divided into two shorts: The lower
+ * one representing the exclusive (writer) lock hold count,
+ * and the upper the shared (reader) hold count.
+ */
+
+ static final int SHARED_SHIFT = 16;
+ static final int SHARED_UNIT = (1 << SHARED_SHIFT);
+ static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
+
+ /** Returns the number of shared holds represented in count */
+ static int sharedCount(int c) { return c >>> SHARED_SHIFT; }
+ /** Returns the number of exclusive holds represented in count */
+ static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
+
+ /**
+ * Synchronization implementation for ReentrantReadWriteLock.
+ * Subclassed into fair and nonfair versions.
+ */
+ abstract static class Sync extends AbstractQueuedSynchronizer {
+ /** Current (exclusive) owner thread */
+ transient Thread owner;
+
+ /**
+ * Perform write lock. Allows fast path in non-fair version.
+ */
+ abstract void wlock();
+
+ /**
+ * Perform non-fair tryLock for write. tryAcquire is
+ * implemented in subclasses, but both versions need nonfair
+ * try for trylock method
+ */
+ final boolean nonfairTryAcquire(int acquires) {
+ // mask out readlocks if called from condition methods
+ acquires = exclusiveCount(acquires);
+ Thread current = Thread.currentThread();
+ int c = getState();
+ int w = exclusiveCount(c);
+ if (w + acquires >= SHARED_UNIT)
+ throw new Error("Maximum lock count exceeded");
+ if (c != 0 && (w == 0 || current != owner))
+ return false;
+ if (!compareAndSetState(c, c + acquires))
+ return false;
+ owner = current;
+ return true;
+ }
+
+ /**
+ * Perform nonfair tryLock for read.
+ */
+ final int nonfairTryAcquireShared(int acquires) {
+ for (;;) {
+ int c = getState();
+ int nextc = c + (acquires << SHARED_SHIFT);
+ if (nextc < c)
+ throw new Error("Maximum lock count exceeded");
+ if (exclusiveCount(c) != 0 &&
+ owner != Thread.currentThread())
+ return -1;
+ if (compareAndSetState(c, nextc))
+ return 1;
+ // Recheck count if lost CAS
+ }
+ }
+
+ protected final boolean tryRelease(int releases) {
+ Thread current = Thread.currentThread();
+ int c = getState();
+ if (owner != current)
+ throw new IllegalMonitorStateException();
+ int nextc = c - releases;
+ boolean free = false;
+ if (exclusiveCount(c) == releases) {
+ free = true;
+ owner = null;
+ }
+ setState(nextc);
+ return free;
+ }
+
+ protected final boolean tryReleaseShared(int releases) {
+ for (;;) {
+ int c = getState();
+ int nextc = c - (releases << SHARED_SHIFT);
+ if (nextc < 0)
+ throw new IllegalMonitorStateException();
+ if (compareAndSetState(c, nextc))
+ return nextc == 0;
+ }
+ }
+
+ protected final boolean isHeldExclusively() {
+ return exclusiveCount(getState()) != 0 &&
+ owner == Thread.currentThread();
+ }
+
+ // Methods relayed to outer class
+
+ final ConditionObject newCondition() {
+ return new ConditionObject();
+ }
+
+ final Thread getOwner() {
+ int c = exclusiveCount(getState());
+ Thread o = owner;
+ return (c == 0)? null : o;
+ }
+
+ final int getReadLockCount() {
+ return sharedCount(getState());
+ }
+
+ final boolean isWriteLocked() {
+ return exclusiveCount(getState()) != 0;
+ }
+
+ final int getWriteHoldCount() {
+ int c = exclusiveCount(getState());
+ Thread o = owner;
+ return (o == Thread.currentThread())? c : 0;
+ }
+
+ /**
+ * Reconstitute this lock instance from a stream
+ * @param s the stream
+ */
+ private void readObject(java.io.ObjectInputStream s)
+ throws java.io.IOException, ClassNotFoundException {
+ s.defaultReadObject();
+ setState(0); // reset to unlocked state
+ }
+
+ final int getCount() { return getState(); }
+ }
+
+ /**
+ * Nonfair version of Sync
+ */
+ final static class NonfairSync extends Sync {
+ protected final boolean tryAcquire(int acquires) {
+ return nonfairTryAcquire(acquires);
+ }
+
+ protected final int tryAcquireShared(int acquires) {
+ return nonfairTryAcquireShared(acquires);
+ }
+
+ // Use fastpath for main write lock method
+ final void wlock() {
+ if (compareAndSetState(0, 1))
+ owner = Thread.currentThread();
+ else
+ acquire(1);
+ }
+ }
+
+ /**
+ * Fair version of Sync
+ */
+ final static class FairSync extends Sync {
+ protected final boolean tryAcquire(int acquires) {
+ // mask out readlocks if called from condition methods
+ acquires = exclusiveCount(acquires);
+ Thread current = Thread.currentThread();
+ Thread first;
+ int c = getState();
+ int w = exclusiveCount(c);
+ if (w + acquires >= SHARED_UNIT)
+ throw new Error("Maximum lock count exceeded");
+ if ((w == 0 || current != owner) &&
+ (c != 0 ||
+ ((first = getFirstQueuedThread()) != null &&
+ first != current)))
+ return false;
+ if (!compareAndSetState(c, c + acquires))
+ return false;
+ owner = current;
+ return true;
+ }
+
+ protected final int tryAcquireShared(int acquires) {
+ Thread current = Thread.currentThread();
+ for (;;) {
+ Thread first = getFirstQueuedThread();
+ if (first != null && first != current)
+ return -1;
+ int c = getState();
+ int nextc = c + (acquires << SHARED_SHIFT);
+ if (nextc < c)
+ throw new Error("Maximum lock count exceeded");
+ if (exclusiveCount(c) != 0 &&
+ owner != Thread.currentThread())
+ return -1;
+ if (compareAndSetState(c, nextc))
+ return 1;
+ // Recheck count if lost CAS
+ }
+ }
+
+ final void wlock() { // no fast path
+ acquire(1);
+ }
+ }
+
+ /**
+ * The lock returned by method {@link ReentrantReadWriteLock#readLock}.
+ */
+ public static class ReadLock implements Lock, java.io.Serializable {
+ private static final long serialVersionUID = -5992448646407690164L;
+ private final Sync sync;
+
+ /**
+ * Constructor for use by subclasses
+ * @param lock the outer lock object
+ * @throws NullPointerException if lock null
+ */
+ protected ReadLock(ReentrantReadWriteLock lock) {
+ sync = lock.sync;
+ }
+
+ /**
+ * Acquires the shared lock.
+ *
+ * <p>Acquires the lock if it is not held exclusively by
+ * another thread and returns immediately.
+ *
+ * <p>If the lock is held exclusively by another thread then
+ * the current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until the lock has been acquired.
+ */
+ public void lock() {
+ sync.acquireShared(1);
+ }
+
+ /**
+ * Acquires the shared lock unless the current thread is
+ * {@link Thread#interrupt interrupted}.
+ *
+ * <p>Acquires the shared lock if it is not held exclusively
+ * by another thread and 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 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.acquireSharedInterruptibly(1);
+ }
+
+ /**
+ * Acquires the shared lock only if it is not held exclusively by
+ * another thread at the time of invocation.
+ *
+ * <p>Acquires the lock if it is not held exclusively by
+ * another thread and returns immediately with the value
+ * <tt>true</tt>. 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 lock is held exclusively by another thread then
+ * this method will return immediately with the value
+ * <tt>false</tt>.
+ *
+ * @return <tt>true</tt> if the lock was acquired.
+ */
+ public boolean tryLock() {
+ return sync.nonfairTryAcquireShared(1) >= 0;
+ }
+
+ /**
+ * Acquires the shared lock if it is not held exclusively 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 exclusively by
+ * another thread and returns immediately with the value
+ * <tt>true</tt>. 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 lock is held exclusively 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.
+ *
+ * <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 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.tryAcquireSharedNanos(1, unit.toNanos(timeout));
+ }
+
+ /**
+ * Attempts to release this lock.
+ *
+ * <p> If the number of readers is now zero then the lock
+ * is made available for other lock attempts.
+ */
+ public void unlock() {
+ sync.releaseShared(1);
+ }
+
+ /**
+ * Throws UnsupportedOperationException because ReadLocks
+ * do not support conditions.
+ * @throws UnsupportedOperationException always
+ */
+ public Condition newCondition() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns a string identifying this lock, as well as its lock state.
+ * The state, in brackets, includes the String
+ * "Read locks =" followed by the number of held
+ * read locks.
+ * @return a string identifying this lock, as well as its lock state.
+ */
+ public String toString() {
+ int r = sync.getReadLockCount();
+ return super.toString() +
+ "[Read locks = " + r + "]";
+ }
+
+ }
+
+ /**
+ * The lock returned by method {@link ReentrantReadWriteLock#writeLock}.
+ */
+ public static class WriteLock implements Lock, java.io.Serializable {
+ private static final long serialVersionUID = -4992448646407690164L;
+ private final Sync sync;
+
+ /**
+ * Constructor for use by subclasses
+ * @param lock the outer lock object
+ * @throws NullPointerException if lock null
+ */
+ protected WriteLock(ReentrantReadWriteLock lock) {
+ sync = lock.sync;
+ }
+
+ /**
+ * Acquire 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.wlock();
+ }
+
+ /**
+ * 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.acquireInterruptibly(1);
+ }
+
+ /**
+ * 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.nonfairTryAcquire(1);
+ }
+
+ /**
+ * 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.tryAcquireNanos(1, unit.toNanos(timeout));
+ }
+
+ /**
+ * 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.release(1);
+ }
+
+ /**
+ * 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 write lock is not held when any {@link
+ * Condition} method is called then an {@link
+ * IllegalMonitorStateException} is thrown. (Read locks are
+ * held independently of write locks, so are not checked or
+ * affected. However it is essentially always an error to
+ * invoke a condition waiting method when the current thread
+ * has also acquired read locks, since other threads that
+ * could unblock it will not be able to access the write
+ * lock.)
+ *
+ * <li>When the condition {@link Condition#await() waiting}
+ * methods are called the write lock is released and, before
+ * they return, the write 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 sync.newCondition();
+ }
+
+ /**
+ * 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 owner = sync.getOwner();
+ return super.toString() + ((owner == null) ?
+ "[Unlocked]" :
+ "[Locked by thread " + owner.getName() + "]");
+ }
+
+ }
+
+
+ // Instrumentation and status
+
+ /**
+ * Returns true if this lock has fairness set true.
+ * @return true if this lock has fairness set true.
+ */
+ public final boolean isFair() {
+ return sync instanceof FairSync;
+ }
+
+ /**
+ * Returns the thread that currently owns the exclusive lock, or
+ * <tt>null</tt> if not owned. Note that 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 the number of read locks held for this lock. This
+ * method is designed for use in monitoring system state, not for
+ * synchronization control.
+ * @return the number of read locks held.
+ */
+ public int getReadLockCount() {
+ return sync.getReadLockCount();
+ }
+
+ /**
+ * Queries if the write lock is held by any thread. This method is
+ * designed for use in monitoring system state, not for
+ * synchronization control.
+ * @return <tt>true</tt> if any thread holds write lock and
+ * <tt>false</tt> otherwise.
+ */
+ public boolean isWriteLocked() {
+ return sync.isWriteLocked();
+ }
+
+ /**
+ * Queries if the write lock is held by the current thread.
+ * @return <tt>true</tt> if current thread holds this lock and
+ * <tt>false</tt> otherwise.
+ */
+ public boolean isWriteLockedByCurrentThread() {
+ return sync.isHeldExclusively();
+ }
+
+ /**
+ * Queries the number of reentrant write holds on this lock by the
+ * current thread. A writer thread has a hold on a lock for
+ * each lock action that is not matched by an unlock action.
+ *
+ * @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 getWriteHoldCount() {
+ return sync.getWriteHoldCount();
+ }
+
+ /**
+ * Returns a collection containing threads that may be waiting to
+ * acquire the write 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 lock monitoring facilities.
+ * @return the collection of threads
+ */
+ protected Collection<Thread> getQueuedWriterThreads() {
+ return sync.getExclusiveQueuedThreads();
+ }
+
+ /**
+ * Returns a collection containing threads that may be waiting to
+ * acquire the read 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 lock monitoring facilities.
+ * @return the collection of threads
+ */
+ protected Collection<Thread> getQueuedReaderThreads() {
+ return sync.getSharedQueuedThreads();
+ }
+
+ /**
+ * Queries whether any threads are waiting to acquire. 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 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 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. 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. 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<Thread> getQueuedThreads() {
+ return sync.getQueuedThreads();
+ }
+
+ /**
+ * Queries whether any threads are waiting on the given condition
+ * associated with the write 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) {
+ if (condition == null)
+ throw new NullPointerException();
+ if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
+ throw new IllegalArgumentException("not owner");
+ return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
+ }
+
+ /**
+ * Returns an estimate of the number of threads waiting on the
+ * given condition associated with the write 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) {
+ if (condition == null)
+ throw new NullPointerException();
+ if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
+ throw new IllegalArgumentException("not owner");
+ return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
+ }
+
+ /**
+ * Returns a collection containing those threads that may be
+ * waiting on the given condition associated with the write 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<Thread> getWaitingThreads(Condition condition) {
+ if (condition == null)
+ throw new NullPointerException();
+ if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
+ throw new IllegalArgumentException("not owner");
+ return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
+ }
+
+ /**
+ * Returns a string identifying this lock, as well as its lock state.
+ * The state, in brackets, includes the String "Write locks ="
+ * follwed by the number of reentrantly held write locks, and the
+ * String "Read locks =" followed by the number of held
+ * read locks.
+ * @return a string identifying this lock, as well as its lock state.
+ */
+ public String toString() {
+ int c = sync.getCount();
+ int w = exclusiveCount(c);
+ int r = sharedCount(c);
+
+ return super.toString() +
+ "[Write locks = " + w + ", Read locks = " + r + "]";
+ }
+
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/locks/package.html
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/locks/package.html?rev=434296&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/locks/package.html (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/locks/package.html Wed Aug 23 20:42:25 2006
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html> <head>
+<title>Locks</title>
+</head>
+
+<body>
+
+Interfaces and classes providing a framework for locking and waiting
+for conditions that is distinct from built-in synchronization and
+monitors. The framework permits much greater flexibility in the use of
+locks and conditions, at the expense of more awkward syntax.
+
+<p> The {@link java.util.concurrent.locks.Lock} interface supports
+locking disciplines that differ in semantics (reentrant, fair, etc),
+and that can be used in non-block-structured contexts including
+hand-over-hand and lock reordering algorithms. The main implementation
+is {@link java.util.concurrent.locks.ReentrantLock}.
+
+<p> The {@link java.util.concurrent.locks.ReadWriteLock} interface
+similarly defines locks that may be shared among readers but are
+exclusive to writers. Only a single implementation, {@link
+java.util.concurrent.locks.ReentrantReadWriteLock}, is provided, since
+it covers most standard usage contexts. But programmers may create
+their own implementations to cover nonstandard requirements.
+
+<p> The {@link java.util.concurrent.locks.Condition} interface
+describes condition variables that may be associated with Locks.
+These are similar in usage to the implicit monitors accessed using
+<tt>Object.wait</tt>, but offer extended capabilities. In particular,
+multiple <tt>Condition</tt> objects may be associated with a single
+<tt>Lock</tt>. To avoid compatibility issues, the names of
+<tt>Condition</tt> methods are different than the corresponding
+<tt>Object</tt> versions.
+
+<p> The {@link java.util.concurrent.locks.AbstractQueuedSynchronizer}
+class serves as a useful superclass for defining locks and other
+synchronizers that rely on queuing blocked threads. The {@link
+java.util.concurrent.locks.LockSupport} class provides lower-level
+blocking and unblocking support that is useful for those developers
+implementing their own customized lock classes.
+
+@since 1.5
+
+</body> </html>
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/locks/package.html
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/package.html
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/package.html?rev=434296&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/package.html (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/package.html Wed Aug 23 20:42:25 2006
@@ -0,0 +1,125 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html> <head>
+<title>Concurrency Utilities</title>
+</head>
+
+<body>
+
+<p> Utility classes commonly useful in concurrent programming. This
+package includes a few small standardized extensible frameworks, as
+well as some classes that provide useful functionality and are
+otherwise tedious or difficult to implement. Here are brief
+descriptions of the main components. See also the <tt>locks</tt> and
+<tt>atomic</tt> packages.
+
+<h2>Executors</h2>
+
+<b>Interfaces.</b> {@link java.util.concurrent.Executor} is a simple
+standardized interface for defining custom thread-like subsystems,
+including thread pools, asynchronous IO, and lightweight task
+frameworks. Depending on which concrete Executor class is being used,
+tasks may execute in a newly created thread, an existing
+task-execution thread, or the thread calling <tt>execute()</tt>, and
+may execute sequentially or concurrently. {@link
+java.util.concurrent.ExecutorService} provides a more complete
+asynchronous task execution framework. An ExecutorService manages
+queuing and scheduling of tasks, and allows controlled shutdown. The
+{@link java.util.concurrent.ScheduledExecutorService} subinterface
+adds support for delayed and periodic task execution.
+ExecutorServices provide methods arranging asynchronous execution of
+any function expressed as {@link java.util.concurrent.Callable}, the
+result-bearing analog of {@link java.lang.Runnable}. A {@link
+java.util.concurrent.Future} returns the results of a function, allows
+determination of whether execution has completed, and provides a means to
+cancel execution.
+
+<p>
+
+<b>Implementations.</b> Classes {@link
+java.util.concurrent.ThreadPoolExecutor} and {@link
+java.util.concurrent.ScheduledThreadPoolExecutor} provide tunable,
+flexible thread pools. The {@link java.util.concurrent.Executors}
+class provides factory methods for the most common kinds and
+configurations of Executors, as well as a few utility methods for
+using them. Other utilities based on Executors include the concrete
+class {@link java.util.concurrent.FutureTask} providing a common
+extensible implementation of Futures, and {@link
+java.util.concurrent.ExecutorCompletionService}, that assists in
+coordinating the processing of groups of asynchronous tasks.
+
+<h2>Queues</h2>
+
+The java.util.concurrent {@link
+java.util.concurrent.ConcurrentLinkedQueue} class supplies an
+efficient scalable thread-safe non-blocking FIFO queue. Five
+implementations in java.util.concurrent support the extended {@link
+java.util.concurrent.BlockingQueue} interface, that defines blocking
+versions of put and take: {@link
+java.util.concurrent.LinkedBlockingQueue}, {@link
+java.util.concurrent.ArrayBlockingQueue}, {@link
+java.util.concurrent.SynchronousQueue}, {@link
+java.util.concurrent.PriorityBlockingQueue}, and {@link
+java.util.concurrent.DelayQueue}. The different classes cover the most
+common usage contexts for producer-consumer, messaging, parallel
+tasking, and related concurrent designs.
+
+
+<h2>Timing</h2>
+
+The {@link java.util.concurrent.TimeUnit} class provides multiple
+granularities (including nanoseconds) for specifying and controlling
+time-out based operations. Most classes in the package contain
+operations based on time-outs in addition to indefinite waits. In all
+cases that time-outs are used, the time-out specifies the minimum time
+that the method should wait before indicating that it
+timed-out. Implementations make a "best effort" to detect
+time-outs as soon as possible after they occur. However, an indefinite
+amount of time may elapse between a time-out being detected and a
+thread actually executing again after that time-out.
+
+<h2>Synchronizers</h2>
+
+Four classes aid common special-purpose synchronization idioms.
+{@link java.util.concurrent.Semaphore} is a classic concurrency tool.
+{@link java.util.concurrent.CountDownLatch} is a very simple yet very
+common utility for blocking until a given number of signals, events,
+or conditions hold. A {@link java.util.concurrent.CyclicBarrier} is a
+resettable multiway synchronization point useful in some styles of
+parallel programming. An {@link java.util.concurrent.Exchanger} allows
+two threads to exchange objects at a rendezvous point, and is useful
+in several pipeline designs.
+
+<h2>Concurrent Collections</h2>
+
+Besides Queues, this package supplies a few Collection implementations
+designed for use in multithreaded contexts: {@link
+java.util.concurrent.ConcurrentHashMap}, {@link
+java.util.concurrent.CopyOnWriteArrayList}, and {@link
+java.util.concurrent.CopyOnWriteArraySet}.
+
+<p>The "Concurrent" prefix used with some classes in this package is a
+shorthand indicating several differences from similar "synchronized"
+classes. For example <tt>java.util.Hashtable</tt> and
+<tt>Collections.synchronizedMap(new HashMap())</tt> are
+synchronized. But {@link java.util.concurrent.ConcurrentHashMap} is
+"concurrent". A concurrent collection is thread-safe, but not
+governed by a single exclusion lock. In the particular case of
+ConcurrentHashMap, it safely permits any number of concurrent reads as
+well as a tunable number of concurrent writes. "Synchronized" classes
+can be useful when you need to prevent all access to a collection via
+a single lock, at the expense of poorer scalability. In other cases in
+which multiple threads are expected to access a common collection,
+"concurrent" versions are normally preferable. And unsynchronized
+collections are preferable when either collections are unshared, or
+are accessible only when holding other locks.
+
+<p> Most concurrent Collection implementations (including most Queues)
+also differ from the usual java.util conventions in that their Iterators
+provide <em>weakly consistent</em> rather than fast-fail traversal. A
+weakly consistent iterator is thread-safe, but does not necessarily
+freeze the collection while iterating, so it may (or may not) reflect
+any updates since the iterator was created.
+
+@since 1.5
+
+</body> </html>
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/package.html
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/harmony/enhanced/classlib/trunk/modules/concurrent/src/test/java/AbstractExecutorServiceTest.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/concurrent/src/test/java/AbstractExecutorServiceTest.java?rev=434296&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/concurrent/src/test/java/AbstractExecutorServiceTest.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/concurrent/src/test/java/AbstractExecutorServiceTest.java Wed Aug 23 20:42:25 2006
@@ -0,0 +1,807 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
+ */
+
+
+import junit.framework.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.math.BigInteger;
+import java.security.*;
+
+public class AbstractExecutorServiceTest extends JSR166TestCase{
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run (suite());
+ }
+ public static Test suite() {
+ return new TestSuite(AbstractExecutorServiceTest.class);
+ }
+
+ /**
+ * A no-frills implementation of AbstractExecutorService, designed
+ * to test the submit methods only.
+ */
+ static class DirectExecutorService extends AbstractExecutorService {
+ public void execute(Runnable r) { r.run(); }
+ public void shutdown() { shutdown = true; }
+ public List<Runnable> shutdownNow() { shutdown = true; return Collections.EMPTY_LIST; }
+ public boolean isShutdown() { return shutdown; }
+ public boolean isTerminated() { return isShutdown(); }
+ public boolean awaitTermination(long timeout, TimeUnit unit) { return isShutdown(); }
+ private volatile boolean shutdown = false;
+ }
+
+ /**
+ * execute(runnable) runs it to completion
+ */
+ public void testExecuteRunnable() {
+ try {
+ ExecutorService e = new DirectExecutorService();
+ TrackedShortRunnable task = new TrackedShortRunnable();
+ assertFalse(task.done);
+ Future<?> future = e.submit(task);
+ future.get();
+ assertTrue(task.done);
+ }
+ catch (ExecutionException ex) {
+ unexpectedException();
+ }
+ catch (InterruptedException ex) {
+ unexpectedException();
+ }
+ }
+
+
+ /**
+ * Completed submit(callable) returns result
+ */
+ public void testSubmitCallable() {
+ try {
+ ExecutorService e = new DirectExecutorService();
+ Future<String> future = e.submit(new StringTask());
+ String result = future.get();
+ assertSame(TEST_STRING, result);
+ }
+ catch (ExecutionException ex) {
+ unexpectedException();
+ }
+ catch (InterruptedException ex) {
+ unexpectedException();
+ }
+ }
+
+ /**
+ * Completed submit(runnable) returns successfully
+ */
+ public void testSubmitRunnable() {
+ try {
+ ExecutorService e = new DirectExecutorService();
+ Future<?> future = e.submit(new NoOpRunnable());
+ future.get();
+ assertTrue(future.isDone());
+ }
+ catch (ExecutionException ex) {
+ unexpectedException();
+ }
+ catch (InterruptedException ex) {
+ unexpectedException();
+ }
+ }
+
+ /**
+ * Completed submit(runnable, result) returns result
+ */
+ public void testSubmitRunnable2() {
+ try {
+ ExecutorService e = new DirectExecutorService();
+ Future<String> future = e.submit(new NoOpRunnable(), TEST_STRING);
+ String result = future.get();
+ assertSame(TEST_STRING, result);
+ }
+ catch (ExecutionException ex) {
+ unexpectedException();
+ }
+ catch (InterruptedException ex) {
+ unexpectedException();
+ }
+ }
+
+
+ /**
+ * A submitted privileged action to completion
+ */
+ public void testSubmitPrivilegedAction() {
+ Policy savedPolicy = null;
+ try {
+ savedPolicy = Policy.getPolicy();
+ AdjustablePolicy policy = new AdjustablePolicy();
+ policy.addPermission(new RuntimePermission("getContextClassLoader"));
+ policy.addPermission(new RuntimePermission("setContextClassLoader"));
+ Policy.setPolicy(policy);
+ } catch(AccessControlException ok) {
+ return;
+ }
+ try {
+ ExecutorService e = new DirectExecutorService();
+ Future future = e.submit(Executors.callable(new PrivilegedAction() {
+ public Object run() {
+ return TEST_STRING;
+ }}));
+
+ Object result = future.get();
+ assertSame(TEST_STRING, result);
+ }
+ catch (ExecutionException ex) {
+ unexpectedException();
+ }
+ catch (InterruptedException ex) {
+ unexpectedException();
+ }
+ finally {
+ try {
+ Policy.setPolicy(savedPolicy);
+ } catch(AccessControlException ok) {
+ return;
+ }
+ }
+ }
+
+ /**
+ * A submitted a privileged exception action runs to completion
+ */
+ public void testSubmitPrivilegedExceptionAction() {
+ Policy savedPolicy = null;
+ try {
+ savedPolicy = Policy.getPolicy();
+ AdjustablePolicy policy = new AdjustablePolicy();
+ policy.addPermission(new RuntimePermission("getContextClassLoader"));
+ policy.addPermission(new RuntimePermission("setContextClassLoader"));
+ Policy.setPolicy(policy);
+ } catch(AccessControlException ok) {
+ return;
+ }
+
+ try {
+ ExecutorService e = new DirectExecutorService();
+ Future future = e.submit(Executors.callable(new PrivilegedExceptionAction() {
+ public Object run() {
+ return TEST_STRING;
+ }}));
+
+ Object result = future.get();
+ assertSame(TEST_STRING, result);
+ }
+ catch (ExecutionException ex) {
+ unexpectedException();
+ }
+ catch (InterruptedException ex) {
+ unexpectedException();
+ }
+ finally {
+ Policy.setPolicy(savedPolicy);
+ }
+ }
+
+ /**
+ * A submitted failed privileged exception action reports exception
+ */
+ public void testSubmitFailedPrivilegedExceptionAction() {
+ Policy savedPolicy = null;
+ try {
+ savedPolicy = Policy.getPolicy();
+ AdjustablePolicy policy = new AdjustablePolicy();
+ policy.addPermission(new RuntimePermission("getContextClassLoader"));
+ policy.addPermission(new RuntimePermission("setContextClassLoader"));
+ Policy.setPolicy(policy);
+ } catch(AccessControlException ok) {
+ return;
+ }
+
+
+ try {
+ ExecutorService e = new DirectExecutorService();
+ Future future = e.submit(Executors.callable(new PrivilegedExceptionAction() {
+ public Object run() throws Exception {
+ throw new IndexOutOfBoundsException();
+ }}));
+
+ Object result = future.get();
+ shouldThrow();
+ }
+ catch (ExecutionException success) {
+ }
+ catch (InterruptedException ex) {
+ unexpectedException();
+ }
+ finally {
+ Policy.setPolicy(savedPolicy);
+ }
+ }
+
+ /**
+ * execute(null runnable) throws NPE
+ */
+ public void testExecuteNullRunnable() {
+ try {
+ ExecutorService e = new DirectExecutorService();
+ TrackedShortRunnable task = null;
+ Future<?> future = e.submit(task);
+ shouldThrow();
+ }
+ catch (NullPointerException success) {
+ }
+ catch (Exception ex) {
+ unexpectedException();
+ }
+ }
+
+
+ /**
+ * submit(null callable) throws NPE
+ */
+ public void testSubmitNullCallable() {
+ try {
+ ExecutorService e = new DirectExecutorService();
+ StringTask t = null;
+ Future<String> future = e.submit(t);
+ shouldThrow();
+ }
+ catch (NullPointerException success) {
+ }
+ catch (Exception ex) {
+ unexpectedException();
+ }
+ }
+
+ /**
+ * submit(runnable) throws RejectedExecutionException if
+ * executor is saturated.
+ */
+ public void testExecute1() {
+ ThreadPoolExecutor p = new ThreadPoolExecutor(1,1, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1));
+ try {
+
+ for(int i = 0; i < 5; ++i){
+ p.submit(new MediumRunnable());
+ }
+ shouldThrow();
+ } catch(RejectedExecutionException success){}
+ joinPool(p);
+ }
+
+ /**
+ * submit(callable) throws RejectedExecutionException
+ * if executor is saturated.
+ */
+ public void testExecute2() {
+ ThreadPoolExecutor p = new ThreadPoolExecutor(1,1, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1));
+ try {
+ for(int i = 0; i < 5; ++i) {
+ p.submit(new SmallCallable());
+ }
+ shouldThrow();
+ } catch(RejectedExecutionException e){}
+ joinPool(p);
+ }
+
+
+ /**
+ * Blocking on submit(callable) throws InterruptedException if
+ * caller interrupted.
+ */
+ public void testInterruptedSubmit() {
+ final ThreadPoolExecutor p = new ThreadPoolExecutor(1,1,60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10));
+ Thread t = new Thread(new Runnable() {
+ public void run() {
+ try {
+ p.submit(new Callable<Object>() {
+ public Object call() {
+ try {
+ Thread.sleep(MEDIUM_DELAY_MS);
+ shouldThrow();
+ } catch(InterruptedException e){
+ }
+ return null;
+ }
+ }).get();
+ } catch(InterruptedException success){
+ } catch(Exception e) {
+ unexpectedException();
+ }
+
+ }
+ });
+ try {
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ } catch(Exception e){
+ unexpectedException();
+ }
+ joinPool(p);
+ }
+
+ /**
+ * get of submitted callable throws Exception if callable
+ * interrupted
+ */
+ public void testSubmitIE() {
+ final ThreadPoolExecutor p = new ThreadPoolExecutor(1,1,60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10));
+
+ final Callable c = new Callable() {
+ public Object call() {
+ try {
+ p.submit(new SmallCallable()).get();
+ shouldThrow();
+ } catch(InterruptedException e){}
+ catch(RejectedExecutionException e2){}
+ catch(ExecutionException e3){}
+ return Boolean.TRUE;
+ }
+ };
+
+
+
+ Thread t = new Thread(new Runnable() {
+ public void run() {
+ try {
+ c.call();
+ } catch(Exception e){}
+ }
+ });
+ try {
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
+ } catch(InterruptedException e){
+ unexpectedException();
+ }
+
+ joinPool(p);
+ }
+
+ /**
+ * get of submit(callable) throws ExecutionException if callable
+ * throws exception
+ */
+ public void testSubmitEE() {
+ ThreadPoolExecutor p = new ThreadPoolExecutor(1,1,60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10));
+
+ try {
+ Callable c = new Callable() {
+ public Object call() {
+ int i = 5/0;
+ return Boolean.TRUE;
+ }
+ };
+
+ for(int i =0; i < 5; i++){
+ p.submit(c).get();
+ }
+
+ shouldThrow();
+ }
+ catch(ExecutionException success){
+ } catch(Exception e) {
+ unexpectedException();
+ }
+ joinPool(p);
+ }
+
+ /**
+ * invokeAny(null) throws NPE
+ */
+ public void testInvokeAny1() {
+ ExecutorService e = new DirectExecutorService();
+ try {
+ e.invokeAny(null);
+ } catch (NullPointerException success) {
+ } catch(Exception ex) {
+ unexpectedException();
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * invokeAny(empty collection) throws IAE
+ */
+ public void testInvokeAny2() {
+ ExecutorService e = new DirectExecutorService();
+ try {
+ e.invokeAny(new ArrayList<Callable<String>>());
+ } catch (IllegalArgumentException success) {
+ } catch(Exception ex) {
+ unexpectedException();
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * invokeAny(c) throws NPE if c has null elements
+ */
+ public void testInvokeAny3() {
+ ExecutorService e = new DirectExecutorService();
+ try {
+ ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(null);
+ e.invokeAny(l);
+ } catch (NullPointerException success) {
+ } catch(Exception ex) {
+ ex.printStackTrace();
+ unexpectedException();
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * invokeAny(c) throws ExecutionException if no task in c completes
+ */
+ public void testInvokeAny4() {
+ ExecutorService e = new DirectExecutorService();
+ try {
+ ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new NPETask());
+ e.invokeAny(l);
+ } catch(ExecutionException success) {
+ } catch(Exception ex) {
+ unexpectedException();
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * invokeAny(c) returns result of some task in c if at least one completes
+ */
+ public void testInvokeAny5() {
+ ExecutorService e = new DirectExecutorService();
+ try {
+ ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(new StringTask());
+ String result = e.invokeAny(l);
+ assertSame(TEST_STRING, result);
+ } catch (ExecutionException success) {
+ } catch(Exception ex) {
+ unexpectedException();
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * invokeAll(null) throws NPE
+ */
+ public void testInvokeAll1() {
+ ExecutorService e = new DirectExecutorService();
+ try {
+ e.invokeAll(null);
+ } catch (NullPointerException success) {
+ } catch(Exception ex) {
+ unexpectedException();
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * invokeAll(empty collection) returns empty collection
+ */
+ public void testInvokeAll2() {
+ ExecutorService e = new DirectExecutorService();
+ try {
+ List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>());
+ assertTrue(r.isEmpty());
+ } catch(Exception ex) {
+ unexpectedException();
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * invokeAll(c) throws NPE if c has null elements
+ */
+ public void testInvokeAll3() {
+ ExecutorService e = new DirectExecutorService();
+ try {
+ ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(null);
+ e.invokeAll(l);
+ } catch (NullPointerException success) {
+ } catch(Exception ex) {
+ unexpectedException();
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * get of returned element of invokeAll(c) throws exception on failed task
+ */
+ public void testInvokeAll4() {
+ ExecutorService e = new DirectExecutorService();
+ try {
+ ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new NPETask());
+ List<Future<String>> result = e.invokeAll(l);
+ assertEquals(1, result.size());
+ for (Iterator<Future<String>> it = result.iterator(); it.hasNext();)
+ it.next().get();
+ } catch(ExecutionException success) {
+ } catch(Exception ex) {
+ unexpectedException();
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * invokeAll(c) returns results of all completed tasks in c
+ */
+ public void testInvokeAll5() {
+ ExecutorService e = new DirectExecutorService();
+ try {
+ ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(new StringTask());
+ List<Future<String>> result = e.invokeAll(l);
+ assertEquals(2, result.size());
+ for (Iterator<Future<String>> it = result.iterator(); it.hasNext();)
+ assertSame(TEST_STRING, it.next().get());
+ } catch (ExecutionException success) {
+ } catch(Exception ex) {
+ unexpectedException();
+ } finally {
+ joinPool(e);
+ }
+ }
+
+
+ /**
+ * timed invokeAny(null) throws NPE
+ */
+ public void testTimedInvokeAny1() {
+ ExecutorService e = new DirectExecutorService();
+ try {
+ e.invokeAny(null, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ } catch (NullPointerException success) {
+ } catch(Exception ex) {
+ unexpectedException();
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAny(null time unit) throws NPE
+ */
+ public void testTimedInvokeAnyNullTimeUnit() {
+ ExecutorService e = new DirectExecutorService();
+ try {
+ ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ e.invokeAny(l, MEDIUM_DELAY_MS, null);
+ } catch (NullPointerException success) {
+ } catch(Exception ex) {
+ unexpectedException();
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAny(empty collection) throws IAE
+ */
+ public void testTimedInvokeAny2() {
+ ExecutorService e = new DirectExecutorService();
+ try {
+ e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ } catch (IllegalArgumentException success) {
+ } catch(Exception ex) {
+ unexpectedException();
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAny(c) throws NPE if c has null elements
+ */
+ public void testTimedInvokeAny3() {
+ ExecutorService e = new DirectExecutorService();
+ try {
+ ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(null);
+ e.invokeAny(l, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ } catch (NullPointerException success) {
+ } catch(Exception ex) {
+ ex.printStackTrace();
+ unexpectedException();
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAny(c) throws ExecutionException if no task completes
+ */
+ public void testTimedInvokeAny4() {
+ ExecutorService e = new DirectExecutorService();
+ try {
+ ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new NPETask());
+ e.invokeAny(l, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ } catch(ExecutionException success) {
+ } catch(Exception ex) {
+ unexpectedException();
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAny(c) returns result of some task in c
+ */
+ public void testTimedInvokeAny5() {
+ ExecutorService e = new DirectExecutorService();
+ try {
+ ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(new StringTask());
+ String result = e.invokeAny(l, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ assertSame(TEST_STRING, result);
+ } catch (ExecutionException success) {
+ } catch(Exception ex) {
+ unexpectedException();
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAll(null) throws NPE
+ */
+ public void testTimedInvokeAll1() {
+ ExecutorService e = new DirectExecutorService();
+ try {
+ e.invokeAll(null, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ } catch (NullPointerException success) {
+ } catch(Exception ex) {
+ unexpectedException();
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAll(null time unit) throws NPE
+ */
+ public void testTimedInvokeAllNullTimeUnit() {
+ ExecutorService e = new DirectExecutorService();
+ try {
+ ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ e.invokeAll(l, MEDIUM_DELAY_MS, null);
+ } catch (NullPointerException success) {
+ } catch(Exception ex) {
+ unexpectedException();
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAll(empty collection) returns empty collection
+ */
+ public void testTimedInvokeAll2() {
+ ExecutorService e = new DirectExecutorService();
+ try {
+ List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ assertTrue(r.isEmpty());
+ } catch(Exception ex) {
+ unexpectedException();
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAll(c) throws NPE if c has null elements
+ */
+ public void testTimedInvokeAll3() {
+ ExecutorService e = new DirectExecutorService();
+ try {
+ ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(null);
+ e.invokeAll(l, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ } catch (NullPointerException success) {
+ } catch(Exception ex) {
+ unexpectedException();
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * get of returned element of invokeAll(c) throws exception on failed task
+ */
+ public void testTimedInvokeAll4() {
+ ExecutorService e = new DirectExecutorService();
+ try {
+ ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new NPETask());
+ List<Future<String>> result = e.invokeAll(l, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ assertEquals(1, result.size());
+ for (Iterator<Future<String>> it = result.iterator(); it.hasNext();)
+ it.next().get();
+ } catch(ExecutionException success) {
+ } catch(Exception ex) {
+ unexpectedException();
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAll(c) returns results of all completed tasks in c
+ */
+ public void testTimedInvokeAll5() {
+ ExecutorService e = new DirectExecutorService();
+ try {
+ ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(new StringTask());
+ List<Future<String>> result = e.invokeAll(l, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ assertEquals(2, result.size());
+ for (Iterator<Future<String>> it = result.iterator(); it.hasNext();)
+ assertSame(TEST_STRING, it.next().get());
+ } catch (ExecutionException success) {
+ } catch(Exception ex) {
+ unexpectedException();
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAll cancels tasks not completed by timeout
+ */
+ public void testTimedInvokeAll6() {
+ ExecutorService e = new DirectExecutorService();
+ try {
+ ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(Executors.callable(new MediumPossiblyInterruptedRunnable(), TEST_STRING));
+ l.add(new StringTask());
+ List<Future<String>> result = e.invokeAll(l, SMALL_DELAY_MS, TimeUnit.MILLISECONDS);
+ assertEquals(3, result.size());
+ Iterator<Future<String>> it = result.iterator();
+ Future<String> f1 = it.next();
+ Future<String> f2 = it.next();
+ Future<String> f3 = it.next();
+ assertTrue(f1.isDone());
+ assertFalse(f1.isCancelled());
+ assertTrue(f2.isDone());
+ assertTrue(f3.isDone());
+ assertTrue(f3.isCancelled());
+ } catch(Exception ex) {
+ unexpectedException();
+ } finally {
+ joinPool(e);
+ }
+ }
+
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/concurrent/src/test/java/AbstractExecutorServiceTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/harmony/enhanced/classlib/trunk/modules/concurrent/src/test/java/AbstractQueueTest.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/concurrent/src/test/java/AbstractQueueTest.java?rev=434296&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/concurrent/src/test/java/AbstractQueueTest.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/concurrent/src/test/java/AbstractQueueTest.java Wed Aug 23 20:42:25 2006
@@ -0,0 +1,186 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
+ */
+
+
+import junit.framework.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.locks.*;
+import java.io.*;
+
+public class AbstractQueueTest extends JSR166TestCase {
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run (suite());
+ }
+ public static Test suite() {
+ return new TestSuite(AbstractQueueTest.class);
+ }
+
+ static class Succeed extends AbstractQueue<Integer> {
+ public boolean offer(Integer x) {
+ if (x == null) throw new NullPointerException();
+ return true;
+ }
+ public Integer peek() { return one; }
+ public Integer poll() { return one; }
+ public int size() { return 0; }
+ public Iterator iterator() { return null; } // not needed
+ }
+
+ static class Fail extends AbstractQueue<Integer> {
+ public boolean offer(Integer x) {
+ if (x == null) throw new NullPointerException();
+ return false;
+ }
+ public Integer peek() { return null; }
+ public Integer poll() { return null; }
+ public int size() { return 0; }
+ public Iterator iterator() { return null; } // not needed
+ }
+
+ /**
+ * add returns true if offer succeeds
+ */
+ public void testAddS() {
+ Succeed q = new Succeed();
+ assertTrue(q.add(two));
+ }
+
+ /**
+ * add throws ISE true if offer fails
+ */
+ public void testAddF() {
+ Fail q = new Fail();
+ try {
+ q.add(one);
+ shouldThrow();
+ } catch (IllegalStateException success) {
+ }
+ }
+
+ /**
+ * add throws NPE if offer does
+ */
+ public void testAddNPE() {
+ Succeed q = new Succeed();
+ try {
+ q.add(null);
+ shouldThrow();
+ } catch (NullPointerException success) {
+ }
+ }
+
+ /**
+ * remove returns normally if poll succeeds
+ */
+ public void testRemoveS() {
+ Succeed q = new Succeed();
+ q.remove();
+ }
+
+ /**
+ * remove throws NSEE if poll returns null
+ */
+ public void testRemoveF() {
+ Fail q = new Fail();
+ try {
+ q.remove();
+ shouldThrow();
+ } catch (NoSuchElementException success) {
+ }
+ }
+
+
+ /**
+ * element returns normally if peek succeeds
+ */
+ public void testElementS() {
+ Succeed q = new Succeed();
+ q.element();
+ }
+
+ /**
+ * element throws NSEE if peek returns null
+ */
+ public void testElementF() {
+ Fail q = new Fail();
+ try {
+ q.element();
+ shouldThrow();
+ } catch (NoSuchElementException success) {
+ }
+ }
+
+ /**
+ * addAll(null) throws NPE
+ */
+ public void testAddAll1() {
+ try {
+ Succeed q = new Succeed();
+ q.addAll(null);
+ shouldThrow();
+ }
+ catch (NullPointerException success) {}
+ }
+
+ /**
+ * addAll(this) throws IAE
+ */
+ public void testAddAllSelf() {
+ try {
+ Succeed q = new Succeed();
+ q.addAll(q);
+ shouldThrow();
+ }
+ catch (IllegalArgumentException success) {}
+ }
+
+
+ /**
+ * addAll of a collection with null elements throws NPE
+ */
+ public void testAddAll2() {
+ try {
+ Succeed q = new Succeed();
+ Integer[] ints = new Integer[SIZE];
+ q.addAll(Arrays.asList(ints));
+ shouldThrow();
+ }
+ catch (NullPointerException success) {}
+ }
+ /**
+ * addAll of a collection with any null elements throws NPE after
+ * possibly adding some elements
+ */
+ public void testAddAll3() {
+ try {
+ Succeed q = new Succeed();
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE-1; ++i)
+ ints[i] = new Integer(i);
+ q.addAll(Arrays.asList(ints));
+ shouldThrow();
+ }
+ catch (NullPointerException success) {}
+ }
+ /**
+ * addAll throws ISE if an add fails
+ */
+ public void testAddAll4() {
+ try {
+ Fail q = new Fail();
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = new Integer(i);
+ q.addAll(Arrays.asList(ints));
+ shouldThrow();
+ }
+ catch (IllegalStateException success) {}
+ }
+
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/concurrent/src/test/java/AbstractQueueTest.java
------------------------------------------------------------------------------
svn:eol-style = native