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&lt;String, Data&gt;  m = new TreeMap&lt;String, Data&gt;();
+ *    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 &quot;barging&quot; 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 
+         * &quot;Read locks =&quot; 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 &quot;barging&quot;
+         * 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
+         * &quot;Unlocked&quot; or the String &quot;Locked by&quot;
+         * 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 &quot;Write locks =&quot;
+     * follwed by the number of reentrantly held write locks, and the
+     * String &quot;Read locks =&quot; 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 &quot;best effort&quot; 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