summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Wilson <jessewilson@google.com>2010-04-09 16:48:34 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2010-04-09 16:48:34 -0700
commitcabe39b8ed4f98a711f864267a47a5f58b7d0b10 (patch)
tree6a54ad1628a08678a47e91784c3bcd7c5dde2e4e
parentfc032185188db3fb8fbdb924c4c75f954643e60c (diff)
parent6232a5efed0ea103e35aec73206e5e03a8b82e0c (diff)
downloadlibcore-cabe39b8ed4f98a711f864267a47a5f58b7d0b10.zip
libcore-cabe39b8ed4f98a711f864267a47a5f58b7d0b10.tar.gz
libcore-cabe39b8ed4f98a711f864267a47a5f58b7d0b10.tar.bz2
Merge "Latest java.util.concurrent from the JSR 166 project." into dalvik-dev
-rw-r--r--concurrent/src/main/java/java/util/concurrent/AbstractExecutorService.java82
-rw-r--r--concurrent/src/main/java/java/util/concurrent/ArrayBlockingQueue.java4
-rw-r--r--concurrent/src/main/java/java/util/concurrent/BlockingDeque.java613
-rw-r--r--concurrent/src/main/java/java/util/concurrent/BlockingQueue.java4
-rw-r--r--concurrent/src/main/java/java/util/concurrent/ConcurrentHashMap.java75
-rw-r--r--concurrent/src/main/java/java/util/concurrent/ConcurrentLinkedDeque.java1246
-rw-r--r--concurrent/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java151
-rw-r--r--concurrent/src/main/java/java/util/concurrent/ConcurrentNavigableMap.java148
-rw-r--r--concurrent/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java3115
-rw-r--r--concurrent/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java456
-rw-r--r--concurrent/src/main/java/java/util/concurrent/CopyOnWriteArrayList.java31
-rw-r--r--concurrent/src/main/java/java/util/concurrent/Delayed.java9
-rw-r--r--concurrent/src/main/java/java/util/concurrent/Exchanger.java4
-rw-r--r--concurrent/src/main/java/java/util/concurrent/ExecutorCompletionService.java20
-rw-r--r--concurrent/src/main/java/java/util/concurrent/ExecutorService.java16
-rw-r--r--concurrent/src/main/java/java/util/concurrent/Executors.java17
-rw-r--r--concurrent/src/main/java/java/util/concurrent/FutureTask.java2
-rw-r--r--concurrent/src/main/java/java/util/concurrent/Java6Arrays.java77
-rw-r--r--concurrent/src/main/java/java/util/concurrent/LinkedBlockingDeque.java1137
-rw-r--r--concurrent/src/main/java/java/util/concurrent/LinkedBlockingQueue.java406
-rw-r--r--concurrent/src/main/java/java/util/concurrent/PriorityBlockingQueue.java1
-rw-r--r--concurrent/src/main/java/java/util/concurrent/RunnableFuture.java25
-rw-r--r--concurrent/src/main/java/java/util/concurrent/RunnableScheduledFuture.java29
-rw-r--r--concurrent/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java284
-rw-r--r--concurrent/src/main/java/java/util/concurrent/Semaphore.java4
-rw-r--r--concurrent/src/main/java/java/util/concurrent/SynchronousQueue.java23
-rw-r--r--concurrent/src/main/java/java/util/concurrent/ThreadPoolExecutor.java85
-rw-r--r--concurrent/src/main/java/java/util/concurrent/TimeUnit.java46
-rw-r--r--concurrent/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java16
-rw-r--r--concurrent/src/main/java/java/util/concurrent/atomic/AtomicInteger.java14
-rw-r--r--concurrent/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java121
-rw-r--r--concurrent/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java32
-rw-r--r--concurrent/src/main/java/java/util/concurrent/atomic/AtomicLong.java14
-rw-r--r--concurrent/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java130
-rw-r--r--concurrent/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java49
-rw-r--r--concurrent/src/main/java/java/util/concurrent/atomic/AtomicReference.java14
-rw-r--r--concurrent/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java85
-rw-r--r--concurrent/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java37
-rw-r--r--concurrent/src/main/java/java/util/concurrent/atomic/package-info.java8
-rw-r--r--concurrent/src/main/java/java/util/concurrent/locks/AbstractOwnableSynchronizer.java7
-rw-r--r--concurrent/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java2073
-rw-r--r--concurrent/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java43
-rw-r--r--concurrent/src/main/java/java/util/concurrent/locks/Condition.java18
-rw-r--r--concurrent/src/main/java/java/util/concurrent/locks/LockSupport.java159
-rw-r--r--concurrent/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java39
-rw-r--r--concurrent/src/main/java/java/util/concurrent/locks/package-info.java14
-rw-r--r--concurrent/src/main/java/java/util/concurrent/package-info.java67
-rw-r--r--concurrent/src/test/java/tests/api/java/util/concurrent/AbstractExecutorServiceTest.java631
-rw-r--r--concurrent/src/test/java/tests/api/java/util/concurrent/AbstractQueueTest.java41
-rw-r--r--concurrent/src/test/java/tests/api/java/util/concurrent/AbstractQueuedLongSynchronizerTest.java1025
-rw-r--r--concurrent/src/test/java/tests/api/java/util/concurrent/AbstractQueuedSynchronizerTest.java1352
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/ArrayBlockingQueueTest.java693
-rw-r--r--concurrent/src/test/java/tests/api/java/util/concurrent/ArrayDequeTest.java630
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/AtomicBooleanTest.java110
-rw-r--r--concurrent/src/test/java/tests/api/java/util/concurrent/AtomicIntegerArrayTest.java166
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/AtomicIntegerFieldUpdaterTest.java104
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/AtomicIntegerTest.java156
-rw-r--r--concurrent/src/test/java/tests/api/java/util/concurrent/AtomicLongArrayTest.java183
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/AtomicLongFieldUpdaterTest.java129
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/AtomicLongTest.java157
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/AtomicMarkableReferenceTest.java115
-rw-r--r--concurrent/src/test/java/tests/api/java/util/concurrent/AtomicReferenceArrayTest.java153
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/AtomicReferenceFieldUpdaterTest.java130
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/AtomicReferenceTest.java118
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/AtomicStampedReferenceTest.java115
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentHashMapTest.java120
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentLinkedQueueTest.java161
-rw-r--r--concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentSkipListMapTest.java1280
-rw-r--r--concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentSkipListSetTest.java961
-rw-r--r--concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentSkipListSubMapTest.java1438
-rw-r--r--concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentSkipListSubSetTest.java1117
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/CopyOnWriteArrayListTest.java139
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/CopyOnWriteArraySetTest.java95
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/CountDownLatchTest.java171
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/CyclicBarrierTest.java764
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/DelayQueueTest.java568
-rw-r--r--concurrent/src/test/java/tests/api/java/util/concurrent/EntryTest.java131
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/ExchangerTest.java267
-rw-r--r--concurrent/src/test/java/tests/api/java/util/concurrent/ExecutorCompletionServiceTest.java117
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/ExecutorsTest.java627
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/FutureTaskTest.java430
-rw-r--r--concurrent/src/test/java/tests/api/java/util/concurrent/JSR166TestCase.java565
-rw-r--r--concurrent/src/test/java/tests/api/java/util/concurrent/LinkedBlockingDequeTest.java1671
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/LinkedBlockingQueueTest.java659
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/LockSupportTest.java179
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/PriorityBlockingQueueTest.java578
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/PriorityQueueTest.java169
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/ReentrantLockTest.java1118
-rw-r--r--concurrent/src/test/java/tests/api/java/util/concurrent/ReentrantReadWriteLockTest.java1724
-rw-r--r--concurrent/src/test/java/tests/api/java/util/concurrent/ScheduledExecutorSubclassTest.java1060
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/ScheduledExecutorTest.java754
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/SemaphoreTest.java1015
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/SynchronousQueueTest.java696
-rw-r--r--concurrent/src/test/java/tests/api/java/util/concurrent/SystemTest.java75
-rw-r--r--concurrent/src/test/java/tests/api/java/util/concurrent/ThreadLocalTest.java43
-rw-r--r--concurrent/src/test/java/tests/api/java/util/concurrent/ThreadPoolExecutorSubclassTest.java1578
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/ThreadPoolExecutorTest.java1019
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/ThreadTest.java14
-rwxr-xr-xconcurrent/src/test/java/tests/api/java/util/concurrent/TimeUnitTest.java432
-rw-r--r--luni-kernel/src/main/java/java/lang/Thread.java3
-rw-r--r--luni/src/main/java/java/util/AbstractMap.java238
-rw-r--r--luni/src/main/java/java/util/ArrayDeque.java885
-rw-r--r--luni/src/main/java/java/util/Deque.java255
-rw-r--r--luni/src/main/java/java/util/NavigableMap.java262
-rw-r--r--luni/src/main/java/java/util/NavigableSet.java192
-rw-r--r--suncompat/src/main/java/sun/misc/Unsafe.java34
106 files changed, 30243 insertions, 10419 deletions
diff --git a/concurrent/src/main/java/java/util/concurrent/AbstractExecutorService.java b/concurrent/src/main/java/java/util/concurrent/AbstractExecutorService.java
index f7ed15c..a7c8fe5 100644
--- a/concurrent/src/main/java/java/util/concurrent/AbstractExecutorService.java
+++ b/concurrent/src/main/java/java/util/concurrent/AbstractExecutorService.java
@@ -10,26 +10,74 @@ import java.util.*;
/**
* Provides default implementations of {@link ExecutorService}
* execution methods. This class implements the <tt>submit</tt>,
- * <tt>invokeAny</tt> and <tt>invokeAll</tt> methods using the default
- * {@link FutureTask} class provided in this package. For example,
+ * <tt>invokeAny</tt> and <tt>invokeAll</tt> methods using a
+ * {@link RunnableFuture} returned by <tt>newTaskFor</tt>, which defaults
+ * to the {@link FutureTask} class provided in this package. For example,
* the implementation of <tt>submit(Runnable)</tt> creates an
- * associated <tt>FutureTask</tt> that is executed and
- * returned. Subclasses overriding these methods to use different
- * {@link Future} implementations should do so consistently for each
- * of these methods.
+ * associated <tt>RunnableFuture</tt> that is executed and
+ * returned. Subclasses may override the <tt>newTaskFor</tt> methods
+ * to return <tt>RunnableFuture</tt> implementations other than
+ * <tt>FutureTask</tt>.
*
+ * <p> <b>Extension example</b>. Here is a sketch of a class
+ * that customizes {@link ThreadPoolExecutor} to use
+ * a <tt>CustomTask</tt> class instead of the default <tt>FutureTask</tt>:
+ * <pre>
+ * public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
+ *
+ * static class CustomTask&lt;V&gt; implements RunnableFuture&lt;V&gt; {...}
+ *
+ * protected &lt;V&gt; RunnableFuture&lt;V&gt; newTaskFor(Callable&lt;V&gt; c) {
+ * return new CustomTask&lt;V&gt;(c);
+ * }
+ * protected &lt;V&gt; RunnableFuture&lt;V&gt; newTaskFor(Runnable r, V v) {
+ * return new CustomTask&lt;V&gt;(r, v);
+ * }
+ * // ... add constructors, etc.
+ * }
+ * </pre>
* @since 1.5
* @author Doug Lea
*/
public abstract class AbstractExecutorService implements ExecutorService {
/**
+ * Returns a <tt>RunnableFuture</tt> for the given runnable and default
+ * value.
+ *
+ * @param runnable the runnable task being wrapped
+ * @param value the default value for the returned future
+ * @return a <tt>RunnableFuture</tt> which when run will run the
+ * underlying runnable and which, as a <tt>Future</tt>, will yield
+ * the given value as its result and provide for cancellation of
+ * the underlying task.
+ * @since 1.6
+ */
+ protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
+ return new FutureTask<T>(runnable, value);
+ }
+
+ /**
+ * Returns a <tt>RunnableFuture</tt> for the given callable task.
+ *
+ * @param callable the callable task being wrapped
+ * @return a <tt>RunnableFuture</tt> which when run will call the
+ * underlying callable and which, as a <tt>Future</tt>, will yield
+ * the callable's result as its result and provide for
+ * cancellation of the underlying task.
+ * @since 1.6
+ */
+ protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
+ return new FutureTask<T>(callable);
+ }
+
+ /**
* @throws RejectedExecutionException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
- FutureTask<Object> ftask = new FutureTask<Object>(task, null);
+ RunnableFuture<Object> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}
@@ -40,7 +88,7 @@ public abstract class AbstractExecutorService implements ExecutorService {
*/
public <T> Future<T> submit(Runnable task, T result) {
if (task == null) throw new NullPointerException();
- FutureTask<T> ftask = new FutureTask<T>(task, result);
+ RunnableFuture<T> ftask = newTaskFor(task, result);
execute(ftask);
return ftask;
}
@@ -51,7 +99,7 @@ public abstract class AbstractExecutorService implements ExecutorService {
*/
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
- FutureTask<T> ftask = new FutureTask<T>(task);
+ RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
@@ -59,7 +107,7 @@ public abstract class AbstractExecutorService implements ExecutorService {
/**
* the main mechanics of invokeAny.
*/
- private <T> T doInvokeAny(Collection<Callable<T>> tasks,
+ private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,
boolean timed, long nanos)
throws InterruptedException, ExecutionException, TimeoutException {
if (tasks == null)
@@ -82,7 +130,7 @@ public abstract class AbstractExecutorService implements ExecutorService {
// result, we can throw the last exception we got.
ExecutionException ee = null;
long lastTime = (timed)? System.nanoTime() : 0;
- Iterator<Callable<T>> it = tasks.iterator();
+ Iterator<? extends Callable<T>> it = tasks.iterator();
// Start one task for sure; the rest incrementally
futures.add(ecs.submit(it.next()));
@@ -134,7 +182,7 @@ public abstract class AbstractExecutorService implements ExecutorService {
}
}
- public <T> T invokeAny(Collection<Callable<T>> tasks)
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException {
try {
return doInvokeAny(tasks, false, 0);
@@ -144,13 +192,13 @@ public abstract class AbstractExecutorService implements ExecutorService {
}
}
- public <T> T invokeAny(Collection<Callable<T>> tasks,
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
return doInvokeAny(tasks, true, unit.toNanos(timeout));
}
- public <T> List<Future<T>> invokeAll(Collection<Callable<T>> tasks)
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException {
if (tasks == null)
throw new NullPointerException();
@@ -158,7 +206,7 @@ public abstract class AbstractExecutorService implements ExecutorService {
boolean done = false;
try {
for (Callable<T> t : tasks) {
- FutureTask<T> f = new FutureTask<T>(t);
+ RunnableFuture<T> f = newTaskFor(t);
futures.add(f);
execute(f);
}
@@ -180,7 +228,7 @@ public abstract class AbstractExecutorService implements ExecutorService {
}
}
- public <T> List<Future<T>> invokeAll(Collection<Callable<T>> tasks,
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException {
if (tasks == null || unit == null)
@@ -190,7 +238,7 @@ public abstract class AbstractExecutorService implements ExecutorService {
boolean done = false;
try {
for (Callable<T> t : tasks)
- futures.add(new FutureTask<T>(t));
+ futures.add(newTaskFor(t));
long lastTime = System.nanoTime();
diff --git a/concurrent/src/main/java/java/util/concurrent/ArrayBlockingQueue.java b/concurrent/src/main/java/java/util/concurrent/ArrayBlockingQueue.java
index 0082f07..1c6f613 100644
--- a/concurrent/src/main/java/java/util/concurrent/ArrayBlockingQueue.java
+++ b/concurrent/src/main/java/java/util/concurrent/ArrayBlockingQueue.java
@@ -189,8 +189,8 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
if (capacity < c.size())
throw new IllegalArgumentException();
- for (Iterator<? extends E> it = c.iterator(); it.hasNext();)
- add(it.next());
+ for (E e : c)
+ add(e);
}
/**
diff --git a/concurrent/src/main/java/java/util/concurrent/BlockingDeque.java b/concurrent/src/main/java/java/util/concurrent/BlockingDeque.java
new file mode 100644
index 0000000..d77a965
--- /dev/null
+++ b/concurrent/src/main/java/java/util/concurrent/BlockingDeque.java
@@ -0,0 +1,613 @@
+/*
+ * 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;
+import java.util.*;
+
+/**
+ * A {@link Deque} that additionally supports blocking operations that wait
+ * for the deque to become non-empty when retrieving an element, and wait for
+ * space to become available in the deque when storing an element.
+ *
+ * <p><tt>BlockingDeque</tt> methods come in four forms, with different ways
+ * of handling operations that cannot be satisfied immediately, but may be
+ * satisfied at some point in the future:
+ * one throws an exception, the second returns a special value (either
+ * <tt>null</tt> or <tt>false</tt>, depending on the operation), the third
+ * blocks the current thread indefinitely until the operation can succeed,
+ * and the fourth blocks for only a given maximum time limit before giving
+ * up. These methods are summarized in the following table:
+ *
+ * <p>
+ * <table BORDER CELLPADDING=3 CELLSPACING=1>
+ * <tr>
+ * <td ALIGN=CENTER COLSPAN = 5> <b>First Element (Head)</b></td>
+ * </tr>
+ * <tr>
+ * <td></td>
+ * <td ALIGN=CENTER><em>Throws exception</em></td>
+ * <td ALIGN=CENTER><em>Special value</em></td>
+ * <td ALIGN=CENTER><em>Blocks</em></td>
+ * <td ALIGN=CENTER><em>Times out</em></td>
+ * </tr>
+ * <tr>
+ * <td><b>Insert</b></td>
+ * <td>{@link #addFirst addFirst(e)}</td>
+ * <td>{@link #offerFirst(Object) offerFirst(e)}</td>
+ * <td>{@link #putFirst putFirst(e)}</td>
+ * <td>{@link #offerFirst(Object, long, TimeUnit) offerFirst(e, time, unit)}</td>
+ * </tr>
+ * <tr>
+ * <td><b>Remove</b></td>
+ * <td>{@link #removeFirst removeFirst()}</td>
+ * <td>{@link #pollFirst pollFirst()}</td>
+ * <td>{@link #takeFirst takeFirst()}</td>
+ * <td>{@link #pollFirst(long, TimeUnit) pollFirst(time, unit)}</td>
+ * </tr>
+ * <tr>
+ * <td><b>Examine</b></td>
+ * <td>{@link #getFirst getFirst()}</td>
+ * <td>{@link #peekFirst peekFirst()}</td>
+ * <td><em>not applicable</em></td>
+ * <td><em>not applicable</em></td>
+ * </tr>
+ * <tr>
+ * <td ALIGN=CENTER COLSPAN = 5> <b>Last Element (Tail)</b></td>
+ * </tr>
+ * <tr>
+ * <td></td>
+ * <td ALIGN=CENTER><em>Throws exception</em></td>
+ * <td ALIGN=CENTER><em>Special value</em></td>
+ * <td ALIGN=CENTER><em>Blocks</em></td>
+ * <td ALIGN=CENTER><em>Times out</em></td>
+ * </tr>
+ * <tr>
+ * <td><b>Insert</b></td>
+ * <td>{@link #addLast addLast(e)}</td>
+ * <td>{@link #offerLast(Object) offerLast(e)}</td>
+ * <td>{@link #putLast putLast(e)}</td>
+ * <td>{@link #offerLast(Object, long, TimeUnit) offerLast(e, time, unit)}</td>
+ * </tr>
+ * <tr>
+ * <td><b>Remove</b></td>
+ * <td>{@link #removeLast() removeLast()}</td>
+ * <td>{@link #pollLast() pollLast()}</td>
+ * <td>{@link #takeLast takeLast()}</td>
+ * <td>{@link #pollLast(long, TimeUnit) pollLast(time, unit)}</td>
+ * </tr>
+ * <tr>
+ * <td><b>Examine</b></td>
+ * <td>{@link #getLast getLast()}</td>
+ * <td>{@link #peekLast peekLast()}</td>
+ * <td><em>not applicable</em></td>
+ * <td><em>not applicable</em></td>
+ * </tr>
+ * </table>
+ *
+ * <p>Like any {@link BlockingQueue}, a <tt>BlockingDeque</tt> is thread safe,
+ * does not permit null elements, and may (or may not) be
+ * capacity-constrained.
+ *
+ * <p>A <tt>BlockingDeque</tt> implementation may be used directly as a FIFO
+ * <tt>BlockingQueue</tt>. The methods inherited from the
+ * <tt>BlockingQueue</tt> interface are precisely equivalent to
+ * <tt>BlockingDeque</tt> methods as indicated in the following table:
+ *
+ * <p>
+ * <table BORDER CELLPADDING=3 CELLSPACING=1>
+ * <tr>
+ * <td ALIGN=CENTER> <b><tt>BlockingQueue</tt> Method</b></td>
+ * <td ALIGN=CENTER> <b>Equivalent <tt>BlockingDeque</tt> Method</b></td>
+ * </tr>
+ * <tr>
+ * <td ALIGN=CENTER COLSPAN = 2> <b>Insert</b></td>
+ * </tr>
+ * <tr>
+ * <td>{@link #add(Object) add(e)}</td>
+ * <td>{@link #addLast(Object) addLast(e)}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #offer(Object) offer(e)}</td>
+ * <td>{@link #offerLast(Object) offerLast(e)}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #put(Object) put(e)}</td>
+ * <td>{@link #putLast(Object) putLast(e)}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #offer(Object, long, TimeUnit) offer(e, time, unit)}</td>
+ * <td>{@link #offerLast(Object, long, TimeUnit) offerLast(e, time, unit)}</td>
+ * </tr>
+ * <tr>
+ * <td ALIGN=CENTER COLSPAN = 2> <b>Remove</b></td>
+ * </tr>
+ * <tr>
+ * <td>{@link #remove() remove()}</td>
+ * <td>{@link #removeFirst() removeFirst()}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #poll() poll()}</td>
+ * <td>{@link #pollFirst() pollFirst()}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #take() take()}</td>
+ * <td>{@link #takeFirst() takeFirst()}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #poll(long, TimeUnit) poll(time, unit)}</td>
+ * <td>{@link #pollFirst(long, TimeUnit) pollFirst(time, unit)}</td>
+ * </tr>
+ * <tr>
+ * <td ALIGN=CENTER COLSPAN = 2> <b>Examine</b></td>
+ * </tr>
+ * <tr>
+ * <td>{@link #element() element()}</td>
+ * <td>{@link #getFirst() getFirst()}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #peek() peek()}</td>
+ * <td>{@link #peekFirst() peekFirst()}</td>
+ * </tr>
+ * </table>
+ *
+ * <p>Memory consistency effects: As with other concurrent
+ * collections, actions in a thread prior to placing an object into a
+ * {@code BlockingDeque}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions subsequent to the access or removal of that element from
+ * the {@code BlockingDeque} in another thread.
+ *
+ * <p>This interface is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @since 1.6
+ * @author Doug Lea
+ * @param <E> the type of elements held in this collection
+ */
+public interface BlockingDeque<E> extends BlockingQueue<E>, Deque<E> {
+ /*
+ * We have "diamond" multiple interface inheritance here, and that
+ * introduces ambiguities. Methods might end up with different
+ * specs depending on the branch chosen by javadoc. Thus a lot of
+ * methods specs here are copied from superinterfaces.
+ */
+
+ /**
+ * Inserts the specified element at the front of this deque if it is
+ * possible to do so immediately without violating capacity restrictions,
+ * throwing an <tt>IllegalStateException</tt> if no space is currently
+ * available. When using a capacity-restricted deque, it is generally
+ * preferable to use {@link #offerFirst(Object) offerFirst}.
+ *
+ * @param e the element to add
+ * @throws IllegalStateException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ void addFirst(E e);
+
+ /**
+ * Inserts the specified element at the end of this deque if it is
+ * possible to do so immediately without violating capacity restrictions,
+ * throwing an <tt>IllegalStateException</tt> if no space is currently
+ * available. When using a capacity-restricted deque, it is generally
+ * preferable to use {@link #offerLast(Object) offerLast}.
+ *
+ * @param e the element to add
+ * @throws IllegalStateException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ void addLast(E e);
+
+ /**
+ * Inserts the specified element at the front of this deque if it is
+ * possible to do so immediately without violating capacity restrictions,
+ * returning <tt>true</tt> upon success and <tt>false</tt> if no space is
+ * currently available.
+ * When using a capacity-restricted deque, this method is generally
+ * preferable to the {@link #addFirst(Object) addFirst} method, which can
+ * fail to insert an element only by throwing an exception.
+ *
+ * @param e the element to add
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ boolean offerFirst(E e);
+
+ /**
+ * Inserts the specified element at the end of this deque if it is
+ * possible to do so immediately without violating capacity restrictions,
+ * returning <tt>true</tt> upon success and <tt>false</tt> if no space is
+ * currently available.
+ * When using a capacity-restricted deque, this method is generally
+ * preferable to the {@link #addLast(Object) addLast} method, which can
+ * fail to insert an element only by throwing an exception.
+ *
+ * @param e the element to add
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ boolean offerLast(E e);
+
+ /**
+ * Inserts the specified element at the front of this deque,
+ * waiting if necessary for space to become available.
+ *
+ * @param e the element to add
+ * @throws InterruptedException if interrupted while waiting
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this deque
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this deque
+ */
+ void putFirst(E e) throws InterruptedException;
+
+ /**
+ * Inserts the specified element at the end of this deque,
+ * waiting if necessary for space to become available.
+ *
+ * @param e the element to add
+ * @throws InterruptedException if interrupted while waiting
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this deque
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this deque
+ */
+ void putLast(E e) throws InterruptedException;
+
+ /**
+ * Inserts the specified element at the front of this deque,
+ * waiting up to the specified wait time if necessary for space to
+ * become available.
+ *
+ * @param e the element to add
+ * @param timeout how long to wait before giving up, in units of
+ * <tt>unit</tt>
+ * @param unit a <tt>TimeUnit</tt> determining how to interpret the
+ * <tt>timeout</tt> parameter
+ * @return <tt>true</tt> if successful, or <tt>false</tt> if
+ * the specified waiting time elapses before space is available
+ * @throws InterruptedException if interrupted while waiting
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this deque
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this deque
+ */
+ boolean offerFirst(E e, long timeout, TimeUnit unit)
+ throws InterruptedException;
+
+ /**
+ * Inserts the specified element at the end of this deque,
+ * waiting up to the specified wait time if necessary for space to
+ * become available.
+ *
+ * @param e the element to add
+ * @param timeout how long to wait before giving up, in units of
+ * <tt>unit</tt>
+ * @param unit a <tt>TimeUnit</tt> determining how to interpret the
+ * <tt>timeout</tt> parameter
+ * @return <tt>true</tt> if successful, or <tt>false</tt> if
+ * the specified waiting time elapses before space is available
+ * @throws InterruptedException if interrupted while waiting
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this deque
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this deque
+ */
+ boolean offerLast(E e, long timeout, TimeUnit unit)
+ throws InterruptedException;
+
+ /**
+ * Retrieves and removes the first element of this deque, waiting
+ * if necessary until an element becomes available.
+ *
+ * @return the head of this deque
+ * @throws InterruptedException if interrupted while waiting
+ */
+ E takeFirst() throws InterruptedException;
+
+ /**
+ * Retrieves and removes the last element of this deque, waiting
+ * if necessary until an element becomes available.
+ *
+ * @return the tail of this deque
+ * @throws InterruptedException if interrupted while waiting
+ */
+ E takeLast() throws InterruptedException;
+
+ /**
+ * Retrieves and removes the first element of this deque, waiting
+ * up to the specified wait time if necessary for an element to
+ * become available.
+ *
+ * @param timeout how long to wait before giving up, in units of
+ * <tt>unit</tt>
+ * @param unit a <tt>TimeUnit</tt> determining how to interpret the
+ * <tt>timeout</tt> parameter
+ * @return the head of this deque, or <tt>null</tt> if the specified
+ * waiting time elapses before an element is available
+ * @throws InterruptedException if interrupted while waiting
+ */
+ E pollFirst(long timeout, TimeUnit unit)
+ throws InterruptedException;
+
+ /**
+ * Retrieves and removes the last element of this deque, waiting
+ * up to the specified wait time if necessary for an element to
+ * become available.
+ *
+ * @param timeout how long to wait before giving up, in units of
+ * <tt>unit</tt>
+ * @param unit a <tt>TimeUnit</tt> determining how to interpret the
+ * <tt>timeout</tt> parameter
+ * @return the tail of this deque, or <tt>null</tt> if the specified
+ * waiting time elapses before an element is available
+ * @throws InterruptedException if interrupted while waiting
+ */
+ E pollLast(long timeout, TimeUnit unit)
+ throws InterruptedException;
+
+ /**
+ * Removes the first occurrence of the specified element from this deque.
+ * If the deque does not contain the element, it is unchanged.
+ * More formally, removes the first element <tt>e</tt> such that
+ * <tt>o.equals(e)</tt> (if such an element exists).
+ * Returns <tt>true</tt> if this deque contained the specified element
+ * (or equivalently, if this deque changed as a result of the call).
+ *
+ * @param o element to be removed from this deque, if present
+ * @return <tt>true</tt> if an element was removed as a result of this call
+ * @throws ClassCastException if the class of the specified element
+ * is incompatible with this deque (optional)
+ * @throws NullPointerException if the specified element is null (optional)
+ */
+ boolean removeFirstOccurrence(Object o);
+
+ /**
+ * Removes the last occurrence of the specified element from this deque.
+ * If the deque does not contain the element, it is unchanged.
+ * More formally, removes the last element <tt>e</tt> such that
+ * <tt>o.equals(e)</tt> (if such an element exists).
+ * Returns <tt>true</tt> if this deque contained the specified element
+ * (or equivalently, if this deque changed as a result of the call).
+ *
+ * @param o element to be removed from this deque, if present
+ * @return <tt>true</tt> if an element was removed as a result of this call
+ * @throws ClassCastException if the class of the specified element
+ * is incompatible with this deque (optional)
+ * @throws NullPointerException if the specified element is null (optional)
+ */
+ boolean removeLastOccurrence(Object o);
+
+ // *** BlockingQueue methods ***
+
+ /**
+ * Inserts the specified element into the queue represented by this deque
+ * (in other words, at the tail of this deque) if it is possible to do so
+ * immediately without violating capacity restrictions, returning
+ * <tt>true</tt> upon success and throwing an
+ * <tt>IllegalStateException</tt> if no space is currently available.
+ * When using a capacity-restricted deque, it is generally preferable to
+ * use {@link #offer(Object) offer}.
+ *
+ * <p>This method is equivalent to {@link #addLast(Object) addLast}.
+ *
+ * @param e the element to add
+ * @throws IllegalStateException {@inheritDoc}
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this deque
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this deque
+ */
+ boolean add(E e);
+
+ /**
+ * Inserts the specified element into the queue represented by this deque
+ * (in other words, at the tail of this deque) if it is possible to do so
+ * immediately without violating capacity restrictions, returning
+ * <tt>true</tt> upon success and <tt>false</tt> if no space is currently
+ * available. When using a capacity-restricted deque, this method is
+ * generally preferable to the {@link #add} method, which can fail to
+ * insert an element only by throwing an exception.
+ *
+ * <p>This method is equivalent to {@link #offerLast(Object) offerLast}.
+ *
+ * @param e the element to add
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this deque
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this deque
+ */
+ boolean offer(E e);
+
+ /**
+ * Inserts the specified element into the queue represented by this deque
+ * (in other words, at the tail of this deque), waiting if necessary for
+ * space to become available.
+ *
+ * <p>This method is equivalent to {@link #putLast(Object) putLast}.
+ *
+ * @param e the element to add
+ * @throws InterruptedException {@inheritDoc}
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this deque
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this deque
+ */
+ void put(E e) throws InterruptedException;
+
+ /**
+ * Inserts the specified element into the queue represented by this deque
+ * (in other words, at the tail of this deque), waiting up to the
+ * specified wait time if necessary for space to become available.
+ *
+ * <p>This method is equivalent to
+ * {@link #offerLast(Object,long,TimeUnit) offerLast}.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> if the element was added to this deque, else
+ * <tt>false</tt>
+ * @throws InterruptedException {@inheritDoc}
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this deque
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this deque
+ */
+ boolean offer(E e, long timeout, TimeUnit unit)
+ throws InterruptedException;
+
+ /**
+ * Retrieves and removes the head of the queue represented by this deque
+ * (in other words, the first element of this deque).
+ * This method differs from {@link #poll poll} only in that it
+ * throws an exception if this deque is empty.
+ *
+ * <p>This method is equivalent to {@link #removeFirst() removeFirst}.
+ *
+ * @return the head of the queue represented by this deque
+ * @throws NoSuchElementException if this deque is empty
+ */
+ E remove();
+
+ /**
+ * Retrieves and removes the head of the queue represented by this deque
+ * (in other words, the first element of this deque), or returns
+ * <tt>null</tt> if this deque is empty.
+ *
+ * <p>This method is equivalent to {@link #pollFirst()}.
+ *
+ * @return the head of this deque, or <tt>null</tt> if this deque is empty
+ */
+ E poll();
+
+ /**
+ * Retrieves and removes the head of the queue represented by this deque
+ * (in other words, the first element of this deque), waiting if
+ * necessary until an element becomes available.
+ *
+ * <p>This method is equivalent to {@link #takeFirst() takeFirst}.
+ *
+ * @return the head of this deque
+ * @throws InterruptedException if interrupted while waiting
+ */
+ E take() throws InterruptedException;
+
+ /**
+ * Retrieves and removes the head of the queue represented by this deque
+ * (in other words, the first element of this deque), waiting up to the
+ * specified wait time if necessary for an element to become available.
+ *
+ * <p>This method is equivalent to
+ * {@link #pollFirst(long,TimeUnit) pollFirst}.
+ *
+ * @return the head of this deque, or <tt>null</tt> if the
+ * specified waiting time elapses before an element is available
+ * @throws InterruptedException if interrupted while waiting
+ */
+ E poll(long timeout, TimeUnit unit)
+ throws InterruptedException;
+
+ /**
+ * Retrieves, but does not remove, the head of the queue represented by
+ * this deque (in other words, the first element of this deque).
+ * This method differs from {@link #peek peek} only in that it throws an
+ * exception if this deque is empty.
+ *
+ * <p>This method is equivalent to {@link #getFirst() getFirst}.
+ *
+ * @return the head of this deque
+ * @throws NoSuchElementException if this deque is empty
+ */
+ E element();
+
+ /**
+ * Retrieves, but does not remove, the head of the queue represented by
+ * this deque (in other words, the first element of this deque), or
+ * returns <tt>null</tt> if this deque is empty.
+ *
+ * <p>This method is equivalent to {@link #peekFirst() peekFirst}.
+ *
+ * @return the head of this deque, or <tt>null</tt> if this deque is empty
+ */
+ E peek();
+
+ /**
+ * Removes the first occurrence of the specified element from this deque.
+ * If the deque does not contain the element, it is unchanged.
+ * More formally, removes the first element <tt>e</tt> such that
+ * <tt>o.equals(e)</tt> (if such an element exists).
+ * Returns <tt>true</tt> if this deque contained the specified element
+ * (or equivalently, if this deque changed as a result of the call).
+ *
+ * <p>This method is equivalent to
+ * {@link #removeFirstOccurrence(Object) removeFirstOccurrence}.
+ *
+ * @param o element to be removed from this deque, if present
+ * @return <tt>true</tt> if this deque changed as a result of the call
+ * @throws ClassCastException if the class of the specified element
+ * is incompatible with this deque (optional)
+ * @throws NullPointerException if the specified element is null (optional)
+ */
+ boolean remove(Object o);
+
+ /**
+ * Returns <tt>true</tt> if this deque contains the specified element.
+ * More formally, returns <tt>true</tt> if and only if this deque contains
+ * at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
+ *
+ * @param o object to be checked for containment in this deque
+ * @return <tt>true</tt> if this deque contains the specified element
+ * @throws ClassCastException if the class of the specified element
+ * is incompatible with this deque (optional)
+ * @throws NullPointerException if the specified element is null (optional)
+ */
+ public boolean contains(Object o);
+
+ /**
+ * Returns the number of elements in this deque.
+ *
+ * @return the number of elements in this deque
+ */
+ public int size();
+
+ /**
+ * Returns an iterator over the elements in this deque in proper sequence.
+ * The elements will be returned in order from first (head) to last (tail).
+ *
+ * @return an iterator over the elements in this deque in proper sequence
+ */
+ Iterator<E> iterator();
+
+ // *** Stack methods ***
+
+ /**
+ * Pushes an element onto the stack represented by this deque. In other
+ * words, inserts the element at the front of this deque unless it would
+ * violate capacity restrictions.
+ *
+ * <p>This method is equivalent to {@link #addFirst(Object) addFirst}.
+ *
+ * @throws IllegalStateException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ void push(E e);
+}
diff --git a/concurrent/src/main/java/java/util/concurrent/BlockingQueue.java b/concurrent/src/main/java/java/util/concurrent/BlockingQueue.java
index d01c097..85945b9 100644
--- a/concurrent/src/main/java/java/util/concurrent/BlockingQueue.java
+++ b/concurrent/src/main/java/java/util/concurrent/BlockingQueue.java
@@ -42,7 +42,7 @@ import java.util.Queue;
* <td>{@link #add add(e)}</td>
* <td>{@link #offer offer(e)}</td>
* <td>{@link #put put(e)}</td>
- * <td>{@link #offer offer(e, time, unit)}</td>
+ * <td>{@link #offer(Object, long, TimeUnit) offer(e, time, unit)}</td>
* </tr>
* <tr>
* <td><b>Remove</b></td>
@@ -156,7 +156,7 @@ public interface BlockingQueue<E> extends Queue<E> {
* <tt>true</tt> upon success and throwing an
* <tt>IllegalStateException</tt> if no space is currently available.
* When using a capacity-restricted queue, it is generally preferable to
- * use {@link #offer offer}.
+ * use {@link #offer(Object) offer}.
*
* @param e the element to add
* @return <tt>true</tt> (as specified by {@link Collection#add})
diff --git a/concurrent/src/main/java/java/util/concurrent/ConcurrentHashMap.java b/concurrent/src/main/java/java/util/concurrent/ConcurrentHashMap.java
index cb5fb3f..1c157b4 100644
--- a/concurrent/src/main/java/java/util/concurrent/ConcurrentHashMap.java
+++ b/concurrent/src/main/java/java/util/concurrent/ConcurrentHashMap.java
@@ -613,6 +613,24 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
}
/**
+ * Creates a new, empty map with the specified initial capacity
+ * and load factor and with the default concurrencyLevel (16).
+ *
+ * @param initialCapacity The implementation performs internal
+ * sizing to accommodate this many elements.
+ * @param loadFactor the load factor threshold, used to control resizing.
+ * Resizing may be performed when the average number of elements per
+ * bin exceeds this threshold.
+ * @throws IllegalArgumentException if the initial capacity of
+ * elements is negative or the load factor is nonpositive
+ *
+ * @since 1.6
+ */
+ public ConcurrentHashMap(int initialCapacity, float loadFactor) {
+ this(initialCapacity, loadFactor, DEFAULT_CONCURRENCY_LEVEL);
+ }
+
+ /**
* Creates a new, empty map with the specified initial capacity,
* and with default load factor (0.75) and concurrencyLevel (16).
*
@@ -1112,7 +1130,7 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
* setValue changes to the underlying map.
*/
final class WriteThroughEntry
- extends SimpleEntry<K,V>
+ extends AbstractMap.SimpleEntry<K,V>
{
WriteThroughEntry(K k, V v) {
super(k,v);
@@ -1212,60 +1230,7 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
}
}
- /**
- * This duplicates java.util.AbstractMap.SimpleEntry until this class
- * is made accessible.
- */
- static class SimpleEntry<K,V> implements Entry<K,V> {
- K key;
- V value;
-
- public SimpleEntry(K key, V value) {
- this.key = key;
- this.value = value;
- }
-
- public SimpleEntry(Entry<K,V> e) {
- this.key = e.getKey();
- this.value = e.getValue();
- }
-
- public K getKey() {
- return key;
- }
-
- public V getValue() {
- return value;
- }
-
- public V setValue(V value) {
- V oldValue = this.value;
- this.value = value;
- return oldValue;
- }
-
- public boolean equals(Object o) {
- if (!(o instanceof Map.Entry))
- return false;
- Map.Entry e = (Map.Entry)o;
- return eq(key, e.getKey()) && eq(value, e.getValue());
- }
-
- public int hashCode() {
- return ((key == null) ? 0 : key.hashCode()) ^
- ((value == null) ? 0 : value.hashCode());
- }
-
- public String toString() {
- return key + "=" + value;
- }
-
- static boolean eq(Object o1, Object o2) {
- return (o1 == null ? o2 == null : o1.equals(o2));
- }
- }
-
- /* ---------------- Serialization Support -------------- */
+ /* ---------------- Serialization Support -------------- */
/**
* Save the state of the <tt>ConcurrentHashMap</tt> instance to a
diff --git a/concurrent/src/main/java/java/util/concurrent/ConcurrentLinkedDeque.java b/concurrent/src/main/java/java/util/concurrent/ConcurrentLinkedDeque.java
new file mode 100644
index 0000000..ee3534e
--- /dev/null
+++ b/concurrent/src/main/java/java/util/concurrent/ConcurrentLinkedDeque.java
@@ -0,0 +1,1246 @@
+/*
+ * Written by Doug Lea and Martin Buchholz 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;
+
+import java.util.AbstractCollection;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Deque;
+import java.util.Iterator;
+import java.util.ConcurrentModificationException;
+import java.util.NoSuchElementException;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * A concurrent linked-list implementation of a {@link Deque}
+ * (double-ended queue). Concurrent insertion, removal, and access
+ * operations execute safely across multiple threads. Iterators are
+ * <i>weakly consistent</i>, returning elements reflecting the state
+ * of the deque at some point at or since the creation of the
+ * iterator. They do <em>not</em> throw {@link
+ * ConcurrentModificationException}, and may proceed concurrently with
+ * other operations.
+ *
+ * <p>This class and its iterators implement all of the
+ * <em>optional</em> methods of the {@link Collection} and {@link
+ * Iterator} interfaces. Like most other concurrent collection
+ * implementations, this class does not permit the use of
+ * {@code null} elements. because some null arguments and return
+ * values cannot be reliably distinguished from the absence of
+ * elements. Arbitrarily, the {@link Collection#remove} method is
+ * mapped to {@code removeFirstOccurrence}, and {@link
+ * Collection#add} is mapped to {@code addLast}.
+ *
+ * <p>Beware that, unlike in most collections, the {@code size}
+ * method is <em>NOT</em> a constant-time operation. Because of the
+ * asynchronous nature of these deques, determining the current number
+ * of elements requires a traversal of the elements.
+ *
+ * <p>This class is {@code Serializable}, but relies on default
+ * serialization mechanisms. Usually, it is a better idea for any
+ * serializable class using a {@code ConcurrentLinkedDeque} to instead
+ * serialize a snapshot of the elements obtained by method
+ * {@code toArray}.
+ *
+ * @author Doug Lea
+ * @author Martin Buchholz
+ * @param <E> the type of elements held in this collection
+ */
+
+public class ConcurrentLinkedDeque<E>
+ extends AbstractCollection<E>
+ implements Deque<E>, java.io.Serializable {
+
+ /*
+ * This is an implementation of a concurrent lock-free deque
+ * supporting interior removes but not interior insertions, as
+ * required to fully support the Deque interface.
+ *
+ * We extend the techniques developed for
+ * ConcurrentLinkedQueue and LinkedTransferQueue
+ * (see the internal docs for those classes).
+ *
+ * At any time, there is precisely one "first" active node with a
+ * null prev pointer. Similarly there is one "last" active node
+ * with a null next pointer. New nodes are simply enqueued by
+ * null-CASing.
+ *
+ * A node p is considered "active" if it either contains an
+ * element, or is an end node and neither next nor prev pointers
+ * are self-links:
+ *
+ * p.item != null ||
+ * (p.prev == null && p.next != p) ||
+ * (p.next == null && p.prev != p)
+ *
+ * The head and tail pointers are only approximations to the start
+ * and end of the deque. The first node can always be found by
+ * following prev pointers from head; likewise for tail. However,
+ * head and tail may be pointing at deleted nodes that have been
+ * unlinked and so may not be reachable from any live node.
+ *
+ * There are 3 levels of node deletion:
+ * - logical deletion atomically removes the element
+ * - "unlinking" makes a deleted node unreachable from active
+ * nodes, and thus eventually reclaimable by GC
+ * - "gc-unlinking" further does the reverse of making active
+ * nodes unreachable from deleted nodes, making it easier for
+ * the GC to reclaim future deleted nodes
+ *
+ * TODO: find a better name for "gc-unlinked"
+ *
+ * Logical deletion of a node simply involves CASing its element
+ * to null. Physical deletion is merely an optimization (albeit a
+ * critical one), and can be performed at our convenience. At any
+ * time, the set of non-logically-deleted nodes maintained by prev
+ * and next links are identical, that is the live elements found
+ * via next links from the first node is equal to the elements
+ * found via prev links from the last node. However, this is not
+ * true for nodes that have already been logically deleted - such
+ * nodes may only be reachable in one direction.
+ *
+ * When a node is dequeued at either end, e.g. via poll(), we
+ * would like to break any references from the node to live nodes,
+ * to stop old garbage from causing retention of new garbage with
+ * a generational or conservative GC. We develop further the
+ * self-linking trick that was very effective in other concurrent
+ * collection classes. The idea is to replace prev and next
+ * pointers to active nodes with special values that are
+ * interpreted to mean off-the-list-at-one-end. These are
+ * approximations, but good enough to preserve the properties we
+ * want in our traversals, e.g. we guarantee that a traversal will
+ * never hit the same element twice, but we don't guarantee
+ * whether a traversal that runs out of elements will be able to
+ * see more elements later after more elements are added at that
+ * end. Doing gc-unlinking safely is particularly tricky, since
+ * any node can be in use indefinitely (for example by an
+ * iterator). We must make sure that the nodes pointed at by
+ * head/tail do not get gc-unlinked, since head/tail are needed to
+ * get "back on track" by other nodes that are gc-unlinked.
+ * gc-unlinking accounts for much of the implementation complexity.
+ *
+ * Since neither unlinking nor gc-unlinking are necessary for
+ * correctness, there are many implementation choices regarding
+ * frequency (eagerness) of these operations. Since volatile
+ * reads are likely to be much cheaper than CASes, saving CASes by
+ * unlinking multiple adjacent nodes at a time may be a win.
+ * gc-unlinking can be performed rarely and still be effective,
+ * since it is most important that long chains of deleted nodes
+ * are occasionally broken.
+ *
+ * The actual representation we use is that p.next == p means to
+ * goto the first node, and p.next == null && p.prev == p means
+ * that the iteration is at an end and that p is a (final static)
+ * dummy node, NEXT_TERMINATOR, and not the last active node.
+ * Finishing the iteration when encountering such a TERMINATOR is
+ * good enough for read-only traversals. When the last active
+ * node is desired, for example when enqueueing, goto tail and
+ * continue traversal.
+ *
+ * The implementation is completely directionally symmetrical,
+ * except that most public methods that iterate through the list
+ * follow next pointers ("forward" direction).
+ *
+ * There is one desirable property we would like to have, but
+ * don't: it is possible, when an addFirst(A) is racing with
+ * pollFirst() removing B, for an iterating observer to see A B C
+ * and subsequently see A C, even though no interior removes are
+ * ever performed. I believe this wart can only be removed at
+ * significant runtime cost.
+ *
+ * Empirically, microbenchmarks suggest that this class adds about
+ * 40% overhead relative to ConcurrentLinkedQueue, which feels as
+ * good as we can hope for.
+ */
+
+ /**
+ * A node from which the first node on list (that is, the unique
+ * node with node.prev == null) can be reached in O(1) time.
+ * Invariants:
+ * - the first node is always O(1) reachable from head via prev links
+ * - all live nodes are reachable from the first node via succ()
+ * - head != null
+ * - (tmp = head).next != tmp || tmp != head
+ * Non-invariants:
+ * - head.item may or may not be null
+ * - head may not be reachable from the first or last node, or from tail
+ */
+ private transient volatile Node<E> head = new Node<E>(null);
+
+ private final static Node<Object> PREV_TERMINATOR, NEXT_TERMINATOR;
+
+ static {
+ PREV_TERMINATOR = new Node<Object>(null);
+ PREV_TERMINATOR.next = PREV_TERMINATOR;
+ NEXT_TERMINATOR = new Node<Object>(null);
+ NEXT_TERMINATOR.prev = NEXT_TERMINATOR;
+ }
+
+ @SuppressWarnings("unchecked")
+ Node<E> prevTerminator() {
+ return (Node<E>) PREV_TERMINATOR;
+ }
+
+ @SuppressWarnings("unchecked")
+ Node<E> nextTerminator() {
+ return (Node<E>) NEXT_TERMINATOR;
+ }
+
+ /**
+ * A node from which the last node on list (that is, the unique
+ * node with node.next == null) can be reached in O(1) time.
+ * Invariants:
+ * - the last node is always O(1) reachable from tail via next links
+ * - all live nodes are reachable from the last node via pred()
+ * - tail != null
+ * Non-invariants:
+ * - tail.item may or may not be null
+ * - tail may not be reachable from the first or last node, or from head
+ */
+ private transient volatile Node<E> tail = head;
+
+ static final class Node<E> {
+ volatile Node<E> prev;
+ volatile E item;
+ volatile Node<E> next;
+
+ Node(E item) {
+ // Piggyback on imminent casNext() or casPrev()
+ lazySetItem(item);
+ }
+
+ boolean casItem(E cmp, E val) {
+ return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
+ }
+
+ void lazySetItem(E val) {
+ UNSAFE.putOrderedObject(this, itemOffset, val);
+ }
+
+ void lazySetNext(Node<E> val) {
+ UNSAFE.putOrderedObject(this, nextOffset, val);
+ }
+
+ boolean casNext(Node<E> cmp, Node<E> val) {
+ return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
+ }
+
+ void lazySetPrev(Node<E> val) {
+ UNSAFE.putOrderedObject(this, prevOffset, val);
+ }
+
+ boolean casPrev(Node<E> cmp, Node<E> val) {
+ return UNSAFE.compareAndSwapObject(this, prevOffset, cmp, val);
+ }
+
+ // Unsafe mechanics
+
+ private static final sun.misc.Unsafe UNSAFE =
+ sun.misc.Unsafe.getUnsafe();
+ private static final long prevOffset =
+ objectFieldOffset(UNSAFE, "prev", Node.class);
+ private static final long itemOffset =
+ objectFieldOffset(UNSAFE, "item", Node.class);
+ private static final long nextOffset =
+ objectFieldOffset(UNSAFE, "next", Node.class);
+ }
+
+ /**
+ * Links e as first element.
+ */
+ private void linkFirst(E e) {
+ checkNotNull(e);
+ final Node<E> newNode = new Node<E>(e);
+
+ retry:
+ for (;;) {
+ for (Node<E> h = head, p = h;;) {
+ Node<E> q = p.prev;
+ if (q == null) {
+ if (p.next == p)
+ continue retry;
+ newNode.lazySetNext(p); // CAS piggyback
+ if (p.casPrev(null, newNode)) {
+ if (p != h) // hop two nodes at a time
+ casHead(h, newNode);
+ return;
+ } else {
+ p = p.prev; // lost CAS race to another thread
+ }
+ }
+ else if (p == q)
+ continue retry;
+ else
+ p = q;
+ }
+ }
+ }
+
+ /**
+ * Links e as last element.
+ */
+ private void linkLast(E e) {
+ checkNotNull(e);
+ final Node<E> newNode = new Node<E>(e);
+
+ retry:
+ for (;;) {
+ for (Node<E> t = tail, p = t;;) {
+ Node<E> q = p.next;
+ if (q == null) {
+ if (p.prev == p)
+ continue retry;
+ newNode.lazySetPrev(p); // CAS piggyback
+ if (p.casNext(null, newNode)) {
+ if (p != t) // hop two nodes at a time
+ casTail(t, newNode);
+ return;
+ } else {
+ p = p.next; // lost CAS race to another thread
+ }
+ }
+ else if (p == q)
+ continue retry;
+ else
+ p = q;
+ }
+ }
+ }
+
+ // TODO: Is there a better cheap way of performing some cleanup
+ // operation "occasionally"?
+ static class Count {
+ int count = 0;
+ }
+ private final static ThreadLocal<Count> tlc =
+ new ThreadLocal<Count>() {
+ protected Count initialValue() { return new Count(); }
+ };
+ private static boolean shouldGCUnlinkOccasionally() {
+ return (tlc.get().count++ & 0x3) == 0;
+ }
+
+ private final static int HOPS = 2;
+
+ /**
+ * Unlinks non-null node x.
+ */
+ void unlink(Node<E> x) {
+ assert x != null;
+ assert x.item == null;
+ assert x != PREV_TERMINATOR;
+ assert x != NEXT_TERMINATOR;
+
+ final Node<E> prev = x.prev;
+ final Node<E> next = x.next;
+ if (prev == null) {
+ unlinkFirst(x, next);
+ } else if (next == null) {
+ unlinkLast(x, prev);
+ } else {
+ // Unlink interior node.
+ //
+ // This is the common case, since a series of polls at the
+ // same end will be "interior" removes, except perhaps for
+ // the first one, since end nodes cannot be physically removed.
+ //
+ // At any time, all active nodes are mutually reachable by
+ // following a sequence of either next or prev pointers.
+ //
+ // Our strategy is to find the unique active predecessor
+ // and successor of x. Try to fix up their links so that
+ // they point to each other, leaving x unreachable from
+ // active nodes. If successful, and if x has no live
+ // predecessor/successor, we additionally try to leave
+ // active nodes unreachable from x, by rechecking that
+ // the status of predecessor and successor are unchanged
+ // and ensuring that x is not reachable from tail/head,
+ // before setting x's prev/next links to their logical
+ // approximate replacements, self/TERMINATOR.
+ Node<E> activePred, activeSucc;
+ boolean isFirst, isLast;
+ int hops = 1;
+
+ // Find active predecessor
+ for (Node<E> p = prev;; ++hops) {
+ if (p.item != null) {
+ activePred = p;
+ isFirst = false;
+ break;
+ }
+ Node<E> q = p.prev;
+ if (q == null) {
+ if (p == p.next)
+ return;
+ activePred = p;
+ isFirst = true;
+ break;
+ }
+ else if (p == q)
+ return;
+ else
+ p = q;
+ }
+
+ // Find active successor
+ for (Node<E> p = next;; ++hops) {
+ if (p.item != null) {
+ activeSucc = p;
+ isLast = false;
+ break;
+ }
+ Node<E> q = p.next;
+ if (q == null) {
+ if (p == p.prev)
+ return;
+ activeSucc = p;
+ isLast = true;
+ break;
+ }
+ else if (p == q)
+ return;
+ else
+ p = q;
+ }
+
+ // TODO: better HOP heuristics
+ if (hops < HOPS
+ // always squeeze out interior deleted nodes
+ && (isFirst | isLast))
+ return;
+
+ // Squeeze out deleted nodes between activePred and
+ // activeSucc, including x.
+ skipDeletedSuccessors(activePred);
+ skipDeletedPredecessors(activeSucc);
+
+ // Try to gc-unlink, if possible
+ if ((isFirst | isLast) &&
+ //shouldGCUnlinkOccasionally() &&
+
+ // Recheck expected state of predecessor and successor
+ (activePred.next == activeSucc) &&
+ (activeSucc.prev == activePred) &&
+ (isFirst ? activePred.prev == null : activePred.item != null) &&
+ (isLast ? activeSucc.next == null : activeSucc.item != null)) {
+
+ // Ensure x is not reachable from head or tail
+ updateHead();
+ updateTail();
+ x.lazySetPrev(isFirst ? prevTerminator() : x);
+ x.lazySetNext(isLast ? nextTerminator() : x);
+ }
+ }
+ }
+
+ /**
+ * Unlinks non-null first node.
+ */
+ private void unlinkFirst(Node<E> first, Node<E> next) {
+ assert first != null && next != null && first.item == null;
+ Node<E> o = null, p = next;
+ for (int hops = 0;; ++hops) {
+ Node<E> q;
+ if (p.item != null || (q = p.next) == null) {
+ if (hops >= HOPS) {
+ if (p == p.prev)
+ return;
+ if (first.casNext(next, p)) {
+ skipDeletedPredecessors(p);
+ if (//shouldGCUnlinkOccasionally() &&
+ first.prev == null &&
+ (p.next == null || p.item != null) &&
+ p.prev == first) {
+
+ updateHead();
+ updateTail();
+ o.lazySetNext(o);
+ o.lazySetPrev(prevTerminator());
+ }
+ }
+ }
+ return;
+ }
+ else if (p == q)
+ return;
+ else {
+ o = p;
+ p = q;
+ }
+ }
+ }
+
+ /**
+ * Unlinks non-null last node.
+ */
+ private void unlinkLast(Node<E> last, Node<E> prev) {
+ assert last != null && prev != null && last.item == null;
+ Node<E> o = null, p = prev;
+ for (int hops = 0;; ++hops) {
+ Node<E> q;
+ if (p.item != null || (q = p.prev) == null) {
+ if (hops >= HOPS) {
+ if (p == p.next)
+ return;
+ if (last.casPrev(prev, p)) {
+ skipDeletedSuccessors(p);
+ if (//shouldGCUnlinkOccasionally() &&
+ last.next == null &&
+ (p.prev == null || p.item != null) &&
+ p.next == last) {
+
+ updateHead();
+ updateTail();
+ o.lazySetPrev(o);
+ o.lazySetNext(nextTerminator());
+ }
+ }
+ }
+ return;
+ }
+ else if (p == q)
+ return;
+ else {
+ o = p;
+ p = q;
+ }
+ }
+ }
+
+ private final void updateHead() {
+ first();
+ }
+
+ private final void updateTail() {
+ last();
+ }
+
+ private void skipDeletedPredecessors(Node<E> x) {
+ whileActive:
+ do {
+ Node<E> prev = x.prev;
+ assert prev != null;
+ assert x != NEXT_TERMINATOR;
+ assert x != PREV_TERMINATOR;
+ Node<E> p = prev;
+ findActive:
+ for (;;) {
+ if (p.item != null)
+ break findActive;
+ Node<E> q = p.prev;
+ if (q == null) {
+ if (p.next == p)
+ continue whileActive;
+ break findActive;
+ }
+ else if (p == q)
+ continue whileActive;
+ else
+ p = q;
+ }
+
+ // found active CAS target
+ if (prev == p || x.casPrev(prev, p))
+ return;
+
+ } while (x.item != null || x.next == null);
+ }
+
+ private void skipDeletedSuccessors(Node<E> x) {
+ whileActive:
+ do {
+ Node<E> next = x.next;
+ assert next != null;
+ assert x != NEXT_TERMINATOR;
+ assert x != PREV_TERMINATOR;
+ Node<E> p = next;
+ findActive:
+ for (;;) {
+ if (p.item != null)
+ break findActive;
+ Node<E> q = p.next;
+ if (q == null) {
+ if (p.prev == p)
+ continue whileActive;
+ break findActive;
+ }
+ else if (p == q)
+ continue whileActive;
+ else
+ p = q;
+ }
+
+ // found active CAS target
+ if (next == p || x.casNext(next, p))
+ return;
+
+ } while (x.item != null || x.prev == null);
+ }
+
+ /**
+ * Returns the successor of p, or the first node if p.next has been
+ * linked to self, which will only be true if traversing with a
+ * stale pointer that is now off the list.
+ */
+ final Node<E> succ(Node<E> p) {
+ // TODO: should we skip deleted nodes here?
+ Node<E> q = p.next;
+ return (p == q) ? first() : q;
+ }
+
+ /**
+ * Returns the predecessor of p, or the last node if p.prev has been
+ * linked to self, which will only be true if traversing with a
+ * stale pointer that is now off the list.
+ */
+ final Node<E> pred(Node<E> p) {
+ Node<E> q = p.prev;
+ return (p == q) ? last() : q;
+ }
+
+ /**
+ * Returns the first node, the unique node which has a null prev link.
+ * The returned node may or may not be logically deleted.
+ * Guarantees that head is set to the returned node.
+ */
+ Node<E> first() {
+ retry:
+ for (;;) {
+ for (Node<E> h = head, p = h;;) {
+ Node<E> q = p.prev;
+ if (q == null) {
+ if (p == h
+ // It is possible that p is PREV_TERMINATOR,
+ // but if so, the CAS will fail.
+ || casHead(h, p))
+ return p;
+ else
+ continue retry;
+ } else if (p == q) {
+ continue retry;
+ } else {
+ p = q;
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the last node, the unique node which has a null next link.
+ * The returned node may or may not be logically deleted.
+ * Guarantees that tail is set to the returned node.
+ */
+ Node<E> last() {
+ retry:
+ for (;;) {
+ for (Node<E> t = tail, p = t;;) {
+ Node<E> q = p.next;
+ if (q == null) {
+ if (p == t
+ // It is possible that p is NEXT_TERMINATOR,
+ // but if so, the CAS will fail.
+ || casTail(t, p))
+ return p;
+ else
+ continue retry;
+ } else if (p == q) {
+ continue retry;
+ } else {
+ p = q;
+ }
+ }
+ }
+ }
+
+ // Minor convenience utilities
+
+ /**
+ * Throws NullPointerException if argument is null.
+ *
+ * @param v the element
+ */
+ private static void checkNotNull(Object v) {
+ if (v == null)
+ throw new NullPointerException();
+ }
+
+ /**
+ * Returns element unless it is null, in which case throws
+ * NoSuchElementException.
+ *
+ * @param v the element
+ * @return the element
+ */
+ private E screenNullResult(E v) {
+ if (v == null)
+ throw new NoSuchElementException();
+ return v;
+ }
+
+ /**
+ * Creates an array list and fills it with elements of this list.
+ * Used by toArray.
+ *
+ * @return the arrayList
+ */
+ private ArrayList<E> toArrayList() {
+ ArrayList<E> c = new ArrayList<E>();
+ for (Node<E> p = first(); p != null; p = succ(p)) {
+ E item = p.item;
+ if (item != null)
+ c.add(item);
+ }
+ return c;
+ }
+
+ // Fields and constructors
+
+ private static final long serialVersionUID = 876323262645176354L;
+
+ /**
+ * Constructs an empty deque.
+ */
+ public ConcurrentLinkedDeque() {}
+
+ /**
+ * Constructs a deque initially containing the elements of
+ * the given collection, added in traversal order of the
+ * collection's iterator.
+ *
+ * @param c the collection of elements to initially contain
+ * @throws NullPointerException if the specified collection or any
+ * of its elements are null
+ */
+ public ConcurrentLinkedDeque(Collection<? extends E> c) {
+ this();
+ addAll(c);
+ }
+
+ /**
+ * Inserts the specified element at the front of this deque.
+ *
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public void addFirst(E e) {
+ linkFirst(e);
+ }
+
+ /**
+ * Inserts the specified element at the end of this deque.
+ * This is identical in function to the {@code add} method.
+ *
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public void addLast(E e) {
+ linkLast(e);
+ }
+
+ /**
+ * Inserts the specified element at the front of this deque.
+ *
+ * @return {@code true} always
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean offerFirst(E e) {
+ linkFirst(e);
+ return true;
+ }
+
+ /**
+ * Inserts the specified element at the end of this deque.
+ *
+ * <p>This method is equivalent to {@link #add}.
+ *
+ * @return {@code true} always
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean offerLast(E e) {
+ linkLast(e);
+ return true;
+ }
+
+ public E peekFirst() {
+ for (Node<E> p = first(); p != null; p = succ(p)) {
+ E item = p.item;
+ if (item != null)
+ return item;
+ }
+ return null;
+ }
+
+ public E peekLast() {
+ for (Node<E> p = last(); p != null; p = pred(p)) {
+ E item = p.item;
+ if (item != null)
+ return item;
+ }
+ return null;
+ }
+
+ /**
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public E getFirst() {
+ return screenNullResult(peekFirst());
+ }
+
+ /**
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public E getLast() {
+ return screenNullResult(peekLast());
+ }
+
+ public E pollFirst() {
+ for (Node<E> p = first(); p != null; p = succ(p)) {
+ E item = p.item;
+ if (item != null && p.casItem(item, null)) {
+ unlink(p);
+ return item;
+ }
+ }
+ return null;
+ }
+
+ public E pollLast() {
+ for (Node<E> p = last(); p != null; p = pred(p)) {
+ E item = p.item;
+ if (item != null && p.casItem(item, null)) {
+ unlink(p);
+ return item;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public E removeFirst() {
+ return screenNullResult(pollFirst());
+ }
+
+ /**
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public E removeLast() {
+ return screenNullResult(pollLast());
+ }
+
+ // *** Queue and stack methods ***
+
+ /**
+ * Inserts the specified element at the tail of this deque.
+ *
+ * @return {@code true} (as specified by {@link Queue#offer})
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean offer(E e) {
+ return offerLast(e);
+ }
+
+ /**
+ * Inserts the specified element at the tail of this deque.
+ *
+ * @return {@code true} (as specified by {@link Collection#add})
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean add(E e) {
+ return offerLast(e);
+ }
+
+ public E poll() { return pollFirst(); }
+ public E remove() { return removeFirst(); }
+ public E peek() { return peekFirst(); }
+ public E element() { return getFirst(); }
+ public void push(E e) { addFirst(e); }
+ public E pop() { return removeFirst(); }
+
+ /**
+ * Removes the first element {@code e} such that
+ * {@code o.equals(e)}, if such an element exists in this deque.
+ * If the deque does not contain the element, it is unchanged.
+ *
+ * @param o element to be removed from this deque, if present
+ * @return {@code true} if the deque contained the specified element
+ * @throws NullPointerException if the specified element is {@code null}
+ */
+ public boolean removeFirstOccurrence(Object o) {
+ checkNotNull(o);
+ for (Node<E> p = first(); p != null; p = succ(p)) {
+ E item = p.item;
+ if (item != null && o.equals(item) && p.casItem(item, null)) {
+ unlink(p);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Removes the last element {@code e} such that
+ * {@code o.equals(e)}, if such an element exists in this deque.
+ * If the deque does not contain the element, it is unchanged.
+ *
+ * @param o element to be removed from this deque, if present
+ * @return {@code true} if the deque contained the specified element
+ * @throws NullPointerException if the specified element is {@code null}
+ */
+ public boolean removeLastOccurrence(Object o) {
+ checkNotNull(o);
+ for (Node<E> p = last(); p != null; p = pred(p)) {
+ E item = p.item;
+ if (item != null && o.equals(item) && p.casItem(item, null)) {
+ unlink(p);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns {@code true} if this deque contains at least one
+ * element {@code e} such that {@code o.equals(e)}.
+ *
+ * @param o element whose presence in this deque is to be tested
+ * @return {@code true} if this deque contains the specified element
+ */
+ public boolean contains(Object o) {
+ if (o == null) return false;
+ for (Node<E> p = first(); p != null; p = succ(p)) {
+ E item = p.item;
+ if (item != null && o.equals(item))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns {@code true} if this collection contains no elements.
+ *
+ * @return {@code true} if this collection contains no elements
+ */
+ public boolean isEmpty() {
+ return peekFirst() == null;
+ }
+
+ /**
+ * Returns the number of elements in this deque. If this deque
+ * contains more than {@code Integer.MAX_VALUE} elements, it
+ * returns {@code Integer.MAX_VALUE}.
+ *
+ * <p>Beware that, unlike in most collections, this method is
+ * <em>NOT</em> a constant-time operation. Because of the
+ * asynchronous nature of these deques, determining the current
+ * number of elements requires traversing them all to count them.
+ * Additionally, it is possible for the size to change during
+ * execution of this method, in which case the returned result
+ * will be inaccurate. Thus, this method is typically not very
+ * useful in concurrent applications.
+ *
+ * @return the number of elements in this deque
+ */
+ public int size() {
+ long count = 0;
+ for (Node<E> p = first(); p != null; p = succ(p))
+ if (p.item != null)
+ ++count;
+ return (count >= Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) count;
+ }
+
+ /**
+ * Removes the first element {@code e} such that
+ * {@code o.equals(e)}, if such an element exists in this deque.
+ * If the deque does not contain the element, it is unchanged.
+ *
+ * @param o element to be removed from this deque, if present
+ * @return {@code true} if the deque contained the specified element
+ * @throws NullPointerException if the specified element is {@code null}
+ */
+ public boolean remove(Object o) {
+ return removeFirstOccurrence(o);
+ }
+
+ /**
+ * Appends all of the elements in the specified collection to the end of
+ * this deque, in the order that they are returned by the specified
+ * collection's iterator. The behavior of this operation is undefined if
+ * the specified collection is modified while the operation is in
+ * progress. (This implies that the behavior of this call is undefined if
+ * the specified Collection is this deque, and this deque is nonempty.)
+ *
+ * @param c the elements to be inserted into this deque
+ * @return {@code true} if this deque changed as a result of the call
+ * @throws NullPointerException if {@code c} or any element within it
+ * is {@code null}
+ */
+ public boolean addAll(Collection<? extends E> c) {
+ Iterator<? extends E> it = c.iterator();
+ if (!it.hasNext())
+ return false;
+ do {
+ addLast(it.next());
+ } while (it.hasNext());
+ return true;
+ }
+
+ /**
+ * Removes all of the elements from this deque.
+ */
+ public void clear() {
+ while (pollFirst() != null)
+ ;
+ }
+
+ /**
+ * Returns an array containing all of the elements in this deque, in
+ * proper sequence (from first to last element).
+ *
+ * <p>The returned array will be "safe" in that no references to it are
+ * maintained by this deque. (In other words, this method must allocate
+ * a new array). The caller is thus free to modify the returned array.
+ *
+ * <p>This method acts as bridge between array-based and collection-based
+ * APIs.
+ *
+ * @return an array containing all of the elements in this deque
+ */
+ public Object[] toArray() {
+ return toArrayList().toArray();
+ }
+
+ /**
+ * Returns an array containing all of the elements in this deque,
+ * in proper sequence (from first to last element); the runtime
+ * type of the returned array is that of the specified array. If
+ * the deque fits in the specified array, it is returned therein.
+ * Otherwise, a new array is allocated with the runtime type of
+ * the specified array and the size of this deque.
+ *
+ * <p>If this deque fits in the specified array with room to spare
+ * (i.e., the array has more elements than this deque), the element in
+ * the array immediately following the end of the deque is set to
+ * {@code null}.
+ *
+ * <p>Like the {@link #toArray()} method, this method acts as bridge between
+ * array-based and collection-based APIs. Further, this method allows
+ * precise control over the runtime type of the output array, and may,
+ * under certain circumstances, be used to save allocation costs.
+ *
+ * <p>Suppose {@code x} is a deque known to contain only strings.
+ * The following code can be used to dump the deque into a newly
+ * allocated array of {@code String}:
+ *
+ * <pre>
+ * String[] y = x.toArray(new String[0]);</pre>
+ *
+ * Note that {@code toArray(new Object[0])} is identical in function to
+ * {@code toArray()}.
+ *
+ * @param a the array into which the elements of the deque are to
+ * be stored, if it is big enough; otherwise, a new array of the
+ * same runtime type is allocated for this purpose
+ * @return an array containing all of the elements in this deque
+ * @throws ArrayStoreException if the runtime type of the specified array
+ * is not a supertype of the runtime type of every element in
+ * this deque
+ * @throws NullPointerException if the specified array is null
+ */
+ public <T> T[] toArray(T[] a) {
+ return toArrayList().toArray(a);
+ }
+
+ /**
+ * Returns an iterator over the elements in this deque in proper sequence.
+ * The elements will be returned in order from first (head) to last (tail).
+ *
+ * <p>The returned {@code Iterator} is a "weakly consistent" iterator that
+ * will never throw {@link java.util.ConcurrentModificationException
+ * ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ *
+ * @return an iterator over the elements in this deque in proper sequence
+ */
+ public Iterator<E> iterator() {
+ return new Itr();
+ }
+
+ /**
+ * Returns an iterator over the elements in this deque in reverse
+ * sequential order. The elements will be returned in order from
+ * last (tail) to first (head).
+ *
+ * <p>The returned {@code Iterator} is a "weakly consistent" iterator that
+ * will never throw {@link java.util.ConcurrentModificationException
+ * ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ */
+ public Iterator<E> descendingIterator() {
+ return new DescendingItr();
+ }
+
+ private abstract class AbstractItr implements Iterator<E> {
+ /**
+ * Next node to return item for.
+ */
+ private Node<E> nextNode;
+
+ /**
+ * nextItem holds on to item fields because once we claim
+ * that an element exists in hasNext(), we must return it in
+ * the following next() call even if it was in the process of
+ * being removed when hasNext() was called.
+ */
+ private E nextItem;
+
+ /**
+ * Node returned by most recent call to next. Needed by remove.
+ * Reset to null if this element is deleted by a call to remove.
+ */
+ private Node<E> lastRet;
+
+ abstract Node<E> startNode();
+ abstract Node<E> nextNode(Node<E> p);
+
+ AbstractItr() {
+ advance();
+ }
+
+ /**
+ * Sets nextNode and nextItem to next valid node, or to null
+ * if no such.
+ */
+ private void advance() {
+ lastRet = nextNode;
+
+ Node<E> p = (nextNode == null) ? startNode() : nextNode(nextNode);
+ for (;; p = nextNode(p)) {
+ if (p == null) {
+ // p might be active end or TERMINATOR node; both are OK
+ nextNode = null;
+ nextItem = null;
+ break;
+ }
+ E item = p.item;
+ if (item != null) {
+ nextNode = p;
+ nextItem = item;
+ break;
+ }
+ }
+ }
+
+ public boolean hasNext() {
+ return nextItem != null;
+ }
+
+ public E next() {
+ E item = nextItem;
+ if (item == null) throw new NoSuchElementException();
+ advance();
+ return item;
+ }
+
+ public void remove() {
+ Node<E> l = lastRet;
+ if (l == null) throw new IllegalStateException();
+ l.item = null;
+ unlink(l);
+ lastRet = null;
+ }
+ }
+
+ /** Forward iterator */
+ private class Itr extends AbstractItr {
+ Node<E> startNode() { return first(); }
+ Node<E> nextNode(Node<E> p) { return succ(p); }
+ }
+
+ /** Descending iterator */
+ private class DescendingItr extends AbstractItr {
+ Node<E> startNode() { return last(); }
+ Node<E> nextNode(Node<E> p) { return pred(p); }
+ }
+
+ /**
+ * Save the state to a stream (that is, serialize it).
+ *
+ * @serialData All of the elements (each an {@code E}) in
+ * the proper order, followed by a null
+ * @param s the stream
+ */
+ private void writeObject(java.io.ObjectOutputStream s)
+ throws java.io.IOException {
+
+ // Write out any hidden stuff
+ s.defaultWriteObject();
+
+ // Write out all elements in the proper order.
+ for (Node<E> p = first(); p != null; p = succ(p)) {
+ Object item = p.item;
+ if (item != null)
+ s.writeObject(item);
+ }
+
+ // Use trailing null as sentinel
+ s.writeObject(null);
+ }
+
+ /**
+ * Reconstitute the Queue instance from a stream (that is,
+ * deserialize it).
+ * @param s the stream
+ */
+ private void readObject(java.io.ObjectInputStream s)
+ throws java.io.IOException, ClassNotFoundException {
+ // Read in capacity, and any hidden stuff
+ s.defaultReadObject();
+ tail = head = new Node<E>(null);
+ // Read in all elements and place in queue
+ for (;;) {
+ @SuppressWarnings("unchecked")
+ E item = (E)s.readObject();
+ if (item == null)
+ break;
+ else
+ offer(item);
+ }
+ }
+
+ // Unsafe mechanics
+
+ private static final sun.misc.Unsafe UNSAFE =
+ sun.misc.Unsafe.getUnsafe();
+ private static final long headOffset =
+ objectFieldOffset(UNSAFE, "head", ConcurrentLinkedDeque.class);
+ private static final long tailOffset =
+ objectFieldOffset(UNSAFE, "tail", ConcurrentLinkedDeque.class);
+
+ private boolean casHead(Node<E> cmp, Node<E> val) {
+ return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
+ }
+
+ private boolean casTail(Node<E> cmp, Node<E> val) {
+ return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val);
+ }
+
+ static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
+ String field, Class<?> klazz) {
+ try {
+ return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
+ } catch (NoSuchFieldException e) {
+ // Convert Exception to corresponding Error
+ NoSuchFieldError error = new NoSuchFieldError(field);
+ error.initCause(e);
+ throw error;
+ }
+ }
+}
diff --git a/concurrent/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java b/concurrent/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java
index 2253823..2d222c1 100644
--- a/concurrent/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java
+++ b/concurrent/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java
@@ -5,9 +5,13 @@
*/
package java.util.concurrent;
-import java.util.*;
-import java.util.concurrent.atomic.*;
+import java.util.AbstractQueue;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Queue;
// BEGIN android-note
// removed link to collections framework docs
@@ -126,34 +130,34 @@ public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
* CAS, so they never regress, although again this is merely an
* optimization.
*/
+
private static class Node<E> {
private volatile E item;
private volatile Node<E> next;
- private static final
- AtomicReferenceFieldUpdater<Node, Node>
- nextUpdater =
- AtomicReferenceFieldUpdater.newUpdater
- (Node.class, Node.class, "next");
- private static final
- AtomicReferenceFieldUpdater<Node, Object>
- itemUpdater =
- AtomicReferenceFieldUpdater.newUpdater
- (Node.class, Object.class, "item");
-
-
- Node(E item) { setItem(item); }
+ Node(E item) {
+ // Piggyback on imminent casNext()
+ lazySetItem(item);
+ }
E getItem() {
return item;
}
boolean casItem(E cmp, E val) {
- return itemUpdater.compareAndSet(this, cmp, val);
+ return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
}
void setItem(E val) {
- itemUpdater.set(this, val);
+ item = val;
+ }
+
+ void lazySetItem(E val) {
+ UNSAFE.putOrderedObject(this, itemOffset, val);
+ }
+
+ void lazySetNext(Node<E> val) {
+ UNSAFE.putOrderedObject(this, nextOffset, val);
}
Node<E> getNext() {
@@ -161,42 +165,45 @@ public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
}
boolean casNext(Node<E> cmp, Node<E> val) {
- return nextUpdater.compareAndSet(this, cmp, val);
+ return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
}
- void setNext(Node<E> val) {
- nextUpdater.set(this, val);
- }
+ // Unsafe mechanics
+ private static final sun.misc.Unsafe UNSAFE =
+ sun.misc.Unsafe.getUnsafe();
+ private static final long nextOffset =
+ objectFieldOffset(UNSAFE, "next", Node.class);
+ private static final long itemOffset =
+ objectFieldOffset(UNSAFE, "item", Node.class);
}
- private static final
- AtomicReferenceFieldUpdater<ConcurrentLinkedQueue, Node>
- tailUpdater =
- AtomicReferenceFieldUpdater.newUpdater
- (ConcurrentLinkedQueue.class, Node.class, "tail");
- private static final
- AtomicReferenceFieldUpdater<ConcurrentLinkedQueue, Node>
- headUpdater =
- AtomicReferenceFieldUpdater.newUpdater
- (ConcurrentLinkedQueue.class, Node.class, "head");
-
- private boolean casTail(Node<E> cmp, Node<E> val) {
- return tailUpdater.compareAndSet(this, cmp, val);
- }
-
- private boolean casHead(Node<E> cmp, Node<E> val) {
- return headUpdater.compareAndSet(this, cmp, val);
- }
-
-
-
/**
- * Pointer to first node, initialized to a dummy node.
+ * A node from which the first live (non-deleted) node (if any)
+ * can be reached in O(1) time.
+ * Invariants:
+ * - all live nodes are reachable from head via succ()
+ * - head != null
+ * - (tmp = head).next != tmp || tmp != head
+ * Non-invariants:
+ * - head.item may or may not be null.
+ * - it is permitted for tail to lag behind head, that is, for tail
+ * to not be reachable from head!
*/
private transient volatile Node<E> head = new Node<E>(null);
- /** Pointer to last node on list */
+ /**
+ * A node from which the last node on list (that is, the unique
+ * node with node.next == null) can be reached in O(1) time.
+ * Invariants:
+ * - the last node is always reachable from tail via succ()
+ * - tail != null
+ * Non-invariants:
+ * - tail.item may or may not be null.
+ * - it is permitted for tail to lag behind head, that is, for tail
+ * to not be reachable from head!
+ * - tail.next may or may not be self-pointing to tail.
+ */
private transient volatile Node<E> tail = head;
@@ -214,8 +221,8 @@ public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
* of its elements are null
*/
public ConcurrentLinkedQueue(Collection<? extends E> c) {
- for (Iterator<? extends E> it = c.iterator(); it.hasNext();)
- add(it.next());
+ for (E e : c)
+ add(e);
}
// Have to override just to update the javadoc
@@ -231,7 +238,7 @@ public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
}
/**
- * We don't bother to update head or tail pointers if less than
+ * We don't bother to update head or tail pointers if fewer than
* HOPS links from "true" location. We assume that volatile
* writes are significantly more expensive than volatile reads.
*/
@@ -243,7 +250,7 @@ public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
*/
final void updateHead(Node<E> h, Node<E> p) {
if (h != p && casHead(h, p))
- h.setNext(h);
+ h.lazySetNext(h);
}
/**
@@ -328,10 +335,12 @@ public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
}
/**
- * Returns the first actual (non-header) node on list. This is yet
- * another variant of poll/peek; here returning out the first
- * node, not element (so we cannot collapse with peek() without
- * introducing race.)
+ * Returns the first live (non-deleted) node on list, or null if none.
+ * This is yet another variant of poll/peek; here returning the
+ * first node, not element. We could make peek() a wrapper around
+ * first(), but that would cost an extra volatile read of item,
+ * and the need to add a retry loop to deal with the possibility
+ * of losing a race to a concurrent poll().
*/
Node<E> first() {
Node<E> h = head;
@@ -422,7 +431,9 @@ public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
Node<E> pred = null;
for (Node<E> p = first(); p != null; p = succ(p)) {
E item = p.getItem();
- if (item != null && o.equals(item) && p.casItem(item, null)) {
+ if (item != null &&
+ o.equals(item) &&
+ p.casItem(item, null)) {
Node<E> next = succ(p);
if (pred != null && next != null)
pred.casNext(p, next);
@@ -522,7 +533,8 @@ public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
/**
* Returns an iterator over the elements in this queue in proper sequence.
* The returned iterator is a "weakly consistent" iterator that
- * will never throw {@link ConcurrentModificationException},
+ * will never throw {@link java.util.ConcurrentModificationException
+ * ConcurrentModificationException},
* and guarantees to traverse elements as they existed upon
* construction of the iterator, and may (but is not guaranteed to)
* reflect any modifications subsequent to construction.
@@ -658,4 +670,35 @@ public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
}
}
+ // Unsafe mechanics
+
+ private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+ private static final long headOffset =
+ objectFieldOffset(UNSAFE, "head", ConcurrentLinkedQueue.class);
+ private static final long tailOffset =
+ objectFieldOffset(UNSAFE, "tail", ConcurrentLinkedQueue.class);
+
+ private boolean casTail(Node<E> cmp, Node<E> val) {
+ return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val);
+ }
+
+ private boolean casHead(Node<E> cmp, Node<E> val) {
+ return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
+ }
+
+ private void lazySetHead(Node<E> val) {
+ UNSAFE.putOrderedObject(this, headOffset, val);
+ }
+
+ static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
+ String field, Class<?> klazz) {
+ try {
+ return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
+ } catch (NoSuchFieldException e) {
+ // Convert Exception to corresponding Error
+ NoSuchFieldError error = new NoSuchFieldError(field);
+ error.initCause(e);
+ throw error;
+ }
+ }
}
diff --git a/concurrent/src/main/java/java/util/concurrent/ConcurrentNavigableMap.java b/concurrent/src/main/java/java/util/concurrent/ConcurrentNavigableMap.java
new file mode 100644
index 0000000..7d86afb
--- /dev/null
+++ b/concurrent/src/main/java/java/util/concurrent/ConcurrentNavigableMap.java
@@ -0,0 +1,148 @@
+/*
+ * 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;
+import java.util.*;
+
+/**
+ * A {@link ConcurrentMap} supporting {@link NavigableMap} operations,
+ * and recursively so for its navigable sub-maps.
+ *
+ * <p>This interface is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @author Doug Lea
+ * @param <K> the type of keys maintained by this map
+ * @param <V> the type of mapped values
+ * @since 1.6
+ */
+public interface ConcurrentNavigableMap<K,V>
+ extends ConcurrentMap<K,V>, NavigableMap<K,V>
+{
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ ConcurrentNavigableMap<K,V> subMap(K fromKey, boolean fromInclusive,
+ K toKey, boolean toInclusive);
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ ConcurrentNavigableMap<K,V> headMap(K toKey, boolean inclusive);
+
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ ConcurrentNavigableMap<K,V> tailMap(K fromKey, boolean inclusive);
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ ConcurrentNavigableMap<K,V> subMap(K fromKey, K toKey);
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ ConcurrentNavigableMap<K,V> headMap(K toKey);
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ ConcurrentNavigableMap<K,V> tailMap(K fromKey);
+
+ /**
+ * Returns a reverse order view of the mappings contained in this map.
+ * The descending map is backed by this map, so changes to the map are
+ * reflected in the descending map, and vice-versa.
+ *
+ * <p>The returned map has an ordering equivalent to
+ * <tt>{@link Collections#reverseOrder(Comparator) Collections.reverseOrder}(comparator())</tt>.
+ * The expression {@code m.descendingMap().descendingMap()} returns a
+ * view of {@code m} essentially equivalent to {@code m}.
+ *
+ * @return a reverse order view of this map
+ */
+ ConcurrentNavigableMap<K,V> descendingMap();
+
+ /**
+ * Returns a {@link NavigableSet} view of the keys contained in this map.
+ * The set's iterator returns the keys in ascending order.
+ * The set is backed by the map, so changes to the map are
+ * reflected in the set, and vice-versa. The set supports element
+ * removal, which removes the corresponding mapping from the map,
+ * via the {@code Iterator.remove}, {@code Set.remove},
+ * {@code removeAll}, {@code retainAll}, and {@code clear}
+ * operations. It does not support the {@code add} or {@code addAll}
+ * operations.
+ *
+ * <p>The view's {@code iterator} is a "weakly consistent" iterator
+ * that will never throw {@link ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ *
+ * @return a navigable set view of the keys in this map
+ */
+ public NavigableSet<K> navigableKeySet();
+
+ /**
+ * Returns a {@link NavigableSet} view of the keys contained in this map.
+ * The set's iterator returns the keys in ascending order.
+ * The set is backed by the map, so changes to the map are
+ * reflected in the set, and vice-versa. The set supports element
+ * removal, which removes the corresponding mapping from the map,
+ * via the {@code Iterator.remove}, {@code Set.remove},
+ * {@code removeAll}, {@code retainAll}, and {@code clear}
+ * operations. It does not support the {@code add} or {@code addAll}
+ * operations.
+ *
+ * <p>The view's {@code iterator} is a "weakly consistent" iterator
+ * that will never throw {@link ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ *
+ * <p>This method is equivalent to method {@code navigableKeySet}.
+ *
+ * @return a navigable set view of the keys in this map
+ */
+ NavigableSet<K> keySet();
+
+ /**
+ * Returns a reverse order {@link NavigableSet} view of the keys contained in this map.
+ * The set's iterator returns the keys in descending order.
+ * The set is backed by the map, so changes to the map are
+ * reflected in the set, and vice-versa. The set supports element
+ * removal, which removes the corresponding mapping from the map,
+ * via the {@code Iterator.remove}, {@code Set.remove},
+ * {@code removeAll}, {@code retainAll}, and {@code clear}
+ * operations. It does not support the {@code add} or {@code addAll}
+ * operations.
+ *
+ * <p>The view's {@code iterator} is a "weakly consistent" iterator
+ * that will never throw {@link ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ *
+ * @return a reverse order navigable set view of the keys in this map
+ */
+ public NavigableSet<K> descendingKeySet();
+}
diff --git a/concurrent/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java b/concurrent/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java
new file mode 100644
index 0000000..d73d163
--- /dev/null
+++ b/concurrent/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java
@@ -0,0 +1,3115 @@
+/*
+ * 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;
+import java.util.*;
+import java.util.concurrent.atomic.*;
+
+/**
+ * A scalable concurrent {@link ConcurrentNavigableMap} implementation.
+ * The map is sorted according to the {@linkplain Comparable natural
+ * ordering} of its keys, or by a {@link Comparator} provided at map
+ * creation time, depending on which constructor is used.
+ *
+ * <p>This class implements a concurrent variant of <a
+ * href="http://www.cs.umd.edu/~pugh/">SkipLists</a> providing
+ * expected average <i>log(n)</i> time cost for the
+ * <tt>containsKey</tt>, <tt>get</tt>, <tt>put</tt> and
+ * <tt>remove</tt> operations and their variants. Insertion, removal,
+ * update, and access operations safely execute concurrently by
+ * multiple threads. Iterators are <i>weakly consistent</i>, returning
+ * elements reflecting the state of the map at some point at or since
+ * the creation of the iterator. They do <em>not</em> throw {@link
+ * ConcurrentModificationException}, and may proceed concurrently with
+ * other operations. Ascending key ordered views and their iterators
+ * are faster than descending ones.
+ *
+ * <p>All <tt>Map.Entry</tt> pairs returned by methods in this class
+ * and its views represent snapshots of mappings at the time they were
+ * produced. They do <em>not</em> support the <tt>Entry.setValue</tt>
+ * method. (Note however that it is possible to change mappings in the
+ * associated map using <tt>put</tt>, <tt>putIfAbsent</tt>, or
+ * <tt>replace</tt>, depending on exactly which effect you need.)
+ *
+ * <p>Beware that, unlike in most collections, the <tt>size</tt>
+ * method is <em>not</em> a constant-time operation. Because of the
+ * asynchronous nature of these maps, determining the current number
+ * of elements requires a traversal of the elements. Additionally,
+ * the bulk operations <tt>putAll</tt>, <tt>equals</tt>, and
+ * <tt>clear</tt> are <em>not</em> guaranteed to be performed
+ * atomically. For example, an iterator operating concurrently with a
+ * <tt>putAll</tt> operation might view only some of the added
+ * elements.
+ *
+ * <p>This class and its views and iterators implement all of the
+ * <em>optional</em> methods of the {@link Map} and {@link Iterator}
+ * interfaces. Like most other concurrent collections, this class does
+ * <em>not</em> permit the use of <tt>null</tt> keys or values because some
+ * null return values cannot be reliably distinguished from the absence of
+ * elements.
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @author Doug Lea
+ * @param <K> the type of keys maintained by this map
+ * @param <V> the type of mapped values
+ * @since 1.6
+ */
+public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
+ implements ConcurrentNavigableMap<K,V>,
+ Cloneable,
+ java.io.Serializable {
+ /*
+ * This class implements a tree-like two-dimensionally linked skip
+ * list in which the index levels are represented in separate
+ * nodes from the base nodes holding data. There are two reasons
+ * for taking this approach instead of the usual array-based
+ * structure: 1) Array based implementations seem to encounter
+ * more complexity and overhead 2) We can use cheaper algorithms
+ * for the heavily-traversed index lists than can be used for the
+ * base lists. Here's a picture of some of the basics for a
+ * possible list with 2 levels of index:
+ *
+ * Head nodes Index nodes
+ * +-+ right +-+ +-+
+ * |2|---------------->| |--------------------->| |->null
+ * +-+ +-+ +-+
+ * | down | |
+ * v v v
+ * +-+ +-+ +-+ +-+ +-+ +-+
+ * |1|----------->| |->| |------>| |----------->| |------>| |->null
+ * +-+ +-+ +-+ +-+ +-+ +-+
+ * v | | | | |
+ * Nodes next v v v v v
+ * +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+
+ * | |->|A|->|B|->|C|->|D|->|E|->|F|->|G|->|H|->|I|->|J|->|K|->null
+ * +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+
+ *
+ * The base lists use a variant of the HM linked ordered set
+ * algorithm. See Tim Harris, "A pragmatic implementation of
+ * non-blocking linked lists"
+ * http://www.cl.cam.ac.uk/~tlh20/publications.html and Maged
+ * Michael "High Performance Dynamic Lock-Free Hash Tables and
+ * List-Based Sets"
+ * http://www.research.ibm.com/people/m/michael/pubs.htm. The
+ * basic idea in these lists is to mark the "next" pointers of
+ * deleted nodes when deleting to avoid conflicts with concurrent
+ * insertions, and when traversing to keep track of triples
+ * (predecessor, node, successor) in order to detect when and how
+ * to unlink these deleted nodes.
+ *
+ * Rather than using mark-bits to mark list deletions (which can
+ * be slow and space-intensive using AtomicMarkedReference), nodes
+ * use direct CAS'able next pointers. On deletion, instead of
+ * marking a pointer, they splice in another node that can be
+ * thought of as standing for a marked pointer (indicating this by
+ * using otherwise impossible field values). Using plain nodes
+ * acts roughly like "boxed" implementations of marked pointers,
+ * but uses new nodes only when nodes are deleted, not for every
+ * link. This requires less space and supports faster
+ * traversal. Even if marked references were better supported by
+ * JVMs, traversal using this technique might still be faster
+ * because any search need only read ahead one more node than
+ * otherwise required (to check for trailing marker) rather than
+ * unmasking mark bits or whatever on each read.
+ *
+ * This approach maintains the essential property needed in the HM
+ * algorithm of changing the next-pointer of a deleted node so
+ * that any other CAS of it will fail, but implements the idea by
+ * changing the pointer to point to a different node, not by
+ * marking it. While it would be possible to further squeeze
+ * space by defining marker nodes not to have key/value fields, it
+ * isn't worth the extra type-testing overhead. The deletion
+ * markers are rarely encountered during traversal and are
+ * normally quickly garbage collected. (Note that this technique
+ * would not work well in systems without garbage collection.)
+ *
+ * In addition to using deletion markers, the lists also use
+ * nullness of value fields to indicate deletion, in a style
+ * similar to typical lazy-deletion schemes. If a node's value is
+ * null, then it is considered logically deleted and ignored even
+ * though it is still reachable. This maintains proper control of
+ * concurrent replace vs delete operations -- an attempted replace
+ * must fail if a delete beat it by nulling field, and a delete
+ * must return the last non-null value held in the field. (Note:
+ * Null, rather than some special marker, is used for value fields
+ * here because it just so happens to mesh with the Map API
+ * requirement that method get returns null if there is no
+ * mapping, which allows nodes to remain concurrently readable
+ * even when deleted. Using any other marker value here would be
+ * messy at best.)
+ *
+ * Here's the sequence of events for a deletion of node n with
+ * predecessor b and successor f, initially:
+ *
+ * +------+ +------+ +------+
+ * ... | b |------>| n |----->| f | ...
+ * +------+ +------+ +------+
+ *
+ * 1. CAS n's value field from non-null to null.
+ * From this point on, no public operations encountering
+ * the node consider this mapping to exist. However, other
+ * ongoing insertions and deletions might still modify
+ * n's next pointer.
+ *
+ * 2. CAS n's next pointer to point to a new marker node.
+ * From this point on, no other nodes can be appended to n.
+ * which avoids deletion errors in CAS-based linked lists.
+ *
+ * +------+ +------+ +------+ +------+
+ * ... | b |------>| n |----->|marker|------>| f | ...
+ * +------+ +------+ +------+ +------+
+ *
+ * 3. CAS b's next pointer over both n and its marker.
+ * From this point on, no new traversals will encounter n,
+ * and it can eventually be GCed.
+ * +------+ +------+
+ * ... | b |----------------------------------->| f | ...
+ * +------+ +------+
+ *
+ * A failure at step 1 leads to simple retry due to a lost race
+ * with another operation. Steps 2-3 can fail because some other
+ * thread noticed during a traversal a node with null value and
+ * helped out by marking and/or unlinking. This helping-out
+ * ensures that no thread can become stuck waiting for progress of
+ * the deleting thread. The use of marker nodes slightly
+ * complicates helping-out code because traversals must track
+ * consistent reads of up to four nodes (b, n, marker, f), not
+ * just (b, n, f), although the next field of a marker is
+ * immutable, and once a next field is CAS'ed to point to a
+ * marker, it never again changes, so this requires less care.
+ *
+ * Skip lists add indexing to this scheme, so that the base-level
+ * traversals start close to the locations being found, inserted
+ * or deleted -- usually base level traversals only traverse a few
+ * nodes. This doesn't change the basic algorithm except for the
+ * need to make sure base traversals start at predecessors (here,
+ * b) that are not (structurally) deleted, otherwise retrying
+ * after processing the deletion.
+ *
+ * Index levels are maintained as lists with volatile next fields,
+ * using CAS to link and unlink. Races are allowed in index-list
+ * operations that can (rarely) fail to link in a new index node
+ * or delete one. (We can't do this of course for data nodes.)
+ * However, even when this happens, the index lists remain sorted,
+ * so correctly serve as indices. This can impact performance,
+ * but since skip lists are probabilistic anyway, the net result
+ * is that under contention, the effective "p" value may be lower
+ * than its nominal value. And race windows are kept small enough
+ * that in practice these failures are rare, even under a lot of
+ * contention.
+ *
+ * The fact that retries (for both base and index lists) are
+ * relatively cheap due to indexing allows some minor
+ * simplifications of retry logic. Traversal restarts are
+ * performed after most "helping-out" CASes. This isn't always
+ * strictly necessary, but the implicit backoffs tend to help
+ * reduce other downstream failed CAS's enough to outweigh restart
+ * cost. This worsens the worst case, but seems to improve even
+ * highly contended cases.
+ *
+ * Unlike most skip-list implementations, index insertion and
+ * deletion here require a separate traversal pass occuring after
+ * the base-level action, to add or remove index nodes. This adds
+ * to single-threaded overhead, but improves contended
+ * multithreaded performance by narrowing interference windows,
+ * and allows deletion to ensure that all index nodes will be made
+ * unreachable upon return from a public remove operation, thus
+ * avoiding unwanted garbage retention. This is more important
+ * here than in some other data structures because we cannot null
+ * out node fields referencing user keys since they might still be
+ * read by other ongoing traversals.
+ *
+ * Indexing uses skip list parameters that maintain good search
+ * performance while using sparser-than-usual indices: The
+ * hardwired parameters k=1, p=0.5 (see method randomLevel) mean
+ * that about one-quarter of the nodes have indices. Of those that
+ * do, half have one level, a quarter have two, and so on (see
+ * Pugh's Skip List Cookbook, sec 3.4). The expected total space
+ * requirement for a map is slightly less than for the current
+ * implementation of java.util.TreeMap.
+ *
+ * Changing the level of the index (i.e, the height of the
+ * tree-like structure) also uses CAS. The head index has initial
+ * level/height of one. Creation of an index with height greater
+ * than the current level adds a level to the head index by
+ * CAS'ing on a new top-most head. To maintain good performance
+ * after a lot of removals, deletion methods heuristically try to
+ * reduce the height if the topmost levels appear to be empty.
+ * This may encounter races in which it possible (but rare) to
+ * reduce and "lose" a level just as it is about to contain an
+ * index (that will then never be encountered). This does no
+ * structural harm, and in practice appears to be a better option
+ * than allowing unrestrained growth of levels.
+ *
+ * The code for all this is more verbose than you'd like. Most
+ * operations entail locating an element (or position to insert an
+ * element). The code to do this can't be nicely factored out
+ * because subsequent uses require a snapshot of predecessor
+ * and/or successor and/or value fields which can't be returned
+ * all at once, at least not without creating yet another object
+ * to hold them -- creating such little objects is an especially
+ * bad idea for basic internal search operations because it adds
+ * to GC overhead. (This is one of the few times I've wished Java
+ * had macros.) Instead, some traversal code is interleaved within
+ * insertion and removal operations. The control logic to handle
+ * all the retry conditions is sometimes twisty. Most search is
+ * broken into 2 parts. findPredecessor() searches index nodes
+ * only, returning a base-level predecessor of the key. findNode()
+ * finishes out the base-level search. Even with this factoring,
+ * there is a fair amount of near-duplication of code to handle
+ * variants.
+ *
+ * For explanation of algorithms sharing at least a couple of
+ * features with this one, see Mikhail Fomitchev's thesis
+ * (http://www.cs.yorku.ca/~mikhail/), Keir Fraser's thesis
+ * (http://www.cl.cam.ac.uk/users/kaf24/), and Hakan Sundell's
+ * thesis (http://www.cs.chalmers.se/~phs/).
+ *
+ * Given the use of tree-like index nodes, you might wonder why
+ * this doesn't use some kind of search tree instead, which would
+ * support somewhat faster search operations. The reason is that
+ * there are no known efficient lock-free insertion and deletion
+ * algorithms for search trees. The immutability of the "down"
+ * links of index nodes (as opposed to mutable "left" fields in
+ * true trees) makes this tractable using only CAS operations.
+ *
+ * Notation guide for local variables
+ * Node: b, n, f for predecessor, node, successor
+ * Index: q, r, d for index node, right, down.
+ * t for another index node
+ * Head: h
+ * Levels: j
+ * Keys: k, key
+ * Values: v, value
+ * Comparisons: c
+ */
+
+ private static final long serialVersionUID = -8627078645895051609L;
+
+ /**
+ * Generates the initial random seed for the cheaper per-instance
+ * random number generators used in randomLevel.
+ */
+ private static final Random seedGenerator = new Random();
+
+ /**
+ * Special value used to identify base-level header
+ */
+ private static final Object BASE_HEADER = new Object();
+
+ /**
+ * The topmost head index of the skiplist.
+ */
+ private transient volatile HeadIndex<K,V> head;
+
+ /**
+ * The comparator used to maintain order in this map, or null
+ * if using natural ordering.
+ * @serial
+ */
+ private final Comparator<? super K> comparator;
+
+ /**
+ * Seed for simple random number generator. Not volatile since it
+ * doesn't matter too much if different threads don't see updates.
+ */
+ private transient int randomSeed;
+
+ /** Lazily initialized key set */
+ private transient KeySet keySet;
+ /** Lazily initialized entry set */
+ private transient EntrySet entrySet;
+ /** Lazily initialized values collection */
+ private transient Values values;
+ /** Lazily initialized descending key set */
+ private transient ConcurrentNavigableMap<K,V> descendingMap;
+
+ /**
+ * Initializes or resets state. Needed by constructors, clone,
+ * clear, readObject. and ConcurrentSkipListSet.clone.
+ * (Note that comparator must be separately initialized.)
+ */
+ final void initialize() {
+ keySet = null;
+ entrySet = null;
+ values = null;
+ descendingMap = null;
+ randomSeed = seedGenerator.nextInt() | 0x0100; // ensure nonzero
+ head = new HeadIndex<K,V>(new Node<K,V>(null, BASE_HEADER, null),
+ null, null, 1);
+ }
+
+ /** Updater for casHead */
+ private static final
+ AtomicReferenceFieldUpdater<ConcurrentSkipListMap, HeadIndex>
+ headUpdater = AtomicReferenceFieldUpdater.newUpdater
+ (ConcurrentSkipListMap.class, HeadIndex.class, "head");
+
+ /**
+ * compareAndSet head node
+ */
+ private boolean casHead(HeadIndex<K,V> cmp, HeadIndex<K,V> val) {
+ return headUpdater.compareAndSet(this, cmp, val);
+ }
+
+ /* ---------------- Nodes -------------- */
+
+ /**
+ * Nodes hold keys and values, and are singly linked in sorted
+ * order, possibly with some intervening marker nodes. The list is
+ * headed by a dummy node accessible as head.node. The value field
+ * is declared only as Object because it takes special non-V
+ * values for marker and header nodes.
+ */
+ static final class Node<K,V> {
+ final K key;
+ volatile Object value;
+ volatile Node<K,V> next;
+
+ /**
+ * Creates a new regular node.
+ */
+ Node(K key, Object value, Node<K,V> next) {
+ this.key = key;
+ this.value = value;
+ this.next = next;
+ }
+
+ /**
+ * Creates a new marker node. A marker is distinguished by
+ * having its value field point to itself. Marker nodes also
+ * have null keys, a fact that is exploited in a few places,
+ * but this doesn't distinguish markers from the base-level
+ * header node (head.node), which also has a null key.
+ */
+ Node(Node<K,V> next) {
+ this.key = null;
+ this.value = this;
+ this.next = next;
+ }
+
+ /** Updater for casNext */
+ static final AtomicReferenceFieldUpdater<Node, Node>
+ nextUpdater = AtomicReferenceFieldUpdater.newUpdater
+ (Node.class, Node.class, "next");
+
+ /** Updater for casValue */
+ static final AtomicReferenceFieldUpdater<Node, Object>
+ valueUpdater = AtomicReferenceFieldUpdater.newUpdater
+ (Node.class, Object.class, "value");
+
+ /**
+ * compareAndSet value field
+ */
+ boolean casValue(Object cmp, Object val) {
+ return valueUpdater.compareAndSet(this, cmp, val);
+ }
+
+ /**
+ * compareAndSet next field
+ */
+ boolean casNext(Node<K,V> cmp, Node<K,V> val) {
+ return nextUpdater.compareAndSet(this, cmp, val);
+ }
+
+ /**
+ * Returns true if this node is a marker. This method isn't
+ * actually called in any current code checking for markers
+ * because callers will have already read value field and need
+ * to use that read (not another done here) and so directly
+ * test if value points to node.
+ * @param n a possibly null reference to a node
+ * @return true if this node is a marker node
+ */
+ boolean isMarker() {
+ return value == this;
+ }
+
+ /**
+ * Returns true if this node is the header of base-level list.
+ * @return true if this node is header node
+ */
+ boolean isBaseHeader() {
+ return value == BASE_HEADER;
+ }
+
+ /**
+ * Tries to append a deletion marker to this node.
+ * @param f the assumed current successor of this node
+ * @return true if successful
+ */
+ boolean appendMarker(Node<K,V> f) {
+ return casNext(f, new Node<K,V>(f));
+ }
+
+ /**
+ * Helps out a deletion by appending marker or unlinking from
+ * predecessor. This is called during traversals when value
+ * field seen to be null.
+ * @param b predecessor
+ * @param f successor
+ */
+ void helpDelete(Node<K,V> b, Node<K,V> f) {
+ /*
+ * Rechecking links and then doing only one of the
+ * help-out stages per call tends to minimize CAS
+ * interference among helping threads.
+ */
+ if (f == next && this == b.next) {
+ if (f == null || f.value != f) // not already marked
+ appendMarker(f);
+ else
+ b.casNext(this, f.next);
+ }
+ }
+
+ /**
+ * Returns value if this node contains a valid key-value pair,
+ * else null.
+ * @return this node's value if it isn't a marker or header or
+ * is deleted, else null.
+ */
+ V getValidValue() {
+ Object v = value;
+ if (v == this || v == BASE_HEADER)
+ return null;
+ return (V)v;
+ }
+
+ /**
+ * Creates and returns a new SimpleImmutableEntry holding current
+ * mapping if this node holds a valid value, else null.
+ * @return new entry or null
+ */
+ AbstractMap.SimpleImmutableEntry<K,V> createSnapshot() {
+ V v = getValidValue();
+ if (v == null)
+ return null;
+ return new AbstractMap.SimpleImmutableEntry<K,V>(key, v);
+ }
+ }
+
+ /* ---------------- Indexing -------------- */
+
+ /**
+ * Index nodes represent the levels of the skip list. Note that
+ * even though both Nodes and Indexes have forward-pointing
+ * fields, they have different types and are handled in different
+ * ways, that can't nicely be captured by placing field in a
+ * shared abstract class.
+ */
+ static class Index<K,V> {
+ final Node<K,V> node;
+ final Index<K,V> down;
+ volatile Index<K,V> right;
+
+ /**
+ * Creates index node with given values.
+ */
+ Index(Node<K,V> node, Index<K,V> down, Index<K,V> right) {
+ this.node = node;
+ this.down = down;
+ this.right = right;
+ }
+
+ /** Updater for casRight */
+ static final AtomicReferenceFieldUpdater<Index, Index>
+ rightUpdater = AtomicReferenceFieldUpdater.newUpdater
+ (Index.class, Index.class, "right");
+
+ /**
+ * compareAndSet right field
+ */
+ final boolean casRight(Index<K,V> cmp, Index<K,V> val) {
+ return rightUpdater.compareAndSet(this, cmp, val);
+ }
+
+ /**
+ * Returns true if the node this indexes has been deleted.
+ * @return true if indexed node is known to be deleted
+ */
+ final boolean indexesDeletedNode() {
+ return node.value == null;
+ }
+
+ /**
+ * Tries to CAS newSucc as successor. To minimize races with
+ * unlink that may lose this index node, if the node being
+ * indexed is known to be deleted, it doesn't try to link in.
+ * @param succ the expected current successor
+ * @param newSucc the new successor
+ * @return true if successful
+ */
+ final boolean link(Index<K,V> succ, Index<K,V> newSucc) {
+ Node<K,V> n = node;
+ newSucc.right = succ;
+ return n.value != null && casRight(succ, newSucc);
+ }
+
+ /**
+ * Tries to CAS right field to skip over apparent successor
+ * succ. Fails (forcing a retraversal by caller) if this node
+ * is known to be deleted.
+ * @param succ the expected current successor
+ * @return true if successful
+ */
+ final boolean unlink(Index<K,V> succ) {
+ return !indexesDeletedNode() && casRight(succ, succ.right);
+ }
+ }
+
+ /* ---------------- Head nodes -------------- */
+
+ /**
+ * Nodes heading each level keep track of their level.
+ */
+ static final class HeadIndex<K,V> extends Index<K,V> {
+ final int level;
+ HeadIndex(Node<K,V> node, Index<K,V> down, Index<K,V> right, int level) {
+ super(node, down, right);
+ this.level = level;
+ }
+ }
+
+ /* ---------------- Comparison utilities -------------- */
+
+ /**
+ * Represents a key with a comparator as a Comparable.
+ *
+ * Because most sorted collections seem to use natural ordering on
+ * Comparables (Strings, Integers, etc), most internal methods are
+ * geared to use them. This is generally faster than checking
+ * per-comparison whether to use comparator or comparable because
+ * it doesn't require a (Comparable) cast for each comparison.
+ * (Optimizers can only sometimes remove such redundant checks
+ * themselves.) When Comparators are used,
+ * ComparableUsingComparators are created so that they act in the
+ * same way as natural orderings. This penalizes use of
+ * Comparators vs Comparables, which seems like the right
+ * tradeoff.
+ */
+ static final class ComparableUsingComparator<K> implements Comparable<K> {
+ final K actualKey;
+ final Comparator<? super K> cmp;
+ ComparableUsingComparator(K key, Comparator<? super K> cmp) {
+ this.actualKey = key;
+ this.cmp = cmp;
+ }
+ public int compareTo(K k2) {
+ return cmp.compare(actualKey, k2);
+ }
+ }
+
+ /**
+ * If using comparator, return a ComparableUsingComparator, else
+ * cast key as Comparable, which may cause ClassCastException,
+ * which is propagated back to caller.
+ */
+ private Comparable<? super K> comparable(Object key) throws ClassCastException {
+ if (key == null)
+ throw new NullPointerException();
+ if (comparator != null)
+ return new ComparableUsingComparator<K>((K)key, comparator);
+ else
+ return (Comparable<? super K>)key;
+ }
+
+ /**
+ * Compares using comparator or natural ordering. Used when the
+ * ComparableUsingComparator approach doesn't apply.
+ */
+ int compare(K k1, K k2) throws ClassCastException {
+ Comparator<? super K> cmp = comparator;
+ if (cmp != null)
+ return cmp.compare(k1, k2);
+ else
+ return ((Comparable<? super K>)k1).compareTo(k2);
+ }
+
+ /**
+ * Returns true if given key greater than or equal to least and
+ * strictly less than fence, bypassing either test if least or
+ * fence are null. Needed mainly in submap operations.
+ */
+ boolean inHalfOpenRange(K key, K least, K fence) {
+ if (key == null)
+ throw new NullPointerException();
+ return ((least == null || compare(key, least) >= 0) &&
+ (fence == null || compare(key, fence) < 0));
+ }
+
+ /**
+ * Returns true if given key greater than or equal to least and less
+ * or equal to fence. Needed mainly in submap operations.
+ */
+ boolean inOpenRange(K key, K least, K fence) {
+ if (key == null)
+ throw new NullPointerException();
+ return ((least == null || compare(key, least) >= 0) &&
+ (fence == null || compare(key, fence) <= 0));
+ }
+
+ /* ---------------- Traversal -------------- */
+
+ /**
+ * Returns a base-level node with key strictly less than given key,
+ * or the base-level header if there is no such node. Also
+ * unlinks indexes to deleted nodes found along the way. Callers
+ * rely on this side-effect of clearing indices to deleted nodes.
+ * @param key the key
+ * @return a predecessor of key
+ */
+ private Node<K,V> findPredecessor(Comparable<? super K> key) {
+ if (key == null)
+ throw new NullPointerException(); // don't postpone errors
+ for (;;) {
+ Index<K,V> q = head;
+ Index<K,V> r = q.right;
+ for (;;) {
+ if (r != null) {
+ Node<K,V> n = r.node;
+ K k = n.key;
+ if (n.value == null) {
+ if (!q.unlink(r))
+ break; // restart
+ r = q.right; // reread r
+ continue;
+ }
+ if (key.compareTo(k) > 0) {
+ q = r;
+ r = r.right;
+ continue;
+ }
+ }
+ Index<K,V> d = q.down;
+ if (d != null) {
+ q = d;
+ r = d.right;
+ } else
+ return q.node;
+ }
+ }
+ }
+
+ /**
+ * Returns node holding key or null if no such, clearing out any
+ * deleted nodes seen along the way. Repeatedly traverses at
+ * base-level looking for key starting at predecessor returned
+ * from findPredecessor, processing base-level deletions as
+ * encountered. Some callers rely on this side-effect of clearing
+ * deleted nodes.
+ *
+ * Restarts occur, at traversal step centered on node n, if:
+ *
+ * (1) After reading n's next field, n is no longer assumed
+ * predecessor b's current successor, which means that
+ * we don't have a consistent 3-node snapshot and so cannot
+ * unlink any subsequent deleted nodes encountered.
+ *
+ * (2) n's value field is null, indicating n is deleted, in
+ * which case we help out an ongoing structural deletion
+ * before retrying. Even though there are cases where such
+ * unlinking doesn't require restart, they aren't sorted out
+ * here because doing so would not usually outweigh cost of
+ * restarting.
+ *
+ * (3) n is a marker or n's predecessor's value field is null,
+ * indicating (among other possibilities) that
+ * findPredecessor returned a deleted node. We can't unlink
+ * the node because we don't know its predecessor, so rely
+ * on another call to findPredecessor to notice and return
+ * some earlier predecessor, which it will do. This check is
+ * only strictly needed at beginning of loop, (and the
+ * b.value check isn't strictly needed at all) but is done
+ * each iteration to help avoid contention with other
+ * threads by callers that will fail to be able to change
+ * links, and so will retry anyway.
+ *
+ * The traversal loops in doPut, doRemove, and findNear all
+ * include the same three kinds of checks. And specialized
+ * versions appear in findFirst, and findLast and their
+ * variants. They can't easily share code because each uses the
+ * reads of fields held in locals occurring in the orders they
+ * were performed.
+ *
+ * @param key the key
+ * @return node holding key, or null if no such
+ */
+ private Node<K,V> findNode(Comparable<? super K> key) {
+ for (;;) {
+ Node<K,V> b = findPredecessor(key);
+ Node<K,V> n = b.next;
+ for (;;) {
+ if (n == null)
+ return null;
+ Node<K,V> f = n.next;
+ if (n != b.next) // inconsistent read
+ break;
+ Object v = n.value;
+ if (v == null) { // n is deleted
+ n.helpDelete(b, f);
+ break;
+ }
+ if (v == n || b.value == null) // b is deleted
+ break;
+ int c = key.compareTo(n.key);
+ if (c == 0)
+ return n;
+ if (c < 0)
+ return null;
+ b = n;
+ n = f;
+ }
+ }
+ }
+
+ /**
+ * Specialized variant of findNode to perform Map.get. Does a weak
+ * traversal, not bothering to fix any deleted index nodes,
+ * returning early if it happens to see key in index, and passing
+ * over any deleted base nodes, falling back to getUsingFindNode
+ * only if it would otherwise return value from an ongoing
+ * deletion. Also uses "bound" to eliminate need for some
+ * comparisons (see Pugh Cookbook). Also folds uses of null checks
+ * and node-skipping because markers have null keys.
+ * @param okey the key
+ * @return the value, or null if absent
+ */
+ private V doGet(Object okey) {
+ Comparable<? super K> key = comparable(okey);
+ Node<K,V> bound = null;
+ Index<K,V> q = head;
+ Index<K,V> r = q.right;
+ Node<K,V> n;
+ K k;
+ int c;
+ for (;;) {
+ Index<K,V> d;
+ // Traverse rights
+ if (r != null && (n = r.node) != bound && (k = n.key) != null) {
+ if ((c = key.compareTo(k)) > 0) {
+ q = r;
+ r = r.right;
+ continue;
+ } else if (c == 0) {
+ Object v = n.value;
+ return (v != null)? (V)v : getUsingFindNode(key);
+ } else
+ bound = n;
+ }
+
+ // Traverse down
+ if ((d = q.down) != null) {
+ q = d;
+ r = d.right;
+ } else
+ break;
+ }
+
+ // Traverse nexts
+ for (n = q.node.next; n != null; n = n.next) {
+ if ((k = n.key) != null) {
+ if ((c = key.compareTo(k)) == 0) {
+ Object v = n.value;
+ return (v != null)? (V)v : getUsingFindNode(key);
+ } else if (c < 0)
+ break;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Performs map.get via findNode. Used as a backup if doGet
+ * encounters an in-progress deletion.
+ * @param key the key
+ * @return the value, or null if absent
+ */
+ private V getUsingFindNode(Comparable<? super K> key) {
+ /*
+ * Loop needed here and elsewhere in case value field goes
+ * null just as it is about to be returned, in which case we
+ * lost a race with a deletion, so must retry.
+ */
+ for (;;) {
+ Node<K,V> n = findNode(key);
+ if (n == null)
+ return null;
+ Object v = n.value;
+ if (v != null)
+ return (V)v;
+ }
+ }
+
+ /* ---------------- Insertion -------------- */
+
+ /**
+ * Main insertion method. Adds element if not present, or
+ * replaces value if present and onlyIfAbsent is false.
+ * @param kkey the key
+ * @param value the value that must be associated with key
+ * @param onlyIfAbsent if should not insert if already present
+ * @return the old value, or null if newly inserted
+ */
+ private V doPut(K kkey, V value, boolean onlyIfAbsent) {
+ Comparable<? super K> key = comparable(kkey);
+ for (;;) {
+ Node<K,V> b = findPredecessor(key);
+ Node<K,V> n = b.next;
+ for (;;) {
+ if (n != null) {
+ Node<K,V> f = n.next;
+ if (n != b.next) // inconsistent read
+ break;
+ Object v = n.value;
+ if (v == null) { // n is deleted
+ n.helpDelete(b, f);
+ break;
+ }
+ if (v == n || b.value == null) // b is deleted
+ break;
+ int c = key.compareTo(n.key);
+ if (c > 0) {
+ b = n;
+ n = f;
+ continue;
+ }
+ if (c == 0) {
+ if (onlyIfAbsent || n.casValue(v, value))
+ return (V)v;
+ else
+ break; // restart if lost race to replace value
+ }
+ // else c < 0; fall through
+ }
+
+ Node<K,V> z = new Node<K,V>(kkey, value, n);
+ if (!b.casNext(n, z))
+ break; // restart if lost race to append to b
+ int level = randomLevel();
+ if (level > 0)
+ insertIndex(z, level);
+ return null;
+ }
+ }
+ }
+
+ /**
+ * Returns a random level for inserting a new node.
+ * Hardwired to k=1, p=0.5, max 31 (see above and
+ * Pugh's "Skip List Cookbook", sec 3.4).
+ *
+ * This uses the simplest of the generators described in George
+ * Marsaglia's "Xorshift RNGs" paper. This is not a high-quality
+ * generator but is acceptable here.
+ */
+ private int randomLevel() {
+ int x = randomSeed;
+ x ^= x << 13;
+ x ^= x >>> 17;
+ randomSeed = x ^= x << 5;
+ if ((x & 0x8001) != 0) // test highest and lowest bits
+ return 0;
+ int level = 1;
+ while (((x >>>= 1) & 1) != 0) ++level;
+ return level;
+ }
+
+ /**
+ * Creates and adds index nodes for the given node.
+ * @param z the node
+ * @param level the level of the index
+ */
+ private void insertIndex(Node<K,V> z, int level) {
+ HeadIndex<K,V> h = head;
+ int max = h.level;
+
+ if (level <= max) {
+ Index<K,V> idx = null;
+ for (int i = 1; i <= level; ++i)
+ idx = new Index<K,V>(z, idx, null);
+ addIndex(idx, h, level);
+
+ } else { // Add a new level
+ /*
+ * To reduce interference by other threads checking for
+ * empty levels in tryReduceLevel, new levels are added
+ * with initialized right pointers. Which in turn requires
+ * keeping levels in an array to access them while
+ * creating new head index nodes from the opposite
+ * direction.
+ */
+ level = max + 1;
+ Index<K,V>[] idxs = (Index<K,V>[])new Index[level+1];
+ Index<K,V> idx = null;
+ for (int i = 1; i <= level; ++i)
+ idxs[i] = idx = new Index<K,V>(z, idx, null);
+
+ HeadIndex<K,V> oldh;
+ int k;
+ for (;;) {
+ oldh = head;
+ int oldLevel = oldh.level;
+ if (level <= oldLevel) { // lost race to add level
+ k = level;
+ break;
+ }
+ HeadIndex<K,V> newh = oldh;
+ Node<K,V> oldbase = oldh.node;
+ for (int j = oldLevel+1; j <= level; ++j)
+ newh = new HeadIndex<K,V>(oldbase, newh, idxs[j], j);
+ if (casHead(oldh, newh)) {
+ k = oldLevel;
+ break;
+ }
+ }
+ addIndex(idxs[k], oldh, k);
+ }
+ }
+
+ /**
+ * Adds given index nodes from given level down to 1.
+ * @param idx the topmost index node being inserted
+ * @param h the value of head to use to insert. This must be
+ * snapshotted by callers to provide correct insertion level
+ * @param indexLevel the level of the index
+ */
+ private void addIndex(Index<K,V> idx, HeadIndex<K,V> h, int indexLevel) {
+ // Track next level to insert in case of retries
+ int insertionLevel = indexLevel;
+ Comparable<? super K> key = comparable(idx.node.key);
+ if (key == null) throw new NullPointerException();
+
+ // Similar to findPredecessor, but adding index nodes along
+ // path to key.
+ for (;;) {
+ int j = h.level;
+ Index<K,V> q = h;
+ Index<K,V> r = q.right;
+ Index<K,V> t = idx;
+ for (;;) {
+ if (r != null) {
+ Node<K,V> n = r.node;
+ // compare before deletion check avoids needing recheck
+ int c = key.compareTo(n.key);
+ if (n.value == null) {
+ if (!q.unlink(r))
+ break;
+ r = q.right;
+ continue;
+ }
+ if (c > 0) {
+ q = r;
+ r = r.right;
+ continue;
+ }
+ }
+
+ if (j == insertionLevel) {
+ // Don't insert index if node already deleted
+ if (t.indexesDeletedNode()) {
+ findNode(key); // cleans up
+ return;
+ }
+ if (!q.link(r, t))
+ break; // restart
+ if (--insertionLevel == 0) {
+ // need final deletion check before return
+ if (t.indexesDeletedNode())
+ findNode(key);
+ return;
+ }
+ }
+
+ if (--j >= insertionLevel && j < indexLevel)
+ t = t.down;
+ q = q.down;
+ r = q.right;
+ }
+ }
+ }
+
+ /* ---------------- Deletion -------------- */
+
+ /**
+ * Main deletion method. Locates node, nulls value, appends a
+ * deletion marker, unlinks predecessor, removes associated index
+ * nodes, and possibly reduces head index level.
+ *
+ * Index nodes are cleared out simply by calling findPredecessor.
+ * which unlinks indexes to deleted nodes found along path to key,
+ * which will include the indexes to this node. This is done
+ * unconditionally. We can't check beforehand whether there are
+ * index nodes because it might be the case that some or all
+ * indexes hadn't been inserted yet for this node during initial
+ * search for it, and we'd like to ensure lack of garbage
+ * retention, so must call to be sure.
+ *
+ * @param okey the key
+ * @param value if non-null, the value that must be
+ * associated with key
+ * @return the node, or null if not found
+ */
+ final V doRemove(Object okey, Object value) {
+ Comparable<? super K> key = comparable(okey);
+ for (;;) {
+ Node<K,V> b = findPredecessor(key);
+ Node<K,V> n = b.next;
+ for (;;) {
+ if (n == null)
+ return null;
+ Node<K,V> f = n.next;
+ if (n != b.next) // inconsistent read
+ break;
+ Object v = n.value;
+ if (v == null) { // n is deleted
+ n.helpDelete(b, f);
+ break;
+ }
+ if (v == n || b.value == null) // b is deleted
+ break;
+ int c = key.compareTo(n.key);
+ if (c < 0)
+ return null;
+ if (c > 0) {
+ b = n;
+ n = f;
+ continue;
+ }
+ if (value != null && !value.equals(v))
+ return null;
+ if (!n.casValue(v, null))
+ break;
+ if (!n.appendMarker(f) || !b.casNext(n, f))
+ findNode(key); // Retry via findNode
+ else {
+ findPredecessor(key); // Clean index
+ if (head.right == null)
+ tryReduceLevel();
+ }
+ return (V)v;
+ }
+ }
+ }
+
+ /**
+ * Possibly reduce head level if it has no nodes. This method can
+ * (rarely) make mistakes, in which case levels can disappear even
+ * though they are about to contain index nodes. This impacts
+ * performance, not correctness. To minimize mistakes as well as
+ * to reduce hysteresis, the level is reduced by one only if the
+ * topmost three levels look empty. Also, if the removed level
+ * looks non-empty after CAS, we try to change it back quick
+ * before anyone notices our mistake! (This trick works pretty
+ * well because this method will practically never make mistakes
+ * unless current thread stalls immediately before first CAS, in
+ * which case it is very unlikely to stall again immediately
+ * afterwards, so will recover.)
+ *
+ * We put up with all this rather than just let levels grow
+ * because otherwise, even a small map that has undergone a large
+ * number of insertions and removals will have a lot of levels,
+ * slowing down access more than would an occasional unwanted
+ * reduction.
+ */
+ private void tryReduceLevel() {
+ HeadIndex<K,V> h = head;
+ HeadIndex<K,V> d;
+ HeadIndex<K,V> e;
+ if (h.level > 3 &&
+ (d = (HeadIndex<K,V>)h.down) != null &&
+ (e = (HeadIndex<K,V>)d.down) != null &&
+ e.right == null &&
+ d.right == null &&
+ h.right == null &&
+ casHead(h, d) && // try to set
+ h.right != null) // recheck
+ casHead(d, h); // try to backout
+ }
+
+ /* ---------------- Finding and removing first element -------------- */
+
+ /**
+ * Specialized variant of findNode to get first valid node.
+ * @return first node or null if empty
+ */
+ Node<K,V> findFirst() {
+ for (;;) {
+ Node<K,V> b = head.node;
+ Node<K,V> n = b.next;
+ if (n == null)
+ return null;
+ if (n.value != null)
+ return n;
+ n.helpDelete(b, n.next);
+ }
+ }
+
+ /**
+ * Removes first entry; returns its snapshot.
+ * @return null if empty, else snapshot of first entry
+ */
+ Map.Entry<K,V> doRemoveFirstEntry() {
+ for (;;) {
+ Node<K,V> b = head.node;
+ Node<K,V> n = b.next;
+ if (n == null)
+ return null;
+ Node<K,V> f = n.next;
+ if (n != b.next)
+ continue;
+ Object v = n.value;
+ if (v == null) {
+ n.helpDelete(b, f);
+ continue;
+ }
+ if (!n.casValue(v, null))
+ continue;
+ if (!n.appendMarker(f) || !b.casNext(n, f))
+ findFirst(); // retry
+ clearIndexToFirst();
+ return new AbstractMap.SimpleImmutableEntry<K,V>(n.key, (V)v);
+ }
+ }
+
+ /**
+ * Clears out index nodes associated with deleted first entry.
+ */
+ private void clearIndexToFirst() {
+ for (;;) {
+ Index<K,V> q = head;
+ for (;;) {
+ Index<K,V> r = q.right;
+ if (r != null && r.indexesDeletedNode() && !q.unlink(r))
+ break;
+ if ((q = q.down) == null) {
+ if (head.right == null)
+ tryReduceLevel();
+ return;
+ }
+ }
+ }
+ }
+
+
+ /* ---------------- Finding and removing last element -------------- */
+
+ /**
+ * Specialized version of find to get last valid node.
+ * @return last node or null if empty
+ */
+ Node<K,V> findLast() {
+ /*
+ * findPredecessor can't be used to traverse index level
+ * because this doesn't use comparisons. So traversals of
+ * both levels are folded together.
+ */
+ Index<K,V> q = head;
+ for (;;) {
+ Index<K,V> d, r;
+ if ((r = q.right) != null) {
+ if (r.indexesDeletedNode()) {
+ q.unlink(r);
+ q = head; // restart
+ }
+ else
+ q = r;
+ } else if ((d = q.down) != null) {
+ q = d;
+ } else {
+ Node<K,V> b = q.node;
+ Node<K,V> n = b.next;
+ for (;;) {
+ if (n == null)
+ return (b.isBaseHeader())? null : b;
+ Node<K,V> f = n.next; // inconsistent read
+ if (n != b.next)
+ break;
+ Object v = n.value;
+ if (v == null) { // n is deleted
+ n.helpDelete(b, f);
+ break;
+ }
+ if (v == n || b.value == null) // b is deleted
+ break;
+ b = n;
+ n = f;
+ }
+ q = head; // restart
+ }
+ }
+ }
+
+ /**
+ * Specialized variant of findPredecessor to get predecessor of last
+ * valid node. Needed when removing the last entry. It is possible
+ * that all successors of returned node will have been deleted upon
+ * return, in which case this method can be retried.
+ * @return likely predecessor of last node
+ */
+ private Node<K,V> findPredecessorOfLast() {
+ for (;;) {
+ Index<K,V> q = head;
+ for (;;) {
+ Index<K,V> d, r;
+ if ((r = q.right) != null) {
+ if (r.indexesDeletedNode()) {
+ q.unlink(r);
+ break; // must restart
+ }
+ // proceed as far across as possible without overshooting
+ if (r.node.next != null) {
+ q = r;
+ continue;
+ }
+ }
+ if ((d = q.down) != null)
+ q = d;
+ else
+ return q.node;
+ }
+ }
+ }
+
+ /**
+ * Removes last entry; returns its snapshot.
+ * Specialized variant of doRemove.
+ * @return null if empty, else snapshot of last entry
+ */
+ Map.Entry<K,V> doRemoveLastEntry() {
+ for (;;) {
+ Node<K,V> b = findPredecessorOfLast();
+ Node<K,V> n = b.next;
+ if (n == null) {
+ if (b.isBaseHeader()) // empty
+ return null;
+ else
+ continue; // all b's successors are deleted; retry
+ }
+ for (;;) {
+ Node<K,V> f = n.next;
+ if (n != b.next) // inconsistent read
+ break;
+ Object v = n.value;
+ if (v == null) { // n is deleted
+ n.helpDelete(b, f);
+ break;
+ }
+ if (v == n || b.value == null) // b is deleted
+ break;
+ if (f != null) {
+ b = n;
+ n = f;
+ continue;
+ }
+ if (!n.casValue(v, null))
+ break;
+ K key = n.key;
+ Comparable<? super K> ck = comparable(key);
+ if (!n.appendMarker(f) || !b.casNext(n, f))
+ findNode(ck); // Retry via findNode
+ else {
+ findPredecessor(ck); // Clean index
+ if (head.right == null)
+ tryReduceLevel();
+ }
+ return new AbstractMap.SimpleImmutableEntry<K,V>(key, (V)v);
+ }
+ }
+ }
+
+ /* ---------------- Relational operations -------------- */
+
+ // Control values OR'ed as arguments to findNear
+
+ private static final int EQ = 1;
+ private static final int LT = 2;
+ private static final int GT = 0; // Actually checked as !LT
+
+ /**
+ * Utility for ceiling, floor, lower, higher methods.
+ * @param kkey the key
+ * @param rel the relation -- OR'ed combination of EQ, LT, GT
+ * @return nearest node fitting relation, or null if no such
+ */
+ Node<K,V> findNear(K kkey, int rel) {
+ Comparable<? super K> key = comparable(kkey);
+ for (;;) {
+ Node<K,V> b = findPredecessor(key);
+ Node<K,V> n = b.next;
+ for (;;) {
+ if (n == null)
+ return ((rel & LT) == 0 || b.isBaseHeader())? null : b;
+ Node<K,V> f = n.next;
+ if (n != b.next) // inconsistent read
+ break;
+ Object v = n.value;
+ if (v == null) { // n is deleted
+ n.helpDelete(b, f);
+ break;
+ }
+ if (v == n || b.value == null) // b is deleted
+ break;
+ int c = key.compareTo(n.key);
+ if ((c == 0 && (rel & EQ) != 0) ||
+ (c < 0 && (rel & LT) == 0))
+ return n;
+ if ( c <= 0 && (rel & LT) != 0)
+ return (b.isBaseHeader())? null : b;
+ b = n;
+ n = f;
+ }
+ }
+ }
+
+ /**
+ * Returns SimpleImmutableEntry for results of findNear.
+ * @param key the key
+ * @param rel the relation -- OR'ed combination of EQ, LT, GT
+ * @return Entry fitting relation, or null if no such
+ */
+ AbstractMap.SimpleImmutableEntry<K,V> getNear(K key, int rel) {
+ for (;;) {
+ Node<K,V> n = findNear(key, rel);
+ if (n == null)
+ return null;
+ AbstractMap.SimpleImmutableEntry<K,V> e = n.createSnapshot();
+ if (e != null)
+ return e;
+ }
+ }
+
+
+ /* ---------------- Constructors -------------- */
+
+ /**
+ * Constructs a new, empty map, sorted according to the
+ * {@linkplain Comparable natural ordering} of the keys.
+ */
+ public ConcurrentSkipListMap() {
+ this.comparator = null;
+ initialize();
+ }
+
+ /**
+ * Constructs a new, empty map, sorted according to the specified
+ * comparator.
+ *
+ * @param comparator the comparator that will be used to order this map.
+ * If <tt>null</tt>, the {@linkplain Comparable natural
+ * ordering} of the keys will be used.
+ */
+ public ConcurrentSkipListMap(Comparator<? super K> comparator) {
+ this.comparator = comparator;
+ initialize();
+ }
+
+ /**
+ * Constructs a new map containing the same mappings as the given map,
+ * sorted according to the {@linkplain Comparable natural ordering} of
+ * the keys.
+ *
+ * @param m the map whose mappings are to be placed in this map
+ * @throws ClassCastException if the keys in <tt>m</tt> are not
+ * {@link Comparable}, or are not mutually comparable
+ * @throws NullPointerException if the specified map or any of its keys
+ * or values are null
+ */
+ public ConcurrentSkipListMap(Map<? extends K, ? extends V> m) {
+ this.comparator = null;
+ initialize();
+ putAll(m);
+ }
+
+ /**
+ * Constructs a new map containing the same mappings and using the
+ * same ordering as the specified sorted map.
+ *
+ * @param m the sorted map whose mappings are to be placed in this
+ * map, and whose comparator is to be used to sort this map
+ * @throws NullPointerException if the specified sorted map or any of
+ * its keys or values are null
+ */
+ public ConcurrentSkipListMap(SortedMap<K, ? extends V> m) {
+ this.comparator = m.comparator();
+ initialize();
+ buildFromSorted(m);
+ }
+
+ /**
+ * Returns a shallow copy of this <tt>ConcurrentSkipListMap</tt>
+ * instance. (The keys and values themselves are not cloned.)
+ *
+ * @return a shallow copy of this map
+ */
+ public ConcurrentSkipListMap<K,V> clone() {
+ ConcurrentSkipListMap<K,V> clone = null;
+ try {
+ clone = (ConcurrentSkipListMap<K,V>) super.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new InternalError();
+ }
+
+ clone.initialize();
+ clone.buildFromSorted(this);
+ return clone;
+ }
+
+ /**
+ * Streamlined bulk insertion to initialize from elements of
+ * given sorted map. Call only from constructor or clone
+ * method.
+ */
+ private void buildFromSorted(SortedMap<K, ? extends V> map) {
+ if (map == null)
+ throw new NullPointerException();
+
+ HeadIndex<K,V> h = head;
+ Node<K,V> basepred = h.node;
+
+ // Track the current rightmost node at each level. Uses an
+ // ArrayList to avoid committing to initial or maximum level.
+ ArrayList<Index<K,V>> preds = new ArrayList<Index<K,V>>();
+
+ // initialize
+ for (int i = 0; i <= h.level; ++i)
+ preds.add(null);
+ Index<K,V> q = h;
+ for (int i = h.level; i > 0; --i) {
+ preds.set(i, q);
+ q = q.down;
+ }
+
+ Iterator<? extends Map.Entry<? extends K, ? extends V>> it =
+ map.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry<? extends K, ? extends V> e = it.next();
+ int j = randomLevel();
+ if (j > h.level) j = h.level + 1;
+ K k = e.getKey();
+ V v = e.getValue();
+ if (k == null || v == null)
+ throw new NullPointerException();
+ Node<K,V> z = new Node<K,V>(k, v, null);
+ basepred.next = z;
+ basepred = z;
+ if (j > 0) {
+ Index<K,V> idx = null;
+ for (int i = 1; i <= j; ++i) {
+ idx = new Index<K,V>(z, idx, null);
+ if (i > h.level)
+ h = new HeadIndex<K,V>(h.node, h, idx, i);
+
+ if (i < preds.size()) {
+ preds.get(i).right = idx;
+ preds.set(i, idx);
+ } else
+ preds.add(idx);
+ }
+ }
+ }
+ head = h;
+ }
+
+ /* ---------------- Serialization -------------- */
+
+ /**
+ * Save the state of this map to a stream.
+ *
+ * @serialData The key (Object) and value (Object) for each
+ * key-value mapping represented by the map, followed by
+ * <tt>null</tt>. The key-value mappings are emitted in key-order
+ * (as determined by the Comparator, or by the keys' natural
+ * ordering if no Comparator).
+ */
+ private void writeObject(java.io.ObjectOutputStream s)
+ throws java.io.IOException {
+ // Write out the Comparator and any hidden stuff
+ s.defaultWriteObject();
+
+ // Write out keys and values (alternating)
+ for (Node<K,V> n = findFirst(); n != null; n = n.next) {
+ V v = n.getValidValue();
+ if (v != null) {
+ s.writeObject(n.key);
+ s.writeObject(v);
+ }
+ }
+ s.writeObject(null);
+ }
+
+ /**
+ * Reconstitute the map from a stream.
+ */
+ private void readObject(final java.io.ObjectInputStream s)
+ throws java.io.IOException, ClassNotFoundException {
+ // Read in the Comparator and any hidden stuff
+ s.defaultReadObject();
+ // Reset transients
+ initialize();
+
+ /*
+ * This is nearly identical to buildFromSorted, but is
+ * distinct because readObject calls can't be nicely adapted
+ * as the kind of iterator needed by buildFromSorted. (They
+ * can be, but doing so requires type cheats and/or creation
+ * of adaptor classes.) It is simpler to just adapt the code.
+ */
+
+ HeadIndex<K,V> h = head;
+ Node<K,V> basepred = h.node;
+ ArrayList<Index<K,V>> preds = new ArrayList<Index<K,V>>();
+ for (int i = 0; i <= h.level; ++i)
+ preds.add(null);
+ Index<K,V> q = h;
+ for (int i = h.level; i > 0; --i) {
+ preds.set(i, q);
+ q = q.down;
+ }
+
+ for (;;) {
+ Object k = s.readObject();
+ if (k == null)
+ break;
+ Object v = s.readObject();
+ if (v == null)
+ throw new NullPointerException();
+ K key = (K) k;
+ V val = (V) v;
+ int j = randomLevel();
+ if (j > h.level) j = h.level + 1;
+ Node<K,V> z = new Node<K,V>(key, val, null);
+ basepred.next = z;
+ basepred = z;
+ if (j > 0) {
+ Index<K,V> idx = null;
+ for (int i = 1; i <= j; ++i) {
+ idx = new Index<K,V>(z, idx, null);
+ if (i > h.level)
+ h = new HeadIndex<K,V>(h.node, h, idx, i);
+
+ if (i < preds.size()) {
+ preds.get(i).right = idx;
+ preds.set(i, idx);
+ } else
+ preds.add(idx);
+ }
+ }
+ }
+ head = h;
+ }
+
+ /* ------ Map API methods ------ */
+
+ /**
+ * Returns <tt>true</tt> if this map contains a mapping for the specified
+ * key.
+ *
+ * @param key key whose presence in this map is to be tested
+ * @return <tt>true</tt> if this map contains a mapping for the specified key
+ * @throws ClassCastException if the specified key cannot be compared
+ * with the keys currently in the map
+ * @throws NullPointerException if the specified key is null
+ */
+ public boolean containsKey(Object key) {
+ return doGet(key) != null;
+ }
+
+ /**
+ * Returns the value to which the specified key is mapped,
+ * or {@code null} if this map contains no mapping for the key.
+ *
+ * <p>More formally, if this map contains a mapping from a key
+ * {@code k} to a value {@code v} such that {@code key} compares
+ * equal to {@code k} according to the map's ordering, then this
+ * method returns {@code v}; otherwise it returns {@code null}.
+ * (There can be at most one such mapping.)
+ *
+ * @throws ClassCastException if the specified key cannot be compared
+ * with the keys currently in the map
+ * @throws NullPointerException if the specified key is null
+ */
+ public V get(Object key) {
+ return doGet(key);
+ }
+
+ /**
+ * Associates the specified value with the specified key in this map.
+ * If the map previously contained a mapping for the key, the old
+ * value is replaced.
+ *
+ * @param key key with which the specified value is to be associated
+ * @param value value to be associated with the specified key
+ * @return the previous value associated with the specified key, or
+ * <tt>null</tt> if there was no mapping for the key
+ * @throws ClassCastException if the specified key cannot be compared
+ * with the keys currently in the map
+ * @throws NullPointerException if the specified key or value is null
+ */
+ public V put(K key, V value) {
+ if (value == null)
+ throw new NullPointerException();
+ return doPut(key, value, false);
+ }
+
+ /**
+ * Removes the mapping for the specified key from this map if present.
+ *
+ * @param key key for which mapping should be removed
+ * @return the previous value associated with the specified key, or
+ * <tt>null</tt> if there was no mapping for the key
+ * @throws ClassCastException if the specified key cannot be compared
+ * with the keys currently in the map
+ * @throws NullPointerException if the specified key is null
+ */
+ public V remove(Object key) {
+ return doRemove(key, null);
+ }
+
+ /**
+ * Returns <tt>true</tt> if this map maps one or more keys to the
+ * specified value. This operation requires time linear in the
+ * map size.
+ *
+ * @param value value whose presence in this map is to be tested
+ * @return <tt>true</tt> if a mapping to <tt>value</tt> exists;
+ * <tt>false</tt> otherwise
+ * @throws NullPointerException if the specified value is null
+ */
+ public boolean containsValue(Object value) {
+ if (value == null)
+ throw new NullPointerException();
+ for (Node<K,V> n = findFirst(); n != null; n = n.next) {
+ V v = n.getValidValue();
+ if (v != null && value.equals(v))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns the number of key-value mappings in this map. If this map
+ * contains more than <tt>Integer.MAX_VALUE</tt> elements, it
+ * returns <tt>Integer.MAX_VALUE</tt>.
+ *
+ * <p>Beware that, unlike in most collections, this method is
+ * <em>NOT</em> a constant-time operation. Because of the
+ * asynchronous nature of these maps, determining the current
+ * number of elements requires traversing them all to count them.
+ * Additionally, it is possible for the size to change during
+ * execution of this method, in which case the returned result
+ * will be inaccurate. Thus, this method is typically not very
+ * useful in concurrent applications.
+ *
+ * @return the number of elements in this map
+ */
+ public int size() {
+ long count = 0;
+ for (Node<K,V> n = findFirst(); n != null; n = n.next) {
+ if (n.getValidValue() != null)
+ ++count;
+ }
+ return (count >= Integer.MAX_VALUE)? Integer.MAX_VALUE : (int)count;
+ }
+
+ /**
+ * Returns <tt>true</tt> if this map contains no key-value mappings.
+ * @return <tt>true</tt> if this map contains no key-value mappings
+ */
+ public boolean isEmpty() {
+ return findFirst() == null;
+ }
+
+ /**
+ * Removes all of the mappings from this map.
+ */
+ public void clear() {
+ initialize();
+ }
+
+ /* ---------------- View methods -------------- */
+
+ /*
+ * Note: Lazy initialization works for views because view classes
+ * are stateless/immutable so it doesn't matter wrt correctness if
+ * more than one is created (which will only rarely happen). Even
+ * so, the following idiom conservatively ensures that the method
+ * returns the one it created if it does so, not one created by
+ * another racing thread.
+ */
+
+ /**
+ * Returns a {@link NavigableSet} view of the keys contained in this map.
+ * The set's iterator returns the keys in ascending order.
+ * The set is backed by the map, so changes to the map are
+ * reflected in the set, and vice-versa. The set supports element
+ * removal, which removes the corresponding mapping from the map,
+ * via the {@code Iterator.remove}, {@code Set.remove},
+ * {@code removeAll}, {@code retainAll}, and {@code clear}
+ * operations. It does not support the {@code add} or {@code addAll}
+ * operations.
+ *
+ * <p>The view's {@code iterator} is a "weakly consistent" iterator
+ * that will never throw {@link ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ *
+ * <p>This method is equivalent to method {@code navigableKeySet}.
+ *
+ * @return a navigable set view of the keys in this map
+ */
+ public NavigableSet<K> keySet() {
+ KeySet ks = keySet;
+ return (ks != null) ? ks : (keySet = new KeySet(this));
+ }
+
+ public NavigableSet<K> navigableKeySet() {
+ KeySet ks = keySet;
+ return (ks != null) ? ks : (keySet = new KeySet(this));
+ }
+
+ /**
+ * Returns a {@link Collection} view of the values contained in this map.
+ * The collection's iterator returns the values in ascending order
+ * of the corresponding keys.
+ * The collection is backed by the map, so changes to the map are
+ * reflected in the collection, and vice-versa. The collection
+ * supports element removal, which removes the corresponding
+ * mapping from the map, via the <tt>Iterator.remove</tt>,
+ * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
+ * <tt>retainAll</tt> and <tt>clear</tt> operations. It does not
+ * support the <tt>add</tt> or <tt>addAll</tt> operations.
+ *
+ * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
+ * that will never throw {@link ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ */
+ public Collection<V> values() {
+ Values vs = values;
+ return (vs != null) ? vs : (values = new Values(this));
+ }
+
+ /**
+ * Returns a {@link Set} view of the mappings contained in this map.
+ * The set's iterator returns the entries in ascending key order.
+ * The set is backed by the map, so changes to the map are
+ * reflected in the set, and vice-versa. The set supports element
+ * removal, which removes the corresponding mapping from the map,
+ * via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
+ * <tt>removeAll</tt>, <tt>retainAll</tt> and <tt>clear</tt>
+ * operations. It does not support the <tt>add</tt> or
+ * <tt>addAll</tt> operations.
+ *
+ * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
+ * that will never throw {@link ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ *
+ * <p>The <tt>Map.Entry</tt> elements returned by
+ * <tt>iterator.next()</tt> do <em>not</em> support the
+ * <tt>setValue</tt> operation.
+ *
+ * @return a set view of the mappings contained in this map,
+ * sorted in ascending key order
+ */
+ public Set<Map.Entry<K,V>> entrySet() {
+ EntrySet es = entrySet;
+ return (es != null) ? es : (entrySet = new EntrySet(this));
+ }
+
+ public ConcurrentNavigableMap<K,V> descendingMap() {
+ ConcurrentNavigableMap<K,V> dm = descendingMap;
+ return (dm != null) ? dm : (descendingMap = new SubMap<K,V>
+ (this, null, false, null, false, true));
+ }
+
+ public NavigableSet<K> descendingKeySet() {
+ return descendingMap().navigableKeySet();
+ }
+
+ /* ---------------- AbstractMap Overrides -------------- */
+
+ /**
+ * Compares the specified object with this map for equality.
+ * Returns <tt>true</tt> if the given object is also a map and the
+ * two maps represent the same mappings. More formally, two maps
+ * <tt>m1</tt> and <tt>m2</tt> represent the same mappings if
+ * <tt>m1.entrySet().equals(m2.entrySet())</tt>. This
+ * operation may return misleading results if either map is
+ * concurrently modified during execution of this method.
+ *
+ * @param o object to be compared for equality with this map
+ * @return <tt>true</tt> if the specified object is equal to this map
+ */
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+ if (!(o instanceof Map))
+ return false;
+ Map<?,?> m = (Map<?,?>) o;
+ try {
+ for (Map.Entry<K,V> e : this.entrySet())
+ if (! e.getValue().equals(m.get(e.getKey())))
+ return false;
+ for (Map.Entry<?,?> e : m.entrySet()) {
+ Object k = e.getKey();
+ Object v = e.getValue();
+ if (k == null || v == null || !v.equals(get(k)))
+ return false;
+ }
+ return true;
+ } catch (ClassCastException unused) {
+ return false;
+ } catch (NullPointerException unused) {
+ return false;
+ }
+ }
+
+ /* ------ ConcurrentMap API methods ------ */
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return the previous value associated with the specified key,
+ * or <tt>null</tt> if there was no mapping for the key
+ * @throws ClassCastException if the specified key cannot be compared
+ * with the keys currently in the map
+ * @throws NullPointerException if the specified key or value is null
+ */
+ public V putIfAbsent(K key, V value) {
+ if (value == null)
+ throw new NullPointerException();
+ return doPut(key, value, true);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws ClassCastException if the specified key cannot be compared
+ * with the keys currently in the map
+ * @throws NullPointerException if the specified key is null
+ */
+ public boolean remove(Object key, Object value) {
+ if (key == null)
+ throw new NullPointerException();
+ if (value == null)
+ return false;
+ return doRemove(key, value) != null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws ClassCastException if the specified key cannot be compared
+ * with the keys currently in the map
+ * @throws NullPointerException if any of the arguments are null
+ */
+ public boolean replace(K key, V oldValue, V newValue) {
+ if (oldValue == null || newValue == null)
+ throw new NullPointerException();
+ Comparable<? super K> k = comparable(key);
+ for (;;) {
+ Node<K,V> n = findNode(k);
+ if (n == null)
+ return false;
+ Object v = n.value;
+ if (v != null) {
+ if (!oldValue.equals(v))
+ return false;
+ if (n.casValue(v, newValue))
+ return true;
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return the previous value associated with the specified key,
+ * or <tt>null</tt> if there was no mapping for the key
+ * @throws ClassCastException if the specified key cannot be compared
+ * with the keys currently in the map
+ * @throws NullPointerException if the specified key or value is null
+ */
+ public V replace(K key, V value) {
+ if (value == null)
+ throw new NullPointerException();
+ Comparable<? super K> k = comparable(key);
+ for (;;) {
+ Node<K,V> n = findNode(k);
+ if (n == null)
+ return null;
+ Object v = n.value;
+ if (v != null && n.casValue(v, value))
+ return (V)v;
+ }
+ }
+
+ /* ------ SortedMap API methods ------ */
+
+ public Comparator<? super K> comparator() {
+ return comparator;
+ }
+
+ /**
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public K firstKey() {
+ Node<K,V> n = findFirst();
+ if (n == null)
+ throw new NoSuchElementException();
+ return n.key;
+ }
+
+ /**
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public K lastKey() {
+ Node<K,V> n = findLast();
+ if (n == null)
+ throw new NoSuchElementException();
+ return n.key;
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if {@code fromKey} or {@code toKey} is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public ConcurrentNavigableMap<K,V> subMap(K fromKey,
+ boolean fromInclusive,
+ K toKey,
+ boolean toInclusive) {
+ if (fromKey == null || toKey == null)
+ throw new NullPointerException();
+ return new SubMap<K,V>
+ (this, fromKey, fromInclusive, toKey, toInclusive, false);
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if {@code toKey} is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public ConcurrentNavigableMap<K,V> headMap(K toKey,
+ boolean inclusive) {
+ if (toKey == null)
+ throw new NullPointerException();
+ return new SubMap<K,V>
+ (this, null, false, toKey, inclusive, false);
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if {@code fromKey} is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public ConcurrentNavigableMap<K,V> tailMap(K fromKey,
+ boolean inclusive) {
+ if (fromKey == null)
+ throw new NullPointerException();
+ return new SubMap<K,V>
+ (this, fromKey, inclusive, null, false, false);
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if {@code fromKey} or {@code toKey} is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public ConcurrentNavigableMap<K,V> subMap(K fromKey, K toKey) {
+ return subMap(fromKey, true, toKey, false);
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if {@code toKey} is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public ConcurrentNavigableMap<K,V> headMap(K toKey) {
+ return headMap(toKey, false);
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if {@code fromKey} is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public ConcurrentNavigableMap<K,V> tailMap(K fromKey) {
+ return tailMap(fromKey, true);
+ }
+
+ /* ---------------- Relational operations -------------- */
+
+ /**
+ * Returns a key-value mapping associated with the greatest key
+ * strictly less than the given key, or <tt>null</tt> if there is
+ * no such key. The returned entry does <em>not</em> support the
+ * <tt>Entry.setValue</tt> method.
+ *
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified key is null
+ */
+ public Map.Entry<K,V> lowerEntry(K key) {
+ return getNear(key, LT);
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified key is null
+ */
+ public K lowerKey(K key) {
+ Node<K,V> n = findNear(key, LT);
+ return (n == null)? null : n.key;
+ }
+
+ /**
+ * Returns a key-value mapping associated with the greatest key
+ * less than or equal to the given key, or <tt>null</tt> if there
+ * is no such key. The returned entry does <em>not</em> support
+ * the <tt>Entry.setValue</tt> method.
+ *
+ * @param key the key
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified key is null
+ */
+ public Map.Entry<K,V> floorEntry(K key) {
+ return getNear(key, LT|EQ);
+ }
+
+ /**
+ * @param key the key
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified key is null
+ */
+ public K floorKey(K key) {
+ Node<K,V> n = findNear(key, LT|EQ);
+ return (n == null)? null : n.key;
+ }
+
+ /**
+ * Returns a key-value mapping associated with the least key
+ * greater than or equal to the given key, or <tt>null</tt> if
+ * there is no such entry. The returned entry does <em>not</em>
+ * support the <tt>Entry.setValue</tt> method.
+ *
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified key is null
+ */
+ public Map.Entry<K,V> ceilingEntry(K key) {
+ return getNear(key, GT|EQ);
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified key is null
+ */
+ public K ceilingKey(K key) {
+ Node<K,V> n = findNear(key, GT|EQ);
+ return (n == null)? null : n.key;
+ }
+
+ /**
+ * Returns a key-value mapping associated with the least key
+ * strictly greater than the given key, or <tt>null</tt> if there
+ * is no such key. The returned entry does <em>not</em> support
+ * the <tt>Entry.setValue</tt> method.
+ *
+ * @param key the key
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified key is null
+ */
+ public Map.Entry<K,V> higherEntry(K key) {
+ return getNear(key, GT);
+ }
+
+ /**
+ * @param key the key
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified key is null
+ */
+ public K higherKey(K key) {
+ Node<K,V> n = findNear(key, GT);
+ return (n == null)? null : n.key;
+ }
+
+ /**
+ * Returns a key-value mapping associated with the least
+ * key in this map, or <tt>null</tt> if the map is empty.
+ * The returned entry does <em>not</em> support
+ * the <tt>Entry.setValue</tt> method.
+ */
+ public Map.Entry<K,V> firstEntry() {
+ for (;;) {
+ Node<K,V> n = findFirst();
+ if (n == null)
+ return null;
+ AbstractMap.SimpleImmutableEntry<K,V> e = n.createSnapshot();
+ if (e != null)
+ return e;
+ }
+ }
+
+ /**
+ * Returns a key-value mapping associated with the greatest
+ * key in this map, or <tt>null</tt> if the map is empty.
+ * The returned entry does <em>not</em> support
+ * the <tt>Entry.setValue</tt> method.
+ */
+ public Map.Entry<K,V> lastEntry() {
+ for (;;) {
+ Node<K,V> n = findLast();
+ if (n == null)
+ return null;
+ AbstractMap.SimpleImmutableEntry<K,V> e = n.createSnapshot();
+ if (e != null)
+ return e;
+ }
+ }
+
+ /**
+ * Removes and returns a key-value mapping associated with
+ * the least key in this map, or <tt>null</tt> if the map is empty.
+ * The returned entry does <em>not</em> support
+ * the <tt>Entry.setValue</tt> method.
+ */
+ public Map.Entry<K,V> pollFirstEntry() {
+ return doRemoveFirstEntry();
+ }
+
+ /**
+ * Removes and returns a key-value mapping associated with
+ * the greatest key in this map, or <tt>null</tt> if the map is empty.
+ * The returned entry does <em>not</em> support
+ * the <tt>Entry.setValue</tt> method.
+ */
+ public Map.Entry<K,V> pollLastEntry() {
+ return doRemoveLastEntry();
+ }
+
+
+ /* ---------------- Iterators -------------- */
+
+ /**
+ * Base of iterator classes:
+ */
+ abstract class Iter<T> implements Iterator<T> {
+ /** the last node returned by next() */
+ Node<K,V> lastReturned;
+ /** the next node to return from next(); */
+ Node<K,V> next;
+ /** Cache of next value field to maintain weak consistency */
+ V nextValue;
+
+ /** Initializes ascending iterator for entire range. */
+ Iter() {
+ for (;;) {
+ next = findFirst();
+ if (next == null)
+ break;
+ Object x = next.value;
+ if (x != null && x != next) {
+ nextValue = (V) x;
+ break;
+ }
+ }
+ }
+
+ public final boolean hasNext() {
+ return next != null;
+ }
+
+ /** Advances next to higher entry. */
+ final void advance() {
+ if (next == null)
+ throw new NoSuchElementException();
+ lastReturned = next;
+ for (;;) {
+ next = next.next;
+ if (next == null)
+ break;
+ Object x = next.value;
+ if (x != null && x != next) {
+ nextValue = (V) x;
+ break;
+ }
+ }
+ }
+
+ public void remove() {
+ Node<K,V> l = lastReturned;
+ if (l == null)
+ throw new IllegalStateException();
+ // It would not be worth all of the overhead to directly
+ // unlink from here. Using remove is fast enough.
+ ConcurrentSkipListMap.this.remove(l.key);
+ lastReturned = null;
+ }
+
+ }
+
+ final class ValueIterator extends Iter<V> {
+ public V next() {
+ V v = nextValue;
+ advance();
+ return v;
+ }
+ }
+
+ final class KeyIterator extends Iter<K> {
+ public K next() {
+ Node<K,V> n = next;
+ advance();
+ return n.key;
+ }
+ }
+
+ final class EntryIterator extends Iter<Map.Entry<K,V>> {
+ public Map.Entry<K,V> next() {
+ Node<K,V> n = next;
+ V v = nextValue;
+ advance();
+ return new AbstractMap.SimpleImmutableEntry<K,V>(n.key, v);
+ }
+ }
+
+ // Factory methods for iterators needed by ConcurrentSkipListSet etc
+
+ Iterator<K> keyIterator() {
+ return new KeyIterator();
+ }
+
+ Iterator<V> valueIterator() {
+ return new ValueIterator();
+ }
+
+ Iterator<Map.Entry<K,V>> entryIterator() {
+ return new EntryIterator();
+ }
+
+ /* ---------------- View Classes -------------- */
+
+ /*
+ * View classes are static, delegating to a ConcurrentNavigableMap
+ * to allow use by SubMaps, which outweighs the ugliness of
+ * needing type-tests for Iterator methods.
+ */
+
+ static final <E> List<E> toList(Collection<E> c) {
+ // Using size() here would be a pessimization.
+ List<E> list = new ArrayList<E>();
+ for (E e : c)
+ list.add(e);
+ return list;
+ }
+
+ static final class KeySet<E> extends AbstractSet<E> implements NavigableSet<E> {
+ private final ConcurrentNavigableMap<E,Object> m;
+ KeySet(ConcurrentNavigableMap<E,Object> map) { m = map; }
+ public int size() { return m.size(); }
+ public boolean isEmpty() { return m.isEmpty(); }
+ public boolean contains(Object o) { return m.containsKey(o); }
+ public boolean remove(Object o) { return m.remove(o) != null; }
+ public void clear() { m.clear(); }
+ public E lower(E e) { return m.lowerKey(e); }
+ public E floor(E e) { return m.floorKey(e); }
+ public E ceiling(E e) { return m.ceilingKey(e); }
+ public E higher(E e) { return m.higherKey(e); }
+ public Comparator<? super E> comparator() { return m.comparator(); }
+ public E first() { return m.firstKey(); }
+ public E last() { return m.lastKey(); }
+ public E pollFirst() {
+ Map.Entry<E,Object> e = m.pollFirstEntry();
+ return e == null? null : e.getKey();
+ }
+ public E pollLast() {
+ Map.Entry<E,Object> e = m.pollLastEntry();
+ return e == null? null : e.getKey();
+ }
+ public Iterator<E> iterator() {
+ if (m instanceof ConcurrentSkipListMap)
+ return ((ConcurrentSkipListMap<E,Object>)m).keyIterator();
+ else
+ return ((ConcurrentSkipListMap.SubMap<E,Object>)m).keyIterator();
+ }
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+ if (!(o instanceof Set))
+ return false;
+ Collection<?> c = (Collection<?>) o;
+ try {
+ return containsAll(c) && c.containsAll(this);
+ } catch (ClassCastException unused) {
+ return false;
+ } catch (NullPointerException unused) {
+ return false;
+ }
+ }
+ public Object[] toArray() { return toList(this).toArray(); }
+ public <T> T[] toArray(T[] a) { return toList(this).toArray(a); }
+ public Iterator<E> descendingIterator() {
+ return descendingSet().iterator();
+ }
+ public NavigableSet<E> subSet(E fromElement,
+ boolean fromInclusive,
+ E toElement,
+ boolean toInclusive) {
+ return new KeySet<E>(m.subMap(fromElement, fromInclusive,
+ toElement, toInclusive));
+ }
+ public NavigableSet<E> headSet(E toElement, boolean inclusive) {
+ return new KeySet<E>(m.headMap(toElement, inclusive));
+ }
+ public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
+ return new KeySet<E>(m.tailMap(fromElement, inclusive));
+ }
+ public NavigableSet<E> subSet(E fromElement, E toElement) {
+ return subSet(fromElement, true, toElement, false);
+ }
+ public NavigableSet<E> headSet(E toElement) {
+ return headSet(toElement, false);
+ }
+ public NavigableSet<E> tailSet(E fromElement) {
+ return tailSet(fromElement, true);
+ }
+ public NavigableSet<E> descendingSet() {
+ return new KeySet(m.descendingMap());
+ }
+ }
+
+ static final class Values<E> extends AbstractCollection<E> {
+ private final ConcurrentNavigableMap<Object, E> m;
+ Values(ConcurrentNavigableMap<Object, E> map) {
+ m = map;
+ }
+ public Iterator<E> iterator() {
+ if (m instanceof ConcurrentSkipListMap)
+ return ((ConcurrentSkipListMap<Object,E>)m).valueIterator();
+ else
+ return ((SubMap<Object,E>)m).valueIterator();
+ }
+ public boolean isEmpty() {
+ return m.isEmpty();
+ }
+ public int size() {
+ return m.size();
+ }
+ public boolean contains(Object o) {
+ return m.containsValue(o);
+ }
+ public void clear() {
+ m.clear();
+ }
+ public Object[] toArray() { return toList(this).toArray(); }
+ public <T> T[] toArray(T[] a) { return toList(this).toArray(a); }
+ }
+
+ static final class EntrySet<K1,V1> extends AbstractSet<Map.Entry<K1,V1>> {
+ private final ConcurrentNavigableMap<K1, V1> m;
+ EntrySet(ConcurrentNavigableMap<K1, V1> map) {
+ m = map;
+ }
+
+ public Iterator<Map.Entry<K1,V1>> iterator() {
+ if (m instanceof ConcurrentSkipListMap)
+ return ((ConcurrentSkipListMap<K1,V1>)m).entryIterator();
+ else
+ return ((SubMap<K1,V1>)m).entryIterator();
+ }
+
+ public boolean contains(Object o) {
+ if (!(o instanceof Map.Entry))
+ return false;
+ Map.Entry<K1,V1> e = (Map.Entry<K1,V1>)o;
+ V1 v = m.get(e.getKey());
+ return v != null && v.equals(e.getValue());
+ }
+ public boolean remove(Object o) {
+ if (!(o instanceof Map.Entry))
+ return false;
+ Map.Entry<K1,V1> e = (Map.Entry<K1,V1>)o;
+ return m.remove(e.getKey(),
+ e.getValue());
+ }
+ public boolean isEmpty() {
+ return m.isEmpty();
+ }
+ public int size() {
+ return m.size();
+ }
+ public void clear() {
+ m.clear();
+ }
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+ if (!(o instanceof Set))
+ return false;
+ Collection<?> c = (Collection<?>) o;
+ try {
+ return containsAll(c) && c.containsAll(this);
+ } catch (ClassCastException unused) {
+ return false;
+ } catch (NullPointerException unused) {
+ return false;
+ }
+ }
+ public Object[] toArray() { return toList(this).toArray(); }
+ public <T> T[] toArray(T[] a) { return toList(this).toArray(a); }
+ }
+
+ /**
+ * Submaps returned by {@link ConcurrentSkipListMap} submap operations
+ * represent a subrange of mappings of their underlying
+ * maps. Instances of this class support all methods of their
+ * underlying maps, differing in that mappings outside their range are
+ * ignored, and attempts to add mappings outside their ranges result
+ * in {@link IllegalArgumentException}. Instances of this class are
+ * constructed only using the <tt>subMap</tt>, <tt>headMap</tt>, and
+ * <tt>tailMap</tt> methods of their underlying maps.
+ *
+ * @serial include
+ */
+ static final class SubMap<K,V> extends AbstractMap<K,V>
+ implements ConcurrentNavigableMap<K,V>, Cloneable,
+ java.io.Serializable {
+ private static final long serialVersionUID = -7647078645895051609L;
+
+ /** Underlying map */
+ private final ConcurrentSkipListMap<K,V> m;
+ /** lower bound key, or null if from start */
+ private final K lo;
+ /** upper bound key, or null if to end */
+ private final K hi;
+ /** inclusion flag for lo */
+ private final boolean loInclusive;
+ /** inclusion flag for hi */
+ private final boolean hiInclusive;
+ /** direction */
+ private final boolean isDescending;
+
+ // Lazily initialized view holders
+ private transient KeySet<K> keySetView;
+ private transient Set<Map.Entry<K,V>> entrySetView;
+ private transient Collection<V> valuesView;
+
+ /**
+ * Creates a new submap, initializing all fields
+ */
+ SubMap(ConcurrentSkipListMap<K,V> map,
+ K fromKey, boolean fromInclusive,
+ K toKey, boolean toInclusive,
+ boolean isDescending) {
+ if (fromKey != null && toKey != null &&
+ map.compare(fromKey, toKey) > 0)
+ throw new IllegalArgumentException("inconsistent range");
+ this.m = map;
+ this.lo = fromKey;
+ this.hi = toKey;
+ this.loInclusive = fromInclusive;
+ this.hiInclusive = toInclusive;
+ this.isDescending = isDescending;
+ }
+
+ /* ---------------- Utilities -------------- */
+
+ private boolean tooLow(K key) {
+ if (lo != null) {
+ int c = m.compare(key, lo);
+ if (c < 0 || (c == 0 && !loInclusive))
+ return true;
+ }
+ return false;
+ }
+
+ private boolean tooHigh(K key) {
+ if (hi != null) {
+ int c = m.compare(key, hi);
+ if (c > 0 || (c == 0 && !hiInclusive))
+ return true;
+ }
+ return false;
+ }
+
+ private boolean inBounds(K key) {
+ return !tooLow(key) && !tooHigh(key);
+ }
+
+ private void checkKeyBounds(K key) throws IllegalArgumentException {
+ if (key == null)
+ throw new NullPointerException();
+ if (!inBounds(key))
+ throw new IllegalArgumentException("key out of range");
+ }
+
+ /**
+ * Returns true if node key is less than upper bound of range
+ */
+ private boolean isBeforeEnd(ConcurrentSkipListMap.Node<K,V> n) {
+ if (n == null)
+ return false;
+ if (hi == null)
+ return true;
+ K k = n.key;
+ if (k == null) // pass by markers and headers
+ return true;
+ int c = m.compare(k, hi);
+ if (c > 0 || (c == 0 && !hiInclusive))
+ return false;
+ return true;
+ }
+
+ /**
+ * Returns lowest node. This node might not be in range, so
+ * most usages need to check bounds
+ */
+ private ConcurrentSkipListMap.Node<K,V> loNode() {
+ if (lo == null)
+ return m.findFirst();
+ else if (loInclusive)
+ return m.findNear(lo, m.GT|m.EQ);
+ else
+ return m.findNear(lo, m.GT);
+ }
+
+ /**
+ * Returns highest node. This node might not be in range, so
+ * most usages need to check bounds
+ */
+ private ConcurrentSkipListMap.Node<K,V> hiNode() {
+ if (hi == null)
+ return m.findLast();
+ else if (hiInclusive)
+ return m.findNear(hi, m.LT|m.EQ);
+ else
+ return m.findNear(hi, m.LT);
+ }
+
+ /**
+ * Returns lowest absolute key (ignoring directonality)
+ */
+ private K lowestKey() {
+ ConcurrentSkipListMap.Node<K,V> n = loNode();
+ if (isBeforeEnd(n))
+ return n.key;
+ else
+ throw new NoSuchElementException();
+ }
+
+ /**
+ * Returns highest absolute key (ignoring directonality)
+ */
+ private K highestKey() {
+ ConcurrentSkipListMap.Node<K,V> n = hiNode();
+ if (n != null) {
+ K last = n.key;
+ if (inBounds(last))
+ return last;
+ }
+ throw new NoSuchElementException();
+ }
+
+ private Map.Entry<K,V> lowestEntry() {
+ for (;;) {
+ ConcurrentSkipListMap.Node<K,V> n = loNode();
+ if (!isBeforeEnd(n))
+ return null;
+ Map.Entry<K,V> e = n.createSnapshot();
+ if (e != null)
+ return e;
+ }
+ }
+
+ private Map.Entry<K,V> highestEntry() {
+ for (;;) {
+ ConcurrentSkipListMap.Node<K,V> n = hiNode();
+ if (n == null || !inBounds(n.key))
+ return null;
+ Map.Entry<K,V> e = n.createSnapshot();
+ if (e != null)
+ return e;
+ }
+ }
+
+ private Map.Entry<K,V> removeLowest() {
+ for (;;) {
+ Node<K,V> n = loNode();
+ if (n == null)
+ return null;
+ K k = n.key;
+ if (!inBounds(k))
+ return null;
+ V v = m.doRemove(k, null);
+ if (v != null)
+ return new AbstractMap.SimpleImmutableEntry<K,V>(k, v);
+ }
+ }
+
+ private Map.Entry<K,V> removeHighest() {
+ for (;;) {
+ Node<K,V> n = hiNode();
+ if (n == null)
+ return null;
+ K k = n.key;
+ if (!inBounds(k))
+ return null;
+ V v = m.doRemove(k, null);
+ if (v != null)
+ return new AbstractMap.SimpleImmutableEntry<K,V>(k, v);
+ }
+ }
+
+ /**
+ * Submap version of ConcurrentSkipListMap.getNearEntry
+ */
+ private Map.Entry<K,V> getNearEntry(K key, int rel) {
+ if (isDescending) { // adjust relation for direction
+ if ((rel & m.LT) == 0)
+ rel |= m.LT;
+ else
+ rel &= ~m.LT;
+ }
+ if (tooLow(key))
+ return ((rel & m.LT) != 0)? null : lowestEntry();
+ if (tooHigh(key))
+ return ((rel & m.LT) != 0)? highestEntry() : null;
+ for (;;) {
+ Node<K,V> n = m.findNear(key, rel);
+ if (n == null || !inBounds(n.key))
+ return null;
+ K k = n.key;
+ V v = n.getValidValue();
+ if (v != null)
+ return new AbstractMap.SimpleImmutableEntry<K,V>(k, v);
+ }
+ }
+
+ // Almost the same as getNearEntry, except for keys
+ private K getNearKey(K key, int rel) {
+ if (isDescending) { // adjust relation for direction
+ if ((rel & m.LT) == 0)
+ rel |= m.LT;
+ else
+ rel &= ~m.LT;
+ }
+ if (tooLow(key)) {
+ if ((rel & m.LT) == 0) {
+ ConcurrentSkipListMap.Node<K,V> n = loNode();
+ if (isBeforeEnd(n))
+ return n.key;
+ }
+ return null;
+ }
+ if (tooHigh(key)) {
+ if ((rel & m.LT) != 0) {
+ ConcurrentSkipListMap.Node<K,V> n = hiNode();
+ if (n != null) {
+ K last = n.key;
+ if (inBounds(last))
+ return last;
+ }
+ }
+ return null;
+ }
+ for (;;) {
+ Node<K,V> n = m.findNear(key, rel);
+ if (n == null || !inBounds(n.key))
+ return null;
+ K k = n.key;
+ V v = n.getValidValue();
+ if (v != null)
+ return k;
+ }
+ }
+
+ /* ---------------- Map API methods -------------- */
+
+ public boolean containsKey(Object key) {
+ if (key == null) throw new NullPointerException();
+ K k = (K)key;
+ return inBounds(k) && m.containsKey(k);
+ }
+
+ public V get(Object key) {
+ if (key == null) throw new NullPointerException();
+ K k = (K)key;
+ return ((!inBounds(k)) ? null : m.get(k));
+ }
+
+ public V put(K key, V value) {
+ checkKeyBounds(key);
+ return m.put(key, value);
+ }
+
+ public V remove(Object key) {
+ K k = (K)key;
+ return (!inBounds(k))? null : m.remove(k);
+ }
+
+ public int size() {
+ long count = 0;
+ for (ConcurrentSkipListMap.Node<K,V> n = loNode();
+ isBeforeEnd(n);
+ n = n.next) {
+ if (n.getValidValue() != null)
+ ++count;
+ }
+ return count >= Integer.MAX_VALUE? Integer.MAX_VALUE : (int)count;
+ }
+
+ public boolean isEmpty() {
+ return !isBeforeEnd(loNode());
+ }
+
+ public boolean containsValue(Object value) {
+ if (value == null)
+ throw new NullPointerException();
+ for (ConcurrentSkipListMap.Node<K,V> n = loNode();
+ isBeforeEnd(n);
+ n = n.next) {
+ V v = n.getValidValue();
+ if (v != null && value.equals(v))
+ return true;
+ }
+ return false;
+ }
+
+ public void clear() {
+ for (ConcurrentSkipListMap.Node<K,V> n = loNode();
+ isBeforeEnd(n);
+ n = n.next) {
+ if (n.getValidValue() != null)
+ m.remove(n.key);
+ }
+ }
+
+ /* ---------------- ConcurrentMap API methods -------------- */
+
+ public V putIfAbsent(K key, V value) {
+ checkKeyBounds(key);
+ return m.putIfAbsent(key, value);
+ }
+
+ public boolean remove(Object key, Object value) {
+ K k = (K)key;
+ return inBounds(k) && m.remove(k, value);
+ }
+
+ public boolean replace(K key, V oldValue, V newValue) {
+ checkKeyBounds(key);
+ return m.replace(key, oldValue, newValue);
+ }
+
+ public V replace(K key, V value) {
+ checkKeyBounds(key);
+ return m.replace(key, value);
+ }
+
+ /* ---------------- SortedMap API methods -------------- */
+
+ public Comparator<? super K> comparator() {
+ Comparator<? super K> cmp = m.comparator();
+ if (isDescending)
+ return Collections.reverseOrder(cmp);
+ else
+ return cmp;
+ }
+
+ /**
+ * Utility to create submaps, where given bounds override
+ * unbounded(null) ones and/or are checked against bounded ones.
+ */
+ private SubMap<K,V> newSubMap(K fromKey,
+ boolean fromInclusive,
+ K toKey,
+ boolean toInclusive) {
+ if (isDescending) { // flip senses
+ K tk = fromKey;
+ fromKey = toKey;
+ toKey = tk;
+ boolean ti = fromInclusive;
+ fromInclusive = toInclusive;
+ toInclusive = ti;
+ }
+ if (lo != null) {
+ if (fromKey == null) {
+ fromKey = lo;
+ fromInclusive = loInclusive;
+ }
+ else {
+ int c = m.compare(fromKey, lo);
+ if (c < 0 || (c == 0 && !loInclusive && fromInclusive))
+ throw new IllegalArgumentException("key out of range");
+ }
+ }
+ if (hi != null) {
+ if (toKey == null) {
+ toKey = hi;
+ toInclusive = hiInclusive;
+ }
+ else {
+ int c = m.compare(toKey, hi);
+ if (c > 0 || (c == 0 && !hiInclusive && toInclusive))
+ throw new IllegalArgumentException("key out of range");
+ }
+ }
+ return new SubMap<K,V>(m, fromKey, fromInclusive,
+ toKey, toInclusive, isDescending);
+ }
+
+ public SubMap<K,V> subMap(K fromKey,
+ boolean fromInclusive,
+ K toKey,
+ boolean toInclusive) {
+ if (fromKey == null || toKey == null)
+ throw new NullPointerException();
+ return newSubMap(fromKey, fromInclusive, toKey, toInclusive);
+ }
+
+ public SubMap<K,V> headMap(K toKey,
+ boolean inclusive) {
+ if (toKey == null)
+ throw new NullPointerException();
+ return newSubMap(null, false, toKey, inclusive);
+ }
+
+ public SubMap<K,V> tailMap(K fromKey,
+ boolean inclusive) {
+ if (fromKey == null)
+ throw new NullPointerException();
+ return newSubMap(fromKey, inclusive, null, false);
+ }
+
+ public SubMap<K,V> subMap(K fromKey, K toKey) {
+ return subMap(fromKey, true, toKey, false);
+ }
+
+ public SubMap<K,V> headMap(K toKey) {
+ return headMap(toKey, false);
+ }
+
+ public SubMap<K,V> tailMap(K fromKey) {
+ return tailMap(fromKey, true);
+ }
+
+ public SubMap<K,V> descendingMap() {
+ return new SubMap<K,V>(m, lo, loInclusive,
+ hi, hiInclusive, !isDescending);
+ }
+
+ /* ---------------- Relational methods -------------- */
+
+ public Map.Entry<K,V> ceilingEntry(K key) {
+ return getNearEntry(key, (m.GT|m.EQ));
+ }
+
+ public K ceilingKey(K key) {
+ return getNearKey(key, (m.GT|m.EQ));
+ }
+
+ public Map.Entry<K,V> lowerEntry(K key) {
+ return getNearEntry(key, (m.LT));
+ }
+
+ public K lowerKey(K key) {
+ return getNearKey(key, (m.LT));
+ }
+
+ public Map.Entry<K,V> floorEntry(K key) {
+ return getNearEntry(key, (m.LT|m.EQ));
+ }
+
+ public K floorKey(K key) {
+ return getNearKey(key, (m.LT|m.EQ));
+ }
+
+ public Map.Entry<K,V> higherEntry(K key) {
+ return getNearEntry(key, (m.GT));
+ }
+
+ public K higherKey(K key) {
+ return getNearKey(key, (m.GT));
+ }
+
+ public K firstKey() {
+ return isDescending? highestKey() : lowestKey();
+ }
+
+ public K lastKey() {
+ return isDescending? lowestKey() : highestKey();
+ }
+
+ public Map.Entry<K,V> firstEntry() {
+ return isDescending? highestEntry() : lowestEntry();
+ }
+
+ public Map.Entry<K,V> lastEntry() {
+ return isDescending? lowestEntry() : highestEntry();
+ }
+
+ public Map.Entry<K,V> pollFirstEntry() {
+ return isDescending? removeHighest() : removeLowest();
+ }
+
+ public Map.Entry<K,V> pollLastEntry() {
+ return isDescending? removeLowest() : removeHighest();
+ }
+
+ /* ---------------- Submap Views -------------- */
+
+ public NavigableSet<K> keySet() {
+ KeySet<K> ks = keySetView;
+ return (ks != null) ? ks : (keySetView = new KeySet(this));
+ }
+
+ public NavigableSet<K> navigableKeySet() {
+ KeySet<K> ks = keySetView;
+ return (ks != null) ? ks : (keySetView = new KeySet(this));
+ }
+
+ public Collection<V> values() {
+ Collection<V> vs = valuesView;
+ return (vs != null) ? vs : (valuesView = new Values(this));
+ }
+
+ public Set<Map.Entry<K,V>> entrySet() {
+ Set<Map.Entry<K,V>> es = entrySetView;
+ return (es != null) ? es : (entrySetView = new EntrySet(this));
+ }
+
+ public NavigableSet<K> descendingKeySet() {
+ return descendingMap().navigableKeySet();
+ }
+
+ Iterator<K> keyIterator() {
+ return new SubMapKeyIterator();
+ }
+
+ Iterator<V> valueIterator() {
+ return new SubMapValueIterator();
+ }
+
+ Iterator<Map.Entry<K,V>> entryIterator() {
+ return new SubMapEntryIterator();
+ }
+
+ /**
+ * Variant of main Iter class to traverse through submaps.
+ */
+ abstract class SubMapIter<T> implements Iterator<T> {
+ /** the last node returned by next() */
+ Node<K,V> lastReturned;
+ /** the next node to return from next(); */
+ Node<K,V> next;
+ /** Cache of next value field to maintain weak consistency */
+ V nextValue;
+
+ SubMapIter() {
+ for (;;) {
+ next = isDescending ? hiNode() : loNode();
+ if (next == null)
+ break;
+ Object x = next.value;
+ if (x != null && x != next) {
+ if (! inBounds(next.key))
+ next = null;
+ else
+ nextValue = (V) x;
+ break;
+ }
+ }
+ }
+
+ public final boolean hasNext() {
+ return next != null;
+ }
+
+ final void advance() {
+ if (next == null)
+ throw new NoSuchElementException();
+ lastReturned = next;
+ if (isDescending)
+ descend();
+ else
+ ascend();
+ }
+
+ private void ascend() {
+ for (;;) {
+ next = next.next;
+ if (next == null)
+ break;
+ Object x = next.value;
+ if (x != null && x != next) {
+ if (tooHigh(next.key))
+ next = null;
+ else
+ nextValue = (V) x;
+ break;
+ }
+ }
+ }
+
+ private void descend() {
+ for (;;) {
+ next = m.findNear(lastReturned.key, LT);
+ if (next == null)
+ break;
+ Object x = next.value;
+ if (x != null && x != next) {
+ if (tooLow(next.key))
+ next = null;
+ else
+ nextValue = (V) x;
+ break;
+ }
+ }
+ }
+
+ public void remove() {
+ Node<K,V> l = lastReturned;
+ if (l == null)
+ throw new IllegalStateException();
+ m.remove(l.key);
+ lastReturned = null;
+ }
+
+ }
+
+ final class SubMapValueIterator extends SubMapIter<V> {
+ public V next() {
+ V v = nextValue;
+ advance();
+ return v;
+ }
+ }
+
+ final class SubMapKeyIterator extends SubMapIter<K> {
+ public K next() {
+ Node<K,V> n = next;
+ advance();
+ return n.key;
+ }
+ }
+
+ final class SubMapEntryIterator extends SubMapIter<Map.Entry<K,V>> {
+ public Map.Entry<K,V> next() {
+ Node<K,V> n = next;
+ V v = nextValue;
+ advance();
+ return new AbstractMap.SimpleImmutableEntry<K,V>(n.key, v);
+ }
+ }
+ }
+}
diff --git a/concurrent/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java b/concurrent/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java
new file mode 100644
index 0000000..7fd1c76
--- /dev/null
+++ b/concurrent/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java
@@ -0,0 +1,456 @@
+/*
+ * 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;
+import java.util.*;
+import sun.misc.Unsafe;
+
+/**
+ * A scalable concurrent {@link NavigableSet} implementation based on
+ * a {@link ConcurrentSkipListMap}. The elements of the set are kept
+ * sorted according to their {@linkplain Comparable natural ordering},
+ * or by a {@link Comparator} provided at set creation time, depending
+ * on which constructor is used.
+ *
+ * <p>This implementation provides expected average <i>log(n)</i> time
+ * cost for the <tt>contains</tt>, <tt>add</tt>, and <tt>remove</tt>
+ * operations and their variants. Insertion, removal, and access
+ * operations safely execute concurrently by multiple threads.
+ * Iterators are <i>weakly consistent</i>, returning elements
+ * reflecting the state of the set at some point at or since the
+ * creation of the iterator. They do <em>not</em> throw {@link
+ * ConcurrentModificationException}, and may proceed concurrently with
+ * other operations. Ascending ordered views and their iterators are
+ * faster than descending ones.
+ *
+ * <p>Beware that, unlike in most collections, the <tt>size</tt>
+ * method is <em>not</em> a constant-time operation. Because of the
+ * asynchronous nature of these sets, determining the current number
+ * of elements requires a traversal of the elements. Additionally, the
+ * bulk operations <tt>addAll</tt>, <tt>removeAll</tt>,
+ * <tt>retainAll</tt>, and <tt>containsAll</tt> are <em>not</em>
+ * guaranteed to be performed atomically. For example, an iterator
+ * operating concurrently with an <tt>addAll</tt> operation might view
+ * only some of the added elements.
+ *
+ * <p>This class and its iterators implement all of the
+ * <em>optional</em> methods of the {@link Set} and {@link Iterator}
+ * interfaces. Like most other concurrent collection implementations,
+ * this class does not permit the use of <tt>null</tt> elements,
+ * because <tt>null</tt> arguments and return values cannot be reliably
+ * distinguished from the absence of elements.
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @author Doug Lea
+ * @param <E> the type of elements maintained by this set
+ * @since 1.6
+ */
+public class ConcurrentSkipListSet<E>
+ extends AbstractSet<E>
+ implements NavigableSet<E>, Cloneable, java.io.Serializable {
+
+ private static final long serialVersionUID = -2479143111061671589L;
+
+ /**
+ * The underlying map. Uses Boolean.TRUE as value for each
+ * element. This field is declared final for the sake of thread
+ * safety, which entails some ugliness in clone()
+ */
+ private final ConcurrentNavigableMap<E,Object> m;
+
+ /**
+ * Constructs a new, empty set that orders its elements according to
+ * their {@linkplain Comparable natural ordering}.
+ */
+ public ConcurrentSkipListSet() {
+ m = new ConcurrentSkipListMap<E,Object>();
+ }
+
+ /**
+ * Constructs a new, empty set that orders its elements according to
+ * the specified comparator.
+ *
+ * @param comparator the comparator that will be used to order this set.
+ * If <tt>null</tt>, the {@linkplain Comparable natural
+ * ordering} of the elements will be used.
+ */
+ public ConcurrentSkipListSet(Comparator<? super E> comparator) {
+ m = new ConcurrentSkipListMap<E,Object>(comparator);
+ }
+
+ /**
+ * Constructs a new set containing the elements in the specified
+ * collection, that orders its elements according to their
+ * {@linkplain Comparable natural ordering}.
+ *
+ * @param c The elements that will comprise the new set
+ * @throws ClassCastException if the elements in <tt>c</tt> are
+ * not {@link Comparable}, or are not mutually comparable
+ * @throws NullPointerException if the specified collection or any
+ * of its elements are null
+ */
+ public ConcurrentSkipListSet(Collection<? extends E> c) {
+ m = new ConcurrentSkipListMap<E,Object>();
+ addAll(c);
+ }
+
+ /**
+ * Constructs a new set containing the same elements and using the
+ * same ordering as the specified sorted set.
+ *
+ * @param s sorted set whose elements will comprise the new set
+ * @throws NullPointerException if the specified sorted set or any
+ * of its elements are null
+ */
+ public ConcurrentSkipListSet(SortedSet<E> s) {
+ m = new ConcurrentSkipListMap<E,Object>(s.comparator());
+ addAll(s);
+ }
+
+ /**
+ * For use by submaps
+ */
+ ConcurrentSkipListSet(ConcurrentNavigableMap<E,Object> m) {
+ this.m = m;
+ }
+
+ /**
+ * Returns a shallow copy of this <tt>ConcurrentSkipListSet</tt>
+ * instance. (The elements themselves are not cloned.)
+ *
+ * @return a shallow copy of this set
+ */
+ public ConcurrentSkipListSet<E> clone() {
+ ConcurrentSkipListSet<E> clone = null;
+ try {
+ clone = (ConcurrentSkipListSet<E>) super.clone();
+ clone.setMap(new ConcurrentSkipListMap(m));
+ } catch (CloneNotSupportedException e) {
+ throw new InternalError();
+ }
+
+ return clone;
+ }
+
+ /* ---------------- Set operations -------------- */
+
+ /**
+ * Returns the number of elements in this set. If this set
+ * contains more than <tt>Integer.MAX_VALUE</tt> elements, it
+ * returns <tt>Integer.MAX_VALUE</tt>.
+ *
+ * <p>Beware that, unlike in most collections, this method is
+ * <em>NOT</em> a constant-time operation. Because of the
+ * asynchronous nature of these sets, determining the current
+ * number of elements requires traversing them all to count them.
+ * Additionally, it is possible for the size to change during
+ * execution of this method, in which case the returned result
+ * will be inaccurate. Thus, this method is typically not very
+ * useful in concurrent applications.
+ *
+ * @return the number of elements in this set
+ */
+ public int size() {
+ return m.size();
+ }
+
+ /**
+ * Returns <tt>true</tt> if this set contains no elements.
+ * @return <tt>true</tt> if this set contains no elements
+ */
+ public boolean isEmpty() {
+ return m.isEmpty();
+ }
+
+ /**
+ * Returns <tt>true</tt> if this set contains the specified element.
+ * More formally, returns <tt>true</tt> if and only if this set
+ * contains an element <tt>e</tt> such that <tt>o.equals(e)</tt>.
+ *
+ * @param o object to be checked for containment in this set
+ * @return <tt>true</tt> if this set contains the specified element
+ * @throws ClassCastException if the specified element cannot be
+ * compared with the elements currently in this set
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean contains(Object o) {
+ return m.containsKey(o);
+ }
+
+ /**
+ * Adds the specified element to this set if it is not already present.
+ * More formally, adds the specified element <tt>e</tt> to this set if
+ * the set contains no element <tt>e2</tt> such that <tt>e.equals(e2)</tt>.
+ * If this set already contains the element, the call leaves the set
+ * unchanged and returns <tt>false</tt>.
+ *
+ * @param e element to be added to this set
+ * @return <tt>true</tt> if this set did not already contain the
+ * specified element
+ * @throws ClassCastException if <tt>e</tt> cannot be compared
+ * with the elements currently in this set
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean add(E e) {
+ return m.putIfAbsent(e, Boolean.TRUE) == null;
+ }
+
+ /**
+ * Removes the specified element from this set if it is present.
+ * More formally, removes an element <tt>e</tt> such that
+ * <tt>o.equals(e)</tt>, if this set contains such an element.
+ * Returns <tt>true</tt> if this set contained the element (or
+ * equivalently, if this set changed as a result of the call).
+ * (This set will not contain the element once the call returns.)
+ *
+ * @param o object to be removed from this set, if present
+ * @return <tt>true</tt> if this set contained the specified element
+ * @throws ClassCastException if <tt>o</tt> cannot be compared
+ * with the elements currently in this set
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean remove(Object o) {
+ return m.remove(o, Boolean.TRUE);
+ }
+
+ /**
+ * Removes all of the elements from this set.
+ */
+ public void clear() {
+ m.clear();
+ }
+
+ /**
+ * Returns an iterator over the elements in this set in ascending order.
+ *
+ * @return an iterator over the elements in this set in ascending order
+ */
+ public Iterator<E> iterator() {
+ return m.navigableKeySet().iterator();
+ }
+
+ /**
+ * Returns an iterator over the elements in this set in descending order.
+ *
+ * @return an iterator over the elements in this set in descending order
+ */
+ public Iterator<E> descendingIterator() {
+ return m.descendingKeySet().iterator();
+ }
+
+
+ /* ---------------- AbstractSet Overrides -------------- */
+
+ /**
+ * Compares the specified object with this set for equality. Returns
+ * <tt>true</tt> if the specified object is also a set, the two sets
+ * have the same size, and every member of the specified set is
+ * contained in this set (or equivalently, every member of this set is
+ * contained in the specified set). This definition ensures that the
+ * equals method works properly across different implementations of the
+ * set interface.
+ *
+ * @param o the object to be compared for equality with this set
+ * @return <tt>true</tt> if the specified object is equal to this set
+ */
+ public boolean equals(Object o) {
+ // Override AbstractSet version to avoid calling size()
+ if (o == this)
+ return true;
+ if (!(o instanceof Set))
+ return false;
+ Collection<?> c = (Collection<?>) o;
+ try {
+ return containsAll(c) && c.containsAll(this);
+ } catch (ClassCastException unused) {
+ return false;
+ } catch (NullPointerException unused) {
+ return false;
+ }
+ }
+
+ /**
+ * Removes from this set all of its elements that are contained in
+ * the specified collection. If the specified collection is also
+ * a set, this operation effectively modifies this set so that its
+ * value is the <i>asymmetric set difference</i> of the two sets.
+ *
+ * @param c collection containing elements to be removed from this set
+ * @return <tt>true</tt> if this set changed as a result of the call
+ * @throws ClassCastException if the types of one or more elements in this
+ * set are incompatible with the specified collection
+ * @throws NullPointerException if the specified collection or any
+ * of its elements are null
+ */
+ public boolean removeAll(Collection<?> c) {
+ // Override AbstractSet version to avoid unnecessary call to size()
+ boolean modified = false;
+ for (Iterator<?> i = c.iterator(); i.hasNext(); )
+ if (remove(i.next()))
+ modified = true;
+ return modified;
+ }
+
+ /* ---------------- Relational operations -------------- */
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified element is null
+ */
+ public E lower(E e) {
+ return m.lowerKey(e);
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified element is null
+ */
+ public E floor(E e) {
+ return m.floorKey(e);
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified element is null
+ */
+ public E ceiling(E e) {
+ return m.ceilingKey(e);
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified element is null
+ */
+ public E higher(E e) {
+ return m.higherKey(e);
+ }
+
+ public E pollFirst() {
+ Map.Entry<E,Object> e = m.pollFirstEntry();
+ return e == null? null : e.getKey();
+ }
+
+ public E pollLast() {
+ Map.Entry<E,Object> e = m.pollLastEntry();
+ return e == null? null : e.getKey();
+ }
+
+
+ /* ---------------- SortedSet operations -------------- */
+
+
+ public Comparator<? super E> comparator() {
+ return m.comparator();
+ }
+
+ /**
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public E first() {
+ return m.firstKey();
+ }
+
+ /**
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public E last() {
+ return m.lastKey();
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if {@code fromElement} or
+ * {@code toElement} is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public NavigableSet<E> subSet(E fromElement,
+ boolean fromInclusive,
+ E toElement,
+ boolean toInclusive) {
+ return new ConcurrentSkipListSet<E>
+ (m.subMap(fromElement, fromInclusive,
+ toElement, toInclusive));
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if {@code toElement} is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public NavigableSet<E> headSet(E toElement, boolean inclusive) {
+ return new ConcurrentSkipListSet<E>(m.headMap(toElement, inclusive));
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if {@code fromElement} is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
+ return new ConcurrentSkipListSet<E>(m.tailMap(fromElement, inclusive));
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if {@code fromElement} or
+ * {@code toElement} is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public NavigableSet<E> subSet(E fromElement, E toElement) {
+ return subSet(fromElement, true, toElement, false);
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if {@code toElement} is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public NavigableSet<E> headSet(E toElement) {
+ return headSet(toElement, false);
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if {@code fromElement} is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public NavigableSet<E> tailSet(E fromElement) {
+ return tailSet(fromElement, true);
+ }
+
+ /**
+ * Returns a reverse order view of the elements contained in this set.
+ * The descending set is backed by this set, so changes to the set are
+ * reflected in the descending set, and vice-versa.
+ *
+ * <p>The returned set has an ordering equivalent to
+ * <tt>{@link Collections#reverseOrder(Comparator) Collections.reverseOrder}(comparator())</tt>.
+ * The expression {@code s.descendingSet().descendingSet()} returns a
+ * view of {@code s} essentially equivalent to {@code s}.
+ *
+ * @return a reverse order view of this set
+ */
+ public NavigableSet<E> descendingSet() {
+ return new ConcurrentSkipListSet(m.descendingMap());
+ }
+
+ // Support for resetting map in clone
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private static final long mapOffset;
+ static {
+ try {
+ mapOffset = unsafe.objectFieldOffset
+ (ConcurrentSkipListSet.class.getDeclaredField("m"));
+ } catch (Exception ex) { throw new Error(ex); }
+ }
+ private void setMap(ConcurrentNavigableMap<E,Object> map) {
+ unsafe.putObjectVolatile(this, mapOffset, map);
+ }
+
+}
diff --git a/concurrent/src/main/java/java/util/concurrent/CopyOnWriteArrayList.java b/concurrent/src/main/java/java/util/concurrent/CopyOnWriteArrayList.java
index f0c8ac6..237c5df 100644
--- a/concurrent/src/main/java/java/util/concurrent/CopyOnWriteArrayList.java
+++ b/concurrent/src/main/java/java/util/concurrent/CopyOnWriteArrayList.java
@@ -17,8 +17,6 @@
package java.util.concurrent;
import java.util.*;
import java.util.concurrent.locks.*;
-import java.lang.reflect.Array;
-
import sun.misc.Unsafe;
// BEGIN android-note
@@ -102,7 +100,7 @@ public class CopyOnWriteArrayList<E>
Object[] elements = c.toArray();
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elements.getClass() != Object[].class)
- elements = Java6Arrays.copyOf(elements, elements.length, Object[].class);
+ elements = Arrays.copyOf(elements, elements.length, Object[].class);
setArray(elements);
}
@@ -114,7 +112,7 @@ public class CopyOnWriteArrayList<E>
* @throws NullPointerException if the specified array is null
*/
public CopyOnWriteArrayList(E[] toCopyIn) {
- setArray(Java6Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class));
+ setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class));
}
/**
@@ -288,7 +286,7 @@ public class CopyOnWriteArrayList<E>
*/
public Object[] toArray() {
Object[] elements = getArray();
- return Java6Arrays.copyOf(elements, elements.length);
+ return Arrays.copyOf(elements, elements.length);
}
/**
@@ -335,7 +333,7 @@ public class CopyOnWriteArrayList<E>
Object[] elements = getArray();
int len = elements.length;
if (a.length < len)
- return (T[]) Java6Arrays.copyOf(elements, len, a.getClass());
+ return (T[]) Arrays.copyOf(elements, len, a.getClass());
else {
System.arraycopy(elements, 0, a, 0, len);
if (a.length > len)
@@ -375,7 +373,7 @@ public class CopyOnWriteArrayList<E>
if (oldValue != element) {
int len = elements.length;
- Object[] newElements = Java6Arrays.copyOf(elements, len);
+ Object[] newElements = Arrays.copyOf(elements, len);
newElements[index] = element;
setArray(newElements);
} else {
@@ -400,7 +398,7 @@ public class CopyOnWriteArrayList<E>
try {
Object[] elements = getArray();
int len = elements.length;
- Object[] newElements = Java6Arrays.copyOf(elements, len + 1);
+ Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
@@ -428,7 +426,7 @@ public class CopyOnWriteArrayList<E>
Object[] newElements;
int numMoved = len - index;
if (numMoved == 0)
- newElements = Java6Arrays.copyOf(elements, len + 1);
+ newElements = Arrays.copyOf(elements, len + 1);
else {
newElements = new Object[len + 1];
System.arraycopy(elements, 0, newElements, 0, index);
@@ -458,7 +456,7 @@ public class CopyOnWriteArrayList<E>
E oldValue = get(elements, index);
int numMoved = len - index - 1;
if (numMoved == 0)
- setArray(Java6Arrays.copyOf(elements, len - 1));
+ setArray(Arrays.copyOf(elements, len - 1));
else {
Object[] newElements = new Object[len - 1];
System.arraycopy(elements, 0, newElements, 0, index);
@@ -544,7 +542,7 @@ public class CopyOnWriteArrayList<E>
int newlen = len - (toIndex - fromIndex);
int numMoved = len - toIndex;
if (numMoved == 0)
- setArray(Java6Arrays.copyOf(elements, newlen));
+ setArray(Arrays.copyOf(elements, newlen));
else {
Object[] newElements = new Object[newlen];
System.arraycopy(elements, 0, newElements, 0, fromIndex);
@@ -636,7 +634,7 @@ public class CopyOnWriteArrayList<E>
temp[newlen++] = element;
}
if (newlen != len) {
- setArray(Java6Arrays.copyOf(temp, newlen));
+ setArray(Arrays.copyOf(temp, newlen));
return true;
}
}
@@ -676,7 +674,7 @@ public class CopyOnWriteArrayList<E>
temp[newlen++] = element;
}
if (newlen != len) {
- setArray(Java6Arrays.copyOf(temp, newlen));
+ setArray(Arrays.copyOf(temp, newlen));
return true;
}
}
@@ -715,7 +713,7 @@ public class CopyOnWriteArrayList<E>
uniq[added++] = e;
}
if (added > 0) {
- Object[] newElements = Java6Arrays.copyOf(elements, len + added);
+ Object[] newElements = Arrays.copyOf(elements, len + added);
System.arraycopy(uniq, 0, newElements, len, added);
setArray(newElements);
}
@@ -758,7 +756,7 @@ public class CopyOnWriteArrayList<E>
try {
Object[] elements = getArray();
int len = elements.length;
- Object[] newElements = Java6Arrays.copyOf(elements, len + cs.length);
+ Object[] newElements = Arrays.copyOf(elements, len + cs.length);
System.arraycopy(cs, 0, newElements, len, cs.length);
setArray(newElements);
return true;
@@ -798,7 +796,7 @@ public class CopyOnWriteArrayList<E>
int numMoved = len - index;
Object[] newElements;
if (numMoved == 0)
- newElements = Java6Arrays.copyOf(elements, len + cs.length);
+ newElements = Arrays.copyOf(elements, len + cs.length);
else {
newElements = new Object[len + cs.length];
System.arraycopy(elements, 0, newElements, 0, index);
@@ -1314,4 +1312,5 @@ public class CopyOnWriteArrayList<E>
private void resetLock() {
unsafe.putObjectVolatile(this, lockOffset, new ReentrantLock());
}
+
}
diff --git a/concurrent/src/main/java/java/util/concurrent/Delayed.java b/concurrent/src/main/java/java/util/concurrent/Delayed.java
index af41300..b1ff4ee 100644
--- a/concurrent/src/main/java/java/util/concurrent/Delayed.java
+++ b/concurrent/src/main/java/java/util/concurrent/Delayed.java
@@ -4,19 +4,10 @@
* http://creativecommons.org/licenses/publicdomain
*/
-/*
- * Modified in Apache Harmony to comply with Java 5 signature
- * specification.
- */
-
package java.util.concurrent;
import java.util.*;
-// BEGIN android-note
-// Added generic type Delayed to Comparable to be closer to the RI.
-// END android-note
-
/**
* A mix-in style interface for marking objects that should be
* acted upon after a given delay.
diff --git a/concurrent/src/main/java/java/util/concurrent/Exchanger.java b/concurrent/src/main/java/java/util/concurrent/Exchanger.java
index f67659c..bb2193c 100644
--- a/concurrent/src/main/java/java/util/concurrent/Exchanger.java
+++ b/concurrent/src/main/java/java/util/concurrent/Exchanger.java
@@ -471,7 +471,7 @@ public class Exchanger<V> {
else if (w.isInterrupted()) // Abort on interrupt
tryCancel(node, slot);
else // Block
- LockSupport.park();
+ LockSupport.park(node);
}
}
@@ -506,7 +506,7 @@ public class Exchanger<V> {
else if (w.isInterrupted())
tryCancel(node, slot);
else
- LockSupport.parkNanos(nanos);
+ LockSupport.parkNanos(node, nanos);
}
else if (tryCancel(node, slot) && !w.isInterrupted())
return scanOnTimeout(node);
diff --git a/concurrent/src/main/java/java/util/concurrent/ExecutorCompletionService.java b/concurrent/src/main/java/java/util/concurrent/ExecutorCompletionService.java
index 02606f9..bf4a584 100644
--- a/concurrent/src/main/java/java/util/concurrent/ExecutorCompletionService.java
+++ b/concurrent/src/main/java/java/util/concurrent/ExecutorCompletionService.java
@@ -84,7 +84,7 @@ public class ExecutorCompletionService<V> implements CompletionService<V> {
* FutureTask extension to enqueue upon completion
*/
private class QueueingFuture extends FutureTask<Void> {
- QueueingFuture(FutureTask<V> task) {
+ QueueingFuture(RunnableFuture<V> task) {
super(task, null);
this.task = task;
}
@@ -92,12 +92,18 @@ public class ExecutorCompletionService<V> implements CompletionService<V> {
private final Future<V> task;
}
- private FutureTask<V> newTaskFor(Callable<V> task) {
- return new FutureTask<V>(task);
+ private RunnableFuture<V> newTaskFor(Callable<V> task) {
+ if (aes == null)
+ return new FutureTask<V>(task);
+ else
+ return aes.newTaskFor(task);
}
- private FutureTask<V> newTaskFor(Runnable task, V result) {
- return new FutureTask<V>(task, result);
+ private RunnableFuture<V> newTaskFor(Runnable task, V result) {
+ if (aes == null)
+ return new FutureTask<V>(task, result);
+ else
+ return aes.newTaskFor(task, result);
}
/**
@@ -142,14 +148,14 @@ public class ExecutorCompletionService<V> implements CompletionService<V> {
public Future<V> submit(Callable<V> task) {
if (task == null) throw new NullPointerException();
- FutureTask<V> f = newTaskFor(task);
+ RunnableFuture<V> f = newTaskFor(task);
executor.execute(new QueueingFuture(f));
return f;
}
public Future<V> submit(Runnable task, V result) {
if (task == null) throw new NullPointerException();
- FutureTask<V> f = newTaskFor(task, result);
+ RunnableFuture<V> f = newTaskFor(task, result);
executor.execute(new QueueingFuture(f));
return f;
}
diff --git a/concurrent/src/main/java/java/util/concurrent/ExecutorService.java b/concurrent/src/main/java/java/util/concurrent/ExecutorService.java
index 757f7cb..ddd77bf 100644
--- a/concurrent/src/main/java/java/util/concurrent/ExecutorService.java
+++ b/concurrent/src/main/java/java/util/concurrent/ExecutorService.java
@@ -258,7 +258,7 @@ public interface ExecutorService extends Executor {
* scheduled for execution
*/
- <T> List<Future<T>> invokeAll(Collection<Callable<T>> tasks)
+ <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException;
/**
@@ -288,7 +288,7 @@ public interface ExecutorService extends Executor {
* @throws RejectedExecutionException if any task cannot be scheduled
* for execution
*/
- <T> List<Future<T>> invokeAll(Collection<Callable<T>> tasks,
+ <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException;
@@ -303,14 +303,14 @@ public interface ExecutorService extends Executor {
* @param tasks the collection of tasks
* @return the result returned by one of the tasks
* @throws InterruptedException if interrupted while waiting
- * @throws NullPointerException if tasks or any of its elements
- * are <tt>null</tt>
+ * @throws NullPointerException if tasks or any element task
+ * subject to execution is <tt>null</tt>
* @throws IllegalArgumentException if tasks is empty
* @throws ExecutionException if no task successfully completes
* @throws RejectedExecutionException if tasks cannot be scheduled
* for execution
*/
- <T> T invokeAny(Collection<Callable<T>> tasks)
+ <T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException;
/**
@@ -327,15 +327,15 @@ public interface ExecutorService extends Executor {
* @param unit the time unit of the timeout argument
* @return the result returned by one of the tasks.
* @throws InterruptedException if interrupted while waiting
- * @throws NullPointerException if tasks, any of its elements, or
- * unit are <tt>null</tt>
+ * @throws NullPointerException if tasks, or unit, or any element
+ * task subject to execution is <tt>null</tt>
* @throws TimeoutException if the given timeout elapses before
* any task successfully completes
* @throws ExecutionException if no task successfully completes
* @throws RejectedExecutionException if tasks cannot be scheduled
* for execution
*/
- <T> T invokeAny(Collection<Callable<T>> tasks,
+ <T> T invokeAny(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
diff --git a/concurrent/src/main/java/java/util/concurrent/Executors.java b/concurrent/src/main/java/java/util/concurrent/Executors.java
index a57abe5..96f6c15 100644
--- a/concurrent/src/main/java/java/util/concurrent/Executors.java
+++ b/concurrent/src/main/java/java/util/concurrent/Executors.java
@@ -13,6 +13,7 @@ import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;
import java.security.AccessControlException;
+// import sun.security.util.SecurityConstants; // android-removed
/**
* Factory and utility methods for {@link Executor}, {@link
@@ -359,7 +360,7 @@ public class Executors {
* @return a callable object
* @throws NullPointerException if action null
*/
- public static Callable<Object> callable(final PrivilegedAction action) {
+ public static Callable<Object> callable(final PrivilegedAction<?> action) {
if (action == null)
throw new NullPointerException();
return new Callable<Object>() {
@@ -374,7 +375,7 @@ public class Executors {
* @return a callable object
* @throws NullPointerException if action null
*/
- public static Callable<Object> callable(final PrivilegedExceptionAction action) {
+ public static Callable<Object> callable(final PrivilegedExceptionAction<?> action) {
if (action == null)
throw new NullPointerException();
return new Callable<Object>() {
@@ -484,7 +485,7 @@ public class Executors {
// Calls to getContextClassLoader from this class
// never trigger a security check, but we check
// whether our callers have this permission anyways.
- sm.checkPermission(new RuntimePermission("getContextClassLoader"));
+ sm.checkPermission(new RuntimePermission("getContextClassLoader")); // android-changed
// Whether setContextClassLoader turns out to be necessary
// or not, we fail fast if permission is not available.
@@ -565,7 +566,7 @@ public class Executors {
// Calls to getContextClassLoader from this class
// never trigger a security check, but we check
// whether our callers have this permission anyways.
- sm.checkPermission(new RuntimePermission("getContextClassLoader"));
+ sm.checkPermission(new RuntimePermission("getContextClassLoader")); // android-changed
// Fail fast
sm.checkPermission(new RuntimePermission("setContextClassLoader"));
@@ -614,20 +615,20 @@ public class Executors {
public <T> Future<T> submit(Runnable task, T result) {
return e.submit(task, result);
}
- public <T> List<Future<T>> invokeAll(Collection<Callable<T>> tasks)
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException {
return e.invokeAll(tasks);
}
- public <T> List<Future<T>> invokeAll(Collection<Callable<T>> tasks,
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException {
return e.invokeAll(tasks, timeout, unit);
}
- public <T> T invokeAny(Collection<Callable<T>> tasks)
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException {
return e.invokeAny(tasks);
}
- public <T> T invokeAny(Collection<Callable<T>> tasks,
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
return e.invokeAny(tasks, timeout, unit);
diff --git a/concurrent/src/main/java/java/util/concurrent/FutureTask.java b/concurrent/src/main/java/java/util/concurrent/FutureTask.java
index 8aa9dd1..6bd13f9 100644
--- a/concurrent/src/main/java/java/util/concurrent/FutureTask.java
+++ b/concurrent/src/main/java/java/util/concurrent/FutureTask.java
@@ -30,7 +30,7 @@ import java.util.concurrent.locks.*;
* @author Doug Lea
* @param <V> The result type returned by this FutureTask's <tt>get</tt> method
*/
-public class FutureTask<V> implements Future<V>, Runnable {
+public class FutureTask<V> implements RunnableFuture<V> {
/** Synchronization control for FutureTask */
private final Sync sync;
diff --git a/concurrent/src/main/java/java/util/concurrent/Java6Arrays.java b/concurrent/src/main/java/java/util/concurrent/Java6Arrays.java
deleted file mode 100644
index 6b728be..0000000
--- a/concurrent/src/main/java/java/util/concurrent/Java6Arrays.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.util.concurrent;
-
-import java.lang.reflect.Array;
-
-/**
- * Arrays.copyOf and Arrays.copyOfRange backported from Java 6.
- */
-class Java6Arrays {
-
- static <T> T[] copyOf(T[] original, int newLength) {
- if (null == original) {
- throw new NullPointerException();
- }
- if (0 <= newLength) {
- return copyOfRange(original, 0, newLength);
- }
- throw new NegativeArraySizeException();
- }
-
- static <T, U> T[] copyOf(U[] original, int newLength,
- Class<? extends T[]> newType) {
- if (0 <= newLength) {
- return copyOfRange(original, 0, newLength, newType);
- }
- throw new NegativeArraySizeException();
- }
-
- @SuppressWarnings("unchecked")
- static <T> T[] copyOfRange(T[] original, int start, int end) {
- if (original.length >= start && 0 <= start) {
- if (start <= end) {
- int length = end - start;
- int copyLength = Math.min(length, original.length - start);
- T[] copy = (T[]) Array.newInstance(original.getClass().getComponentType(), length);
- System.arraycopy(original, start, copy, 0, copyLength);
- return copy;
- }
- throw new IllegalArgumentException();
- }
- throw new ArrayIndexOutOfBoundsException();
- }
-
- @SuppressWarnings("unchecked")
- static <T, U> T[] copyOfRange(U[] original, int start, int end,
- Class<? extends T[]> newType) {
- if (start <= end) {
- if (original.length >= start && 0 <= start) {
- int length = end - start;
- int copyLength = Math.min(length, original.length - start);
- T[] copy = (T[]) Array.newInstance(newType.getComponentType(),
- length);
- System.arraycopy(original, start, copy, 0, copyLength);
- return copy;
- }
- throw new ArrayIndexOutOfBoundsException();
- }
- throw new IllegalArgumentException();
- }
-
-}
diff --git a/concurrent/src/main/java/java/util/concurrent/LinkedBlockingDeque.java b/concurrent/src/main/java/java/util/concurrent/LinkedBlockingDeque.java
new file mode 100644
index 0000000..196ea76
--- /dev/null
+++ b/concurrent/src/main/java/java/util/concurrent/LinkedBlockingDeque.java
@@ -0,0 +1,1137 @@
+/*
+ * 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;
+
+import java.util.AbstractQueue;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * An optionally-bounded {@linkplain BlockingDeque blocking deque} based on
+ * linked nodes.
+ *
+ * <p> The optional capacity bound constructor argument serves as a
+ * way to prevent excessive expansion. The capacity, if unspecified,
+ * is equal to {@link Integer#MAX_VALUE}. Linked nodes are
+ * dynamically created upon each insertion unless this would bring the
+ * deque above capacity.
+ *
+ * <p>Most operations run in constant time (ignoring time spent
+ * blocking). Exceptions include {@link #remove(Object) remove},
+ * {@link #removeFirstOccurrence removeFirstOccurrence}, {@link
+ * #removeLastOccurrence removeLastOccurrence}, {@link #contains
+ * contains}, {@link #iterator iterator.remove()}, and the bulk
+ * operations, all of which run in linear time.
+ *
+ * <p>This class and its iterator implement all of the
+ * <em>optional</em> methods of the {@link Collection} and {@link
+ * Iterator} interfaces.
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @since 1.6
+ * @author Doug Lea
+ * @param <E> the type of elements held in this collection
+ */
+public class LinkedBlockingDeque<E>
+ extends AbstractQueue<E>
+ implements BlockingDeque<E>, java.io.Serializable {
+
+ /*
+ * Implemented as a simple doubly-linked list protected by a
+ * single lock and using conditions to manage blocking.
+ *
+ * To implement weakly consistent iterators, it appears we need to
+ * keep all Nodes GC-reachable from a predecessor dequeued Node.
+ * That would cause two problems:
+ * - allow a rogue Iterator to cause unbounded memory retention
+ * - cause cross-generational linking of old Nodes to new Nodes if
+ * a Node was tenured while live, which generational GCs have a
+ * hard time dealing with, causing repeated major collections.
+ * However, only non-deleted Nodes need to be reachable from
+ * dequeued Nodes, and reachability does not necessarily have to
+ * be of the kind understood by the GC. We use the trick of
+ * linking a Node that has just been dequeued to itself. Such a
+ * self-link implicitly means to jump to "first" (for next links)
+ * or "last" (for prev links).
+ */
+
+ /*
+ * We have "diamond" multiple interface/abstract class inheritance
+ * here, and that introduces ambiguities. Often we want the
+ * BlockingDeque javadoc combined with the AbstractQueue
+ * implementation, so a lot of method specs are duplicated here.
+ */
+
+ private static final long serialVersionUID = -387911632671998426L;
+
+ /** Doubly-linked list node class */
+ static final class Node<E> {
+ /**
+ * The item, or null if this node has been removed.
+ */
+ E item;
+
+ /**
+ * One of:
+ * - the real predecessor Node
+ * - this Node, meaning the predecessor is tail
+ * - null, meaning there is no predecessor
+ */
+ Node<E> prev;
+
+ /**
+ * One of:
+ * - the real successor Node
+ * - this Node, meaning the successor is head
+ * - null, meaning there is no successor
+ */
+ Node<E> next;
+
+ Node(E x, Node<E> p, Node<E> n) {
+ item = x;
+ prev = p;
+ next = n;
+ }
+ }
+
+ /**
+ * Pointer to first node.
+ * Invariant: (first == null && last == null) ||
+ * (first.prev == null && first.item != null)
+ */
+ transient Node<E> first;
+
+ /**
+ * Pointer to last node.
+ * Invariant: (first == null && last == null) ||
+ * (last.next == null && last.item != null)
+ */
+ transient Node<E> last;
+
+ /** Number of items in the deque */
+ private transient int count;
+
+ /** Maximum number of items in the deque */
+ private final int capacity;
+
+ /** Main lock guarding all access */
+ final ReentrantLock lock = new ReentrantLock();
+
+ /** Condition for waiting takes */
+ private final Condition notEmpty = lock.newCondition();
+
+ /** Condition for waiting puts */
+ private final Condition notFull = lock.newCondition();
+
+ /**
+ * Creates a {@code LinkedBlockingDeque} with a capacity of
+ * {@link Integer#MAX_VALUE}.
+ */
+ public LinkedBlockingDeque() {
+ this(Integer.MAX_VALUE);
+ }
+
+ /**
+ * Creates a {@code LinkedBlockingDeque} with the given (fixed) capacity.
+ *
+ * @param capacity the capacity of this deque
+ * @throws IllegalArgumentException if {@code capacity} is less than 1
+ */
+ public LinkedBlockingDeque(int capacity) {
+ if (capacity <= 0) throw new IllegalArgumentException();
+ this.capacity = capacity;
+ }
+
+ /**
+ * Creates a {@code LinkedBlockingDeque} with a capacity of
+ * {@link Integer#MAX_VALUE}, initially containing the elements of
+ * the given collection, added in traversal order of the
+ * collection's iterator.
+ *
+ * @param c the collection of elements to initially contain
+ * @throws NullPointerException if the specified collection or any
+ * of its elements are null
+ */
+ public LinkedBlockingDeque(Collection<? extends E> c) {
+ this(Integer.MAX_VALUE);
+ final ReentrantLock lock = this.lock;
+ lock.lock(); // Never contended, but necessary for visibility
+ try {
+ for (E e : c) {
+ if (e == null)
+ throw new NullPointerException();
+ if (!linkLast(e))
+ throw new IllegalStateException("Deque full");
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+
+ // Basic linking and unlinking operations, called only while holding lock
+
+ /**
+ * Links e as first element, or returns false if full.
+ */
+ private boolean linkFirst(E e) {
+ // assert lock.isHeldByCurrentThread();
+ if (count >= capacity)
+ return false;
+ Node<E> f = first;
+ Node<E> x = new Node<E>(e, null, f);
+ first = x;
+ if (last == null)
+ last = x;
+ else
+ f.prev = x;
+ ++count;
+ notEmpty.signal();
+ return true;
+ }
+
+ /**
+ * Links e as last element, or returns false if full.
+ */
+ private boolean linkLast(E e) {
+ // assert lock.isHeldByCurrentThread();
+ if (count >= capacity)
+ return false;
+ Node<E> l = last;
+ Node<E> x = new Node<E>(e, l, null);
+ last = x;
+ if (first == null)
+ first = x;
+ else
+ l.next = x;
+ ++count;
+ notEmpty.signal();
+ return true;
+ }
+
+ /**
+ * Removes and returns first element, or null if empty.
+ */
+ private E unlinkFirst() {
+ // assert lock.isHeldByCurrentThread();
+ Node<E> f = first;
+ if (f == null)
+ return null;
+ Node<E> n = f.next;
+ E item = f.item;
+ f.item = null;
+ f.next = f; // help GC
+ first = n;
+ if (n == null)
+ last = null;
+ else
+ n.prev = null;
+ --count;
+ notFull.signal();
+ return item;
+ }
+
+ /**
+ * Removes and returns last element, or null if empty.
+ */
+ private E unlinkLast() {
+ // assert lock.isHeldByCurrentThread();
+ Node<E> l = last;
+ if (l == null)
+ return null;
+ Node<E> p = l.prev;
+ E item = l.item;
+ l.item = null;
+ l.prev = l; // help GC
+ last = p;
+ if (p == null)
+ first = null;
+ else
+ p.next = null;
+ --count;
+ notFull.signal();
+ return item;
+ }
+
+ /**
+ * Unlinks x.
+ */
+ void unlink(Node<E> x) {
+ // assert lock.isHeldByCurrentThread();
+ Node<E> p = x.prev;
+ Node<E> n = x.next;
+ if (p == null) {
+ unlinkFirst();
+ } else if (n == null) {
+ unlinkLast();
+ } else {
+ p.next = n;
+ n.prev = p;
+ x.item = null;
+ // Don't mess with x's links. They may still be in use by
+ // an iterator.
+ --count;
+ notFull.signal();
+ }
+ }
+
+ // BlockingDeque methods
+
+ /**
+ * @throws IllegalStateException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public void addFirst(E e) {
+ if (!offerFirst(e))
+ throw new IllegalStateException("Deque full");
+ }
+
+ /**
+ * @throws IllegalStateException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public void addLast(E e) {
+ if (!offerLast(e))
+ throw new IllegalStateException("Deque full");
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean offerFirst(E e) {
+ if (e == null) throw new NullPointerException();
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return linkFirst(e);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean offerLast(E e) {
+ if (e == null) throw new NullPointerException();
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return linkLast(e);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ * @throws InterruptedException {@inheritDoc}
+ */
+ public void putFirst(E e) throws InterruptedException {
+ if (e == null) throw new NullPointerException();
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ while (!linkFirst(e))
+ notFull.await();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ * @throws InterruptedException {@inheritDoc}
+ */
+ public void putLast(E e) throws InterruptedException {
+ if (e == null) throw new NullPointerException();
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ while (!linkLast(e))
+ notFull.await();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ * @throws InterruptedException {@inheritDoc}
+ */
+ public boolean offerFirst(E e, long timeout, TimeUnit unit)
+ throws InterruptedException {
+ if (e == null) throw new NullPointerException();
+ long nanos = unit.toNanos(timeout);
+ final ReentrantLock lock = this.lock;
+ lock.lockInterruptibly();
+ try {
+ while (!linkFirst(e)) {
+ if (nanos <= 0)
+ return false;
+ nanos = notFull.awaitNanos(nanos);
+ }
+ return true;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ * @throws InterruptedException {@inheritDoc}
+ */
+ public boolean offerLast(E e, long timeout, TimeUnit unit)
+ throws InterruptedException {
+ if (e == null) throw new NullPointerException();
+ long nanos = unit.toNanos(timeout);
+ final ReentrantLock lock = this.lock;
+ lock.lockInterruptibly();
+ try {
+ while (!linkLast(e)) {
+ if (nanos <= 0)
+ return false;
+ nanos = notFull.awaitNanos(nanos);
+ }
+ return true;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public E removeFirst() {
+ E x = pollFirst();
+ if (x == null) throw new NoSuchElementException();
+ return x;
+ }
+
+ /**
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public E removeLast() {
+ E x = pollLast();
+ if (x == null) throw new NoSuchElementException();
+ return x;
+ }
+
+ public E pollFirst() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return unlinkFirst();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E pollLast() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return unlinkLast();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E takeFirst() throws InterruptedException {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ E x;
+ while ( (x = unlinkFirst()) == null)
+ notEmpty.await();
+ return x;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E takeLast() throws InterruptedException {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ E x;
+ while ( (x = unlinkLast()) == null)
+ notEmpty.await();
+ return x;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E pollFirst(long timeout, TimeUnit unit)
+ throws InterruptedException {
+ long nanos = unit.toNanos(timeout);
+ final ReentrantLock lock = this.lock;
+ lock.lockInterruptibly();
+ try {
+ E x;
+ while ( (x = unlinkFirst()) == null) {
+ if (nanos <= 0)
+ return null;
+ nanos = notEmpty.awaitNanos(nanos);
+ }
+ return x;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E pollLast(long timeout, TimeUnit unit)
+ throws InterruptedException {
+ long nanos = unit.toNanos(timeout);
+ final ReentrantLock lock = this.lock;
+ lock.lockInterruptibly();
+ try {
+ E x;
+ while ( (x = unlinkLast()) == null) {
+ if (nanos <= 0)
+ return null;
+ nanos = notEmpty.awaitNanos(nanos);
+ }
+ return x;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public E getFirst() {
+ E x = peekFirst();
+ if (x == null) throw new NoSuchElementException();
+ return x;
+ }
+
+ /**
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public E getLast() {
+ E x = peekLast();
+ if (x == null) throw new NoSuchElementException();
+ return x;
+ }
+
+ public E peekFirst() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return (first == null) ? null : first.item;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E peekLast() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return (last == null) ? null : last.item;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public boolean removeFirstOccurrence(Object o) {
+ if (o == null) return false;
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ for (Node<E> p = first; p != null; p = p.next) {
+ if (o.equals(p.item)) {
+ unlink(p);
+ return true;
+ }
+ }
+ return false;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public boolean removeLastOccurrence(Object o) {
+ if (o == null) return false;
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ for (Node<E> p = last; p != null; p = p.prev) {
+ if (o.equals(p.item)) {
+ unlink(p);
+ return true;
+ }
+ }
+ return false;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ // BlockingQueue methods
+
+ /**
+ * Inserts the specified element at the end of this deque unless it would
+ * violate capacity restrictions. When using a capacity-restricted deque,
+ * it is generally preferable to use method {@link #offer(Object) offer}.
+ *
+ * <p>This method is equivalent to {@link #addLast}.
+ *
+ * @throws IllegalStateException if the element cannot be added at this
+ * time due to capacity restrictions
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean add(E e) {
+ addLast(e);
+ return true;
+ }
+
+ /**
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean offer(E e) {
+ return offerLast(e);
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ * @throws InterruptedException {@inheritDoc}
+ */
+ public void put(E e) throws InterruptedException {
+ putLast(e);
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ * @throws InterruptedException {@inheritDoc}
+ */
+ public boolean offer(E e, long timeout, TimeUnit unit)
+ throws InterruptedException {
+ return offerLast(e, timeout, unit);
+ }
+
+ /**
+ * Retrieves and removes the head of the queue represented by this deque.
+ * This method differs from {@link #poll poll} only in that it throws an
+ * exception if this deque is empty.
+ *
+ * <p>This method is equivalent to {@link #removeFirst() removeFirst}.
+ *
+ * @return the head of the queue represented by this deque
+ * @throws NoSuchElementException if this deque is empty
+ */
+ public E remove() {
+ return removeFirst();
+ }
+
+ public E poll() {
+ return pollFirst();
+ }
+
+ public E take() throws InterruptedException {
+ return takeFirst();
+ }
+
+ public E poll(long timeout, TimeUnit unit) throws InterruptedException {
+ return pollFirst(timeout, unit);
+ }
+
+ /**
+ * Retrieves, but does not remove, the head of the queue represented by
+ * this deque. This method differs from {@link #peek peek} only in that
+ * it throws an exception if this deque is empty.
+ *
+ * <p>This method is equivalent to {@link #getFirst() getFirst}.
+ *
+ * @return the head of the queue represented by this deque
+ * @throws NoSuchElementException if this deque is empty
+ */
+ public E element() {
+ return getFirst();
+ }
+
+ public E peek() {
+ return peekFirst();
+ }
+
+ /**
+ * Returns the number of additional elements that this deque can ideally
+ * (in the absence of memory or resource constraints) accept without
+ * blocking. This is always equal to the initial capacity of this deque
+ * less the current {@code size} of this deque.
+ *
+ * <p>Note that you <em>cannot</em> always tell if an attempt to insert
+ * an element will succeed by inspecting {@code remainingCapacity}
+ * because it may be the case that another thread is about to
+ * insert or remove an element.
+ */
+ public int remainingCapacity() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return capacity - count;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws UnsupportedOperationException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public int drainTo(Collection<? super E> c) {
+ return drainTo(c, Integer.MAX_VALUE);
+ }
+
+ /**
+ * @throws UnsupportedOperationException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public int drainTo(Collection<? super E> c, int maxElements) {
+ if (c == null)
+ throw new NullPointerException();
+ if (c == this)
+ throw new IllegalArgumentException();
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ int n = Math.min(maxElements, count);
+ for (int i = 0; i < n; i++) {
+ c.add(first.item); // In this order, in case add() throws.
+ unlinkFirst();
+ }
+ return n;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ // Stack methods
+
+ /**
+ * @throws IllegalStateException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public void push(E e) {
+ addFirst(e);
+ }
+
+ /**
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public E pop() {
+ return removeFirst();
+ }
+
+ // Collection methods
+
+ /**
+ * Removes the first occurrence of the specified element from this deque.
+ * If the deque does not contain the element, it is unchanged.
+ * More formally, removes the first element {@code e} such that
+ * {@code o.equals(e)} (if such an element exists).
+ * Returns {@code true} if this deque contained the specified element
+ * (or equivalently, if this deque changed as a result of the call).
+ *
+ * <p>This method is equivalent to
+ * {@link #removeFirstOccurrence(Object) removeFirstOccurrence}.
+ *
+ * @param o element to be removed from this deque, if present
+ * @return {@code true} if this deque changed as a result of the call
+ */
+ public boolean remove(Object o) {
+ return removeFirstOccurrence(o);
+ }
+
+ /**
+ * Returns the number of elements in this deque.
+ *
+ * @return the number of elements in this deque
+ */
+ public int size() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return count;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns {@code true} if this deque contains the specified element.
+ * More formally, returns {@code true} if and only if this deque contains
+ * at least one element {@code e} such that {@code o.equals(e)}.
+ *
+ * @param o object to be checked for containment in this deque
+ * @return {@code true} if this deque contains the specified element
+ */
+ public boolean contains(Object o) {
+ if (o == null) return false;
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ for (Node<E> p = first; p != null; p = p.next)
+ if (o.equals(p.item))
+ return true;
+ return false;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /*
+ * TODO: Add support for more efficient bulk operations.
+ *
+ * We don't want to acquire the lock for every iteration, but we
+ * also want other threads a chance to interact with the
+ * collection, especially when count is close to capacity.
+ */
+
+// /**
+// * Adds all of the elements in the specified collection to this
+// * queue. Attempts to addAll of a queue to itself result in
+// * {@code IllegalArgumentException}. Further, the behavior of
+// * this operation is undefined if the specified collection is
+// * modified while the operation is in progress.
+// *
+// * @param c collection containing elements to be added to this queue
+// * @return {@code true} if this queue changed as a result of the call
+// * @throws ClassCastException {@inheritDoc}
+// * @throws NullPointerException {@inheritDoc}
+// * @throws IllegalArgumentException {@inheritDoc}
+// * @throws IllegalStateException {@inheritDoc}
+// * @see #add(Object)
+// */
+// public boolean addAll(Collection<? extends E> c) {
+// if (c == null)
+// throw new NullPointerException();
+// if (c == this)
+// throw new IllegalArgumentException();
+// final ReentrantLock lock = this.lock;
+// lock.lock();
+// try {
+// boolean modified = false;
+// for (E e : c)
+// if (linkLast(e))
+// modified = true;
+// return modified;
+// } finally {
+// lock.unlock();
+// }
+// }
+
+ /**
+ * Returns an array containing all of the elements in this deque, in
+ * proper sequence (from first to last element).
+ *
+ * <p>The returned array will be "safe" in that no references to it are
+ * maintained by this deque. (In other words, this method must allocate
+ * a new array). The caller is thus free to modify the returned array.
+ *
+ * <p>This method acts as bridge between array-based and collection-based
+ * APIs.
+ *
+ * @return an array containing all of the elements in this deque
+ */
+ @SuppressWarnings("unchecked")
+ public Object[] toArray() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ Object[] a = new Object[count];
+ int k = 0;
+ for (Node<E> p = first; p != null; p = p.next)
+ a[k++] = p.item;
+ return a;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns an array containing all of the elements in this deque, in
+ * proper sequence; the runtime type of the returned array is that of
+ * the specified array. If the deque fits in the specified array, it
+ * is returned therein. Otherwise, a new array is allocated with the
+ * runtime type of the specified array and the size of this deque.
+ *
+ * <p>If this deque fits in the specified array with room to spare
+ * (i.e., the array has more elements than this deque), the element in
+ * the array immediately following the end of the deque is set to
+ * {@code null}.
+ *
+ * <p>Like the {@link #toArray()} method, this method acts as bridge between
+ * array-based and collection-based APIs. Further, this method allows
+ * precise control over the runtime type of the output array, and may,
+ * under certain circumstances, be used to save allocation costs.
+ *
+ * <p>Suppose {@code x} is a deque known to contain only strings.
+ * The following code can be used to dump the deque into a newly
+ * allocated array of {@code String}:
+ *
+ * <pre>
+ * String[] y = x.toArray(new String[0]);</pre>
+ *
+ * Note that {@code toArray(new Object[0])} is identical in function to
+ * {@code toArray()}.
+ *
+ * @param a the array into which the elements of the deque are to
+ * be stored, if it is big enough; otherwise, a new array of the
+ * same runtime type is allocated for this purpose
+ * @return an array containing all of the elements in this deque
+ * @throws ArrayStoreException if the runtime type of the specified array
+ * is not a supertype of the runtime type of every element in
+ * this deque
+ * @throws NullPointerException if the specified array is null
+ */
+ @SuppressWarnings("unchecked")
+ public <T> T[] toArray(T[] a) {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ if (a.length < count)
+ a = (T[])java.lang.reflect.Array.newInstance
+ (a.getClass().getComponentType(), count);
+
+ int k = 0;
+ for (Node<E> p = first; p != null; p = p.next)
+ a[k++] = (T)p.item;
+ if (a.length > k)
+ a[k] = null;
+ return a;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public String toString() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return super.toString();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Atomically removes all of the elements from this deque.
+ * The deque will be empty after this call returns.
+ */
+ public void clear() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ for (Node<E> f = first; f != null; ) {
+ f.item = null;
+ Node<E> n = f.next;
+ f.prev = null;
+ f.next = null;
+ f = n;
+ }
+ first = last = null;
+ count = 0;
+ notFull.signalAll();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns an iterator over the elements in this deque in proper sequence.
+ * The elements will be returned in order from first (head) to last (tail).
+ * The returned {@code Iterator} is a "weakly consistent" iterator that
+ * will never throw {@link java.util.ConcurrentModificationException
+ * ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ *
+ * @return an iterator over the elements in this deque in proper sequence
+ */
+ public Iterator<E> iterator() {
+ return new Itr();
+ }
+
+ /**
+ * Returns an iterator over the elements in this deque in reverse
+ * sequential order. The elements will be returned in order from
+ * last (tail) to first (head).
+ * The returned {@code Iterator} is a "weakly consistent" iterator that
+ * will never throw {@link java.util.ConcurrentModificationException
+ * ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ */
+ public Iterator<E> descendingIterator() {
+ return new DescendingItr();
+ }
+
+ /**
+ * Base class for Iterators for LinkedBlockingDeque
+ */
+ private abstract class AbstractItr implements Iterator<E> {
+ /**
+ * The next node to return in next()
+ */
+ Node<E> next;
+
+ /**
+ * nextItem holds on to item fields because once we claim that
+ * an element exists in hasNext(), we must return item read
+ * under lock (in advance()) even if it was in the process of
+ * being removed when hasNext() was called.
+ */
+ E nextItem;
+
+ /**
+ * Node returned by most recent call to next. Needed by remove.
+ * Reset to null if this element is deleted by a call to remove.
+ */
+ private Node<E> lastRet;
+
+ abstract Node<E> firstNode();
+ abstract Node<E> nextNode(Node<E> n);
+
+ AbstractItr() {
+ // set to initial position
+ final ReentrantLock lock = LinkedBlockingDeque.this.lock;
+ lock.lock();
+ try {
+ next = firstNode();
+ nextItem = (next == null) ? null : next.item;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Advances next.
+ */
+ void advance() {
+ final ReentrantLock lock = LinkedBlockingDeque.this.lock;
+ lock.lock();
+ try {
+ // assert next != null;
+ Node<E> s = nextNode(next);
+ if (s == next) {
+ next = firstNode();
+ } else {
+ // Skip over removed nodes.
+ // May be necessary if multiple interior Nodes are removed.
+ while (s != null && s.item == null)
+ s = nextNode(s);
+ next = s;
+ }
+ nextItem = (next == null) ? null : next.item;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public boolean hasNext() {
+ return next != null;
+ }
+
+ public E next() {
+ if (next == null)
+ throw new NoSuchElementException();
+ lastRet = next;
+ E x = nextItem;
+ advance();
+ return x;
+ }
+
+ public void remove() {
+ Node<E> n = lastRet;
+ if (n == null)
+ throw new IllegalStateException();
+ lastRet = null;
+ final ReentrantLock lock = LinkedBlockingDeque.this.lock;
+ lock.lock();
+ try {
+ if (n.item != null)
+ unlink(n);
+ } finally {
+ lock.unlock();
+ }
+ }
+ }
+
+ /** Forward iterator */
+ private class Itr extends AbstractItr {
+ Node<E> firstNode() { return first; }
+ Node<E> nextNode(Node<E> n) { return n.next; }
+ }
+
+ /** Descending iterator */
+ private class DescendingItr extends AbstractItr {
+ Node<E> firstNode() { return last; }
+ Node<E> nextNode(Node<E> n) { return n.prev; }
+ }
+
+ /**
+ * Save the state of this deque to a stream (that is, serialize it).
+ *
+ * @serialData The capacity (int), followed by elements (each an
+ * {@code Object}) in the proper order, followed by a null
+ * @param s the stream
+ */
+ private void writeObject(java.io.ObjectOutputStream s)
+ throws java.io.IOException {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ // Write out capacity and any hidden stuff
+ s.defaultWriteObject();
+ // Write out all elements in the proper order.
+ for (Node<E> p = first; p != null; p = p.next)
+ s.writeObject(p.item);
+ // Use trailing null as sentinel
+ s.writeObject(null);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Reconstitute this deque from a stream (that is,
+ * deserialize it).
+ * @param s the stream
+ */
+ private void readObject(java.io.ObjectInputStream s)
+ throws java.io.IOException, ClassNotFoundException {
+ s.defaultReadObject();
+ count = 0;
+ first = null;
+ last = null;
+ // Read in all elements and place in queue
+ for (;;) {
+ @SuppressWarnings("unchecked")
+ E item = (E)s.readObject();
+ if (item == null)
+ break;
+ add(item);
+ }
+ }
+
+}
diff --git a/concurrent/src/main/java/java/util/concurrent/LinkedBlockingQueue.java b/concurrent/src/main/java/java/util/concurrent/LinkedBlockingQueue.java
index e06f7bd..1a8e412 100644
--- a/concurrent/src/main/java/java/util/concurrent/LinkedBlockingQueue.java
+++ b/concurrent/src/main/java/java/util/concurrent/LinkedBlockingQueue.java
@@ -5,14 +5,19 @@
*/
package java.util.concurrent;
-import java.util.concurrent.atomic.*;
-import java.util.concurrent.locks.*;
-import java.util.*;
// BEGIN android-note
// removed link to collections framework docs
// END android-note
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.AbstractQueue;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
/**
* An optionally-bounded {@linkplain BlockingQueue blocking queue} based on
* linked nodes.
@@ -57,15 +62,43 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
* items have been entered since the signal. And symmetrically for
* takes signalling puts. Operations such as remove(Object) and
* iterators acquire both locks.
+ *
+ * Visibility between writers and readers is provided as follows:
+ *
+ * Whenever an element is enqueued, the putLock is acquired and
+ * count updated. A subsequent reader guarantees visibility to the
+ * enqueued Node by either acquiring the putLock (via fullyLock)
+ * or by acquiring the takeLock, and then reading n = count.get();
+ * this gives visibility to the first n items.
+ *
+ * To implement weakly consistent iterators, it appears we need to
+ * keep all Nodes GC-reachable from a predecessor dequeued Node.
+ * That would cause two problems:
+ * - allow a rogue Iterator to cause unbounded memory retention
+ * - cause cross-generational linking of old Nodes to new Nodes if
+ * a Node was tenured while live, which generational GCs have a
+ * hard time dealing with, causing repeated major collections.
+ * However, only non-deleted Nodes need to be reachable from
+ * dequeued Nodes, and reachability does not necessarily have to
+ * be of the kind understood by the GC. We use the trick of
+ * linking a Node that has just been dequeued to itself. Such a
+ * self-link implicitly means to advance to head.next.
*/
/**
* Linked list node class
*/
static class Node<E> {
- /** The item, volatile to ensure barrier separating write and read */
- volatile E item;
+ E item;
+
+ /**
+ * One of:
+ * - the real successor Node
+ * - this Node, meaning the successor is head.next
+ * - null, meaning there is no successor (this is the last node)
+ */
Node<E> next;
+
Node(E x) { item = x; }
}
@@ -75,10 +108,16 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
/** Current number of elements */
private final AtomicInteger count = new AtomicInteger(0);
- /** Head of linked list */
+ /**
+ * Head of linked list.
+ * Invariant: head.item == null
+ */
private transient Node<E> head;
- /** Tail of linked list */
+ /**
+ * Tail of linked list.
+ * Invariant: last.next == null
+ */
private transient Node<E> last;
/** Lock held by take, poll, etc */
@@ -122,20 +161,26 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
/**
* Creates a node and links it at end of queue.
+ *
* @param x the item
*/
- private void insert(E x) {
+ private void enqueue(E x) {
+ // assert putLock.isHeldByCurrentThread();
+ // assert last.next == null;
last = last.next = new Node<E>(x);
}
/**
- * Removes a node from head of queue,
+ * Removes a node from head of queue.
+ *
* @return the node
*/
- private E extract() {
+ private E dequeue() {
+ // assert takeLock.isHeldByCurrentThread();
+ // assert head.item == null;
Node<E> h = head;
Node<E> first = h.next;
- h.next = null; // help GC
+ h.next = h; // help GC
head = first;
E x = first.item;
first.item = null;
@@ -145,7 +190,7 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
/**
* Lock to prevent both puts and takes.
*/
- private void fullyLock() {
+ void fullyLock() {
putLock.lock();
takeLock.lock();
}
@@ -153,14 +198,21 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
/**
* Unlock to allow both puts and takes.
*/
- private void fullyUnlock() {
+ void fullyUnlock() {
takeLock.unlock();
putLock.unlock();
}
+// /**
+// * Tells whether both locks are held by current thread.
+// */
+// boolean isFullyLocked() {
+// return (putLock.isHeldByCurrentThread() &&
+// takeLock.isHeldByCurrentThread());
+// }
/**
- * Creates a <tt>LinkedBlockingQueue</tt> with a capacity of
+ * Creates a {@code LinkedBlockingQueue} with a capacity of
* {@link Integer#MAX_VALUE}.
*/
public LinkedBlockingQueue() {
@@ -168,10 +220,10 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
}
/**
- * Creates a <tt>LinkedBlockingQueue</tt> with the given (fixed) capacity.
+ * Creates a {@code LinkedBlockingQueue} with the given (fixed) capacity.
*
* @param capacity the capacity of this queue
- * @throws IllegalArgumentException if <tt>capacity</tt> is not greater
+ * @throws IllegalArgumentException if {@code capacity} is not greater
* than zero
*/
public LinkedBlockingQueue(int capacity) {
@@ -181,7 +233,7 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
}
/**
- * Creates a <tt>LinkedBlockingQueue</tt> with a capacity of
+ * Creates a {@code LinkedBlockingQueue} with a capacity of
* {@link Integer#MAX_VALUE}, initially containing the elements of the
* given collection,
* added in traversal order of the collection's iterator.
@@ -192,8 +244,22 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
*/
public LinkedBlockingQueue(Collection<? extends E> c) {
this(Integer.MAX_VALUE);
- for (E e : c)
- add(e);
+ final ReentrantLock putLock = this.putLock;
+ putLock.lock(); // Never contended, but necessary for visibility
+ try {
+ int n = 0;
+ for (E e : c) {
+ if (e == null)
+ throw new NullPointerException();
+ if (n == capacity)
+ throw new IllegalStateException("Queue full");
+ enqueue(e);
+ ++n;
+ }
+ count.set(n);
+ } finally {
+ putLock.unlock();
+ }
}
@@ -214,10 +280,10 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
* Returns the number of additional elements that this queue can ideally
* (in the absence of memory or resource constraints) accept without
* blocking. This is always equal to the initial capacity of this queue
- * less the current <tt>size</tt> of this queue.
+ * less the current {@code size} of this queue.
*
* <p>Note that you <em>cannot</em> always tell if an attempt to insert
- * an element will succeed by inspecting <tt>remainingCapacity</tt>
+ * an element will succeed by inspecting {@code remainingCapacity}
* because it may be the case that another thread is about to
* insert or remove an element.
*/
@@ -234,8 +300,8 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
*/
public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
- // Note: convention in all put/take/etc is to preset
- // local var holding count negative to indicate failure unless set.
+ // Note: convention in all put/take/etc is to preset local var
+ // holding count negative to indicate failure unless set.
int c = -1;
final ReentrantLock putLock = this.putLock;
final AtomicInteger count = this.count;
@@ -246,18 +312,13 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
* not protected by lock. This works because count can
* only decrease at this point (all other puts are shut
* out by lock), and we (or some other waiting put) are
- * signalled if it ever changes from
- * capacity. Similarly for all other uses of count in
- * other wait guards.
+ * signalled if it ever changes from capacity. Similarly
+ * for all other uses of count in other wait guards.
*/
- try {
- while (count.get() == capacity)
- notFull.await();
- } catch (InterruptedException ie) {
- notFull.signal(); // propagate to a non-interrupted thread
- throw ie;
+ while (count.get() == capacity) {
+ notFull.await();
}
- insert(e);
+ enqueue(e);
c = count.getAndIncrement();
if (c + 1 < capacity)
notFull.signal();
@@ -272,7 +333,7 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
* Inserts the specified element at the tail of this queue, waiting if
* necessary up to the specified wait time for space to become available.
*
- * @return <tt>true</tt> if successful, or <tt>false</tt> if
+ * @return {@code true} if successful, or {@code false} if
* the specified waiting time elapses before space is available.
* @throws InterruptedException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
@@ -287,23 +348,15 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
final AtomicInteger count = this.count;
putLock.lockInterruptibly();
try {
- for (;;) {
- if (count.get() < capacity) {
- insert(e);
- c = count.getAndIncrement();
- if (c + 1 < capacity)
- notFull.signal();
- break;
- }
+ while (count.get() == capacity) {
if (nanos <= 0)
return false;
- try {
- nanos = notFull.awaitNanos(nanos);
- } catch (InterruptedException ie) {
- notFull.signal(); // propagate to a non-interrupted thread
- throw ie;
- }
+ nanos = notFull.awaitNanos(nanos);
}
+ enqueue(e);
+ c = count.getAndIncrement();
+ if (c + 1 < capacity)
+ notFull.signal();
} finally {
putLock.unlock();
}
@@ -315,7 +368,7 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
/**
* Inserts the specified element at the tail of this queue if it is
* possible to do so immediately without exceeding the queue's capacity,
- * returning <tt>true</tt> upon success and <tt>false</tt> if this queue
+ * returning {@code true} upon success and {@code false} if this queue
* is full.
* When using a capacity-restricted queue, this method is generally
* preferable to method {@link BlockingQueue#add add}, which can fail to
@@ -333,7 +386,7 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
putLock.lock();
try {
if (count.get() < capacity) {
- insert(e);
+ enqueue(e);
c = count.getAndIncrement();
if (c + 1 < capacity)
notFull.signal();
@@ -354,15 +407,10 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
final ReentrantLock takeLock = this.takeLock;
takeLock.lockInterruptibly();
try {
- try {
- while (count.get() == 0)
- notEmpty.await();
- } catch (InterruptedException ie) {
- notEmpty.signal(); // propagate to a non-interrupted thread
- throw ie;
+ while (count.get() == 0) {
+ notEmpty.await();
}
-
- x = extract();
+ x = dequeue();
c = count.getAndDecrement();
if (c > 1)
notEmpty.signal();
@@ -382,23 +430,15 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
final ReentrantLock takeLock = this.takeLock;
takeLock.lockInterruptibly();
try {
- for (;;) {
- if (count.get() > 0) {
- x = extract();
- c = count.getAndDecrement();
- if (c > 1)
- notEmpty.signal();
- break;
- }
+ while (count.get() == 0) {
if (nanos <= 0)
return null;
- try {
- nanos = notEmpty.awaitNanos(nanos);
- } catch (InterruptedException ie) {
- notEmpty.signal(); // propagate to a non-interrupted thread
- throw ie;
- }
+ nanos = notEmpty.awaitNanos(nanos);
}
+ x = dequeue();
+ c = count.getAndDecrement();
+ if (c > 1)
+ notEmpty.signal();
} finally {
takeLock.unlock();
}
@@ -417,7 +457,7 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
takeLock.lock();
try {
if (count.get() > 0) {
- x = extract();
+ x = dequeue();
c = count.getAndDecrement();
if (c > 1)
notEmpty.signal();
@@ -430,7 +470,6 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
return x;
}
-
public E peek() {
if (count.get() == 0)
return null;
@@ -448,43 +487,47 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
}
/**
+ * Unlinks interior Node p with predecessor trail.
+ */
+ void unlink(Node<E> p, Node<E> trail) {
+ // assert isFullyLocked();
+ // p.next is not changed, to allow iterators that are
+ // traversing p to maintain their weak-consistency guarantee.
+ p.item = null;
+ trail.next = p.next;
+ if (last == p)
+ last = trail;
+ if (count.getAndDecrement() == capacity)
+ notFull.signal();
+ }
+
+ /**
* Removes a single instance of the specified element from this queue,
- * if it is present. More formally, removes an element <tt>e</tt> such
- * that <tt>o.equals(e)</tt>, if this queue contains one or more such
+ * if it is present. More formally, removes an element {@code e} such
+ * that {@code o.equals(e)}, if this queue contains one or more such
* elements.
- * Returns <tt>true</tt> if this queue contained the specified element
+ * Returns {@code true} if this queue contained the specified element
* (or equivalently, if this queue changed as a result of the call).
*
* @param o element to be removed from this queue, if present
- * @return <tt>true</tt> if this queue changed as a result of the call
+ * @return {@code true} if this queue changed as a result of the call
*/
public boolean remove(Object o) {
if (o == null) return false;
- boolean removed = false;
fullyLock();
try {
- Node<E> trail = head;
- Node<E> p = head.next;
- while (p != null) {
+ for (Node<E> trail = head, p = trail.next;
+ p != null;
+ trail = p, p = p.next) {
if (o.equals(p.item)) {
- removed = true;
- break;
+ unlink(p, trail);
+ return true;
}
- trail = p;
- p = p.next;
- }
- if (removed) {
- p.item = null;
- trail.next = p.next;
- if (last == p)
- last = trail;
- if (count.getAndDecrement() == capacity)
- notFull.signalAll();
}
+ return false;
} finally {
fullyUnlock();
}
- return removed;
}
/**
@@ -524,22 +567,22 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
* <p>If this queue fits in the specified array with room to spare
* (i.e., the array has more elements than this queue), the element in
* the array immediately following the end of the queue is set to
- * <tt>null</tt>.
+ * {@code null}.
*
* <p>Like the {@link #toArray()} method, this method acts as bridge between
* array-based and collection-based APIs. Further, this method allows
* precise control over the runtime type of the output array, and may,
* under certain circumstances, be used to save allocation costs.
*
- * <p>Suppose <tt>x</tt> is a queue known to contain only strings.
+ * <p>Suppose {@code x} is a queue known to contain only strings.
* The following code can be used to dump the queue into a newly
- * allocated array of <tt>String</tt>:
+ * allocated array of {@code String}:
*
* <pre>
* String[] y = x.toArray(new String[0]);</pre>
*
- * Note that <tt>toArray(new Object[0])</tt> is identical in function to
- * <tt>toArray()</tt>.
+ * Note that {@code toArray(new Object[0])} is identical in function to
+ * {@code toArray()}.
*
* @param a the array into which the elements of the queue are to
* be stored, if it is big enough; otherwise, a new array of the
@@ -550,6 +593,7 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
* this queue
* @throws NullPointerException if the specified array is null
*/
+ @SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
fullyLock();
try {
@@ -559,7 +603,7 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
(a.getClass().getComponentType(), size);
int k = 0;
- for (Node p = head.next; p != null; p = p.next)
+ for (Node<E> p = head.next; p != null; p = p.next)
a[k++] = (T)p.item;
if (a.length > k)
a[k] = null;
@@ -585,11 +629,14 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
public void clear() {
fullyLock();
try {
- head.next = null;
- assert head.item == null;
- last = head;
+ for (Node<E> p, h = head; (p = h.next) != null; h = p) {
+ h.next = h;
+ p.item = null;
+ }
+ head = last;
+ // assert head.item == null && head.next == null;
if (count.getAndSet(0) == capacity)
- notFull.signalAll();
+ notFull.signal();
} finally {
fullyUnlock();
}
@@ -602,30 +649,7 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
* @throws IllegalArgumentException {@inheritDoc}
*/
public int drainTo(Collection<? super E> c) {
- if (c == null)
- throw new NullPointerException();
- if (c == this)
- throw new IllegalArgumentException();
- Node<E> first;
- fullyLock();
- try {
- first = head.next;
- head.next = null;
- assert head.item == null;
- last = head;
- if (count.getAndSet(0) == capacity)
- notFull.signalAll();
- } finally {
- fullyUnlock();
- }
- // Transfer the elements outside of locks
- int n = 0;
- for (Node<E> p = first; p != null; p = p.next) {
- c.add(p.item);
- p.item = null;
- ++n;
- }
- return n;
+ return drainTo(c, Integer.MAX_VALUE);
}
/**
@@ -639,34 +663,44 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
throw new NullPointerException();
if (c == this)
throw new IllegalArgumentException();
- fullyLock();
+ boolean signalNotFull = false;
+ final ReentrantLock takeLock = this.takeLock;
+ takeLock.lock();
try {
- int n = 0;
- Node<E> p = head.next;
- while (p != null && n < maxElements) {
- c.add(p.item);
- p.item = null;
- p = p.next;
- ++n;
- }
- if (n != 0) {
- head.next = p;
- assert head.item == null;
- if (p == null)
- last = head;
- if (count.getAndAdd(-n) == capacity)
- notFull.signalAll();
+ int n = Math.min(maxElements, count.get());
+ // count.get provides visibility to first n Nodes
+ Node<E> h = head;
+ int i = 0;
+ try {
+ while (i < n) {
+ Node<E> p = h.next;
+ c.add(p.item);
+ p.item = null;
+ h.next = h;
+ h = p;
+ ++i;
+ }
+ return n;
+ } finally {
+ // Restore invariants even if c.add() threw
+ if (i > 0) {
+ // assert h.item == null;
+ head = h;
+ signalNotFull = (count.getAndAdd(-i) == capacity);
+ }
}
- return n;
} finally {
- fullyUnlock();
+ takeLock.unlock();
+ if (signalNotFull)
+ signalNotFull();
}
}
/**
* Returns an iterator over the elements in this queue in proper sequence.
- * The returned <tt>Iterator</tt> is a "weakly consistent" iterator that
- * will never throw {@link ConcurrentModificationException},
+ * The returned {@code Iterator} is a "weakly consistent" iterator that
+ * will never throw {@link java.util.ConcurrentModificationException
+ * ConcurrentModificationException},
* and guarantees to traverse elements as they existed upon
* construction of the iterator, and may (but is not guaranteed to)
* reflect any modifications subsequent to construction.
@@ -679,7 +713,7 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
private class Itr implements Iterator<E> {
/*
- * Basic weak-consistent iterator. At all times hold the next
+ * Basic weakly-consistent iterator. At all times hold the next
* item to hand out so that if hasNext() reports true, we will
* still have it to return even if lost race with a take etc.
*/
@@ -688,17 +722,13 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
private E currentElement;
Itr() {
- final ReentrantLock putLock = LinkedBlockingQueue.this.putLock;
- final ReentrantLock takeLock = LinkedBlockingQueue.this.takeLock;
- putLock.lock();
- takeLock.lock();
+ fullyLock();
try {
current = head.next;
if (current != null)
currentElement = current.item;
} finally {
- takeLock.unlock();
- putLock.unlock();
+ fullyUnlock();
}
}
@@ -706,54 +736,56 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
return current != null;
}
+ /**
+ * Returns the next live successor of p, or null if no such.
+ *
+ * Unlike other traversal methods, iterators need to handle both:
+ * - dequeued nodes (p.next == p)
+ * - (possibly multiple) interior removed nodes (p.item == null)
+ */
+ private Node<E> nextNode(Node<E> p) {
+ for (;;) {
+ Node<E> s = p.next;
+ if (s == p)
+ return head.next;
+ if (s == null || s.item != null)
+ return s;
+ p = s;
+ }
+ }
+
public E next() {
- final ReentrantLock putLock = LinkedBlockingQueue.this.putLock;
- final ReentrantLock takeLock = LinkedBlockingQueue.this.takeLock;
- putLock.lock();
- takeLock.lock();
+ fullyLock();
try {
if (current == null)
throw new NoSuchElementException();
E x = currentElement;
lastRet = current;
- current = current.next;
- if (current != null)
- currentElement = current.item;
+ current = nextNode(current);
+ currentElement = (current == null) ? null : current.item;
return x;
} finally {
- takeLock.unlock();
- putLock.unlock();
+ fullyUnlock();
}
}
public void remove() {
if (lastRet == null)
throw new IllegalStateException();
- final ReentrantLock putLock = LinkedBlockingQueue.this.putLock;
- final ReentrantLock takeLock = LinkedBlockingQueue.this.takeLock;
- putLock.lock();
- takeLock.lock();
+ fullyLock();
try {
Node<E> node = lastRet;
lastRet = null;
- Node<E> trail = head;
- Node<E> p = head.next;
- while (p != null && p != node) {
- trail = p;
- p = p.next;
- }
- if (p == node) {
- p.item = null;
- trail.next = p.next;
- if (last == p)
- last = trail;
- int c = count.getAndDecrement();
- if (c == capacity)
- notFull.signalAll();
+ for (Node<E> trail = head, p = trail.next;
+ p != null;
+ trail = p, p = p.next) {
+ if (p == node) {
+ unlink(p, trail);
+ break;
+ }
}
} finally {
- takeLock.unlock();
- putLock.unlock();
+ fullyUnlock();
}
}
}
@@ -762,7 +794,7 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
* Save the state to a stream (that is, serialize it).
*
* @serialData The capacity is emitted (int), followed by all of
- * its elements (each an <tt>Object</tt>) in the proper order,
+ * its elements (each an {@code Object}) in the proper order,
* followed by a null
* @param s the stream
*/
@@ -788,6 +820,7 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
/**
* Reconstitute this queue instance from a stream (that is,
* deserialize it).
+ *
* @param s the stream
*/
private void readObject(java.io.ObjectInputStream s)
@@ -800,6 +833,7 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
// Read in all elements and place in queue
for (;;) {
+ @SuppressWarnings("unchecked")
E item = (E)s.readObject();
if (item == null)
break;
diff --git a/concurrent/src/main/java/java/util/concurrent/PriorityBlockingQueue.java b/concurrent/src/main/java/java/util/concurrent/PriorityBlockingQueue.java
index 7a33dc7..35d7b89 100644
--- a/concurrent/src/main/java/java/util/concurrent/PriorityBlockingQueue.java
+++ b/concurrent/src/main/java/java/util/concurrent/PriorityBlockingQueue.java
@@ -146,7 +146,6 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E>
return offer(e);
}
- // BEGIN android-changed
/**
* Inserts the specified element into this priority queue.
*
diff --git a/concurrent/src/main/java/java/util/concurrent/RunnableFuture.java b/concurrent/src/main/java/java/util/concurrent/RunnableFuture.java
new file mode 100644
index 0000000..d74211d
--- /dev/null
+++ b/concurrent/src/main/java/java/util/concurrent/RunnableFuture.java
@@ -0,0 +1,25 @@
+/*
+ * 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;
+
+/**
+ * A {@link Future} that is {@link Runnable}. Successful execution of
+ * the <tt>run</tt> method causes completion of the <tt>Future</tt>
+ * and allows access to its results.
+ * @see FutureTask
+ * @see Executor
+ * @since 1.6
+ * @author Doug Lea
+ * @param <V> The result type returned by this Future's <tt>get</tt> method
+ */
+public interface RunnableFuture<V> extends Runnable, Future<V> {
+ /**
+ * Sets this Future to the result of its computation
+ * unless it has been cancelled.
+ */
+ void run();
+}
diff --git a/concurrent/src/main/java/java/util/concurrent/RunnableScheduledFuture.java b/concurrent/src/main/java/java/util/concurrent/RunnableScheduledFuture.java
new file mode 100644
index 0000000..0e8cc32
--- /dev/null
+++ b/concurrent/src/main/java/java/util/concurrent/RunnableScheduledFuture.java
@@ -0,0 +1,29 @@
+/*
+ * 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;
+
+/**
+ * A {@link ScheduledFuture} that is {@link Runnable}. Successful
+ * execution of the <tt>run</tt> method causes completion of the
+ * <tt>Future</tt> and allows access to its results.
+ * @see FutureTask
+ * @see Executor
+ * @since 1.6
+ * @author Doug Lea
+ * @param <V> The result type returned by this Future's <tt>get</tt> method
+ */
+public interface RunnableScheduledFuture<V> extends RunnableFuture<V>, ScheduledFuture<V> {
+
+ /**
+ * Returns true if this is a periodic task. A periodic task may
+ * re-run according to some schedule. A non-periodic task can be
+ * run only once.
+ *
+ * @return true if this task is periodic
+ */
+ boolean isPeriodic();
+}
diff --git a/concurrent/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java b/concurrent/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java
index 83ffb99..7e69936 100644
--- a/concurrent/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java
+++ b/concurrent/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java
@@ -4,10 +4,6 @@
* http://creativecommons.org/licenses/publicdomain
*/
-/*
- * Modified in Apache Harmony.
- */
-
package java.util.concurrent;
import java.util.concurrent.atomic.*;
import java.util.concurrent.locks.*;
@@ -27,6 +23,15 @@ import java.util.*;
* execution time are enabled in first-in-first-out (FIFO) order of
* submission.
*
+ * <p>When a submitted task is cancelled before it is run, execution
+ * is suppressed. By default, such a cancelled task is not
+ * automatically removed from the work queue until its delay
+ * elapses. While this enables further inspection and monitoring, it
+ * may also cause unbounded retention of cancelled tasks. To avoid
+ * this, set {@link #setRemoveOnCancelPolicy} to {@code true}, which
+ * causes tasks to be immediately removed from the work queue at
+ * time of cancellation.
+ *
* <p>Successive executions of a task scheduled via
* <code>scheduleAtFixedRate</code> or
* <code>scheduleWithFixedDelay</code> do not overlap. While different
@@ -37,9 +42,47 @@ import java.util.*;
*
* <p>While this class inherits from {@link ThreadPoolExecutor}, a few
* of the inherited tuning methods are not useful for it. In
- * particular, because it acts as a fixed-sized pool using {@code
- * corePoolSize} threads and an unbounded queue, adjustments to {@code
- * maximumPoolSize} have no useful effect.
+ * particular, because it acts as a fixed-sized pool using
+ * {@code corePoolSize} threads and an unbounded queue, adjustments
+ * to {@code maximumPoolSize} have no useful effect. Additionally, it
+ * is almost never a good idea to set {@code corePoolSize} to zero or
+ * use {@code allowCoreThreadTimeOut} because this may leave the pool
+ * without threads to handle tasks once they become eligible to run.
+ *
+ * <p><b>Extension notes:</b> This class overrides the
+ * {@link ThreadPoolExecutor#execute execute} and
+ * {@link AbstractExecutorService#submit(Runnable) submit}
+ * methods to generate internal {@link ScheduledFuture} objects to
+ * control per-task delays and scheduling. To preserve
+ * functionality, any further overrides of these methods in
+ * subclasses must invoke superclass versions, which effectively
+ * disables additional task customization. However, this class
+ * provides alternative protected extension method
+ * {@code decorateTask} (one version each for {@code Runnable} and
+ * {@code Callable}) that can be used to customize the concrete task
+ * types used to execute commands entered via {@code execute},
+ * {@code submit}, {@code schedule}, {@code scheduleAtFixedRate},
+ * and {@code scheduleWithFixedDelay}. By default, a
+ * {@code ScheduledThreadPoolExecutor} uses a task type extending
+ * {@link FutureTask}. However, this may be modified or replaced using
+ * subclasses of the form:
+ *
+ * <pre> {@code
+ * public class CustomScheduledExecutor extends ScheduledThreadPoolExecutor {
+ *
+ * static class CustomTask<V> implements RunnableScheduledFuture<V> { ... }
+ *
+ * protected <V> RunnableScheduledFuture<V> decorateTask(
+ * Runnable r, RunnableScheduledFuture<V> task) {
+ * return new CustomTask<V>(r, task);
+ * }
+ *
+ * protected <V> RunnableScheduledFuture<V> decorateTask(
+ * Callable<V> c, RunnableScheduledFuture<V> task) {
+ * return new CustomTask<V>(c, task);
+ * }
+ * // ... add constructors, etc.
+ * }}</pre>
*
* @since 1.5
* @author Doug Lea
@@ -96,23 +139,15 @@ public class ScheduledThreadPoolExecutor
*/
private static final AtomicLong sequencer = new AtomicLong(0);
-
- /**
- * Value of System.nanoTime upon static initialization. This is
- * used as an offset by now() to avoid wraparound of time values
- * that would make them appear negative.
- */
- static final long initialNanoTime = System.nanoTime();
-
/**
* Returns current nanosecond time.
*/
- static long now() {
- return System.nanoTime() - initialNanoTime;
+ final long now() {
+ return System.nanoTime();
}
private class ScheduledFutureTask<V>
- extends FutureTask<V> implements ScheduledFuture<V> {
+ extends FutureTask<V> implements RunnableScheduledFuture<V> {
/** Sequence number to break ties FIFO */
private final long sequenceNumber;
@@ -129,7 +164,7 @@ public class ScheduledThreadPoolExecutor
private final long period;
/** The actual task to be re-enqueued by reExecutePeriodic */
- ScheduledFutureTask<V> outerTask = this;
+ RunnableScheduledFuture<V> outerTask = this;
/**
* Index into delay queue, to support faster cancellation.
@@ -167,8 +202,7 @@ public class ScheduledThreadPoolExecutor
}
public long getDelay(TimeUnit unit) {
- long d = time - now();
- return d<=0? 0 : unit.convert(d, TimeUnit.NANOSECONDS);
+ return unit.convert(time - now(), TimeUnit.NANOSECONDS);
}
public int compareTo(Delayed other) {
@@ -208,7 +242,7 @@ public class ScheduledThreadPoolExecutor
if (p > 0)
time += p;
else
- time = now() - p;
+ time = triggerTime(-p);
}
public boolean cancel(boolean mayInterruptIfRunning) {
@@ -257,7 +291,7 @@ public class ScheduledThreadPoolExecutor
*
* @param task the task
*/
- private void delayedExecute(ScheduledFutureTask<?> task) {
+ private void delayedExecute(RunnableScheduledFuture<?> task) {
if (isShutdown())
reject(task);
else {
@@ -277,7 +311,7 @@ public class ScheduledThreadPoolExecutor
*
* @param task the task
*/
- void reExecutePeriodic(ScheduledFutureTask<?> task) {
+ void reExecutePeriodic(RunnableScheduledFuture<?> task) {
if (canRunInCurrentRunState(true)) {
super.getQueue().add(task);
if (!canRunInCurrentRunState(true) && remove(task))
@@ -302,9 +336,9 @@ public class ScheduledThreadPoolExecutor
else {
// Traverse snapshot to avoid iterator exceptions
for (Object e : q.toArray()) {
- if (e instanceof ScheduledFutureTask) {
- ScheduledFutureTask<?> t =
- (ScheduledFutureTask<?>)e;
+ if (e instanceof RunnableScheduledFuture) {
+ RunnableScheduledFuture<?> t =
+ (RunnableScheduledFuture<?>)e;
if ((t.isPeriodic() ? !keepPeriodic : !keepDelayed) ||
t.isCancelled()) { // also remove if already cancelled
if (q.remove(t))
@@ -317,11 +351,43 @@ public class ScheduledThreadPoolExecutor
}
/**
+ * Modifies or replaces the task used to execute a runnable.
+ * This method can be used to override the concrete
+ * class used for managing internal tasks.
+ * The default implementation simply returns the given task.
+ *
+ * @param runnable the submitted Runnable
+ * @param task the task created to execute the runnable
+ * @return a task that can execute the runnable
+ * @since 1.6
+ */
+ protected <V> RunnableScheduledFuture<V> decorateTask(
+ Runnable runnable, RunnableScheduledFuture<V> task) {
+ return task;
+ }
+
+ /**
+ * Modifies or replaces the task used to execute a callable.
+ * This method can be used to override the concrete
+ * class used for managing internal tasks.
+ * The default implementation simply returns the given task.
+ *
+ * @param callable the submitted Callable
+ * @param task the task created to execute the callable
+ * @return a task that can execute the callable
+ * @since 1.6
+ */
+ protected <V> RunnableScheduledFuture<V> decorateTask(
+ Callable<V> callable, RunnableScheduledFuture<V> task) {
+ return task;
+ }
+
+ /**
* Creates a new {@code ScheduledThreadPoolExecutor} with the
* given core pool size.
*
* @param corePoolSize the number of threads to keep in the pool, even
- * if they are idle
+ * if they are idle, unless {@code allowCoreThreadTimeOut} is set
* @throws IllegalArgumentException if {@code corePoolSize < 0}
*/
public ScheduledThreadPoolExecutor(int corePoolSize) {
@@ -334,7 +400,7 @@ public class ScheduledThreadPoolExecutor
* given initial parameters.
*
* @param corePoolSize the number of threads to keep in the pool, even
- * if they are idle
+ * if they are idle, unless {@code allowCoreThreadTimeOut} is set
* @param threadFactory the factory to use when the executor
* creates a new thread
* @throws IllegalArgumentException if {@code corePoolSize < 0}
@@ -351,7 +417,7 @@ public class ScheduledThreadPoolExecutor
* initial parameters.
*
* @param corePoolSize the number of threads to keep in the pool, even
- * if they are idle
+ * if they are idle, unless {@code allowCoreThreadTimeOut} is set
* @param handler the handler to use when execution is blocked
* because the thread bounds and queue capacities are reached
* @throws IllegalArgumentException if {@code corePoolSize < 0}
@@ -368,7 +434,7 @@ public class ScheduledThreadPoolExecutor
* initial parameters.
*
* @param corePoolSize the number of threads to keep in the pool, even
- * if they are idle
+ * if they are idle, unless {@code allowCoreThreadTimeOut} is set
* @param threadFactory the factory to use when the executor
* creates a new thread
* @param handler the handler to use when execution is blocked
@@ -385,17 +451,35 @@ public class ScheduledThreadPoolExecutor
}
/**
- * Returns the trigger time of a delayed action
+ * Returns the trigger time of a delayed action.
*/
- private static long nextTriggerTime(long delay, TimeUnit unit) {
- long triggerTime;
- long now = now();
- if (delay <= 0)
- return now; // avoid negative trigger times
- else if ((triggerTime = now + unit.toNanos(delay)) < 0)
- return Long.MAX_VALUE; // avoid numerical overflow
- else
- return triggerTime;
+ private long triggerTime(long delay, TimeUnit unit) {
+ return triggerTime(unit.toNanos((delay < 0) ? 0 : delay));
+ }
+
+ /**
+ * Returns the trigger time of a delayed action.
+ */
+ long triggerTime(long delay) {
+ return now() +
+ ((delay < (Long.MAX_VALUE >> 1)) ? delay : overflowFree(delay));
+ }
+
+ /**
+ * Constrains the values of all delays in the queue to be within
+ * Long.MAX_VALUE of each other, to avoid overflow in compareTo.
+ * This may occur if a task is eligible to be dequeued, but has
+ * not yet been, while some other task is added with a delay of
+ * Long.MAX_VALUE.
+ */
+ private long overflowFree(long delay) {
+ Delayed head = (Delayed) super.getQueue().peek();
+ if (head != null) {
+ long headDelay = head.getDelay(TimeUnit.NANOSECONDS);
+ if (headDelay < 0 && (delay - headDelay < 0))
+ delay = Long.MAX_VALUE + headDelay;
+ }
+ return delay;
}
/**
@@ -407,9 +491,9 @@ public class ScheduledThreadPoolExecutor
TimeUnit unit) {
if (command == null || unit == null)
throw new NullPointerException();
- long triggerTime = nextTriggerTime(delay, unit);
- ScheduledFutureTask<?> t
- = new ScheduledFutureTask<Void>(command, null, triggerTime);
+ RunnableScheduledFuture<?> t = decorateTask(command,
+ new ScheduledFutureTask<Void>(command, null,
+ triggerTime(delay, unit)));
delayedExecute(t);
return t;
}
@@ -423,9 +507,9 @@ public class ScheduledThreadPoolExecutor
TimeUnit unit) {
if (callable == null || unit == null)
throw new NullPointerException();
- long triggerTime = nextTriggerTime(delay, unit);
- ScheduledFutureTask<V> t
- = new ScheduledFutureTask<V>(callable, triggerTime);
+ RunnableScheduledFuture<V> t = decorateTask(callable,
+ new ScheduledFutureTask<V>(callable,
+ triggerTime(delay, unit)));
delayedExecute(t);
return t;
}
@@ -443,16 +527,15 @@ public class ScheduledThreadPoolExecutor
throw new NullPointerException();
if (period <= 0)
throw new IllegalArgumentException();
- if (initialDelay < 0) initialDelay = 0;
- long triggerTime = nextTriggerTime(initialDelay, unit);
ScheduledFutureTask<Void> sft =
new ScheduledFutureTask<Void>(command,
null,
- triggerTime,
+ triggerTime(initialDelay, unit),
unit.toNanos(period));
- sft.outerTask = sft;
- delayedExecute(sft);
- return sft;
+ RunnableScheduledFuture<Void> t = decorateTask(command, sft);
+ sft.outerTask = t;
+ delayedExecute(t);
+ return t;
}
/**
@@ -468,15 +551,15 @@ public class ScheduledThreadPoolExecutor
throw new NullPointerException();
if (delay <= 0)
throw new IllegalArgumentException();
- long triggerTime = nextTriggerTime(initialDelay, unit);
ScheduledFutureTask<Void> sft =
new ScheduledFutureTask<Void>(command,
null,
- triggerTime,
+ triggerTime(initialDelay, unit),
unit.toNanos(-delay));
- sft.outerTask = sft;
- delayedExecute(sft);
- return sft;
+ RunnableScheduledFuture<Void> t = decorateTask(command, sft);
+ sft.outerTask = t;
+ delayedExecute(t);
+ return t;
}
/**
@@ -595,6 +678,33 @@ public class ScheduledThreadPoolExecutor
}
/**
+ * Sets the policy on whether cancelled tasks should be immediately
+ * removed from the work queue at time of cancellation. This value is
+ * by default {@code false}.
+ *
+ * @param value if {@code true}, remove on cancellation, else don't
+ * @see #getRemoveOnCancelPolicy
+ * @since 1.7
+ */
+ /*public*/ void setRemoveOnCancelPolicy(boolean value) { // android-changed
+ removeOnCancel = value;
+ }
+
+ /**
+ * Gets the policy on whether cancelled tasks should be immediately
+ * removed from the work queue at time of cancellation. This value is
+ * by default {@code false}.
+ *
+ * @return {@code true} if cancelled tasks are immediately removed
+ * from the queue
+ * @see #setRemoveOnCancelPolicy
+ * @since 1.7
+ */
+ /*public*/ boolean getRemoveOnCancelPolicy() { // android-changed
+ return removeOnCancel;
+ }
+
+ /**
* Initiates an orderly shutdown in which previously submitted
* tasks are executed, but no new tasks will be accepted.
* Invocation has no additional effect if already shut down.
@@ -688,8 +798,8 @@ public class ScheduledThreadPoolExecutor
*/
private static final int INITIAL_CAPACITY = 16;
- private ScheduledFutureTask[] queue =
- new ScheduledFutureTask[INITIAL_CAPACITY];
+ private RunnableScheduledFuture[] queue =
+ new RunnableScheduledFuture[INITIAL_CAPACITY];
private final ReentrantLock lock = new ReentrantLock();
private int size = 0;
@@ -720,7 +830,7 @@ public class ScheduledThreadPoolExecutor
/**
* Set f's heapIndex if it is a ScheduledFutureTask.
*/
- private void setIndex(ScheduledFutureTask f, int idx) {
+ private void setIndex(RunnableScheduledFuture f, int idx) {
if (f instanceof ScheduledFutureTask)
((ScheduledFutureTask)f).heapIndex = idx;
}
@@ -729,10 +839,10 @@ public class ScheduledThreadPoolExecutor
* Sift element added at bottom up to its heap-ordered spot.
* Call only when holding lock.
*/
- private void siftUp(int k, ScheduledFutureTask key) {
+ private void siftUp(int k, RunnableScheduledFuture key) {
while (k > 0) {
int parent = (k - 1) >>> 1;
- ScheduledFutureTask e = queue[parent];
+ RunnableScheduledFuture e = queue[parent];
if (key.compareTo(e) >= 0)
break;
queue[k] = e;
@@ -747,11 +857,11 @@ public class ScheduledThreadPoolExecutor
* Sift element added at top down to its heap-ordered spot.
* Call only when holding lock.
*/
- private void siftDown(int k, ScheduledFutureTask key) {
+ private void siftDown(int k, RunnableScheduledFuture key) {
int half = size >>> 1;
while (k < half) {
int child = (k << 1) + 1;
- ScheduledFutureTask c = queue[child];
+ RunnableScheduledFuture c = queue[child];
int right = child + 1;
if (right < size && c.compareTo(queue[right]) > 0)
c = queue[child = right];
@@ -773,7 +883,7 @@ public class ScheduledThreadPoolExecutor
int newCapacity = oldCapacity + (oldCapacity >> 1); // grow 50%
if (newCapacity < 0) // overflow
newCapacity = Integer.MAX_VALUE;
- queue = Java6Arrays.copyOf(queue, newCapacity);
+ queue = Arrays.copyOf(queue, newCapacity);
}
/**
@@ -816,7 +926,7 @@ public class ScheduledThreadPoolExecutor
setIndex(queue[i], -1);
int s = --size;
- ScheduledFutureTask replacement = queue[s];
+ RunnableScheduledFuture replacement = queue[s];
queue[s] = null;
if (s != i) {
siftDown(i, replacement);
@@ -847,7 +957,7 @@ public class ScheduledThreadPoolExecutor
return Integer.MAX_VALUE;
}
- public ScheduledFutureTask peek() {
+ public RunnableScheduledFuture peek() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
@@ -860,7 +970,7 @@ public class ScheduledThreadPoolExecutor
public boolean offer(Runnable x) {
if (x == null)
throw new NullPointerException();
- ScheduledFutureTask e = (ScheduledFutureTask)x;
+ RunnableScheduledFuture e = (RunnableScheduledFuture)x;
final ReentrantLock lock = this.lock;
lock.lock();
try {
@@ -902,9 +1012,9 @@ public class ScheduledThreadPoolExecutor
* holding lock.
* @param f the task to remove and return
*/
- private ScheduledFutureTask finishPoll(ScheduledFutureTask f) {
+ private RunnableScheduledFuture finishPoll(RunnableScheduledFuture f) {
int s = --size;
- ScheduledFutureTask x = queue[s];
+ RunnableScheduledFuture x = queue[s];
queue[s] = null;
if (s != 0)
siftDown(0, x);
@@ -912,11 +1022,11 @@ public class ScheduledThreadPoolExecutor
return f;
}
- public ScheduledFutureTask poll() {
+ public RunnableScheduledFuture poll() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
- ScheduledFutureTask first = queue[0];
+ RunnableScheduledFuture first = queue[0];
if (first == null || first.getDelay(TimeUnit.NANOSECONDS) > 0)
return null;
else
@@ -926,12 +1036,12 @@ public class ScheduledThreadPoolExecutor
}
}
- public ScheduledFutureTask take() throws InterruptedException {
+ public RunnableScheduledFuture take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
for (;;) {
- ScheduledFutureTask first = queue[0];
+ RunnableScheduledFuture first = queue[0];
if (first == null)
available.await();
else {
@@ -959,14 +1069,14 @@ public class ScheduledThreadPoolExecutor
}
}
- public ScheduledFutureTask poll(long timeout, TimeUnit unit)
+ public RunnableScheduledFuture poll(long timeout, TimeUnit unit)
throws InterruptedException {
long nanos = unit.toNanos(timeout);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
for (;;) {
- ScheduledFutureTask first = queue[0];
+ RunnableScheduledFuture first = queue[0];
if (first == null) {
if (nanos <= 0)
return null;
@@ -1005,7 +1115,7 @@ public class ScheduledThreadPoolExecutor
lock.lock();
try {
for (int i = 0; i < size; i++) {
- ScheduledFutureTask t = queue[i];
+ RunnableScheduledFuture t = queue[i];
if (t != null) {
queue[i] = null;
setIndex(t, -1);
@@ -1021,8 +1131,8 @@ public class ScheduledThreadPoolExecutor
* Return and remove first element only if it is expired.
* Used only by drainTo. Call only when holding lock.
*/
- private ScheduledFutureTask pollExpired() {
- ScheduledFutureTask first = queue[0];
+ private RunnableScheduledFuture pollExpired() {
+ RunnableScheduledFuture first = queue[0];
if (first == null || first.getDelay(TimeUnit.NANOSECONDS) > 0)
return null;
return finishPoll(first);
@@ -1036,7 +1146,7 @@ public class ScheduledThreadPoolExecutor
final ReentrantLock lock = this.lock;
lock.lock();
try {
- ScheduledFutureTask first;
+ RunnableScheduledFuture first;
int n = 0;
while ((first = pollExpired()) != null) {
c.add(first);
@@ -1058,7 +1168,7 @@ public class ScheduledThreadPoolExecutor
final ReentrantLock lock = this.lock;
lock.lock();
try {
- ScheduledFutureTask first;
+ RunnableScheduledFuture first;
int n = 0;
while (n < maxElements && (first = pollExpired()) != null) {
c.add(first);
@@ -1074,7 +1184,7 @@ public class ScheduledThreadPoolExecutor
final ReentrantLock lock = this.lock;
lock.lock();
try {
- return Java6Arrays.copyOf(queue, size, Object[].class);
+ return Arrays.copyOf(queue, size, Object[].class);
} finally {
lock.unlock();
}
@@ -1086,7 +1196,7 @@ public class ScheduledThreadPoolExecutor
lock.lock();
try {
if (a.length < size)
- return (T[]) Java6Arrays.copyOf(queue, size, a.getClass());
+ return (T[]) Arrays.copyOf(queue, size, a.getClass());
System.arraycopy(queue, 0, a, 0, size);
if (a.length > size)
a[size] = null;
@@ -1097,18 +1207,18 @@ public class ScheduledThreadPoolExecutor
}
public Iterator<Runnable> iterator() {
- return new Itr(Java6Arrays.copyOf(queue, size));
+ return new Itr(Arrays.copyOf(queue, size));
}
/**
* Snapshot iterator that works off copy of underlying q array.
*/
private class Itr implements Iterator<Runnable> {
- final ScheduledFutureTask[] array;
+ final RunnableScheduledFuture[] array;
int cursor = 0; // index of next element to return
int lastRet = -1; // index of last element, or -1 if no such
- Itr(ScheduledFutureTask[] array) {
+ Itr(RunnableScheduledFuture[] array) {
this.array = array;
}
diff --git a/concurrent/src/main/java/java/util/concurrent/Semaphore.java b/concurrent/src/main/java/java/util/concurrent/Semaphore.java
index 1052364..1f5c00e 100644
--- a/concurrent/src/main/java/java/util/concurrent/Semaphore.java
+++ b/concurrent/src/main/java/java/util/concurrent/Semaphore.java
@@ -212,10 +212,8 @@ public class Semaphore implements java.io.Serializable {
}
protected int tryAcquireShared(int acquires) {
- Thread current = Thread.currentThread();
for (;;) {
- Thread first = getFirstQueuedThread();
- if (first != null && first != current)
+ if (hasQueuedPredecessors())
return -1;
int available = getState();
int remaining = available - acquires;
diff --git a/concurrent/src/main/java/java/util/concurrent/SynchronousQueue.java b/concurrent/src/main/java/java/util/concurrent/SynchronousQueue.java
index 0d297ff..5f9e8d7 100644
--- a/concurrent/src/main/java/java/util/concurrent/SynchronousQueue.java
+++ b/concurrent/src/main/java/java/util/concurrent/SynchronousQueue.java
@@ -419,9 +419,9 @@ public class SynchronousQueue<E> extends AbstractQueue<E>
else if (s.waiter == null)
s.waiter = w; // establish waiter so can park next iter
else if (!timed)
- LockSupport.park();
+ LockSupport.park(this);
else if (nanos > spinForTimeoutThreshold)
- LockSupport.parkNanos(nanos);
+ LockSupport.parkNanos(this, nanos);
}
}
@@ -711,9 +711,9 @@ public class SynchronousQueue<E> extends AbstractQueue<E>
else if (s.waiter == null)
s.waiter = w;
else if (!timed)
- LockSupport.park();
+ LockSupport.park(this);
else if (nanos > spinForTimeoutThreshold)
- LockSupport.parkNanos(nanos);
+ LockSupport.parkNanos(this, nanos);
}
}
@@ -991,19 +991,6 @@ public class SynchronousQueue<E> extends AbstractQueue<E>
return null;
}
-
- static class EmptyIterator<E> implements Iterator<E> {
- public boolean hasNext() {
- return false;
- }
- public E next() {
- throw new NoSuchElementException();
- }
- public void remove() {
- throw new IllegalStateException();
- }
- }
-
/**
* Returns an empty iterator in which <tt>hasNext</tt> always returns
* <tt>false</tt>.
@@ -1011,7 +998,7 @@ public class SynchronousQueue<E> extends AbstractQueue<E>
* @return an empty iterator
*/
public Iterator<E> iterator() {
- return new EmptyIterator<E>();
+ return Collections.<E>emptySet().iterator(); // android-changed
}
/**
diff --git a/concurrent/src/main/java/java/util/concurrent/ThreadPoolExecutor.java b/concurrent/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
index d0c934d..c362c99 100644
--- a/concurrent/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
+++ b/concurrent/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
@@ -92,9 +92,12 @@ import java.util.*;
* threads will be constructed. This parameter can also be changed
* dynamically using method {@link #setKeepAliveTime}. Using a value
* of {@code Long.MAX_VALUE} {@link TimeUnit#NANOSECONDS} effectively
- * disables idle threads from ever terminating prior to shut down. The
- * keep-alive policy applies only when there are more than
- * corePoolSizeThreads.</dd>
+ * disables idle threads from ever terminating prior to shut down. By
+ * default, the keep-alive policy applies only when there are more
+ * than corePoolSizeThreads. But method {@link
+ * #allowCoreThreadTimeOut(boolean)} can be used to apply this
+ * time-out policy to core threads as well, so long as the
+ * keepAliveTime value is non-zero. </dd>
*
* <dt>Queuing</dt>
*
@@ -228,7 +231,8 @@ import java.util.*;
* you would like to ensure that unreferenced pools are reclaimed even
* if users forget to call {@link #shutdown}, then you must arrange
* that unused threads eventually die, by setting appropriate
- * keep-alive times using a lower bound of zero core threads. </dd>
+ * keep-alive times, using a lower bound of zero core threads and/or
+ * setting {@link #allowCoreThreadTimeOut(boolean)}. </dd>
*
* </dl>
*
@@ -473,13 +477,22 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
/**
* Timeout in nanoseconds for idle threads waiting for work.
* Threads use this timeout when there are more than corePoolSize
- * present. Otherwise they wait forever for new work.
+ * present or if allowCoreThreadTimeOut. Otherwise they wait
+ * forever for new work.
*/
private volatile long keepAliveTime;
/**
+ * If false (default), core threads stay alive even when idle.
+ * If true, core threads use keepAliveTime to time out waiting
+ * for work.
+ */
+ private volatile boolean allowCoreThreadTimeOut;
+
+ /**
* Core pool size is the minimum number of workers to keep alive
- * (and not allow to time out etc).
+ * (and not allow to time out etc) unless allowCoreThreadTimeOut
+ * is set, in which case the minimum is zero.
*/
private volatile int corePoolSize;
@@ -941,7 +954,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
int c = ctl.get();
if (runStateLessThan(c, STOP)) {
if (!completedAbruptly) {
- int min = corePoolSize;
+ int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
if (min == 0 && ! workQueue.isEmpty())
min = 1;
if (workerCountOf(c) >= min)
@@ -961,7 +974,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* 3. The pool is shutdown and the queue is empty.
* 4. This worker timed out waiting for a task, and timed-out
* workers are subject to termination (that is,
- * {@code workerCount > corePoolSize})
+ * {@code allowCoreThreadTimeOut || workerCount > corePoolSize})
* both before and after the timed wait.
*
* @return task, or null if the worker must exit, in which case
@@ -985,7 +998,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
for (;;) {
int wc = workerCountOf(c);
- timed = wc > corePoolSize;
+ timed = allowCoreThreadTimeOut || wc > corePoolSize;
if (wc <= maximumPoolSize && ! (timedOut && timed))
break;
@@ -1096,7 +1109,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* methods instead of this general purpose constructor.
*
* @param corePoolSize the number of threads to keep in the pool, even
- * if they are idle
+ * if they are idle, unless {@code allowCoreThreadTimeOut} is set
* @param maximumPoolSize the maximum number of threads to allow in the
* pool
* @param keepAliveTime when the number of threads is greater than
@@ -1127,7 +1140,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* parameters and default rejected execution handler.
*
* @param corePoolSize the number of threads to keep in the pool, even
- * if they are idle
+ * if they are idle, unless {@code allowCoreThreadTimeOut} is set
* @param maximumPoolSize the maximum number of threads to allow in the
* pool
* @param keepAliveTime when the number of threads is greater than
@@ -1162,7 +1175,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* parameters and default thread factory.
*
* @param corePoolSize the number of threads to keep in the pool, even
- * if they are idle
+ * if they are idle, unless {@code allowCoreThreadTimeOut} is set
* @param maximumPoolSize the maximum number of threads to allow in the
* pool
* @param keepAliveTime when the number of threads is greater than
@@ -1197,7 +1210,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* parameters.
*
* @param corePoolSize the number of threads to keep in the pool, even
- * if they are idle
+ * if they are idle, unless {@code allowCoreThreadTimeOut} is set
* @param maximumPoolSize the maximum number of threads to allow in the
* pool
* @param keepAliveTime when the number of threads is greater than
@@ -1518,6 +1531,50 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
}
/**
+ * Returns true if this pool allows core threads to time out and
+ * terminate if no tasks arrive within the keepAlive time, being
+ * replaced if needed when new tasks arrive. When true, the same
+ * keep-alive policy applying to non-core threads applies also to
+ * core threads. When false (the default), core threads are never
+ * terminated due to lack of incoming tasks.
+ *
+ * @return {@code true} if core threads are allowed to time out,
+ * else {@code false}
+ *
+ * @since 1.6
+ */
+ public boolean allowsCoreThreadTimeOut() {
+ return allowCoreThreadTimeOut;
+ }
+
+ /**
+ * Sets the policy governing whether core threads may time out and
+ * terminate if no tasks arrive within the keep-alive time, being
+ * replaced if needed when new tasks arrive. When false, core
+ * threads are never terminated due to lack of incoming
+ * tasks. When true, the same keep-alive policy applying to
+ * non-core threads applies also to core threads. To avoid
+ * continual thread replacement, the keep-alive time must be
+ * greater than zero when setting {@code true}. This method
+ * should in general be called before the pool is actively used.
+ *
+ * @param value {@code true} if should time out, else {@code false}
+ * @throws IllegalArgumentException if value is {@code true}
+ * and the current keep-alive time is not greater than zero
+ *
+ * @since 1.6
+ */
+ public void allowCoreThreadTimeOut(boolean value) {
+ if (value && keepAliveTime <= 0)
+ throw new IllegalArgumentException("Core threads must have nonzero keep alive times");
+ if (value != allowCoreThreadTimeOut) {
+ allowCoreThreadTimeOut = value;
+ if (value)
+ interruptIdleWorkers();
+ }
+ }
+
+ /**
* Sets the maximum allowed number of threads. This overrides any
* value set in the constructor. If the new value is smaller than
* the current value, excess existing threads will be
@@ -1564,6 +1621,8 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
public void setKeepAliveTime(long time, TimeUnit unit) {
if (time < 0)
throw new IllegalArgumentException();
+ if (time == 0 && allowsCoreThreadTimeOut())
+ throw new IllegalArgumentException("Core threads must have nonzero keep alive times");
long keepAliveTime = unit.toNanos(time);
long delta = keepAliveTime - this.keepAliveTime;
this.keepAliveTime = keepAliveTime;
diff --git a/concurrent/src/main/java/java/util/concurrent/TimeUnit.java b/concurrent/src/main/java/java/util/concurrent/TimeUnit.java
index 412d28a..ae78fda 100644
--- a/concurrent/src/main/java/java/util/concurrent/TimeUnit.java
+++ b/concurrent/src/main/java/java/util/concurrent/TimeUnit.java
@@ -40,7 +40,6 @@ package java.util.concurrent;
* @author Doug Lea
*/
public enum TimeUnit {
- /** TimeUnit which represents one nanosecond. */
NANOSECONDS {
public long toNanos(long d) { return d; }
public long toMicros(long d) { return d/(C1/C0); }
@@ -52,7 +51,6 @@ public enum TimeUnit {
public long convert(long d, TimeUnit u) { return u.toNanos(d); }
int excessNanos(long d, long m) { return (int)(d - (m*C2)); }
},
- /** TimeUnit which represents one microsecond. */
MICROSECONDS {
public long toNanos(long d) { return x(d, C1/C0, MAX/(C1/C0)); }
public long toMicros(long d) { return d; }
@@ -64,7 +62,6 @@ public enum TimeUnit {
public long convert(long d, TimeUnit u) { return u.toMicros(d); }
int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); }
},
- /** TimeUnit which represents one millisecond. */
MILLISECONDS {
public long toNanos(long d) { return x(d, C2/C0, MAX/(C2/C0)); }
public long toMicros(long d) { return x(d, C2/C1, MAX/(C2/C1)); }
@@ -76,7 +73,6 @@ public enum TimeUnit {
public long convert(long d, TimeUnit u) { return u.toMillis(d); }
int excessNanos(long d, long m) { return 0; }
},
- /** TimeUnit which represents one second. */
SECONDS {
public long toNanos(long d) { return x(d, C3/C0, MAX/(C3/C0)); }
public long toMicros(long d) { return x(d, C3/C1, MAX/(C3/C1)); }
@@ -87,6 +83,39 @@ public enum TimeUnit {
public long toDays(long d) { return d/(C6/C3); }
public long convert(long d, TimeUnit u) { return u.toSeconds(d); }
int excessNanos(long d, long m) { return 0; }
+ },
+ MINUTES {
+ public long toNanos(long d) { return x(d, C4/C0, MAX/(C4/C0)); }
+ public long toMicros(long d) { return x(d, C4/C1, MAX/(C4/C1)); }
+ public long toMillis(long d) { return x(d, C4/C2, MAX/(C4/C2)); }
+ public long toSeconds(long d) { return x(d, C4/C3, MAX/(C4/C3)); }
+ public long toMinutes(long d) { return d; }
+ public long toHours(long d) { return d/(C5/C4); }
+ public long toDays(long d) { return d/(C6/C4); }
+ public long convert(long d, TimeUnit u) { return u.toMinutes(d); }
+ int excessNanos(long d, long m) { return 0; }
+ },
+ HOURS {
+ public long toNanos(long d) { return x(d, C5/C0, MAX/(C5/C0)); }
+ public long toMicros(long d) { return x(d, C5/C1, MAX/(C5/C1)); }
+ public long toMillis(long d) { return x(d, C5/C2, MAX/(C5/C2)); }
+ public long toSeconds(long d) { return x(d, C5/C3, MAX/(C5/C3)); }
+ public long toMinutes(long d) { return x(d, C5/C4, MAX/(C5/C4)); }
+ public long toHours(long d) { return d; }
+ public long toDays(long d) { return d/(C6/C5); }
+ public long convert(long d, TimeUnit u) { return u.toHours(d); }
+ int excessNanos(long d, long m) { return 0; }
+ },
+ DAYS {
+ public long toNanos(long d) { return x(d, C6/C0, MAX/(C6/C0)); }
+ public long toMicros(long d) { return x(d, C6/C1, MAX/(C6/C1)); }
+ public long toMillis(long d) { return x(d, C6/C2, MAX/(C6/C2)); }
+ public long toSeconds(long d) { return x(d, C6/C3, MAX/(C6/C3)); }
+ public long toMinutes(long d) { return x(d, C6/C4, MAX/(C6/C4)); }
+ public long toHours(long d) { return x(d, C6/C5, MAX/(C6/C5)); }
+ public long toDays(long d) { return d; }
+ public long convert(long d, TimeUnit u) { return u.toDays(d); }
+ int excessNanos(long d, long m) { return 0; }
};
// Handy constants for conversion methods
@@ -193,8 +222,9 @@ public enum TimeUnit {
* or <tt>Long.MIN_VALUE</tt> if conversion would negatively
* overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
* @see #convert
+ * @since 1.6
*/
- long toMinutes(long duration) {
+ public long toMinutes(long duration) {
throw new AbstractMethodError();
}
@@ -205,8 +235,9 @@ public enum TimeUnit {
* or <tt>Long.MIN_VALUE</tt> if conversion would negatively
* overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
* @see #convert
+ * @since 1.6
*/
- long toHours(long duration) {
+ public long toHours(long duration) {
throw new AbstractMethodError();
}
@@ -215,8 +246,9 @@ public enum TimeUnit {
* @param duration the duration
* @return the converted duration
* @see #convert
+ * @since 1.6
*/
- long toDays(long duration) {
+ public long toDays(long duration) {
throw new AbstractMethodError();
}
diff --git a/concurrent/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java b/concurrent/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java
index ba60556..c774d21 100644
--- a/concurrent/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java
+++ b/concurrent/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java
@@ -21,10 +21,7 @@ import sun.misc.Unsafe;
public class AtomicBoolean implements java.io.Serializable {
private static final long serialVersionUID = 4654671469794556979L;
// setup to use Unsafe.compareAndSwapInt for updates
- // BEGIN android-changed
- private static final Unsafe unsafe = UnsafeAccess.THE_ONE;
- // END android-changed
-
+ private static final Unsafe unsafe = UnsafeAccess.THE_ONE; // android-changed
private static final long valueOffset;
static {
@@ -103,6 +100,17 @@ public class AtomicBoolean implements java.io.Serializable {
}
/**
+ * Eventually sets to the given value.
+ *
+ * @param newValue the new value
+ * @since 1.6
+ */
+ public final void lazySet(boolean newValue) {
+ int v = newValue ? 1 : 0;
+ unsafe.putOrderedInt(this, valueOffset, v);
+ }
+
+ /**
* Atomically sets to the given value and returns the previous value.
*
* @param newValue the new value
diff --git a/concurrent/src/main/java/java/util/concurrent/atomic/AtomicInteger.java b/concurrent/src/main/java/java/util/concurrent/atomic/AtomicInteger.java
index 1aa32f4..16dd568 100644
--- a/concurrent/src/main/java/java/util/concurrent/atomic/AtomicInteger.java
+++ b/concurrent/src/main/java/java/util/concurrent/atomic/AtomicInteger.java
@@ -24,9 +24,7 @@ public class AtomicInteger extends Number implements java.io.Serializable {
private static final long serialVersionUID = 6214790243416807050L;
// setup to use Unsafe.compareAndSwapInt for updates
- // BEGIN android-changed
- private static final Unsafe unsafe = UnsafeAccess.THE_ONE;
- // END android-changed
+ private static final Unsafe unsafe = UnsafeAccess.THE_ONE; // android-changed
private static final long valueOffset;
static {
@@ -72,6 +70,16 @@ public class AtomicInteger extends Number implements java.io.Serializable {
}
/**
+ * Eventually sets to the given value.
+ *
+ * @param newValue the new value
+ * @since 1.6
+ */
+ public final void lazySet(int newValue) {
+ unsafe.putOrderedInt(this, valueOffset, newValue);
+ }
+
+ /**
* Atomically sets to the given value and returns the old value.
*
* @param newValue the new value
diff --git a/concurrent/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java b/concurrent/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java
index 312c76d..b6d6cc5 100644
--- a/concurrent/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java
+++ b/concurrent/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java
@@ -19,33 +19,30 @@ import java.util.*;
public class AtomicIntegerArray implements java.io.Serializable {
private static final long serialVersionUID = 2862133569453604235L;
- // setup to use Unsafe.compareAndSwapInt for updates
- // BEGIN android-changed
- private static final Unsafe unsafe = UnsafeAccess.THE_ONE;
- // END android-changed
+ private static final Unsafe unsafe = UnsafeAccess.THE_ONE; // android-changed
private static final int base = unsafe.arrayBaseOffset(int[].class);
private static final int scale = unsafe.arrayIndexScale(int[].class);
private final int[] array;
- private long rawIndex(int i) {
+ private long checkedByteOffset(int i) {
if (i < 0 || i >= array.length)
throw new IndexOutOfBoundsException("index " + i);
- // BEGIN android-changed
- // avoid memory corruption
+
+ return byteOffset(i);
+ }
+
+ private static long byteOffset(int i) {
return base + (long) i * scale;
- // END android-changed
}
/**
- * Creates a new AtomicIntegerArray of given length.
+ * Creates a new AtomicIntegerArray of the given length, with all
+ * elements initially zero.
*
* @param length the length of the array
*/
public AtomicIntegerArray(int length) {
array = new int[length];
- // must perform at least one volatile write to conform to JMM
- if (length > 0)
- unsafe.putIntVolatile(array, rawIndex(0), 0);
}
/**
@@ -56,17 +53,8 @@ public class AtomicIntegerArray implements java.io.Serializable {
* @throws NullPointerException if array is null
*/
public AtomicIntegerArray(int[] array) {
- if (array == null)
- throw new NullPointerException();
- int length = array.length;
- this.array = new int[length];
- if (length > 0) {
- int last = length-1;
- for (int i = 0; i < last; ++i)
- this.array[i] = array[i];
- // Do the last write as volatile
- unsafe.putIntVolatile(this.array, rawIndex(last), array[last]);
- }
+ // Visibility guaranteed by final field guarantees
+ this.array = array.clone();
}
/**
@@ -85,7 +73,11 @@ public class AtomicIntegerArray implements java.io.Serializable {
* @return the current value
*/
public final int get(int i) {
- return unsafe.getIntVolatile(array, rawIndex(i));
+ return getRaw(checkedByteOffset(i));
+ }
+
+ private int getRaw(long offset) {
+ return unsafe.getIntVolatile(array, offset);
}
/**
@@ -95,7 +87,18 @@ public class AtomicIntegerArray implements java.io.Serializable {
* @param newValue the new value
*/
public final void set(int i, int newValue) {
- unsafe.putIntVolatile(array, rawIndex(i), newValue);
+ unsafe.putIntVolatile(array, checkedByteOffset(i), newValue);
+ }
+
+ /**
+ * Eventually sets the element at position {@code i} to the given value.
+ *
+ * @param i the index
+ * @param newValue the new value
+ * @since 1.6
+ */
+ public final void lazySet(int i, int newValue) {
+ unsafe.putOrderedInt(array, checkedByteOffset(i), newValue);
}
/**
@@ -107,9 +110,10 @@ public class AtomicIntegerArray implements java.io.Serializable {
* @return the previous value
*/
public final int getAndSet(int i, int newValue) {
+ long offset = checkedByteOffset(i);
while (true) {
- int current = get(i);
- if (compareAndSet(i, current, newValue))
+ int current = getRaw(offset);
+ if (compareAndSetRaw(offset, current, newValue))
return current;
}
}
@@ -125,8 +129,11 @@ public class AtomicIntegerArray implements java.io.Serializable {
* the actual value was not equal to the expected value.
*/
public final boolean compareAndSet(int i, int expect, int update) {
- return unsafe.compareAndSwapInt(array, rawIndex(i),
- expect, update);
+ return compareAndSetRaw(checkedByteOffset(i), expect, update);
+ }
+
+ private boolean compareAndSetRaw(long offset, int expect, int update) {
+ return unsafe.compareAndSwapInt(array, offset, expect, update);
}
/**
@@ -153,12 +160,7 @@ public class AtomicIntegerArray implements java.io.Serializable {
* @return the previous value
*/
public final int getAndIncrement(int i) {
- while (true) {
- int current = get(i);
- int next = current + 1;
- if (compareAndSet(i, current, next))
- return current;
- }
+ return getAndAdd(i, 1);
}
/**
@@ -168,12 +170,7 @@ public class AtomicIntegerArray implements java.io.Serializable {
* @return the previous value
*/
public final int getAndDecrement(int i) {
- while (true) {
- int current = get(i);
- int next = current - 1;
- if (compareAndSet(i, current, next))
- return current;
- }
+ return getAndAdd(i, -1);
}
/**
@@ -184,10 +181,10 @@ public class AtomicIntegerArray implements java.io.Serializable {
* @return the previous value
*/
public final int getAndAdd(int i, int delta) {
+ long offset = checkedByteOffset(i);
while (true) {
- int current = get(i);
- int next = current + delta;
- if (compareAndSet(i, current, next))
+ int current = getRaw(offset);
+ if (compareAndSetRaw(offset, current, current + delta))
return current;
}
}
@@ -199,12 +196,7 @@ public class AtomicIntegerArray implements java.io.Serializable {
* @return the updated value
*/
public final int incrementAndGet(int i) {
- while (true) {
- int current = get(i);
- int next = current + 1;
- if (compareAndSet(i, current, next))
- return next;
- }
+ return addAndGet(i, 1);
}
/**
@@ -214,12 +206,7 @@ public class AtomicIntegerArray implements java.io.Serializable {
* @return the updated value
*/
public final int decrementAndGet(int i) {
- while (true) {
- int current = get(i);
- int next = current - 1;
- if (compareAndSet(i, current, next))
- return next;
- }
+ return addAndGet(i, -1);
}
/**
@@ -230,22 +217,32 @@ public class AtomicIntegerArray implements java.io.Serializable {
* @return the updated value
*/
public final int addAndGet(int i, int delta) {
+ long offset = checkedByteOffset(i);
while (true) {
- int current = get(i);
+ int current = getRaw(offset);
int next = current + delta;
- if (compareAndSet(i, current, next))
+ if (compareAndSetRaw(offset, current, next))
return next;
}
}
/**
* Returns the String representation of the current values of array.
- * @return the String representation of the current values of array.
+ * @return the String representation of the current values of array
*/
public String toString() {
- if (array.length > 0) // force volatile read
- get(0);
- return Arrays.toString(array);
+ int iMax = array.length - 1;
+ if (iMax == -1)
+ return "[]";
+
+ StringBuilder b = new StringBuilder();
+ b.append('[');
+ for (int i = 0; ; i++) {
+ b.append(getRaw(byteOffset(i)));
+ if (i == iMax)
+ return b.append(']').toString();
+ b.append(", ");
+ }
}
}
diff --git a/concurrent/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java b/concurrent/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
index f8d2c81..476bb0a 100644
--- a/concurrent/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
+++ b/concurrent/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
@@ -5,12 +5,10 @@
*/
package java.util.concurrent.atomic;
+import dalvik.system.VMStack;
import sun.misc.Unsafe;
import java.lang.reflect.*;
-import org.apache.harmony.kernel.vm.VM;
-import dalvik.system.VMStack;
-
/**
* A reflection-based utility that enables atomic updates to
* designated {@code volatile int} fields of designated classes.
@@ -100,6 +98,17 @@ public abstract class AtomicIntegerFieldUpdater<T> {
public abstract void set(T obj, int newValue);
/**
+ * Eventually sets the field of the given object managed by this
+ * updater to the given updated value.
+ *
+ * @param obj An object whose field to set
+ * @param newValue the new value
+ * @since 1.6
+ */
+ public abstract void lazySet(T obj, int newValue);
+
+
+ /**
* Gets the current value held in the field of the given object managed
* by this updater.
*
@@ -226,9 +235,7 @@ public abstract class AtomicIntegerFieldUpdater<T> {
* Standard hotspot implementation using intrinsics
*/
private static class AtomicIntegerFieldUpdaterImpl<T> extends AtomicIntegerFieldUpdater<T> {
- // BEGIN android-changed
- private static final Unsafe unsafe = UnsafeAccess.THE_ONE;
- // END android-changed
+ private static final Unsafe unsafe = UnsafeAccess.THE_ONE; // android-changed
private final long offset;
private final Class<T> tclass;
private final Class cclass;
@@ -244,6 +251,7 @@ public abstract class AtomicIntegerFieldUpdater<T> {
// END android-changed
modifiers = field.getModifiers();
+ // BEGIN android-added
SecurityManager smgr = System.getSecurityManager();
if (smgr != null) {
int type = Modifier.isPublic(modifiers)
@@ -251,6 +259,13 @@ public abstract class AtomicIntegerFieldUpdater<T> {
smgr.checkMemberAccess(tclass, type);
smgr.checkPackageAccess(tclass.getPackage().getName());
}
+ // END android-added
+ // BEGIN android-removed
+ // modifiers = field.getModifiers();
+ // sun.reflect.misc.ReflectUtil.ensureMemberAccess(
+ // caller, tclass, null, modifiers);
+ // sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+ // END android-removed
} catch (Exception ex) {
throw new RuntimeException(ex);
}
@@ -290,6 +305,11 @@ public abstract class AtomicIntegerFieldUpdater<T> {
unsafe.putIntVolatile(obj, offset, newValue);
}
+ public void lazySet(T obj, int newValue) {
+ if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+ unsafe.putOrderedInt(obj, offset, newValue);
+ }
+
public final int get(T obj) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
return unsafe.getIntVolatile(obj, offset);
diff --git a/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLong.java b/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLong.java
index 9b56002..e1f5dc7 100644
--- a/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLong.java
+++ b/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLong.java
@@ -24,9 +24,7 @@ public class AtomicLong extends Number implements java.io.Serializable {
private static final long serialVersionUID = 1927816293512124184L;
// setup to use Unsafe.compareAndSwapLong for updates
- // BEGIN android-changed
- private static final Unsafe unsafe = UnsafeAccess.THE_ONE;
- // END android-changed
+ private static final Unsafe unsafe = UnsafeAccess.THE_ONE; // android-changed
private static final long valueOffset;
/**
@@ -97,6 +95,16 @@ public class AtomicLong extends Number implements java.io.Serializable {
}
/**
+ * Eventually sets to the given value.
+ *
+ * @param newValue the new value
+ * @since 1.6
+ */
+ public final void lazySet(long newValue) {
+ unsafe.putOrderedLong(this, valueOffset, newValue);
+ }
+
+ /**
* Atomically sets to the given value and returns the old value.
*
* @param newValue the new value
diff --git a/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java b/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java
index 187acbc..33e6914 100644
--- a/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java
+++ b/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java
@@ -18,33 +18,30 @@ import java.util.*;
public class AtomicLongArray implements java.io.Serializable {
private static final long serialVersionUID = -2308431214976778248L;
- // setup to use Unsafe.compareAndSwapInt for updates
- // BEGIN android-changed
- private static final Unsafe unsafe = UnsafeAccess.THE_ONE;
- // END android-changed
+ private static final Unsafe unsafe = UnsafeAccess.THE_ONE; // android-changed
private static final int base = unsafe.arrayBaseOffset(long[].class);
private static final int scale = unsafe.arrayIndexScale(long[].class);
private final long[] array;
- private long rawIndex(int i) {
+ private long checkedByteOffset(int i) {
if (i < 0 || i >= array.length)
throw new IndexOutOfBoundsException("index " + i);
- // BEGIN android-changed
- // avoid memory corruption
+
+ return byteOffset(i);
+ }
+
+ private static long byteOffset(int i) {
return base + (long) i * scale;
- // END android-changed
}
/**
- * Creates a new AtomicLongArray of given length.
+ * Creates a new AtomicLongArray of the given length, with all
+ * elements initially zero.
*
* @param length the length of the array
*/
public AtomicLongArray(int length) {
array = new long[length];
- // must perform at least one volatile write to conform to JMM
- if (length > 0)
- unsafe.putLongVolatile(array, rawIndex(0), 0);
}
/**
@@ -55,17 +52,8 @@ public class AtomicLongArray implements java.io.Serializable {
* @throws NullPointerException if array is null
*/
public AtomicLongArray(long[] array) {
- if (array == null)
- throw new NullPointerException();
- int length = array.length;
- this.array = new long[length];
- if (length > 0) {
- int last = length-1;
- for (int i = 0; i < last; ++i)
- this.array[i] = array[i];
- // Do the last write as volatile
- unsafe.putLongVolatile(this.array, rawIndex(last), array[last]);
- }
+ // Visibility guaranteed by final field guarantees
+ this.array = array.clone();
}
/**
@@ -84,7 +72,11 @@ public class AtomicLongArray implements java.io.Serializable {
* @return the current value
*/
public final long get(int i) {
- return unsafe.getLongVolatile(array, rawIndex(i));
+ return getRaw(checkedByteOffset(i));
+ }
+
+ private long getRaw(long offset) {
+ return unsafe.getLongVolatile(array, offset);
}
/**
@@ -94,10 +86,22 @@ public class AtomicLongArray implements java.io.Serializable {
* @param newValue the new value
*/
public final void set(int i, long newValue) {
- unsafe.putLongVolatile(array, rawIndex(i), newValue);
+ unsafe.putLongVolatile(array, checkedByteOffset(i), newValue);
}
/**
+ * Eventually sets the element at position {@code i} to the given value.
+ *
+ * @param i the index
+ * @param newValue the new value
+ * @since 1.6
+ */
+ public final void lazySet(int i, long newValue) {
+ unsafe.putOrderedLong(array, checkedByteOffset(i), newValue);
+ }
+
+
+ /**
* Atomically sets the element at position {@code i} to the given value
* and returns the old value.
*
@@ -106,16 +110,17 @@ public class AtomicLongArray implements java.io.Serializable {
* @return the previous value
*/
public final long getAndSet(int i, long newValue) {
+ long offset = checkedByteOffset(i);
while (true) {
- long current = get(i);
- if (compareAndSet(i, current, newValue))
+ long current = getRaw(offset);
+ if (compareAndSetRaw(offset, current, newValue))
return current;
}
}
/**
- * Atomically sets the value to the given updated value
- * if the current value {@code ==} the expected value.
+ * Atomically sets the element at position {@code i} to the given
+ * updated value if the current value {@code ==} the expected value.
*
* @param i the index
* @param expect the expected value
@@ -124,13 +129,16 @@ public class AtomicLongArray implements java.io.Serializable {
* the actual value was not equal to the expected value.
*/
public final boolean compareAndSet(int i, long expect, long update) {
- return unsafe.compareAndSwapLong(array, rawIndex(i),
- expect, update);
+ return compareAndSetRaw(checkedByteOffset(i), expect, update);
+ }
+
+ private boolean compareAndSetRaw(long offset, long expect, long update) {
+ return unsafe.compareAndSwapLong(array, offset, expect, update);
}
/**
- * Atomically sets the value to the given updated value
- * if the current value {@code ==} the expected value.
+ * Atomically sets the element at position {@code i} to the given
+ * updated value if the current value {@code ==} the expected value.
*
* <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
* and does not provide ordering guarantees, so is only rarely an
@@ -152,12 +160,7 @@ public class AtomicLongArray implements java.io.Serializable {
* @return the previous value
*/
public final long getAndIncrement(int i) {
- while (true) {
- long current = get(i);
- long next = current + 1;
- if (compareAndSet(i, current, next))
- return current;
- }
+ return getAndAdd(i, 1);
}
/**
@@ -167,12 +170,7 @@ public class AtomicLongArray implements java.io.Serializable {
* @return the previous value
*/
public final long getAndDecrement(int i) {
- while (true) {
- long current = get(i);
- long next = current - 1;
- if (compareAndSet(i, current, next))
- return current;
- }
+ return getAndAdd(i, -1);
}
/**
@@ -183,10 +181,10 @@ public class AtomicLongArray implements java.io.Serializable {
* @return the previous value
*/
public final long getAndAdd(int i, long delta) {
+ long offset = checkedByteOffset(i);
while (true) {
- long current = get(i);
- long next = current + delta;
- if (compareAndSet(i, current, next))
+ long current = getRaw(offset);
+ if (compareAndSetRaw(offset, current, current + delta))
return current;
}
}
@@ -198,12 +196,7 @@ public class AtomicLongArray implements java.io.Serializable {
* @return the updated value
*/
public final long incrementAndGet(int i) {
- while (true) {
- long current = get(i);
- long next = current + 1;
- if (compareAndSet(i, current, next))
- return next;
- }
+ return addAndGet(i, 1);
}
/**
@@ -213,12 +206,7 @@ public class AtomicLongArray implements java.io.Serializable {
* @return the updated value
*/
public final long decrementAndGet(int i) {
- while (true) {
- long current = get(i);
- long next = current - 1;
- if (compareAndSet(i, current, next))
- return next;
- }
+ return addAndGet(i, -1);
}
/**
@@ -229,22 +217,32 @@ public class AtomicLongArray implements java.io.Serializable {
* @return the updated value
*/
public long addAndGet(int i, long delta) {
+ long offset = checkedByteOffset(i);
while (true) {
- long current = get(i);
+ long current = getRaw(offset);
long next = current + delta;
- if (compareAndSet(i, current, next))
+ if (compareAndSetRaw(offset, current, next))
return next;
}
}
/**
* Returns the String representation of the current values of array.
- * @return the String representation of the current values of array.
+ * @return the String representation of the current values of array
*/
public String toString() {
- if (array.length > 0) // force volatile read
- get(0);
- return Arrays.toString(array);
+ int iMax = array.length - 1;
+ if (iMax == -1)
+ return "[]";
+
+ StringBuilder b = new StringBuilder();
+ b.append('[');
+ for (int i = 0; ; i++) {
+ b.append(getRaw(byteOffset(i)));
+ if (i == iMax)
+ return b.append(']').toString();
+ b.append(", ");
+ }
}
}
diff --git a/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java b/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
index d97c2e4..427a9e1 100644
--- a/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
+++ b/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
@@ -5,12 +5,10 @@
*/
package java.util.concurrent.atomic;
+import dalvik.system.VMStack;
import sun.misc.Unsafe;
import java.lang.reflect.*;
-import org.apache.harmony.kernel.vm.VM;
-import dalvik.system.VMStack;
-
/**
* A reflection-based utility that enables atomic updates to
* designated {@code volatile long} fields of designated classes.
@@ -103,6 +101,16 @@ public abstract class AtomicLongFieldUpdater<T> {
public abstract void set(T obj, long newValue);
/**
+ * Eventually sets the field of the given object managed by this
+ * updater to the given updated value.
+ *
+ * @param obj An object whose field to set
+ * @param newValue the new value
+ * @since 1.6
+ */
+ public abstract void lazySet(T obj, long newValue);
+
+ /**
* Gets the current value held in the field of the given object managed
* by this updater.
*
@@ -226,9 +234,7 @@ public abstract class AtomicLongFieldUpdater<T> {
}
private static class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
- // BEGIN android-changed
- private static final Unsafe unsafe = UnsafeAccess.THE_ONE;
- // END android-changed
+ private static final Unsafe unsafe = UnsafeAccess.THE_ONE; // android-changed
private final long offset;
private final Class<T> tclass;
private final Class cclass;
@@ -239,10 +245,9 @@ public abstract class AtomicLongFieldUpdater<T> {
int modifiers = 0;
try {
field = tclass.getDeclaredField(fieldName);
- // BEGIN android-changed
- caller = VMStack.getStackClass2();
- // END android-changed
+ caller = VMStack.getStackClass2(); // android-changed
modifiers = field.getModifiers();
+ // BEGIN android-added
SecurityManager smgr = System.getSecurityManager();
if (smgr != null) {
int type = Modifier.isPublic(modifiers)
@@ -250,6 +255,12 @@ public abstract class AtomicLongFieldUpdater<T> {
smgr.checkMemberAccess(tclass, type);
smgr.checkPackageAccess(tclass.getPackage().getName());
}
+ // END android-added
+ // BEGIN android-removed
+ // sun.reflect.misc.ReflectUtil.ensureMemberAccess(
+ // caller, tclass, null, modifiers);
+ // sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+ // END android-removed
} catch (Exception ex) {
throw new RuntimeException(ex);
}
@@ -289,6 +300,11 @@ public abstract class AtomicLongFieldUpdater<T> {
unsafe.putLongVolatile(obj, offset, newValue);
}
+ public void lazySet(T obj, long newValue) {
+ if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+ unsafe.putOrderedLong(obj, offset, newValue);
+ }
+
public long get(T obj) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
return unsafe.getLongVolatile(obj, offset);
@@ -312,9 +328,7 @@ public abstract class AtomicLongFieldUpdater<T> {
private static class LockedUpdater<T> extends AtomicLongFieldUpdater<T> {
- // BEGIN android-changed
- private static final Unsafe unsafe = UnsafeAccess.THE_ONE;
- // END android-changed
+ private static final Unsafe unsafe = UnsafeAccess.THE_ONE; // android-changed
private final long offset;
private final Class<T> tclass;
private final Class cclass;
@@ -325,10 +339,9 @@ public abstract class AtomicLongFieldUpdater<T> {
int modifiers = 0;
try {
field = tclass.getDeclaredField(fieldName);
- // BEGIN android-changed
- caller = VMStack.getStackClass2();
- // END android-changed
+ caller = VMStack.getStackClass2(); // android-changed
modifiers = field.getModifiers();
+ // BEGIN android-added
SecurityManager smgr = System.getSecurityManager();
if (smgr != null) {
int type = Modifier.isPublic(modifiers)
@@ -336,6 +349,12 @@ public abstract class AtomicLongFieldUpdater<T> {
smgr.checkMemberAccess(tclass, type);
smgr.checkPackageAccess(tclass.getPackage().getName());
}
+ // END android-added
+ // BEGIN android-removed
+ // sun.reflect.misc.ReflectUtil.ensureMemberAccess(
+ // caller, tclass, null, modifiers);
+ // sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+ // END android-removed
} catch (Exception ex) {
throw new RuntimeException(ex);
}
diff --git a/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReference.java b/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReference.java
index 1de9b1c..f041bbd 100644
--- a/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReference.java
+++ b/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReference.java
@@ -18,9 +18,7 @@ import sun.misc.Unsafe;
public class AtomicReference<V> implements java.io.Serializable {
private static final long serialVersionUID = -1848883965231344442L;
- // BEGIN android-changed
- private static final Unsafe unsafe = UnsafeAccess.THE_ONE;
- // END android-changed
+ private static final Unsafe unsafe = UnsafeAccess.THE_ONE; // android-changed
private static final long valueOffset;
static {
@@ -66,6 +64,16 @@ public class AtomicReference<V> implements java.io.Serializable {
}
/**
+ * Eventually sets to the given value.
+ *
+ * @param newValue the new value
+ * @since 1.6
+ */
+ public final void lazySet(V newValue) {
+ unsafe.putOrderedObject(this, valueOffset, newValue);
+ }
+
+ /**
* Atomically sets the value to the given updated value
* if the current value {@code ==} the expected value.
* @param expect the expected value
diff --git a/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java b/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java
index fff6a1e..2501c2b 100644
--- a/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java
+++ b/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java
@@ -20,31 +20,30 @@ import java.util.*;
public class AtomicReferenceArray<E> implements java.io.Serializable {
private static final long serialVersionUID = -6209656149925076980L;
- // BEGIN android-changed
- private static final Unsafe unsafe = UnsafeAccess.THE_ONE;
- // END android-changed
+ private static final Unsafe unsafe = UnsafeAccess.THE_ONE; // android-changed
private static final int base = unsafe.arrayBaseOffset(Object[].class);
private static final int scale = unsafe.arrayIndexScale(Object[].class);
private final Object[] array;
- private long rawIndex(int i) {
+ private long checkedByteOffset(int i) {
if (i < 0 || i >= array.length)
throw new IndexOutOfBoundsException("index " + i);
- // BEGIN android-changed
- // avoid memory corruption
+
+ return byteOffset(i);
+ }
+
+ private static long byteOffset(int i) {
return base + (long) i * scale;
- // END android-changed
}
/**
- * Creates a new AtomicReferenceArray of given length.
+ * Creates a new AtomicReferenceArray of the given length, with all
+ * elements initially zero.
+ *
* @param length the length of the array
*/
public AtomicReferenceArray(int length) {
array = new Object[length];
- // must perform at least one volatile write to conform to JMM
- if (length > 0)
- unsafe.putObjectVolatile(array, rawIndex(0), null);
}
/**
@@ -55,18 +54,8 @@ public class AtomicReferenceArray<E> implements java.io.Serializable {
* @throws NullPointerException if array is null
*/
public AtomicReferenceArray(E[] array) {
- if (array == null)
- throw new NullPointerException();
- int length = array.length;
- this.array = new Object[length];
- if (length > 0) {
- int last = length-1;
- for (int i = 0; i < last; ++i)
- this.array[i] = array[i];
- // Do the last write as volatile
- E e = array[last];
- unsafe.putObjectVolatile(this.array, rawIndex(last), e);
- }
+ // Visibility guaranteed by final field guarantees
+ this.array = array.clone();
}
/**
@@ -85,7 +74,11 @@ public class AtomicReferenceArray<E> implements java.io.Serializable {
* @return the current value
*/
public final E get(int i) {
- return (E) unsafe.getObjectVolatile(array, rawIndex(i));
+ return getRaw(checkedByteOffset(i));
+ }
+
+ private E getRaw(long offset) {
+ return (E) unsafe.getObjectVolatile(array, offset);
}
/**
@@ -95,9 +88,21 @@ public class AtomicReferenceArray<E> implements java.io.Serializable {
* @param newValue the new value
*/
public final void set(int i, E newValue) {
- unsafe.putObjectVolatile(array, rawIndex(i), newValue);
+ unsafe.putObjectVolatile(array, checkedByteOffset(i), newValue);
+ }
+
+ /**
+ * Eventually sets the element at position {@code i} to the given value.
+ *
+ * @param i the index
+ * @param newValue the new value
+ * @since 1.6
+ */
+ public final void lazySet(int i, E newValue) {
+ unsafe.putOrderedObject(array, checkedByteOffset(i), newValue);
}
+
/**
* Atomically sets the element at position {@code i} to the given
* value and returns the old value.
@@ -107,9 +112,10 @@ public class AtomicReferenceArray<E> implements java.io.Serializable {
* @return the previous value
*/
public final E getAndSet(int i, E newValue) {
+ long offset = checkedByteOffset(i);
while (true) {
- E current = get(i);
- if (compareAndSet(i, current, newValue))
+ E current = (E) getRaw(offset);
+ if (compareAndSetRaw(offset, current, newValue))
return current;
}
}
@@ -117,6 +123,7 @@ public class AtomicReferenceArray<E> implements java.io.Serializable {
/**
* Atomically sets the element at position {@code i} to the given
* updated value if the current value {@code ==} the expected value.
+ *
* @param i the index
* @param expect the expected value
* @param update the new value
@@ -124,8 +131,11 @@ public class AtomicReferenceArray<E> implements java.io.Serializable {
* the actual value was not equal to the expected value.
*/
public final boolean compareAndSet(int i, E expect, E update) {
- return unsafe.compareAndSwapObject(array, rawIndex(i),
- expect, update);
+ return compareAndSetRaw(checkedByteOffset(i), expect, update);
+ }
+
+ private boolean compareAndSetRaw(long offset, E expect, E update) {
+ return unsafe.compareAndSwapObject(array, offset, expect, update);
}
/**
@@ -147,12 +157,21 @@ public class AtomicReferenceArray<E> implements java.io.Serializable {
/**
* Returns the String representation of the current values of array.
- * @return the String representation of the current values of array.
+ * @return the String representation of the current values of array
*/
public String toString() {
- if (array.length > 0) // force volatile read
- get(0);
- return Arrays.toString(array);
+ int iMax = array.length - 1;
+ if (iMax == -1)
+ return "[]";
+
+ StringBuilder b = new StringBuilder();
+ b.append('[');
+ for (int i = 0; ; i++) {
+ b.append(getRaw(byteOffset(i)));
+ if (i == iMax)
+ return b.append(']').toString();
+ b.append(", ");
+ }
}
}
diff --git a/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
index fae134f..e53f2e9 100644
--- a/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
+++ b/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
@@ -5,12 +5,10 @@
*/
package java.util.concurrent.atomic;
+import dalvik.system.VMStack;
import sun.misc.Unsafe;
import java.lang.reflect.*;
-import org.apache.harmony.kernel.vm.VM;
-import dalvik.system.VMStack;
-
/**
* A reflection-based utility that enables atomic updates to
* designated {@code volatile} reference fields of designated
@@ -118,6 +116,16 @@ public abstract class AtomicReferenceFieldUpdater<T, V> {
public abstract void set(T obj, V newValue);
/**
+ * Eventually sets the field of the given object managed by this
+ * updater to the given updated value.
+ *
+ * @param obj An object whose field to set
+ * @param newValue the new value
+ * @since 1.6
+ */
+ public abstract void lazySet(T obj, V newValue);
+
+ /**
* Gets the current value held in the field of the given object managed
* by this updater.
*
@@ -144,9 +152,7 @@ public abstract class AtomicReferenceFieldUpdater<T, V> {
private static final class AtomicReferenceFieldUpdaterImpl<T,V>
extends AtomicReferenceFieldUpdater<T,V> {
- // BEGIN android-changed
- private static final Unsafe unsafe = UnsafeAccess.THE_ONE;
- // END android-changed
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
private final long offset;
private final Class<T> tclass;
private final Class<V> vclass;
@@ -173,10 +179,9 @@ public abstract class AtomicReferenceFieldUpdater<T, V> {
int modifiers = 0;
try {
field = tclass.getDeclaredField(fieldName);
- // BEGIN android-changed
- caller = VMStack.getStackClass2();
- // END android-changed
+ caller = VMStack.getStackClass2(); // android-changed
modifiers = field.getModifiers();
+ // BEGIN android-added
SecurityManager smgr = System.getSecurityManager();
if (smgr != null) {
int type = Modifier.isPublic(modifiers)
@@ -184,6 +189,12 @@ public abstract class AtomicReferenceFieldUpdater<T, V> {
smgr.checkMemberAccess(tclass, type);
smgr.checkPackageAccess(tclass.getPackage().getName());
}
+ // END android-added
+ // BEGIN android-removed
+ // sun.reflect.misc.ReflectUtil.ensureMemberAccess(
+ // caller, tclass, null, modifiers);
+ // sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+ // END android-removed
fieldClass = field.getType();
} catch (Exception ex) {
throw new RuntimeException(ex);
@@ -245,6 +256,14 @@ public abstract class AtomicReferenceFieldUpdater<T, V> {
unsafe.putObjectVolatile(obj, offset, newValue);
}
+ public void lazySet(T obj, V newValue) {
+ if (obj == null || obj.getClass() != tclass || cclass != null ||
+ (newValue != null && vclass != null &&
+ vclass != newValue.getClass()))
+ updateCheck(obj, newValue);
+ unsafe.putOrderedObject(obj, offset, newValue);
+ }
+
public V get(T obj) {
if (obj == null || obj.getClass() != tclass || cclass != null)
targetCheck(obj);
diff --git a/concurrent/src/main/java/java/util/concurrent/atomic/package-info.java b/concurrent/src/main/java/java/util/concurrent/atomic/package-info.java
index 2252e5c..4a4375d 100644
--- a/concurrent/src/main/java/java/util/concurrent/atomic/package-info.java
+++ b/concurrent/src/main/java/java/util/concurrent/atomic/package-info.java
@@ -63,6 +63,14 @@
* <li> {@code set} has the memory effects of writing (assigning) a
* {@code volatile} variable.
*
+ * <li> {@code lazySet} has the memory effects of writing (assigning)
+ * a {@code volatile} variable except that it permits reorderings with
+ * subsequent (but not previous) memory actions that do not themselves
+ * impose reordering constraints with ordinary non-{@code volatile}
+ * writes. Among other usage contexts, {@code lazySet} may apply when
+ * nulling out, for the sake of garbage collection, a reference that is
+ * never accessed again.
+ *
* <li>{@code weakCompareAndSet} atomically reads and conditionally
* writes a variable but does <em>not</em>
* create any happens-before orderings, so provides no guarantees
diff --git a/concurrent/src/main/java/java/util/concurrent/locks/AbstractOwnableSynchronizer.java b/concurrent/src/main/java/java/util/concurrent/locks/AbstractOwnableSynchronizer.java
index bf2fe16..f3780e5 100644
--- a/concurrent/src/main/java/java/util/concurrent/locks/AbstractOwnableSynchronizer.java
+++ b/concurrent/src/main/java/java/util/concurrent/locks/AbstractOwnableSynchronizer.java
@@ -15,10 +15,11 @@ package java.util.concurrent.locks;
* appropriately maintained values to help control and monitor access
* and provide diagnostics.
*
+ * @since 1.6
* @author Doug Lea
*/
-abstract class AbstractOwnableSynchronizer
- implements java.io.Serializable {
+public abstract class AbstractOwnableSynchronizer
+ implements java.io.Serializable {
/** Use serial ID even though all fields transient. */
private static final long serialVersionUID = 3737899427754241961L;
@@ -53,4 +54,4 @@ abstract class AbstractOwnableSynchronizer
protected final Thread getExclusiveOwnerThread() {
return exclusiveOwnerThread;
}
-} \ No newline at end of file
+}
diff --git a/concurrent/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java b/concurrent/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java
new file mode 100644
index 0000000..d805259
--- /dev/null
+++ b/concurrent/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java
@@ -0,0 +1,2073 @@
+/*
+ * 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.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+import sun.misc.Unsafe;
+
+/**
+ * A version of {@link AbstractQueuedSynchronizer} in
+ * which synchronization state is maintained as a <tt>long</tt>.
+ * This class has exactly the same structure, properties, and methods
+ * as <tt>AbstractQueuedSynchronizer</tt> with the exception
+ * that all state-related parameters and results are defined
+ * as <tt>long</tt> rather than <tt>int</tt>. This class
+ * may be useful when creating synchronizers such as
+ * multilevel locks and barriers that require
+ * 64 bits of state.
+ *
+ * <p>See {@link AbstractQueuedSynchronizer} for usage
+ * notes and examples.
+ *
+ * @since 1.6
+ * @author Doug Lea
+ */
+public abstract class AbstractQueuedLongSynchronizer
+ extends AbstractOwnableSynchronizer
+ implements java.io.Serializable {
+
+ private static final long serialVersionUID = 7373984972572414692L;
+
+ /*
+ To keep sources in sync, the remainder of this source file is
+ exactly cloned from AbstractQueuedSynchronizer, replacing class
+ name and changing ints related with sync state to longs. Please
+ keep it that way.
+ */
+
+ /**
+ * Creates a new <tt>AbstractQueuedLongSynchronizer</tt> instance
+ * with initial synchronization state of zero.
+ */
+ protected AbstractQueuedLongSynchronizer() { }
+
+ /**
+ * Wait queue node class.
+ *
+ * <p>The wait queue is a variant of a "CLH" (Craig, Landin, and
+ * Hagersten) lock queue. CLH locks are normally used for
+ * spinlocks. We instead use them for blocking synchronizers, but
+ * use the same basic tactic of holding some of the control
+ * information about a thread in the predecessor of its node. A
+ * "status" field in each node keeps track of whether a thread
+ * should block. A node is signalled when its predecessor
+ * releases. Each node of the queue otherwise serves as a
+ * specific-notification-style monitor holding a single waiting
+ * thread. The status field does NOT control whether threads are
+ * granted locks etc though. A thread may try to acquire if it is
+ * first in the queue. But being first does not guarantee success;
+ * it only gives the right to contend. So the currently released
+ * contender thread may need to rewait.
+ *
+ * <p>To enqueue into a CLH lock, you atomically splice it in as new
+ * tail. To dequeue, you just set the head field.
+ * <pre>
+ * +------+ prev +-----+ +-----+
+ * head | | <---- | | <---- | | tail
+ * +------+ +-----+ +-----+
+ * </pre>
+ *
+ * <p>Insertion into a CLH queue requires only a single atomic
+ * operation on "tail", so there is a simple atomic point of
+ * demarcation from unqueued to queued. Similarly, dequeing
+ * involves only updating the "head". However, it takes a bit
+ * more work for nodes to determine who their successors are,
+ * in part to deal with possible cancellation due to timeouts
+ * and interrupts.
+ *
+ * <p>The "prev" links (not used in original CLH locks), are mainly
+ * needed to handle cancellation. If a node is cancelled, its
+ * successor is (normally) relinked to a non-cancelled
+ * predecessor. For explanation of similar mechanics in the case
+ * of spin locks, see the papers by Scott and Scherer at
+ * http://www.cs.rochester.edu/u/scott/synchronization/
+ *
+ * <p>We also use "next" links to implement blocking mechanics.
+ * The thread id for each node is kept in its own node, so a
+ * predecessor signals the next node to wake up by traversing
+ * next link to determine which thread it is. Determination of
+ * successor must avoid races with newly queued nodes to set
+ * the "next" fields of their predecessors. This is solved
+ * when necessary by checking backwards from the atomically
+ * updated "tail" when a node's successor appears to be null.
+ * (Or, said differently, the next-links are an optimization
+ * so that we don't usually need a backward scan.)
+ *
+ * <p>Cancellation introduces some conservatism to the basic
+ * algorithms. Since we must poll for cancellation of other
+ * nodes, we can miss noticing whether a cancelled node is
+ * ahead or behind us. This is dealt with by always unparking
+ * successors upon cancellation, allowing them to stabilize on
+ * a new predecessor, unless we can identify an uncancelled
+ * predecessor who will carry this responsibility.
+ *
+ * <p>CLH queues need a dummy header node to get started. But
+ * we don't create them on construction, because it would be wasted
+ * effort if there is never contention. Instead, the node
+ * is constructed and head and tail pointers are set upon first
+ * contention.
+ *
+ * <p>Threads waiting on Conditions use the same nodes, but
+ * use an additional link. Conditions only need to link nodes
+ * in simple (non-concurrent) linked queues because they are
+ * only accessed when exclusively held. Upon await, a node is
+ * inserted into a condition queue. Upon signal, the node is
+ * transferred to the main queue. A special value of status
+ * field is used to mark which queue a node is on.
+ *
+ * <p>Thanks go to Dave Dice, Mark Moir, Victor Luchangco, Bill
+ * Scherer and Michael Scott, along with members of JSR-166
+ * expert group, for helpful ideas, discussions, and critiques
+ * on the design of this class.
+ */
+ static final class Node {
+ /** Marker to indicate a node is waiting in shared mode */
+ static final Node SHARED = new Node();
+ /** Marker to indicate a node is waiting in exclusive mode */
+ static final Node EXCLUSIVE = null;
+
+ /** waitStatus value to indicate thread has cancelled */
+ static final int CANCELLED = 1;
+ /** waitStatus value to indicate successor's thread needs unparking */
+ static final int SIGNAL = -1;
+ /** waitStatus value to indicate thread is waiting on condition */
+ static final int CONDITION = -2;
+ /**
+ * waitStatus value to indicate the next acquireShared should
+ * unconditionally propagate
+ */
+ static final int PROPAGATE = -3;
+
+ /**
+ * Status field, taking on only the values:
+ * SIGNAL: The successor of this node is (or will soon be)
+ * blocked (via park), so the current node must
+ * unpark its successor when it releases or
+ * cancels. To avoid races, acquire methods must
+ * first indicate they need a signal,
+ * then retry the atomic acquire, and then,
+ * on failure, block.
+ * CANCELLED: This node is cancelled due to timeout or interrupt.
+ * Nodes never leave this state. In particular,
+ * a thread with cancelled node never again blocks.
+ * CONDITION: This node is currently on a condition queue.
+ * It will not be used as a sync queue node
+ * until transferred, at which time the status
+ * will be set to 0. (Use of this value here has
+ * nothing to do with the other uses of the
+ * field, but simplifies mechanics.)
+ * PROPAGATE: A releaseShared should be propagated to other
+ * nodes. This is set (for head node only) in
+ * doReleaseShared to ensure propagation
+ * continues, even if other operations have
+ * since intervened.
+ * 0: None of the above
+ *
+ * The values are arranged numerically to simplify use.
+ * Non-negative values mean that a node doesn't need to
+ * signal. So, most code doesn't need to check for particular
+ * values, just for sign.
+ *
+ * The field is initialized to 0 for normal sync nodes, and
+ * CONDITION for condition nodes. It is modified using CAS
+ * (or when possible, unconditional volatile writes).
+ */
+ volatile int waitStatus;
+
+ /**
+ * Link to predecessor node that current node/thread relies on
+ * for checking waitStatus. Assigned during enqueing, and nulled
+ * out (for sake of GC) only upon dequeuing. Also, upon
+ * cancellation of a predecessor, we short-circuit while
+ * finding a non-cancelled one, which will always exist
+ * because the head node is never cancelled: A node becomes
+ * head only as a result of successful acquire. A
+ * cancelled thread never succeeds in acquiring, and a thread only
+ * cancels itself, not any other node.
+ */
+ volatile Node prev;
+
+ /**
+ * Link to the successor node that the current node/thread
+ * unparks upon release. Assigned during enqueuing, adjusted
+ * when bypassing cancelled predecessors, and nulled out (for
+ * sake of GC) when dequeued. The enq operation does not
+ * assign next field of a predecessor until after attachment,
+ * so seeing a null next field does not necessarily mean that
+ * node is at end of queue. However, if a next field appears
+ * to be null, we can scan prev's from the tail to
+ * double-check. The next field of cancelled nodes is set to
+ * point to the node itself instead of null, to make life
+ * easier for isOnSyncQueue.
+ */
+ volatile Node next;
+
+ /**
+ * The thread that enqueued this node. Initialized on
+ * construction and nulled out after use.
+ */
+ volatile Thread thread;
+
+ /**
+ * Link to next node waiting on condition, or the special
+ * value SHARED. Because condition queues are accessed only
+ * when holding in exclusive mode, we just need a simple
+ * linked queue to hold nodes while they are waiting on
+ * conditions. They are then transferred to the queue to
+ * re-acquire. And because conditions can only be exclusive,
+ * we save a field by using special value to indicate shared
+ * mode.
+ */
+ Node nextWaiter;
+
+ /**
+ * Returns true if node is waiting in shared mode
+ */
+ final boolean isShared() {
+ return nextWaiter == SHARED;
+ }
+
+ /**
+ * Returns previous node, or throws NullPointerException if null.
+ * Use when predecessor cannot be null. The null check could
+ * be elided, but is present to help the VM.
+ *
+ * @return the predecessor of this node
+ */
+ final Node predecessor() throws NullPointerException {
+ Node p = prev;
+ if (p == null)
+ throw new NullPointerException();
+ else
+ return p;
+ }
+
+ Node() { // Used to establish initial head or SHARED marker
+ }
+
+ Node(Thread thread, Node mode) { // Used by addWaiter
+ this.nextWaiter = mode;
+ this.thread = thread;
+ }
+
+ Node(Thread thread, int waitStatus) { // Used by Condition
+ this.waitStatus = waitStatus;
+ this.thread = thread;
+ }
+ }
+
+ /**
+ * Head of the wait queue, lazily initialized. Except for
+ * initialization, it is modified only via method setHead. Note:
+ * If head exists, its waitStatus is guaranteed not to be
+ * CANCELLED.
+ */
+ private transient volatile Node head;
+
+ /**
+ * Tail of the wait queue, lazily initialized. Modified only via
+ * method enq to add new wait node.
+ */
+ private transient volatile Node tail;
+
+ /**
+ * The synchronization state.
+ */
+ private volatile long state;
+
+ /**
+ * Returns the current value of synchronization state.
+ * This operation has memory semantics of a <tt>volatile</tt> read.
+ * @return current state value
+ */
+ protected final long getState() {
+ return state;
+ }
+
+ /**
+ * Sets the value of synchronization state.
+ * This operation has memory semantics of a <tt>volatile</tt> write.
+ * @param newState the new state value
+ */
+ protected final void setState(long newState) {
+ state = newState;
+ }
+
+ /**
+ * Atomically sets synchronization state to the given updated
+ * value if the current state value equals the expected value.
+ * This operation has memory semantics of a <tt>volatile</tt> read
+ * and write.
+ *
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful. False return indicates that the actual
+ * value was not equal to the expected value.
+ */
+ protected final boolean compareAndSetState(long expect, long update) {
+ // See below for intrinsics setup to support this
+ return unsafe.compareAndSwapLong(this, stateOffset, expect, update);
+ }
+
+ // Queuing utilities
+
+ /**
+ * The number of nanoseconds for which it is faster to spin
+ * rather than to use timed park. A rough estimate suffices
+ * to improve responsiveness with very short timeouts.
+ */
+ static final long spinForTimeoutThreshold = 1000L;
+
+ /**
+ * Inserts node into queue, initializing if necessary. See picture above.
+ * @param node the node to insert
+ * @return node's predecessor
+ */
+ private Node enq(final Node node) {
+ for (;;) {
+ Node t = tail;
+ if (t == null) { // Must initialize
+ if (compareAndSetHead(new Node()))
+ tail = head;
+ } else {
+ node.prev = t;
+ if (compareAndSetTail(t, node)) {
+ t.next = node;
+ return t;
+ }
+ }
+ }
+ }
+
+ /**
+ * Creates and enqueues node for current thread and given mode.
+ *
+ * @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared
+ * @return the new node
+ */
+ private Node addWaiter(Node mode) {
+ Node node = new Node(Thread.currentThread(), mode);
+ // Try the fast path of enq; backup to full enq on failure
+ Node pred = tail;
+ if (pred != null) {
+ node.prev = pred;
+ if (compareAndSetTail(pred, node)) {
+ pred.next = node;
+ return node;
+ }
+ }
+ enq(node);
+ return node;
+ }
+
+ /**
+ * Sets head of queue to be node, thus dequeuing. Called only by
+ * acquire methods. Also nulls out unused fields for sake of GC
+ * and to suppress unnecessary signals and traversals.
+ *
+ * @param node the node
+ */
+ private void setHead(Node node) {
+ head = node;
+ node.thread = null;
+ node.prev = null;
+ }
+
+ /**
+ * Wakes up node's successor, if one exists.
+ *
+ * @param node the node
+ */
+ private void unparkSuccessor(Node node) {
+ /*
+ * If status is negative (i.e., possibly needing signal) try
+ * to clear in anticipation of signalling. It is OK if this
+ * fails or if status is changed by waiting thread.
+ */
+ int ws = node.waitStatus;
+ if (ws < 0)
+ compareAndSetWaitStatus(node, ws, 0);
+
+ /*
+ * Thread to unpark is held in successor, which is normally
+ * just the next node. But if cancelled or apparently null,
+ * traverse backwards from tail to find the actual
+ * non-cancelled successor.
+ */
+ Node s = node.next;
+ if (s == null || s.waitStatus > 0) {
+ s = null;
+ for (Node t = tail; t != null && t != node; t = t.prev)
+ if (t.waitStatus <= 0)
+ s = t;
+ }
+ if (s != null)
+ LockSupport.unpark(s.thread);
+ }
+
+ /**
+ * Release action for shared mode -- signal successor and ensure
+ * propagation. (Note: For exclusive mode, release just amounts
+ * to calling unparkSuccessor of head if it needs signal.)
+ */
+ private void doReleaseShared() {
+ /*
+ * Ensure that a release propagates, even if there are other
+ * in-progress acquires/releases. This proceeds in the usual
+ * way of trying to unparkSuccessor of head if it needs
+ * signal. But if it does not, status is set to PROPAGATE to
+ * ensure that upon release, propagation continues.
+ * Additionally, we must loop in case a new node is added
+ * while we are doing this. Also, unlike other uses of
+ * unparkSuccessor, we need to know if CAS to reset status
+ * fails, if so rechecking.
+ */
+ for (;;) {
+ Node h = head;
+ if (h != null && h != tail) {
+ int ws = h.waitStatus;
+ if (ws == Node.SIGNAL) {
+ if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
+ continue; // loop to recheck cases
+ unparkSuccessor(h);
+ }
+ else if (ws == 0 &&
+ !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
+ continue; // loop on failed CAS
+ }
+ if (h == head) // loop if head changed
+ break;
+ }
+ }
+
+ /**
+ * Sets head of queue, and checks if successor may be waiting
+ * in shared mode, if so propagating if either propagate > 0 or
+ * PROPAGATE status was set.
+ *
+ * @param node the node
+ * @param propagate the return value from a tryAcquireShared
+ */
+ private void setHeadAndPropagate(Node node, long propagate) {
+ Node h = head; // Record old head for check below
+ setHead(node);
+ /*
+ * Try to signal next queued node if:
+ * Propagation was indicated by caller,
+ * or was recorded (as h.waitStatus) by a previous operation
+ * (note: this uses sign-check of waitStatus because
+ * PROPAGATE status may transition to SIGNAL.)
+ * and
+ * The next node is waiting in shared mode,
+ * or we don't know, because it appears null
+ *
+ * The conservatism in both of these checks may cause
+ * unnecessary wake-ups, but only when there are multiple
+ * racing acquires/releases, so most need signals now or soon
+ * anyway.
+ */
+ if (propagate > 0 || h == null || h.waitStatus < 0) {
+ Node s = node.next;
+ if (s == null || s.isShared())
+ doReleaseShared();
+ }
+ }
+
+ // Utilities for various versions of acquire
+
+ /**
+ * Cancels an ongoing attempt to acquire.
+ *
+ * @param node the node
+ */
+ private void cancelAcquire(Node node) {
+ // Ignore if node doesn't exist
+ if (node == null)
+ return;
+
+ node.thread = null;
+
+ // Skip cancelled predecessors
+ Node pred = node.prev;
+ while (pred.waitStatus > 0)
+ node.prev = pred = pred.prev;
+
+ // predNext is the apparent node to unsplice. CASes below will
+ // fail if not, in which case, we lost race vs another cancel
+ // or signal, so no further action is necessary.
+ Node predNext = pred.next;
+
+ // Can use unconditional write instead of CAS here.
+ // After this atomic step, other Nodes can skip past us.
+ // Before, we are free of interference from other threads.
+ node.waitStatus = Node.CANCELLED;
+
+ // If we are the tail, remove ourselves.
+ if (node == tail && compareAndSetTail(node, pred)) {
+ compareAndSetNext(pred, predNext, null);
+ } else {
+ // If successor needs signal, try to set pred's next-link
+ // so it will get one. Otherwise wake it up to propagate.
+ int ws;
+ if (pred != head &&
+ ((ws = pred.waitStatus) == Node.SIGNAL ||
+ (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
+ pred.thread != null) {
+ Node next = node.next;
+ if (next != null && next.waitStatus <= 0)
+ compareAndSetNext(pred, predNext, next);
+ } else {
+ unparkSuccessor(node);
+ }
+
+ node.next = node; // help GC
+ }
+ }
+
+ /**
+ * Checks and updates status for a node that failed to acquire.
+ * Returns true if thread should block. This is the main signal
+ * control in all acquire loops. Requires that pred == node.prev
+ *
+ * @param pred node's predecessor holding status
+ * @param node the node
+ * @return {@code true} if thread should block
+ */
+ private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
+ int ws = pred.waitStatus;
+ if (ws == Node.SIGNAL)
+ /*
+ * This node has already set status asking a release
+ * to signal it, so it can safely park.
+ */
+ return true;
+ if (ws > 0) {
+ /*
+ * Predecessor was cancelled. Skip over predecessors and
+ * indicate retry.
+ */
+ do {
+ node.prev = pred = pred.prev;
+ } while (pred.waitStatus > 0);
+ pred.next = node;
+ } else {
+ /*
+ * waitStatus must be 0 or PROPAGATE. Indicate that we
+ * need a signal, but don't park yet. Caller will need to
+ * retry to make sure it cannot acquire before parking.
+ */
+ compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
+ }
+ return false;
+ }
+
+ /**
+ * Convenience method to interrupt current thread.
+ */
+ private static void selfInterrupt() {
+ Thread.currentThread().interrupt();
+ }
+
+ /**
+ * Convenience method to park and then check if interrupted
+ *
+ * @return {@code true} if interrupted
+ */
+ private final boolean parkAndCheckInterrupt() {
+ LockSupport.park(this);
+ return Thread.interrupted();
+ }
+
+ /*
+ * Various flavors of acquire, varying in exclusive/shared and
+ * control modes. Each is mostly the same, but annoyingly
+ * different. Only a little bit of factoring is possible due to
+ * interactions of exception mechanics (including ensuring that we
+ * cancel if tryAcquire throws exception) and other control, at
+ * least not without hurting performance too much.
+ */
+
+ /**
+ * Acquires in exclusive uninterruptible mode for thread already in
+ * queue. Used by condition wait methods as well as acquire.
+ *
+ * @param node the node
+ * @param arg the acquire argument
+ * @return {@code true} if interrupted while waiting
+ */
+ final boolean acquireQueued(final Node node, long arg) {
+ boolean failed = true;
+ try {
+ boolean interrupted = false;
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head && tryAcquire(arg)) {
+ setHead(node);
+ p.next = null; // help GC
+ failed = false;
+ return interrupted;
+ }
+ if (shouldParkAfterFailedAcquire(p, node) &&
+ parkAndCheckInterrupt())
+ interrupted = true;
+ }
+ } finally {
+ if (failed)
+ cancelAcquire(node);
+ }
+ }
+
+ /**
+ * Acquires in exclusive interruptible mode.
+ * @param arg the acquire argument
+ */
+ private void doAcquireInterruptibly(long arg)
+ throws InterruptedException {
+ final Node node = addWaiter(Node.EXCLUSIVE);
+ boolean failed = true;
+ try {
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head && tryAcquire(arg)) {
+ setHead(node);
+ p.next = null; // help GC
+ failed = false;
+ return;
+ }
+ if (shouldParkAfterFailedAcquire(p, node) &&
+ parkAndCheckInterrupt())
+ throw new InterruptedException();
+ }
+ } finally {
+ if (failed)
+ cancelAcquire(node);
+ }
+ }
+
+ /**
+ * Acquires in exclusive timed mode.
+ *
+ * @param arg the acquire argument
+ * @param nanosTimeout max wait time
+ * @return {@code true} if acquired
+ */
+ private boolean doAcquireNanos(long arg, long nanosTimeout)
+ throws InterruptedException {
+ long lastTime = System.nanoTime();
+ final Node node = addWaiter(Node.EXCLUSIVE);
+ boolean failed = true;
+ try {
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head && tryAcquire(arg)) {
+ setHead(node);
+ p.next = null; // help GC
+ failed = false;
+ return true;
+ }
+ if (nanosTimeout <= 0)
+ return false;
+ if (shouldParkAfterFailedAcquire(p, node) &&
+ nanosTimeout > spinForTimeoutThreshold)
+ LockSupport.parkNanos(this, nanosTimeout);
+ long now = System.nanoTime();
+ nanosTimeout -= now - lastTime;
+ lastTime = now;
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ }
+ } finally {
+ if (failed)
+ cancelAcquire(node);
+ }
+ }
+
+ /**
+ * Acquires in shared uninterruptible mode.
+ * @param arg the acquire argument
+ */
+ private void doAcquireShared(long arg) {
+ final Node node = addWaiter(Node.SHARED);
+ boolean failed = true;
+ try {
+ boolean interrupted = false;
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head) {
+ long r = tryAcquireShared(arg);
+ if (r >= 0) {
+ setHeadAndPropagate(node, r);
+ p.next = null; // help GC
+ if (interrupted)
+ selfInterrupt();
+ failed = false;
+ return;
+ }
+ }
+ if (shouldParkAfterFailedAcquire(p, node) &&
+ parkAndCheckInterrupt())
+ interrupted = true;
+ }
+ } finally {
+ if (failed)
+ cancelAcquire(node);
+ }
+ }
+
+ /**
+ * Acquires in shared interruptible mode.
+ * @param arg the acquire argument
+ */
+ private void doAcquireSharedInterruptibly(long arg)
+ throws InterruptedException {
+ final Node node = addWaiter(Node.SHARED);
+ boolean failed = true;
+ try {
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head) {
+ long r = tryAcquireShared(arg);
+ if (r >= 0) {
+ setHeadAndPropagate(node, r);
+ p.next = null; // help GC
+ failed = false;
+ return;
+ }
+ }
+ if (shouldParkAfterFailedAcquire(p, node) &&
+ parkAndCheckInterrupt())
+ throw new InterruptedException();
+ }
+ } finally {
+ if (failed)
+ cancelAcquire(node);
+ }
+ }
+
+ /**
+ * Acquires in shared timed mode.
+ *
+ * @param arg the acquire argument
+ * @param nanosTimeout max wait time
+ * @return {@code true} if acquired
+ */
+ private boolean doAcquireSharedNanos(long arg, long nanosTimeout)
+ throws InterruptedException {
+
+ long lastTime = System.nanoTime();
+ final Node node = addWaiter(Node.SHARED);
+ boolean failed = true;
+ try {
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head) {
+ long r = tryAcquireShared(arg);
+ if (r >= 0) {
+ setHeadAndPropagate(node, r);
+ p.next = null; // help GC
+ failed = false;
+ return true;
+ }
+ }
+ if (nanosTimeout <= 0)
+ return false;
+ if (shouldParkAfterFailedAcquire(p, node) &&
+ nanosTimeout > spinForTimeoutThreshold)
+ LockSupport.parkNanos(this, nanosTimeout);
+ long now = System.nanoTime();
+ nanosTimeout -= now - lastTime;
+ lastTime = now;
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ }
+ } finally {
+ if (failed)
+ cancelAcquire(node);
+ }
+ }
+
+ // Main exported methods
+
+ /**
+ * Attempts to acquire in exclusive mode. This method should query
+ * if the state of the object permits it to be acquired in the
+ * exclusive mode, and if so to acquire it.
+ *
+ * <p>This method is always invoked by the thread performing
+ * acquire. If this method reports failure, the acquire method
+ * may queue the thread, if it is not already queued, until it is
+ * signalled by a release from some other thread. This can be used
+ * to implement method {@link Lock#tryLock()}.
+ *
+ * <p>The default
+ * implementation throws {@link UnsupportedOperationException}.
+ *
+ * @param arg the acquire argument. This value is always the one
+ * passed to an acquire method, or is the value saved on entry
+ * to a condition wait. The value is otherwise uninterpreted
+ * and can represent anything you like.
+ * @return {@code true} if successful. Upon success, this object has
+ * been acquired.
+ * @throws IllegalMonitorStateException if acquiring would place this
+ * synchronizer in an illegal state. This exception must be
+ * thrown in a consistent fashion for synchronization to work
+ * correctly.
+ * @throws UnsupportedOperationException if exclusive mode is not supported
+ */
+ protected boolean tryAcquire(long arg) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Attempts to set the state to reflect a release in exclusive
+ * mode.
+ *
+ * <p>This method is always invoked by the thread performing release.
+ *
+ * <p>The default implementation throws
+ * {@link UnsupportedOperationException}.
+ *
+ * @param arg the release argument. This value is always the one
+ * passed to a release method, or the current state value upon
+ * entry to a condition wait. The value is otherwise
+ * uninterpreted and can represent anything you like.
+ * @return {@code true} if this object is now in a fully released
+ * state, so that any waiting threads may attempt to acquire;
+ * and {@code false} otherwise.
+ * @throws IllegalMonitorStateException if releasing would place this
+ * synchronizer in an illegal state. This exception must be
+ * thrown in a consistent fashion for synchronization to work
+ * correctly.
+ * @throws UnsupportedOperationException if exclusive mode is not supported
+ */
+ protected boolean tryRelease(long arg) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Attempts to acquire in shared mode. This method should query if
+ * the state of the object permits it to be acquired in the shared
+ * mode, and if so to acquire it.
+ *
+ * <p>This method is always invoked by the thread performing
+ * acquire. If this method reports failure, the acquire method
+ * may queue the thread, if it is not already queued, until it is
+ * signalled by a release from some other thread.
+ *
+ * <p>The default implementation throws {@link
+ * UnsupportedOperationException}.
+ *
+ * @param arg the acquire argument. This value is always the one
+ * passed to an acquire method, or is the value saved on entry
+ * to a condition wait. The value is otherwise uninterpreted
+ * and can represent anything you like.
+ * @return a negative value on failure; zero if acquisition in shared
+ * mode succeeded but no subsequent shared-mode acquire can
+ * succeed; and a positive value if acquisition in shared
+ * mode succeeded and subsequent shared-mode acquires might
+ * also succeed, in which case a subsequent waiting thread
+ * must check availability. (Support for three different
+ * return values enables this method to be used in contexts
+ * where acquires only sometimes act exclusively.) Upon
+ * success, this object has been acquired.
+ * @throws IllegalMonitorStateException if acquiring would place this
+ * synchronizer in an illegal state. This exception must be
+ * thrown in a consistent fashion for synchronization to work
+ * correctly.
+ * @throws UnsupportedOperationException if shared mode is not supported
+ */
+ protected long tryAcquireShared(long arg) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Attempts to set the state to reflect a release in shared mode.
+ *
+ * <p>This method is always invoked by the thread performing release.
+ *
+ * <p>The default implementation throws
+ * {@link UnsupportedOperationException}.
+ *
+ * @param arg the release argument. This value is always the one
+ * passed to a release method, or the current state value upon
+ * entry to a condition wait. The value is otherwise
+ * uninterpreted and can represent anything you like.
+ * @return {@code true} if this release of shared mode may permit a
+ * waiting acquire (shared or exclusive) to succeed; and
+ * {@code false} otherwise
+ * @throws IllegalMonitorStateException if releasing would place this
+ * synchronizer in an illegal state. This exception must be
+ * thrown in a consistent fashion for synchronization to work
+ * correctly.
+ * @throws UnsupportedOperationException if shared mode is not supported
+ */
+ protected boolean tryReleaseShared(long arg) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns {@code true} if synchronization is held exclusively with
+ * respect to the current (calling) thread. This method is invoked
+ * upon each call to a non-waiting {@link ConditionObject} method.
+ * (Waiting methods instead invoke {@link #release}.)
+ *
+ * <p>The default implementation throws {@link
+ * UnsupportedOperationException}. This method is invoked
+ * internally only within {@link ConditionObject} methods, so need
+ * not be defined if conditions are not used.
+ *
+ * @return {@code true} if synchronization is held exclusively;
+ * {@code false} otherwise
+ * @throws UnsupportedOperationException if conditions are not supported
+ */
+ protected boolean isHeldExclusively() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Acquires in exclusive mode, ignoring interrupts. Implemented
+ * by invoking at least once {@link #tryAcquire},
+ * returning on success. Otherwise the thread is queued, possibly
+ * repeatedly blocking and unblocking, invoking {@link
+ * #tryAcquire} until success. This method can be used
+ * to implement method {@link Lock#lock}.
+ *
+ * @param arg the acquire argument. This value is conveyed to
+ * {@link #tryAcquire} but is otherwise uninterpreted and
+ * can represent anything you like.
+ */
+ public final void acquire(long arg) {
+ if (!tryAcquire(arg) &&
+ acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
+ selfInterrupt();
+ }
+
+ /**
+ * Acquires in exclusive mode, aborting if interrupted.
+ * Implemented by first checking interrupt status, then invoking
+ * at least once {@link #tryAcquire}, returning on
+ * success. Otherwise the thread is queued, possibly repeatedly
+ * blocking and unblocking, invoking {@link #tryAcquire}
+ * until success or the thread is interrupted. This method can be
+ * used to implement method {@link Lock#lockInterruptibly}.
+ *
+ * @param arg the acquire argument. This value is conveyed to
+ * {@link #tryAcquire} but is otherwise uninterpreted and
+ * can represent anything you like.
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public final void acquireInterruptibly(long arg) throws InterruptedException {
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ if (!tryAcquire(arg))
+ doAcquireInterruptibly(arg);
+ }
+
+ /**
+ * Attempts to acquire in exclusive mode, aborting if interrupted,
+ * and failing if the given timeout elapses. Implemented by first
+ * checking interrupt status, then invoking at least once {@link
+ * #tryAcquire}, returning on success. Otherwise, the thread is
+ * queued, possibly repeatedly blocking and unblocking, invoking
+ * {@link #tryAcquire} until success or the thread is interrupted
+ * or the timeout elapses. This method can be used to implement
+ * method {@link Lock#tryLock(long, TimeUnit)}.
+ *
+ * @param arg the acquire argument. This value is conveyed to
+ * {@link #tryAcquire} but is otherwise uninterpreted and
+ * can represent anything you like.
+ * @param nanosTimeout the maximum number of nanoseconds to wait
+ * @return {@code true} if acquired; {@code false} if timed out
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public final boolean tryAcquireNanos(long arg, long nanosTimeout) throws InterruptedException {
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ return tryAcquire(arg) ||
+ doAcquireNanos(arg, nanosTimeout);
+ }
+
+ /**
+ * Releases in exclusive mode. Implemented by unblocking one or
+ * more threads if {@link #tryRelease} returns true.
+ * This method can be used to implement method {@link Lock#unlock}.
+ *
+ * @param arg the release argument. This value is conveyed to
+ * {@link #tryRelease} but is otherwise uninterpreted and
+ * can represent anything you like.
+ * @return the value returned from {@link #tryRelease}
+ */
+ public final boolean release(long arg) {
+ if (tryRelease(arg)) {
+ Node h = head;
+ if (h != null && h.waitStatus != 0)
+ unparkSuccessor(h);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Acquires in shared mode, ignoring interrupts. Implemented by
+ * first invoking at least once {@link #tryAcquireShared},
+ * returning on success. Otherwise the thread is queued, possibly
+ * repeatedly blocking and unblocking, invoking {@link
+ * #tryAcquireShared} until success.
+ *
+ * @param arg the acquire argument. This value is conveyed to
+ * {@link #tryAcquireShared} but is otherwise uninterpreted
+ * and can represent anything you like.
+ */
+ public final void acquireShared(long arg) {
+ if (tryAcquireShared(arg) < 0)
+ doAcquireShared(arg);
+ }
+
+ /**
+ * Acquires in shared mode, aborting if interrupted. Implemented
+ * by first checking interrupt status, then invoking at least once
+ * {@link #tryAcquireShared}, returning on success. Otherwise the
+ * thread is queued, possibly repeatedly blocking and unblocking,
+ * invoking {@link #tryAcquireShared} until success or the thread
+ * is interrupted.
+ * @param arg the acquire argument
+ * This value is conveyed to {@link #tryAcquireShared} but is
+ * otherwise uninterpreted and can represent anything
+ * you like.
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public final void acquireSharedInterruptibly(long arg) throws InterruptedException {
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ if (tryAcquireShared(arg) < 0)
+ doAcquireSharedInterruptibly(arg);
+ }
+
+ /**
+ * Attempts to acquire in shared mode, aborting if interrupted, and
+ * failing if the given timeout elapses. Implemented by first
+ * checking interrupt status, then invoking at least once {@link
+ * #tryAcquireShared}, returning on success. Otherwise, the
+ * thread is queued, possibly repeatedly blocking and unblocking,
+ * invoking {@link #tryAcquireShared} until success or the thread
+ * is interrupted or the timeout elapses.
+ *
+ * @param arg the acquire argument. This value is conveyed to
+ * {@link #tryAcquireShared} but is otherwise uninterpreted
+ * and can represent anything you like.
+ * @param nanosTimeout the maximum number of nanoseconds to wait
+ * @return {@code true} if acquired; {@code false} if timed out
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public final boolean tryAcquireSharedNanos(long arg, long nanosTimeout) throws InterruptedException {
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ return tryAcquireShared(arg) >= 0 ||
+ doAcquireSharedNanos(arg, nanosTimeout);
+ }
+
+ /**
+ * Releases in shared mode. Implemented by unblocking one or more
+ * threads if {@link #tryReleaseShared} returns true.
+ *
+ * @param arg the release argument. This value is conveyed to
+ * {@link #tryReleaseShared} but is otherwise uninterpreted
+ * and can represent anything you like.
+ * @return the value returned from {@link #tryReleaseShared}
+ */
+ public final boolean releaseShared(long arg) {
+ if (tryReleaseShared(arg)) {
+ doReleaseShared();
+ return true;
+ }
+ return false;
+ }
+
+ // Queue inspection methods
+
+ /**
+ * Queries whether any threads are waiting to acquire. Note that
+ * because cancellations due to interrupts and timeouts may occur
+ * at any time, a {@code true} return does not guarantee that any
+ * other thread will ever acquire.
+ *
+ * <p>In this implementation, this operation returns in
+ * constant time.
+ *
+ * @return {@code true} if there may be other threads waiting to acquire
+ */
+ public final boolean hasQueuedThreads() {
+ return head != tail;
+ }
+
+ /**
+ * Queries whether any threads have ever contended to acquire this
+ * synchronizer; that is if an acquire method has ever blocked.
+ *
+ * <p>In this implementation, this operation returns in
+ * constant time.
+ *
+ * @return {@code true} if there has ever been contention
+ */
+ public final boolean hasContended() {
+ return head != null;
+ }
+
+ /**
+ * Returns the first (longest-waiting) thread in the queue, or
+ * {@code null} if no threads are currently queued.
+ *
+ * <p>In this implementation, this operation normally returns in
+ * constant time, but may iterate upon contention if other threads are
+ * concurrently modifying the queue.
+ *
+ * @return the first (longest-waiting) thread in the queue, or
+ * {@code null} if no threads are currently queued
+ */
+ public final Thread getFirstQueuedThread() {
+ // handle only fast path, else relay
+ return (head == tail) ? null : fullGetFirstQueuedThread();
+ }
+
+ /**
+ * Version of getFirstQueuedThread called when fastpath fails
+ */
+ private Thread fullGetFirstQueuedThread() {
+ /*
+ * The first node is normally head.next. Try to get its
+ * thread field, ensuring consistent reads: If thread
+ * field is nulled out or s.prev is no longer head, then
+ * some other thread(s) concurrently performed setHead in
+ * between some of our reads. We try this twice before
+ * resorting to traversal.
+ */
+ Node h, s;
+ Thread st;
+ if (((h = head) != null && (s = h.next) != null &&
+ s.prev == head && (st = s.thread) != null) ||
+ ((h = head) != null && (s = h.next) != null &&
+ s.prev == head && (st = s.thread) != null))
+ return st;
+
+ /*
+ * Head's next field might not have been set yet, or may have
+ * been unset after setHead. So we must check to see if tail
+ * is actually first node. If not, we continue on, safely
+ * traversing from tail back to head to find first,
+ * guaranteeing termination.
+ */
+
+ Node t = tail;
+ Thread firstThread = null;
+ while (t != null && t != head) {
+ Thread tt = t.thread;
+ if (tt != null)
+ firstThread = tt;
+ t = t.prev;
+ }
+ return firstThread;
+ }
+
+ /**
+ * Returns true if the given thread is currently queued.
+ *
+ * <p>This implementation traverses the queue to determine
+ * presence of the given thread.
+ *
+ * @param thread the thread
+ * @return {@code true} if the given thread is on the queue
+ * @throws NullPointerException if the thread is null
+ */
+ public final boolean isQueued(Thread thread) {
+ if (thread == null)
+ throw new NullPointerException();
+ for (Node p = tail; p != null; p = p.prev)
+ if (p.thread == thread)
+ return true;
+ return false;
+ }
+
+ /**
+ * Returns {@code true} if the apparent first queued thread, if one
+ * exists, is waiting in exclusive mode. If this method returns
+ * {@code true}, and the current thread is attempting to acquire in
+ * shared mode (that is, this method is invoked from {@link
+ * #tryAcquireShared}) then it is guaranteed that the current thread
+ * is not the first queued thread. Used only as a heuristic in
+ * ReentrantReadWriteLock.
+ */
+ final boolean apparentlyFirstQueuedIsExclusive() {
+ Node h, s;
+ return (h = head) != null &&
+ (s = h.next) != null &&
+ !s.isShared() &&
+ s.thread != null;
+ }
+
+ /**
+ * Queries whether any threads have been waiting to acquire longer
+ * than the current thread.
+ *
+ * <p>An invocation of this method is equivalent to (but may be
+ * more efficient than):
+ * <pre> {@code
+ * getFirstQueuedThread() != Thread.currentThread() &&
+ * hasQueuedThreads()}</pre>
+ *
+ * <p>Note that because cancellations due to interrupts and
+ * timeouts may occur at any time, a {@code true} return does not
+ * guarantee that some other thread will acquire before the current
+ * thread. Likewise, it is possible for another thread to win a
+ * race to enqueue after this method has returned {@code false},
+ * due to the queue being empty.
+ *
+ * <p>This method is designed to be used by a fair synchronizer to
+ * avoid <a href="AbstractQueuedSynchronizer#barging">barging</a>.
+ * Such a synchronizer's {@link #tryAcquire} method should return
+ * {@code false}, and its {@link #tryAcquireShared} method should
+ * return a negative value, if this method returns {@code true}
+ * (unless this is a reentrant acquire). For example, the {@code
+ * tryAcquire} method for a fair, reentrant, exclusive mode
+ * synchronizer might look like this:
+ *
+ * <pre> {@code
+ * protected boolean tryAcquire(int arg) {
+ * if (isHeldExclusively()) {
+ * // A reentrant acquire; increment hold count
+ * return true;
+ * } else if (hasQueuedPredecessors()) {
+ * return false;
+ * } else {
+ * // try to acquire normally
+ * }
+ * }}</pre>
+ *
+ * @return {@code true} if there is a queued thread preceding the
+ * current thread, and {@code false} if the current thread
+ * is at the head of the queue or the queue is empty
+ * @since 1.7
+ */
+ /*public*/ final boolean hasQueuedPredecessors() { // android-changed
+ // The correctness of this depends on head being initialized
+ // before tail and on head.next being accurate if the current
+ // thread is first in queue.
+ Node t = tail; // Read fields in reverse initialization order
+ Node h = head;
+ Node s;
+ return h != t &&
+ ((s = h.next) == null || s.thread != Thread.currentThread());
+ }
+
+
+ // Instrumentation and monitoring methods
+
+ /**
+ * 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 system state, not for synchronization
+ * control.
+ *
+ * @return the estimated number of threads waiting to acquire
+ */
+ public final int getQueueLength() {
+ int n = 0;
+ for (Node p = tail; p != null; p = p.prev) {
+ if (p.thread != null)
+ ++n;
+ }
+ return n;
+ }
+
+ /**
+ * 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
+ */
+ public final Collection<Thread> getQueuedThreads() {
+ ArrayList<Thread> list = new ArrayList<Thread>();
+ for (Node p = tail; p != null; p = p.prev) {
+ Thread t = p.thread;
+ if (t != null)
+ list.add(t);
+ }
+ return list;
+ }
+
+ /**
+ * Returns a collection containing threads that may be waiting to
+ * acquire in exclusive mode. This has the same properties
+ * as {@link #getQueuedThreads} except that it only returns
+ * those threads waiting due to an exclusive acquire.
+ *
+ * @return the collection of threads
+ */
+ public final Collection<Thread> getExclusiveQueuedThreads() {
+ ArrayList<Thread> list = new ArrayList<Thread>();
+ for (Node p = tail; p != null; p = p.prev) {
+ if (!p.isShared()) {
+ Thread t = p.thread;
+ if (t != null)
+ list.add(t);
+ }
+ }
+ return list;
+ }
+
+ /**
+ * Returns a collection containing threads that may be waiting to
+ * acquire in shared mode. This has the same properties
+ * as {@link #getQueuedThreads} except that it only returns
+ * those threads waiting due to a shared acquire.
+ *
+ * @return the collection of threads
+ */
+ public final Collection<Thread> getSharedQueuedThreads() {
+ ArrayList<Thread> list = new ArrayList<Thread>();
+ for (Node p = tail; p != null; p = p.prev) {
+ if (p.isShared()) {
+ Thread t = p.thread;
+ if (t != null)
+ list.add(t);
+ }
+ }
+ return list;
+ }
+
+ /**
+ * Returns a string identifying this synchronizer, as well as its state.
+ * The state, in brackets, includes the String {@code "State ="}
+ * followed by the current value of {@link #getState}, and either
+ * {@code "nonempty"} or {@code "empty"} depending on whether the
+ * queue is empty.
+ *
+ * @return a string identifying this synchronizer, as well as its state
+ */
+ public String toString() {
+ long s = getState();
+ String q = hasQueuedThreads() ? "non" : "";
+ return super.toString() +
+ "[State = " + s + ", " + q + "empty queue]";
+ }
+
+
+ // Internal support methods for Conditions
+
+ /**
+ * Returns true if a node, always one that was initially placed on
+ * a condition queue, is now waiting to reacquire on sync queue.
+ * @param node the node
+ * @return true if is reacquiring
+ */
+ final boolean isOnSyncQueue(Node node) {
+ if (node.waitStatus == Node.CONDITION || node.prev == null)
+ return false;
+ if (node.next != null) // If has successor, it must be on queue
+ return true;
+ /*
+ * node.prev can be non-null, but not yet on queue because
+ * the CAS to place it on queue can fail. So we have to
+ * traverse from tail to make sure it actually made it. It
+ * will always be near the tail in calls to this method, and
+ * unless the CAS failed (which is unlikely), it will be
+ * there, so we hardly ever traverse much.
+ */
+ return findNodeFromTail(node);
+ }
+
+ /**
+ * Returns true if node is on sync queue by searching backwards from tail.
+ * Called only when needed by isOnSyncQueue.
+ * @return true if present
+ */
+ private boolean findNodeFromTail(Node node) {
+ Node t = tail;
+ for (;;) {
+ if (t == node)
+ return true;
+ if (t == null)
+ return false;
+ t = t.prev;
+ }
+ }
+
+ /**
+ * Transfers a node from a condition queue onto sync queue.
+ * Returns true if successful.
+ * @param node the node
+ * @return true if successfully transferred (else the node was
+ * cancelled before signal).
+ */
+ final boolean transferForSignal(Node node) {
+ /*
+ * If cannot change waitStatus, the node has been cancelled.
+ */
+ if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
+ return false;
+
+ /*
+ * Splice onto queue and try to set waitStatus of predecessor to
+ * indicate that thread is (probably) waiting. If cancelled or
+ * attempt to set waitStatus fails, wake up to resync (in which
+ * case the waitStatus can be transiently and harmlessly wrong).
+ */
+ Node p = enq(node);
+ int ws = p.waitStatus;
+ if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
+ LockSupport.unpark(node.thread);
+ return true;
+ }
+
+ /**
+ * Transfers node, if necessary, to sync queue after a cancelled
+ * wait. Returns true if thread was cancelled before being
+ * signalled.
+ * @param current the waiting thread
+ * @param node its node
+ * @return true if cancelled before the node was signalled
+ */
+ final boolean transferAfterCancelledWait(Node node) {
+ if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
+ enq(node);
+ return true;
+ }
+ /*
+ * If we lost out to a signal(), then we can't proceed
+ * until it finishes its enq(). Cancelling during an
+ * incomplete transfer is both rare and transient, so just
+ * spin.
+ */
+ while (!isOnSyncQueue(node))
+ Thread.yield();
+ return false;
+ }
+
+ /**
+ * Invokes release with current state value; returns saved state.
+ * Cancels node and throws exception on failure.
+ * @param node the condition node for this wait
+ * @return previous sync state
+ */
+ final long fullyRelease(Node node) {
+ boolean failed = true;
+ try {
+ long savedState = getState();
+ if (release(savedState)) {
+ failed = false;
+ return savedState;
+ } else {
+ throw new IllegalMonitorStateException();
+ }
+ } finally {
+ if (failed)
+ node.waitStatus = Node.CANCELLED;
+ }
+ }
+
+ // Instrumentation methods for conditions
+
+ /**
+ * Queries whether the given ConditionObject
+ * uses this synchronizer as its lock.
+ *
+ * @param condition the condition
+ * @return <tt>true</tt> if owned
+ * @throws NullPointerException if the condition is null
+ */
+ public final boolean owns(ConditionObject condition) {
+ if (condition == null)
+ throw new NullPointerException();
+ return condition.isOwnedBy(this);
+ }
+
+ /**
+ * Queries whether any threads are waiting on the given condition
+ * associated with this synchronizer. 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 exclusive synchronization
+ * is not held
+ * @throws IllegalArgumentException if the given condition is
+ * not associated with this synchronizer
+ * @throws NullPointerException if the condition is null
+ */
+ public final boolean hasWaiters(ConditionObject condition) {
+ if (!owns(condition))
+ throw new IllegalArgumentException("Not owner");
+ return condition.hasWaiters();
+ }
+
+ /**
+ * Returns an estimate of the number of threads waiting on the
+ * given condition associated with this synchronizer. 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 exclusive synchronization
+ * is not held
+ * @throws IllegalArgumentException if the given condition is
+ * not associated with this synchronizer
+ * @throws NullPointerException if the condition is null
+ */
+ public final int getWaitQueueLength(ConditionObject condition) {
+ if (!owns(condition))
+ throw new IllegalArgumentException("Not owner");
+ return condition.getWaitQueueLength();
+ }
+
+ /**
+ * Returns a collection containing those threads that may be
+ * waiting on the given condition associated with this
+ * synchronizer. 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.
+ *
+ * @param condition the condition
+ * @return the collection of threads
+ * @throws IllegalMonitorStateException if exclusive synchronization
+ * is not held
+ * @throws IllegalArgumentException if the given condition is
+ * not associated with this synchronizer
+ * @throws NullPointerException if the condition is null
+ */
+ public final Collection<Thread> getWaitingThreads(ConditionObject condition) {
+ if (!owns(condition))
+ throw new IllegalArgumentException("Not owner");
+ return condition.getWaitingThreads();
+ }
+
+ /**
+ * Condition implementation for a {@link
+ * AbstractQueuedLongSynchronizer} serving as the basis of a {@link
+ * Lock} implementation.
+ *
+ * <p>Method documentation for this class describes mechanics,
+ * not behavioral specifications from the point of view of Lock
+ * and Condition users. Exported versions of this class will in
+ * general need to be accompanied by documentation describing
+ * condition semantics that rely on those of the associated
+ * <tt>AbstractQueuedLongSynchronizer</tt>.
+ *
+ * <p>This class is Serializable, but all fields are transient,
+ * so deserialized conditions have no waiters.
+ *
+ * @since 1.6
+ */
+ public class ConditionObject implements Condition, java.io.Serializable {
+ private static final long serialVersionUID = 1173984872572414699L;
+ /** First node of condition queue. */
+ private transient Node firstWaiter;
+ /** Last node of condition queue. */
+ private transient Node lastWaiter;
+
+ /**
+ * Creates a new <tt>ConditionObject</tt> instance.
+ */
+ public ConditionObject() { }
+
+ // Internal methods
+
+ /**
+ * Adds a new waiter to wait queue.
+ * @return its new wait node
+ */
+ private Node addConditionWaiter() {
+ Node t = lastWaiter;
+ // If lastWaiter is cancelled, clean out.
+ if (t != null && t.waitStatus != Node.CONDITION) {
+ unlinkCancelledWaiters();
+ t = lastWaiter;
+ }
+ Node node = new Node(Thread.currentThread(), Node.CONDITION);
+ if (t == null)
+ firstWaiter = node;
+ else
+ t.nextWaiter = node;
+ lastWaiter = node;
+ return node;
+ }
+
+ /**
+ * Removes and transfers nodes until hit non-cancelled one or
+ * null. Split out from signal in part to encourage compilers
+ * to inline the case of no waiters.
+ * @param first (non-null) the first node on condition queue
+ */
+ private void doSignal(Node first) {
+ do {
+ if ( (firstWaiter = first.nextWaiter) == null)
+ lastWaiter = null;
+ first.nextWaiter = null;
+ } while (!transferForSignal(first) &&
+ (first = firstWaiter) != null);
+ }
+
+ /**
+ * Removes and transfers all nodes.
+ * @param first (non-null) the first node on condition queue
+ */
+ private void doSignalAll(Node first) {
+ lastWaiter = firstWaiter = null;
+ do {
+ Node next = first.nextWaiter;
+ first.nextWaiter = null;
+ transferForSignal(first);
+ first = next;
+ } while (first != null);
+ }
+
+ /**
+ * Unlinks cancelled waiter nodes from condition queue.
+ * Called only while holding lock. This is called when
+ * cancellation occurred during condition wait, and upon
+ * insertion of a new waiter when lastWaiter is seen to have
+ * been cancelled. This method is needed to avoid garbage
+ * retention in the absence of signals. So even though it may
+ * require a full traversal, it comes into play only when
+ * timeouts or cancellations occur in the absence of
+ * signals. It traverses all nodes rather than stopping at a
+ * particular target to unlink all pointers to garbage nodes
+ * without requiring many re-traversals during cancellation
+ * storms.
+ */
+ private void unlinkCancelledWaiters() {
+ Node t = firstWaiter;
+ Node trail = null;
+ while (t != null) {
+ Node next = t.nextWaiter;
+ if (t.waitStatus != Node.CONDITION) {
+ t.nextWaiter = null;
+ if (trail == null)
+ firstWaiter = next;
+ else
+ trail.nextWaiter = next;
+ if (next == null)
+ lastWaiter = trail;
+ }
+ else
+ trail = t;
+ t = next;
+ }
+ }
+
+ // public methods
+
+ /**
+ * Moves the longest-waiting thread, if one exists, from the
+ * wait queue for this condition to the wait queue for the
+ * owning lock.
+ *
+ * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
+ * returns {@code false}
+ */
+ public final void signal() {
+ if (!isHeldExclusively())
+ throw new IllegalMonitorStateException();
+ Node first = firstWaiter;
+ if (first != null)
+ doSignal(first);
+ }
+
+ /**
+ * Moves all threads from the wait queue for this condition to
+ * the wait queue for the owning lock.
+ *
+ * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
+ * returns {@code false}
+ */
+ public final void signalAll() {
+ if (!isHeldExclusively())
+ throw new IllegalMonitorStateException();
+ Node first = firstWaiter;
+ if (first != null)
+ doSignalAll(first);
+ }
+
+ /**
+ * Implements uninterruptible condition wait.
+ * <ol>
+ * <li> Save lock state returned by {@link #getState}.
+ * <li> Invoke {@link #release} with
+ * saved state as argument, throwing
+ * IllegalMonitorStateException if it fails.
+ * <li> Block until signalled.
+ * <li> Reacquire by invoking specialized version of
+ * {@link #acquire} with saved state as argument.
+ * </ol>
+ */
+ public final void awaitUninterruptibly() {
+ Node node = addConditionWaiter();
+ long savedState = fullyRelease(node);
+ boolean interrupted = false;
+ while (!isOnSyncQueue(node)) {
+ LockSupport.park(this);
+ if (Thread.interrupted())
+ interrupted = true;
+ }
+ if (acquireQueued(node, savedState) || interrupted)
+ selfInterrupt();
+ }
+
+ /*
+ * For interruptible waits, we need to track whether to throw
+ * InterruptedException, if interrupted while blocked on
+ * condition, versus reinterrupt current thread, if
+ * interrupted while blocked waiting to re-acquire.
+ */
+
+ /** Mode meaning to reinterrupt on exit from wait */
+ private static final int REINTERRUPT = 1;
+ /** Mode meaning to throw InterruptedException on exit from wait */
+ private static final int THROW_IE = -1;
+
+ /**
+ * Checks for interrupt, returning THROW_IE if interrupted
+ * before signalled, REINTERRUPT if after signalled, or
+ * 0 if not interrupted.
+ */
+ private int checkInterruptWhileWaiting(Node node) {
+ return Thread.interrupted() ?
+ (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :
+ 0;
+ }
+
+ /**
+ * Throws InterruptedException, reinterrupts current thread, or
+ * does nothing, depending on mode.
+ */
+ private void reportInterruptAfterWait(int interruptMode)
+ throws InterruptedException {
+ if (interruptMode == THROW_IE)
+ throw new InterruptedException();
+ else if (interruptMode == REINTERRUPT)
+ selfInterrupt();
+ }
+
+ /**
+ * Implements interruptible condition wait.
+ * <ol>
+ * <li> If current thread is interrupted, throw InterruptedException.
+ * <li> Save lock state returned by {@link #getState}.
+ * <li> Invoke {@link #release} with
+ * saved state as argument, throwing
+ * IllegalMonitorStateException if it fails.
+ * <li> Block until signalled or interrupted.
+ * <li> Reacquire by invoking specialized version of
+ * {@link #acquire} with saved state as argument.
+ * <li> If interrupted while blocked in step 4, throw InterruptedException.
+ * </ol>
+ */
+ public final void await() throws InterruptedException {
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ Node node = addConditionWaiter();
+ long savedState = fullyRelease(node);
+ int interruptMode = 0;
+ while (!isOnSyncQueue(node)) {
+ LockSupport.park(this);
+ if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
+ break;
+ }
+ if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
+ interruptMode = REINTERRUPT;
+ if (node.nextWaiter != null) // clean up if cancelled
+ unlinkCancelledWaiters();
+ if (interruptMode != 0)
+ reportInterruptAfterWait(interruptMode);
+ }
+
+ /**
+ * Implements timed condition wait.
+ * <ol>
+ * <li> If current thread is interrupted, throw InterruptedException.
+ * <li> Save lock state returned by {@link #getState}.
+ * <li> Invoke {@link #release} with
+ * saved state as argument, throwing
+ * IllegalMonitorStateException if it fails.
+ * <li> Block until signalled, interrupted, or timed out.
+ * <li> Reacquire by invoking specialized version of
+ * {@link #acquire} with saved state as argument.
+ * <li> If interrupted while blocked in step 4, throw InterruptedException.
+ * </ol>
+ */
+ public final long awaitNanos(long nanosTimeout) throws InterruptedException {
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ Node node = addConditionWaiter();
+ long savedState = fullyRelease(node);
+ long lastTime = System.nanoTime();
+ int interruptMode = 0;
+ while (!isOnSyncQueue(node)) {
+ if (nanosTimeout <= 0L) {
+ transferAfterCancelledWait(node);
+ break;
+ }
+ LockSupport.parkNanos(this, nanosTimeout);
+ if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
+ break;
+
+ long now = System.nanoTime();
+ nanosTimeout -= now - lastTime;
+ lastTime = now;
+ }
+ if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
+ interruptMode = REINTERRUPT;
+ if (node.nextWaiter != null)
+ unlinkCancelledWaiters();
+ if (interruptMode != 0)
+ reportInterruptAfterWait(interruptMode);
+ return nanosTimeout - (System.nanoTime() - lastTime);
+ }
+
+ /**
+ * Implements absolute timed condition wait.
+ * <ol>
+ * <li> If current thread is interrupted, throw InterruptedException.
+ * <li> Save lock state returned by {@link #getState}.
+ * <li> Invoke {@link #release} with
+ * saved state as argument, throwing
+ * IllegalMonitorStateException if it fails.
+ * <li> Block until signalled, interrupted, or timed out.
+ * <li> Reacquire by invoking specialized version of
+ * {@link #acquire} with saved state as argument.
+ * <li> If interrupted while blocked in step 4, throw InterruptedException.
+ * <li> If timed out while blocked in step 4, return false, else true.
+ * </ol>
+ */
+ public final boolean awaitUntil(Date deadline) throws InterruptedException {
+ if (deadline == null)
+ throw new NullPointerException();
+ long abstime = deadline.getTime();
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ Node node = addConditionWaiter();
+ long savedState = fullyRelease(node);
+ boolean timedout = false;
+ int interruptMode = 0;
+ while (!isOnSyncQueue(node)) {
+ if (System.currentTimeMillis() > abstime) {
+ timedout = transferAfterCancelledWait(node);
+ break;
+ }
+ LockSupport.parkUntil(this, abstime);
+ if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
+ break;
+ }
+ if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
+ interruptMode = REINTERRUPT;
+ if (node.nextWaiter != null)
+ unlinkCancelledWaiters();
+ if (interruptMode != 0)
+ reportInterruptAfterWait(interruptMode);
+ return !timedout;
+ }
+
+ /**
+ * Implements timed condition wait.
+ * <ol>
+ * <li> If current thread is interrupted, throw InterruptedException.
+ * <li> Save lock state returned by {@link #getState}.
+ * <li> Invoke {@link #release} with
+ * saved state as argument, throwing
+ * IllegalMonitorStateException if it fails.
+ * <li> Block until signalled, interrupted, or timed out.
+ * <li> Reacquire by invoking specialized version of
+ * {@link #acquire} with saved state as argument.
+ * <li> If interrupted while blocked in step 4, throw InterruptedException.
+ * <li> If timed out while blocked in step 4, return false, else true.
+ * </ol>
+ */
+ public final boolean await(long time, TimeUnit unit) throws InterruptedException {
+ if (unit == null)
+ throw new NullPointerException();
+ long nanosTimeout = unit.toNanos(time);
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ Node node = addConditionWaiter();
+ long savedState = fullyRelease(node);
+ long lastTime = System.nanoTime();
+ boolean timedout = false;
+ int interruptMode = 0;
+ while (!isOnSyncQueue(node)) {
+ if (nanosTimeout <= 0L) {
+ timedout = transferAfterCancelledWait(node);
+ break;
+ }
+ if (nanosTimeout >= spinForTimeoutThreshold)
+ LockSupport.parkNanos(this, nanosTimeout);
+ if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
+ break;
+ long now = System.nanoTime();
+ nanosTimeout -= now - lastTime;
+ lastTime = now;
+ }
+ if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
+ interruptMode = REINTERRUPT;
+ if (node.nextWaiter != null)
+ unlinkCancelledWaiters();
+ if (interruptMode != 0)
+ reportInterruptAfterWait(interruptMode);
+ return !timedout;
+ }
+
+ // support for instrumentation
+
+ /**
+ * Returns true if this condition was created by the given
+ * synchronization object.
+ *
+ * @return {@code true} if owned
+ */
+ final boolean isOwnedBy(AbstractQueuedLongSynchronizer sync) {
+ return sync == AbstractQueuedLongSynchronizer.this;
+ }
+
+ /**
+ * Queries whether any threads are waiting on this condition.
+ * Implements {@link AbstractQueuedLongSynchronizer#hasWaiters}.
+ *
+ * @return {@code true} if there are any waiting threads
+ * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
+ * returns {@code false}
+ */
+ protected final boolean hasWaiters() {
+ if (!isHeldExclusively())
+ throw new IllegalMonitorStateException();
+ for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
+ if (w.waitStatus == Node.CONDITION)
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns an estimate of the number of threads waiting on
+ * this condition.
+ * Implements {@link AbstractQueuedLongSynchronizer#getWaitQueueLength}.
+ *
+ * @return the estimated number of waiting threads
+ * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
+ * returns {@code false}
+ */
+ protected final int getWaitQueueLength() {
+ if (!isHeldExclusively())
+ throw new IllegalMonitorStateException();
+ int n = 0;
+ for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
+ if (w.waitStatus == Node.CONDITION)
+ ++n;
+ }
+ return n;
+ }
+
+ /**
+ * Returns a collection containing those threads that may be
+ * waiting on this Condition.
+ * Implements {@link AbstractQueuedLongSynchronizer#getWaitingThreads}.
+ *
+ * @return the collection of threads
+ * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
+ * returns {@code false}
+ */
+ protected final Collection<Thread> getWaitingThreads() {
+ if (!isHeldExclusively())
+ throw new IllegalMonitorStateException();
+ ArrayList<Thread> list = new ArrayList<Thread>();
+ for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
+ if (w.waitStatus == Node.CONDITION) {
+ Thread t = w.thread;
+ if (t != null)
+ list.add(t);
+ }
+ }
+ return list;
+ }
+ }
+
+ /**
+ * Setup to support compareAndSet. We need to natively implement
+ * this here: For the sake of permitting future enhancements, we
+ * cannot explicitly subclass AtomicLong, which would be
+ * efficient and useful otherwise. So, as the lesser of evils, we
+ * natively implement using hotspot intrinsics API. And while we
+ * are at it, we do the same for other CASable fields (which could
+ * otherwise be done with atomic field updaters).
+ */
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private static final long stateOffset;
+ private static final long headOffset;
+ private static final long tailOffset;
+ private static final long waitStatusOffset;
+ private static final long nextOffset;
+
+ static {
+ try {
+ stateOffset = unsafe.objectFieldOffset
+ (AbstractQueuedLongSynchronizer.class.getDeclaredField("state"));
+ headOffset = unsafe.objectFieldOffset
+ (AbstractQueuedLongSynchronizer.class.getDeclaredField("head"));
+ tailOffset = unsafe.objectFieldOffset
+ (AbstractQueuedLongSynchronizer.class.getDeclaredField("tail"));
+ waitStatusOffset = unsafe.objectFieldOffset
+ (Node.class.getDeclaredField("waitStatus"));
+ nextOffset = unsafe.objectFieldOffset
+ (Node.class.getDeclaredField("next"));
+
+ } catch (Exception ex) { throw new Error(ex); }
+ }
+
+ /**
+ * CAS head field. Used only by enq.
+ */
+ private final boolean compareAndSetHead(Node update) {
+ return unsafe.compareAndSwapObject(this, headOffset, null, update);
+ }
+
+ /**
+ * CAS tail field. Used only by enq.
+ */
+ private final boolean compareAndSetTail(Node expect, Node update) {
+ return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
+ }
+
+ /**
+ * CAS waitStatus field of a node.
+ */
+ private final static boolean compareAndSetWaitStatus(Node node,
+ int expect,
+ int update) {
+ return unsafe.compareAndSwapInt(node, waitStatusOffset,
+ expect, update);
+ }
+
+ /**
+ * CAS next field of a node.
+ */
+ private final static boolean compareAndSetNext(Node node,
+ Node expect,
+ Node update) {
+ return unsafe.compareAndSwapObject(node, nextOffset, expect, update);
+ }
+}
diff --git a/concurrent/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java b/concurrent/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
index 8b9821e..66498e3 100644
--- a/concurrent/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
+++ b/concurrent/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
@@ -94,6 +94,12 @@ import sun.misc.Unsafe;
* means of using this class. All other methods are declared
* <tt>final</tt> because they cannot be independently varied.
*
+ * <p>You may also find the inherited methods from {@link
+ * AbstractOwnableSynchronizer} useful to keep track of the thread
+ * owning an exclusive synchronizer. You are encouraged to use them
+ * -- this enables monitoring and diagnostic tools to assist users in
+ * determining which threads hold locks.
+ *
* <p>Even though this class is based on an internal FIFO queue, it
* does not automatically enforce FIFO acquisition policies. The core
* of exclusive synchronization takes the form:
@@ -119,8 +125,9 @@ import sun.misc.Unsafe;
* disable barging by internally invoking one or more of the inspection
* methods, thereby providing a <em>fair</em> FIFO acquisition order.
* In particular, most fair synchronizers can define <tt>tryAcquire</tt>
- * to return <tt>false</tt> if predecessors are queued. Other variations
- * are possible.
+ * to return <tt>false</tt> if {@link #hasQueuedPredecessors} (a method
+ * specifically designed to be used by fair synchronizers) returns
+ * <tt>true</tt>. Other variations are possible.
*
* <p>Throughput and scalability are generally highest for the
* default barging (also known as <em>greedy</em>,
@@ -152,7 +159,10 @@ import sun.misc.Unsafe;
*
* <p>Here is a non-reentrant mutual exclusion lock class that uses
* the value zero to represent the unlocked state, and one to
- * represent the locked state. It also supports conditions and exposes
+ * represent the locked state. While a non-reentrant lock
+ * does not strictly require recording of the current owner
+ * thread, this class does so anyway to make usage easier to monitor.
+ * It also supports conditions and exposes
* one of the instrumentation methods:
*
* <pre>
@@ -168,13 +178,18 @@ import sun.misc.Unsafe;
* // Acquire the lock if state is zero
* public boolean tryAcquire(int acquires) {
* assert acquires == 1; // Otherwise unused
- * return compareAndSetState(0, 1);
+ * if (compareAndSetState(0, 1)) {
+ * setExclusiveOwnerThread(Thread.currentThread());
+ * return true;
+ * }
+ * return false;
* }
*
* // Release the lock by setting state to zero
* protected boolean tryRelease(int releases) {
* assert releases == 1; // Otherwise unused
* if (getState() == 0) throw new IllegalMonitorStateException();
+ * setExclusiveOwnerThread(null);
* setState(0);
* return true;
* }
@@ -787,7 +802,7 @@ public abstract class AbstractQueuedSynchronizer
* @return {@code true} if interrupted
*/
private final boolean parkAndCheckInterrupt() {
- LockSupport.park();
+ LockSupport.park(this);
return Thread.interrupted();
}
@@ -882,7 +897,7 @@ public abstract class AbstractQueuedSynchronizer
return false;
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > spinForTimeoutThreshold)
- LockSupport.parkNanos(nanosTimeout);
+ LockSupport.parkNanos(this, nanosTimeout);
long now = System.nanoTime();
nanosTimeout -= now - lastTime;
lastTime = now;
@@ -986,7 +1001,7 @@ public abstract class AbstractQueuedSynchronizer
return false;
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > spinForTimeoutThreshold)
- LockSupport.parkNanos(nanosTimeout);
+ LockSupport.parkNanos(this, nanosTimeout);
long now = System.nanoTime();
nanosTimeout -= now - lastTime;
lastTime = now;
@@ -1458,8 +1473,10 @@ public abstract class AbstractQueuedSynchronizer
* @return {@code true} if there is a queued thread preceding the
* current thread, and {@code false} if the current thread
* is at the head of the queue or the queue is empty
+ * @since 1.7
+ * @hide
*/
- final boolean hasQueuedPredecessors() {
+ public final boolean hasQueuedPredecessors() {
// The correctness of this depends on head being initialized
// before tail and on head.next being accurate if the current
// thread is first in queue.
@@ -1926,7 +1943,7 @@ public abstract class AbstractQueuedSynchronizer
int savedState = fullyRelease(node);
boolean interrupted = false;
while (!isOnSyncQueue(node)) {
- LockSupport.park();
+ LockSupport.park(this);
if (Thread.interrupted())
interrupted = true;
}
@@ -1993,7 +2010,7 @@ public abstract class AbstractQueuedSynchronizer
int savedState = fullyRelease(node);
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
- LockSupport.park();
+ LockSupport.park(this);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
@@ -2040,7 +2057,7 @@ public abstract class AbstractQueuedSynchronizer
transferAfterCancelledWait(node);
break;
}
- LockSupport.parkNanos(nanosTimeout);
+ LockSupport.parkNanos(this, nanosTimeout);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
@@ -2094,7 +2111,7 @@ public abstract class AbstractQueuedSynchronizer
timedout = transferAfterCancelledWait(node);
break;
}
- LockSupport.parkUntil(abstime);
+ LockSupport.parkUntil(this, abstime);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
@@ -2146,7 +2163,7 @@ public abstract class AbstractQueuedSynchronizer
break;
}
if (nanosTimeout >= spinForTimeoutThreshold)
- LockSupport.parkNanos(nanosTimeout);
+ LockSupport.parkNanos(this, nanosTimeout);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
long now = System.nanoTime();
diff --git a/concurrent/src/main/java/java/util/concurrent/locks/Condition.java b/concurrent/src/main/java/java/util/concurrent/locks/Condition.java
index 03be58f..d75de51 100644
--- a/concurrent/src/main/java/java/util/concurrent/locks/Condition.java
+++ b/concurrent/src/main/java/java/util/concurrent/locks/Condition.java
@@ -421,6 +421,15 @@ public interface Condition {
* <p>If any threads are waiting on this condition then one
* is selected for waking up. That thread must then re-acquire the
* lock before returning from {@code await}.
+ *
+ * <p><b>Implementation Considerations</b>
+ *
+ * <p>The current thread is assumed to hold the lock associated
+ * with this {@code Condition} when this method is called. It is
+ * up to the implementation to determine if this is the case and
+ * if not, how to respond. Typically, an exception will be thrown
+ * (such as {@link IllegalMonitorStateException}) and the
+ * implementation must document that fact.
*/
void signal();
@@ -430,6 +439,15 @@ public interface Condition {
* <p>If any threads are waiting on this condition then they are
* all woken up. Each thread must re-acquire the lock before it can
* return from {@code await}.
+ *
+ * <p><b>Implementation Considerations</b>
+ *
+ * <p>The current thread is assumed to hold the lock associated
+ * with this {@code Condition} when this method is called. It is
+ * up to the implementation to determine if this is the case and
+ * if not, how to respond. Typically, an exception will be thrown
+ * (such as {@link IllegalMonitorStateException}) and the
+ * implementation must document that fact.
*/
void signalAll();
}
diff --git a/concurrent/src/main/java/java/util/concurrent/locks/LockSupport.java b/concurrent/src/main/java/java/util/concurrent/locks/LockSupport.java
index b55b874..ac9a94f 100644
--- a/concurrent/src/main/java/java/util/concurrent/locks/LockSupport.java
+++ b/concurrent/src/main/java/java/util/concurrent/locks/LockSupport.java
@@ -36,6 +36,15 @@ import sun.misc.Unsafe;
* spinning, but must be paired with an {@code unpark} to be
* effective.
*
+ * <p>The three forms of {@code park} each also support a
+ * {@code blocker} object parameter. This object is recorded while
+ * the thread is blocked to permit monitoring and diagnostic tools to
+ * identify the reasons that threads are blocked. (Such tools may
+ * access blockers using method {@link #getBlocker}.) The use of these
+ * forms rather than the original forms without this parameter is
+ * strongly encouraged. The normal argument to supply as a
+ * {@code blocker} within a lock implementation is {@code this}.
+ *
* <p>These methods are designed to be used as tools for creating
* higher-level synchronization utilities, and are not in themselves
* useful for most concurrency control applications. The {@code park}
@@ -78,13 +87,25 @@ import sun.misc.Unsafe;
* }
* }}</pre>
*/
-@SuppressWarnings("all")
+
public class LockSupport {
private LockSupport() {} // Cannot be instantiated.
- // BEGIN android-changed
- private static final Unsafe unsafe = UnsafeAccess.THE_ONE;
- // END android-changed
+ // Hotspot implementation via intrinsics API
+ private static final Unsafe unsafe = UnsafeAccess.THE_ONE; // android-changed
+ private static final long parkBlockerOffset;
+
+ static {
+ try {
+ parkBlockerOffset = unsafe.objectFieldOffset
+ (java.lang.Thread.class.getDeclaredField("parkBlocker"));
+ } catch (Exception ex) { throw new Error(ex); }
+ }
+
+ private static void setBlocker(Thread t, Object arg) {
+ // Even though volatile, hotspot doesn't need a write barrier here.
+ unsafe.putObject(t, parkBlockerOffset, arg);
+ }
/**
* Makes available the permit for the given thread, if it
@@ -106,6 +127,136 @@ public class LockSupport {
* Disables the current thread for thread scheduling purposes unless the
* permit is available.
*
+ * <p>If the permit is available then it is consumed and the call returns
+ * immediately; otherwise
+ * the current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until one of three things happens:
+ *
+ * <ul>
+ * <li>Some other thread invokes {@link #unpark unpark} with the
+ * current thread as the target; or
+ *
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread; or
+ *
+ * <li>The call spuriously (that is, for no reason) returns.
+ * </ul>
+ *
+ * <p>This method does <em>not</em> report which of these caused the
+ * method to return. Callers should re-check the conditions which caused
+ * the thread to park in the first place. Callers may also determine,
+ * for example, the interrupt status of the thread upon return.
+ *
+ * @param blocker the synchronization object responsible for this
+ * thread parking
+ * @since 1.6
+ */
+ public static void park(Object blocker) {
+ Thread t = Thread.currentThread();
+ setBlocker(t, blocker);
+ unsafe.park(false, 0L);
+ setBlocker(t, null);
+ }
+
+ /**
+ * Disables the current thread for thread scheduling purposes, for up to
+ * the specified waiting time, unless the permit is available.
+ *
+ * <p>If the permit is available then it is consumed and the call
+ * returns immediately; otherwise the current thread becomes disabled
+ * for thread scheduling purposes and lies dormant until one of four
+ * things happens:
+ *
+ * <ul>
+ * <li>Some other thread invokes {@link #unpark unpark} with the
+ * current thread as the target; or
+ *
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts} the current
+ * thread; or
+ *
+ * <li>The specified waiting time elapses; or
+ *
+ * <li>The call spuriously (that is, for no reason) returns.
+ * </ul>
+ *
+ * <p>This method does <em>not</em> report which of these caused the
+ * method to return. Callers should re-check the conditions which caused
+ * the thread to park in the first place. Callers may also determine,
+ * for example, the interrupt status of the thread, or the elapsed time
+ * upon return.
+ *
+ * @param blocker the synchronization object responsible for this
+ * thread parking
+ * @param nanos the maximum number of nanoseconds to wait
+ * @since 1.6
+ */
+ public static void parkNanos(Object blocker, long nanos) {
+ if (nanos > 0) {
+ Thread t = Thread.currentThread();
+ setBlocker(t, blocker);
+ unsafe.park(false, nanos);
+ setBlocker(t, null);
+ }
+ }
+
+ /**
+ * Disables the current thread for thread scheduling purposes, until
+ * the specified deadline, unless the permit is available.
+ *
+ * <p>If the permit is available then it is consumed and the call
+ * returns immediately; otherwise the current thread becomes disabled
+ * for thread scheduling purposes and lies dormant until one of four
+ * things happens:
+ *
+ * <ul>
+ * <li>Some other thread invokes {@link #unpark unpark} with the
+ * current thread as the target; or
+ *
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts} the
+ * current thread; or
+ *
+ * <li>The specified deadline passes; or
+ *
+ * <li>The call spuriously (that is, for no reason) returns.
+ * </ul>
+ *
+ * <p>This method does <em>not</em> report which of these caused the
+ * method to return. Callers should re-check the conditions which caused
+ * the thread to park in the first place. Callers may also determine,
+ * for example, the interrupt status of the thread, or the current time
+ * upon return.
+ *
+ * @param blocker the synchronization object responsible for this
+ * thread parking
+ * @param deadline the absolute time, in milliseconds from the Epoch,
+ * to wait until
+ * @since 1.6
+ */
+ public static void parkUntil(Object blocker, long deadline) {
+ Thread t = Thread.currentThread();
+ setBlocker(t, blocker);
+ unsafe.park(true, deadline);
+ setBlocker(t, null);
+ }
+
+ /**
+ * Returns the blocker object supplied to the most recent
+ * invocation of a park method that has not yet unblocked, or null
+ * if not blocked. The value returned is just a momentary
+ * snapshot -- the thread may have since unblocked or blocked on a
+ * different blocker object.
+ *
+ * @return the blocker
+ * @since 1.6
+ */
+ public static Object getBlocker(Thread t) {
+ return unsafe.getObjectVolatile(t, parkBlockerOffset);
+ }
+
+ /**
+ * Disables the current thread for thread scheduling purposes unless the
+ * permit is available.
+ *
* <p>If the permit is available then it is consumed and the call
* returns immediately; otherwise the current thread becomes disabled
* for thread scheduling purposes and lies dormant until one of three
diff --git a/concurrent/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java b/concurrent/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java
index c923944..bfaff06 100644
--- a/concurrent/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java
+++ b/concurrent/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java
@@ -1161,6 +1161,32 @@ public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializab
"[Locked by thread " + o.getName() + "]");
}
+ /**
+ * Queries if this write lock is held by the current thread.
+ * Identical in effect to {@link
+ * ReentrantReadWriteLock#isWriteLockedByCurrentThread}.
+ *
+ * @return {@code true} if the current thread holds this lock and
+ * {@code false} otherwise
+ * @since 1.6
+ */
+ public boolean isHeldByCurrentThread() {
+ return sync.isHeldExclusively();
+ }
+
+ /**
+ * Queries the number of holds on this write lock by the current
+ * thread. A thread has a hold on a lock for each lock action
+ * that is not matched by an unlock action. Identical in effect
+ * to {@link ReentrantReadWriteLock#getWriteHoldCount}.
+ *
+ * @return the number of holds on this lock by the current thread,
+ * or zero if this lock is not held by the current thread
+ * @since 1.6
+ */
+ public int getHoldCount() {
+ return sync.getWriteHoldCount();
+ }
}
// Instrumentation and status
@@ -1236,6 +1262,19 @@ public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializab
}
/**
+ * Queries the number of reentrant read holds on this lock by the
+ * current thread. A reader 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 the read lock by the current thread,
+ * or zero if the read lock is not held by the current thread
+ * @since 1.6
+ */
+ public int getReadHoldCount() {
+ return sync.getReadHoldCount();
+ }
+
+ /**
* 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
diff --git a/concurrent/src/main/java/java/util/concurrent/locks/package-info.java b/concurrent/src/main/java/java/util/concurrent/locks/package-info.java
index 801ee9b..860acdd 100644
--- a/concurrent/src/main/java/java/util/concurrent/locks/package-info.java
+++ b/concurrent/src/main/java/java/util/concurrent/locks/package-info.java
@@ -34,10 +34,16 @@
*
* <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.
+ * synchronizers that rely on queuing blocked threads. The {@link
+ * java.util.concurrent.locks.AbstractQueuedLongSynchronizer} class
+ * provides the same functionality but extends support to 64 bits of
+ * synchronization state. Both extend class {@link
+ * java.util.concurrent.locks.AbstractOwnableSynchronizer}, a simple
+ * class that helps record the thread currently holding exclusive
+ * synchronization. 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
*/
diff --git a/concurrent/src/main/java/java/util/concurrent/package-info.java b/concurrent/src/main/java/java/util/concurrent/package-info.java
index d49ef25..dd3a22d 100644
--- a/concurrent/src/main/java/java/util/concurrent/package-info.java
+++ b/concurrent/src/main/java/java/util/concurrent/package-info.java
@@ -41,6 +41,10 @@
* a function, allows determination of whether execution has
* completed, and provides a means to cancel execution.
*
+ * A {@link java.util.concurrent.RunnableFuture} is a {@code Future}
+ * that possesses a {@code run} method that upon execution,
+ * sets its results.
+ *
* <p>
*
* <b>Implementations.</b>
@@ -59,6 +63,13 @@
* assists in coordinating the processing of groups of
* asynchronous tasks.
*
+ * <p>Class {@link java.util.concurrent.ForkJoinPool} provides an
+ * Executor primarily designed for processing instances of {@link
+ * java.util.concurrent.ForkJoinTask} and its subclasses. These
+ * classes employ a work-stealing scheduler that attains high
+ * throughput for tasks conforming to restrictions that often hold in
+ * computation-intensive parallel processing.
+ *
* <h2>Queues</h2>
*
* The {@link java.util.concurrent.ConcurrentLinkedQueue} class
@@ -77,6 +88,18 @@
* for producer-consumer, messaging, parallel tasking, and
* related concurrent designs.
*
+ * <p> Extended interface {@link java.util.concurrent.TransferQueue},
+ * and implementation {@link java.util.concurrent.LinkedTransferQueue}
+ * introduce a synchronous {@code transfer} method (along with related
+ * features) in which a producer may optionally block awaiting its
+ * consumer.
+ *
+ * <p>The {@link java.util.concurrent.BlockingDeque} interface
+ * extends {@code BlockingQueue} to support both FIFO and LIFO
+ * (stack-based) operations.
+ * Class {@link java.util.concurrent.LinkedBlockingDeque}
+ * provides an implementation.
+ *
* <h2>Timing</h2>
*
* The {@link java.util.concurrent.TimeUnit} class provides
@@ -97,28 +120,45 @@
*
* <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.
+ * Five classes aid common special-purpose synchronization idioms.
+ * <ul>
+ *
+ * <li>{@link java.util.concurrent.Semaphore} is a classic concurrency tool.
+ *
+ * <li>{@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.
+ *
+ * <li>A {@link java.util.concurrent.CyclicBarrier} is a resettable
+ * multiway synchronization point useful in some styles of parallel
+ * programming.
+ *
+ * <li>A {@link java.util.concurrent.Phaser} provides
+ * a more flexible form of barrier that may be used to control phased
+ * computation among multiple threads.
+ *
+ * <li>An {@link java.util.concurrent.Exchanger} allows two threads to
+ * exchange objects at a rendezvous point, and is useful in several
+ * pipeline designs.
+ *
+ * </ul>
*
* <h2>Concurrent Collections</h2>
*
* Besides Queues, this package supplies Collection implementations
* designed for use in multithreaded contexts:
* {@link java.util.concurrent.ConcurrentHashMap},
+ * {@link java.util.concurrent.ConcurrentSkipListMap},
+ * {@link java.util.concurrent.ConcurrentSkipListSet},
* {@link java.util.concurrent.CopyOnWriteArrayList}, and
* {@link java.util.concurrent.CopyOnWriteArraySet}.
* When many threads are expected to access a given collection, a
* {@code ConcurrentHashMap} is normally preferable to a synchronized
- * {@code HashMap}. A {@code CopyOnWriteArrayList} is preferable to a
- * synchronized {@code ArrayList} when the expected number of reads and
- * traversals greatly outnumber the number of updates to a list.
+ * {@code HashMap}, and a {@code ConcurrentSkipListMap} is normally
+ * preferable to a synchronized {@code TreeMap}.
+ * A {@code CopyOnWriteArrayList} is preferable to a synchronized
+ * {@code ArrayList} when the expected number of reads and traversals
+ * greatly outnumber the number of updates to a list.
* <p>The "Concurrent" prefix used with some classes in this package
* is a shorthand indicating several differences from similar
@@ -216,7 +256,8 @@
* in each thread <i>happen-before</i> those subsequent to the
* corresponding {@code exchange()} in another thread.
*
- * <li>Actions prior to calling {@code CyclicBarrier.await}
+ * <li>Actions prior to calling {@code CyclicBarrier.await} and
+ * {@code Phaser.awaitAdvance} (as well as its variants)
* <i>happen-before</i> actions performed by the barrier action, and
* actions performed by the barrier action <i>happen-before</i> actions
* subsequent to a successful return from the corresponding {@code await}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/AbstractExecutorServiceTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/AbstractExecutorServiceTest.java
index b80fe64..a8db7ad 100644
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/AbstractExecutorServiceTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/AbstractExecutorServiceTest.java
@@ -2,24 +2,25 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.*;
import java.util.concurrent.*;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.math.BigInteger;
import java.security.*;
-public class AbstractExecutorServiceTest extends JSR166TestCase{
+public class AbstractExecutorServiceTest extends JSR166TestCase {
public static Test suite() {
return new TestSuite(AbstractExecutorServiceTest.class);
}
- /**
+ /**
* A no-frills implementation of AbstractExecutorService, designed
* to test the submit methods only.
*/
@@ -36,188 +37,106 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
/**
* 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();
- }
+ public void testExecuteRunnable() throws Exception {
+ ExecutorService e = new DirectExecutorService();
+ TrackedShortRunnable task = new TrackedShortRunnable();
+ assertFalse(task.done);
+ Future<?> future = e.submit(task);
+ future.get();
+ assertTrue(task.done);
}
/**
* 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();
- }
+ public void testSubmitCallable() throws Exception {
+ ExecutorService e = new DirectExecutorService();
+ Future<String> future = e.submit(new StringTask());
+ String result = future.get();
+ assertSame(TEST_STRING, result);
}
/**
* 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();
- }
+ public void testSubmitRunnable() throws Exception {
+ ExecutorService e = new DirectExecutorService();
+ Future<?> future = e.submit(new NoOpRunnable());
+ future.get();
+ assertTrue(future.isDone());
}
/**
* 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();
- }
+ public void testSubmitRunnable2() throws Exception {
+ ExecutorService e = new DirectExecutorService();
+ Future<String> future = e.submit(new NoOpRunnable(), TEST_STRING);
+ String result = future.get();
+ assertSame(TEST_STRING, result);
}
/**
- * A submitted privileged action to completion
+ * A submitted privileged action runs 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 void testSubmitPrivilegedAction() throws Exception {
+ Runnable r = new CheckedRunnable() {
+ public void realRun() throws Exception {
+ 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;
- }
- }
+ assertSame(TEST_STRING, future.get());
+ }};
+
+ runWithPermissions(r,
+ new RuntimePermission("getClassLoader"),
+ new RuntimePermission("setContextClassLoader"),
+ new RuntimePermission("modifyThread"));
}
/**
- * A submitted a privileged exception action runs to completion
+ * A submitted 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 void testSubmitPrivilegedExceptionAction() throws Exception {
+ Runnable r = new CheckedRunnable() {
+ public void realRun() throws Exception {
+ 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);
- }
+ assertSame(TEST_STRING, future.get());
+ }};
+
+ runWithPermissions(r);
}
/**
* 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 void testSubmitFailedPrivilegedExceptionAction() throws Exception {
+ Runnable r = new CheckedRunnable() {
+ public void realRun() throws Exception {
+ 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);
- }
+ try {
+ future.get();
+ shouldThrow();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof IndexOutOfBoundsException);
+ }}};
+
+ runWithPermissions(r);
}
/**
@@ -226,15 +145,9 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
public void testExecuteNullRunnable() {
try {
ExecutorService e = new DirectExecutorService();
- TrackedShortRunnable task = null;
- Future<?> future = e.submit(task);
+ e.submit((Runnable) null);
shouldThrow();
- }
- catch (NullPointerException success) {
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ } catch (NullPointerException success) {}
}
@@ -244,15 +157,9 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
public void testSubmitNullCallable() {
try {
ExecutorService e = new DirectExecutorService();
- StringTask t = null;
- Future<String> future = e.submit(t);
+ e.submit((Callable) null);
shouldThrow();
- }
- catch (NullPointerException success) {
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ } catch (NullPointerException success) {}
}
/**
@@ -260,15 +167,22 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
* executor is saturated.
*/
public void testExecute1() {
- ThreadPoolExecutor p = new ThreadPoolExecutor(1,1, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1));
+ ThreadPoolExecutor p =
+ new ThreadPoolExecutor(1, 1,
+ 60, TimeUnit.SECONDS,
+ new ArrayBlockingQueue<Runnable>(1));
try {
-
- for(int i = 0; i < 5; ++i){
+ for (int i = 0; i < 2; ++i)
p.submit(new MediumRunnable());
+ for (int i = 0; i < 2; ++i) {
+ try {
+ p.submit(new MediumRunnable());
+ shouldThrow();
+ } catch (RejectedExecutionException success) {}
}
- shouldThrow();
- } catch(RejectedExecutionException success){}
- joinPool(p);
+ } finally {
+ joinPool(p);
+ }
}
/**
@@ -276,14 +190,22 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
* if executor is saturated.
*/
public void testExecute2() {
- ThreadPoolExecutor p = new ThreadPoolExecutor(1,1, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1));
+ 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());
+ for (int i = 0; i < 2; ++i)
+ p.submit(new MediumRunnable());
+ for (int i = 0; i < 2; ++i) {
+ try {
+ p.submit(new SmallCallable());
+ shouldThrow();
+ } catch (RejectedExecutionException success) {}
}
- shouldThrow();
- } catch(RejectedExecutionException e){}
- joinPool(p);
+ } finally {
+ joinPool(p);
+ }
}
@@ -291,75 +213,43 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
* Blocking on submit(callable) throws InterruptedException if
* caller interrupted.
*/
- public void testInterruptedSubmit() {
+ public void testInterruptedSubmit() throws InterruptedException {
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();
- }
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws Exception {
+ p.submit(new CheckedCallable<Object>() {
+ public Object realCall()
+ throws InterruptedException {
+ Thread.sleep(SMALL_DELAY_MS);
+ return null;
+ }}).get();
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
joinPool(p);
}
/**
- * get of submitted callable throws Exception if callable
+ * get of submitted callable throws InterruptedException 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();
- }
-
+ public void testSubmitIE() throws InterruptedException {
+ final ThreadPoolExecutor p =
+ new ThreadPoolExecutor(1, 1,
+ 60, TimeUnit.SECONDS,
+ new ArrayBlockingQueue<Runnable>(10));
+
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws Exception {
+ p.submit(new SmallCallable()).get();
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
joinPool(p);
}
@@ -367,26 +257,20 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
* 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));
+ public void testSubmitEE() throws InterruptedException {
+ 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();
- }
+ Callable c = new Callable() {
+ public Object call() { return 5/0; }};
+ try {
+ p.submit(c).get();
shouldThrow();
- }
- catch(ExecutionException success){
- } catch(Exception e) {
- unexpectedException();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof ArithmeticException);
}
joinPool(p);
}
@@ -394,13 +278,13 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
/**
* invokeAny(null) throws NPE
*/
- public void testInvokeAny1() {
+ public void testInvokeAny1()
+ throws InterruptedException, ExecutionException {
ExecutorService e = new DirectExecutorService();
try {
e.invokeAny(null);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -409,13 +293,13 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
/**
* invokeAny(empty collection) throws IAE
*/
- public void testInvokeAny2() {
+ public void testInvokeAny2()
+ throws InterruptedException, ExecutionException {
ExecutorService e = new DirectExecutorService();
try {
e.invokeAny(new ArrayList<Callable<String>>());
+ shouldThrow();
} catch (IllegalArgumentException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -424,17 +308,16 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
/**
* invokeAny(c) throws NPE if c has null elements
*/
- public void testInvokeAny3() {
+ public void testInvokeAny3() throws Exception {
ExecutorService e = new DirectExecutorService();
+ List<Callable<Integer>> l = new ArrayList<Callable<Integer>>();
+ l.add(new Callable<Integer>() {
+ public Integer call() { return 5/0; }});
+ l.add(null);
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
- l.add(new StringTask());
- l.add(null);
e.invokeAny(l);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- ex.printStackTrace();
- unexpectedException();
} finally {
joinPool(e);
}
@@ -443,15 +326,15 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
/**
* invokeAny(c) throws ExecutionException if no task in c completes
*/
- public void testInvokeAny4() {
+ public void testInvokeAny4() throws InterruptedException {
ExecutorService e = new DirectExecutorService();
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new NPETask());
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
- l.add(new NPETask());
e.invokeAny(l);
- } catch(ExecutionException success) {
- } catch(Exception ex) {
- unexpectedException();
+ shouldThrow();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof NullPointerException);
} finally {
joinPool(e);
}
@@ -460,17 +343,14 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
/**
* invokeAny(c) returns result of some task in c if at least one completes
*/
- public void testInvokeAny5() {
+ public void testInvokeAny5() throws Exception {
ExecutorService e = new DirectExecutorService();
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<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);
}
@@ -479,13 +359,12 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
/**
* invokeAll(null) throws NPE
*/
- public void testInvokeAll1() {
+ public void testInvokeAll1() throws InterruptedException {
ExecutorService e = new DirectExecutorService();
try {
e.invokeAll(null);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -494,13 +373,11 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
/**
* invokeAll(empty collection) returns empty collection
*/
- public void testInvokeAll2() {
+ public void testInvokeAll2() throws InterruptedException {
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);
}
@@ -509,16 +386,15 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
/**
* invokeAll(c) throws NPE if c has null elements
*/
- public void testInvokeAll3() {
+ public void testInvokeAll3() throws InterruptedException {
ExecutorService e = new DirectExecutorService();
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(null);
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
- l.add(new StringTask());
- l.add(null);
e.invokeAll(l);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -527,18 +403,19 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
/**
* get of returned element of invokeAll(c) throws exception on failed task
*/
- public void testInvokeAll4() {
+ public void testInvokeAll4() throws Exception {
ExecutorService e = new DirectExecutorService();
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<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();
+ List<Future<String>> futures = e.invokeAll(l);
+ assertEquals(1, futures.size());
+ try {
+ futures.get(0).get();
+ shouldThrow();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof NullPointerException);
+ }
} finally {
joinPool(e);
}
@@ -547,19 +424,16 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
/**
* invokeAll(c) returns results of all completed tasks in c
*/
- public void testInvokeAll5() {
+ public void testInvokeAll5() throws Exception {
ExecutorService e = new DirectExecutorService();
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<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();
+ List<Future<String>> futures = e.invokeAll(l);
+ assertEquals(2, futures.size());
+ for (Future<String> future : futures)
+ assertSame(TEST_STRING, future.get());
} finally {
joinPool(e);
}
@@ -569,13 +443,12 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
/**
* timed invokeAny(null) throws NPE
*/
- public void testTimedInvokeAny1() {
+ public void testTimedInvokeAny1() throws Exception {
ExecutorService e = new DirectExecutorService();
try {
- e.invokeAny(null, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -584,15 +457,14 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
/**
* timed invokeAny(null time unit) throws NPE
*/
- public void testTimedInvokeAnyNullTimeUnit() {
+ public void testTimedInvokeAnyNullTimeUnit() throws Exception {
ExecutorService e = new DirectExecutorService();
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
- l.add(new StringTask());
e.invokeAny(l, MEDIUM_DELAY_MS, null);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -601,13 +473,12 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
/**
* timed invokeAny(empty collection) throws IAE
*/
- public void testTimedInvokeAny2() {
+ public void testTimedInvokeAny2() throws Exception {
ExecutorService e = new DirectExecutorService();
try {
- e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
} catch (IllegalArgumentException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -616,17 +487,16 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
/**
* timed invokeAny(c) throws NPE if c has null elements
*/
- public void testTimedInvokeAny3() {
+ public void testTimedInvokeAny3() throws Exception {
ExecutorService e = new DirectExecutorService();
+ List<Callable<Integer>> l = new ArrayList<Callable<Integer>>();
+ l.add(new Callable<Integer>() {
+ public Integer call() { return 5/0; }});
+ l.add(null);
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
- l.add(new StringTask());
- l.add(null);
- e.invokeAny(l, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- ex.printStackTrace();
- unexpectedException();
} finally {
joinPool(e);
}
@@ -635,15 +505,15 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
/**
* timed invokeAny(c) throws ExecutionException if no task completes
*/
- public void testTimedInvokeAny4() {
+ public void testTimedInvokeAny4() throws Exception {
ExecutorService e = new DirectExecutorService();
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new NPETask());
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();
+ e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof NullPointerException);
} finally {
joinPool(e);
}
@@ -652,17 +522,14 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
/**
* timed invokeAny(c) returns result of some task in c
*/
- public void testTimedInvokeAny5() {
+ public void testTimedInvokeAny5() throws Exception {
ExecutorService e = new DirectExecutorService();
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<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);
+ String result = e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
assertSame(TEST_STRING, result);
- } catch (ExecutionException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -671,13 +538,12 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
/**
* timed invokeAll(null) throws NPE
*/
- public void testTimedInvokeAll1() {
+ public void testTimedInvokeAll1() throws InterruptedException {
ExecutorService e = new DirectExecutorService();
try {
- e.invokeAll(null, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -686,15 +552,14 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
/**
* timed invokeAll(null time unit) throws NPE
*/
- public void testTimedInvokeAllNullTimeUnit() {
+ public void testTimedInvokeAllNullTimeUnit() throws InterruptedException {
ExecutorService e = new DirectExecutorService();
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
- l.add(new StringTask());
e.invokeAll(l, MEDIUM_DELAY_MS, null);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -703,13 +568,11 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
/**
* timed invokeAll(empty collection) returns empty collection
*/
- public void testTimedInvokeAll2() {
+ public void testTimedInvokeAll2() throws InterruptedException {
ExecutorService e = new DirectExecutorService();
try {
- List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
assertTrue(r.isEmpty());
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -718,16 +581,15 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
/**
* timed invokeAll(c) throws NPE if c has null elements
*/
- public void testTimedInvokeAll3() {
+ public void testTimedInvokeAll3() throws InterruptedException {
ExecutorService e = new DirectExecutorService();
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(null);
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
- l.add(new StringTask());
- l.add(null);
- e.invokeAll(l, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -736,18 +598,20 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
/**
* get of returned element of invokeAll(c) throws exception on failed task
*/
- public void testTimedInvokeAll4() {
+ public void testTimedInvokeAll4() throws Exception {
ExecutorService e = new DirectExecutorService();
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<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();
+ List<Future<String>> futures =
+ e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ assertEquals(1, futures.size());
+ try {
+ futures.get(0).get();
+ shouldThrow();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof NullPointerException);
+ }
} finally {
joinPool(e);
}
@@ -756,19 +620,17 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
/**
* timed invokeAll(c) returns results of all completed tasks in c
*/
- public void testTimedInvokeAll5() {
+ public void testTimedInvokeAll5() throws Exception {
ExecutorService e = new DirectExecutorService();
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<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();
+ List<Future<String>> futures =
+ e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ assertEquals(2, futures.size());
+ for (Future<String> future : futures)
+ assertSame(TEST_STRING, future.get());
} finally {
joinPool(e);
}
@@ -777,16 +639,17 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
/**
* timed invokeAll cancels tasks not completed by timeout
*/
- public void testTimedInvokeAll6() {
+ public void testTimedInvokeAll6() throws InterruptedException {
ExecutorService e = new DirectExecutorService();
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<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();
+ List<Future<String>> futures =
+ e.invokeAll(l, SMALL_DELAY_MS, MILLISECONDS);
+ assertEquals(3, futures.size());
+ Iterator<Future<String>> it = futures.iterator();
Future<String> f1 = it.next();
Future<String> f2 = it.next();
Future<String> f3 = it.next();
@@ -795,8 +658,6 @@ public class AbstractExecutorServiceTest extends JSR166TestCase{
assertTrue(f2.isDone());
assertTrue(f3.isDone());
assertTrue(f3.isCancelled());
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/AbstractQueueTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/AbstractQueueTest.java
index 660fec9..9bb206b 100644
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/AbstractQueueTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/AbstractQueueTest.java
@@ -2,11 +2,11 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.*;
@@ -20,9 +20,9 @@ public class AbstractQueueTest extends JSR166TestCase {
}
static class Succeed extends AbstractQueue<Integer> {
- public boolean offer(Integer x) {
+ public boolean offer(Integer x) {
if (x == null) throw new NullPointerException();
- return true;
+ return true;
}
public Integer peek() { return one; }
public Integer poll() { return one; }
@@ -31,9 +31,9 @@ public class AbstractQueueTest extends JSR166TestCase {
}
static class Fail extends AbstractQueue<Integer> {
- public boolean offer(Integer x) {
+ public boolean offer(Integer x) {
if (x == null) throw new NullPointerException();
- return false;
+ return false;
}
public Integer peek() { return null; }
public Integer poll() { return null; }
@@ -57,8 +57,7 @@ public class AbstractQueueTest extends JSR166TestCase {
try {
q.add(one);
shouldThrow();
- } catch (IllegalStateException success) {
- }
+ } catch (IllegalStateException success) {}
}
/**
@@ -69,8 +68,7 @@ public class AbstractQueueTest extends JSR166TestCase {
try {
q.add(null);
shouldThrow();
- } catch (NullPointerException success) {
- }
+ } catch (NullPointerException success) {}
}
/**
@@ -89,8 +87,7 @@ public class AbstractQueueTest extends JSR166TestCase {
try {
q.remove();
shouldThrow();
- } catch (NoSuchElementException success) {
- }
+ } catch (NoSuchElementException success) {}
}
@@ -110,8 +107,7 @@ public class AbstractQueueTest extends JSR166TestCase {
try {
q.element();
shouldThrow();
- } catch (NoSuchElementException success) {
- }
+ } catch (NoSuchElementException success) {}
}
/**
@@ -122,8 +118,7 @@ public class AbstractQueueTest extends JSR166TestCase {
Succeed q = new Succeed();
q.addAll(null);
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
@@ -134,8 +129,7 @@ public class AbstractQueueTest extends JSR166TestCase {
Succeed q = new Succeed();
q.addAll(q);
shouldThrow();
- }
- catch (IllegalArgumentException success) {}
+ } catch (IllegalArgumentException success) {}
}
@@ -148,8 +142,7 @@ public class AbstractQueueTest extends JSR166TestCase {
Integer[] ints = new Integer[SIZE];
q.addAll(Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
* addAll of a collection with any null elements throws NPE after
@@ -163,8 +156,7 @@ public class AbstractQueueTest extends JSR166TestCase {
ints[i] = new Integer(i);
q.addAll(Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
* addAll throws ISE if an add fails
@@ -177,8 +169,7 @@ public class AbstractQueueTest extends JSR166TestCase {
ints[i] = new Integer(i);
q.addAll(Arrays.asList(ints));
shouldThrow();
- }
- catch (IllegalStateException success) {}
+ } catch (IllegalStateException success) {}
}
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/AbstractQueuedLongSynchronizerTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/AbstractQueuedLongSynchronizerTest.java
new file mode 100644
index 0000000..43a4bd1
--- /dev/null
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/AbstractQueuedLongSynchronizerTest.java
@@ -0,0 +1,1025 @@
+/*
+ * 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.
+ */
+
+package tests.api.java.util.concurrent; // android-added
+
+import junit.framework.*;
+import java.util.*;
+import java.util.concurrent.*;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import java.util.concurrent.locks.*;
+import java.io.*;
+
+public class AbstractQueuedLongSynchronizerTest extends JSR166TestCase {
+ public static Test suite() {
+ return new TestSuite(AbstractQueuedLongSynchronizerTest.class);
+ }
+
+ /**
+ * A simple mutex class, adapted from the
+ * AbstractQueuedLongSynchronizer javadoc. Exclusive acquire tests
+ * exercise this as a sample user extension. Other
+ * methods/features of AbstractQueuedLongSynchronizerTest are tested
+ * via other test classes, including those for ReentrantLock,
+ * ReentrantReadWriteLock, and Semaphore
+ */
+ static class Mutex extends AbstractQueuedLongSynchronizer {
+ // Use value > 32 bits for locked state
+ static final long LOCKED = 1 << 48;
+ public boolean isHeldExclusively() {
+ return getState() == LOCKED;
+ }
+
+ public boolean tryAcquire(long acquires) {
+ return compareAndSetState(0, LOCKED);
+ }
+
+ public boolean tryRelease(long releases) {
+ if (getState() == 0) throw new IllegalMonitorStateException();
+ setState(0);
+ return true;
+ }
+
+ public AbstractQueuedLongSynchronizer.ConditionObject newCondition() { return new AbstractQueuedLongSynchronizer.ConditionObject(); }
+
+ }
+
+
+ /**
+ * A simple latch class, to test shared mode.
+ */
+ static class BooleanLatch extends AbstractQueuedLongSynchronizer {
+ public boolean isSignalled() { return getState() != 0; }
+
+ public long tryAcquireShared(long ignore) {
+ return isSignalled()? 1 : -1;
+ }
+
+ public boolean tryReleaseShared(long ignore) {
+ setState(1 << 62);
+ return true;
+ }
+ }
+
+ /**
+ * A runnable calling acquireInterruptibly that does not expect to
+ * be interrupted.
+ */
+ class InterruptibleSyncRunnable extends CheckedRunnable {
+ final Mutex sync;
+ InterruptibleSyncRunnable(Mutex l) { sync = l; }
+ public void realRun() throws InterruptedException {
+ sync.acquireInterruptibly(1);
+ }
+ }
+
+
+ /**
+ * A runnable calling acquireInterruptibly that expects to be
+ * interrupted.
+ */
+ class InterruptedSyncRunnable extends CheckedInterruptedRunnable {
+ final Mutex sync;
+ InterruptedSyncRunnable(Mutex l) { sync = l; }
+ public void realRun() throws InterruptedException {
+ sync.acquireInterruptibly(1);
+ }
+ }
+
+ /**
+ * isHeldExclusively is false upon construction
+ */
+ public void testIsHeldExclusively() {
+ Mutex rl = new Mutex();
+ assertFalse(rl.isHeldExclusively());
+ }
+
+ /**
+ * acquiring released sync succeeds
+ */
+ public void testAcquire() {
+ Mutex rl = new Mutex();
+ rl.acquire(1);
+ assertTrue(rl.isHeldExclusively());
+ rl.release(1);
+ assertFalse(rl.isHeldExclusively());
+ }
+
+ /**
+ * tryAcquire on an released sync succeeds
+ */
+ public void testTryAcquire() {
+ Mutex rl = new Mutex();
+ assertTrue(rl.tryAcquire(1));
+ assertTrue(rl.isHeldExclusively());
+ rl.release(1);
+ }
+
+ /**
+ * hasQueuedThreads reports whether there are waiting threads
+ */
+ public void testhasQueuedThreads() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
+ Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
+ assertFalse(sync.hasQueuedThreads());
+ sync.acquire(1);
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.hasQueuedThreads());
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.hasQueuedThreads());
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.hasQueuedThreads());
+ sync.release(1);
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(sync.hasQueuedThreads());
+ t1.join();
+ t2.join();
+ }
+
+ /**
+ * isQueued(null) throws NPE
+ */
+ public void testIsQueuedNPE() {
+ final Mutex sync = new Mutex();
+ try {
+ sync.isQueued(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * isQueued reports whether a thread is queued.
+ */
+ public void testIsQueued() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
+ Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
+ assertFalse(sync.isQueued(t1));
+ assertFalse(sync.isQueued(t2));
+ sync.acquire(1);
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.isQueued(t1));
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.isQueued(t1));
+ assertTrue(sync.isQueued(t2));
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(sync.isQueued(t1));
+ assertTrue(sync.isQueued(t2));
+ sync.release(1);
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(sync.isQueued(t1));
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(sync.isQueued(t2));
+ t1.join();
+ t2.join();
+ }
+
+ /**
+ * getFirstQueuedThread returns first waiting thread or null if none
+ */
+ public void testGetFirstQueuedThread() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
+ Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
+ assertNull(sync.getFirstQueuedThread());
+ sync.acquire(1);
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(t1, sync.getFirstQueuedThread());
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(t1, sync.getFirstQueuedThread());
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(t2, sync.getFirstQueuedThread());
+ sync.release(1);
+ Thread.sleep(SHORT_DELAY_MS);
+ assertNull(sync.getFirstQueuedThread());
+ t1.join();
+ t2.join();
+ }
+
+
+ /**
+ * hasContended reports false if no thread has ever blocked, else true
+ */
+ public void testHasContended() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
+ Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
+ assertFalse(sync.hasContended());
+ sync.acquire(1);
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.hasContended());
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.hasContended());
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.hasContended());
+ sync.release(1);
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.hasContended());
+ t1.join();
+ t2.join();
+ }
+
+ /**
+ * getQueuedThreads includes waiting threads
+ */
+ public void testGetQueuedThreads() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
+ Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
+ assertTrue(sync.getQueuedThreads().isEmpty());
+ sync.acquire(1);
+ assertTrue(sync.getQueuedThreads().isEmpty());
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.getQueuedThreads().contains(t1));
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.getQueuedThreads().contains(t1));
+ assertTrue(sync.getQueuedThreads().contains(t2));
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(sync.getQueuedThreads().contains(t1));
+ assertTrue(sync.getQueuedThreads().contains(t2));
+ sync.release(1);
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.getQueuedThreads().isEmpty());
+ t1.join();
+ t2.join();
+ }
+
+ /**
+ * getExclusiveQueuedThreads includes waiting threads
+ */
+ public void testGetExclusiveQueuedThreads() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
+ Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
+ assertTrue(sync.getExclusiveQueuedThreads().isEmpty());
+ sync.acquire(1);
+ assertTrue(sync.getExclusiveQueuedThreads().isEmpty());
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.getExclusiveQueuedThreads().contains(t1));
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.getExclusiveQueuedThreads().contains(t1));
+ assertTrue(sync.getExclusiveQueuedThreads().contains(t2));
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(sync.getExclusiveQueuedThreads().contains(t1));
+ assertTrue(sync.getExclusiveQueuedThreads().contains(t2));
+ sync.release(1);
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.getExclusiveQueuedThreads().isEmpty());
+ t1.join();
+ t2.join();
+ }
+
+ /**
+ * getSharedQueuedThreads does not include exclusively waiting threads
+ */
+ public void testGetSharedQueuedThreads() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
+ Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
+ assertTrue(sync.getSharedQueuedThreads().isEmpty());
+ sync.acquire(1);
+ assertTrue(sync.getSharedQueuedThreads().isEmpty());
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.getSharedQueuedThreads().isEmpty());
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.getSharedQueuedThreads().isEmpty());
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.getSharedQueuedThreads().isEmpty());
+ sync.release(1);
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.getSharedQueuedThreads().isEmpty());
+ t1.join();
+ t2.join();
+ }
+
+ /**
+ * tryAcquireNanos is interruptible.
+ */
+ public void testInterruptedException2() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ sync.acquire(1);
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.tryAcquireNanos(1, MILLISECONDS.toNanos(MEDIUM_DELAY_MS));
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
+ }
+
+
+ /**
+ * TryAcquire on exclusively held sync fails
+ */
+ public void testTryAcquireWhenSynced() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ sync.acquire(1);
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ threadAssertFalse(sync.tryAcquire(1));
+ }});
+
+ t.start();
+ t.join();
+ sync.release(1);
+ }
+
+ /**
+ * tryAcquireNanos on an exclusively held sync times out
+ */
+ public void testAcquireNanos_Timeout() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ sync.acquire(1);
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ long nanos = MILLISECONDS.toNanos(SHORT_DELAY_MS);
+ assertFalse(sync.tryAcquireNanos(1, nanos));
+ }});
+
+ t.start();
+ t.join();
+ sync.release(1);
+ }
+
+
+ /**
+ * getState is true when acquired and false when not
+ */
+ public void testGetState() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ sync.acquire(1);
+ assertTrue(sync.isHeldExclusively());
+ sync.release(1);
+ assertFalse(sync.isHeldExclusively());
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire(1);
+ Thread.sleep(SMALL_DELAY_MS);
+ sync.release(1);
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.isHeldExclusively());
+ t.join();
+ assertFalse(sync.isHeldExclusively());
+ }
+
+
+ /**
+ * acquireInterruptibly is interruptible.
+ */
+ public void testAcquireInterruptibly1() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ sync.acquire(1);
+ Thread t = new Thread(new InterruptedSyncRunnable(sync));
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ sync.release(1);
+ t.join();
+ }
+
+ /**
+ * acquireInterruptibly succeeds when released, else is interruptible
+ */
+ public void testAcquireInterruptibly2() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ sync.acquireInterruptibly(1);
+ Thread t = new Thread(new InterruptedSyncRunnable(sync));
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ assertTrue(sync.isHeldExclusively());
+ t.join();
+ }
+
+ /**
+ * owns is true for a condition created by sync else false
+ */
+ public void testOwns() {
+ final Mutex sync = new Mutex();
+ final AbstractQueuedLongSynchronizer.ConditionObject c = sync.newCondition();
+ final Mutex sync2 = new Mutex();
+ assertTrue(sync.owns(c));
+ assertFalse(sync2.owns(c));
+ }
+
+ /**
+ * Calling await without holding sync throws IllegalMonitorStateException
+ */
+ public void testAwait_IllegalMonitor() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ final AbstractQueuedLongSynchronizer.ConditionObject c = sync.newCondition();
+ try {
+ c.await();
+ shouldThrow();
+ } catch (IllegalMonitorStateException success) {}
+ }
+
+ /**
+ * Calling signal without holding sync throws IllegalMonitorStateException
+ */
+ public void testSignal_IllegalMonitor() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ final AbstractQueuedLongSynchronizer.ConditionObject c = sync.newCondition();
+ try {
+ c.signal();
+ shouldThrow();
+ } catch (IllegalMonitorStateException success) {}
+ }
+
+ /**
+ * awaitNanos without a signal times out
+ */
+ public void testAwaitNanos_Timeout() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ final AbstractQueuedLongSynchronizer.ConditionObject c = sync.newCondition();
+ sync.acquire(1);
+ long t = c.awaitNanos(100);
+ assertTrue(t <= 0);
+ sync.release(1);
+ }
+
+ /**
+ * Timed await without a signal times out
+ */
+ public void testAwait_Timeout() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ final AbstractQueuedLongSynchronizer.ConditionObject c = sync.newCondition();
+ sync.acquire(1);
+ assertFalse(c.await(SHORT_DELAY_MS, MILLISECONDS));
+ sync.release(1);
+ }
+
+ /**
+ * awaitUntil without a signal times out
+ */
+ public void testAwaitUntil_Timeout() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ final AbstractQueuedLongSynchronizer.ConditionObject c = sync.newCondition();
+ sync.acquire(1);
+ java.util.Date d = new java.util.Date();
+ assertFalse(c.awaitUntil(new java.util.Date(d.getTime() + 10)));
+ sync.release(1);
+ }
+
+ /**
+ * await returns when signalled
+ */
+ public void testAwait() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ final AbstractQueuedLongSynchronizer.ConditionObject c = sync.newCondition();
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire(1);
+ c.await();
+ sync.release(1);
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ sync.acquire(1);
+ c.signal();
+ sync.release(1);
+ t.join(SHORT_DELAY_MS);
+ assertFalse(t.isAlive());
+ }
+
+
+
+ /**
+ * hasWaiters throws NPE if null
+ */
+ public void testHasWaitersNPE() {
+ final Mutex sync = new Mutex();
+ try {
+ sync.hasWaiters(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * getWaitQueueLength throws NPE if null
+ */
+ public void testGetWaitQueueLengthNPE() {
+ final Mutex sync = new Mutex();
+ try {
+ sync.getWaitQueueLength(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+
+ /**
+ * getWaitingThreads throws NPE if null
+ */
+ public void testGetWaitingThreadsNPE() {
+ final Mutex sync = new Mutex();
+ try {
+ sync.getWaitingThreads(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+
+ /**
+ * hasWaiters throws IAE if not owned
+ */
+ public void testHasWaitersIAE() {
+ final Mutex sync = new Mutex();
+ final AbstractQueuedLongSynchronizer.ConditionObject c = sync.newCondition();
+ final Mutex sync2 = new Mutex();
+ try {
+ sync2.hasWaiters(c);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * hasWaiters throws IMSE if not synced
+ */
+ public void testHasWaitersIMSE() {
+ final Mutex sync = new Mutex();
+ final AbstractQueuedLongSynchronizer.ConditionObject c = sync.newCondition();
+ try {
+ sync.hasWaiters(c);
+ shouldThrow();
+ } catch (IllegalMonitorStateException success) {}
+ }
+
+
+ /**
+ * getWaitQueueLength throws IAE if not owned
+ */
+ public void testGetWaitQueueLengthIAE() {
+ final Mutex sync = new Mutex();
+ final AbstractQueuedLongSynchronizer.ConditionObject c = sync.newCondition();
+ final Mutex sync2 = new Mutex();
+ try {
+ sync2.getWaitQueueLength(c);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * getWaitQueueLength throws IMSE if not synced
+ */
+ public void testGetWaitQueueLengthIMSE() {
+ final Mutex sync = new Mutex();
+ final AbstractQueuedLongSynchronizer.ConditionObject c = sync.newCondition();
+ try {
+ sync.getWaitQueueLength(c);
+ shouldThrow();
+ } catch (IllegalMonitorStateException success) {}
+ }
+
+
+ /**
+ * getWaitingThreads throws IAE if not owned
+ */
+ public void testGetWaitingThreadsIAE() {
+ final Mutex sync = new Mutex();
+ final AbstractQueuedLongSynchronizer.ConditionObject c = sync.newCondition();
+ final Mutex sync2 = new Mutex();
+ try {
+ sync2.getWaitingThreads(c);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * getWaitingThreads throws IMSE if not synced
+ */
+ public void testGetWaitingThreadsIMSE() {
+ final Mutex sync = new Mutex();
+ final AbstractQueuedLongSynchronizer.ConditionObject c = sync.newCondition();
+ try {
+ sync.getWaitingThreads(c);
+ shouldThrow();
+ } catch (IllegalMonitorStateException success) {}
+ }
+
+
+
+ /**
+ * hasWaiters returns true when a thread is waiting, else false
+ */
+ public void testHasWaiters() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ final AbstractQueuedLongSynchronizer.ConditionObject c = sync.newCondition();
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire(1);
+ threadAssertFalse(sync.hasWaiters(c));
+ threadAssertEquals(0, sync.getWaitQueueLength(c));
+ c.await();
+ sync.release(1);
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ sync.acquire(1);
+ assertTrue(sync.hasWaiters(c));
+ assertEquals(1, sync.getWaitQueueLength(c));
+ c.signal();
+ sync.release(1);
+ Thread.sleep(SHORT_DELAY_MS);
+ sync.acquire(1);
+ assertFalse(sync.hasWaiters(c));
+ assertEquals(0, sync.getWaitQueueLength(c));
+ sync.release(1);
+ t.join(SHORT_DELAY_MS);
+ assertFalse(t.isAlive());
+ }
+
+ /**
+ * getWaitQueueLength returns number of waiting threads
+ */
+ public void testGetWaitQueueLength() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ final AbstractQueuedLongSynchronizer.ConditionObject c = sync.newCondition();
+ Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire(1);
+ threadAssertFalse(sync.hasWaiters(c));
+ threadAssertEquals(0, sync.getWaitQueueLength(c));
+ c.await();
+ sync.release(1);
+ }});
+
+ Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire(1);
+ threadAssertTrue(sync.hasWaiters(c));
+ threadAssertEquals(1, sync.getWaitQueueLength(c));
+ c.await();
+ sync.release(1);
+ }});
+
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ sync.acquire(1);
+ assertTrue(sync.hasWaiters(c));
+ assertEquals(2, sync.getWaitQueueLength(c));
+ c.signalAll();
+ sync.release(1);
+ Thread.sleep(SHORT_DELAY_MS);
+ sync.acquire(1);
+ assertFalse(sync.hasWaiters(c));
+ assertEquals(0, sync.getWaitQueueLength(c));
+ sync.release(1);
+ t1.join(SHORT_DELAY_MS);
+ t2.join(SHORT_DELAY_MS);
+ assertFalse(t1.isAlive());
+ assertFalse(t2.isAlive());
+ }
+
+ /**
+ * getWaitingThreads returns only and all waiting threads
+ */
+ public void testGetWaitingThreads() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ final AbstractQueuedLongSynchronizer.ConditionObject c = sync.newCondition();
+ Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire(1);
+ threadAssertTrue(sync.getWaitingThreads(c).isEmpty());
+ c.await();
+ sync.release(1);
+ }});
+
+ Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire(1);
+ threadAssertFalse(sync.getWaitingThreads(c).isEmpty());
+ c.await();
+ sync.release(1);
+ }});
+
+ sync.acquire(1);
+ assertTrue(sync.getWaitingThreads(c).isEmpty());
+ sync.release(1);
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ sync.acquire(1);
+ assertTrue(sync.hasWaiters(c));
+ assertTrue(sync.getWaitingThreads(c).contains(t1));
+ assertTrue(sync.getWaitingThreads(c).contains(t2));
+ c.signalAll();
+ sync.release(1);
+ Thread.sleep(SHORT_DELAY_MS);
+ sync.acquire(1);
+ assertFalse(sync.hasWaiters(c));
+ assertTrue(sync.getWaitingThreads(c).isEmpty());
+ sync.release(1);
+ t1.join(SHORT_DELAY_MS);
+ t2.join(SHORT_DELAY_MS);
+ assertFalse(t1.isAlive());
+ assertFalse(t2.isAlive());
+ }
+
+
+
+ /**
+ * awaitUninterruptibly doesn't abort on interrupt
+ */
+ public void testAwaitUninterruptibly() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ final AbstractQueuedLongSynchronizer.ConditionObject c = sync.newCondition();
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ sync.acquire(1);
+ c.awaitUninterruptibly();
+ sync.release(1);
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ sync.acquire(1);
+ c.signal();
+ sync.release(1);
+ t.join(SHORT_DELAY_MS);
+ assertFalse(t.isAlive());
+ }
+
+ /**
+ * await is interruptible
+ */
+ public void testAwait_Interrupt() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ final AbstractQueuedLongSynchronizer.ConditionObject c = sync.newCondition();
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire(1);
+ c.await();
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join(SHORT_DELAY_MS);
+ assertFalse(t.isAlive());
+ }
+
+ /**
+ * awaitNanos is interruptible
+ */
+ public void testAwaitNanos_Interrupt() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ final AbstractQueuedLongSynchronizer.ConditionObject c = sync.newCondition();
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire(1);
+ c.awaitNanos(MILLISECONDS.toNanos(LONG_DELAY_MS));
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join(SHORT_DELAY_MS);
+ assertFalse(t.isAlive());
+ }
+
+ /**
+ * awaitUntil is interruptible
+ */
+ public void testAwaitUntil_Interrupt() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ final AbstractQueuedLongSynchronizer.ConditionObject c = sync.newCondition();
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire(1);
+ java.util.Date d = new java.util.Date();
+ c.awaitUntil(new java.util.Date(d.getTime() + 10000));
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join(SHORT_DELAY_MS);
+ assertFalse(t.isAlive());
+ }
+
+ /**
+ * signalAll wakes up all threads
+ */
+ public void testSignalAll() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ final AbstractQueuedLongSynchronizer.ConditionObject c = sync.newCondition();
+ Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire(1);
+ c.await();
+ sync.release(1);
+ }});
+
+ Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire(1);
+ c.await();
+ sync.release(1);
+ }});
+
+ t1.start();
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ sync.acquire(1);
+ c.signalAll();
+ sync.release(1);
+ t1.join(SHORT_DELAY_MS);
+ t2.join(SHORT_DELAY_MS);
+ assertFalse(t1.isAlive());
+ assertFalse(t2.isAlive());
+ }
+
+
+ /**
+ * toString indicates current state
+ */
+ public void testToString() {
+ Mutex sync = new Mutex();
+ String us = sync.toString();
+ assertTrue(us.indexOf("State = 0") >= 0);
+ sync.acquire(1);
+ String ls = sync.toString();
+ assertTrue(ls.indexOf("State = " + Mutex.LOCKED) >= 0);
+ }
+
+ /**
+ * A serialized AQS deserializes with current state
+ */
+ public void testSerialization() throws Exception {
+ Mutex l = new Mutex();
+ l.acquire(1);
+ assertTrue(l.isHeldExclusively());
+
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(l);
+ out.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ Mutex r = (Mutex) in.readObject();
+ assertTrue(r.isHeldExclusively());
+ }
+
+
+ /**
+ * tryReleaseShared setting state changes getState
+ */
+ public void testGetStateWithReleaseShared() {
+ final BooleanLatch l = new BooleanLatch();
+ assertFalse(l.isSignalled());
+ l.releaseShared(0);
+ assertTrue(l.isSignalled());
+ }
+
+ /**
+ * releaseShared has no effect when already signalled
+ */
+ public void testReleaseShared() {
+ final BooleanLatch l = new BooleanLatch();
+ assertFalse(l.isSignalled());
+ l.releaseShared(0);
+ assertTrue(l.isSignalled());
+ l.releaseShared(0);
+ assertTrue(l.isSignalled());
+ }
+
+ /**
+ * acquireSharedInterruptibly returns after release, but not before
+ */
+ public void testAcquireSharedInterruptibly() throws InterruptedException {
+ final BooleanLatch l = new BooleanLatch();
+
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ threadAssertFalse(l.isSignalled());
+ l.acquireSharedInterruptibly(0);
+ threadAssertTrue(l.isSignalled());
+ }});
+
+ t.start();
+ assertFalse(l.isSignalled());
+ Thread.sleep(SHORT_DELAY_MS);
+ l.releaseShared(0);
+ assertTrue(l.isSignalled());
+ t.join();
+ }
+
+
+ /**
+ * acquireSharedTimed returns after release
+ */
+ public void testAsquireSharedTimed() throws InterruptedException {
+ final BooleanLatch l = new BooleanLatch();
+
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertFalse(l.isSignalled());
+ long nanos = MILLISECONDS.toNanos(MEDIUM_DELAY_MS);
+ assertTrue(l.tryAcquireSharedNanos(0, nanos));
+ assertTrue(l.isSignalled());
+ }});
+
+ t.start();
+ assertFalse(l.isSignalled());
+ Thread.sleep(SHORT_DELAY_MS);
+ l.releaseShared(0);
+ assertTrue(l.isSignalled());
+ t.join();
+ }
+
+ /**
+ * acquireSharedInterruptibly throws IE if interrupted before released
+ */
+ public void testAcquireSharedInterruptibly_InterruptedException() throws InterruptedException {
+ final BooleanLatch l = new BooleanLatch();
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ threadAssertFalse(l.isSignalled());
+ l.acquireSharedInterruptibly(0);
+ }});
+
+ t.start();
+ assertFalse(l.isSignalled());
+ t.interrupt();
+ t.join();
+ }
+
+ /**
+ * acquireSharedTimed throws IE if interrupted before released
+ */
+ public void testAcquireSharedNanos_InterruptedException() throws InterruptedException {
+ final BooleanLatch l = new BooleanLatch();
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertFalse(l.isSignalled());
+ long nanos = MILLISECONDS.toNanos(SMALL_DELAY_MS);
+ l.tryAcquireSharedNanos(0, nanos);
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(l.isSignalled());
+ t.interrupt();
+ t.join();
+ }
+
+ /**
+ * acquireSharedTimed times out if not released before timeout
+ */
+ public void testAcquireSharedNanos_Timeout() throws InterruptedException {
+ final BooleanLatch l = new BooleanLatch();
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertFalse(l.isSignalled());
+ long nanos = MILLISECONDS.toNanos(SMALL_DELAY_MS);
+ assertFalse(l.tryAcquireSharedNanos(0, nanos));
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(l.isSignalled());
+ t.join();
+ }
+
+}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/AbstractQueuedSynchronizerTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/AbstractQueuedSynchronizerTest.java
index e2cfe92..a5b6554 100644
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/AbstractQueuedSynchronizerTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/AbstractQueuedSynchronizerTest.java
@@ -2,8 +2,8 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
package tests.api.java.util.concurrent;
@@ -11,6 +11,7 @@ package tests.api.java.util.concurrent;
import junit.framework.*;
import java.util.*;
import java.util.concurrent.*;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.concurrent.locks.*;
import java.io.*;
@@ -29,33 +30,33 @@ public class AbstractQueuedSynchronizerTest extends JSR166TestCase {
*/
static class Mutex extends AbstractQueuedSynchronizer {
public boolean isHeldExclusively() { return getState() == 1; }
-
+
public boolean tryAcquire(int acquires) {
- assertTrue(acquires == 1);
+ assertTrue(acquires == 1);
return compareAndSetState(0, 1);
}
-
+
public boolean tryRelease(int releases) {
if (getState() == 0) throw new IllegalMonitorStateException();
setState(0);
return true;
}
-
+
public AbstractQueuedSynchronizer.ConditionObject newCondition() { return new AbstractQueuedSynchronizer.ConditionObject(); }
}
-
+
/**
* A simple latch class, to test shared mode.
*/
- static class BooleanLatch extends AbstractQueuedSynchronizer {
+ static class BooleanLatch extends AbstractQueuedSynchronizer {
public boolean isSignalled() { return getState() != 0; }
public int tryAcquireShared(int ignore) {
return isSignalled()? 1 : -1;
}
-
+
public boolean tryReleaseShared(int ignore) {
setState(1);
return true;
@@ -63,46 +64,42 @@ public class AbstractQueuedSynchronizerTest extends JSR166TestCase {
}
/**
- * A runnable calling acquireInterruptibly
+ * A runnable calling acquireInterruptibly that does not expect to
+ * be interrupted.
*/
- class InterruptibleSyncRunnable implements Runnable {
+ class InterruptibleSyncRunnable extends CheckedRunnable {
final Mutex sync;
InterruptibleSyncRunnable(Mutex l) { sync = l; }
- public void run() {
- try {
- sync.acquireInterruptibly(1);
- } catch(InterruptedException success){}
+ public void realRun() throws InterruptedException {
+ sync.acquireInterruptibly(1);
}
}
/**
* A runnable calling acquireInterruptibly that expects to be
- * interrupted
+ * interrupted.
*/
- class InterruptedSyncRunnable implements Runnable {
+ class InterruptedSyncRunnable extends CheckedInterruptedRunnable {
final Mutex sync;
InterruptedSyncRunnable(Mutex l) { sync = l; }
- public void run() {
- try {
- sync.acquireInterruptibly(1);
- threadShouldThrow();
- } catch(InterruptedException success){}
+ public void realRun() throws InterruptedException {
+ sync.acquireInterruptibly(1);
}
}
/**
* isHeldExclusively is false upon construction
*/
- public void testIsHeldExclusively() {
+ public void testIsHeldExclusively() {
Mutex rl = new Mutex();
assertFalse(rl.isHeldExclusively());
}
-
+
/**
* acquiring released sync succeeds
*/
- public void testAcquire() {
+ public void testAcquire() {
Mutex rl = new Mutex();
rl.acquire(1);
assertTrue(rl.isHeldExclusively());
@@ -113,7 +110,7 @@ public class AbstractQueuedSynchronizerTest extends JSR166TestCase {
/**
* tryAcquire on an released sync succeeds
*/
- public void testTryAcquire() {
+ public void testTryAcquire() {
Mutex rl = new Mutex();
assertTrue(rl.tryAcquire(1));
assertTrue(rl.isHeldExclusively());
@@ -123,378 +120,314 @@ public class AbstractQueuedSynchronizerTest extends JSR166TestCase {
/**
* hasQueuedThreads reports whether there are waiting threads
*/
- public void testhasQueuedThreads() {
+ public void testhasQueuedThreads() throws InterruptedException {
final Mutex sync = new Mutex();
Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
- try {
- assertFalse(sync.hasQueuedThreads());
- sync.acquire(1);
- t1.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(sync.hasQueuedThreads());
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(sync.hasQueuedThreads());
- t1.interrupt();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(sync.hasQueuedThreads());
- sync.release(1);
- Thread.sleep(SHORT_DELAY_MS);
- assertFalse(sync.hasQueuedThreads());
- t1.join();
- t2.join();
- } catch(Exception e){
- unexpectedException();
- }
- }
+ assertFalse(sync.hasQueuedThreads());
+ sync.acquire(1);
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.hasQueuedThreads());
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.hasQueuedThreads());
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.hasQueuedThreads());
+ sync.release(1);
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(sync.hasQueuedThreads());
+ t1.join();
+ t2.join();
+ }
/**
* isQueued(null) throws NPE
*/
- public void testIsQueuedNPE() {
+ public void testIsQueuedNPE() {
final Mutex sync = new Mutex();
try {
sync.isQueued(null);
shouldThrow();
- } catch (NullPointerException success) {
- }
+ } catch (NullPointerException success) {}
}
/**
* isQueued reports whether a thread is queued.
*/
- public void testIsQueued() {
+ public void testIsQueued() throws InterruptedException {
final Mutex sync = new Mutex();
Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
- try {
- assertFalse(sync.isQueued(t1));
- assertFalse(sync.isQueued(t2));
- sync.acquire(1);
- t1.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(sync.isQueued(t1));
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(sync.isQueued(t1));
- assertTrue(sync.isQueued(t2));
- t1.interrupt();
- Thread.sleep(SHORT_DELAY_MS);
- assertFalse(sync.isQueued(t1));
- assertTrue(sync.isQueued(t2));
- sync.release(1);
- Thread.sleep(SHORT_DELAY_MS);
- assertFalse(sync.isQueued(t1));
- Thread.sleep(SHORT_DELAY_MS);
- assertFalse(sync.isQueued(t2));
- t1.join();
- t2.join();
- } catch(Exception e){
- unexpectedException();
- }
- }
+ assertFalse(sync.isQueued(t1));
+ assertFalse(sync.isQueued(t2));
+ sync.acquire(1);
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.isQueued(t1));
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.isQueued(t1));
+ assertTrue(sync.isQueued(t2));
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(sync.isQueued(t1));
+ assertTrue(sync.isQueued(t2));
+ sync.release(1);
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(sync.isQueued(t1));
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(sync.isQueued(t2));
+ t1.join();
+ t2.join();
+ }
/**
* getFirstQueuedThread returns first waiting thread or null if none
*/
- public void testGetFirstQueuedThread() {
+ public void testGetFirstQueuedThread() throws InterruptedException {
final Mutex sync = new Mutex();
Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
- try {
- assertNull(sync.getFirstQueuedThread());
- sync.acquire(1);
- t1.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertEquals(t1, sync.getFirstQueuedThread());
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertEquals(t1, sync.getFirstQueuedThread());
- t1.interrupt();
- Thread.sleep(SHORT_DELAY_MS);
- Thread.sleep(SHORT_DELAY_MS);
- assertEquals(t2, sync.getFirstQueuedThread());
- sync.release(1);
- Thread.sleep(SHORT_DELAY_MS);
- assertNull(sync.getFirstQueuedThread());
- t1.join();
- t2.join();
- } catch(Exception e){
- unexpectedException();
- }
- }
+ assertNull(sync.getFirstQueuedThread());
+ sync.acquire(1);
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(t1, sync.getFirstQueuedThread());
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(t1, sync.getFirstQueuedThread());
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(t2, sync.getFirstQueuedThread());
+ sync.release(1);
+ Thread.sleep(SHORT_DELAY_MS);
+ assertNull(sync.getFirstQueuedThread());
+ t1.join();
+ t2.join();
+ }
/**
* hasContended reports false if no thread has ever blocked, else true
*/
- public void testHasContended() {
+ public void testHasContended() throws InterruptedException {
final Mutex sync = new Mutex();
Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
- try {
- assertFalse(sync.hasContended());
- sync.acquire(1);
- t1.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(sync.hasContended());
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(sync.hasContended());
- t1.interrupt();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(sync.hasContended());
- sync.release(1);
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(sync.hasContended());
- t1.join();
- t2.join();
- } catch(Exception e){
- unexpectedException();
- }
- }
+ assertFalse(sync.hasContended());
+ sync.acquire(1);
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.hasContended());
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.hasContended());
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.hasContended());
+ sync.release(1);
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.hasContended());
+ t1.join();
+ t2.join();
+ }
/**
* getQueuedThreads includes waiting threads
*/
- public void testGetQueuedThreads() {
+ public void testGetQueuedThreads() throws InterruptedException {
final Mutex sync = new Mutex();
Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
- try {
- assertTrue(sync.getQueuedThreads().isEmpty());
- sync.acquire(1);
- assertTrue(sync.getQueuedThreads().isEmpty());
- t1.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(sync.getQueuedThreads().contains(t1));
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(sync.getQueuedThreads().contains(t1));
- assertTrue(sync.getQueuedThreads().contains(t2));
- t1.interrupt();
- Thread.sleep(SHORT_DELAY_MS);
- assertFalse(sync.getQueuedThreads().contains(t1));
- assertTrue(sync.getQueuedThreads().contains(t2));
- sync.release(1);
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(sync.getQueuedThreads().isEmpty());
- t1.join();
- t2.join();
- } catch(Exception e){
- unexpectedException();
- }
- }
+ assertTrue(sync.getQueuedThreads().isEmpty());
+ sync.acquire(1);
+ assertTrue(sync.getQueuedThreads().isEmpty());
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.getQueuedThreads().contains(t1));
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.getQueuedThreads().contains(t1));
+ assertTrue(sync.getQueuedThreads().contains(t2));
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(sync.getQueuedThreads().contains(t1));
+ assertTrue(sync.getQueuedThreads().contains(t2));
+ sync.release(1);
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.getQueuedThreads().isEmpty());
+ t1.join();
+ t2.join();
+ }
/**
* getExclusiveQueuedThreads includes waiting threads
*/
- public void testGetExclusiveQueuedThreads() {
+ public void testGetExclusiveQueuedThreads() throws InterruptedException {
final Mutex sync = new Mutex();
Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
- try {
- assertTrue(sync.getExclusiveQueuedThreads().isEmpty());
- sync.acquire(1);
- assertTrue(sync.getExclusiveQueuedThreads().isEmpty());
- t1.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(sync.getExclusiveQueuedThreads().contains(t1));
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(sync.getExclusiveQueuedThreads().contains(t1));
- assertTrue(sync.getExclusiveQueuedThreads().contains(t2));
- t1.interrupt();
- Thread.sleep(SHORT_DELAY_MS);
- assertFalse(sync.getExclusiveQueuedThreads().contains(t1));
- assertTrue(sync.getExclusiveQueuedThreads().contains(t2));
- sync.release(1);
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(sync.getExclusiveQueuedThreads().isEmpty());
- t1.join();
- t2.join();
- } catch(Exception e){
- unexpectedException();
- }
- }
+ assertTrue(sync.getExclusiveQueuedThreads().isEmpty());
+ sync.acquire(1);
+ assertTrue(sync.getExclusiveQueuedThreads().isEmpty());
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.getExclusiveQueuedThreads().contains(t1));
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.getExclusiveQueuedThreads().contains(t1));
+ assertTrue(sync.getExclusiveQueuedThreads().contains(t2));
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(sync.getExclusiveQueuedThreads().contains(t1));
+ assertTrue(sync.getExclusiveQueuedThreads().contains(t2));
+ sync.release(1);
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.getExclusiveQueuedThreads().isEmpty());
+ t1.join();
+ t2.join();
+ }
/**
* getSharedQueuedThreads does not include exclusively waiting threads
*/
- public void testGetSharedQueuedThreads() {
+ public void testGetSharedQueuedThreads() throws InterruptedException {
final Mutex sync = new Mutex();
Thread t1 = new Thread(new InterruptedSyncRunnable(sync));
Thread t2 = new Thread(new InterruptibleSyncRunnable(sync));
- try {
- assertTrue(sync.getSharedQueuedThreads().isEmpty());
- sync.acquire(1);
- assertTrue(sync.getSharedQueuedThreads().isEmpty());
- t1.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(sync.getSharedQueuedThreads().isEmpty());
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(sync.getSharedQueuedThreads().isEmpty());
- t1.interrupt();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(sync.getSharedQueuedThreads().isEmpty());
- sync.release(1);
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(sync.getSharedQueuedThreads().isEmpty());
- t1.join();
- t2.join();
- } catch(Exception e){
- unexpectedException();
- }
- }
+ assertTrue(sync.getSharedQueuedThreads().isEmpty());
+ sync.acquire(1);
+ assertTrue(sync.getSharedQueuedThreads().isEmpty());
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.getSharedQueuedThreads().isEmpty());
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.getSharedQueuedThreads().isEmpty());
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.getSharedQueuedThreads().isEmpty());
+ sync.release(1);
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.getSharedQueuedThreads().isEmpty());
+ t1.join();
+ t2.join();
+ }
/**
* tryAcquireNanos is interruptible.
*/
- public void testInterruptedException2() {
+ public void testInterruptedException2() throws InterruptedException {
final Mutex sync = new Mutex();
sync.acquire(1);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- sync.tryAcquireNanos(1, MEDIUM_DELAY_MS * 1000 * 1000);
- threadShouldThrow();
- } catch(InterruptedException success){}
- }
- });
- try {
- t.start();
- t.interrupt();
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.tryAcquireNanos(1, MILLISECONDS.toNanos(MEDIUM_DELAY_MS));
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* TryAcquire on exclusively held sync fails
*/
- public void testTryAcquireWhenSynced() {
+ public void testTryAcquireWhenSynced() throws InterruptedException {
final Mutex sync = new Mutex();
sync.acquire(1);
- Thread t = new Thread(new Runnable() {
- public void run() {
- threadAssertFalse(sync.tryAcquire(1));
- }
- });
- try {
- t.start();
- t.join();
- sync.release(1);
- } catch(Exception e){
- unexpectedException();
- }
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ threadAssertFalse(sync.tryAcquire(1));
+ }});
+
+ t.start();
+ t.join();
+ sync.release(1);
+ }
/**
* tryAcquireNanos on an exclusively held sync times out
*/
- public void testAcquireNanos_Timeout() {
+ public void testAcquireNanos_Timeout() throws InterruptedException {
final Mutex sync = new Mutex();
sync.acquire(1);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- threadAssertFalse(sync.tryAcquireNanos(1, 1000 * 1000));
- } catch (Exception ex) {
- threadUnexpectedException();
- }
- }
- });
- try {
- t.start();
- t.join();
- sync.release(1);
- } catch(Exception e){
- unexpectedException();
- }
- }
-
-
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ long nanos = MILLISECONDS.toNanos(SHORT_DELAY_MS);
+ assertFalse(sync.tryAcquireNanos(1, nanos));
+ }});
+
+ t.start();
+ t.join();
+ sync.release(1);
+ }
+
+
/**
* getState is true when acquired and false when not
*/
- public void testGetState() {
+ public void testGetState() throws InterruptedException {
final Mutex sync = new Mutex();
sync.acquire(1);
assertTrue(sync.isHeldExclusively());
sync.release(1);
assertFalse(sync.isHeldExclusively());
- Thread t = new Thread(new Runnable() {
- public void run() {
- sync.acquire(1);
- try {
- Thread.sleep(SMALL_DELAY_MS);
- }
- catch(Exception e) {
- threadUnexpectedException();
- }
- sync.release(1);
- }
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(sync.isHeldExclusively());
- t.join();
- assertFalse(sync.isHeldExclusively());
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire(1);
+ Thread.sleep(SMALL_DELAY_MS);
+ sync.release(1);
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.isHeldExclusively());
+ t.join();
+ assertFalse(sync.isHeldExclusively());
}
/**
* acquireInterruptibly is interruptible.
*/
- public void testAcquireInterruptibly1() {
+ public void testAcquireInterruptibly1() throws InterruptedException {
final Mutex sync = new Mutex();
sync.acquire(1);
Thread t = new Thread(new InterruptedSyncRunnable(sync));
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- Thread.sleep(SHORT_DELAY_MS);
- sync.release(1);
- t.join();
- } catch(Exception e){
- unexpectedException();
- }
- }
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ sync.release(1);
+ t.join();
+ }
/**
* acquireInterruptibly succeeds when released, else is interruptible
*/
- public void testAcquireInterruptibly2() {
- final Mutex sync = new Mutex();
- try {
- sync.acquireInterruptibly(1);
- } catch(Exception e) {
- unexpectedException();
- }
+ public void testAcquireInterruptibly2() throws InterruptedException {
+ final Mutex sync = new Mutex();
+ sync.acquireInterruptibly(1);
Thread t = new Thread(new InterruptedSyncRunnable(sync));
- try {
- t.start();
- t.interrupt();
- assertTrue(sync.isHeldExclusively());
- t.join();
- } catch(Exception e){
- unexpectedException();
- }
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ assertTrue(sync.isHeldExclusively());
+ t.join();
}
/**
* owns is true for a condition created by sync else false
*/
public void testOwns() {
- final Mutex sync = new Mutex();
+ final Mutex sync = new Mutex();
final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
final Mutex sync2 = new Mutex();
assertTrue(sync.owns(c));
@@ -504,118 +437,82 @@ public class AbstractQueuedSynchronizerTest extends JSR166TestCase {
/**
* Calling await without holding sync throws IllegalMonitorStateException
*/
- public void testAwait_IllegalMonitor() {
- final Mutex sync = new Mutex();
+ public void testAwait_IllegalMonitor() throws InterruptedException {
+ final Mutex sync = new Mutex();
final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
try {
c.await();
shouldThrow();
- }
- catch (IllegalMonitorStateException success) {
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ } catch (IllegalMonitorStateException success) {}
}
/**
* Calling signal without holding sync throws IllegalMonitorStateException
*/
public void testSignal_IllegalMonitor() {
- final Mutex sync = new Mutex();
+ final Mutex sync = new Mutex();
final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
try {
c.signal();
shouldThrow();
- }
- catch (IllegalMonitorStateException success) {
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ } catch (IllegalMonitorStateException success) {}
}
/**
* awaitNanos without a signal times out
*/
- public void testAwaitNanos_Timeout() {
- final Mutex sync = new Mutex();
+ public void testAwaitNanos_Timeout() throws InterruptedException {
+ final Mutex sync = new Mutex();
final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
- try {
- sync.acquire(1);
- long t = c.awaitNanos(100);
- assertTrue(t <= 0);
- sync.release(1);
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ sync.acquire(1);
+ long t = c.awaitNanos(100);
+ assertTrue(t <= 0);
+ sync.release(1);
}
/**
* Timed await without a signal times out
*/
- public void testAwait_Timeout() {
- final Mutex sync = new Mutex();
+ public void testAwait_Timeout() throws InterruptedException {
+ final Mutex sync = new Mutex();
final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
- try {
- sync.acquire(1);
- assertFalse(c.await(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- sync.release(1);
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ sync.acquire(1);
+ assertFalse(c.await(SHORT_DELAY_MS, MILLISECONDS));
+ sync.release(1);
}
/**
* awaitUntil without a signal times out
*/
- public void testAwaitUntil_Timeout() {
- final Mutex sync = new Mutex();
+ public void testAwaitUntil_Timeout() throws InterruptedException {
+ final Mutex sync = new Mutex();
final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
- try {
- sync.acquire(1);
- java.util.Date d = new java.util.Date();
- assertFalse(c.awaitUntil(new java.util.Date(d.getTime() + 10)));
- sync.release(1);
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ sync.acquire(1);
+ java.util.Date d = new java.util.Date();
+ assertFalse(c.awaitUntil(new java.util.Date(d.getTime() + 10)));
+ sync.release(1);
}
/**
* await returns when signalled
*/
- public void testAwait() {
- final Mutex sync = new Mutex();
+ public void testAwait() throws InterruptedException {
+ final Mutex sync = new Mutex();
final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- sync.acquire(1);
- c.await();
- sync.release(1);
- }
- catch(InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire(1);
+ c.await();
+ sync.release(1);
+ }});
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- sync.acquire(1);
- c.signal();
- sync.release(1);
- t.join(SHORT_DELAY_MS);
- assertFalse(t.isAlive());
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ sync.acquire(1);
+ c.signal();
+ sync.release(1);
+ t.join(SHORT_DELAY_MS);
+ assertFalse(t.isAlive());
}
@@ -628,10 +525,7 @@ public class AbstractQueuedSynchronizerTest extends JSR166TestCase {
try {
sync.hasWaiters(null);
shouldThrow();
- } catch (NullPointerException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (NullPointerException success) {}
}
/**
@@ -642,10 +536,7 @@ public class AbstractQueuedSynchronizerTest extends JSR166TestCase {
try {
sync.getWaitQueueLength(null);
shouldThrow();
- } catch (NullPointerException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (NullPointerException success) {}
}
@@ -657,10 +548,7 @@ public class AbstractQueuedSynchronizerTest extends JSR166TestCase {
try {
sync.getWaitingThreads(null);
shouldThrow();
- } catch (NullPointerException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (NullPointerException success) {}
}
@@ -669,15 +557,12 @@ public class AbstractQueuedSynchronizerTest extends JSR166TestCase {
*/
public void testHasWaitersIAE() {
final Mutex sync = new Mutex();
- final AbstractQueuedSynchronizer.ConditionObject c = (sync.newCondition());
+ final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
final Mutex sync2 = new Mutex();
try {
sync2.hasWaiters(c);
shouldThrow();
- } catch (IllegalArgumentException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (IllegalArgumentException success) {}
}
/**
@@ -685,14 +570,11 @@ public class AbstractQueuedSynchronizerTest extends JSR166TestCase {
*/
public void testHasWaitersIMSE() {
final Mutex sync = new Mutex();
- final AbstractQueuedSynchronizer.ConditionObject c = (sync.newCondition());
+ final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
try {
sync.hasWaiters(c);
shouldThrow();
- } catch (IllegalMonitorStateException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (IllegalMonitorStateException success) {}
}
@@ -701,15 +583,12 @@ public class AbstractQueuedSynchronizerTest extends JSR166TestCase {
*/
public void testGetWaitQueueLengthIAE() {
final Mutex sync = new Mutex();
- final AbstractQueuedSynchronizer.ConditionObject c = (sync.newCondition());
+ final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
final Mutex sync2 = new Mutex();
try {
sync2.getWaitQueueLength(c);
shouldThrow();
- } catch (IllegalArgumentException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (IllegalArgumentException success) {}
}
/**
@@ -717,14 +596,11 @@ public class AbstractQueuedSynchronizerTest extends JSR166TestCase {
*/
public void testGetWaitQueueLengthIMSE() {
final Mutex sync = new Mutex();
- final AbstractQueuedSynchronizer.ConditionObject c = (sync.newCondition());
+ final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
try {
sync.getWaitQueueLength(c);
shouldThrow();
- } catch (IllegalMonitorStateException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (IllegalMonitorStateException success) {}
}
@@ -732,31 +608,25 @@ public class AbstractQueuedSynchronizerTest extends JSR166TestCase {
* getWaitingThreads throws IAE if not owned
*/
public void testGetWaitingThreadsIAE() {
- final Mutex sync = new Mutex();
- final AbstractQueuedSynchronizer.ConditionObject c = (sync.newCondition());
- final Mutex sync2 = new Mutex();
+ final Mutex sync = new Mutex();
+ final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
+ final Mutex sync2 = new Mutex();
try {
sync2.getWaitingThreads(c);
shouldThrow();
- } catch (IllegalArgumentException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (IllegalArgumentException success) {}
}
/**
* getWaitingThreads throws IMSE if not synced
*/
public void testGetWaitingThreadsIMSE() {
- final Mutex sync = new Mutex();
- final AbstractQueuedSynchronizer.ConditionObject c = (sync.newCondition());
+ final Mutex sync = new Mutex();
+ final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
try {
sync.getWaitingThreads(c);
shouldThrow();
- } catch (IllegalMonitorStateException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (IllegalMonitorStateException success) {}
}
@@ -764,167 +634,122 @@ public class AbstractQueuedSynchronizerTest extends JSR166TestCase {
/**
* hasWaiters returns true when a thread is waiting, else false
*/
- public void testHasWaiters() {
- final Mutex sync = new Mutex();
+ public void testHasWaiters() throws InterruptedException {
+ final Mutex sync = new Mutex();
final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- sync.acquire(1);
- threadAssertFalse(sync.hasWaiters(c));
- threadAssertEquals(0, sync.getWaitQueueLength(c));
- c.await();
- sync.release(1);
- }
- catch(InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire(1);
+ threadAssertFalse(sync.hasWaiters(c));
+ threadAssertEquals(0, sync.getWaitQueueLength(c));
+ c.await();
+ sync.release(1);
+ }});
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- sync.acquire(1);
- assertTrue(sync.hasWaiters(c));
- assertEquals(1, sync.getWaitQueueLength(c));
- c.signal();
- sync.release(1);
- Thread.sleep(SHORT_DELAY_MS);
- sync.acquire(1);
- assertFalse(sync.hasWaiters(c));
- assertEquals(0, sync.getWaitQueueLength(c));
- sync.release(1);
- t.join(SHORT_DELAY_MS);
- assertFalse(t.isAlive());
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ sync.acquire(1);
+ assertTrue(sync.hasWaiters(c));
+ assertEquals(1, sync.getWaitQueueLength(c));
+ c.signal();
+ sync.release(1);
+ Thread.sleep(SHORT_DELAY_MS);
+ sync.acquire(1);
+ assertFalse(sync.hasWaiters(c));
+ assertEquals(0, sync.getWaitQueueLength(c));
+ sync.release(1);
+ t.join(SHORT_DELAY_MS);
+ assertFalse(t.isAlive());
}
/**
* getWaitQueueLength returns number of waiting threads
*/
- public void testGetWaitQueueLength() {
- final Mutex sync = new Mutex();
+ public void testGetWaitQueueLength() throws InterruptedException {
+ final Mutex sync = new Mutex();
final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- try {
- sync.acquire(1);
- threadAssertFalse(sync.hasWaiters(c));
- threadAssertEquals(0, sync.getWaitQueueLength(c));
- c.await();
- sync.release(1);
- }
- catch(InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
-
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- try {
- sync.acquire(1);
- threadAssertTrue(sync.hasWaiters(c));
- threadAssertEquals(1, sync.getWaitQueueLength(c));
- c.await();
- sync.release(1);
- }
- catch(InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
-
- try {
- t1.start();
- Thread.sleep(SHORT_DELAY_MS);
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- sync.acquire(1);
- assertTrue(sync.hasWaiters(c));
- assertEquals(2, sync.getWaitQueueLength(c));
- c.signalAll();
- sync.release(1);
- Thread.sleep(SHORT_DELAY_MS);
- sync.acquire(1);
- assertFalse(sync.hasWaiters(c));
- assertEquals(0, sync.getWaitQueueLength(c));
- sync.release(1);
- t1.join(SHORT_DELAY_MS);
- t2.join(SHORT_DELAY_MS);
- assertFalse(t1.isAlive());
- assertFalse(t2.isAlive());
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire(1);
+ threadAssertFalse(sync.hasWaiters(c));
+ threadAssertEquals(0, sync.getWaitQueueLength(c));
+ c.await();
+ sync.release(1);
+ }});
+
+ Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire(1);
+ threadAssertTrue(sync.hasWaiters(c));
+ threadAssertEquals(1, sync.getWaitQueueLength(c));
+ c.await();
+ sync.release(1);
+ }});
+
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ sync.acquire(1);
+ assertTrue(sync.hasWaiters(c));
+ assertEquals(2, sync.getWaitQueueLength(c));
+ c.signalAll();
+ sync.release(1);
+ Thread.sleep(SHORT_DELAY_MS);
+ sync.acquire(1);
+ assertFalse(sync.hasWaiters(c));
+ assertEquals(0, sync.getWaitQueueLength(c));
+ sync.release(1);
+ t1.join(SHORT_DELAY_MS);
+ t2.join(SHORT_DELAY_MS);
+ assertFalse(t1.isAlive());
+ assertFalse(t2.isAlive());
}
/**
* getWaitingThreads returns only and all waiting threads
*/
- public void testGetWaitingThreads() {
- final Mutex sync = new Mutex();
+ public void testGetWaitingThreads() throws InterruptedException {
+ final Mutex sync = new Mutex();
final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- try {
- sync.acquire(1);
- threadAssertTrue(sync.getWaitingThreads(c).isEmpty());
- c.await();
- sync.release(1);
- }
- catch(InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
-
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- try {
- sync.acquire(1);
- threadAssertFalse(sync.getWaitingThreads(c).isEmpty());
- c.await();
- sync.release(1);
- }
- catch(InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
+ Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire(1);
+ threadAssertTrue(sync.getWaitingThreads(c).isEmpty());
+ c.await();
+ sync.release(1);
+ }});
+
+ Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire(1);
+ threadAssertFalse(sync.getWaitingThreads(c).isEmpty());
+ c.await();
+ sync.release(1);
+ }});
- try {
- sync.acquire(1);
- assertTrue(sync.getWaitingThreads(c).isEmpty());
- sync.release(1);
- t1.start();
- Thread.sleep(SHORT_DELAY_MS);
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- sync.acquire(1);
- assertTrue(sync.hasWaiters(c));
- assertTrue(sync.getWaitingThreads(c).contains(t1));
- assertTrue(sync.getWaitingThreads(c).contains(t2));
- c.signalAll();
- sync.release(1);
- Thread.sleep(SHORT_DELAY_MS);
- sync.acquire(1);
- assertFalse(sync.hasWaiters(c));
- assertTrue(sync.getWaitingThreads(c).isEmpty());
- sync.release(1);
- t1.join(SHORT_DELAY_MS);
- t2.join(SHORT_DELAY_MS);
- assertFalse(t1.isAlive());
- assertFalse(t2.isAlive());
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ sync.acquire(1);
+ assertTrue(sync.getWaitingThreads(c).isEmpty());
+ sync.release(1);
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ sync.acquire(1);
+ assertTrue(sync.hasWaiters(c));
+ assertTrue(sync.getWaitingThreads(c).contains(t1));
+ assertTrue(sync.getWaitingThreads(c).contains(t2));
+ c.signalAll();
+ sync.release(1);
+ Thread.sleep(SHORT_DELAY_MS);
+ sync.acquire(1);
+ assertFalse(sync.hasWaiters(c));
+ assertTrue(sync.getWaitingThreads(c).isEmpty());
+ sync.release(1);
+ t1.join(SHORT_DELAY_MS);
+ t2.join(SHORT_DELAY_MS);
+ assertFalse(t1.isAlive());
+ assertFalse(t2.isAlive());
}
@@ -932,175 +757,114 @@ public class AbstractQueuedSynchronizerTest extends JSR166TestCase {
/**
* awaitUninterruptibly doesn't abort on interrupt
*/
- public void testAwaitUninterruptibly() {
- final Mutex sync = new Mutex();
+ public void testAwaitUninterruptibly() throws InterruptedException {
+ final Mutex sync = new Mutex();
final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
- Thread t = new Thread(new Runnable() {
- public void run() {
- sync.acquire(1);
- c.awaitUninterruptibly();
- sync.release(1);
- }
- });
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ sync.acquire(1);
+ c.awaitUninterruptibly();
+ sync.release(1);
+ }});
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- sync.acquire(1);
- c.signal();
- sync.release(1);
- t.join(SHORT_DELAY_MS);
- assertFalse(t.isAlive());
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ sync.acquire(1);
+ c.signal();
+ sync.release(1);
+ t.join(SHORT_DELAY_MS);
+ assertFalse(t.isAlive());
}
/**
* await is interruptible
*/
- public void testAwait_Interrupt() {
- final Mutex sync = new Mutex();
+ public void testAwait_Interrupt() throws InterruptedException {
+ final Mutex sync = new Mutex();
final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- sync.acquire(1);
- c.await();
- sync.release(1);
- threadShouldThrow();
- }
- catch(InterruptedException success) {
- }
- }
- });
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire(1);
+ c.await();
+ }});
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join(SHORT_DELAY_MS);
- assertFalse(t.isAlive());
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join(SHORT_DELAY_MS);
+ assertFalse(t.isAlive());
}
/**
* awaitNanos is interruptible
*/
- public void testAwaitNanos_Interrupt() {
- final Mutex sync = new Mutex();
+ public void testAwaitNanos_Interrupt() throws InterruptedException {
+ final Mutex sync = new Mutex();
final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- sync.acquire(1);
- c.awaitNanos(1000 * 1000 * 1000); // 1 sec
- sync.release(1);
- threadShouldThrow();
- }
- catch(InterruptedException success) {
- }
- }
- });
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire(1);
+ c.awaitNanos(MILLISECONDS.toNanos(LONG_DELAY_MS));
+ }});
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join(SHORT_DELAY_MS);
- assertFalse(t.isAlive());
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join(SHORT_DELAY_MS);
+ assertFalse(t.isAlive());
}
/**
* awaitUntil is interruptible
*/
- public void testAwaitUntil_Interrupt() {
- final Mutex sync = new Mutex();
+ public void testAwaitUntil_Interrupt() throws InterruptedException {
+ final Mutex sync = new Mutex();
final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- sync.acquire(1);
- java.util.Date d = new java.util.Date();
- c.awaitUntil(new java.util.Date(d.getTime() + 10000));
- sync.release(1);
- threadShouldThrow();
- }
- catch(InterruptedException success) {
- }
- }
- });
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire(1);
+ java.util.Date d = new java.util.Date();
+ c.awaitUntil(new java.util.Date(d.getTime() + 10000));
+ }});
- try {
- t.start();
- // BEGIN android-changed
- Thread.sleep(SMALL_DELAY_MS); // SHORT_DELAY_MS was flaky on Android
- t.interrupt();
- t.join(SMALL_DELAY_MS); // SHORT_DELAY_MS was flaky on Android
- // END android-changed
- assertFalse(t.isAlive());
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join(SHORT_DELAY_MS);
+ assertFalse(t.isAlive());
}
/**
* signalAll wakes up all threads
*/
- public void testSignalAll() {
- final Mutex sync = new Mutex();
+ public void testSignalAll() throws InterruptedException {
+ final Mutex sync = new Mutex();
final AbstractQueuedSynchronizer.ConditionObject c = sync.newCondition();
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- try {
- sync.acquire(1);
- c.await();
- sync.release(1);
- }
- catch(InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
-
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- try {
- sync.acquire(1);
- c.await();
- sync.release(1);
- }
- catch(InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
-
- try {
- t1.start();
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- sync.acquire(1);
- c.signalAll();
- sync.release(1);
- t1.join(SHORT_DELAY_MS);
- t2.join(SHORT_DELAY_MS);
- assertFalse(t1.isAlive());
- assertFalse(t2.isAlive());
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire(1);
+ c.await();
+ sync.release(1);
+ }});
+
+ Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ sync.acquire(1);
+ c.await();
+ sync.release(1);
+ }});
+
+ t1.start();
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ sync.acquire(1);
+ c.signalAll();
+ sync.release(1);
+ t1.join(SHORT_DELAY_MS);
+ t2.join(SHORT_DELAY_MS);
+ assertFalse(t1.isAlive());
+ assertFalse(t2.isAlive());
}
@@ -1119,25 +883,20 @@ public class AbstractQueuedSynchronizerTest extends JSR166TestCase {
/**
* A serialized AQS deserializes with current state
*/
- public void testSerialization() {
+ public void testSerialization() throws Exception {
Mutex l = new Mutex();
l.acquire(1);
assertTrue(l.isHeldExclusively());
- try {
- ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
- ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
- out.writeObject(l);
- out.close();
-
- ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
- ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
- Mutex r = (Mutex) in.readObject();
- assertTrue(r.isHeldExclusively());
- } catch(Exception e){
- e.printStackTrace();
- unexpectedException();
- }
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(l);
+ out.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ Mutex r = (Mutex) in.readObject();
+ assertTrue(r.isHeldExclusively());
}
@@ -1166,136 +925,99 @@ public class AbstractQueuedSynchronizerTest extends JSR166TestCase {
/**
* acquireSharedInterruptibly returns after release, but not before
*/
- public void testAcquireSharedInterruptibly() {
+ public void testAcquireSharedInterruptibly() throws InterruptedException {
final BooleanLatch l = new BooleanLatch();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- threadAssertFalse(l.isSignalled());
- l.acquireSharedInterruptibly(0);
- threadAssertTrue(l.isSignalled());
- } catch(InterruptedException e){
- threadUnexpectedException();
- }
- }
- });
- try {
- t.start();
- assertFalse(l.isSignalled());
- Thread.sleep(SHORT_DELAY_MS);
- l.releaseShared(0);
- assertTrue(l.isSignalled());
- t.join();
- } catch (InterruptedException e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ threadAssertFalse(l.isSignalled());
+ l.acquireSharedInterruptibly(0);
+ threadAssertTrue(l.isSignalled());
+ }});
+
+ t.start();
+ assertFalse(l.isSignalled());
+ Thread.sleep(SHORT_DELAY_MS);
+ l.releaseShared(0);
+ assertTrue(l.isSignalled());
+ t.join();
}
-
+
/**
* acquireSharedTimed returns after release
*/
- public void testAsquireSharedTimed() {
+ public void testAsquireSharedTimed() throws InterruptedException {
final BooleanLatch l = new BooleanLatch();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- threadAssertFalse(l.isSignalled());
- threadAssertTrue(l.tryAcquireSharedNanos(0, MEDIUM_DELAY_MS* 1000 * 1000));
- threadAssertTrue(l.isSignalled());
-
- } catch(InterruptedException e){
- threadUnexpectedException();
- }
- }
- });
- try {
- t.start();
- assertFalse(l.isSignalled());
- Thread.sleep(SHORT_DELAY_MS);
- l.releaseShared(0);
- assertTrue(l.isSignalled());
- t.join();
- } catch (InterruptedException e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertFalse(l.isSignalled());
+ long nanos = MILLISECONDS.toNanos(MEDIUM_DELAY_MS);
+ assertTrue(l.tryAcquireSharedNanos(0, nanos));
+ assertTrue(l.isSignalled());
+ }});
+
+ t.start();
+ assertFalse(l.isSignalled());
+ Thread.sleep(SHORT_DELAY_MS);
+ l.releaseShared(0);
+ assertTrue(l.isSignalled());
+ t.join();
}
-
+
/**
* acquireSharedInterruptibly throws IE if interrupted before released
*/
- public void testAcquireSharedInterruptibly_InterruptedException() {
+ public void testAcquireSharedInterruptibly_InterruptedException() throws InterruptedException {
final BooleanLatch l = new BooleanLatch();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- threadAssertFalse(l.isSignalled());
- l.acquireSharedInterruptibly(0);
- threadShouldThrow();
- } catch(InterruptedException success){}
- }
- });
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ threadAssertFalse(l.isSignalled());
+ l.acquireSharedInterruptibly(0);
+ }});
+
t.start();
- try {
- assertFalse(l.isSignalled());
- t.interrupt();
- t.join();
- } catch (InterruptedException e){
- unexpectedException();
- }
+ assertFalse(l.isSignalled());
+ t.interrupt();
+ t.join();
}
/**
* acquireSharedTimed throws IE if interrupted before released
*/
- public void testAcquireSharedNanos_InterruptedException() {
+ public void testAcquireSharedNanos_InterruptedException() throws InterruptedException {
final BooleanLatch l = new BooleanLatch();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- threadAssertFalse(l.isSignalled());
- l.tryAcquireSharedNanos(0, SMALL_DELAY_MS* 1000 * 1000);
- threadShouldThrow();
- } catch(InterruptedException success){}
- }
- });
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertFalse(l.isSignalled());
+ long nanos = MILLISECONDS.toNanos(SMALL_DELAY_MS);
+ l.tryAcquireSharedNanos(0, nanos);
+ }});
+
t.start();
- try {
- Thread.sleep(SHORT_DELAY_MS);
- assertFalse(l.isSignalled());
- t.interrupt();
- t.join();
- } catch (InterruptedException e){
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(l.isSignalled());
+ t.interrupt();
+ t.join();
}
/**
* acquireSharedTimed times out if not released before timeout
*/
- public void testAcquireSharedNanos_Timeout() {
+ public void testAcquireSharedNanos_Timeout() throws InterruptedException {
final BooleanLatch l = new BooleanLatch();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- threadAssertFalse(l.isSignalled());
- threadAssertFalse(l.tryAcquireSharedNanos(0, SMALL_DELAY_MS* 1000 * 1000));
- } catch(InterruptedException ie){
- threadUnexpectedException();
- }
- }
- });
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertFalse(l.isSignalled());
+ long nanos = MILLISECONDS.toNanos(SMALL_DELAY_MS);
+ assertFalse(l.tryAcquireSharedNanos(0, nanos));
+ }});
+
t.start();
- try {
- Thread.sleep(SHORT_DELAY_MS);
- assertFalse(l.isSignalled());
- t.join();
- } catch (InterruptedException e){
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(l.isSignalled());
+ t.join();
}
-
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/ArrayBlockingQueueTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/ArrayBlockingQueueTest.java
index 1deea2c..8fc5cb6 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/ArrayBlockingQueueTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/ArrayBlockingQueueTest.java
@@ -2,15 +2,16 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.*;
import java.util.concurrent.*;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.io.*;
public class ArrayBlockingQueueTest extends JSR166TestCase {
@@ -25,14 +26,14 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
private ArrayBlockingQueue populatedQueue(int n) {
ArrayBlockingQueue q = new ArrayBlockingQueue(n);
assertTrue(q.isEmpty());
- for(int i = 0; i < n; i++)
+ for (int i = 0; i < n; i++)
assertTrue(q.offer(new Integer(i)));
assertFalse(q.isEmpty());
assertEquals(0, q.remainingCapacity());
assertEquals(n, q.size());
return q;
}
-
+
/**
* A new queue has the indicated capacity
*/
@@ -41,14 +42,13 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
}
/**
- * Constructor throws IAE if capacity argument nonpositive
+ * Constructor throws IAE if capacity argument nonpositive
*/
public void testConstructor2() {
try {
ArrayBlockingQueue q = new ArrayBlockingQueue(0);
shouldThrow();
- }
- catch (IllegalArgumentException success) {}
+ } catch (IllegalArgumentException success) {}
}
/**
@@ -58,8 +58,7 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
try {
ArrayBlockingQueue q = new ArrayBlockingQueue(1, true, null);
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
@@ -70,8 +69,7 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
Integer[] ints = new Integer[SIZE];
ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE, false, Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
@@ -84,8 +82,7 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
ints[i] = new Integer(i);
ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE, false, Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
@@ -98,23 +95,19 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
ints[i] = new Integer(i);
ArrayBlockingQueue q = new ArrayBlockingQueue(1, false, Arrays.asList(ints));
shouldThrow();
- }
- catch (IllegalArgumentException success) {}
+ } catch (IllegalArgumentException success) {}
}
/**
* Queue contains all elements of collection used to initialize
*/
public void testConstructor7() {
- try {
- Integer[] ints = new Integer[SIZE];
- for (int i = 0; i < SIZE; ++i)
- ints[i] = new Integer(i);
- ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE, true, Arrays.asList(ints));
- for (int i = 0; i < SIZE; ++i)
- assertEquals(ints[i], q.poll());
- }
- finally {}
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = new Integer(i);
+ ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE, true, Arrays.asList(ints));
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(ints[i], q.poll());
}
/**
@@ -157,7 +150,7 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
ArrayBlockingQueue q = new ArrayBlockingQueue(1);
q.offer(null);
shouldThrow();
- } catch (NullPointerException success) { }
+ } catch (NullPointerException success) {}
}
/**
@@ -168,7 +161,7 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
ArrayBlockingQueue q = new ArrayBlockingQueue(1);
q.add(null);
shouldThrow();
- } catch (NullPointerException success) { }
+ } catch (NullPointerException success) {}
}
/**
@@ -191,8 +184,8 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
}
assertEquals(0, q.remainingCapacity());
q.add(new Integer(SIZE));
- } catch (IllegalStateException success){
- }
+ shouldThrow();
+ } catch (IllegalStateException success) {}
}
/**
@@ -203,8 +196,7 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
ArrayBlockingQueue q = new ArrayBlockingQueue(1);
q.addAll(null);
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
@@ -215,8 +207,7 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
ArrayBlockingQueue q = populatedQueue(SIZE);
q.addAll(q);
shouldThrow();
- }
- catch (IllegalArgumentException success) {}
+ } catch (IllegalArgumentException success) {}
}
@@ -229,8 +220,7 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
Integer[] ints = new Integer[SIZE];
q.addAll(Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
* addAll of a collection with any null elements throws NPE after
@@ -244,8 +234,7 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
ints[i] = new Integer(i);
q.addAll(Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
* addAll throws ISE if not enough room
@@ -258,214 +247,166 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
ints[i] = new Integer(i);
q.addAll(Arrays.asList(ints));
shouldThrow();
- }
- catch (IllegalStateException success) {}
+ } catch (IllegalStateException success) {}
}
/**
* Queue contains all elements, in traversal order, of successful addAll
*/
public void testAddAll5() {
- try {
- Integer[] empty = new Integer[0];
- Integer[] ints = new Integer[SIZE];
- for (int i = 0; i < SIZE; ++i)
- ints[i] = new Integer(i);
- ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE);
- assertFalse(q.addAll(Arrays.asList(empty)));
- assertTrue(q.addAll(Arrays.asList(ints)));
- for (int i = 0; i < SIZE; ++i)
- assertEquals(ints[i], q.poll());
- }
- finally {}
+ Integer[] empty = new Integer[0];
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = new Integer(i);
+ ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE);
+ assertFalse(q.addAll(Arrays.asList(empty)));
+ assertTrue(q.addAll(Arrays.asList(ints)));
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(ints[i], q.poll());
}
/**
* put(null) throws NPE
*/
- public void testPutNull() {
+ public void testPutNull() throws InterruptedException {
try {
ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE);
q.put(null);
shouldThrow();
- }
- catch (NullPointerException success){
- }
- catch (InterruptedException ie) {
- unexpectedException();
- }
+ } catch (NullPointerException success) {}
}
/**
* all elements successfully put are contained
*/
- public void testPut() {
- try {
- ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE);
- for (int i = 0; i < SIZE; ++i) {
- Integer I = new Integer(i);
- q.put(I);
- assertTrue(q.contains(I));
- }
- assertEquals(0, q.remainingCapacity());
- }
- catch (InterruptedException ie) {
- unexpectedException();
+ public void testPut() throws InterruptedException {
+ ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ Integer I = new Integer(i);
+ q.put(I);
+ assertTrue(q.contains(I));
}
+ assertEquals(0, q.remainingCapacity());
}
/**
* put blocks interruptibly if full
*/
- public void testBlockingPut() {
+ public void testBlockingPut() throws InterruptedException {
final ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE);
- Thread t = new Thread(new Runnable() {
- public void run() {
- int added = 0;
- try {
- for (int i = 0; i < SIZE; ++i) {
- q.put(new Integer(i));
- ++added;
- }
- q.put(new Integer(SIZE));
- threadShouldThrow();
- } catch (InterruptedException ie){
- threadAssertEquals(added, SIZE);
- }
- }});
- try {
- t.start();
- Thread.sleep(MEDIUM_DELAY_MS);
- t.interrupt();
- t.join();
- }
- catch (InterruptedException ie) {
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ for (int i = 0; i < SIZE; ++i)
+ q.put(i);
+ assertEquals(SIZE, q.size());
+ assertEquals(0, q.remainingCapacity());
+ try {
+ q.put(99);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
+ assertEquals(SIZE, q.size());
+ assertEquals(0, q.remainingCapacity());
}
/**
* put blocks waiting for take when full
*/
- public void testPutWithTake() {
- final ArrayBlockingQueue q = new ArrayBlockingQueue(2);
- Thread t = new Thread(new Runnable() {
- public void run() {
- int added = 0;
- try {
- q.put(new Object());
- ++added;
- q.put(new Object());
- ++added;
- q.put(new Object());
- ++added;
- q.put(new Object());
- ++added;
- threadShouldThrow();
- } catch (InterruptedException e){
- threadAssertTrue(added >= 2);
- }
- }
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- q.take();
- t.interrupt();
- t.join();
- } catch (Exception e){
- unexpectedException();
- }
+ public void testPutWithTake() throws InterruptedException {
+ final int capacity = 2;
+ final ArrayBlockingQueue q = new ArrayBlockingQueue(capacity);
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ for (int i = 0; i < capacity + 1; i++)
+ q.put(i);
+ try {
+ q.put(99);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(q.remainingCapacity(), 0);
+ assertEquals(0, q.take());
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
+ assertEquals(q.remainingCapacity(), 0);
}
/**
* timed offer times out if full and elements not taken
*/
- public void testTimedOffer() {
+ public void testTimedOffer() throws InterruptedException {
final ArrayBlockingQueue q = new ArrayBlockingQueue(2);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- q.put(new Object());
- q.put(new Object());
- threadAssertFalse(q.offer(new Object(), SHORT_DELAY_MS/2, TimeUnit.MILLISECONDS));
- q.offer(new Object(), LONG_DELAY_MS, TimeUnit.MILLISECONDS);
- threadShouldThrow();
- } catch (InterruptedException success){}
- }
- });
-
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- } catch (Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ q.put(new Object());
+ q.put(new Object());
+ assertFalse(q.offer(new Object(), SHORT_DELAY_MS/2, MILLISECONDS));
+ try {
+ q.offer(new Object(), LONG_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* take retrieves elements in FIFO order
*/
- public void testTake() {
- try {
- ArrayBlockingQueue q = populatedQueue(SIZE);
- for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.take()).intValue());
- }
- } catch (InterruptedException e){
- unexpectedException();
- }
+ public void testTake() throws InterruptedException {
+ ArrayBlockingQueue q = populatedQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.take());
+ }
}
/**
* take blocks interruptibly when empty
*/
- public void testTakeFromEmpty() {
+ public void testTakeFromEmpty() throws InterruptedException {
final ArrayBlockingQueue q = new ArrayBlockingQueue(2);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- q.take();
- threadShouldThrow();
- } catch (InterruptedException success){ }
- }
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- } catch (Exception e){
- unexpectedException();
- }
+ Thread t = new ThreadShouldThrow(InterruptedException.class) {
+ public void realRun() throws InterruptedException {
+ q.take();
+ }};
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* Take removes existing elements until empty, then blocks interruptibly
*/
- public void testBlockingTake() {
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- ArrayBlockingQueue q = populatedQueue(SIZE);
- for (int i = 0; i < SIZE; ++i) {
- threadAssertEquals(i, ((Integer)q.take()).intValue());
- }
- q.take();
- threadShouldThrow();
- } catch (InterruptedException success){
- }
- }});
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- }
- catch (InterruptedException ie) {
- unexpectedException();
- }
+ public void testBlockingTake() throws InterruptedException {
+ final ArrayBlockingQueue q = populatedQueue(SIZE);
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.take());
+ }
+ try {
+ q.take();
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
@@ -475,7 +416,7 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
public void testPoll() {
ArrayBlockingQueue q = populatedQueue(SIZE);
for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.poll()).intValue());
+ assertEquals(i, q.poll());
}
assertNull(q.poll());
}
@@ -483,86 +424,70 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
/**
* timed pool with zero timeout succeeds when non-empty, else times out
*/
- public void testTimedPoll0() {
- try {
- ArrayBlockingQueue q = populatedQueue(SIZE);
- for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.poll(0, TimeUnit.MILLISECONDS)).intValue());
- }
- assertNull(q.poll(0, TimeUnit.MILLISECONDS));
- } catch (InterruptedException e){
- unexpectedException();
- }
+ public void testTimedPoll0() throws InterruptedException {
+ ArrayBlockingQueue q = populatedQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.poll(0, MILLISECONDS));
+ }
+ assertNull(q.poll(0, MILLISECONDS));
}
/**
* timed pool with nonzero timeout succeeds when non-empty, else times out
*/
- public void testTimedPoll() {
- try {
- ArrayBlockingQueue q = populatedQueue(SIZE);
- for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)).intValue());
- }
- assertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- } catch (InterruptedException e){
- unexpectedException();
- }
+ public void testTimedPoll() throws InterruptedException {
+ ArrayBlockingQueue q = populatedQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.poll(SHORT_DELAY_MS, MILLISECONDS));
+ }
+ assertNull(q.poll(SHORT_DELAY_MS, MILLISECONDS));
}
/**
* Interrupted timed poll throws InterruptedException instead of
* returning timeout status
*/
- public void testInterruptedTimedPoll() {
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- ArrayBlockingQueue q = populatedQueue(SIZE);
- for (int i = 0; i < SIZE; ++i) {
- threadAssertEquals(i, ((Integer)q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)).intValue());
- }
- threadAssertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- } catch (InterruptedException success){
- }
- }});
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- }
- catch (InterruptedException ie) {
- unexpectedException();
- }
+ public void testInterruptedTimedPoll() throws InterruptedException {
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ ArrayBlockingQueue q = populatedQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.poll(SHORT_DELAY_MS, MILLISECONDS));;
+ }
+ try {
+ q.poll(SMALL_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* timed poll before a delayed offer fails; after offer succeeds;
* on interruption throws
*/
- public void testTimedPollWithOffer() {
+ public void testTimedPollWithOffer() throws InterruptedException {
final ArrayBlockingQueue q = new ArrayBlockingQueue(2);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- threadAssertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- q.poll(LONG_DELAY_MS, TimeUnit.MILLISECONDS);
- q.poll(LONG_DELAY_MS, TimeUnit.MILLISECONDS);
- threadShouldThrow();
- } catch (InterruptedException success) { }
- }
- });
- try {
- t.start();
- Thread.sleep(SMALL_DELAY_MS);
- assertTrue(q.offer(zero, SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- t.interrupt();
- t.join();
- } catch (Exception e){
- unexpectedException();
- }
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertNull(q.poll(SHORT_DELAY_MS, MILLISECONDS));
+ assertSame(zero, q.poll(LONG_DELAY_MS, MILLISECONDS));
+ try {
+ q.poll(LONG_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SMALL_DELAY_MS);
+ assertTrue(q.offer(zero, SHORT_DELAY_MS, MILLISECONDS));
+ t.interrupt();
+ t.join();
+ }
/**
@@ -571,10 +496,10 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
public void testPeek() {
ArrayBlockingQueue q = populatedQueue(SIZE);
for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.peek()).intValue());
- q.poll();
+ assertEquals(i, q.peek());
+ assertEquals(i, q.poll());
assertTrue(q.peek() == null ||
- i != ((Integer)q.peek()).intValue());
+ !q.peek().equals(i));
}
assertNull(q.peek());
}
@@ -585,14 +510,13 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
public void testElement() {
ArrayBlockingQueue q = populatedQueue(SIZE);
for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.element()).intValue());
- q.poll();
+ assertEquals(i, q.element());
+ assertEquals(i, q.poll());
}
try {
q.element();
shouldThrow();
- }
- catch (NoSuchElementException success) {}
+ } catch (NoSuchElementException success) {}
}
/**
@@ -601,13 +525,12 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
public void testRemove() {
ArrayBlockingQueue q = populatedQueue(SIZE);
for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.remove()).intValue());
+ assertEquals(i, q.remove());
}
try {
q.remove();
shouldThrow();
- } catch (NoSuchElementException success){
- }
+ } catch (NoSuchElementException success) {}
}
/**
@@ -624,7 +547,7 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
}
assertTrue(q.isEmpty());
}
-
+
/**
* contains(x) reports true when elements added but not yet removed
*/
@@ -632,7 +555,7 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
ArrayBlockingQueue q = populatedQueue(SIZE);
for (int i = 0; i < SIZE; ++i) {
assertTrue(q.contains(new Integer(i)));
- q.poll();
+ assertEquals(i, q.poll());
assertFalse(q.contains(new Integer(i)));
}
}
@@ -705,68 +628,56 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
/**
* toArray contains all elements
*/
- public void testToArray() {
+ public void testToArray() throws InterruptedException {
ArrayBlockingQueue q = populatedQueue(SIZE);
Object[] o = q.toArray();
- try {
- for(int i = 0; i < o.length; i++)
+ for (int i = 0; i < o.length; i++)
assertEquals(o[i], q.take());
- } catch (InterruptedException e){
- unexpectedException();
- }
}
/**
* toArray(a) contains all elements
*/
- public void testToArray2() {
+ public void testToArray2() throws InterruptedException {
ArrayBlockingQueue q = populatedQueue(SIZE);
Integer[] ints = new Integer[SIZE];
ints = (Integer[])q.toArray(ints);
- try {
- for(int i = 0; i < ints.length; i++)
- assertEquals(ints[i], q.take());
- } catch (InterruptedException e){
- unexpectedException();
- }
+ for (int i = 0; i < ints.length; i++)
+ assertEquals(ints[i], q.take());
}
/**
* toArray(null) throws NPE
*/
public void testToArray_BadArg() {
+ ArrayBlockingQueue q = populatedQueue(SIZE);
try {
- ArrayBlockingQueue q = populatedQueue(SIZE);
Object o[] = q.toArray(null);
shouldThrow();
- } catch(NullPointerException success){}
+ } catch (NullPointerException success) {}
}
/**
* toArray with incompatible array type throws CCE
*/
public void testToArray1_BadArg() {
+ ArrayBlockingQueue q = populatedQueue(SIZE);
try {
- ArrayBlockingQueue q = populatedQueue(SIZE);
- Object o[] = q.toArray(new String[10] );
+ Object o[] = q.toArray(new String[10]);
shouldThrow();
- } catch(ArrayStoreException success){}
+ } catch (ArrayStoreException success) {}
}
-
+
/**
* iterator iterates through all elements
*/
- public void testIterator() {
+ public void testIterator() throws InterruptedException {
ArrayBlockingQueue q = populatedQueue(SIZE);
Iterator it = q.iterator();
- try {
- while(it.hasNext()){
- assertEquals(it.next(), q.take());
- }
- } catch (InterruptedException e){
- unexpectedException();
- }
+ while (it.hasNext()) {
+ assertEquals(it.next(), q.take());
+ }
}
/**
@@ -781,10 +692,10 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
Iterator it = q.iterator();
it.next();
it.remove();
-
+
it = q.iterator();
- assertEquals(it.next(), one);
- assertEquals(it.next(), three);
+ assertSame(it.next(), one);
+ assertSame(it.next(), three);
assertFalse(it.hasNext());
}
@@ -801,8 +712,7 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
int k = 0;
for (Iterator it = q.iterator(); it.hasNext();) {
- int i = ((Integer)(it.next())).intValue();
- assertEquals(++k, i);
+ assertEquals(++k, it.next());
}
assertEquals(3, k);
}
@@ -815,14 +725,9 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
q.add(one);
q.add(two);
q.add(three);
- try {
- for (Iterator it = q.iterator(); it.hasNext();) {
- q.remove();
- it.next();
- }
- }
- catch (ConcurrentModificationException e) {
- unexpectedException();
+ for (Iterator it = q.iterator(); it.hasNext();) {
+ q.remove();
+ it.next();
}
assertEquals(0, q.size());
}
@@ -837,7 +742,7 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
for (int i = 0; i < SIZE; ++i) {
assertTrue(s.indexOf(String.valueOf(i)) >= 0);
}
- }
+ }
/**
@@ -848,33 +753,20 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
q.add(one);
q.add(two);
ExecutorService executor = Executors.newFixedThreadPool(2);
- executor.execute(new Runnable() {
- public void run() {
- threadAssertFalse(q.offer(three));
- try {
- threadAssertTrue(q.offer(three, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS));
- threadAssertEquals(0, q.remainingCapacity());
- }
- catch (InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
+ executor.execute(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertFalse(q.offer(three));
+ assertTrue(q.offer(three, MEDIUM_DELAY_MS, MILLISECONDS));
+ assertEquals(0, q.remainingCapacity());
+ }});
+
+ executor.execute(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ Thread.sleep(SMALL_DELAY_MS);
+ assertSame(one, q.take());
+ }});
- executor.execute(new Runnable() {
- public void run() {
- try {
- Thread.sleep(SMALL_DELAY_MS);
- threadAssertEquals(one, q.take());
- }
- catch (InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
-
joinPool(executor);
-
}
/**
@@ -883,91 +775,73 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
public void testPollInExecutor() {
final ArrayBlockingQueue q = new ArrayBlockingQueue(2);
ExecutorService executor = Executors.newFixedThreadPool(2);
- executor.execute(new Runnable() {
- public void run() {
- threadAssertNull(q.poll());
- try {
- threadAssertTrue(null != q.poll(MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS));
- threadAssertTrue(q.isEmpty());
- }
- catch (InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
+ executor.execute(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertNull(q.poll());
+ assertSame(one, q.poll(MEDIUM_DELAY_MS, MILLISECONDS));
+ assertTrue(q.isEmpty());
+ }});
+
+ executor.execute(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ Thread.sleep(SMALL_DELAY_MS);
+ q.put(one);
+ }});
- executor.execute(new Runnable() {
- public void run() {
- try {
- Thread.sleep(SMALL_DELAY_MS);
- q.put(one);
- }
- catch (InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
-
joinPool(executor);
}
/**
* A deserialized serialized queue has same elements in same order
*/
- public void testSerialization() {
+ public void testSerialization() throws Exception {
ArrayBlockingQueue q = populatedQueue(SIZE);
- try {
- ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
- ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
- out.writeObject(q);
- out.close();
-
- ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
- ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
- ArrayBlockingQueue r = (ArrayBlockingQueue)in.readObject();
- assertEquals(q.size(), r.size());
- while (!q.isEmpty())
- assertEquals(q.remove(), r.remove());
- } catch(Exception e){
- unexpectedException();
- }
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(q);
+ out.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ ArrayBlockingQueue r = (ArrayBlockingQueue)in.readObject();
+ assertEquals(q.size(), r.size());
+ while (!q.isEmpty())
+ assertEquals(q.remove(), r.remove());
}
/**
* drainTo(null) throws NPE
- */
+ */
public void testDrainToNull() {
ArrayBlockingQueue q = populatedQueue(SIZE);
try {
q.drainTo(null);
shouldThrow();
- } catch(NullPointerException success) {
- }
+ } catch (NullPointerException success) {}
}
/**
* drainTo(this) throws IAE
- */
+ */
public void testDrainToSelf() {
ArrayBlockingQueue q = populatedQueue(SIZE);
try {
q.drainTo(q);
shouldThrow();
- } catch(IllegalArgumentException success) {
- }
+ } catch (IllegalArgumentException success) {}
}
/**
* drainTo(c) empties queue into another collection c
- */
+ */
public void testDrainTo() {
ArrayBlockingQueue q = populatedQueue(SIZE);
ArrayList l = new ArrayList();
q.drainTo(l);
assertEquals(q.size(), 0);
assertEquals(l.size(), SIZE);
- for (int i = 0; i < SIZE; ++i)
+ for (int i = 0; i < SIZE; ++i)
assertEquals(l.get(i), new Integer(i));
q.add(zero);
q.add(one);
@@ -978,80 +852,69 @@ public class ArrayBlockingQueueTest extends JSR166TestCase {
q.drainTo(l);
assertEquals(q.size(), 0);
assertEquals(l.size(), 2);
- for (int i = 0; i < 2; ++i)
+ for (int i = 0; i < 2; ++i)
assertEquals(l.get(i), new Integer(i));
}
/**
* drainTo empties full queue, unblocking a waiting put.
- */
- public void testDrainToWithActivePut() {
+ */
+ public void testDrainToWithActivePut() throws InterruptedException {
final ArrayBlockingQueue q = populatedQueue(SIZE);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- q.put(new Integer(SIZE+1));
- } catch (InterruptedException ie){
- threadUnexpectedException();
- }
- }
- });
- try {
- t.start();
- ArrayList l = new ArrayList();
- q.drainTo(l);
- assertTrue(l.size() >= SIZE);
- for (int i = 0; i < SIZE; ++i)
- assertEquals(l.get(i), new Integer(i));
- t.join();
- assertTrue(q.size() + l.size() >= SIZE);
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ q.put(new Integer(SIZE+1));
+ }});
+
+ t.start();
+ ArrayList l = new ArrayList();
+ q.drainTo(l);
+ assertTrue(l.size() >= SIZE);
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(l.get(i), new Integer(i));
+ t.join();
+ assertTrue(q.size() + l.size() >= SIZE);
}
/**
* drainTo(null, n) throws NPE
- */
+ */
public void testDrainToNullN() {
ArrayBlockingQueue q = populatedQueue(SIZE);
try {
q.drainTo(null, 0);
shouldThrow();
- } catch(NullPointerException success) {
- }
+ } catch (NullPointerException success) {}
}
/**
* drainTo(this, n) throws IAE
- */
+ */
public void testDrainToSelfN() {
ArrayBlockingQueue q = populatedQueue(SIZE);
try {
q.drainTo(q, 0);
shouldThrow();
- } catch(IllegalArgumentException success) {
- }
+ } catch (IllegalArgumentException success) {}
}
/**
* drainTo(c, n) empties first max {n, size} elements of queue into c
- */
+ */
public void testDrainToN() {
ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE*2);
for (int i = 0; i < SIZE + 2; ++i) {
- for(int j = 0; j < SIZE; j++)
+ for (int j = 0; j < SIZE; j++)
assertTrue(q.offer(new Integer(j)));
ArrayList l = new ArrayList();
q.drainTo(l, i);
int k = (i < SIZE)? i : SIZE;
assertEquals(l.size(), k);
assertEquals(q.size(), SIZE-k);
- for (int j = 0; j < k; ++j)
+ for (int j = 0; j < k; ++j)
assertEquals(l.get(j), new Integer(j));
while (q.poll() != null) ;
}
}
-
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/ArrayDequeTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/ArrayDequeTest.java
new file mode 100644
index 0000000..cec1d58
--- /dev/null
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/ArrayDequeTest.java
@@ -0,0 +1,630 @@
+/*
+ * 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 tests.api.java.util.concurrent; // android-added
+
+import junit.framework.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+public class ArrayDequeTest extends JSR166TestCase {
+ public static Test suite() {
+ return new TestSuite(ArrayDequeTest.class);
+ }
+
+ /**
+ * Create a queue of given size containing consecutive
+ * Integers 0 ... n.
+ */
+ private ArrayDeque populatedDeque(int n) {
+ ArrayDeque q = new ArrayDeque();
+ assertTrue(q.isEmpty());
+ for (int i = 0; i < n; ++i)
+ assertTrue(q.offerLast(new Integer(i)));
+ assertFalse(q.isEmpty());
+ assertEquals(n, q.size());
+ return q;
+ }
+
+ /**
+ * new queue is empty
+ */
+ public void testConstructor1() {
+ assertEquals(0, new ArrayDeque().size());
+ }
+
+ /**
+ * Initializing from null Collection throws NPE
+ */
+ public void testConstructor3() {
+ try {
+ ArrayDeque q = new ArrayDeque((Collection)null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * Queue contains all elements of collection used to initialize
+
+ */
+ public void testConstructor6() {
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = new Integer(i);
+ ArrayDeque q = new ArrayDeque(Arrays.asList(ints));
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(ints[i], q.pollFirst());
+ }
+
+ /**
+ * isEmpty is true before add, false after
+ */
+ public void testEmpty() {
+ ArrayDeque q = new ArrayDeque();
+ assertTrue(q.isEmpty());
+ q.add(new Integer(1));
+ assertFalse(q.isEmpty());
+ q.add(new Integer(2));
+ q.removeFirst();
+ q.removeFirst();
+ assertTrue(q.isEmpty());
+ }
+
+ /**
+ * size changes when elements added and removed
+ */
+ public void testSize() {
+ ArrayDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(SIZE-i, q.size());
+ q.removeFirst();
+ }
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.size());
+ q.add(new Integer(i));
+ }
+ }
+
+ /**
+ * push(null) throws NPE
+ */
+ public void testPushNull() {
+ try {
+ ArrayDeque q = new ArrayDeque(1);
+ q.push(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * peekFirst returns element inserted with push
+ */
+ public void testPush() {
+ ArrayDeque q = populatedDeque(3);
+ q.pollLast();
+ q.push(four);
+ assertSame(four, q.peekFirst());
+ }
+
+ /**
+ * pop removes next element, or throws NSEE if empty
+ */
+ public void testPop() {
+ ArrayDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.pop());
+ }
+ try {
+ q.pop();
+ shouldThrow();
+ } catch (NoSuchElementException success) {}
+ }
+
+ /**
+ * offer(null) throws NPE
+ */
+ public void testOfferFirstNull() {
+ try {
+ ArrayDeque q = new ArrayDeque();
+ q.offerFirst(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * OfferFirst succeeds
+ */
+ public void testOfferFirst() {
+ ArrayDeque q = new ArrayDeque();
+ assertTrue(q.offerFirst(new Integer(0)));
+ assertTrue(q.offerFirst(new Integer(1)));
+ }
+
+ /**
+ * OfferLast succeeds
+ */
+ public void testOfferLast() {
+ ArrayDeque q = new ArrayDeque();
+ assertTrue(q.offerLast(new Integer(0)));
+ assertTrue(q.offerLast(new Integer(1)));
+ }
+
+ /**
+ * add succeeds
+ */
+ public void testAdd() {
+ ArrayDeque q = new ArrayDeque();
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.size());
+ assertTrue(q.add(new Integer(i)));
+ }
+ }
+
+ /**
+ * addAll(null) throws NPE
+ */
+ public void testAddAll1() {
+ try {
+ ArrayDeque q = new ArrayDeque();
+ q.addAll(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * Queue contains all elements, in traversal order, of successful addAll
+ */
+ public void testAddAll5() {
+ Integer[] empty = new Integer[0];
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = new Integer(i);
+ ArrayDeque q = new ArrayDeque();
+ assertFalse(q.addAll(Arrays.asList(empty)));
+ assertTrue(q.addAll(Arrays.asList(ints)));
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(ints[i], q.pollFirst());
+ }
+
+ /**
+ * pollFirst succeeds unless empty
+ */
+ public void testPollFirst() {
+ ArrayDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.pollFirst());
+ }
+ assertNull(q.pollFirst());
+ }
+
+ /**
+ * pollLast succeeds unless empty
+ */
+ public void testPollLast() {
+ ArrayDeque q = populatedDeque(SIZE);
+ for (int i = SIZE-1; i >= 0; --i) {
+ assertEquals(i, q.pollLast());
+ }
+ assertNull(q.pollLast());
+ }
+
+ /**
+ * poll succeeds unless empty
+ */
+ public void testPoll() {
+ ArrayDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.poll());
+ }
+ assertNull(q.poll());
+ }
+
+ /**
+ * remove removes next element, or throws NSEE if empty
+ */
+ public void testRemove() {
+ ArrayDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.remove());
+ }
+ try {
+ q.remove();
+ shouldThrow();
+ } catch (NoSuchElementException success) {}
+ }
+
+ /**
+ * peekFirst returns next element, or null if empty
+ */
+ public void testPeekFirst() {
+ ArrayDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.peekFirst());
+ assertEquals(i, q.pollFirst());
+ assertTrue(q.peekFirst() == null ||
+ !q.peekFirst().equals(i));
+ }
+ assertNull(q.peekFirst());
+ }
+
+ /**
+ * peek returns next element, or null if empty
+ */
+ public void testPeek() {
+ ArrayDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.peek());
+ assertEquals(i, q.poll());
+ assertTrue(q.peek() == null ||
+ !q.peek().equals(i));
+ }
+ assertNull(q.peek());
+ }
+
+ /**
+ * peekLast returns next element, or null if empty
+ */
+ public void testPeekLast() {
+ ArrayDeque q = populatedDeque(SIZE);
+ for (int i = SIZE-1; i >= 0; --i) {
+ assertEquals(i, q.peekLast());
+ assertEquals(i, q.pollLast());
+ assertTrue(q.peekLast() == null ||
+ !q.peekLast().equals(i));
+ }
+ assertNull(q.peekLast());
+ }
+
+ /**
+ * getFirst returns next getFirst, or throws NSEE if empty
+ */
+ public void testFirstElement() {
+ ArrayDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.getFirst());
+ assertEquals(i, q.pollFirst());
+ }
+ try {
+ q.getFirst();
+ shouldThrow();
+ } catch (NoSuchElementException success) {}
+ }
+
+ /**
+ * getLast returns next element, or throws NSEE if empty
+ */
+ public void testLastElement() {
+ ArrayDeque q = populatedDeque(SIZE);
+ for (int i = SIZE-1; i >= 0; --i) {
+ assertEquals(i, q.getLast());
+ assertEquals(i, q.pollLast());
+ }
+ try {
+ q.getLast();
+ shouldThrow();
+ } catch (NoSuchElementException success) {}
+ assertNull(q.peekLast());
+ }
+
+
+ /**
+ * removeFirst removes next element, or throws NSEE if empty
+ */
+ public void testRemoveFirst() {
+ ArrayDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.removeFirst());
+ }
+ try {
+ q.removeFirst();
+ shouldThrow();
+ } catch (NoSuchElementException success) {}
+ }
+
+ /**
+ * removeFirstOccurrence(x) removes x and returns true if present
+ */
+ public void testRemoveFirstOccurrence() {
+ ArrayDeque q = populatedDeque(SIZE);
+ for (int i = 1; i < SIZE; i+=2) {
+ assertTrue(q.removeFirstOccurrence(new Integer(i)));
+ }
+ for (int i = 0; i < SIZE; i+=2) {
+ assertTrue(q.removeFirstOccurrence(new Integer(i)));
+ assertFalse(q.removeFirstOccurrence(new Integer(i+1)));
+ }
+ assertTrue(q.isEmpty());
+ }
+
+ /**
+ * removeLastOccurrence(x) removes x and returns true if present
+ */
+ public void testRemoveLastOccurrence() {
+ ArrayDeque q = populatedDeque(SIZE);
+ for (int i = 1; i < SIZE; i+=2) {
+ assertTrue(q.removeLastOccurrence(new Integer(i)));
+ }
+ for (int i = 0; i < SIZE; i+=2) {
+ assertTrue(q.removeLastOccurrence(new Integer(i)));
+ assertFalse(q.removeLastOccurrence(new Integer(i+1)));
+ }
+ assertTrue(q.isEmpty());
+ }
+
+ /**
+ * contains(x) reports true when elements added but not yet removed
+ */
+ public void testContains() {
+ ArrayDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertTrue(q.contains(new Integer(i)));
+ assertEquals(i, q.pollFirst());
+ assertFalse(q.contains(new Integer(i)));
+ }
+ }
+
+ /**
+ * clear removes all elements
+ */
+ public void testClear() {
+ ArrayDeque q = populatedDeque(SIZE);
+ q.clear();
+ assertTrue(q.isEmpty());
+ assertEquals(0, q.size());
+ assertTrue(q.add(new Integer(1)));
+ assertFalse(q.isEmpty());
+ q.clear();
+ assertTrue(q.isEmpty());
+ }
+
+ /**
+ * containsAll(c) is true when c contains a subset of elements
+ */
+ public void testContainsAll() {
+ ArrayDeque q = populatedDeque(SIZE);
+ ArrayDeque p = new ArrayDeque();
+ for (int i = 0; i < SIZE; ++i) {
+ assertTrue(q.containsAll(p));
+ assertFalse(p.containsAll(q));
+ assertTrue(p.add(new Integer(i)));
+ }
+ assertTrue(p.containsAll(q));
+ }
+
+ /**
+ * retainAll(c) retains only those elements of c and reports true if changed
+ */
+ public void testRetainAll() {
+ ArrayDeque q = populatedDeque(SIZE);
+ ArrayDeque p = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ boolean changed = q.retainAll(p);
+ assertEquals(changed, (i > 0));
+ assertTrue(q.containsAll(p));
+ assertEquals(SIZE-i, q.size());
+ p.removeFirst();
+ }
+ }
+
+ /**
+ * removeAll(c) removes only those elements of c and reports true if changed
+ */
+ public void testRemoveAll() {
+ for (int i = 1; i < SIZE; ++i) {
+ ArrayDeque q = populatedDeque(SIZE);
+ ArrayDeque p = populatedDeque(i);
+ assertTrue(q.removeAll(p));
+ assertEquals(SIZE-i, q.size());
+ for (int j = 0; j < i; ++j) {
+ assertFalse(q.contains(p.removeFirst()));
+ }
+ }
+ }
+
+ /**
+ * toArray contains all elements
+ */
+ public void testToArray() {
+ ArrayDeque q = populatedDeque(SIZE);
+ Object[] o = q.toArray();
+ Arrays.sort(o);
+ for (int i = 0; i < o.length; i++)
+ assertEquals(o[i], q.pollFirst());
+ }
+
+ /**
+ * toArray(a) contains all elements
+ */
+ public void testToArray2() {
+ ArrayDeque q = populatedDeque(SIZE);
+ Integer[] ints = new Integer[SIZE];
+ ints = (Integer[])q.toArray(ints);
+ Arrays.sort(ints);
+ for (int i = 0; i < ints.length; i++)
+ assertEquals(ints[i], q.pollFirst());
+ }
+
+ /**
+ * toArray(null) throws NPE
+ */
+ public void testToArray_BadArg() {
+ ArrayDeque l = new ArrayDeque();
+ l.add(new Object());
+ try {
+ Object o[] = l.toArray(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * toArray with incompatible array type throws CCE
+ */
+ public void testToArray1_BadArg() {
+ ArrayDeque l = new ArrayDeque();
+ l.add(new Integer(5));
+ try {
+ Object o[] = l.toArray(new String[10]);
+ shouldThrow();
+ } catch (ArrayStoreException success) {}
+ }
+
+ /**
+ * iterator iterates through all elements
+ */
+ public void testIterator() {
+ ArrayDeque q = populatedDeque(SIZE);
+ int i = 0;
+ Iterator it = q.iterator();
+ while (it.hasNext()) {
+ assertTrue(q.contains(it.next()));
+ ++i;
+ }
+ assertEquals(i, SIZE);
+ }
+
+ /**
+ * iterator ordering is FIFO
+ */
+ public void testIteratorOrdering() {
+ final ArrayDeque q = new ArrayDeque();
+ q.add(new Integer(1));
+ q.add(new Integer(2));
+ q.add(new Integer(3));
+ int k = 0;
+ for (Iterator it = q.iterator(); it.hasNext();) {
+ assertEquals(++k, it.next());
+ }
+
+ assertEquals(3, k);
+ }
+
+ /**
+ * iterator.remove removes current element
+ */
+ public void testIteratorRemove () {
+ final ArrayDeque q = new ArrayDeque();
+ final Random rng = new Random();
+ for (int iters = 0; iters < 100; ++iters) {
+ int max = rng.nextInt(5) + 2;
+ int split = rng.nextInt(max-1) + 1;
+ for (int j = 1; j <= max; ++j)
+ q.add(new Integer(j));
+ Iterator it = q.iterator();
+ for (int j = 1; j <= split; ++j)
+ assertEquals(it.next(), new Integer(j));
+ it.remove();
+ assertEquals(it.next(), new Integer(split+1));
+ for (int j = 1; j <= split; ++j)
+ q.remove(new Integer(j));
+ it = q.iterator();
+ for (int j = split+1; j <= max; ++j) {
+ assertEquals(it.next(), new Integer(j));
+ it.remove();
+ }
+ assertFalse(it.hasNext());
+ assertTrue(q.isEmpty());
+ }
+ }
+
+ /**
+ * Descending iterator iterates through all elements
+ */
+ public void testDescendingIterator() {
+ ArrayDeque q = populatedDeque(SIZE);
+ int i = 0;
+ Iterator it = q.descendingIterator();
+ while (it.hasNext()) {
+ assertTrue(q.contains(it.next()));
+ ++i;
+ }
+ assertEquals(i, SIZE);
+ assertFalse(it.hasNext());
+ try {
+ it.next();
+ shouldThrow();
+ } catch (NoSuchElementException success) {}
+ }
+
+ /**
+ * Descending iterator ordering is reverse FIFO
+ */
+ public void testDescendingIteratorOrdering() {
+ final ArrayDeque q = new ArrayDeque();
+ for (int iters = 0; iters < 100; ++iters) {
+ q.add(new Integer(3));
+ q.add(new Integer(2));
+ q.add(new Integer(1));
+ int k = 0;
+ for (Iterator it = q.descendingIterator(); it.hasNext();) {
+ assertEquals(++k, it.next());
+ }
+
+ assertEquals(3, k);
+ q.remove();
+ q.remove();
+ q.remove();
+ }
+ }
+
+ /**
+ * descendingIterator.remove removes current element
+ */
+ public void testDescendingIteratorRemove () {
+ final ArrayDeque q = new ArrayDeque();
+ final Random rng = new Random();
+ for (int iters = 0; iters < 100; ++iters) {
+ int max = rng.nextInt(5) + 2;
+ int split = rng.nextInt(max-1) + 1;
+ for (int j = max; j >= 1; --j)
+ q.add(new Integer(j));
+ Iterator it = q.descendingIterator();
+ for (int j = 1; j <= split; ++j)
+ assertEquals(it.next(), new Integer(j));
+ it.remove();
+ assertEquals(it.next(), new Integer(split+1));
+ for (int j = 1; j <= split; ++j)
+ q.remove(new Integer(j));
+ it = q.descendingIterator();
+ for (int j = split+1; j <= max; ++j) {
+ assertEquals(it.next(), new Integer(j));
+ it.remove();
+ }
+ assertFalse(it.hasNext());
+ assertTrue(q.isEmpty());
+ }
+ }
+
+
+ /**
+ * toString contains toStrings of elements
+ */
+ public void testToString() {
+ ArrayDeque q = populatedDeque(SIZE);
+ String s = q.toString();
+ for (int i = 0; i < SIZE; ++i) {
+ assertTrue(s.indexOf(String.valueOf(i)) >= 0);
+ }
+ }
+
+ /**
+ * peekFirst returns element inserted with addFirst
+ */
+ public void testAddFirst() {
+ ArrayDeque q = populatedDeque(3);
+ q.addFirst(four);
+ assertSame(four, q.peekFirst());
+ }
+
+ /**
+ * peekLast returns element inserted with addLast
+ */
+ public void testAddLast() {
+ ArrayDeque q = populatedDeque(3);
+ q.addLast(four);
+ assertSame(four, q.peekLast());
+ }
+
+}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicBooleanTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicBooleanTest.java
index c76196b..b2d91b8 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicBooleanTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicBooleanTest.java
@@ -2,11 +2,11 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.concurrent.atomic.*;
@@ -21,8 +21,8 @@ public class AtomicBooleanTest extends JSR166TestCase {
* constructor initializes to given value
*/
public void testConstructor() {
- AtomicBoolean ai = new AtomicBoolean(true);
- assertEquals(true,ai.get());
+ assertTrue(new AtomicBoolean(true).get());
+ assertFalse(new AtomicBoolean(false).get());
}
/**
@@ -30,7 +30,7 @@ public class AtomicBooleanTest extends JSR166TestCase {
*/
public void testConstructor2() {
AtomicBoolean ai = new AtomicBoolean();
- assertEquals(false,ai.get());
+ assertFalse(ai.get());
}
/**
@@ -38,12 +38,23 @@ public class AtomicBooleanTest extends JSR166TestCase {
*/
public void testGetSet() {
AtomicBoolean ai = new AtomicBoolean(true);
- assertEquals(true,ai.get());
+ assertTrue(ai.get());
ai.set(false);
- assertEquals(false,ai.get());
+ assertFalse(ai.get());
ai.set(true);
- assertEquals(true,ai.get());
-
+ assertTrue(ai.get());
+ }
+
+ /**
+ * get returns the last value lazySet in same thread
+ */
+ public void testGetLazySet() {
+ AtomicBoolean ai = new AtomicBoolean(true);
+ assertTrue(ai.get());
+ ai.lazySet(false);
+ assertFalse(ai.get());
+ ai.lazySet(true);
+ assertTrue(ai.get());
}
/**
@@ -52,48 +63,44 @@ public class AtomicBooleanTest extends JSR166TestCase {
public void testCompareAndSet() {
AtomicBoolean ai = new AtomicBoolean(true);
assertTrue(ai.compareAndSet(true,false));
- assertEquals(false,ai.get());
+ assertFalse(ai.get());
assertTrue(ai.compareAndSet(false,false));
- assertEquals(false,ai.get());
+ assertFalse(ai.get());
assertFalse(ai.compareAndSet(true,false));
- assertFalse((ai.get()));
+ assertFalse(ai.get());
assertTrue(ai.compareAndSet(false,true));
- assertEquals(true,ai.get());
+ assertTrue(ai.get());
}
/**
* compareAndSet in one thread enables another waiting for value
* to succeed
*/
- public void testCompareAndSetInMultipleThreads() {
+ public void testCompareAndSetInMultipleThreads() throws Exception {
final AtomicBoolean ai = new AtomicBoolean(true);
- Thread t = new Thread(new Runnable() {
- public void run() {
- while(!ai.compareAndSet(false, true)) Thread.yield();
- }});
- try {
- t.start();
- assertTrue(ai.compareAndSet(true, false));
- t.join(LONG_DELAY_MS);
- assertFalse(t.isAlive());
- }
- catch(Exception e) {
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ while (!ai.compareAndSet(false, true)) Thread.yield();
+ }});
+
+ t.start();
+ assertTrue(ai.compareAndSet(true, false));
+ t.join(LONG_DELAY_MS);
+ assertFalse(t.isAlive());
}
/**
* repeated weakCompareAndSet succeeds in changing value when equal
- * to expected
+ * to expected
*/
public void testWeakCompareAndSet() {
AtomicBoolean ai = new AtomicBoolean(true);
- while(!ai.weakCompareAndSet(true,false));
- assertEquals(false,ai.get());
- while(!ai.weakCompareAndSet(false,false));
- assertEquals(false,ai.get());
- while(!ai.weakCompareAndSet(false,true));
- assertEquals(true,ai.get());
+ while (!ai.weakCompareAndSet(true,false));
+ assertFalse(ai.get());
+ while (!ai.weakCompareAndSet(false,false));
+ assertFalse(ai.get());
+ while (!ai.weakCompareAndSet(false,true));
+ assertTrue(ai.get());
}
/**
@@ -104,37 +111,32 @@ public class AtomicBooleanTest extends JSR166TestCase {
assertEquals(true,ai.getAndSet(false));
assertEquals(false,ai.getAndSet(false));
assertEquals(false,ai.getAndSet(true));
- assertEquals(true,ai.get());
+ assertTrue(ai.get());
}
/**
* a deserialized serialized atomic holds same value
*/
- public void testSerialization() {
+ public void testSerialization() throws Exception {
AtomicBoolean l = new AtomicBoolean();
- try {
- l.set(true);
- ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
- ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
- out.writeObject(l);
- out.close();
-
- ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
- ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
- AtomicBoolean r = (AtomicBoolean) in.readObject();
- assertEquals(l.get(), r.get());
- } catch(Exception e){
- e.printStackTrace();
- unexpectedException();
- }
+ l.set(true);
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(l);
+ out.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ AtomicBoolean r = (AtomicBoolean) in.readObject();
+ assertEquals(l.get(), r.get());
}
/**
* toString returns current value.
- */
+ */
public void testToString() {
- AtomicBoolean ai = new AtomicBoolean();
+ AtomicBoolean ai = new AtomicBoolean();
assertEquals(ai.toString(), Boolean.toString(false));
ai.set(true);
assertEquals(ai.toString(), Boolean.toString(true));
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicIntegerArrayTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicIntegerArrayTest.java
index d8afe4e..838296d 100644
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicIntegerArrayTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicIntegerArrayTest.java
@@ -2,11 +2,11 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.concurrent.atomic.*;
@@ -24,7 +24,7 @@ public class AtomicIntegerArrayTest extends JSR166TestCase {
*/
public void testConstructor() {
AtomicIntegerArray ai = new AtomicIntegerArray(SIZE);
- for (int i = 0; i < SIZE; ++i)
+ for (int i = 0; i < SIZE; ++i)
assertEquals(0,ai.get(i));
}
@@ -35,10 +35,8 @@ public class AtomicIntegerArrayTest extends JSR166TestCase {
try {
int[] a = null;
AtomicIntegerArray ai = new AtomicIntegerArray(a);
- } catch (NullPointerException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ shouldThrow();
+ } catch (NullPointerException success) {}
}
/**
@@ -48,30 +46,34 @@ public class AtomicIntegerArrayTest extends JSR166TestCase {
int[] a = { 17, 3, -42, 99, -7};
AtomicIntegerArray ai = new AtomicIntegerArray(a);
assertEquals(a.length, ai.length());
- for (int i = 0; i < a.length; ++i)
+ for (int i = 0; i < a.length; ++i)
assertEquals(a[i], ai.get(i));
}
/**
* get and set for out of bound indices throw IndexOutOfBoundsException
*/
- public void testIndexing(){
+ public void testIndexing() {
AtomicIntegerArray ai = new AtomicIntegerArray(SIZE);
try {
ai.get(SIZE);
- } catch(IndexOutOfBoundsException success){
+ shouldThrow();
+ } catch (IndexOutOfBoundsException success) {
}
try {
ai.get(-1);
- } catch(IndexOutOfBoundsException success){
+ shouldThrow();
+ } catch (IndexOutOfBoundsException success) {
}
try {
ai.set(SIZE, 0);
- } catch(IndexOutOfBoundsException success){
+ shouldThrow();
+ } catch (IndexOutOfBoundsException success) {
}
try {
ai.set(-1, 0);
- } catch(IndexOutOfBoundsException success){
+ shouldThrow();
+ } catch (IndexOutOfBoundsException success) {
}
}
@@ -79,7 +81,7 @@ public class AtomicIntegerArrayTest extends JSR166TestCase {
* get returns the last value set at index
*/
public void testGetSet() {
- AtomicIntegerArray ai = new AtomicIntegerArray(SIZE);
+ AtomicIntegerArray ai = new AtomicIntegerArray(SIZE);
for (int i = 0; i < SIZE; ++i) {
ai.set(i, 1);
assertEquals(1,ai.get(i));
@@ -91,17 +93,32 @@ public class AtomicIntegerArrayTest extends JSR166TestCase {
}
/**
+ * get returns the last value lazySet at index by same thread
+ */
+ public void testGetLazySet() {
+ AtomicIntegerArray ai = new AtomicIntegerArray(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ ai.lazySet(i, 1);
+ assertEquals(1,ai.get(i));
+ ai.lazySet(i, 2);
+ assertEquals(2,ai.get(i));
+ ai.lazySet(i, -3);
+ assertEquals(-3,ai.get(i));
+ }
+ }
+
+ /**
* compareAndSet succeeds in changing value if equal to expected else fails
*/
public void testCompareAndSet() {
- AtomicIntegerArray ai = new AtomicIntegerArray(SIZE);
+ AtomicIntegerArray ai = new AtomicIntegerArray(SIZE);
for (int i = 0; i < SIZE; ++i) {
ai.set(i, 1);
assertTrue(ai.compareAndSet(i, 1,2));
assertTrue(ai.compareAndSet(i, 2,-4));
assertEquals(-4,ai.get(i));
assertFalse(ai.compareAndSet(i, -5,7));
- assertFalse((7 == ai.get(i)));
+ assertEquals(-4,ai.get(i));
assertTrue(ai.compareAndSet(i, -4,7));
assertEquals(7,ai.get(i));
}
@@ -111,37 +128,34 @@ public class AtomicIntegerArrayTest extends JSR166TestCase {
* compareAndSet in one thread enables another waiting for value
* to succeed
*/
- public void testCompareAndSetInMultipleThreads() {
+ public void testCompareAndSetInMultipleThreads() throws Exception {
final AtomicIntegerArray a = new AtomicIntegerArray(1);
a.set(0, 1);
- Thread t = new Thread(new Runnable() {
- public void run() {
- while(!a.compareAndSet(0, 2, 3)) Thread.yield();
- }});
- try {
- t.start();
- assertTrue(a.compareAndSet(0, 1, 2));
- t.join(LONG_DELAY_MS);
- assertFalse(t.isAlive());
- assertEquals(a.get(0), 3);
- }
- catch(Exception e) {
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ while (!a.compareAndSet(0, 2, 3))
+ Thread.yield();
+ }});
+
+ t.start();
+ assertTrue(a.compareAndSet(0, 1, 2));
+ t.join(LONG_DELAY_MS);
+ assertFalse(t.isAlive());
+ assertEquals(a.get(0), 3);
}
/**
* repeated weakCompareAndSet succeeds in changing value when equal
- * to expected
+ * to expected
*/
public void testWeakCompareAndSet() {
- AtomicIntegerArray ai = new AtomicIntegerArray(SIZE);
+ AtomicIntegerArray ai = new AtomicIntegerArray(SIZE);
for (int i = 0; i < SIZE; ++i) {
ai.set(i, 1);
- while(!ai.weakCompareAndSet(i, 1,2));
- while(!ai.weakCompareAndSet(i, 2,-4));
+ while (!ai.weakCompareAndSet(i, 1,2));
+ while (!ai.weakCompareAndSet(i, 2,-4));
assertEquals(-4,ai.get(i));
- while(!ai.weakCompareAndSet(i, -4,7));
+ while (!ai.weakCompareAndSet(i, -4,7));
assertEquals(7,ai.get(i));
}
}
@@ -150,7 +164,7 @@ public class AtomicIntegerArrayTest extends JSR166TestCase {
* getAndSet returns previous value and sets to given value at given index
*/
public void testGetAndSet() {
- AtomicIntegerArray ai = new AtomicIntegerArray(SIZE);
+ AtomicIntegerArray ai = new AtomicIntegerArray(SIZE);
for (int i = 0; i < SIZE; ++i) {
ai.set(i, 1);
assertEquals(1,ai.getAndSet(i,0));
@@ -163,7 +177,7 @@ public class AtomicIntegerArrayTest extends JSR166TestCase {
* getAndAdd returns previous value and adds given value
*/
public void testGetAndAdd() {
- AtomicIntegerArray ai = new AtomicIntegerArray(SIZE);
+ AtomicIntegerArray ai = new AtomicIntegerArray(SIZE);
for (int i = 0; i < SIZE; ++i) {
ai.set(i, 1);
assertEquals(1,ai.getAndAdd(i,2));
@@ -177,7 +191,7 @@ public class AtomicIntegerArrayTest extends JSR166TestCase {
* getAndDecrement returns previous value and decrements
*/
public void testGetAndDecrement() {
- AtomicIntegerArray ai = new AtomicIntegerArray(SIZE);
+ AtomicIntegerArray ai = new AtomicIntegerArray(SIZE);
for (int i = 0; i < SIZE; ++i) {
ai.set(i, 1);
assertEquals(1,ai.getAndDecrement(i));
@@ -190,7 +204,7 @@ public class AtomicIntegerArrayTest extends JSR166TestCase {
* getAndIncrement returns previous value and increments
*/
public void testGetAndIncrement() {
- AtomicIntegerArray ai = new AtomicIntegerArray(SIZE);
+ AtomicIntegerArray ai = new AtomicIntegerArray(SIZE);
for (int i = 0; i < SIZE; ++i) {
ai.set(i, 1);
assertEquals(1,ai.getAndIncrement(i));
@@ -207,7 +221,7 @@ public class AtomicIntegerArrayTest extends JSR166TestCase {
* addAndGet adds given value to current, and returns current value
*/
public void testAddAndGet() {
- AtomicIntegerArray ai = new AtomicIntegerArray(SIZE);
+ AtomicIntegerArray ai = new AtomicIntegerArray(SIZE);
for (int i = 0; i < SIZE; ++i) {
ai.set(i, 1);
assertEquals(3,ai.addAndGet(i,2));
@@ -221,7 +235,7 @@ public class AtomicIntegerArrayTest extends JSR166TestCase {
* decrementAndGet decrements and returns current value
*/
public void testDecrementAndGet() {
- AtomicIntegerArray ai = new AtomicIntegerArray(SIZE);
+ AtomicIntegerArray ai = new AtomicIntegerArray(SIZE);
for (int i = 0; i < SIZE; ++i) {
ai.set(i, 1);
assertEquals(0,ai.decrementAndGet(i));
@@ -235,7 +249,7 @@ public class AtomicIntegerArrayTest extends JSR166TestCase {
* incrementAndGet increments and returns current value
*/
public void testIncrementAndGet() {
- AtomicIntegerArray ai = new AtomicIntegerArray(SIZE);
+ AtomicIntegerArray ai = new AtomicIntegerArray(SIZE);
for (int i = 0; i < SIZE; ++i) {
ai.set(i, 1);
assertEquals(2,ai.incrementAndGet(i));
@@ -249,7 +263,7 @@ public class AtomicIntegerArrayTest extends JSR166TestCase {
}
static final int COUNTDOWN = 100000;
-
+
class Counter implements Runnable {
final AtomicIntegerArray ai;
volatile int counts;
@@ -276,57 +290,47 @@ public class AtomicIntegerArrayTest extends JSR166TestCase {
* Multiple threads using same array of counters successfully
* update a number of times equal to total count
*/
- public void testCountingInMultipleThreads() {
- try {
- final AtomicIntegerArray ai = new AtomicIntegerArray(SIZE);
- for (int i = 0; i < SIZE; ++i)
- ai.set(i, COUNTDOWN);
- Counter c1 = new Counter(ai);
- Counter c2 = new Counter(ai);
- Thread t1 = new Thread(c1);
- Thread t2 = new Thread(c2);
- t1.start();
- t2.start();
- t1.join();
- t2.join();
- assertEquals(c1.counts+c2.counts, SIZE * COUNTDOWN);
- }
- catch(InterruptedException ie) {
- unexpectedException();
- }
+ public void testCountingInMultipleThreads() throws InterruptedException {
+ final AtomicIntegerArray ai = new AtomicIntegerArray(SIZE);
+ for (int i = 0; i < SIZE; ++i)
+ ai.set(i, COUNTDOWN);
+ Counter c1 = new Counter(ai);
+ Counter c2 = new Counter(ai);
+ Thread t1 = new Thread(c1);
+ Thread t2 = new Thread(c2);
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
+ assertEquals(c1.counts+c2.counts, SIZE * COUNTDOWN);
}
/**
* a deserialized serialized array holds same values
*/
- public void testSerialization() {
- AtomicIntegerArray l = new AtomicIntegerArray(SIZE);
- for (int i = 0; i < SIZE; ++i)
+ public void testSerialization() throws Exception {
+ AtomicIntegerArray l = new AtomicIntegerArray(SIZE);
+ for (int i = 0; i < SIZE; ++i)
l.set(i, -i);
- try {
- ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
- ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
- out.writeObject(l);
- out.close();
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(l);
+ out.close();
- ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
- ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
- AtomicIntegerArray r = (AtomicIntegerArray) in.readObject();
- for (int i = 0; i < SIZE; ++i) {
- assertEquals(l.get(i), r.get(i));
- }
- } catch(Exception e){
- e.printStackTrace();
- unexpectedException();
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ AtomicIntegerArray r = (AtomicIntegerArray) in.readObject();
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(l.get(i), r.get(i));
}
}
/**
* toString returns current value.
- */
+ */
public void testToString() {
int[] a = { 17, 3, -42, 99, -7};
AtomicIntegerArray ai = new AtomicIntegerArray(a);
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicIntegerFieldUpdaterTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicIntegerFieldUpdaterTest.java
index a4ec85e..383e30b 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicIntegerFieldUpdaterTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicIntegerFieldUpdaterTest.java
@@ -2,11 +2,11 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import java.util.concurrent.atomic.*;
import junit.framework.*;
@@ -24,60 +24,36 @@ public class AtomicIntegerFieldUpdaterTest extends JSR166TestCase {
* Construction with non-existent field throws RuntimeException
*/
public void testConstructor() {
- try{
- AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest>
+ try {
+ AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest>
a = AtomicIntegerFieldUpdater.newUpdater
(AtomicIntegerFieldUpdaterTest.class, "y");
shouldThrow();
- }
- catch (RuntimeException rt) {}
+ } catch (RuntimeException success) {}
}
/**
* construction with field not of given type throws RuntimeException
*/
public void testConstructor2() {
- try{
- AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest>
+ try {
+ AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest>
a = AtomicIntegerFieldUpdater.newUpdater
(AtomicIntegerFieldUpdaterTest.class, "z");
shouldThrow();
- }
- catch (RuntimeException rt) {}
+ } catch (RuntimeException success) {}
}
/**
* construction with non-volatile field throws RuntimeException
*/
public void testConstructor3() {
- try{
- AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest>
+ try {
+ AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest>
a = AtomicIntegerFieldUpdater.newUpdater
(AtomicIntegerFieldUpdaterTest.class, "w");
shouldThrow();
- }
- catch (RuntimeException rt) {}
- }
-
- static class Base {
- protected volatile int f = 0;
- }
- static class Sub1 extends Base {
- AtomicIntegerFieldUpdater<Base> fUpdater
- = AtomicIntegerFieldUpdater.newUpdater(Base.class, "f");
- }
- static class Sub2 extends Base {}
-
- public void testProtectedFieldOnAnotherSubtype() {
- Sub1 sub1 = new Sub1();
- Sub2 sub2 = new Sub2();
-
- sub1.fUpdater.set(sub1, 1);
- try {
- sub1.fUpdater.set(sub2, 2);
- shouldThrow();
- }
- catch (RuntimeException rt) {}
+ } catch (RuntimeException success) {}
}
/**
@@ -96,7 +72,24 @@ public class AtomicIntegerFieldUpdaterTest extends JSR166TestCase {
assertEquals(2,a.get(this));
a.set(this,-3);
assertEquals(-3,a.get(this));
-
+ }
+
+ /**
+ * get returns the last value lazySet by same thread
+ */
+ public void testGetLazySet() {
+ AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
+ try {
+ a = AtomicIntegerFieldUpdater.newUpdater(AtomicIntegerFieldUpdaterTest.class, "x");
+ } catch (RuntimeException ok) {
+ return;
+ }
+ x = 1;
+ assertEquals(1,a.get(this));
+ a.lazySet(this,2);
+ assertEquals(2,a.get(this));
+ a.lazySet(this,-3);
+ assertEquals(-3,a.get(this));
}
/**
@@ -114,7 +107,7 @@ public class AtomicIntegerFieldUpdaterTest extends JSR166TestCase {
assertTrue(a.compareAndSet(this,2,-4));
assertEquals(-4,a.get(this));
assertFalse(a.compareAndSet(this,-5,7));
- assertFalse((7 == a.get(this)));
+ assertEquals(-4,a.get(this));
assertTrue(a.compareAndSet(this,-4,7));
assertEquals(7,a.get(this));
}
@@ -124,7 +117,7 @@ public class AtomicIntegerFieldUpdaterTest extends JSR166TestCase {
* compareAndSet in one thread enables another waiting for value
* to succeed
*/
- public void testCompareAndSetInMultipleThreads() {
+ public void testCompareAndSetInMultipleThreads() throws Exception {
x = 1;
final AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest>a;
try {
@@ -133,25 +126,22 @@ public class AtomicIntegerFieldUpdaterTest extends JSR166TestCase {
return;
}
- Thread t = new Thread(new Runnable() {
- public void run() {
- while(!a.compareAndSet(AtomicIntegerFieldUpdaterTest.this, 2, 3)) Thread.yield();
- }});
- try {
- t.start();
- assertTrue(a.compareAndSet(this, 1, 2));
- t.join(LONG_DELAY_MS);
- assertFalse(t.isAlive());
- assertEquals(a.get(this), 3);
- }
- catch(Exception e) {
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ while (!a.compareAndSet(AtomicIntegerFieldUpdaterTest.this, 2, 3))
+ Thread.yield();
+ }});
+
+ t.start();
+ assertTrue(a.compareAndSet(this, 1, 2));
+ t.join(LONG_DELAY_MS);
+ assertFalse(t.isAlive());
+ assertEquals(a.get(this), 3);
}
/**
* repeated weakCompareAndSet succeeds in changing value when equal
- * to expected
+ * to expected
*/
public void testWeakCompareAndSet() {
AtomicIntegerFieldUpdater<AtomicIntegerFieldUpdaterTest> a;
@@ -161,10 +151,10 @@ public class AtomicIntegerFieldUpdaterTest extends JSR166TestCase {
return;
}
x = 1;
- while(!a.weakCompareAndSet(this,1,2));
- while(!a.weakCompareAndSet(this,2,-4));
+ while (!a.weakCompareAndSet(this,1,2));
+ while (!a.weakCompareAndSet(this,2,-4));
assertEquals(-4,a.get(this));
- while(!a.weakCompareAndSet(this,-4,7));
+ while (!a.weakCompareAndSet(this,-4,7));
assertEquals(7,a.get(this));
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicIntegerTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicIntegerTest.java
index a6b2a17..a2f3b4b 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicIntegerTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicIntegerTest.java
@@ -2,11 +2,11 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.concurrent.atomic.*;
@@ -17,10 +17,14 @@ public class AtomicIntegerTest extends JSR166TestCase {
return new TestSuite(AtomicIntegerTest.class);
}
+ final int[] VALUES = {
+ Integer.MIN_VALUE, -1, 0, 1, 42, Integer.MAX_VALUE,
+ };
+
/**
* constructor initializes to given value
*/
- public void testConstructor(){
+ public void testConstructor() {
AtomicInteger ai = new AtomicInteger(1);
assertEquals(1,ai.get());
}
@@ -28,7 +32,7 @@ public class AtomicIntegerTest extends JSR166TestCase {
/**
* default constructed initializes to zero
*/
- public void testConstructor2(){
+ public void testConstructor2() {
AtomicInteger ai = new AtomicInteger();
assertEquals(0,ai.get());
}
@@ -36,26 +40,37 @@ public class AtomicIntegerTest extends JSR166TestCase {
/**
* get returns the last value set
*/
- public void testGetSet(){
+ public void testGetSet() {
AtomicInteger ai = new AtomicInteger(1);
assertEquals(1,ai.get());
ai.set(2);
assertEquals(2,ai.get());
ai.set(-3);
assertEquals(-3,ai.get());
-
+ }
+
+ /**
+ * get returns the last value lazySet in same thread
+ */
+ public void testGetLazySet() {
+ AtomicInteger ai = new AtomicInteger(1);
+ assertEquals(1,ai.get());
+ ai.lazySet(2);
+ assertEquals(2,ai.get());
+ ai.lazySet(-3);
+ assertEquals(-3,ai.get());
}
/**
* compareAndSet succeeds in changing value if equal to expected else fails
*/
- public void testCompareAndSet(){
+ public void testCompareAndSet() {
AtomicInteger ai = new AtomicInteger(1);
assertTrue(ai.compareAndSet(1,2));
assertTrue(ai.compareAndSet(2,-4));
assertEquals(-4,ai.get());
assertFalse(ai.compareAndSet(-5,7));
- assertFalse((7 == ai.get()));
+ assertEquals(-4,ai.get());
assertTrue(ai.compareAndSet(-4,7));
assertEquals(7,ai.get());
}
@@ -64,41 +79,38 @@ public class AtomicIntegerTest extends JSR166TestCase {
* compareAndSet in one thread enables another waiting for value
* to succeed
*/
- public void testCompareAndSetInMultipleThreads() {
+ public void testCompareAndSetInMultipleThreads() throws Exception {
final AtomicInteger ai = new AtomicInteger(1);
- Thread t = new Thread(new Runnable() {
- public void run() {
- while(!ai.compareAndSet(2, 3)) Thread.yield();
- }});
- try {
- t.start();
- assertTrue(ai.compareAndSet(1, 2));
- t.join(LONG_DELAY_MS);
- assertFalse(t.isAlive());
- assertEquals(ai.get(), 3);
- }
- catch(Exception e) {
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ while (!ai.compareAndSet(2, 3))
+ Thread.yield();
+ }});
+
+ t.start();
+ assertTrue(ai.compareAndSet(1, 2));
+ t.join(LONG_DELAY_MS);
+ assertFalse(t.isAlive());
+ assertEquals(ai.get(), 3);
}
/**
* repeated weakCompareAndSet succeeds in changing value when equal
- * to expected
+ * to expected
*/
- public void testWeakCompareAndSet(){
+ public void testWeakCompareAndSet() {
AtomicInteger ai = new AtomicInteger(1);
- while(!ai.weakCompareAndSet(1,2));
- while(!ai.weakCompareAndSet(2,-4));
+ while (!ai.weakCompareAndSet(1,2));
+ while (!ai.weakCompareAndSet(2,-4));
assertEquals(-4,ai.get());
- while(!ai.weakCompareAndSet(-4,7));
+ while (!ai.weakCompareAndSet(-4,7));
assertEquals(7,ai.get());
}
/**
* getAndSet returns previous value and sets to given value
*/
- public void testGetAndSet(){
+ public void testGetAndSet() {
AtomicInteger ai = new AtomicInteger(1);
assertEquals(1,ai.getAndSet(0));
assertEquals(0,ai.getAndSet(-10));
@@ -108,7 +120,7 @@ public class AtomicIntegerTest extends JSR166TestCase {
/**
* getAndAdd returns previous value and adds given value
*/
- public void testGetAndAdd(){
+ public void testGetAndAdd() {
AtomicInteger ai = new AtomicInteger(1);
assertEquals(1,ai.getAndAdd(2));
assertEquals(3,ai.get());
@@ -119,7 +131,7 @@ public class AtomicIntegerTest extends JSR166TestCase {
/**
* getAndDecrement returns previous value and decrements
*/
- public void testGetAndDecrement(){
+ public void testGetAndDecrement() {
AtomicInteger ai = new AtomicInteger(1);
assertEquals(1,ai.getAndDecrement());
assertEquals(0,ai.getAndDecrement());
@@ -129,7 +141,7 @@ public class AtomicIntegerTest extends JSR166TestCase {
/**
* getAndIncrement returns previous value and increments
*/
- public void testGetAndIncrement(){
+ public void testGetAndIncrement() {
AtomicInteger ai = new AtomicInteger(1);
assertEquals(1,ai.getAndIncrement());
assertEquals(2,ai.get());
@@ -143,7 +155,7 @@ public class AtomicIntegerTest extends JSR166TestCase {
/**
* addAndGet adds given value to current, and returns current value
*/
- public void testAddAndGet(){
+ public void testAddAndGet() {
AtomicInteger ai = new AtomicInteger(1);
assertEquals(3,ai.addAndGet(2));
assertEquals(3,ai.get());
@@ -154,7 +166,7 @@ public class AtomicIntegerTest extends JSR166TestCase {
/**
* decrementAndGet decrements and returns current value
*/
- public void testDecrementAndGet(){
+ public void testDecrementAndGet() {
AtomicInteger ai = new AtomicInteger(1);
assertEquals(0,ai.decrementAndGet());
assertEquals(-1,ai.decrementAndGet());
@@ -165,7 +177,7 @@ public class AtomicIntegerTest extends JSR166TestCase {
/**
* incrementAndGet increments and returns current value
*/
- public void testIncrementAndGet(){
+ public void testIncrementAndGet() {
AtomicInteger ai = new AtomicInteger(1);
assertEquals(2,ai.incrementAndGet());
assertEquals(2,ai.get());
@@ -179,81 +191,79 @@ public class AtomicIntegerTest extends JSR166TestCase {
/**
* a deserialized serialized atomic holds same value
*/
- public void testSerialization() {
+ public void testSerialization() throws Exception {
AtomicInteger l = new AtomicInteger();
- try {
- l.set(22);
- ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
- ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
- out.writeObject(l);
- out.close();
+ l.set(22);
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(l);
+ out.close();
- ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
- ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
- AtomicInteger r = (AtomicInteger) in.readObject();
- assertEquals(l.get(), r.get());
- } catch(Exception e){
- unexpectedException();
- }
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ AtomicInteger r = (AtomicInteger) in.readObject();
+ assertEquals(l.get(), r.get());
}
/**
* toString returns current value.
- */
+ */
public void testToString() {
AtomicInteger ai = new AtomicInteger();
- for (int i = -12; i < 6; ++i) {
- ai.set(i);
- assertEquals(ai.toString(), Integer.toString(i));
+ assertEquals("0", ai.toString());
+ for (int x : VALUES) {
+ ai.set(x);
+ assertEquals(ai.toString(), Integer.toString(x));
}
}
/**
* intValue returns current value.
- */
+ */
public void testIntValue() {
AtomicInteger ai = new AtomicInteger();
- for (int i = -12; i < 6; ++i) {
- ai.set(i);
- assertEquals(i, ai.intValue());
+ assertEquals(0, ai.intValue());
+ for (int x : VALUES) {
+ ai.set(x);
+ assertEquals(x, ai.intValue());
}
}
-
/**
* longValue returns current value.
- */
+ */
public void testLongValue() {
AtomicInteger ai = new AtomicInteger();
- for (int i = -12; i < 6; ++i) {
- ai.set(i);
- assertEquals((long)i, ai.longValue());
+ assertEquals(0L, ai.longValue());
+ for (int x : VALUES) {
+ ai.set(x);
+ assertEquals((long)x, ai.longValue());
}
}
/**
* floatValue returns current value.
- */
+ */
public void testFloatValue() {
AtomicInteger ai = new AtomicInteger();
- for (int i = -12; i < 6; ++i) {
- ai.set(i);
- assertEquals((float)i, ai.floatValue());
+ assertEquals(0.0f, ai.floatValue());
+ for (int x : VALUES) {
+ ai.set(x);
+ assertEquals((float)x, ai.floatValue());
}
}
/**
* doubleValue returns current value.
- */
+ */
public void testDoubleValue() {
AtomicInteger ai = new AtomicInteger();
- for (int i = -12; i < 6; ++i) {
- ai.set(i);
- assertEquals((double)i, ai.doubleValue());
+ assertEquals(0.0d, ai.doubleValue());
+ for (int x : VALUES) {
+ ai.set(x);
+ assertEquals((double)x, ai.doubleValue());
}
}
-
-
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicLongArrayTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicLongArrayTest.java
index 262d273..88e0984 100644
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicLongArrayTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicLongArrayTest.java
@@ -2,11 +2,11 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.concurrent.atomic.*;
@@ -21,9 +21,9 @@ public class AtomicLongArrayTest extends JSR166TestCase {
/**
* constructor creates array of given size with all elements zero
*/
- public void testConstructor(){
+ public void testConstructor() {
AtomicLongArray ai = new AtomicLongArray(SIZE);
- for (int i = 0; i < SIZE; ++i)
+ for (int i = 0; i < SIZE; ++i)
assertEquals(0,ai.get(i));
}
@@ -34,10 +34,8 @@ public class AtomicLongArrayTest extends JSR166TestCase {
try {
long[] a = null;
AtomicLongArray ai = new AtomicLongArray(a);
- } catch (NullPointerException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ shouldThrow();
+ } catch (NullPointerException success) {}
}
/**
@@ -47,38 +45,42 @@ public class AtomicLongArrayTest extends JSR166TestCase {
long[] a = { 17L, 3L, -42L, 99L, -7L};
AtomicLongArray ai = new AtomicLongArray(a);
assertEquals(a.length, ai.length());
- for (int i = 0; i < a.length; ++i)
+ for (int i = 0; i < a.length; ++i)
assertEquals(a[i], ai.get(i));
}
/**
* get and set for out of bound indices throw IndexOutOfBoundsException
*/
- public void testIndexing(){
+ public void testIndexing() {
AtomicLongArray ai = new AtomicLongArray(SIZE);
try {
ai.get(SIZE);
- } catch(IndexOutOfBoundsException success){
+ shouldThrow();
+ } catch (IndexOutOfBoundsException success) {
}
try {
ai.get(-1);
- } catch(IndexOutOfBoundsException success){
+ shouldThrow();
+ } catch (IndexOutOfBoundsException success) {
}
try {
ai.set(SIZE, 0);
- } catch(IndexOutOfBoundsException success){
+ shouldThrow();
+ } catch (IndexOutOfBoundsException success) {
}
try {
ai.set(-1, 0);
- } catch(IndexOutOfBoundsException success){
+ shouldThrow();
+ } catch (IndexOutOfBoundsException success) {
}
}
/**
* get returns the last value set at index
*/
- public void testGetSet(){
- AtomicLongArray ai = new AtomicLongArray(SIZE);
+ public void testGetSet() {
+ AtomicLongArray ai = new AtomicLongArray(SIZE);
for (int i = 0; i < SIZE; ++i) {
ai.set(i, 1);
assertEquals(1,ai.get(i));
@@ -90,17 +92,32 @@ public class AtomicLongArrayTest extends JSR166TestCase {
}
/**
+ * get returns the last value lazySet at index by same thread
+ */
+ public void testGetLazySet() {
+ AtomicLongArray ai = new AtomicLongArray(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ ai.lazySet(i, 1);
+ assertEquals(1,ai.get(i));
+ ai.lazySet(i, 2);
+ assertEquals(2,ai.get(i));
+ ai.lazySet(i, -3);
+ assertEquals(-3,ai.get(i));
+ }
+ }
+
+ /**
* compareAndSet succeeds in changing value if equal to expected else fails
*/
- public void testCompareAndSet(){
- AtomicLongArray ai = new AtomicLongArray(SIZE);
+ public void testCompareAndSet() {
+ AtomicLongArray ai = new AtomicLongArray(SIZE);
for (int i = 0; i < SIZE; ++i) {
ai.set(i, 1);
assertTrue(ai.compareAndSet(i, 1,2));
assertTrue(ai.compareAndSet(i, 2,-4));
assertEquals(-4,ai.get(i));
assertFalse(ai.compareAndSet(i, -5,7));
- assertFalse((7 == ai.get(i)));
+ assertEquals(-4,ai.get(i));
assertTrue(ai.compareAndSet(i, -4,7));
assertEquals(7,ai.get(i));
}
@@ -110,37 +127,34 @@ public class AtomicLongArrayTest extends JSR166TestCase {
* compareAndSet in one thread enables another waiting for value
* to succeed
*/
- public void testCompareAndSetInMultipleThreads() {
+ public void testCompareAndSetInMultipleThreads() throws InterruptedException {
final AtomicLongArray a = new AtomicLongArray(1);
a.set(0, 1);
- Thread t = new Thread(new Runnable() {
- public void run() {
- while(!a.compareAndSet(0, 2, 3)) Thread.yield();
- }});
- try {
- t.start();
- assertTrue(a.compareAndSet(0, 1, 2));
- t.join(LONG_DELAY_MS);
- assertFalse(t.isAlive());
- assertEquals(a.get(0), 3);
- }
- catch(Exception e) {
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ while (!a.compareAndSet(0, 2, 3))
+ Thread.yield();
+ }});
+
+ t.start();
+ assertTrue(a.compareAndSet(0, 1, 2));
+ t.join(LONG_DELAY_MS);
+ assertFalse(t.isAlive());
+ assertEquals(a.get(0), 3);
}
/**
* repeated weakCompareAndSet succeeds in changing value when equal
- * to expected
+ * to expected
*/
- public void testWeakCompareAndSet(){
- AtomicLongArray ai = new AtomicLongArray(SIZE);
+ public void testWeakCompareAndSet() {
+ AtomicLongArray ai = new AtomicLongArray(SIZE);
for (int i = 0; i < SIZE; ++i) {
ai.set(i, 1);
- while(!ai.weakCompareAndSet(i, 1,2));
- while(!ai.weakCompareAndSet(i, 2,-4));
+ while (!ai.weakCompareAndSet(i, 1,2));
+ while (!ai.weakCompareAndSet(i, 2,-4));
assertEquals(-4,ai.get(i));
- while(!ai.weakCompareAndSet(i, -4,7));
+ while (!ai.weakCompareAndSet(i, -4,7));
assertEquals(7,ai.get(i));
}
}
@@ -148,8 +162,8 @@ public class AtomicLongArrayTest extends JSR166TestCase {
/**
* getAndSet returns previous value and sets to given value at given index
*/
- public void testGetAndSet(){
- AtomicLongArray ai = new AtomicLongArray(SIZE);
+ public void testGetAndSet() {
+ AtomicLongArray ai = new AtomicLongArray(SIZE);
for (int i = 0; i < SIZE; ++i) {
ai.set(i, 1);
assertEquals(1,ai.getAndSet(i,0));
@@ -161,8 +175,8 @@ public class AtomicLongArrayTest extends JSR166TestCase {
/**
* getAndAdd returns previous value and adds given value
*/
- public void testGetAndAdd(){
- AtomicLongArray ai = new AtomicLongArray(SIZE);
+ public void testGetAndAdd() {
+ AtomicLongArray ai = new AtomicLongArray(SIZE);
for (int i = 0; i < SIZE; ++i) {
ai.set(i, 1);
assertEquals(1,ai.getAndAdd(i,2));
@@ -175,8 +189,8 @@ public class AtomicLongArrayTest extends JSR166TestCase {
/**
* getAndDecrement returns previous value and decrements
*/
- public void testGetAndDecrement(){
- AtomicLongArray ai = new AtomicLongArray(SIZE);
+ public void testGetAndDecrement() {
+ AtomicLongArray ai = new AtomicLongArray(SIZE);
for (int i = 0; i < SIZE; ++i) {
ai.set(i, 1);
assertEquals(1,ai.getAndDecrement(i));
@@ -188,8 +202,8 @@ public class AtomicLongArrayTest extends JSR166TestCase {
/**
* getAndIncrement returns previous value and increments
*/
- public void testGetAndIncrement(){
- AtomicLongArray ai = new AtomicLongArray(SIZE);
+ public void testGetAndIncrement() {
+ AtomicLongArray ai = new AtomicLongArray(SIZE);
for (int i = 0; i < SIZE; ++i) {
ai.set(i, 1);
assertEquals(1,ai.getAndIncrement(i));
@@ -206,7 +220,7 @@ public class AtomicLongArrayTest extends JSR166TestCase {
* addAndGet adds given value to current, and returns current value
*/
public void testAddAndGet() {
- AtomicLongArray ai = new AtomicLongArray(SIZE);
+ AtomicLongArray ai = new AtomicLongArray(SIZE);
for (int i = 0; i < SIZE; ++i) {
ai.set(i, 1);
assertEquals(3,ai.addAndGet(i,2));
@@ -219,8 +233,8 @@ public class AtomicLongArrayTest extends JSR166TestCase {
/**
* decrementAndGet decrements and returns current value
*/
- public void testDecrementAndGet(){
- AtomicLongArray ai = new AtomicLongArray(SIZE);
+ public void testDecrementAndGet() {
+ AtomicLongArray ai = new AtomicLongArray(SIZE);
for (int i = 0; i < SIZE; ++i) {
ai.set(i, 1);
assertEquals(0,ai.decrementAndGet(i));
@@ -234,7 +248,7 @@ public class AtomicLongArrayTest extends JSR166TestCase {
* incrementAndGet increments and returns current value
*/
public void testIncrementAndGet() {
- AtomicLongArray ai = new AtomicLongArray(SIZE);
+ AtomicLongArray ai = new AtomicLongArray(SIZE);
for (int i = 0; i < SIZE; ++i) {
ai.set(i, 1);
assertEquals(2,ai.incrementAndGet(i));
@@ -248,7 +262,7 @@ public class AtomicLongArrayTest extends JSR166TestCase {
}
static final long COUNTDOWN = 100000;
-
+
class Counter implements Runnable {
final AtomicLongArray ai;
volatile long counts;
@@ -275,54 +289,45 @@ public class AtomicLongArrayTest extends JSR166TestCase {
* Multiple threads using same array of counters successfully
* update a number of times equal to total count
*/
- public void testCountingInMultipleThreads() {
- try {
- final AtomicLongArray ai = new AtomicLongArray(SIZE);
- for (int i = 0; i < SIZE; ++i)
- ai.set(i, COUNTDOWN);
- Counter c1 = new Counter(ai);
- Counter c2 = new Counter(ai);
- Thread t1 = new Thread(c1);
- Thread t2 = new Thread(c2);
- t1.start();
- t2.start();
- t1.join();
- t2.join();
- assertEquals(c1.counts+c2.counts, SIZE * COUNTDOWN);
- }
- catch(InterruptedException ie) {
- unexpectedException();
- }
+ public void testCountingInMultipleThreads() throws InterruptedException {
+ final AtomicLongArray ai = new AtomicLongArray(SIZE);
+ for (int i = 0; i < SIZE; ++i)
+ ai.set(i, COUNTDOWN);
+ Counter c1 = new Counter(ai);
+ Counter c2 = new Counter(ai);
+ Thread t1 = new Thread(c1);
+ Thread t2 = new Thread(c2);
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
+ assertEquals(c1.counts+c2.counts, SIZE * COUNTDOWN);
}
/**
* a deserialized serialized array holds same values
*/
- public void testSerialization() {
- AtomicLongArray l = new AtomicLongArray(SIZE);
- for (int i = 0; i < SIZE; ++i)
+ public void testSerialization() throws Exception {
+ AtomicLongArray l = new AtomicLongArray(SIZE);
+ for (int i = 0; i < SIZE; ++i)
l.set(i, -i);
- try {
- ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
- ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
- out.writeObject(l);
- out.close();
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(l);
+ out.close();
- ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
- ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
- AtomicLongArray r = (AtomicLongArray) in.readObject();
- for (int i = 0; i < SIZE; ++i) {
- assertEquals(l.get(i), r.get(i));
- }
- } catch(Exception e){
- unexpectedException();
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ AtomicLongArray r = (AtomicLongArray) in.readObject();
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(l.get(i), r.get(i));
}
}
/**
* toString returns current value.
- */
+ */
public void testToString() {
long[] a = { 17, 3, -42, 99, -7};
AtomicLongArray ai = new AtomicLongArray(a);
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicLongFieldUpdaterTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicLongFieldUpdaterTest.java
index bac25dc..491baf4 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicLongFieldUpdaterTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicLongFieldUpdaterTest.java
@@ -2,11 +2,11 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import java.util.concurrent.atomic.*;
import junit.framework.*;
@@ -24,68 +24,61 @@ public class AtomicLongFieldUpdaterTest extends JSR166TestCase {
/**
* Construction with non-existent field throws RuntimeException
*/
- public void testConstructor(){
- try{
+ public void testConstructor() {
+ try {
AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest>
a = AtomicLongFieldUpdater.newUpdater
(AtomicLongFieldUpdaterTest.class, "y");
shouldThrow();
- }
- catch (RuntimeException rt) {}
+ } catch (RuntimeException success) {}
}
/**
* construction with field not of given type throws RuntimeException
*/
- public void testConstructor2(){
- try{
+ public void testConstructor2() {
+ try {
AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest>
a = AtomicLongFieldUpdater.newUpdater
(AtomicLongFieldUpdaterTest.class, "z");
shouldThrow();
- }
- catch (RuntimeException rt) {}
+ } catch (RuntimeException success) {}
}
/**
* construction with non-volatile field throws RuntimeException
*/
- public void testConstructor3(){
- try{
+ public void testConstructor3() {
+ try {
AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest>
a = AtomicLongFieldUpdater.newUpdater
(AtomicLongFieldUpdaterTest.class, "w");
shouldThrow();
- }
-
- catch (RuntimeException rt) {}
+ } catch (RuntimeException success) {}
}
- static class Base {
- protected volatile long f = 0;
- }
- static class Sub1 extends Base {
- AtomicLongFieldUpdater<Base> fUpdater
- = AtomicLongFieldUpdater.newUpdater(Base.class, "f");
- }
- static class Sub2 extends Base {}
-
- public void testProtectedFieldOnAnotherSubtype() {
- Sub1 sub1 = new Sub1();
- Sub2 sub2 = new Sub2();
-
- sub1.fUpdater.set(sub1, 1);
+ /**
+ * get returns the last value set or assigned
+ */
+ public void testGetSet() {
+ AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
try {
- sub1.fUpdater.set(sub2, 2);
- shouldThrow();
+ a = AtomicLongFieldUpdater.newUpdater(AtomicLongFieldUpdaterTest.class, "x");
+ } catch (RuntimeException ok) {
+ return;
}
- catch (RuntimeException rt) {}
+ x = 1;
+ assertEquals(1,a.get(this));
+ a.set(this,2);
+ assertEquals(2,a.get(this));
+ a.set(this,-3);
+ assertEquals(-3,a.get(this));
}
/**
- * get returns the last value set or assigned
+ * get returns the last value lazySet by same thread
*/
- public void testGetSet(){
+ public void testGetLazySet() {
AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
try {
a = AtomicLongFieldUpdater.newUpdater(AtomicLongFieldUpdaterTest.class, "x");
@@ -93,17 +86,18 @@ public class AtomicLongFieldUpdaterTest extends JSR166TestCase {
return;
}
x = 1;
- assertEquals(1,a.get(this));
- a.set(this,2);
- assertEquals(2,a.get(this));
- a.set(this,-3);
- assertEquals(-3,a.get(this));
-
+ assertEquals(1,a.get(this));
+ a.lazySet(this,2);
+ assertEquals(2,a.get(this));
+ a.lazySet(this,-3);
+ assertEquals(-3,a.get(this));
}
+
+
/**
* compareAndSet succeeds in changing value if equal to expected else fails
*/
- public void testCompareAndSet(){
+ public void testCompareAndSet() {
AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
try {
a = AtomicLongFieldUpdater.newUpdater(AtomicLongFieldUpdaterTest.class, "x");
@@ -115,7 +109,7 @@ public class AtomicLongFieldUpdaterTest extends JSR166TestCase {
assertTrue(a.compareAndSet(this,2,-4));
assertEquals(-4,a.get(this));
assertFalse(a.compareAndSet(this,-5,7));
- assertFalse((7 == a.get(this)));
+ assertEquals(-4,a.get(this));
assertTrue(a.compareAndSet(this,-4,7));
assertEquals(7,a.get(this));
}
@@ -125,7 +119,7 @@ public class AtomicLongFieldUpdaterTest extends JSR166TestCase {
* compareAndSet in one thread enables another waiting for value
* to succeed
*/
- public void testCompareAndSetInMultipleThreads() {
+ public void testCompareAndSetInMultipleThreads() throws Exception {
x = 1;
final AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest>a;
try {
@@ -134,27 +128,24 @@ public class AtomicLongFieldUpdaterTest extends JSR166TestCase {
return;
}
- Thread t = new Thread(new Runnable() {
- public void run() {
- while(!a.compareAndSet(AtomicLongFieldUpdaterTest.this, 2, 3)) Thread.yield();
- }});
- try {
- t.start();
- assertTrue(a.compareAndSet(this, 1, 2));
- t.join(LONG_DELAY_MS);
- assertFalse(t.isAlive());
- assertEquals(a.get(this), 3);
- }
- catch(Exception e) {
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ while (!a.compareAndSet(AtomicLongFieldUpdaterTest.this, 2, 3))
+ Thread.yield();
+ }});
+
+ t.start();
+ assertTrue(a.compareAndSet(this, 1, 2));
+ t.join(LONG_DELAY_MS);
+ assertFalse(t.isAlive());
+ assertEquals(a.get(this), 3);
}
/**
* repeated weakCompareAndSet succeeds in changing value when equal
* to expected
*/
- public void testWeakCompareAndSet(){
+ public void testWeakCompareAndSet() {
AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
try {
a = AtomicLongFieldUpdater.newUpdater(AtomicLongFieldUpdaterTest.class, "x");
@@ -162,17 +153,17 @@ public class AtomicLongFieldUpdaterTest extends JSR166TestCase {
return;
}
x = 1;
- while(!a.weakCompareAndSet(this,1,2));
- while(!a.weakCompareAndSet(this,2,-4));
+ while (!a.weakCompareAndSet(this,1,2));
+ while (!a.weakCompareAndSet(this,2,-4));
assertEquals(-4,a.get(this));
- while(!a.weakCompareAndSet(this,-4,7));
+ while (!a.weakCompareAndSet(this,-4,7));
assertEquals(7,a.get(this));
}
/**
* getAndSet returns previous value and sets to given value
*/
- public void testGetAndSet(){
+ public void testGetAndSet() {
AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
try {
a = AtomicLongFieldUpdater.newUpdater(AtomicLongFieldUpdaterTest.class, "x");
@@ -188,7 +179,7 @@ public class AtomicLongFieldUpdaterTest extends JSR166TestCase {
/**
* getAndAdd returns previous value and adds given value
*/
- public void testGetAndAdd(){
+ public void testGetAndAdd() {
AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
try {
a = AtomicLongFieldUpdater.newUpdater(AtomicLongFieldUpdaterTest.class, "x");
@@ -205,7 +196,7 @@ public class AtomicLongFieldUpdaterTest extends JSR166TestCase {
/**
* getAndDecrement returns previous value and decrements
*/
- public void testGetAndDecrement(){
+ public void testGetAndDecrement() {
AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
try {
a = AtomicLongFieldUpdater.newUpdater(AtomicLongFieldUpdaterTest.class, "x");
@@ -221,7 +212,7 @@ public class AtomicLongFieldUpdaterTest extends JSR166TestCase {
/**
* getAndIncrement returns previous value and increments
*/
- public void testGetAndIncrement(){
+ public void testGetAndIncrement() {
AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
try {
a = AtomicLongFieldUpdater.newUpdater(AtomicLongFieldUpdaterTest.class, "x");
@@ -241,7 +232,7 @@ public class AtomicLongFieldUpdaterTest extends JSR166TestCase {
/**
* addAndGet adds given value to current, and returns current value
*/
- public void testAddAndGet(){
+ public void testAddAndGet() {
AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
try {
a = AtomicLongFieldUpdater.newUpdater(AtomicLongFieldUpdaterTest.class, "x");
@@ -258,7 +249,7 @@ public class AtomicLongFieldUpdaterTest extends JSR166TestCase {
/**
* decrementAndGet decrements and returns current value
*/
- public void testDecrementAndGet(){
+ public void testDecrementAndGet() {
AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
try {
a = AtomicLongFieldUpdater.newUpdater(AtomicLongFieldUpdaterTest.class, "x");
@@ -275,7 +266,7 @@ public class AtomicLongFieldUpdaterTest extends JSR166TestCase {
/**
* incrementAndGet increments and returns current value
*/
- public void testIncrementAndGet(){
+ public void testIncrementAndGet() {
AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
try {
a = AtomicLongFieldUpdater.newUpdater(AtomicLongFieldUpdaterTest.class, "x");
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicLongTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicLongTest.java
index f4805bf..e73e86e 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicLongTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicLongTest.java
@@ -2,11 +2,11 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.concurrent.atomic.*;
@@ -17,10 +17,16 @@ public class AtomicLongTest extends JSR166TestCase {
return new TestSuite(AtomicLongTest.class);
}
+ final long[] VALUES = {
+ Long.MIN_VALUE,
+ Integer.MIN_VALUE, -1, 0, 1, 42, Integer.MAX_VALUE,
+ Long.MAX_VALUE,
+ };
+
/**
* constructor initializes to given value
*/
- public void testConstructor(){
+ public void testConstructor() {
AtomicLong ai = new AtomicLong(1);
assertEquals(1,ai.get());
}
@@ -28,7 +34,7 @@ public class AtomicLongTest extends JSR166TestCase {
/**
* default constructed initializes to zero
*/
- public void testConstructor2(){
+ public void testConstructor2() {
AtomicLong ai = new AtomicLong();
assertEquals(0,ai.get());
}
@@ -36,26 +42,37 @@ public class AtomicLongTest extends JSR166TestCase {
/**
* get returns the last value set
*/
- public void testGetSet(){
+ public void testGetSet() {
AtomicLong ai = new AtomicLong(1);
assertEquals(1,ai.get());
ai.set(2);
assertEquals(2,ai.get());
ai.set(-3);
assertEquals(-3,ai.get());
-
+ }
+
+ /**
+ * get returns the last value lazySet in same thread
+ */
+ public void testGetLazySet() {
+ AtomicLong ai = new AtomicLong(1);
+ assertEquals(1,ai.get());
+ ai.lazySet(2);
+ assertEquals(2,ai.get());
+ ai.lazySet(-3);
+ assertEquals(-3,ai.get());
}
/**
* compareAndSet succeeds in changing value if equal to expected else fails
*/
- public void testCompareAndSet(){
+ public void testCompareAndSet() {
AtomicLong ai = new AtomicLong(1);
assertTrue(ai.compareAndSet(1,2));
assertTrue(ai.compareAndSet(2,-4));
assertEquals(-4,ai.get());
assertFalse(ai.compareAndSet(-5,7));
- assertFalse((7 == ai.get()));
+ assertEquals(-4,ai.get());
assertTrue(ai.compareAndSet(-4,7));
assertEquals(7,ai.get());
}
@@ -64,41 +81,38 @@ public class AtomicLongTest extends JSR166TestCase {
* compareAndSet in one thread enables another waiting for value
* to succeed
*/
- public void testCompareAndSetInMultipleThreads() {
+ public void testCompareAndSetInMultipleThreads() throws Exception {
final AtomicLong ai = new AtomicLong(1);
- Thread t = new Thread(new Runnable() {
- public void run() {
- while(!ai.compareAndSet(2, 3)) Thread.yield();
- }});
- try {
- t.start();
- assertTrue(ai.compareAndSet(1, 2));
- t.join(LONG_DELAY_MS);
- assertFalse(t.isAlive());
- assertEquals(ai.get(), 3);
- }
- catch(Exception e) {
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ while (!ai.compareAndSet(2, 3))
+ Thread.yield();
+ }});
+
+ t.start();
+ assertTrue(ai.compareAndSet(1, 2));
+ t.join(LONG_DELAY_MS);
+ assertFalse(t.isAlive());
+ assertEquals(ai.get(), 3);
}
/**
* repeated weakCompareAndSet succeeds in changing value when equal
- * to expected
+ * to expected
*/
- public void testWeakCompareAndSet(){
+ public void testWeakCompareAndSet() {
AtomicLong ai = new AtomicLong(1);
- while(!ai.weakCompareAndSet(1,2));
- while(!ai.weakCompareAndSet(2,-4));
+ while (!ai.weakCompareAndSet(1,2));
+ while (!ai.weakCompareAndSet(2,-4));
assertEquals(-4,ai.get());
- while(!ai.weakCompareAndSet(-4,7));
+ while (!ai.weakCompareAndSet(-4,7));
assertEquals(7,ai.get());
}
/**
* getAndSet returns previous value and sets to given value
*/
- public void testGetAndSet(){
+ public void testGetAndSet() {
AtomicLong ai = new AtomicLong(1);
assertEquals(1,ai.getAndSet(0));
assertEquals(0,ai.getAndSet(-10));
@@ -108,7 +122,7 @@ public class AtomicLongTest extends JSR166TestCase {
/**
* getAndAdd returns previous value and adds given value
*/
- public void testGetAndAdd(){
+ public void testGetAndAdd() {
AtomicLong ai = new AtomicLong(1);
assertEquals(1,ai.getAndAdd(2));
assertEquals(3,ai.get());
@@ -119,7 +133,7 @@ public class AtomicLongTest extends JSR166TestCase {
/**
* getAndDecrement returns previous value and decrements
*/
- public void testGetAndDecrement(){
+ public void testGetAndDecrement() {
AtomicLong ai = new AtomicLong(1);
assertEquals(1,ai.getAndDecrement());
assertEquals(0,ai.getAndDecrement());
@@ -129,7 +143,7 @@ public class AtomicLongTest extends JSR166TestCase {
/**
* getAndIncrement returns previous value and increments
*/
- public void testGetAndIncrement(){
+ public void testGetAndIncrement() {
AtomicLong ai = new AtomicLong(1);
assertEquals(1,ai.getAndIncrement());
assertEquals(2,ai.get());
@@ -143,7 +157,7 @@ public class AtomicLongTest extends JSR166TestCase {
/**
* addAndGet adds given value to current, and returns current value
*/
- public void testAddAndGet(){
+ public void testAddAndGet() {
AtomicLong ai = new AtomicLong(1);
assertEquals(3,ai.addAndGet(2));
assertEquals(3,ai.get());
@@ -154,7 +168,7 @@ public class AtomicLongTest extends JSR166TestCase {
/**
* decrementAndGet decrements and returns current value
*/
- public void testDecrementAndGet(){
+ public void testDecrementAndGet() {
AtomicLong ai = new AtomicLong(1);
assertEquals(0,ai.decrementAndGet());
assertEquals(-1,ai.decrementAndGet());
@@ -165,7 +179,7 @@ public class AtomicLongTest extends JSR166TestCase {
/**
* incrementAndGet increments and returns current value
*/
- public void testIncrementAndGet(){
+ public void testIncrementAndGet() {
AtomicLong ai = new AtomicLong(1);
assertEquals(2,ai.incrementAndGet());
assertEquals(2,ai.get());
@@ -179,68 +193,79 @@ public class AtomicLongTest extends JSR166TestCase {
/**
* a deserialized serialized atomic holds same value
*/
- public void testSerialization() {
+ public void testSerialization() throws Exception {
AtomicLong l = new AtomicLong();
- try {
- l.set(-22);
- ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
- ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
- out.writeObject(l);
- out.close();
-
- ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
- ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
- AtomicLong r = (AtomicLong) in.readObject();
- assertEquals(l.get(), r.get());
- } catch(Exception e){
- unexpectedException();
- }
+ l.set(-22);
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(l);
+ out.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ AtomicLong r = (AtomicLong) in.readObject();
+ assertEquals(l.get(), r.get());
}
/**
* toString returns current value.
- */
+ */
public void testToString() {
AtomicLong ai = new AtomicLong();
- for (long i = -12; i < 6; ++i) {
+ assertEquals("0", ai.toString());
+ for (long i : VALUES) {
ai.set(i);
assertEquals(ai.toString(), Long.toString(i));
}
}
/**
+ * intValue returns current value.
+ */
+ public void testIntValue() {
+ AtomicLong ai = new AtomicLong();
+ assertEquals(0, ai.intValue());
+ for (long x : VALUES) {
+ ai.set(x);
+ assertEquals((int)x, ai.intValue());
+ }
+ }
+
+ /**
* longValue returns current value.
- */
+ */
public void testLongValue() {
AtomicLong ai = new AtomicLong();
- for (int i = -12; i < 6; ++i) {
- ai.set(i);
- assertEquals((long)i, ai.longValue());
+ assertEquals(0L, ai.longValue());
+ for (long x : VALUES) {
+ ai.set(x);
+ assertEquals((long)x, ai.longValue());
}
}
/**
* floatValue returns current value.
- */
+ */
public void testFloatValue() {
AtomicLong ai = new AtomicLong();
- for (int i = -12; i < 6; ++i) {
- ai.set(i);
- assertEquals((float)i, ai.floatValue());
+ assertEquals(0.0f, ai.floatValue());
+ for (long x : VALUES) {
+ ai.set(x);
+ assertEquals((float)x, ai.floatValue());
}
}
/**
* doubleValue returns current value.
- */
+ */
public void testDoubleValue() {
AtomicLong ai = new AtomicLong();
- for (int i = -12; i < 6; ++i) {
- ai.set(i);
- assertEquals((double)i, ai.doubleValue());
+ assertEquals(0.0d, ai.doubleValue());
+ for (long x : VALUES) {
+ ai.set(x);
+ assertEquals((double)x, ai.doubleValue());
}
}
-
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicMarkableReferenceTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicMarkableReferenceTest.java
index 7857dde..72a2337 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicMarkableReferenceTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicMarkableReferenceTest.java
@@ -2,65 +2,64 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.concurrent.atomic.*;
-public class AtomicMarkableReferenceTest extends JSR166TestCase{
+public class AtomicMarkableReferenceTest extends JSR166TestCase {
public static Test suite() {
return new TestSuite(AtomicMarkableReferenceTest.class);
}
-
+
/**
* constructor initializes to given reference and mark
*/
- public void testConstructor(){
+ public void testConstructor() {
AtomicMarkableReference ai = new AtomicMarkableReference(one, false);
- assertEquals(one,ai.getReference());
+ assertSame(one,ai.getReference());
assertFalse(ai.isMarked());
AtomicMarkableReference a2 = new AtomicMarkableReference(null, true);
assertNull(a2.getReference());
assertTrue(a2.isMarked());
-
}
/**
* get returns the last values of reference and mark set
*/
- public void testGetSet(){
+ public void testGetSet() {
boolean[] mark = new boolean[1];
AtomicMarkableReference ai = new AtomicMarkableReference(one, false);
- assertEquals(one,ai.getReference());
+ assertSame(one,ai.getReference());
assertFalse(ai.isMarked());
- assertEquals(one, ai.get(mark));
+ assertSame(one, ai.get(mark));
assertFalse(mark[0]);
ai.set(two, false);
- assertEquals(two,ai.getReference());
+ assertSame(two,ai.getReference());
assertFalse(ai.isMarked());
- assertEquals(two, ai.get(mark));
+ assertSame(two, ai.get(mark));
assertFalse(mark[0]);
ai.set(one, true);
- assertEquals(one,ai.getReference());
+ assertSame(one,ai.getReference());
assertTrue(ai.isMarked());
- assertEquals(one, ai.get(mark));
+ assertSame(one, ai.get(mark));
assertTrue(mark[0]);
}
/**
* attemptMark succeeds in single thread
*/
- public void testAttemptMark(){
+ public void testAttemptMark() {
boolean[] mark = new boolean[1];
AtomicMarkableReference ai = new AtomicMarkableReference(one, false);
assertFalse(ai.isMarked());
assertTrue(ai.attemptMark(one, true));
assertTrue(ai.isMarked());
- assertEquals(one, ai.get(mark));
+ assertSame(one, ai.get(mark));
assertTrue(mark[0]);
}
@@ -68,23 +67,23 @@ public class AtomicMarkableReferenceTest extends JSR166TestCase{
* compareAndSet succeeds in changing values if equal to expected reference
* and mark else fails
*/
- public void testCompareAndSet(){
+ public void testCompareAndSet() {
boolean[] mark = new boolean[1];
AtomicMarkableReference ai = new AtomicMarkableReference(one, false);
- assertEquals(one, ai.get(mark));
+ assertSame(one, ai.get(mark));
assertFalse(ai.isMarked());
assertFalse(mark[0]);
assertTrue(ai.compareAndSet(one, two, false, false));
- assertEquals(two, ai.get(mark));
+ assertSame(two, ai.get(mark));
assertFalse(mark[0]);
assertTrue(ai.compareAndSet(two, m3, false, true));
- assertEquals(m3, ai.get(mark));
+ assertSame(m3, ai.get(mark));
assertTrue(mark[0]);
assertFalse(ai.compareAndSet(two, m3, true, true));
- assertEquals(m3, ai.get(mark));
+ assertSame(m3, ai.get(mark));
assertTrue(mark[0]);
}
@@ -92,65 +91,59 @@ public class AtomicMarkableReferenceTest extends JSR166TestCase{
* compareAndSet in one thread enables another waiting for reference value
* to succeed
*/
- public void testCompareAndSetInMultipleThreads() {
+ public void testCompareAndSetInMultipleThreads() throws Exception {
final AtomicMarkableReference ai = new AtomicMarkableReference(one, false);
- Thread t = new Thread(new Runnable() {
- public void run() {
- while(!ai.compareAndSet(two, three, false, false)) Thread.yield();
- }});
- try {
- t.start();
- assertTrue(ai.compareAndSet(one, two, false, false));
- t.join(LONG_DELAY_MS);
- assertFalse(t.isAlive());
- assertEquals(ai.getReference(), three);
- assertFalse(ai.isMarked());
- }
- catch(Exception e) {
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ while (!ai.compareAndSet(two, three, false, false))
+ Thread.yield();
+ }});
+
+ t.start();
+ assertTrue(ai.compareAndSet(one, two, false, false));
+ t.join(LONG_DELAY_MS);
+ assertFalse(t.isAlive());
+ assertSame(ai.getReference(), three);
+ assertFalse(ai.isMarked());
}
/**
* compareAndSet in one thread enables another waiting for mark value
* to succeed
*/
- public void testCompareAndSetInMultipleThreads2() {
+ public void testCompareAndSetInMultipleThreads2() throws Exception {
final AtomicMarkableReference ai = new AtomicMarkableReference(one, false);
- Thread t = new Thread(new Runnable() {
- public void run() {
- while(!ai.compareAndSet(one, one, true, false)) Thread.yield();
- }});
- try {
- t.start();
- assertTrue(ai.compareAndSet(one, one, false, true));
- t.join(LONG_DELAY_MS);
- assertFalse(t.isAlive());
- assertEquals(ai.getReference(), one);
- assertFalse(ai.isMarked());
- }
- catch(Exception e) {
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ while (!ai.compareAndSet(one, one, true, false))
+ Thread.yield();
+ }});
+
+ t.start();
+ assertTrue(ai.compareAndSet(one, one, false, true));
+ t.join(LONG_DELAY_MS);
+ assertFalse(t.isAlive());
+ assertSame(ai.getReference(), one);
+ assertFalse(ai.isMarked());
}
/**
* repeated weakCompareAndSet succeeds in changing values when equal
- * to expected
+ * to expected
*/
- public void testWeakCompareAndSet(){
+ public void testWeakCompareAndSet() {
boolean[] mark = new boolean[1];
AtomicMarkableReference ai = new AtomicMarkableReference(one, false);
- assertEquals(one, ai.get(mark));
+ assertSame(one, ai.get(mark));
assertFalse(ai.isMarked());
assertFalse(mark[0]);
- while(!ai.weakCompareAndSet(one, two, false, false));
- assertEquals(two, ai.get(mark));
+ while (!ai.weakCompareAndSet(one, two, false, false));
+ assertSame(two, ai.get(mark));
assertFalse(mark[0]);
- while(!ai.weakCompareAndSet(two, m3, false, true));
- assertEquals(m3, ai.get(mark));
+ while (!ai.weakCompareAndSet(two, m3, false, true));
+ assertSame(m3, ai.get(mark));
assertTrue(mark[0]);
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicReferenceArrayTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicReferenceArrayTest.java
index 81248cc..25f8474 100644
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicReferenceArrayTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicReferenceArrayTest.java
@@ -2,19 +2,18 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.concurrent.atomic.*;
import java.io.*;
import java.util.*;
-public class AtomicReferenceArrayTest extends JSR166TestCase
-{
+public class AtomicReferenceArrayTest extends JSR166TestCase {
public static Test suite() {
return new TestSuite(AtomicReferenceArrayTest.class);
}
@@ -22,7 +21,7 @@ public class AtomicReferenceArrayTest extends JSR166TestCase
/**
* constructor creates array of given size with all elements null
*/
- public void testConstructor(){
+ public void testConstructor() {
AtomicReferenceArray<Integer> ai = new AtomicReferenceArray<Integer>(SIZE);
for (int i = 0; i < SIZE; ++i) {
assertNull(ai.get(i));
@@ -36,10 +35,8 @@ public class AtomicReferenceArrayTest extends JSR166TestCase
try {
Integer[] a = null;
AtomicReferenceArray<Integer> ai = new AtomicReferenceArray<Integer>(a);
- } catch (NullPointerException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ shouldThrow();
+ } catch (NullPointerException success) {}
}
/**
@@ -49,7 +46,7 @@ public class AtomicReferenceArrayTest extends JSR166TestCase
Integer[] a = { two, one, three, four, seven};
AtomicReferenceArray<Integer> ai = new AtomicReferenceArray<Integer>(a);
assertEquals(a.length, ai.length());
- for (int i = 0; i < a.length; ++i)
+ for (int i = 0; i < a.length; ++i)
assertEquals(a[i], ai.get(i));
}
@@ -57,55 +54,74 @@ public class AtomicReferenceArrayTest extends JSR166TestCase
/**
* get and set for out of bound indices throw IndexOutOfBoundsException
*/
- public void testIndexing(){
+ public void testIndexing() {
AtomicReferenceArray<Integer> ai = new AtomicReferenceArray<Integer>(SIZE);
try {
ai.get(SIZE);
- } catch(IndexOutOfBoundsException success){
+ shouldThrow();
+ } catch (IndexOutOfBoundsException success) {
}
try {
ai.get(-1);
- } catch(IndexOutOfBoundsException success){
+ shouldThrow();
+ } catch (IndexOutOfBoundsException success) {
}
try {
ai.set(SIZE, null);
- } catch(IndexOutOfBoundsException success){
+ shouldThrow();
+ } catch (IndexOutOfBoundsException success) {
}
try {
ai.set(-1, null);
- } catch(IndexOutOfBoundsException success){
+ shouldThrow();
+ } catch (IndexOutOfBoundsException success) {
}
}
/**
* get returns the last value set at index
*/
- public void testGetSet(){
- AtomicReferenceArray ai = new AtomicReferenceArray(SIZE);
+ public void testGetSet() {
+ AtomicReferenceArray ai = new AtomicReferenceArray(SIZE);
for (int i = 0; i < SIZE; ++i) {
ai.set(i, one);
- assertEquals(one,ai.get(i));
+ assertSame(one,ai.get(i));
ai.set(i, two);
- assertEquals(two,ai.get(i));
+ assertSame(two,ai.get(i));
ai.set(i, m3);
- assertEquals(m3,ai.get(i));
+ assertSame(m3,ai.get(i));
+ }
+ }
+
+ /**
+ * get returns the last value lazySet at index by same thread
+ */
+ public void testGetLazySet() {
+ AtomicReferenceArray ai = new AtomicReferenceArray(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ ai.lazySet(i, one);
+ assertSame(one,ai.get(i));
+ ai.lazySet(i, two);
+ assertSame(two,ai.get(i));
+ ai.lazySet(i, m3);
+ assertSame(m3,ai.get(i));
}
}
/**
* compareAndSet succeeds in changing value if equal to expected else fails
*/
- public void testCompareAndSet(){
- AtomicReferenceArray ai = new AtomicReferenceArray(SIZE);
+ public void testCompareAndSet() {
+ AtomicReferenceArray ai = new AtomicReferenceArray(SIZE);
for (int i = 0; i < SIZE; ++i) {
ai.set(i, one);
assertTrue(ai.compareAndSet(i, one,two));
assertTrue(ai.compareAndSet(i, two,m4));
- assertEquals(m4,ai.get(i));
+ assertSame(m4,ai.get(i));
assertFalse(ai.compareAndSet(i, m5,seven));
- assertFalse((seven.equals(ai.get(i))));
+ assertSame(m4,ai.get(i));
assertTrue(ai.compareAndSet(i, m4,seven));
- assertEquals(seven,ai.get(i));
+ assertSame(seven,ai.get(i));
}
}
@@ -113,85 +129,78 @@ public class AtomicReferenceArrayTest extends JSR166TestCase
* compareAndSet in one thread enables another waiting for value
* to succeed
*/
- public void testCompareAndSetInMultipleThreads() {
+ public void testCompareAndSetInMultipleThreads() throws InterruptedException {
final AtomicReferenceArray a = new AtomicReferenceArray(1);
a.set(0, one);
- Thread t = new Thread(new Runnable() {
- public void run() {
- while(!a.compareAndSet(0, two, three)) Thread.yield();
- }});
- try {
- t.start();
- assertTrue(a.compareAndSet(0, one, two));
- t.join(LONG_DELAY_MS);
- assertFalse(t.isAlive());
- assertEquals(a.get(0), three);
- }
- catch(Exception e) {
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ while (!a.compareAndSet(0, two, three))
+ Thread.yield();
+ }});
+
+ t.start();
+ assertTrue(a.compareAndSet(0, one, two));
+ t.join(LONG_DELAY_MS);
+ assertFalse(t.isAlive());
+ assertSame(a.get(0), three);
}
/**
* repeated weakCompareAndSet succeeds in changing value when equal
- * to expected
+ * to expected
*/
- public void testWeakCompareAndSet(){
- AtomicReferenceArray ai = new AtomicReferenceArray(SIZE);
+ public void testWeakCompareAndSet() {
+ AtomicReferenceArray ai = new AtomicReferenceArray(SIZE);
for (int i = 0; i < SIZE; ++i) {
ai.set(i, one);
- while(!ai.weakCompareAndSet(i, one,two));
- while(!ai.weakCompareAndSet(i, two,m4));
- assertEquals(m4,ai.get(i));
- while(!ai.weakCompareAndSet(i, m4,seven));
- assertEquals(seven,ai.get(i));
+ while (!ai.weakCompareAndSet(i, one,two));
+ while (!ai.weakCompareAndSet(i, two,m4));
+ assertSame(m4,ai.get(i));
+ while (!ai.weakCompareAndSet(i, m4,seven));
+ assertSame(seven,ai.get(i));
}
}
/**
* getAndSet returns previous value and sets to given value at given index
*/
- public void testGetAndSet(){
- AtomicReferenceArray ai = new AtomicReferenceArray(SIZE);
+ public void testGetAndSet() {
+ AtomicReferenceArray ai = new AtomicReferenceArray(SIZE);
for (int i = 0; i < SIZE; ++i) {
ai.set(i, one);
- assertEquals(one,ai.getAndSet(i,zero));
- assertEquals(0,ai.getAndSet(i,m10));
- assertEquals(m10,ai.getAndSet(i,one));
+ assertSame(one,ai.getAndSet(i,zero));
+ assertSame(zero,ai.getAndSet(i,m10));
+ assertSame(m10,ai.getAndSet(i,one));
}
}
/**
* a deserialized serialized array holds same values
*/
- public void testSerialization() {
- AtomicReferenceArray l = new AtomicReferenceArray(SIZE);
+ public void testSerialization() throws Exception {
+ AtomicReferenceArray l = new AtomicReferenceArray(SIZE);
for (int i = 0; i < SIZE; ++i) {
l.set(i, new Integer(-i));
}
- try {
- ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
- ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
- out.writeObject(l);
- out.close();
-
- ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
- ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
- AtomicReferenceArray r = (AtomicReferenceArray) in.readObject();
- assertEquals(l.length(), r.length());
- for (int i = 0; i < SIZE; ++i) {
- assertEquals(r.get(i), l.get(i));
- }
- } catch(Exception e){
- unexpectedException();
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(l);
+ out.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ AtomicReferenceArray r = (AtomicReferenceArray) in.readObject();
+ assertEquals(l.length(), r.length());
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(r.get(i), l.get(i));
}
}
/**
* toString returns current value.
- */
+ */
public void testToString() {
Integer[] a = { two, one, three, four, seven};
AtomicReferenceArray<Integer> ai = new AtomicReferenceArray<Integer>(a);
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicReferenceFieldUpdaterTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicReferenceFieldUpdaterTest.java
index 7f71781..78c321e 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicReferenceFieldUpdaterTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicReferenceFieldUpdaterTest.java
@@ -2,17 +2,17 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import java.util.concurrent.atomic.*;
import junit.framework.*;
import java.util.*;
-public class AtomicReferenceFieldUpdaterTest extends JSR166TestCase{
+public class AtomicReferenceFieldUpdaterTest extends JSR166TestCase {
volatile Integer x = null;
Object z;
Integer w;
@@ -24,68 +24,62 @@ public class AtomicReferenceFieldUpdaterTest extends JSR166TestCase{
/**
* Construction with non-existent field throws RuntimeException
*/
- public void testConstructor(){
- try{
+ public void testConstructor() {
+ try {
AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer>
a = AtomicReferenceFieldUpdater.newUpdater
(AtomicReferenceFieldUpdaterTest.class, Integer.class, "y");
shouldThrow();
- }
- catch (RuntimeException rt) {}
+ } catch (RuntimeException success) {}
}
/**
* construction with field not of given type throws RuntimeException
*/
- public void testConstructor2(){
- try{
+ public void testConstructor2() {
+ try {
AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer>
a = AtomicReferenceFieldUpdater.newUpdater
(AtomicReferenceFieldUpdaterTest.class, Integer.class, "z");
shouldThrow();
- }
- catch (RuntimeException rt) {}
+ } catch (RuntimeException success) {}
}
/**
* Constructor with non-volatile field throws exception
*/
- public void testConstructor3(){
- try{
+ public void testConstructor3() {
+ try {
AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer>
a = AtomicReferenceFieldUpdater.newUpdater
(AtomicReferenceFieldUpdaterTest.class, Integer.class, "w");
shouldThrow();
- }
- catch (RuntimeException rt) {}
+ } catch (RuntimeException success) {}
}
- static class Base {
- protected volatile Object f = null;
- }
- static class Sub1 extends Base {
- AtomicReferenceFieldUpdater<Base, Object> fUpdater
- = AtomicReferenceFieldUpdater.newUpdater(Base.class, Object.class, "f");
- }
- static class Sub2 extends Base {}
-
- public void testProtectedFieldOnAnotherSubtype() {
- Sub1 sub1 = new Sub1();
- Sub2 sub2 = new Sub2();
-
- sub1.fUpdater.set(sub1, "f");
+ /**
+ * get returns the last value set or assigned
+ */
+ public void testGetSet() {
+ AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer>a;
try {
- sub1.fUpdater.set(sub2, "g");
- shouldThrow();
+ a = AtomicReferenceFieldUpdater.newUpdater(AtomicReferenceFieldUpdaterTest.class, Integer.class, "x");
+ } catch (RuntimeException ok) {
+ return;
}
- catch (RuntimeException rt) {}
+ x = one;
+ assertSame(one,a.get(this));
+ a.set(this,two);
+ assertSame(two,a.get(this));
+ a.set(this,m3);
+ assertSame(m3,a.get(this));
}
/**
- * get returns the last value set or assigned
+ * get returns the last value lazySet by same thread
*/
- public void testGetSet(){
+ public void testGetLazySet() {
AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer>a;
try {
a = AtomicReferenceFieldUpdater.newUpdater(AtomicReferenceFieldUpdaterTest.class, Integer.class, "x");
@@ -93,16 +87,17 @@ public class AtomicReferenceFieldUpdaterTest extends JSR166TestCase{
return;
}
x = one;
- assertEquals(one,a.get(this));
- a.set(this,two);
- assertEquals(two,a.get(this));
- a.set(this,m3);
- assertEquals(m3,a.get(this));
+ assertSame(one,a.get(this));
+ a.lazySet(this,two);
+ assertSame(two,a.get(this));
+ a.lazySet(this,m3);
+ assertSame(m3,a.get(this));
}
+
/**
* compareAndSet succeeds in changing value if equal to expected else fails
*/
- public void testCompareAndSet(){
+ public void testCompareAndSet() {
AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer>a;
try {
a = AtomicReferenceFieldUpdater.newUpdater(AtomicReferenceFieldUpdaterTest.class, Integer.class, "x");
@@ -112,18 +107,18 @@ public class AtomicReferenceFieldUpdaterTest extends JSR166TestCase{
x = one;
assertTrue(a.compareAndSet(this,one,two));
assertTrue(a.compareAndSet(this,two,m4));
- assertEquals(m4,a.get(this));
+ assertSame(m4,a.get(this));
assertFalse(a.compareAndSet(this,m5,seven));
- assertFalse((seven == a.get(this)));
+ assertFalse(seven == a.get(this));
assertTrue(a.compareAndSet(this,m4,seven));
- assertEquals(seven,a.get(this));
+ assertSame(seven,a.get(this));
}
/**
* compareAndSet in one thread enables another waiting for value
* to succeed
*/
- public void testCompareAndSetInMultipleThreads() {
+ public void testCompareAndSetInMultipleThreads() throws Exception {
x = one;
final AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer>a;
try {
@@ -132,27 +127,24 @@ public class AtomicReferenceFieldUpdaterTest extends JSR166TestCase{
return;
}
- Thread t = new Thread(new Runnable() {
- public void run() {
- while(!a.compareAndSet(AtomicReferenceFieldUpdaterTest.this, two, three)) Thread.yield();
- }});
- try {
- t.start();
- assertTrue(a.compareAndSet(this, one, two));
- t.join(LONG_DELAY_MS);
- assertFalse(t.isAlive());
- assertEquals(a.get(this), three);
- }
- catch(Exception e) {
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ while (!a.compareAndSet(AtomicReferenceFieldUpdaterTest.this, two, three))
+ Thread.yield();
+ }});
+
+ t.start();
+ assertTrue(a.compareAndSet(this, one, two));
+ t.join(LONG_DELAY_MS);
+ assertFalse(t.isAlive());
+ assertSame(a.get(this), three);
}
/**
* repeated weakCompareAndSet succeeds in changing value when equal
* to expected
*/
- public void testWeakCompareAndSet(){
+ public void testWeakCompareAndSet() {
AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer>a;
try {
a = AtomicReferenceFieldUpdater.newUpdater(AtomicReferenceFieldUpdaterTest.class, Integer.class, "x");
@@ -160,17 +152,17 @@ public class AtomicReferenceFieldUpdaterTest extends JSR166TestCase{
return;
}
x = one;
- while(!a.weakCompareAndSet(this,one,two));
- while(!a.weakCompareAndSet(this,two,m4));
- assertEquals(m4,a.get(this));
- while(!a.weakCompareAndSet(this,m4,seven));
- assertEquals(seven,a.get(this));
+ while (!a.weakCompareAndSet(this,one,two));
+ while (!a.weakCompareAndSet(this,two,m4));
+ assertSame(m4,a.get(this));
+ while (!a.weakCompareAndSet(this,m4,seven));
+ assertSame(seven,a.get(this));
}
/**
* getAndSet returns previous value and sets to given value
*/
- public void testGetAndSet(){
+ public void testGetAndSet() {
AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer>a;
try {
a = AtomicReferenceFieldUpdater.newUpdater(AtomicReferenceFieldUpdaterTest.class, Integer.class, "x");
@@ -178,9 +170,9 @@ public class AtomicReferenceFieldUpdaterTest extends JSR166TestCase{
return;
}
x = one;
- assertEquals(one,a.getAndSet(this, zero));
- assertEquals(zero,a.getAndSet(this,m10));
- assertEquals(m10,a.getAndSet(this,1));
+ assertSame(one,a.getAndSet(this, zero));
+ assertSame(zero,a.getAndSet(this,m10));
+ assertSame(m10,a.getAndSet(this,1));
}
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicReferenceTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicReferenceTest.java
index bcb4701..5046ee8 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicReferenceTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicReferenceTest.java
@@ -2,11 +2,11 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.concurrent.atomic.*;
@@ -20,15 +20,15 @@ public class AtomicReferenceTest extends JSR166TestCase {
/**
* constructor initializes to given value
*/
- public void testConstructor(){
+ public void testConstructor() {
AtomicReference ai = new AtomicReference(one);
- assertEquals(one,ai.get());
+ assertSame(one,ai.get());
}
/**
* default constructed initializes to null
*/
- public void testConstructor2(){
+ public void testConstructor2() {
AtomicReference ai = new AtomicReference();
assertNull(ai.get());
}
@@ -36,105 +36,109 @@ public class AtomicReferenceTest extends JSR166TestCase {
/**
* get returns the last value set
*/
- public void testGetSet(){
+ public void testGetSet() {
AtomicReference ai = new AtomicReference(one);
- assertEquals(one,ai.get());
+ assertSame(one,ai.get());
ai.set(two);
- assertEquals(two,ai.get());
+ assertSame(two,ai.get());
ai.set(m3);
- assertEquals(m3,ai.get());
+ assertSame(m3,ai.get());
+ }
+ /**
+ * get returns the last value lazySet in same thread
+ */
+ public void testGetLazySet() {
+ AtomicReference ai = new AtomicReference(one);
+ assertSame(one,ai.get());
+ ai.lazySet(two);
+ assertSame(two,ai.get());
+ ai.lazySet(m3);
+ assertSame(m3,ai.get());
}
+
/**
* compareAndSet succeeds in changing value if equal to expected else fails
*/
- public void testCompareAndSet(){
+ public void testCompareAndSet() {
AtomicReference ai = new AtomicReference(one);
assertTrue(ai.compareAndSet(one,two));
assertTrue(ai.compareAndSet(two,m4));
- assertEquals(m4,ai.get());
+ assertSame(m4,ai.get());
assertFalse(ai.compareAndSet(m5,seven));
- assertFalse((seven.equals(ai.get())));
+ assertSame(m4,ai.get());
assertTrue(ai.compareAndSet(m4,seven));
- assertEquals(seven,ai.get());
+ assertSame(seven,ai.get());
}
/**
* compareAndSet in one thread enables another waiting for value
* to succeed
*/
- public void testCompareAndSetInMultipleThreads() {
+ public void testCompareAndSetInMultipleThreads() throws Exception {
final AtomicReference ai = new AtomicReference(one);
- Thread t = new Thread(new Runnable() {
- public void run() {
- while(!ai.compareAndSet(two, three)) Thread.yield();
- }});
- try {
- t.start();
- assertTrue(ai.compareAndSet(one, two));
- t.join(LONG_DELAY_MS);
- assertFalse(t.isAlive());
- assertEquals(ai.get(), three);
- }
- catch(Exception e) {
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ while (!ai.compareAndSet(two, three))
+ Thread.yield();
+ }});
+
+ t.start();
+ assertTrue(ai.compareAndSet(one, two));
+ t.join(LONG_DELAY_MS);
+ assertFalse(t.isAlive());
+ assertSame(ai.get(), three);
}
/**
* repeated weakCompareAndSet succeeds in changing value when equal
* to expected
*/
- public void testWeakCompareAndSet(){
+ public void testWeakCompareAndSet() {
AtomicReference ai = new AtomicReference(one);
- while(!ai.weakCompareAndSet(one,two));
- while(!ai.weakCompareAndSet(two,m4));
- assertEquals(m4,ai.get());
- while(!ai.weakCompareAndSet(m4,seven));
- assertEquals(seven,ai.get());
+ while (!ai.weakCompareAndSet(one,two));
+ while (!ai.weakCompareAndSet(two,m4));
+ assertSame(m4,ai.get());
+ while (!ai.weakCompareAndSet(m4,seven));
+ assertSame(seven,ai.get());
}
/**
* getAndSet returns previous value and sets to given value
*/
- public void testGetAndSet(){
+ public void testGetAndSet() {
AtomicReference ai = new AtomicReference(one);
- assertEquals(one,ai.getAndSet(zero));
- assertEquals(zero,ai.getAndSet(m10));
- assertEquals(m10,ai.getAndSet(one));
+ assertSame(one,ai.getAndSet(zero));
+ assertSame(zero,ai.getAndSet(m10));
+ assertSame(m10,ai.getAndSet(one));
}
/**
* a deserialized serialized atomic holds same value
*/
- public void testSerialization() {
+ public void testSerialization() throws Exception {
AtomicReference l = new AtomicReference();
- try {
- l.set(one);
- ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
- ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
- out.writeObject(l);
- out.close();
-
- ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
- ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
- AtomicReference r = (AtomicReference) in.readObject();
- assertEquals(l.get(), r.get());
- } catch(Exception e){
- unexpectedException();
- }
+ l.set(one);
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(l);
+ out.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ AtomicReference r = (AtomicReference) in.readObject();
+ assertEquals(l.get(), r.get());
}
/**
* toString returns current value.
- */
+ */
public void testToString() {
- AtomicReference<Integer> ai = new AtomicReference<Integer>(one);
+ AtomicReference<Integer> ai = new AtomicReference<Integer>(one);
assertEquals(ai.toString(), one.toString());
ai.set(two);
assertEquals(ai.toString(), two.toString());
}
}
-
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicStampedReferenceTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicStampedReferenceTest.java
index 9f4e4f7..ca9b724 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicStampedReferenceTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicStampedReferenceTest.java
@@ -2,65 +2,64 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.concurrent.atomic.*;
-public class AtomicStampedReferenceTest extends JSR166TestCase{
+public class AtomicStampedReferenceTest extends JSR166TestCase {
public static Test suite() {
return new TestSuite(AtomicStampedReferenceTest.class);
}
-
+
/**
* constructor initializes to given reference and stamp
*/
- public void testConstructor(){
+ public void testConstructor() {
AtomicStampedReference ai = new AtomicStampedReference(one, 0);
- assertEquals(one,ai.getReference());
+ assertSame(one,ai.getReference());
assertEquals(0, ai.getStamp());
AtomicStampedReference a2 = new AtomicStampedReference(null, 1);
assertNull(a2.getReference());
assertEquals(1, a2.getStamp());
-
}
/**
* get returns the last values of reference and stamp set
*/
- public void testGetSet(){
+ public void testGetSet() {
int[] mark = new int[1];
AtomicStampedReference ai = new AtomicStampedReference(one, 0);
- assertEquals(one,ai.getReference());
+ assertSame(one,ai.getReference());
assertEquals(0, ai.getStamp());
- assertEquals(one, ai.get(mark));
+ assertSame(one, ai.get(mark));
assertEquals(0, mark[0]);
ai.set(two, 0);
- assertEquals(two,ai.getReference());
+ assertSame(two,ai.getReference());
assertEquals(0, ai.getStamp());
- assertEquals(two, ai.get(mark));
+ assertSame(two, ai.get(mark));
assertEquals(0, mark[0]);
ai.set(one, 1);
- assertEquals(one,ai.getReference());
+ assertSame(one,ai.getReference());
assertEquals(1, ai.getStamp());
- assertEquals(one, ai.get(mark));
+ assertSame(one, ai.get(mark));
assertEquals(1,mark[0]);
}
/**
* attemptStamp succeeds in single thread
*/
- public void testAttemptStamp(){
+ public void testAttemptStamp() {
int[] mark = new int[1];
AtomicStampedReference ai = new AtomicStampedReference(one, 0);
assertEquals(0, ai.getStamp());
assertTrue(ai.attemptStamp(one, 1));
assertEquals(1, ai.getStamp());
- assertEquals(one, ai.get(mark));
+ assertSame(one, ai.get(mark));
assertEquals(1, mark[0]);
}
@@ -68,23 +67,23 @@ public class AtomicStampedReferenceTest extends JSR166TestCase{
* compareAndSet succeeds in changing values if equal to expected reference
* and stamp else fails
*/
- public void testCompareAndSet(){
+ public void testCompareAndSet() {
int[] mark = new int[1];
AtomicStampedReference ai = new AtomicStampedReference(one, 0);
- assertEquals(one, ai.get(mark));
+ assertSame(one, ai.get(mark));
assertEquals(0, ai.getStamp());
assertEquals(0, mark[0]);
assertTrue(ai.compareAndSet(one, two, 0, 0));
- assertEquals(two, ai.get(mark));
+ assertSame(two, ai.get(mark));
assertEquals(0, mark[0]);
assertTrue(ai.compareAndSet(two, m3, 0, 1));
- assertEquals(m3, ai.get(mark));
+ assertSame(m3, ai.get(mark));
assertEquals(1, mark[0]);
assertFalse(ai.compareAndSet(two, m3, 1, 1));
- assertEquals(m3, ai.get(mark));
+ assertSame(m3, ai.get(mark));
assertEquals(1, mark[0]);
}
@@ -92,65 +91,59 @@ public class AtomicStampedReferenceTest extends JSR166TestCase{
* compareAndSet in one thread enables another waiting for reference value
* to succeed
*/
- public void testCompareAndSetInMultipleThreads() {
+ public void testCompareAndSetInMultipleThreads() throws Exception {
final AtomicStampedReference ai = new AtomicStampedReference(one, 0);
- Thread t = new Thread(new Runnable() {
- public void run() {
- while(!ai.compareAndSet(two, three, 0, 0)) Thread.yield();
- }});
- try {
- t.start();
- assertTrue(ai.compareAndSet(one, two, 0, 0));
- t.join(LONG_DELAY_MS);
- assertFalse(t.isAlive());
- assertEquals(ai.getReference(), three);
- assertEquals(ai.getStamp(), 0);
- }
- catch(Exception e) {
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ while (!ai.compareAndSet(two, three, 0, 0))
+ Thread.yield();
+ }});
+
+ t.start();
+ assertTrue(ai.compareAndSet(one, two, 0, 0));
+ t.join(LONG_DELAY_MS);
+ assertFalse(t.isAlive());
+ assertSame(ai.getReference(), three);
+ assertEquals(ai.getStamp(), 0);
}
/**
* compareAndSet in one thread enables another waiting for stamp value
* to succeed
*/
- public void testCompareAndSetInMultipleThreads2() {
+ public void testCompareAndSetInMultipleThreads2() throws Exception {
final AtomicStampedReference ai = new AtomicStampedReference(one, 0);
- Thread t = new Thread(new Runnable() {
- public void run() {
- while(!ai.compareAndSet(one, one, 1, 2)) Thread.yield();
- }});
- try {
- t.start();
- assertTrue(ai.compareAndSet(one, one, 0, 1));
- t.join(LONG_DELAY_MS);
- assertFalse(t.isAlive());
- assertEquals(ai.getReference(), one);
- assertEquals(ai.getStamp(), 2);
- }
- catch(Exception e) {
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ while (!ai.compareAndSet(one, one, 1, 2))
+ Thread.yield();
+ }});
+
+ t.start();
+ assertTrue(ai.compareAndSet(one, one, 0, 1));
+ t.join(LONG_DELAY_MS);
+ assertFalse(t.isAlive());
+ assertSame(ai.getReference(), one);
+ assertEquals(ai.getStamp(), 2);
}
/**
* repeated weakCompareAndSet succeeds in changing values when equal
- * to expected
+ * to expected
*/
- public void testWeakCompareAndSet(){
+ public void testWeakCompareAndSet() {
int[] mark = new int[1];
AtomicStampedReference ai = new AtomicStampedReference(one, 0);
- assertEquals(one, ai.get(mark));
+ assertSame(one, ai.get(mark));
assertEquals(0, ai.getStamp ());
assertEquals(0, mark[0]);
- while(!ai.weakCompareAndSet(one, two, 0, 0));
- assertEquals(two, ai.get(mark));
+ while (!ai.weakCompareAndSet(one, two, 0, 0));
+ assertSame(two, ai.get(mark));
assertEquals(0, mark[0]);
- while(!ai.weakCompareAndSet(two, m3, 0, 1));
- assertEquals(m3, ai.get(mark));
+ while (!ai.weakCompareAndSet(two, m3, 0, 1));
+ assertSame(m3, ai.get(mark));
assertEquals(1, mark[0]);
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentHashMapTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentHashMapTest.java
index b7549a4..9b355f5 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentHashMapTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentHashMapTest.java
@@ -2,11 +2,11 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.*;
@@ -14,7 +14,7 @@ import java.util.concurrent.*;
import java.util.Enumeration;
import java.io.*;
-public class ConcurrentHashMapTest extends JSR166TestCase{
+public class ConcurrentHashMapTest extends JSR166TestCase {
public static Test suite() {
return new TestSuite(ConcurrentHashMapTest.class);
}
@@ -80,7 +80,7 @@ public class ConcurrentHashMapTest extends JSR166TestCase{
*/
public void testContainsValue() {
ConcurrentHashMap map = map5();
- assertTrue(map.containsValue("A"));
+ assertTrue(map.containsValue("A"));
assertFalse(map.containsValue("Z"));
}
@@ -92,7 +92,7 @@ public class ConcurrentHashMapTest extends JSR166TestCase{
ConcurrentHashMap map = map5();
Enumeration e = map.elements();
int count = 0;
- while(e.hasMoreElements()){
+ while (e.hasMoreElements()) {
count++;
e.nextElement();
}
@@ -127,7 +127,7 @@ public class ConcurrentHashMapTest extends JSR166TestCase{
ConcurrentHashMap map = map5();
Enumeration e = map.keys();
int count = 0;
- while(e.hasMoreElements()){
+ while (e.hasMoreElements()) {
count++;
e.nextElement();
}
@@ -153,10 +153,10 @@ public class ConcurrentHashMapTest extends JSR166TestCase{
*/
public void testKeySetToArray() {
ConcurrentHashMap map = map5();
- Set s = map.keySet();
+ Set s = map.keySet();
Object[] ar = s.toArray();
assertTrue(s.containsAll(Arrays.asList(ar)));
- assertEquals(5, ar.length);
+ assertEquals(5, ar.length);
ar[0] = m10;
assertFalse(s.containsAll(Arrays.asList(ar)));
}
@@ -166,15 +166,15 @@ public class ConcurrentHashMapTest extends JSR166TestCase{
*/
public void testValuesToArray() {
ConcurrentHashMap map = map5();
- Collection v = map.values();
+ Collection v = map.values();
Object[] ar = v.toArray();
ArrayList s = new ArrayList(Arrays.asList(ar));
- assertEquals(5, ar.length);
- assertTrue(s.contains("A"));
- assertTrue(s.contains("B"));
- assertTrue(s.contains("C"));
- assertTrue(s.contains("D"));
- assertTrue(s.contains("E"));
+ assertEquals(5, ar.length);
+ assertTrue(s.contains("A"));
+ assertTrue(s.contains("B"));
+ assertTrue(s.contains("C"));
+ assertTrue(s.contains("D"));
+ assertTrue(s.contains("E"));
}
/**
@@ -182,7 +182,7 @@ public class ConcurrentHashMapTest extends JSR166TestCase{
*/
public void testEntrySetToArray() {
ConcurrentHashMap map = map5();
- Set s = map.entrySet();
+ Set s = map.entrySet();
Object[] ar = s.toArray();
assertEquals(5, ar.length);
for (int i = 0; i < 5; ++i) {
@@ -317,7 +317,6 @@ public class ConcurrentHashMapTest extends JSR166TestCase{
map.remove(four, "A");
assertEquals(4, map.size());
assertTrue(map.containsKey(four));
-
}
/**
@@ -350,7 +349,7 @@ public class ConcurrentHashMapTest extends JSR166TestCase{
try {
new ConcurrentHashMap(-1,0,1);
shouldThrow();
- } catch(IllegalArgumentException e){}
+ } catch (IllegalArgumentException success) {}
}
/**
@@ -360,7 +359,7 @@ public class ConcurrentHashMapTest extends JSR166TestCase{
try {
new ConcurrentHashMap(1,0,-1);
shouldThrow();
- } catch(IllegalArgumentException e){}
+ } catch (IllegalArgumentException success) {}
}
/**
@@ -370,7 +369,7 @@ public class ConcurrentHashMapTest extends JSR166TestCase{
try {
new ConcurrentHashMap(-1);
shouldThrow();
- } catch(IllegalArgumentException e){}
+ } catch (IllegalArgumentException success) {}
}
/**
@@ -381,7 +380,7 @@ public class ConcurrentHashMapTest extends JSR166TestCase{
ConcurrentHashMap c = new ConcurrentHashMap(5);
c.get(null);
shouldThrow();
- } catch(NullPointerException e){}
+ } catch (NullPointerException success) {}
}
/**
@@ -392,7 +391,7 @@ public class ConcurrentHashMapTest extends JSR166TestCase{
ConcurrentHashMap c = new ConcurrentHashMap(5);
c.containsKey(null);
shouldThrow();
- } catch(NullPointerException e){}
+ } catch (NullPointerException success) {}
}
/**
@@ -403,7 +402,7 @@ public class ConcurrentHashMapTest extends JSR166TestCase{
ConcurrentHashMap c = new ConcurrentHashMap(5);
c.containsValue(null);
shouldThrow();
- } catch(NullPointerException e){}
+ } catch (NullPointerException success) {}
}
/**
@@ -414,7 +413,7 @@ public class ConcurrentHashMapTest extends JSR166TestCase{
ConcurrentHashMap c = new ConcurrentHashMap(5);
c.contains(null);
shouldThrow();
- } catch(NullPointerException e){}
+ } catch (NullPointerException success) {}
}
/**
@@ -425,7 +424,7 @@ public class ConcurrentHashMapTest extends JSR166TestCase{
ConcurrentHashMap c = new ConcurrentHashMap(5);
c.put(null, "whatever");
shouldThrow();
- } catch(NullPointerException e){}
+ } catch (NullPointerException success) {}
}
/**
@@ -436,7 +435,7 @@ public class ConcurrentHashMapTest extends JSR166TestCase{
ConcurrentHashMap c = new ConcurrentHashMap(5);
c.put("whatever", null);
shouldThrow();
- } catch(NullPointerException e){}
+ } catch (NullPointerException success) {}
}
/**
@@ -447,7 +446,7 @@ public class ConcurrentHashMapTest extends JSR166TestCase{
ConcurrentHashMap c = new ConcurrentHashMap(5);
c.putIfAbsent(null, "whatever");
shouldThrow();
- } catch(NullPointerException e){}
+ } catch (NullPointerException success) {}
}
/**
@@ -458,7 +457,7 @@ public class ConcurrentHashMapTest extends JSR166TestCase{
ConcurrentHashMap c = new ConcurrentHashMap(5);
c.replace(null, "whatever");
shouldThrow();
- } catch(NullPointerException e){}
+ } catch (NullPointerException success) {}
}
/**
@@ -469,7 +468,7 @@ public class ConcurrentHashMapTest extends JSR166TestCase{
ConcurrentHashMap c = new ConcurrentHashMap(5);
c.replace(null, one, "whatever");
shouldThrow();
- } catch(NullPointerException e){}
+ } catch (NullPointerException success) {}
}
/**
@@ -480,7 +479,7 @@ public class ConcurrentHashMapTest extends JSR166TestCase{
ConcurrentHashMap c = new ConcurrentHashMap(5);
c.putIfAbsent("whatever", null);
shouldThrow();
- } catch(NullPointerException e){}
+ } catch (NullPointerException success) {}
}
@@ -492,7 +491,7 @@ public class ConcurrentHashMapTest extends JSR166TestCase{
ConcurrentHashMap c = new ConcurrentHashMap(5);
c.replace("whatever", null);
shouldThrow();
- } catch(NullPointerException e){}
+ } catch (NullPointerException success) {}
}
/**
@@ -503,7 +502,7 @@ public class ConcurrentHashMapTest extends JSR166TestCase{
ConcurrentHashMap c = new ConcurrentHashMap(5);
c.replace("whatever", null, "A");
shouldThrow();
- } catch(NullPointerException e){}
+ } catch (NullPointerException success) {}
}
/**
@@ -514,7 +513,7 @@ public class ConcurrentHashMapTest extends JSR166TestCase{
ConcurrentHashMap c = new ConcurrentHashMap(5);
c.replace("whatever", one, null);
shouldThrow();
- } catch(NullPointerException e){}
+ } catch (NullPointerException success) {}
}
@@ -527,7 +526,7 @@ public class ConcurrentHashMapTest extends JSR166TestCase{
c.put("sadsdf", "asdads");
c.remove(null);
shouldThrow();
- } catch(NullPointerException e){}
+ } catch (NullPointerException success) {}
}
/**
@@ -539,44 +538,35 @@ public class ConcurrentHashMapTest extends JSR166TestCase{
c.put("sadsdf", "asdads");
c.remove(null, "whatever");
shouldThrow();
- } catch(NullPointerException e){}
+ } catch (NullPointerException success) {}
}
/**
* remove(x, null) returns false
*/
public void testRemove3() {
- try {
- ConcurrentHashMap c = new ConcurrentHashMap(5);
- c.put("sadsdf", "asdads");
- assertFalse(c.remove("sadsdf", null));
- } catch(NullPointerException e){
- fail();
- }
+ ConcurrentHashMap c = new ConcurrentHashMap(5);
+ c.put("sadsdf", "asdads");
+ assertFalse(c.remove("sadsdf", null));
}
/**
* A deserialized map equals original
*/
- public void testSerialization() {
+ public void testSerialization() throws Exception {
ConcurrentHashMap q = map5();
- try {
- ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
- ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
- out.writeObject(q);
- out.close();
-
- ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
- ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
- ConcurrentHashMap r = (ConcurrentHashMap)in.readObject();
- assertEquals(q.size(), r.size());
- assertTrue(q.equals(r));
- assertTrue(r.equals(q));
- } catch(Exception e){
- e.printStackTrace();
- unexpectedException();
- }
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(q);
+ out.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ ConcurrentHashMap r = (ConcurrentHashMap)in.readObject();
+ assertEquals(q.size(), r.size());
+ assertTrue(q.equals(r));
+ assertTrue(r.equals(q));
}
@@ -584,23 +574,23 @@ public class ConcurrentHashMapTest extends JSR166TestCase{
* SetValue of an EntrySet entry sets value in the map.
*/
public void testSetValueWriteThrough() {
- // Adapted from a bug report by Eric Zoerner
+ // Adapted from a bug report by Eric Zoerner
ConcurrentHashMap map = new ConcurrentHashMap(2, 5.0f, 1);
assertTrue(map.isEmpty());
for (int i = 0; i < 20; i++)
map.put(new Integer(i), new Integer(i));
assertFalse(map.isEmpty());
Map.Entry entry1 = (Map.Entry)map.entrySet().iterator().next();
-
+
// assert that entry1 is not 16
assertTrue("entry is 16, test not valid",
!entry1.getKey().equals(new Integer(16)));
-
- // remove 16 (a different key) from map
+
+ // remove 16 (a different key) from map
// which just happens to cause entry1 to be cloned in map
map.remove(new Integer(16));
entry1.setValue("XYZ");
assertTrue(map.containsValue("XYZ")); // fails
}
-
+
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentLinkedQueueTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentLinkedQueueTest.java
index c84dc59..1fbc729 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentLinkedQueueTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentLinkedQueueTest.java
@@ -2,11 +2,11 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.*;
@@ -25,13 +25,13 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase {
private ConcurrentLinkedQueue populatedQueue(int n) {
ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
assertTrue(q.isEmpty());
- for(int i = 0; i < n; ++i)
+ for (int i = 0; i < n; ++i)
assertTrue(q.offer(new Integer(i)));
assertFalse(q.isEmpty());
assertEquals(n, q.size());
return q;
}
-
+
/**
* new queue is empty
*/
@@ -46,8 +46,7 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase {
try {
ConcurrentLinkedQueue q = new ConcurrentLinkedQueue((Collection)null);
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
@@ -58,8 +57,7 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase {
Integer[] ints = new Integer[SIZE];
ConcurrentLinkedQueue q = new ConcurrentLinkedQueue(Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
@@ -72,23 +70,19 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase {
ints[i] = new Integer(i);
ConcurrentLinkedQueue q = new ConcurrentLinkedQueue(Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
* Queue contains all elements of collection used to initialize
*/
public void testConstructor6() {
- try {
- Integer[] ints = new Integer[SIZE];
- for (int i = 0; i < SIZE; ++i)
- ints[i] = new Integer(i);
- ConcurrentLinkedQueue q = new ConcurrentLinkedQueue(Arrays.asList(ints));
- for (int i = 0; i < SIZE; ++i)
- assertEquals(ints[i], q.poll());
- }
- finally {}
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = new Integer(i);
+ ConcurrentLinkedQueue q = new ConcurrentLinkedQueue(Arrays.asList(ints));
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(ints[i], q.poll());
}
/**
@@ -128,7 +122,7 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase {
ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
q.offer(null);
shouldThrow();
- } catch (NullPointerException success) { }
+ } catch (NullPointerException success) {}
}
/**
@@ -139,7 +133,7 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase {
ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
q.add(null);
shouldThrow();
- } catch (NullPointerException success) { }
+ } catch (NullPointerException success) {}
}
@@ -171,8 +165,7 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase {
ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
q.addAll(null);
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
@@ -183,8 +176,7 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase {
ConcurrentLinkedQueue q = populatedQueue(SIZE);
q.addAll(q);
shouldThrow();
- }
- catch (IllegalArgumentException success) {}
+ } catch (IllegalArgumentException success) {}
}
/**
@@ -196,8 +188,7 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase {
Integer[] ints = new Integer[SIZE];
q.addAll(Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
* addAll of a collection with any null elements throws NPE after
@@ -211,26 +202,22 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase {
ints[i] = new Integer(i);
q.addAll(Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
* Queue contains all elements, in traversal order, of successful addAll
*/
public void testAddAll5() {
- try {
- Integer[] empty = new Integer[0];
- Integer[] ints = new Integer[SIZE];
- for (int i = 0; i < SIZE; ++i)
- ints[i] = new Integer(i);
- ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
- assertFalse(q.addAll(Arrays.asList(empty)));
- assertTrue(q.addAll(Arrays.asList(ints)));
- for (int i = 0; i < SIZE; ++i)
- assertEquals(ints[i], q.poll());
- }
- finally {}
+ Integer[] empty = new Integer[0];
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = new Integer(i);
+ ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
+ assertFalse(q.addAll(Arrays.asList(empty)));
+ assertTrue(q.addAll(Arrays.asList(ints)));
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(ints[i], q.poll());
}
/**
@@ -239,7 +226,7 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase {
public void testPoll() {
ConcurrentLinkedQueue q = populatedQueue(SIZE);
for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.poll()).intValue());
+ assertEquals(i, q.poll());
}
assertNull(q.poll());
}
@@ -250,10 +237,10 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase {
public void testPeek() {
ConcurrentLinkedQueue q = populatedQueue(SIZE);
for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.peek()).intValue());
- q.poll();
+ assertEquals(i, q.peek());
+ assertEquals(i, q.poll());
assertTrue(q.peek() == null ||
- i != ((Integer)q.peek()).intValue());
+ !q.peek().equals(i));
}
assertNull(q.peek());
}
@@ -264,14 +251,13 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase {
public void testElement() {
ConcurrentLinkedQueue q = populatedQueue(SIZE);
for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.element()).intValue());
- q.poll();
+ assertEquals(i, q.element());
+ assertEquals(i, q.poll());
}
try {
q.element();
shouldThrow();
- }
- catch (NoSuchElementException success) {}
+ } catch (NoSuchElementException success) {}
}
/**
@@ -280,13 +266,12 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase {
public void testRemove() {
ConcurrentLinkedQueue q = populatedQueue(SIZE);
for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.remove()).intValue());
+ assertEquals(i, q.remove());
}
try {
q.remove();
shouldThrow();
- } catch (NoSuchElementException success){
- }
+ } catch (NoSuchElementException success) {}
}
/**
@@ -303,7 +288,7 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase {
}
assertTrue(q.isEmpty());
}
-
+
/**
* contains(x) reports true when elements added but not yet removed
*/
@@ -386,7 +371,7 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase {
ConcurrentLinkedQueue q = populatedQueue(SIZE);
Object[] o = q.toArray();
Arrays.sort(o);
- for(int i = 0; i < o.length; i++)
+ for (int i = 0; i < o.length; i++)
assertEquals(o[i], q.poll());
}
@@ -398,7 +383,7 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase {
Integer[] ints = new Integer[SIZE];
ints = (Integer[])q.toArray(ints);
Arrays.sort(ints);
- for(int i = 0; i < ints.length; i++)
+ for (int i = 0; i < ints.length; i++)
assertEquals(ints[i], q.poll());
}
@@ -406,24 +391,24 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase {
* toArray(null) throws NPE
*/
public void testToArray_BadArg() {
+ ConcurrentLinkedQueue q = populatedQueue(SIZE);
try {
- ConcurrentLinkedQueue q = populatedQueue(SIZE);
Object o[] = q.toArray(null);
shouldThrow();
- } catch(NullPointerException success){}
+ } catch (NullPointerException success) {}
}
/**
- * toArray with incompatible array type throws CCE
+ * toArray with incompatible array type throws ArrayStoreException
*/
public void testToArray1_BadArg() {
+ ConcurrentLinkedQueue q = populatedQueue(SIZE);
try {
- ConcurrentLinkedQueue q = populatedQueue(SIZE);
- Object o[] = q.toArray(new String[10] );
+ Object o[] = q.toArray(new String[10]);
shouldThrow();
- } catch(ArrayStoreException success){}
+ } catch (ArrayStoreException success) {}
}
-
+
/**
* iterator iterates through all elements
*/
@@ -431,7 +416,7 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase {
ConcurrentLinkedQueue q = populatedQueue(SIZE);
int i = 0;
Iterator it = q.iterator();
- while(it.hasNext()) {
+ while (it.hasNext()) {
assertTrue(q.contains(it.next()));
++i;
}
@@ -449,8 +434,7 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase {
int k = 0;
for (Iterator it = q.iterator(); it.hasNext();) {
- int i = ((Integer)(it.next())).intValue();
- assertEquals(++k, i);
+ assertEquals(++k, it.next());
}
assertEquals(3, k);
@@ -465,14 +449,9 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase {
q.add(two);
q.add(three);
- try {
- for (Iterator it = q.iterator(); it.hasNext();) {
- q.remove();
- it.next();
- }
- }
- catch (ConcurrentModificationException e) {
- shouldThrow();
+ for (Iterator it = q.iterator(); it.hasNext();) {
+ q.remove();
+ it.next();
}
assertEquals("queue should be empty again", 0, q.size());
@@ -490,8 +469,8 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase {
it.next();
it.remove();
it = q.iterator();
- assertEquals(it.next(), two);
- assertEquals(it.next(), three);
+ assertSame(it.next(), two);
+ assertSame(it.next(), three);
assertFalse(it.hasNext());
}
@@ -505,28 +484,24 @@ public class ConcurrentLinkedQueueTest extends JSR166TestCase {
for (int i = 0; i < SIZE; ++i) {
assertTrue(s.indexOf(String.valueOf(i)) >= 0);
}
- }
+ }
/**
* A deserialized serialized queue has same elements in same order
*/
- public void testSerialization() {
+ public void testSerialization() throws Exception {
ConcurrentLinkedQueue q = populatedQueue(SIZE);
- try {
- ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
- ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
- out.writeObject(q);
- out.close();
-
- ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
- ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
- ConcurrentLinkedQueue r = (ConcurrentLinkedQueue)in.readObject();
- assertEquals(q.size(), r.size());
- while (!q.isEmpty())
- assertEquals(q.remove(), r.remove());
- } catch(Exception e){
- unexpectedException();
- }
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(q);
+ out.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ ConcurrentLinkedQueue r = (ConcurrentLinkedQueue)in.readObject();
+ assertEquals(q.size(), r.size());
+ while (!q.isEmpty())
+ assertEquals(q.remove(), r.remove());
}
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentSkipListMapTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentSkipListMapTest.java
new file mode 100644
index 0000000..3cf5b75
--- /dev/null
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentSkipListMapTest.java
@@ -0,0 +1,1280 @@
+/*
+ * 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 tests.api.java.util.concurrent; // android-added
+
+import junit.framework.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.io.*;
+
+public class ConcurrentSkipListMapTest extends JSR166TestCase {
+ public static Test suite() {
+ return new TestSuite(ConcurrentSkipListMapTest.class);
+ }
+
+ /**
+ * Create a map from Integers 1-5 to Strings "A"-"E".
+ */
+ private static ConcurrentSkipListMap map5() {
+ ConcurrentSkipListMap map = new ConcurrentSkipListMap();
+ assertTrue(map.isEmpty());
+ map.put(one, "A");
+ map.put(five, "E");
+ map.put(three, "C");
+ map.put(two, "B");
+ map.put(four, "D");
+ assertFalse(map.isEmpty());
+ assertEquals(5, map.size());
+ return map;
+ }
+
+ /**
+ * clear removes all pairs
+ */
+ public void testClear() {
+ ConcurrentSkipListMap map = map5();
+ map.clear();
+ assertEquals(map.size(), 0);
+ }
+
+ /**
+ *
+ */
+ public void testConstructFromSorted() {
+ ConcurrentSkipListMap map = map5();
+ ConcurrentSkipListMap map2 = new ConcurrentSkipListMap(map);
+ assertEquals(map, map2);
+ }
+
+ /**
+ * Maps with same contents are equal
+ */
+ public void testEquals() {
+ ConcurrentSkipListMap map1 = map5();
+ ConcurrentSkipListMap map2 = map5();
+ assertEquals(map1, map2);
+ assertEquals(map2, map1);
+ map1.clear();
+ assertFalse(map1.equals(map2));
+ assertFalse(map2.equals(map1));
+ }
+
+ /**
+ * containsKey returns true for contained key
+ */
+ public void testContainsKey() {
+ ConcurrentSkipListMap map = map5();
+ assertTrue(map.containsKey(one));
+ assertFalse(map.containsKey(zero));
+ }
+
+ /**
+ * containsValue returns true for held values
+ */
+ public void testContainsValue() {
+ ConcurrentSkipListMap map = map5();
+ assertTrue(map.containsValue("A"));
+ assertFalse(map.containsValue("Z"));
+ }
+
+ /**
+ * get returns the correct element at the given key,
+ * or null if not present
+ */
+ public void testGet() {
+ ConcurrentSkipListMap map = map5();
+ assertEquals("A", (String)map.get(one));
+ ConcurrentSkipListMap empty = new ConcurrentSkipListMap();
+ assertNull(empty.get(one));
+ }
+
+ /**
+ * isEmpty is true of empty map and false for non-empty
+ */
+ public void testIsEmpty() {
+ ConcurrentSkipListMap empty = new ConcurrentSkipListMap();
+ ConcurrentSkipListMap map = map5();
+ assertTrue(empty.isEmpty());
+ assertFalse(map.isEmpty());
+ }
+
+ /**
+ * firstKey returns first key
+ */
+ public void testFirstKey() {
+ ConcurrentSkipListMap map = map5();
+ assertEquals(one, map.firstKey());
+ }
+
+ /**
+ * lastKey returns last key
+ */
+ public void testLastKey() {
+ ConcurrentSkipListMap map = map5();
+ assertEquals(five, map.lastKey());
+ }
+
+
+ /**
+ * keySet.toArray returns contains all keys
+ */
+ public void testKeySetToArray() {
+ ConcurrentSkipListMap map = map5();
+ Set s = map.keySet();
+ Object[] ar = s.toArray();
+ assertTrue(s.containsAll(Arrays.asList(ar)));
+ assertEquals(5, ar.length);
+ ar[0] = m10;
+ assertFalse(s.containsAll(Arrays.asList(ar)));
+ }
+
+ /**
+ * descendingkeySet.toArray returns contains all keys
+ */
+ public void testDescendingKeySetToArray() {
+ ConcurrentSkipListMap map = map5();
+ Set s = map.descendingKeySet();
+ Object[] ar = s.toArray();
+ assertEquals(5, ar.length);
+ assertTrue(s.containsAll(Arrays.asList(ar)));
+ ar[0] = m10;
+ assertFalse(s.containsAll(Arrays.asList(ar)));
+ }
+
+ /**
+ * keySet returns a Set containing all the keys
+ */
+ public void testKeySet() {
+ ConcurrentSkipListMap map = map5();
+ Set s = map.keySet();
+ assertEquals(5, s.size());
+ assertTrue(s.contains(one));
+ assertTrue(s.contains(two));
+ assertTrue(s.contains(three));
+ assertTrue(s.contains(four));
+ assertTrue(s.contains(five));
+ }
+
+ /**
+ * keySet is ordered
+ */
+ public void testKeySetOrder() {
+ ConcurrentSkipListMap map = map5();
+ Set s = map.keySet();
+ Iterator i = s.iterator();
+ Integer last = (Integer)i.next();
+ assertEquals(last, one);
+ int count = 1;
+ while (i.hasNext()) {
+ Integer k = (Integer)i.next();
+ assertTrue(last.compareTo(k) < 0);
+ last = k;
+ ++count;
+ }
+ assertEquals(count ,5);
+ }
+
+ /**
+ * descending iterator of key set is inverse ordered
+ */
+ public void testKeySetDescendingIteratorOrder() {
+ ConcurrentSkipListMap map = map5();
+ NavigableSet s = map.navigableKeySet();
+ Iterator i = s.descendingIterator();
+ Integer last = (Integer)i.next();
+ assertEquals(last, five);
+ int count = 1;
+ while (i.hasNext()) {
+ Integer k = (Integer)i.next();
+ assertTrue(last.compareTo(k) > 0);
+ last = k;
+ ++count;
+ }
+ assertEquals(count ,5);
+ }
+
+ /**
+ * descendingKeySet is ordered
+ */
+ public void testDescendingKeySetOrder() {
+ ConcurrentSkipListMap map = map5();
+ Set s = map.descendingKeySet();
+ Iterator i = s.iterator();
+ Integer last = (Integer)i.next();
+ assertEquals(last, five);
+ int count = 1;
+ while (i.hasNext()) {
+ Integer k = (Integer)i.next();
+ assertTrue(last.compareTo(k) > 0);
+ last = k;
+ ++count;
+ }
+ assertEquals(count, 5);
+ }
+
+ /**
+ * descending iterator of descendingKeySet is ordered
+ */
+ public void testDescendingKeySetDescendingIteratorOrder() {
+ ConcurrentSkipListMap map = map5();
+ NavigableSet s = map.descendingKeySet();
+ Iterator i = s.descendingIterator();
+ Integer last = (Integer)i.next();
+ assertEquals(last, one);
+ int count = 1;
+ while (i.hasNext()) {
+ Integer k = (Integer)i.next();
+ assertTrue(last.compareTo(k) < 0);
+ last = k;
+ ++count;
+ }
+ assertEquals(count, 5);
+ }
+
+ /**
+ * Values.toArray contains all values
+ */
+ public void testValuesToArray() {
+ ConcurrentSkipListMap map = map5();
+ Collection v = map.values();
+ Object[] ar = v.toArray();
+ ArrayList s = new ArrayList(Arrays.asList(ar));
+ assertEquals(5, ar.length);
+ assertTrue(s.contains("A"));
+ assertTrue(s.contains("B"));
+ assertTrue(s.contains("C"));
+ assertTrue(s.contains("D"));
+ assertTrue(s.contains("E"));
+ }
+
+ /**
+ * values collection contains all values
+ */
+ public void testValues() {
+ ConcurrentSkipListMap map = map5();
+ Collection s = map.values();
+ assertEquals(5, s.size());
+ assertTrue(s.contains("A"));
+ assertTrue(s.contains("B"));
+ assertTrue(s.contains("C"));
+ assertTrue(s.contains("D"));
+ assertTrue(s.contains("E"));
+ }
+
+ /**
+ * entrySet contains all pairs
+ */
+ public void testEntrySet() {
+ ConcurrentSkipListMap map = map5();
+ Set s = map.entrySet();
+ assertEquals(5, s.size());
+ Iterator it = s.iterator();
+ while (it.hasNext()) {
+ Map.Entry e = (Map.Entry) it.next();
+ assertTrue(
+ (e.getKey().equals(one) && e.getValue().equals("A")) ||
+ (e.getKey().equals(two) && e.getValue().equals("B")) ||
+ (e.getKey().equals(three) && e.getValue().equals("C")) ||
+ (e.getKey().equals(four) && e.getValue().equals("D")) ||
+ (e.getKey().equals(five) && e.getValue().equals("E")));
+ }
+ }
+
+ /**
+ * descendingEntrySet contains all pairs
+ */
+ public void testDescendingEntrySet() {
+ ConcurrentSkipListMap map = map5();
+ Set s = map.descendingMap().entrySet();
+ assertEquals(5, s.size());
+ Iterator it = s.iterator();
+ while (it.hasNext()) {
+ Map.Entry e = (Map.Entry) it.next();
+ assertTrue(
+ (e.getKey().equals(one) && e.getValue().equals("A")) ||
+ (e.getKey().equals(two) && e.getValue().equals("B")) ||
+ (e.getKey().equals(three) && e.getValue().equals("C")) ||
+ (e.getKey().equals(four) && e.getValue().equals("D")) ||
+ (e.getKey().equals(five) && e.getValue().equals("E")));
+ }
+ }
+
+ /**
+ * entrySet.toArray contains all entries
+ */
+ public void testEntrySetToArray() {
+ ConcurrentSkipListMap map = map5();
+ Set s = map.entrySet();
+ Object[] ar = s.toArray();
+ assertEquals(5, ar.length);
+ for (int i = 0; i < 5; ++i) {
+ assertTrue(map.containsKey(((Map.Entry)(ar[i])).getKey()));
+ assertTrue(map.containsValue(((Map.Entry)(ar[i])).getValue()));
+ }
+ }
+
+ /**
+ * descendingEntrySet.toArray contains all entries
+ */
+ public void testDescendingEntrySetToArray() {
+ ConcurrentSkipListMap map = map5();
+ Set s = map.descendingMap().entrySet();
+ Object[] ar = s.toArray();
+ assertEquals(5, ar.length);
+ for (int i = 0; i < 5; ++i) {
+ assertTrue(map.containsKey(((Map.Entry)(ar[i])).getKey()));
+ assertTrue(map.containsValue(((Map.Entry)(ar[i])).getValue()));
+ }
+ }
+
+ /**
+ * putAll adds all key-value pairs from the given map
+ */
+ public void testPutAll() {
+ ConcurrentSkipListMap empty = new ConcurrentSkipListMap();
+ ConcurrentSkipListMap map = map5();
+ empty.putAll(map);
+ assertEquals(5, empty.size());
+ assertTrue(empty.containsKey(one));
+ assertTrue(empty.containsKey(two));
+ assertTrue(empty.containsKey(three));
+ assertTrue(empty.containsKey(four));
+ assertTrue(empty.containsKey(five));
+ }
+
+ /**
+ * putIfAbsent works when the given key is not present
+ */
+ public void testPutIfAbsent() {
+ ConcurrentSkipListMap map = map5();
+ map.putIfAbsent(six, "Z");
+ assertTrue(map.containsKey(six));
+ }
+
+ /**
+ * putIfAbsent does not add the pair if the key is already present
+ */
+ public void testPutIfAbsent2() {
+ ConcurrentSkipListMap map = map5();
+ assertEquals("A", map.putIfAbsent(one, "Z"));
+ }
+
+ /**
+ * replace fails when the given key is not present
+ */
+ public void testReplace() {
+ ConcurrentSkipListMap map = map5();
+ assertNull(map.replace(six, "Z"));
+ assertFalse(map.containsKey(six));
+ }
+
+ /**
+ * replace succeeds if the key is already present
+ */
+ public void testReplace2() {
+ ConcurrentSkipListMap map = map5();
+ assertNotNull(map.replace(one, "Z"));
+ assertEquals("Z", map.get(one));
+ }
+
+
+ /**
+ * replace value fails when the given key not mapped to expected value
+ */
+ public void testReplaceValue() {
+ ConcurrentSkipListMap map = map5();
+ assertEquals("A", map.get(one));
+ assertFalse(map.replace(one, "Z", "Z"));
+ assertEquals("A", map.get(one));
+ }
+
+ /**
+ * replace value succeeds when the given key mapped to expected value
+ */
+ public void testReplaceValue2() {
+ ConcurrentSkipListMap map = map5();
+ assertEquals("A", map.get(one));
+ assertTrue(map.replace(one, "A", "Z"));
+ assertEquals("Z", map.get(one));
+ }
+
+
+ /**
+ * remove removes the correct key-value pair from the map
+ */
+ public void testRemove() {
+ ConcurrentSkipListMap map = map5();
+ map.remove(five);
+ assertEquals(4, map.size());
+ assertFalse(map.containsKey(five));
+ }
+
+ /**
+ * remove(key,value) removes only if pair present
+ */
+ public void testRemove2() {
+ ConcurrentSkipListMap map = map5();
+ assertTrue(map.containsKey(five));
+ assertEquals("E", map.get(five));
+ map.remove(five, "E");
+ assertEquals(4, map.size());
+ assertFalse(map.containsKey(five));
+ map.remove(four, "A");
+ assertEquals(4, map.size());
+ assertTrue(map.containsKey(four));
+ }
+
+ /**
+ * lowerEntry returns preceding entry.
+ */
+ public void testLowerEntry() {
+ ConcurrentSkipListMap map = map5();
+ Map.Entry e1 = map.lowerEntry(three);
+ assertEquals(two, e1.getKey());
+
+ Map.Entry e2 = map.lowerEntry(six);
+ assertEquals(five, e2.getKey());
+
+ Map.Entry e3 = map.lowerEntry(one);
+ assertNull(e3);
+
+ Map.Entry e4 = map.lowerEntry(zero);
+ assertNull(e4);
+ }
+
+ /**
+ * higherEntry returns next entry.
+ */
+ public void testHigherEntry() {
+ ConcurrentSkipListMap map = map5();
+ Map.Entry e1 = map.higherEntry(three);
+ assertEquals(four, e1.getKey());
+
+ Map.Entry e2 = map.higherEntry(zero);
+ assertEquals(one, e2.getKey());
+
+ Map.Entry e3 = map.higherEntry(five);
+ assertNull(e3);
+
+ Map.Entry e4 = map.higherEntry(six);
+ assertNull(e4);
+ }
+
+ /**
+ * floorEntry returns preceding entry.
+ */
+ public void testFloorEntry() {
+ ConcurrentSkipListMap map = map5();
+ Map.Entry e1 = map.floorEntry(three);
+ assertEquals(three, e1.getKey());
+
+ Map.Entry e2 = map.floorEntry(six);
+ assertEquals(five, e2.getKey());
+
+ Map.Entry e3 = map.floorEntry(one);
+ assertEquals(one, e3.getKey());
+
+ Map.Entry e4 = map.floorEntry(zero);
+ assertNull(e4);
+ }
+
+ /**
+ * ceilingEntry returns next entry.
+ */
+ public void testCeilingEntry() {
+ ConcurrentSkipListMap map = map5();
+ Map.Entry e1 = map.ceilingEntry(three);
+ assertEquals(three, e1.getKey());
+
+ Map.Entry e2 = map.ceilingEntry(zero);
+ assertEquals(one, e2.getKey());
+
+ Map.Entry e3 = map.ceilingEntry(five);
+ assertEquals(five, e3.getKey());
+
+ Map.Entry e4 = map.ceilingEntry(six);
+ assertNull(e4);
+ }
+
+ /**
+ * lowerEntry, higherEntry, ceilingEntry, and floorEntry return
+ * immutable entries
+ */
+ public void testEntryImmutablity() {
+ ConcurrentSkipListMap map = map5();
+ Map.Entry e = map.lowerEntry(three);
+ assertEquals(two, e.getKey());
+ try {
+ e.setValue("X");
+ shouldThrow();
+ } catch (UnsupportedOperationException success) {}
+ e = map.higherEntry(zero);
+ assertEquals(one, e.getKey());
+ try {
+ e.setValue("X");
+ shouldThrow();
+ } catch (UnsupportedOperationException success) {}
+ e = map.floorEntry(one);
+ assertEquals(one, e.getKey());
+ try {
+ e.setValue("X");
+ shouldThrow();
+ } catch (UnsupportedOperationException success) {}
+ e = map.ceilingEntry(five);
+ assertEquals(five, e.getKey());
+ try {
+ e.setValue("X");
+ shouldThrow();
+ } catch (UnsupportedOperationException success) {}
+ }
+
+
+
+ /**
+ * lowerKey returns preceding element
+ */
+ public void testLowerKey() {
+ ConcurrentSkipListMap q = map5();
+ Object e1 = q.lowerKey(three);
+ assertEquals(two, e1);
+
+ Object e2 = q.lowerKey(six);
+ assertEquals(five, e2);
+
+ Object e3 = q.lowerKey(one);
+ assertNull(e3);
+
+ Object e4 = q.lowerKey(zero);
+ assertNull(e4);
+ }
+
+ /**
+ * higherKey returns next element
+ */
+ public void testHigherKey() {
+ ConcurrentSkipListMap q = map5();
+ Object e1 = q.higherKey(three);
+ assertEquals(four, e1);
+
+ Object e2 = q.higherKey(zero);
+ assertEquals(one, e2);
+
+ Object e3 = q.higherKey(five);
+ assertNull(e3);
+
+ Object e4 = q.higherKey(six);
+ assertNull(e4);
+ }
+
+ /**
+ * floorKey returns preceding element
+ */
+ public void testFloorKey() {
+ ConcurrentSkipListMap q = map5();
+ Object e1 = q.floorKey(three);
+ assertEquals(three, e1);
+
+ Object e2 = q.floorKey(six);
+ assertEquals(five, e2);
+
+ Object e3 = q.floorKey(one);
+ assertEquals(one, e3);
+
+ Object e4 = q.floorKey(zero);
+ assertNull(e4);
+ }
+
+ /**
+ * ceilingKey returns next element
+ */
+ public void testCeilingKey() {
+ ConcurrentSkipListMap q = map5();
+ Object e1 = q.ceilingKey(three);
+ assertEquals(three, e1);
+
+ Object e2 = q.ceilingKey(zero);
+ assertEquals(one, e2);
+
+ Object e3 = q.ceilingKey(five);
+ assertEquals(five, e3);
+
+ Object e4 = q.ceilingKey(six);
+ assertNull(e4);
+ }
+
+ /**
+ * pollFirstEntry returns entries in order
+ */
+ public void testPollFirstEntry() {
+ ConcurrentSkipListMap map = map5();
+ Map.Entry e = map.pollFirstEntry();
+ assertEquals(one, e.getKey());
+ assertEquals("A", e.getValue());
+ e = map.pollFirstEntry();
+ assertEquals(two, e.getKey());
+ map.put(one, "A");
+ e = map.pollFirstEntry();
+ assertEquals(one, e.getKey());
+ assertEquals("A", e.getValue());
+ e = map.pollFirstEntry();
+ assertEquals(three, e.getKey());
+ map.remove(four);
+ e = map.pollFirstEntry();
+ assertEquals(five, e.getKey());
+ try {
+ e.setValue("A");
+ shouldThrow();
+ } catch (UnsupportedOperationException success) {}
+ e = map.pollFirstEntry();
+ assertNull(e);
+ }
+
+ /**
+ * pollLastEntry returns entries in order
+ */
+ public void testPollLastEntry() {
+ ConcurrentSkipListMap map = map5();
+ Map.Entry e = map.pollLastEntry();
+ assertEquals(five, e.getKey());
+ assertEquals("E", e.getValue());
+ e = map.pollLastEntry();
+ assertEquals(four, e.getKey());
+ map.put(five, "E");
+ e = map.pollLastEntry();
+ assertEquals(five, e.getKey());
+ assertEquals("E", e.getValue());
+ e = map.pollLastEntry();
+ assertEquals(three, e.getKey());
+ map.remove(two);
+ e = map.pollLastEntry();
+ assertEquals(one, e.getKey());
+ try {
+ e.setValue("E");
+ shouldThrow();
+ } catch (UnsupportedOperationException success) {}
+ e = map.pollLastEntry();
+ assertNull(e);
+ }
+
+ /**
+ * size returns the correct values
+ */
+ public void testSize() {
+ ConcurrentSkipListMap map = map5();
+ ConcurrentSkipListMap empty = new ConcurrentSkipListMap();
+ assertEquals(0, empty.size());
+ assertEquals(5, map.size());
+ }
+
+ /**
+ * toString contains toString of elements
+ */
+ public void testToString() {
+ ConcurrentSkipListMap map = map5();
+ String s = map.toString();
+ for (int i = 1; i <= 5; ++i) {
+ assertTrue(s.indexOf(String.valueOf(i)) >= 0);
+ }
+ }
+
+ // Exception tests
+
+ /**
+ * get(null) of nonempty map throws NPE
+ */
+ public void testGet_NullPointerException() {
+ try {
+ ConcurrentSkipListMap c = map5();
+ c.get(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * containsKey(null) of nonempty map throws NPE
+ */
+ public void testContainsKey_NullPointerException() {
+ try {
+ ConcurrentSkipListMap c = map5();
+ c.containsKey(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * containsValue(null) throws NPE
+ */
+ public void testContainsValue_NullPointerException() {
+ try {
+ ConcurrentSkipListMap c = new ConcurrentSkipListMap();
+ c.containsValue(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+
+ /**
+ * put(null,x) throws NPE
+ */
+ public void testPut1_NullPointerException() {
+ try {
+ ConcurrentSkipListMap c = map5();
+ c.put(null, "whatever");
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * putIfAbsent(null, x) throws NPE
+ */
+ public void testPutIfAbsent1_NullPointerException() {
+ try {
+ ConcurrentSkipListMap c = map5();
+ c.putIfAbsent(null, "whatever");
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * replace(null, x) throws NPE
+ */
+ public void testReplace_NullPointerException() {
+ try {
+ ConcurrentSkipListMap c = map5();
+ c.replace(null, "whatever");
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * replace(null, x, y) throws NPE
+ */
+ public void testReplaceValue_NullPointerException() {
+ try {
+ ConcurrentSkipListMap c = map5();
+ c.replace(null, one, "whatever");
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * remove(null) throws NPE
+ */
+ public void testRemove1_NullPointerException() {
+ try {
+ ConcurrentSkipListMap c = new ConcurrentSkipListMap();
+ c.put("sadsdf", "asdads");
+ c.remove(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * remove(null, x) throws NPE
+ */
+ public void testRemove2_NullPointerException() {
+ try {
+ ConcurrentSkipListMap c = new ConcurrentSkipListMap();
+ c.put("sadsdf", "asdads");
+ c.remove(null, "whatever");
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * remove(x, null) returns false
+ */
+ public void testRemove3() {
+ ConcurrentSkipListMap c = new ConcurrentSkipListMap();
+ c.put("sadsdf", "asdads");
+ assertFalse(c.remove("sadsdf", null));
+ }
+
+ /**
+ * A deserialized map equals original
+ */
+ public void testSerialization() throws Exception {
+ ConcurrentSkipListMap q = map5();
+
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(q);
+ out.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ ConcurrentSkipListMap r = (ConcurrentSkipListMap)in.readObject();
+ assertEquals(q.size(), r.size());
+ assertTrue(q.equals(r));
+ assertTrue(r.equals(q));
+ }
+
+
+
+ /**
+ * subMap returns map with keys in requested range
+ */
+ public void testSubMapContents() {
+ ConcurrentSkipListMap map = map5();
+ NavigableMap sm = map.subMap(two, true, four, false);
+ assertEquals(two, sm.firstKey());
+ assertEquals(three, sm.lastKey());
+ assertEquals(2, sm.size());
+ assertFalse(sm.containsKey(one));
+ assertTrue(sm.containsKey(two));
+ assertTrue(sm.containsKey(three));
+ assertFalse(sm.containsKey(four));
+ assertFalse(sm.containsKey(five));
+ Iterator i = sm.keySet().iterator();
+ Object k;
+ k = (Integer)(i.next());
+ assertEquals(two, k);
+ k = (Integer)(i.next());
+ assertEquals(three, k);
+ assertFalse(i.hasNext());
+ Iterator r = sm.descendingKeySet().iterator();
+ k = (Integer)(r.next());
+ assertEquals(three, k);
+ k = (Integer)(r.next());
+ assertEquals(two, k);
+ assertFalse(r.hasNext());
+
+ Iterator j = sm.keySet().iterator();
+ j.next();
+ j.remove();
+ assertFalse(map.containsKey(two));
+ assertEquals(4, map.size());
+ assertEquals(1, sm.size());
+ assertEquals(three, sm.firstKey());
+ assertEquals(three, sm.lastKey());
+ assertEquals("C", sm.remove(three));
+ assertTrue(sm.isEmpty());
+ assertEquals(3, map.size());
+ }
+
+ public void testSubMapContents2() {
+ ConcurrentSkipListMap map = map5();
+ NavigableMap sm = map.subMap(two, true, three, false);
+ assertEquals(1, sm.size());
+ assertEquals(two, sm.firstKey());
+ assertEquals(two, sm.lastKey());
+ assertFalse(sm.containsKey(one));
+ assertTrue(sm.containsKey(two));
+ assertFalse(sm.containsKey(three));
+ assertFalse(sm.containsKey(four));
+ assertFalse(sm.containsKey(five));
+ Iterator i = sm.keySet().iterator();
+ Object k;
+ k = (Integer)(i.next());
+ assertEquals(two, k);
+ assertFalse(i.hasNext());
+ Iterator r = sm.descendingKeySet().iterator();
+ k = (Integer)(r.next());
+ assertEquals(two, k);
+ assertFalse(r.hasNext());
+
+ Iterator j = sm.keySet().iterator();
+ j.next();
+ j.remove();
+ assertFalse(map.containsKey(two));
+ assertEquals(4, map.size());
+ assertEquals(0, sm.size());
+ assertTrue(sm.isEmpty());
+ assertSame(sm.remove(three), null);
+ assertEquals(4, map.size());
+ }
+
+ /**
+ * headMap returns map with keys in requested range
+ */
+ public void testHeadMapContents() {
+ ConcurrentSkipListMap map = map5();
+ NavigableMap sm = map.headMap(four, false);
+ assertTrue(sm.containsKey(one));
+ assertTrue(sm.containsKey(two));
+ assertTrue(sm.containsKey(three));
+ assertFalse(sm.containsKey(four));
+ assertFalse(sm.containsKey(five));
+ Iterator i = sm.keySet().iterator();
+ Object k;
+ k = (Integer)(i.next());
+ assertEquals(one, k);
+ k = (Integer)(i.next());
+ assertEquals(two, k);
+ k = (Integer)(i.next());
+ assertEquals(three, k);
+ assertFalse(i.hasNext());
+ sm.clear();
+ assertTrue(sm.isEmpty());
+ assertEquals(2, map.size());
+ assertEquals(four, map.firstKey());
+ }
+
+ /**
+ * tailMap returns map with keys in requested range
+ */
+ public void testTailMapContents() {
+ ConcurrentSkipListMap map = map5();
+ NavigableMap sm = map.tailMap(two, true);
+ assertFalse(sm.containsKey(one));
+ assertTrue(sm.containsKey(two));
+ assertTrue(sm.containsKey(three));
+ assertTrue(sm.containsKey(four));
+ assertTrue(sm.containsKey(five));
+ Iterator i = sm.keySet().iterator();
+ Object k;
+ k = (Integer)(i.next());
+ assertEquals(two, k);
+ k = (Integer)(i.next());
+ assertEquals(three, k);
+ k = (Integer)(i.next());
+ assertEquals(four, k);
+ k = (Integer)(i.next());
+ assertEquals(five, k);
+ assertFalse(i.hasNext());
+ Iterator r = sm.descendingKeySet().iterator();
+ k = (Integer)(r.next());
+ assertEquals(five, k);
+ k = (Integer)(r.next());
+ assertEquals(four, k);
+ k = (Integer)(r.next());
+ assertEquals(three, k);
+ k = (Integer)(r.next());
+ assertEquals(two, k);
+ assertFalse(r.hasNext());
+
+ Iterator ei = sm.entrySet().iterator();
+ Map.Entry e;
+ e = (Map.Entry)(ei.next());
+ assertEquals(two, e.getKey());
+ assertEquals("B", e.getValue());
+ e = (Map.Entry)(ei.next());
+ assertEquals(three, e.getKey());
+ assertEquals("C", e.getValue());
+ e = (Map.Entry)(ei.next());
+ assertEquals(four, e.getKey());
+ assertEquals("D", e.getValue());
+ e = (Map.Entry)(ei.next());
+ assertEquals(five, e.getKey());
+ assertEquals("E", e.getValue());
+ assertFalse(i.hasNext());
+
+ NavigableMap ssm = sm.tailMap(four, true);
+ assertEquals(four, ssm.firstKey());
+ assertEquals(five, ssm.lastKey());
+ assertEquals("D", ssm.remove(four));
+ assertEquals(1, ssm.size());
+ assertEquals(3, sm.size());
+ assertEquals(4, map.size());
+ }
+
+ Random rnd = new Random(666);
+ BitSet bs;
+
+ /**
+ * Submaps of submaps subdivide correctly
+ */
+ public void testRecursiveSubMaps() throws Exception {
+ int mapSize = 1000;
+ Class cl = ConcurrentSkipListMap.class;
+ NavigableMap<Integer, Integer> map = newMap(cl);
+ bs = new BitSet(mapSize);
+
+ populate(map, mapSize);
+ check(map, 0, mapSize - 1, true);
+ check(map.descendingMap(), 0, mapSize - 1, false);
+
+ mutateMap(map, 0, mapSize - 1);
+ check(map, 0, mapSize - 1, true);
+ check(map.descendingMap(), 0, mapSize - 1, false);
+
+ bashSubMap(map.subMap(0, true, mapSize, false),
+ 0, mapSize - 1, true);
+ }
+
+ static NavigableMap<Integer, Integer> newMap(Class cl) throws Exception {
+ NavigableMap<Integer, Integer> result =
+ (NavigableMap<Integer, Integer>) cl.newInstance();
+ assertEquals(result.size(), 0);
+ assertFalse(result.keySet().iterator().hasNext());
+ return result;
+ }
+
+ void populate(NavigableMap<Integer, Integer> map, int limit) {
+ for (int i = 0, n = 2 * limit / 3; i < n; i++) {
+ int key = rnd.nextInt(limit);
+ put(map, key);
+ }
+ }
+
+ void mutateMap(NavigableMap<Integer, Integer> map, int min, int max) {
+ int size = map.size();
+ int rangeSize = max - min + 1;
+
+ // Remove a bunch of entries directly
+ for (int i = 0, n = rangeSize / 2; i < n; i++) {
+ remove(map, min - 5 + rnd.nextInt(rangeSize + 10));
+ }
+
+ // Remove a bunch of entries with iterator
+ for (Iterator<Integer> it = map.keySet().iterator(); it.hasNext(); ) {
+ if (rnd.nextBoolean()) {
+ bs.clear(it.next());
+ it.remove();
+ }
+ }
+
+ // Add entries till we're back to original size
+ while (map.size() < size) {
+ int key = min + rnd.nextInt(rangeSize);
+ assertTrue(key >= min && key<= max);
+ put(map, key);
+ }
+ }
+
+ void mutateSubMap(NavigableMap<Integer, Integer> map, int min, int max) {
+ int size = map.size();
+ int rangeSize = max - min + 1;
+
+ // Remove a bunch of entries directly
+ for (int i = 0, n = rangeSize / 2; i < n; i++) {
+ remove(map, min - 5 + rnd.nextInt(rangeSize + 10));
+ }
+
+ // Remove a bunch of entries with iterator
+ for (Iterator<Integer> it = map.keySet().iterator(); it.hasNext(); ) {
+ if (rnd.nextBoolean()) {
+ bs.clear(it.next());
+ it.remove();
+ }
+ }
+
+ // Add entries till we're back to original size
+ while (map.size() < size) {
+ int key = min - 5 + rnd.nextInt(rangeSize + 10);
+ if (key >= min && key<= max) {
+ put(map, key);
+ } else {
+ try {
+ map.put(key, 2 * key);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+ }
+ }
+
+ void put(NavigableMap<Integer, Integer> map, int key) {
+ if (map.put(key, 2 * key) == null)
+ bs.set(key);
+ }
+
+ void remove(NavigableMap<Integer, Integer> map, int key) {
+ if (map.remove(key) != null)
+ bs.clear(key);
+ }
+
+ void bashSubMap(NavigableMap<Integer, Integer> map,
+ int min, int max, boolean ascending) {
+ check(map, min, max, ascending);
+ check(map.descendingMap(), min, max, !ascending);
+
+ mutateSubMap(map, min, max);
+ check(map, min, max, ascending);
+ check(map.descendingMap(), min, max, !ascending);
+
+ // Recurse
+ if (max - min < 2)
+ return;
+ int midPoint = (min + max) / 2;
+
+ // headMap - pick direction and endpoint inclusion randomly
+ boolean incl = rnd.nextBoolean();
+ NavigableMap<Integer,Integer> hm = map.headMap(midPoint, incl);
+ if (ascending) {
+ if (rnd.nextBoolean())
+ bashSubMap(hm, min, midPoint - (incl ? 0 : 1), true);
+ else
+ bashSubMap(hm.descendingMap(), min, midPoint - (incl ? 0 : 1),
+ false);
+ } else {
+ if (rnd.nextBoolean())
+ bashSubMap(hm, midPoint + (incl ? 0 : 1), max, false);
+ else
+ bashSubMap(hm.descendingMap(), midPoint + (incl ? 0 : 1), max,
+ true);
+ }
+
+ // tailMap - pick direction and endpoint inclusion randomly
+ incl = rnd.nextBoolean();
+ NavigableMap<Integer,Integer> tm = map.tailMap(midPoint,incl);
+ if (ascending) {
+ if (rnd.nextBoolean())
+ bashSubMap(tm, midPoint + (incl ? 0 : 1), max, true);
+ else
+ bashSubMap(tm.descendingMap(), midPoint + (incl ? 0 : 1), max,
+ false);
+ } else {
+ if (rnd.nextBoolean()) {
+ bashSubMap(tm, min, midPoint - (incl ? 0 : 1), false);
+ } else {
+ bashSubMap(tm.descendingMap(), min, midPoint - (incl ? 0 : 1),
+ true);
+ }
+ }
+
+ // subMap - pick direction and endpoint inclusion randomly
+ int rangeSize = max - min + 1;
+ int[] endpoints = new int[2];
+ endpoints[0] = min + rnd.nextInt(rangeSize);
+ endpoints[1] = min + rnd.nextInt(rangeSize);
+ Arrays.sort(endpoints);
+ boolean lowIncl = rnd.nextBoolean();
+ boolean highIncl = rnd.nextBoolean();
+ if (ascending) {
+ NavigableMap<Integer,Integer> sm = map.subMap(
+ endpoints[0], lowIncl, endpoints[1], highIncl);
+ if (rnd.nextBoolean())
+ bashSubMap(sm, endpoints[0] + (lowIncl ? 0 : 1),
+ endpoints[1] - (highIncl ? 0 : 1), true);
+ else
+ bashSubMap(sm.descendingMap(), endpoints[0] + (lowIncl ? 0 : 1),
+ endpoints[1] - (highIncl ? 0 : 1), false);
+ } else {
+ NavigableMap<Integer,Integer> sm = map.subMap(
+ endpoints[1], highIncl, endpoints[0], lowIncl);
+ if (rnd.nextBoolean())
+ bashSubMap(sm, endpoints[0] + (lowIncl ? 0 : 1),
+ endpoints[1] - (highIncl ? 0 : 1), false);
+ else
+ bashSubMap(sm.descendingMap(), endpoints[0] + (lowIncl ? 0 : 1),
+ endpoints[1] - (highIncl ? 0 : 1), true);
+ }
+ }
+
+ /**
+ * min and max are both inclusive. If max < min, interval is empty.
+ */
+ void check(NavigableMap<Integer, Integer> map,
+ final int min, final int max, final boolean ascending) {
+ class ReferenceSet {
+ int lower(int key) {
+ return ascending ? lowerAscending(key) : higherAscending(key);
+ }
+ int floor(int key) {
+ return ascending ? floorAscending(key) : ceilingAscending(key);
+ }
+ int ceiling(int key) {
+ return ascending ? ceilingAscending(key) : floorAscending(key);
+ }
+ int higher(int key) {
+ return ascending ? higherAscending(key) : lowerAscending(key);
+ }
+ int first() {
+ return ascending ? firstAscending() : lastAscending();
+ }
+ int last() {
+ return ascending ? lastAscending() : firstAscending();
+ }
+ int lowerAscending(int key) {
+ return floorAscending(key - 1);
+ }
+ int floorAscending(int key) {
+ if (key < min)
+ return -1;
+ else if (key > max)
+ key = max;
+
+ // BitSet should support this! Test would run much faster
+ while (key >= min) {
+ if (bs.get(key))
+ return(key);
+ key--;
+ }
+ return -1;
+ }
+ int ceilingAscending(int key) {
+ if (key < min)
+ key = min;
+ else if (key > max)
+ return -1;
+ int result = bs.nextSetBit(key);
+ return result > max ? -1 : result;
+ }
+ int higherAscending(int key) {
+ return ceilingAscending(key + 1);
+ }
+ private int firstAscending() {
+ int result = ceilingAscending(min);
+ return result > max ? -1 : result;
+ }
+ private int lastAscending() {
+ int result = floorAscending(max);
+ return result < min ? -1 : result;
+ }
+ }
+ ReferenceSet rs = new ReferenceSet();
+
+ // Test contents using containsKey
+ int size = 0;
+ for (int i = min; i <= max; i++) {
+ boolean bsContainsI = bs.get(i);
+ assertEquals(bsContainsI, map.containsKey(i));
+ if (bsContainsI)
+ size++;
+ }
+ assertEquals(map.size(), size);
+
+ // Test contents using contains keySet iterator
+ int size2 = 0;
+ int previousKey = -1;
+ for (int key : map.keySet()) {
+ assertTrue(bs.get(key));
+ size2++;
+ assertTrue(previousKey < 0 ||
+ (ascending ? key - previousKey > 0 : key - previousKey < 0));
+ previousKey = key;
+ }
+ assertEquals(size2, size);
+
+ // Test navigation ops
+ for (int key = min - 1; key <= max + 1; key++) {
+ assertEq(map.lowerKey(key), rs.lower(key));
+ assertEq(map.floorKey(key), rs.floor(key));
+ assertEq(map.higherKey(key), rs.higher(key));
+ assertEq(map.ceilingKey(key), rs.ceiling(key));
+ }
+
+ // Test extrema
+ if (map.size() != 0) {
+ assertEq(map.firstKey(), rs.first());
+ assertEq(map.lastKey(), rs.last());
+ } else {
+ assertEq(rs.first(), -1);
+ assertEq(rs.last(), -1);
+ try {
+ map.firstKey();
+ shouldThrow();
+ } catch (NoSuchElementException success) {}
+ try {
+ map.lastKey();
+ shouldThrow();
+ } catch (NoSuchElementException success) {}
+ }
+ }
+
+ static void assertEq(Integer i, int j) {
+ if (i == null)
+ assertEquals(j, -1);
+ else
+ assertEquals((int) i, j);
+ }
+
+ static boolean eq(Integer i, int j) {
+ return i == null ? j == -1 : i == j;
+ }
+
+}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentSkipListSetTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentSkipListSetTest.java
new file mode 100644
index 0000000..2d03b3c
--- /dev/null
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentSkipListSetTest.java
@@ -0,0 +1,961 @@
+/*
+ * 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 tests.api.java.util.concurrent; // android-added
+
+import junit.framework.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.io.*;
+
+public class ConcurrentSkipListSetTest extends JSR166TestCase {
+ public static Test suite() {
+ return new TestSuite(ConcurrentSkipListSetTest.class);
+ }
+
+ static class MyReverseComparator implements Comparator {
+ public int compare(Object x, Object y) {
+ return ((Comparable)y).compareTo(x);
+ }
+ }
+
+ /**
+ * Create a set of given size containing consecutive
+ * Integers 0 ... n.
+ */
+ private ConcurrentSkipListSet populatedSet(int n) {
+ ConcurrentSkipListSet q = new ConcurrentSkipListSet();
+ assertTrue(q.isEmpty());
+ for (int i = n-1; i >= 0; i-=2)
+ assertTrue(q.add(new Integer(i)));
+ for (int i = (n & 1); i < n; i+=2)
+ assertTrue(q.add(new Integer(i)));
+ assertFalse(q.isEmpty());
+ assertEquals(n, q.size());
+ return q;
+ }
+
+ /**
+ * Create set of first 5 ints
+ */
+ private ConcurrentSkipListSet set5() {
+ ConcurrentSkipListSet q = new ConcurrentSkipListSet();
+ assertTrue(q.isEmpty());
+ q.add(one);
+ q.add(two);
+ q.add(three);
+ q.add(four);
+ q.add(five);
+ assertEquals(5, q.size());
+ return q;
+ }
+
+ /**
+ * A new set has unbounded capacity
+ */
+ public void testConstructor1() {
+ assertEquals(0, new ConcurrentSkipListSet().size());
+ }
+
+ /**
+ * Initializing from null Collection throws NPE
+ */
+ public void testConstructor3() {
+ try {
+ ConcurrentSkipListSet q = new ConcurrentSkipListSet((Collection)null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * Initializing from Collection of null elements throws NPE
+ */
+ public void testConstructor4() {
+ try {
+ Integer[] ints = new Integer[SIZE];
+ ConcurrentSkipListSet q = new ConcurrentSkipListSet(Arrays.asList(ints));
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * Initializing from Collection with some null elements throws NPE
+ */
+ public void testConstructor5() {
+ try {
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE-1; ++i)
+ ints[i] = new Integer(i);
+ ConcurrentSkipListSet q = new ConcurrentSkipListSet(Arrays.asList(ints));
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * Set contains all elements of collection used to initialize
+ */
+ public void testConstructor6() {
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = new Integer(i);
+ ConcurrentSkipListSet q = new ConcurrentSkipListSet(Arrays.asList(ints));
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(ints[i], q.pollFirst());
+ }
+
+ /**
+ * The comparator used in constructor is used
+ */
+ public void testConstructor7() {
+ MyReverseComparator cmp = new MyReverseComparator();
+ ConcurrentSkipListSet q = new ConcurrentSkipListSet(cmp);
+ assertEquals(cmp, q.comparator());
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = new Integer(i);
+ q.addAll(Arrays.asList(ints));
+ for (int i = SIZE-1; i >= 0; --i)
+ assertEquals(ints[i], q.pollFirst());
+ }
+
+ /**
+ * isEmpty is true before add, false after
+ */
+ public void testEmpty() {
+ ConcurrentSkipListSet q = new ConcurrentSkipListSet();
+ assertTrue(q.isEmpty());
+ q.add(new Integer(1));
+ assertFalse(q.isEmpty());
+ q.add(new Integer(2));
+ q.pollFirst();
+ q.pollFirst();
+ assertTrue(q.isEmpty());
+ }
+
+ /**
+ * size changes when elements added and removed
+ */
+ public void testSize() {
+ ConcurrentSkipListSet q = populatedSet(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(SIZE-i, q.size());
+ q.pollFirst();
+ }
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.size());
+ q.add(new Integer(i));
+ }
+ }
+
+ /**
+ * add(null) throws NPE
+ */
+ public void testAddNull() {
+ try {
+ ConcurrentSkipListSet q = new ConcurrentSkipListSet();
+ q.add(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * Add of comparable element succeeds
+ */
+ public void testAdd() {
+ ConcurrentSkipListSet q = new ConcurrentSkipListSet();
+ assertTrue(q.add(zero));
+ assertTrue(q.add(one));
+ }
+
+ /**
+ * Add of duplicate element fails
+ */
+ public void testAddDup() {
+ ConcurrentSkipListSet q = new ConcurrentSkipListSet();
+ assertTrue(q.add(zero));
+ assertFalse(q.add(zero));
+ }
+
+ /**
+ * Add of non-Comparable throws CCE
+ */
+ public void testAddNonComparable() {
+ try {
+ ConcurrentSkipListSet q = new ConcurrentSkipListSet();
+ q.add(new Object());
+ q.add(new Object());
+ q.add(new Object());
+ shouldThrow();
+ } catch (ClassCastException success) {}
+ }
+
+ /**
+ * addAll(null) throws NPE
+ */
+ public void testAddAll1() {
+ try {
+ ConcurrentSkipListSet q = new ConcurrentSkipListSet();
+ q.addAll(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+ /**
+ * addAll of a collection with null elements throws NPE
+ */
+ public void testAddAll2() {
+ try {
+ ConcurrentSkipListSet q = new ConcurrentSkipListSet();
+ 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 {
+ ConcurrentSkipListSet q = new ConcurrentSkipListSet();
+ 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) {}
+ }
+
+ /**
+ * Set contains all elements of successful addAll
+ */
+ public void testAddAll5() {
+ Integer[] empty = new Integer[0];
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = new Integer(SIZE-1-i);
+ ConcurrentSkipListSet q = new ConcurrentSkipListSet();
+ assertFalse(q.addAll(Arrays.asList(empty)));
+ assertTrue(q.addAll(Arrays.asList(ints)));
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(i, q.pollFirst());
+ }
+
+ /**
+ * pollFirst succeeds unless empty
+ */
+ public void testPollFirst() {
+ ConcurrentSkipListSet q = populatedSet(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.pollFirst());
+ }
+ assertNull(q.pollFirst());
+ }
+
+ /**
+ * pollLast succeeds unless empty
+ */
+ public void testPollLast() {
+ ConcurrentSkipListSet q = populatedSet(SIZE);
+ for (int i = SIZE-1; i >= 0; --i) {
+ assertEquals(i, q.pollLast());
+ }
+ assertNull(q.pollFirst());
+ }
+
+
+ /**
+ * remove(x) removes x and returns true if present
+ */
+ public void testRemoveElement() {
+ ConcurrentSkipListSet q = populatedSet(SIZE);
+ for (int i = 1; i < SIZE; i+=2) {
+ assertTrue(q.remove(new Integer(i)));
+ }
+ for (int i = 0; i < SIZE; i+=2) {
+ assertTrue(q.remove(new Integer(i)));
+ assertFalse(q.remove(new Integer(i+1)));
+ }
+ assertTrue(q.isEmpty());
+ }
+
+ /**
+ * contains(x) reports true when elements added but not yet removed
+ */
+ public void testContains() {
+ ConcurrentSkipListSet q = populatedSet(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertTrue(q.contains(new Integer(i)));
+ q.pollFirst();
+ assertFalse(q.contains(new Integer(i)));
+ }
+ }
+
+ /**
+ * clear removes all elements
+ */
+ public void testClear() {
+ ConcurrentSkipListSet q = populatedSet(SIZE);
+ q.clear();
+ assertTrue(q.isEmpty());
+ assertEquals(0, q.size());
+ q.add(new Integer(1));
+ assertFalse(q.isEmpty());
+ q.clear();
+ assertTrue(q.isEmpty());
+ }
+
+ /**
+ * containsAll(c) is true when c contains a subset of elements
+ */
+ public void testContainsAll() {
+ ConcurrentSkipListSet q = populatedSet(SIZE);
+ ConcurrentSkipListSet p = new ConcurrentSkipListSet();
+ for (int i = 0; i < SIZE; ++i) {
+ assertTrue(q.containsAll(p));
+ assertFalse(p.containsAll(q));
+ p.add(new Integer(i));
+ }
+ assertTrue(p.containsAll(q));
+ }
+
+ /**
+ * retainAll(c) retains only those elements of c and reports true if changed
+ */
+ public void testRetainAll() {
+ ConcurrentSkipListSet q = populatedSet(SIZE);
+ ConcurrentSkipListSet p = populatedSet(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ boolean changed = q.retainAll(p);
+ if (i == 0)
+ assertFalse(changed);
+ else
+ assertTrue(changed);
+
+ assertTrue(q.containsAll(p));
+ assertEquals(SIZE-i, q.size());
+ p.pollFirst();
+ }
+ }
+
+ /**
+ * removeAll(c) removes only those elements of c and reports true if changed
+ */
+ public void testRemoveAll() {
+ for (int i = 1; i < SIZE; ++i) {
+ ConcurrentSkipListSet q = populatedSet(SIZE);
+ ConcurrentSkipListSet p = populatedSet(i);
+ assertTrue(q.removeAll(p));
+ assertEquals(SIZE-i, q.size());
+ for (int j = 0; j < i; ++j) {
+ Integer I = (Integer)(p.pollFirst());
+ assertFalse(q.contains(I));
+ }
+ }
+ }
+
+
+
+ /**
+ * lower returns preceding element
+ */
+ public void testLower() {
+ ConcurrentSkipListSet q = set5();
+ Object e1 = q.lower(three);
+ assertEquals(two, e1);
+
+ Object e2 = q.lower(six);
+ assertEquals(five, e2);
+
+ Object e3 = q.lower(one);
+ assertNull(e3);
+
+ Object e4 = q.lower(zero);
+ assertNull(e4);
+ }
+
+ /**
+ * higher returns next element
+ */
+ public void testHigher() {
+ ConcurrentSkipListSet q = set5();
+ Object e1 = q.higher(three);
+ assertEquals(four, e1);
+
+ Object e2 = q.higher(zero);
+ assertEquals(one, e2);
+
+ Object e3 = q.higher(five);
+ assertNull(e3);
+
+ Object e4 = q.higher(six);
+ assertNull(e4);
+ }
+
+ /**
+ * floor returns preceding element
+ */
+ public void testFloor() {
+ ConcurrentSkipListSet q = set5();
+ Object e1 = q.floor(three);
+ assertEquals(three, e1);
+
+ Object e2 = q.floor(six);
+ assertEquals(five, e2);
+
+ Object e3 = q.floor(one);
+ assertEquals(one, e3);
+
+ Object e4 = q.floor(zero);
+ assertNull(e4);
+ }
+
+ /**
+ * ceiling returns next element
+ */
+ public void testCeiling() {
+ ConcurrentSkipListSet q = set5();
+ Object e1 = q.ceiling(three);
+ assertEquals(three, e1);
+
+ Object e2 = q.ceiling(zero);
+ assertEquals(one, e2);
+
+ Object e3 = q.ceiling(five);
+ assertEquals(five, e3);
+
+ Object e4 = q.ceiling(six);
+ assertNull(e4);
+ }
+
+ /**
+ * toArray contains all elements
+ */
+ public void testToArray() {
+ ConcurrentSkipListSet q = populatedSet(SIZE);
+ Object[] o = q.toArray();
+ Arrays.sort(o);
+ for (int i = 0; i < o.length; i++)
+ assertEquals(o[i], q.pollFirst());
+ }
+
+ /**
+ * toArray(a) contains all elements
+ */
+ public void testToArray2() {
+ ConcurrentSkipListSet q = populatedSet(SIZE);
+ Integer[] ints = new Integer[SIZE];
+ ints = (Integer[])q.toArray(ints);
+ Arrays.sort(ints);
+ for (int i = 0; i < ints.length; i++)
+ assertEquals(ints[i], q.pollFirst());
+ }
+
+ /**
+ * iterator iterates through all elements
+ */
+ public void testIterator() {
+ ConcurrentSkipListSet q = populatedSet(SIZE);
+ int i = 0;
+ Iterator it = q.iterator();
+ while (it.hasNext()) {
+ assertTrue(q.contains(it.next()));
+ ++i;
+ }
+ assertEquals(i, SIZE);
+ }
+
+ /**
+ * iterator of empty set has no elements
+ */
+ public void testEmptyIterator() {
+ ConcurrentSkipListSet q = new ConcurrentSkipListSet();
+ int i = 0;
+ Iterator it = q.iterator();
+ while (it.hasNext()) {
+ assertTrue(q.contains(it.next()));
+ ++i;
+ }
+ assertEquals(i, 0);
+ }
+
+ /**
+ * iterator.remove removes current element
+ */
+ public void testIteratorRemove () {
+ final ConcurrentSkipListSet q = new ConcurrentSkipListSet();
+ q.add(new Integer(2));
+ q.add(new Integer(1));
+ q.add(new Integer(3));
+
+ Iterator it = q.iterator();
+ it.next();
+ it.remove();
+
+ it = q.iterator();
+ assertEquals(it.next(), new Integer(2));
+ assertEquals(it.next(), new Integer(3));
+ assertFalse(it.hasNext());
+ }
+
+
+ /**
+ * toString contains toStrings of elements
+ */
+ public void testToString() {
+ ConcurrentSkipListSet q = populatedSet(SIZE);
+ String s = q.toString();
+ for (int i = 0; i < SIZE; ++i) {
+ assertTrue(s.indexOf(String.valueOf(i)) >= 0);
+ }
+ }
+
+ /**
+ * A deserialized serialized set has same elements
+ */
+ public void testSerialization() throws Exception {
+ ConcurrentSkipListSet q = populatedSet(SIZE);
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(q);
+ out.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ ConcurrentSkipListSet r = (ConcurrentSkipListSet)in.readObject();
+ assertEquals(q.size(), r.size());
+ while (!q.isEmpty())
+ assertEquals(q.pollFirst(), r.pollFirst());
+ }
+
+ /**
+ * subSet returns set with keys in requested range
+ */
+ public void testSubSetContents() {
+ ConcurrentSkipListSet set = set5();
+ SortedSet sm = set.subSet(two, four);
+ assertEquals(two, sm.first());
+ assertEquals(three, sm.last());
+ assertEquals(2, sm.size());
+ assertFalse(sm.contains(one));
+ assertTrue(sm.contains(two));
+ assertTrue(sm.contains(three));
+ assertFalse(sm.contains(four));
+ assertFalse(sm.contains(five));
+ Iterator i = sm.iterator();
+ Object k;
+ k = (Integer)(i.next());
+ assertEquals(two, k);
+ k = (Integer)(i.next());
+ assertEquals(three, k);
+ assertFalse(i.hasNext());
+ Iterator j = sm.iterator();
+ j.next();
+ j.remove();
+ assertFalse(set.contains(two));
+ assertEquals(4, set.size());
+ assertEquals(1, sm.size());
+ assertEquals(three, sm.first());
+ assertEquals(three, sm.last());
+ assertTrue(sm.remove(three));
+ assertTrue(sm.isEmpty());
+ assertEquals(3, set.size());
+ }
+
+ public void testSubSetContents2() {
+ ConcurrentSkipListSet set = set5();
+ SortedSet sm = set.subSet(two, three);
+ assertEquals(1, sm.size());
+ assertEquals(two, sm.first());
+ assertEquals(two, sm.last());
+ assertFalse(sm.contains(one));
+ assertTrue(sm.contains(two));
+ assertFalse(sm.contains(three));
+ assertFalse(sm.contains(four));
+ assertFalse(sm.contains(five));
+ Iterator i = sm.iterator();
+ Object k;
+ k = (Integer)(i.next());
+ assertEquals(two, k);
+ assertFalse(i.hasNext());
+ Iterator j = sm.iterator();
+ j.next();
+ j.remove();
+ assertFalse(set.contains(two));
+ assertEquals(4, set.size());
+ assertEquals(0, sm.size());
+ assertTrue(sm.isEmpty());
+ assertFalse(sm.remove(three));
+ assertEquals(4, set.size());
+ }
+
+ /**
+ * headSet returns set with keys in requested range
+ */
+ public void testHeadSetContents() {
+ ConcurrentSkipListSet set = set5();
+ SortedSet sm = set.headSet(four);
+ assertTrue(sm.contains(one));
+ assertTrue(sm.contains(two));
+ assertTrue(sm.contains(three));
+ assertFalse(sm.contains(four));
+ assertFalse(sm.contains(five));
+ Iterator i = sm.iterator();
+ Object k;
+ k = (Integer)(i.next());
+ assertEquals(one, k);
+ k = (Integer)(i.next());
+ assertEquals(two, k);
+ k = (Integer)(i.next());
+ assertEquals(three, k);
+ assertFalse(i.hasNext());
+ sm.clear();
+ assertTrue(sm.isEmpty());
+ assertEquals(2, set.size());
+ assertEquals(four, set.first());
+ }
+
+ /**
+ * tailSet returns set with keys in requested range
+ */
+ public void testTailSetContents() {
+ ConcurrentSkipListSet set = set5();
+ SortedSet sm = set.tailSet(two);
+ assertFalse(sm.contains(one));
+ assertTrue(sm.contains(two));
+ assertTrue(sm.contains(three));
+ assertTrue(sm.contains(four));
+ assertTrue(sm.contains(five));
+ Iterator i = sm.iterator();
+ Object k;
+ k = (Integer)(i.next());
+ assertEquals(two, k);
+ k = (Integer)(i.next());
+ assertEquals(three, k);
+ k = (Integer)(i.next());
+ assertEquals(four, k);
+ k = (Integer)(i.next());
+ assertEquals(five, k);
+ assertFalse(i.hasNext());
+
+ SortedSet ssm = sm.tailSet(four);
+ assertEquals(four, ssm.first());
+ assertEquals(five, ssm.last());
+ assertTrue(ssm.remove(four));
+ assertEquals(1, ssm.size());
+ assertEquals(3, sm.size());
+ assertEquals(4, set.size());
+ }
+
+ Random rnd = new Random(666);
+ BitSet bs;
+
+ /**
+ * Subsets of subsets subdivide correctly
+ */
+ public void testRecursiveSubSets() throws Exception {
+ int setSize = 1000;
+ Class cl = ConcurrentSkipListSet.class;
+
+ NavigableSet<Integer> set = newSet(cl);
+ bs = new BitSet(setSize);
+
+ populate(set, setSize);
+ check(set, 0, setSize - 1, true);
+ check(set.descendingSet(), 0, setSize - 1, false);
+
+ mutateSet(set, 0, setSize - 1);
+ check(set, 0, setSize - 1, true);
+ check(set.descendingSet(), 0, setSize - 1, false);
+
+ bashSubSet(set.subSet(0, true, setSize, false),
+ 0, setSize - 1, true);
+ }
+
+ static NavigableSet<Integer> newSet(Class cl) throws Exception {
+ NavigableSet<Integer> result = (NavigableSet<Integer>) cl.newInstance();
+ assertEquals(result.size(), 0);
+ assertFalse(result.iterator().hasNext());
+ return result;
+ }
+
+ void populate(NavigableSet<Integer> set, int limit) {
+ for (int i = 0, n = 2 * limit / 3; i < n; i++) {
+ int element = rnd.nextInt(limit);
+ put(set, element);
+ }
+ }
+
+ void mutateSet(NavigableSet<Integer> set, int min, int max) {
+ int size = set.size();
+ int rangeSize = max - min + 1;
+
+ // Remove a bunch of entries directly
+ for (int i = 0, n = rangeSize / 2; i < n; i++) {
+ remove(set, min - 5 + rnd.nextInt(rangeSize + 10));
+ }
+
+ // Remove a bunch of entries with iterator
+ for (Iterator<Integer> it = set.iterator(); it.hasNext(); ) {
+ if (rnd.nextBoolean()) {
+ bs.clear(it.next());
+ it.remove();
+ }
+ }
+
+ // Add entries till we're back to original size
+ while (set.size() < size) {
+ int element = min + rnd.nextInt(rangeSize);
+ assertTrue(element >= min && element<= max);
+ put(set, element);
+ }
+ }
+
+ void mutateSubSet(NavigableSet<Integer> set, int min, int max) {
+ int size = set.size();
+ int rangeSize = max - min + 1;
+
+ // Remove a bunch of entries directly
+ for (int i = 0, n = rangeSize / 2; i < n; i++) {
+ remove(set, min - 5 + rnd.nextInt(rangeSize + 10));
+ }
+
+ // Remove a bunch of entries with iterator
+ for (Iterator<Integer> it = set.iterator(); it.hasNext(); ) {
+ if (rnd.nextBoolean()) {
+ bs.clear(it.next());
+ it.remove();
+ }
+ }
+
+ // Add entries till we're back to original size
+ while (set.size() < size) {
+ int element = min - 5 + rnd.nextInt(rangeSize + 10);
+ if (element >= min && element<= max) {
+ put(set, element);
+ } else {
+ try {
+ set.add(element);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+ }
+ }
+
+ void put(NavigableSet<Integer> set, int element) {
+ if (set.add(element))
+ bs.set(element);
+ }
+
+ void remove(NavigableSet<Integer> set, int element) {
+ if (set.remove(element))
+ bs.clear(element);
+ }
+
+ void bashSubSet(NavigableSet<Integer> set,
+ int min, int max, boolean ascending) {
+ check(set, min, max, ascending);
+ check(set.descendingSet(), min, max, !ascending);
+
+ mutateSubSet(set, min, max);
+ check(set, min, max, ascending);
+ check(set.descendingSet(), min, max, !ascending);
+
+ // Recurse
+ if (max - min < 2)
+ return;
+ int midPoint = (min + max) / 2;
+
+ // headSet - pick direction and endpoint inclusion randomly
+ boolean incl = rnd.nextBoolean();
+ NavigableSet<Integer> hm = set.headSet(midPoint, incl);
+ if (ascending) {
+ if (rnd.nextBoolean())
+ bashSubSet(hm, min, midPoint - (incl ? 0 : 1), true);
+ else
+ bashSubSet(hm.descendingSet(), min, midPoint - (incl ? 0 : 1),
+ false);
+ } else {
+ if (rnd.nextBoolean())
+ bashSubSet(hm, midPoint + (incl ? 0 : 1), max, false);
+ else
+ bashSubSet(hm.descendingSet(), midPoint + (incl ? 0 : 1), max,
+ true);
+ }
+
+ // tailSet - pick direction and endpoint inclusion randomly
+ incl = rnd.nextBoolean();
+ NavigableSet<Integer> tm = set.tailSet(midPoint,incl);
+ if (ascending) {
+ if (rnd.nextBoolean())
+ bashSubSet(tm, midPoint + (incl ? 0 : 1), max, true);
+ else
+ bashSubSet(tm.descendingSet(), midPoint + (incl ? 0 : 1), max,
+ false);
+ } else {
+ if (rnd.nextBoolean()) {
+ bashSubSet(tm, min, midPoint - (incl ? 0 : 1), false);
+ } else {
+ bashSubSet(tm.descendingSet(), min, midPoint - (incl ? 0 : 1),
+ true);
+ }
+ }
+
+ // subSet - pick direction and endpoint inclusion randomly
+ int rangeSize = max - min + 1;
+ int[] endpoints = new int[2];
+ endpoints[0] = min + rnd.nextInt(rangeSize);
+ endpoints[1] = min + rnd.nextInt(rangeSize);
+ Arrays.sort(endpoints);
+ boolean lowIncl = rnd.nextBoolean();
+ boolean highIncl = rnd.nextBoolean();
+ if (ascending) {
+ NavigableSet<Integer> sm = set.subSet(
+ endpoints[0], lowIncl, endpoints[1], highIncl);
+ if (rnd.nextBoolean())
+ bashSubSet(sm, endpoints[0] + (lowIncl ? 0 : 1),
+ endpoints[1] - (highIncl ? 0 : 1), true);
+ else
+ bashSubSet(sm.descendingSet(), endpoints[0] + (lowIncl ? 0 : 1),
+ endpoints[1] - (highIncl ? 0 : 1), false);
+ } else {
+ NavigableSet<Integer> sm = set.subSet(
+ endpoints[1], highIncl, endpoints[0], lowIncl);
+ if (rnd.nextBoolean())
+ bashSubSet(sm, endpoints[0] + (lowIncl ? 0 : 1),
+ endpoints[1] - (highIncl ? 0 : 1), false);
+ else
+ bashSubSet(sm.descendingSet(), endpoints[0] + (lowIncl ? 0 : 1),
+ endpoints[1] - (highIncl ? 0 : 1), true);
+ }
+ }
+
+ /**
+ * min and max are both inclusive. If max < min, interval is empty.
+ */
+ void check(NavigableSet<Integer> set,
+ final int min, final int max, final boolean ascending) {
+ class ReferenceSet {
+ int lower(int element) {
+ return ascending ?
+ lowerAscending(element) : higherAscending(element);
+ }
+ int floor(int element) {
+ return ascending ?
+ floorAscending(element) : ceilingAscending(element);
+ }
+ int ceiling(int element) {
+ return ascending ?
+ ceilingAscending(element) : floorAscending(element);
+ }
+ int higher(int element) {
+ return ascending ?
+ higherAscending(element) : lowerAscending(element);
+ }
+ int first() {
+ return ascending ? firstAscending() : lastAscending();
+ }
+ int last() {
+ return ascending ? lastAscending() : firstAscending();
+ }
+ int lowerAscending(int element) {
+ return floorAscending(element - 1);
+ }
+ int floorAscending(int element) {
+ if (element < min)
+ return -1;
+ else if (element > max)
+ element = max;
+
+ // BitSet should support this! Test would run much faster
+ while (element >= min) {
+ if (bs.get(element))
+ return(element);
+ element--;
+ }
+ return -1;
+ }
+ int ceilingAscending(int element) {
+ if (element < min)
+ element = min;
+ else if (element > max)
+ return -1;
+ int result = bs.nextSetBit(element);
+ return result > max ? -1 : result;
+ }
+ int higherAscending(int element) {
+ return ceilingAscending(element + 1);
+ }
+ private int firstAscending() {
+ int result = ceilingAscending(min);
+ return result > max ? -1 : result;
+ }
+ private int lastAscending() {
+ int result = floorAscending(max);
+ return result < min ? -1 : result;
+ }
+ }
+ ReferenceSet rs = new ReferenceSet();
+
+ // Test contents using containsElement
+ int size = 0;
+ for (int i = min; i <= max; i++) {
+ boolean bsContainsI = bs.get(i);
+ assertEquals(bsContainsI, set.contains(i));
+ if (bsContainsI)
+ size++;
+ }
+ assertEquals(set.size(), size);
+
+ // Test contents using contains elementSet iterator
+ int size2 = 0;
+ int previousElement = -1;
+ for (int element : set) {
+ assertTrue(bs.get(element));
+ size2++;
+ assertTrue(previousElement < 0 || (ascending ?
+ element - previousElement > 0 : element - previousElement < 0));
+ previousElement = element;
+ }
+ assertEquals(size2, size);
+
+ // Test navigation ops
+ for (int element = min - 1; element <= max + 1; element++) {
+ assertEq(set.lower(element), rs.lower(element));
+ assertEq(set.floor(element), rs.floor(element));
+ assertEq(set.higher(element), rs.higher(element));
+ assertEq(set.ceiling(element), rs.ceiling(element));
+ }
+
+ // Test extrema
+ if (set.size() != 0) {
+ assertEq(set.first(), rs.first());
+ assertEq(set.last(), rs.last());
+ } else {
+ assertEq(rs.first(), -1);
+ assertEq(rs.last(), -1);
+ try {
+ set.first();
+ shouldThrow();
+ } catch (NoSuchElementException success) {}
+ try {
+ set.last();
+ shouldThrow();
+ } catch (NoSuchElementException success) {}
+ }
+ }
+
+ static void assertEq(Integer i, int j) {
+ if (i == null)
+ assertEquals(j, -1);
+ else
+ assertEquals((int) i, j);
+ }
+
+ static boolean eq(Integer i, int j) {
+ return i == null ? j == -1 : i == j;
+ }
+
+}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentSkipListSubMapTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentSkipListSubMapTest.java
new file mode 100644
index 0000000..fc70935
--- /dev/null
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentSkipListSubMapTest.java
@@ -0,0 +1,1438 @@
+/*
+ * 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 tests.api.java.util.concurrent; // android-added
+
+import junit.framework.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.io.*;
+
+public class ConcurrentSkipListSubMapTest extends JSR166TestCase {
+ public static Test suite() {
+ return new TestSuite(ConcurrentSkipListSubMapTest.class);
+ }
+
+ /**
+ * Create a map from Integers 1-5 to Strings "A"-"E".
+ */
+ private static ConcurrentNavigableMap map5() {
+ ConcurrentSkipListMap map = new ConcurrentSkipListMap();
+ assertTrue(map.isEmpty());
+ map.put(zero, "Z");
+ map.put(one, "A");
+ map.put(five, "E");
+ map.put(three, "C");
+ map.put(two, "B");
+ map.put(four, "D");
+ map.put(seven, "F");
+ assertFalse(map.isEmpty());
+ assertEquals(7, map.size());
+ return map.subMap(one, true, seven, false);
+ }
+
+ /**
+ * Create a map from Integers -5 to -1 to Strings "A"-"E".
+ */
+ private static ConcurrentNavigableMap dmap5() {
+ ConcurrentSkipListMap map = new ConcurrentSkipListMap();
+ assertTrue(map.isEmpty());
+ map.put(m1, "A");
+ map.put(m5, "E");
+ map.put(m3, "C");
+ map.put(m2, "B");
+ map.put(m4, "D");
+ assertFalse(map.isEmpty());
+ assertEquals(5, map.size());
+ return map.descendingMap();
+ }
+
+ private static ConcurrentNavigableMap map0() {
+ ConcurrentSkipListMap map = new ConcurrentSkipListMap();
+ assertTrue(map.isEmpty());
+ return map.tailMap(one, true);
+ }
+
+ private static ConcurrentNavigableMap dmap0() {
+ ConcurrentSkipListMap map = new ConcurrentSkipListMap();
+ assertTrue(map.isEmpty());
+ return map;
+ }
+
+ /**
+ * clear removes all pairs
+ */
+ public void testClear() {
+ ConcurrentNavigableMap map = map5();
+ map.clear();
+ assertEquals(map.size(), 0);
+ }
+
+
+ /**
+ * Maps with same contents are equal
+ */
+ public void testEquals() {
+ ConcurrentNavigableMap map1 = map5();
+ ConcurrentNavigableMap map2 = map5();
+ assertEquals(map1, map2);
+ assertEquals(map2, map1);
+ map1.clear();
+ assertFalse(map1.equals(map2));
+ assertFalse(map2.equals(map1));
+ }
+
+ /**
+ * containsKey returns true for contained key
+ */
+ public void testContainsKey() {
+ ConcurrentNavigableMap map = map5();
+ assertTrue(map.containsKey(one));
+ assertFalse(map.containsKey(zero));
+ }
+
+ /**
+ * containsValue returns true for held values
+ */
+ public void testContainsValue() {
+ ConcurrentNavigableMap map = map5();
+ assertTrue(map.containsValue("A"));
+ assertFalse(map.containsValue("Z"));
+ }
+
+ /**
+ * get returns the correct element at the given key,
+ * or null if not present
+ */
+ public void testGet() {
+ ConcurrentNavigableMap map = map5();
+ assertEquals("A", (String)map.get(one));
+ ConcurrentNavigableMap empty = map0();
+ assertNull(empty.get(one));
+ }
+
+ /**
+ * isEmpty is true of empty map and false for non-empty
+ */
+ public void testIsEmpty() {
+ ConcurrentNavigableMap empty = map0();
+ ConcurrentNavigableMap map = map5();
+ assertTrue(empty.isEmpty());
+ assertFalse(map.isEmpty());
+ }
+
+ /**
+ * firstKey returns first key
+ */
+ public void testFirstKey() {
+ ConcurrentNavigableMap map = map5();
+ assertEquals(one, map.firstKey());
+ }
+
+ /**
+ * lastKey returns last key
+ */
+ public void testLastKey() {
+ ConcurrentNavigableMap map = map5();
+ assertEquals(five, map.lastKey());
+ }
+
+
+ /**
+ * keySet returns a Set containing all the keys
+ */
+ public void testKeySet() {
+ ConcurrentNavigableMap map = map5();
+ Set s = map.keySet();
+ assertEquals(5, s.size());
+ assertTrue(s.contains(one));
+ assertTrue(s.contains(two));
+ assertTrue(s.contains(three));
+ assertTrue(s.contains(four));
+ assertTrue(s.contains(five));
+ }
+
+ /**
+ * keySet is ordered
+ */
+ public void testKeySetOrder() {
+ ConcurrentNavigableMap map = map5();
+ Set s = map.keySet();
+ Iterator i = s.iterator();
+ Integer last = (Integer)i.next();
+ assertEquals(last, one);
+ while (i.hasNext()) {
+ Integer k = (Integer)i.next();
+ assertTrue(last.compareTo(k) < 0);
+ last = k;
+ }
+ }
+
+ /**
+ * values collection contains all values
+ */
+ public void testValues() {
+ ConcurrentNavigableMap map = map5();
+ Collection s = map.values();
+ assertEquals(5, s.size());
+ assertTrue(s.contains("A"));
+ assertTrue(s.contains("B"));
+ assertTrue(s.contains("C"));
+ assertTrue(s.contains("D"));
+ assertTrue(s.contains("E"));
+ }
+
+ /**
+ * keySet.toArray returns contains all keys
+ */
+ public void testKeySetToArray() {
+ ConcurrentNavigableMap map = map5();
+ Set s = map.keySet();
+ Object[] ar = s.toArray();
+ assertTrue(s.containsAll(Arrays.asList(ar)));
+ assertEquals(5, ar.length);
+ ar[0] = m10;
+ assertFalse(s.containsAll(Arrays.asList(ar)));
+ }
+
+ /**
+ * descendingkeySet.toArray returns contains all keys
+ */
+ public void testDescendingKeySetToArray() {
+ ConcurrentNavigableMap map = map5();
+ Set s = map.descendingKeySet();
+ Object[] ar = s.toArray();
+ assertEquals(5, ar.length);
+ assertTrue(s.containsAll(Arrays.asList(ar)));
+ ar[0] = m10;
+ assertFalse(s.containsAll(Arrays.asList(ar)));
+ }
+
+ /**
+ * Values.toArray contains all values
+ */
+ public void testValuesToArray() {
+ ConcurrentNavigableMap map = map5();
+ Collection v = map.values();
+ Object[] ar = v.toArray();
+ ArrayList s = new ArrayList(Arrays.asList(ar));
+ assertEquals(5, ar.length);
+ assertTrue(s.contains("A"));
+ assertTrue(s.contains("B"));
+ assertTrue(s.contains("C"));
+ assertTrue(s.contains("D"));
+ assertTrue(s.contains("E"));
+ }
+
+
+ /**
+ * entrySet contains all pairs
+ */
+ public void testEntrySet() {
+ ConcurrentNavigableMap map = map5();
+ Set s = map.entrySet();
+ assertEquals(5, s.size());
+ Iterator it = s.iterator();
+ while (it.hasNext()) {
+ Map.Entry e = (Map.Entry) it.next();
+ assertTrue(
+ (e.getKey().equals(one) && e.getValue().equals("A")) ||
+ (e.getKey().equals(two) && e.getValue().equals("B")) ||
+ (e.getKey().equals(three) && e.getValue().equals("C")) ||
+ (e.getKey().equals(four) && e.getValue().equals("D")) ||
+ (e.getKey().equals(five) && e.getValue().equals("E")));
+ }
+ }
+
+ /**
+ * putAll adds all key-value pairs from the given map
+ */
+ public void testPutAll() {
+ ConcurrentNavigableMap empty = map0();
+ ConcurrentNavigableMap map = map5();
+ empty.putAll(map);
+ assertEquals(5, empty.size());
+ assertTrue(empty.containsKey(one));
+ assertTrue(empty.containsKey(two));
+ assertTrue(empty.containsKey(three));
+ assertTrue(empty.containsKey(four));
+ assertTrue(empty.containsKey(five));
+ }
+
+ /**
+ * putIfAbsent works when the given key is not present
+ */
+ public void testPutIfAbsent() {
+ ConcurrentNavigableMap map = map5();
+ map.putIfAbsent(six, "Z");
+ assertTrue(map.containsKey(six));
+ }
+
+ /**
+ * putIfAbsent does not add the pair if the key is already present
+ */
+ public void testPutIfAbsent2() {
+ ConcurrentNavigableMap map = map5();
+ assertEquals("A", map.putIfAbsent(one, "Z"));
+ }
+
+ /**
+ * replace fails when the given key is not present
+ */
+ public void testReplace() {
+ ConcurrentNavigableMap map = map5();
+ assertNull(map.replace(six, "Z"));
+ assertFalse(map.containsKey(six));
+ }
+
+ /**
+ * replace succeeds if the key is already present
+ */
+ public void testReplace2() {
+ ConcurrentNavigableMap map = map5();
+ assertNotNull(map.replace(one, "Z"));
+ assertEquals("Z", map.get(one));
+ }
+
+
+ /**
+ * replace value fails when the given key not mapped to expected value
+ */
+ public void testReplaceValue() {
+ ConcurrentNavigableMap map = map5();
+ assertEquals("A", map.get(one));
+ assertFalse(map.replace(one, "Z", "Z"));
+ assertEquals("A", map.get(one));
+ }
+
+ /**
+ * replace value succeeds when the given key mapped to expected value
+ */
+ public void testReplaceValue2() {
+ ConcurrentNavigableMap map = map5();
+ assertEquals("A", map.get(one));
+ assertTrue(map.replace(one, "A", "Z"));
+ assertEquals("Z", map.get(one));
+ }
+
+
+ /**
+ * remove removes the correct key-value pair from the map
+ */
+ public void testRemove() {
+ ConcurrentNavigableMap map = map5();
+ map.remove(five);
+ assertEquals(4, map.size());
+ assertFalse(map.containsKey(five));
+ }
+
+ /**
+ * remove(key,value) removes only if pair present
+ */
+ public void testRemove2() {
+ ConcurrentNavigableMap map = map5();
+ assertTrue(map.containsKey(five));
+ assertEquals("E", map.get(five));
+ map.remove(five, "E");
+ assertEquals(4, map.size());
+ assertFalse(map.containsKey(five));
+ map.remove(four, "A");
+ assertEquals(4, map.size());
+ assertTrue(map.containsKey(four));
+ }
+
+ /**
+ * lowerEntry returns preceding entry.
+ */
+ public void testLowerEntry() {
+ ConcurrentNavigableMap map = map5();
+ Map.Entry e1 = map.lowerEntry(three);
+ assertEquals(two, e1.getKey());
+
+ Map.Entry e2 = map.lowerEntry(six);
+ assertEquals(five, e2.getKey());
+
+ Map.Entry e3 = map.lowerEntry(one);
+ assertNull(e3);
+
+ Map.Entry e4 = map.lowerEntry(zero);
+ assertNull(e4);
+ }
+
+ /**
+ * higherEntry returns next entry.
+ */
+ public void testHigherEntry() {
+ ConcurrentNavigableMap map = map5();
+ Map.Entry e1 = map.higherEntry(three);
+ assertEquals(four, e1.getKey());
+
+ Map.Entry e2 = map.higherEntry(zero);
+ assertEquals(one, e2.getKey());
+
+ Map.Entry e3 = map.higherEntry(five);
+ assertNull(e3);
+
+ Map.Entry e4 = map.higherEntry(six);
+ assertNull(e4);
+ }
+
+ /**
+ * floorEntry returns preceding entry.
+ */
+ public void testFloorEntry() {
+ ConcurrentNavigableMap map = map5();
+ Map.Entry e1 = map.floorEntry(three);
+ assertEquals(three, e1.getKey());
+
+ Map.Entry e2 = map.floorEntry(six);
+ assertEquals(five, e2.getKey());
+
+ Map.Entry e3 = map.floorEntry(one);
+ assertEquals(one, e3.getKey());
+
+ Map.Entry e4 = map.floorEntry(zero);
+ assertNull(e4);
+ }
+
+ /**
+ * ceilingEntry returns next entry.
+ */
+ public void testCeilingEntry() {
+ ConcurrentNavigableMap map = map5();
+ Map.Entry e1 = map.ceilingEntry(three);
+ assertEquals(three, e1.getKey());
+
+ Map.Entry e2 = map.ceilingEntry(zero);
+ assertEquals(one, e2.getKey());
+
+ Map.Entry e3 = map.ceilingEntry(five);
+ assertEquals(five, e3.getKey());
+
+ Map.Entry e4 = map.ceilingEntry(six);
+ assertNull(e4);
+ }
+
+ /**
+ * pollFirstEntry returns entries in order
+ */
+ public void testPollFirstEntry() {
+ ConcurrentNavigableMap map = map5();
+ Map.Entry e = map.pollFirstEntry();
+ assertEquals(one, e.getKey());
+ assertEquals("A", e.getValue());
+ e = map.pollFirstEntry();
+ assertEquals(two, e.getKey());
+ map.put(one, "A");
+ e = map.pollFirstEntry();
+ assertEquals(one, e.getKey());
+ assertEquals("A", e.getValue());
+ e = map.pollFirstEntry();
+ assertEquals(three, e.getKey());
+ map.remove(four);
+ e = map.pollFirstEntry();
+ assertEquals(five, e.getKey());
+ try {
+ e.setValue("A");
+ shouldThrow();
+ } catch (UnsupportedOperationException success) {}
+ e = map.pollFirstEntry();
+ assertNull(e);
+ }
+
+ /**
+ * pollLastEntry returns entries in order
+ */
+ public void testPollLastEntry() {
+ ConcurrentNavigableMap map = map5();
+ Map.Entry e = map.pollLastEntry();
+ assertEquals(five, e.getKey());
+ assertEquals("E", e.getValue());
+ e = map.pollLastEntry();
+ assertEquals(four, e.getKey());
+ map.put(five, "E");
+ e = map.pollLastEntry();
+ assertEquals(five, e.getKey());
+ assertEquals("E", e.getValue());
+ e = map.pollLastEntry();
+ assertEquals(three, e.getKey());
+ map.remove(two);
+ e = map.pollLastEntry();
+ assertEquals(one, e.getKey());
+ try {
+ e.setValue("E");
+ shouldThrow();
+ } catch (UnsupportedOperationException success) {}
+ e = map.pollLastEntry();
+ assertNull(e);
+ }
+
+ /**
+ * size returns the correct values
+ */
+ public void testSize() {
+ ConcurrentNavigableMap map = map5();
+ ConcurrentNavigableMap empty = map0();
+ assertEquals(0, empty.size());
+ assertEquals(5, map.size());
+ }
+
+ /**
+ * toString contains toString of elements
+ */
+ public void testToString() {
+ ConcurrentNavigableMap map = map5();
+ String s = map.toString();
+ for (int i = 1; i <= 5; ++i) {
+ assertTrue(s.indexOf(String.valueOf(i)) >= 0);
+ }
+ }
+
+ // Exception tests
+
+ /**
+ * get(null) of nonempty map throws NPE
+ */
+ public void testGet_NullPointerException() {
+ try {
+ ConcurrentNavigableMap c = map5();
+ c.get(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * containsKey(null) of nonempty map throws NPE
+ */
+ public void testContainsKey_NullPointerException() {
+ try {
+ ConcurrentNavigableMap c = map5();
+ c.containsKey(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * containsValue(null) throws NPE
+ */
+ public void testContainsValue_NullPointerException() {
+ try {
+ ConcurrentNavigableMap c = map0();
+ c.containsValue(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+
+ /**
+ * put(null,x) throws NPE
+ */
+ public void testPut1_NullPointerException() {
+ try {
+ ConcurrentNavigableMap c = map5();
+ c.put(null, "whatever");
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * putIfAbsent(null, x) throws NPE
+ */
+ public void testPutIfAbsent1_NullPointerException() {
+ try {
+ ConcurrentNavigableMap c = map5();
+ c.putIfAbsent(null, "whatever");
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * replace(null, x) throws NPE
+ */
+ public void testReplace_NullPointerException() {
+ try {
+ ConcurrentNavigableMap c = map5();
+ c.replace(null, "whatever");
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * replace(null, x, y) throws NPE
+ */
+ public void testReplaceValue_NullPointerException() {
+ try {
+ ConcurrentNavigableMap c = map5();
+ c.replace(null, one, "whatever");
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * remove(null) throws NPE
+ */
+ public void testRemove1_NullPointerException() {
+ try {
+ ConcurrentNavigableMap c = map5();
+ c.remove(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * remove(null, x) throws NPE
+ */
+ public void testRemove2_NullPointerException() {
+ try {
+ ConcurrentNavigableMap c = map5();
+ c.remove(null, "whatever");
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * A deserialized map equals original
+ */
+ public void testSerialization() throws Exception {
+ ConcurrentNavigableMap q = map5();
+
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(q);
+ out.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ ConcurrentNavigableMap r = (ConcurrentNavigableMap)in.readObject();
+ assertEquals(q.size(), r.size());
+ assertTrue(q.equals(r));
+ assertTrue(r.equals(q));
+ }
+
+
+
+ /**
+ * subMap returns map with keys in requested range
+ */
+ public void testSubMapContents() {
+ ConcurrentNavigableMap map = map5();
+ SortedMap sm = map.subMap(two, four);
+ assertEquals(two, sm.firstKey());
+ assertEquals(three, sm.lastKey());
+ assertEquals(2, sm.size());
+ assertFalse(sm.containsKey(one));
+ assertTrue(sm.containsKey(two));
+ assertTrue(sm.containsKey(three));
+ assertFalse(sm.containsKey(four));
+ assertFalse(sm.containsKey(five));
+ Iterator i = sm.keySet().iterator();
+ Object k;
+ k = (Integer)(i.next());
+ assertEquals(two, k);
+ k = (Integer)(i.next());
+ assertEquals(three, k);
+ assertFalse(i.hasNext());
+ Iterator j = sm.keySet().iterator();
+ j.next();
+ j.remove();
+ assertFalse(map.containsKey(two));
+ assertEquals(4, map.size());
+ assertEquals(1, sm.size());
+ assertEquals(three, sm.firstKey());
+ assertEquals(three, sm.lastKey());
+ assertEquals("C", sm.remove(three));
+ assertTrue(sm.isEmpty());
+ assertEquals(3, map.size());
+ }
+
+ public void testSubMapContents2() {
+ ConcurrentNavigableMap map = map5();
+ SortedMap sm = map.subMap(two, three);
+ assertEquals(1, sm.size());
+ assertEquals(two, sm.firstKey());
+ assertEquals(two, sm.lastKey());
+ assertFalse(sm.containsKey(one));
+ assertTrue(sm.containsKey(two));
+ assertFalse(sm.containsKey(three));
+ assertFalse(sm.containsKey(four));
+ assertFalse(sm.containsKey(five));
+ Iterator i = sm.keySet().iterator();
+ Object k;
+ k = (Integer)(i.next());
+ assertEquals(two, k);
+ assertFalse(i.hasNext());
+ Iterator j = sm.keySet().iterator();
+ j.next();
+ j.remove();
+ assertFalse(map.containsKey(two));
+ assertEquals(4, map.size());
+ assertEquals(0, sm.size());
+ assertTrue(sm.isEmpty());
+ assertSame(sm.remove(three), null);
+ assertEquals(4, map.size());
+ }
+
+ /**
+ * headMap returns map with keys in requested range
+ */
+ public void testHeadMapContents() {
+ ConcurrentNavigableMap map = map5();
+ SortedMap sm = map.headMap(four);
+ assertTrue(sm.containsKey(one));
+ assertTrue(sm.containsKey(two));
+ assertTrue(sm.containsKey(three));
+ assertFalse(sm.containsKey(four));
+ assertFalse(sm.containsKey(five));
+ Iterator i = sm.keySet().iterator();
+ Object k;
+ k = (Integer)(i.next());
+ assertEquals(one, k);
+ k = (Integer)(i.next());
+ assertEquals(two, k);
+ k = (Integer)(i.next());
+ assertEquals(three, k);
+ assertFalse(i.hasNext());
+ sm.clear();
+ assertTrue(sm.isEmpty());
+ assertEquals(2, map.size());
+ assertEquals(four, map.firstKey());
+ }
+
+ /**
+ * headMap returns map with keys in requested range
+ */
+ public void testTailMapContents() {
+ ConcurrentNavigableMap map = map5();
+ SortedMap sm = map.tailMap(two);
+ assertFalse(sm.containsKey(one));
+ assertTrue(sm.containsKey(two));
+ assertTrue(sm.containsKey(three));
+ assertTrue(sm.containsKey(four));
+ assertTrue(sm.containsKey(five));
+ Iterator i = sm.keySet().iterator();
+ Object k;
+ k = (Integer)(i.next());
+ assertEquals(two, k);
+ k = (Integer)(i.next());
+ assertEquals(three, k);
+ k = (Integer)(i.next());
+ assertEquals(four, k);
+ k = (Integer)(i.next());
+ assertEquals(five, k);
+ assertFalse(i.hasNext());
+
+ Iterator ei = sm.entrySet().iterator();
+ Map.Entry e;
+ e = (Map.Entry)(ei.next());
+ assertEquals(two, e.getKey());
+ assertEquals("B", e.getValue());
+ e = (Map.Entry)(ei.next());
+ assertEquals(three, e.getKey());
+ assertEquals("C", e.getValue());
+ e = (Map.Entry)(ei.next());
+ assertEquals(four, e.getKey());
+ assertEquals("D", e.getValue());
+ e = (Map.Entry)(ei.next());
+ assertEquals(five, e.getKey());
+ assertEquals("E", e.getValue());
+ assertFalse(i.hasNext());
+
+ SortedMap ssm = sm.tailMap(four);
+ assertEquals(four, ssm.firstKey());
+ assertEquals(five, ssm.lastKey());
+ assertEquals("D", ssm.remove(four));
+ assertEquals(1, ssm.size());
+ assertEquals(3, sm.size());
+ assertEquals(4, map.size());
+ }
+
+ /**
+ * clear removes all pairs
+ */
+ public void testDescendingClear() {
+ ConcurrentNavigableMap map = dmap5();
+ map.clear();
+ assertEquals(map.size(), 0);
+ }
+
+
+ /**
+ * Maps with same contents are equal
+ */
+ public void testDescendingEquals() {
+ ConcurrentNavigableMap map1 = dmap5();
+ ConcurrentNavigableMap map2 = dmap5();
+ assertEquals(map1, map2);
+ assertEquals(map2, map1);
+ map1.clear();
+ assertFalse(map1.equals(map2));
+ assertFalse(map2.equals(map1));
+ }
+
+ /**
+ * containsKey returns true for contained key
+ */
+ public void testDescendingContainsKey() {
+ ConcurrentNavigableMap map = dmap5();
+ assertTrue(map.containsKey(m1));
+ assertFalse(map.containsKey(zero));
+ }
+
+ /**
+ * containsValue returns true for held values
+ */
+ public void testDescendingContainsValue() {
+ ConcurrentNavigableMap map = dmap5();
+ assertTrue(map.containsValue("A"));
+ assertFalse(map.containsValue("Z"));
+ }
+
+ /**
+ * get returns the correct element at the given key,
+ * or null if not present
+ */
+ public void testDescendingGet() {
+ ConcurrentNavigableMap map = dmap5();
+ assertEquals("A", (String)map.get(m1));
+ ConcurrentNavigableMap empty = dmap0();
+ assertNull(empty.get(m1));
+ }
+
+ /**
+ * isEmpty is true of empty map and false for non-empty
+ */
+ public void testDescendingIsEmpty() {
+ ConcurrentNavigableMap empty = dmap0();
+ ConcurrentNavigableMap map = dmap5();
+ assertTrue(empty.isEmpty());
+ assertFalse(map.isEmpty());
+ }
+
+ /**
+ * firstKey returns first key
+ */
+ public void testDescendingFirstKey() {
+ ConcurrentNavigableMap map = dmap5();
+ assertEquals(m1, map.firstKey());
+ }
+
+ /**
+ * lastKey returns last key
+ */
+ public void testDescendingLastKey() {
+ ConcurrentNavigableMap map = dmap5();
+ assertEquals(m5, map.lastKey());
+ }
+
+
+ /**
+ * keySet returns a Set containing all the keys
+ */
+ public void testDescendingKeySet() {
+ ConcurrentNavigableMap map = dmap5();
+ Set s = map.keySet();
+ assertEquals(5, s.size());
+ assertTrue(s.contains(m1));
+ assertTrue(s.contains(m2));
+ assertTrue(s.contains(m3));
+ assertTrue(s.contains(m4));
+ assertTrue(s.contains(m5));
+ }
+
+ /**
+ * keySet is ordered
+ */
+ public void testDescendingKeySetOrder() {
+ ConcurrentNavigableMap map = dmap5();
+ Set s = map.keySet();
+ Iterator i = s.iterator();
+ Integer last = (Integer)i.next();
+ assertEquals(last, m1);
+ while (i.hasNext()) {
+ Integer k = (Integer)i.next();
+ assertTrue(last.compareTo(k) > 0);
+ last = k;
+ }
+ }
+
+ /**
+ * values collection contains all values
+ */
+ public void testDescendingValues() {
+ ConcurrentNavigableMap map = dmap5();
+ Collection s = map.values();
+ assertEquals(5, s.size());
+ assertTrue(s.contains("A"));
+ assertTrue(s.contains("B"));
+ assertTrue(s.contains("C"));
+ assertTrue(s.contains("D"));
+ assertTrue(s.contains("E"));
+ }
+
+ /**
+ * keySet.toArray returns contains all keys
+ */
+ public void testDescendingAscendingKeySetToArray() {
+ ConcurrentNavigableMap map = dmap5();
+ Set s = map.keySet();
+ Object[] ar = s.toArray();
+ assertTrue(s.containsAll(Arrays.asList(ar)));
+ assertEquals(5, ar.length);
+ ar[0] = m10;
+ assertFalse(s.containsAll(Arrays.asList(ar)));
+ }
+
+ /**
+ * descendingkeySet.toArray returns contains all keys
+ */
+ public void testDescendingDescendingKeySetToArray() {
+ ConcurrentNavigableMap map = dmap5();
+ Set s = map.descendingKeySet();
+ Object[] ar = s.toArray();
+ assertEquals(5, ar.length);
+ assertTrue(s.containsAll(Arrays.asList(ar)));
+ ar[0] = m10;
+ assertFalse(s.containsAll(Arrays.asList(ar)));
+ }
+
+ /**
+ * Values.toArray contains all values
+ */
+ public void testDescendingValuesToArray() {
+ ConcurrentNavigableMap map = dmap5();
+ Collection v = map.values();
+ Object[] ar = v.toArray();
+ ArrayList s = new ArrayList(Arrays.asList(ar));
+ assertEquals(5, ar.length);
+ assertTrue(s.contains("A"));
+ assertTrue(s.contains("B"));
+ assertTrue(s.contains("C"));
+ assertTrue(s.contains("D"));
+ assertTrue(s.contains("E"));
+ }
+
+
+ /**
+ * entrySet contains all pairs
+ */
+ public void testDescendingEntrySet() {
+ ConcurrentNavigableMap map = dmap5();
+ Set s = map.entrySet();
+ assertEquals(5, s.size());
+ Iterator it = s.iterator();
+ while (it.hasNext()) {
+ Map.Entry e = (Map.Entry) it.next();
+ assertTrue(
+ (e.getKey().equals(m1) && e.getValue().equals("A")) ||
+ (e.getKey().equals(m2) && e.getValue().equals("B")) ||
+ (e.getKey().equals(m3) && e.getValue().equals("C")) ||
+ (e.getKey().equals(m4) && e.getValue().equals("D")) ||
+ (e.getKey().equals(m5) && e.getValue().equals("E")));
+ }
+ }
+
+ /**
+ * putAll adds all key-value pairs from the given map
+ */
+ public void testDescendingPutAll() {
+ ConcurrentNavigableMap empty = dmap0();
+ ConcurrentNavigableMap map = dmap5();
+ empty.putAll(map);
+ assertEquals(5, empty.size());
+ assertTrue(empty.containsKey(m1));
+ assertTrue(empty.containsKey(m2));
+ assertTrue(empty.containsKey(m3));
+ assertTrue(empty.containsKey(m4));
+ assertTrue(empty.containsKey(m5));
+ }
+
+ /**
+ * putIfAbsent works when the given key is not present
+ */
+ public void testDescendingPutIfAbsent() {
+ ConcurrentNavigableMap map = dmap5();
+ map.putIfAbsent(six, "Z");
+ assertTrue(map.containsKey(six));
+ }
+
+ /**
+ * putIfAbsent does not add the pair if the key is already present
+ */
+ public void testDescendingPutIfAbsent2() {
+ ConcurrentNavigableMap map = dmap5();
+ assertEquals("A", map.putIfAbsent(m1, "Z"));
+ }
+
+ /**
+ * replace fails when the given key is not present
+ */
+ public void testDescendingReplace() {
+ ConcurrentNavigableMap map = dmap5();
+ assertNull(map.replace(six, "Z"));
+ assertFalse(map.containsKey(six));
+ }
+
+ /**
+ * replace succeeds if the key is already present
+ */
+ public void testDescendingReplace2() {
+ ConcurrentNavigableMap map = dmap5();
+ assertNotNull(map.replace(m1, "Z"));
+ assertEquals("Z", map.get(m1));
+ }
+
+
+ /**
+ * replace value fails when the given key not mapped to expected value
+ */
+ public void testDescendingReplaceValue() {
+ ConcurrentNavigableMap map = dmap5();
+ assertEquals("A", map.get(m1));
+ assertFalse(map.replace(m1, "Z", "Z"));
+ assertEquals("A", map.get(m1));
+ }
+
+ /**
+ * replace value succeeds when the given key mapped to expected value
+ */
+ public void testDescendingReplaceValue2() {
+ ConcurrentNavigableMap map = dmap5();
+ assertEquals("A", map.get(m1));
+ assertTrue(map.replace(m1, "A", "Z"));
+ assertEquals("Z", map.get(m1));
+ }
+
+
+ /**
+ * remove removes the correct key-value pair from the map
+ */
+ public void testDescendingRemove() {
+ ConcurrentNavigableMap map = dmap5();
+ map.remove(m5);
+ assertEquals(4, map.size());
+ assertFalse(map.containsKey(m5));
+ }
+
+ /**
+ * remove(key,value) removes only if pair present
+ */
+ public void testDescendingRemove2() {
+ ConcurrentNavigableMap map = dmap5();
+ assertTrue(map.containsKey(m5));
+ assertEquals("E", map.get(m5));
+ map.remove(m5, "E");
+ assertEquals(4, map.size());
+ assertFalse(map.containsKey(m5));
+ map.remove(m4, "A");
+ assertEquals(4, map.size());
+ assertTrue(map.containsKey(m4));
+ }
+
+ /**
+ * lowerEntry returns preceding entry.
+ */
+ public void testDescendingLowerEntry() {
+ ConcurrentNavigableMap map = dmap5();
+ Map.Entry e1 = map.lowerEntry(m3);
+ assertEquals(m2, e1.getKey());
+
+ Map.Entry e2 = map.lowerEntry(m6);
+ assertEquals(m5, e2.getKey());
+
+ Map.Entry e3 = map.lowerEntry(m1);
+ assertNull(e3);
+
+ Map.Entry e4 = map.lowerEntry(zero);
+ assertNull(e4);
+ }
+
+ /**
+ * higherEntry returns next entry.
+ */
+ public void testDescendingHigherEntry() {
+ ConcurrentNavigableMap map = dmap5();
+ Map.Entry e1 = map.higherEntry(m3);
+ assertEquals(m4, e1.getKey());
+
+ Map.Entry e2 = map.higherEntry(zero);
+ assertEquals(m1, e2.getKey());
+
+ Map.Entry e3 = map.higherEntry(m5);
+ assertNull(e3);
+
+ Map.Entry e4 = map.higherEntry(m6);
+ assertNull(e4);
+ }
+
+ /**
+ * floorEntry returns preceding entry.
+ */
+ public void testDescendingFloorEntry() {
+ ConcurrentNavigableMap map = dmap5();
+ Map.Entry e1 = map.floorEntry(m3);
+ assertEquals(m3, e1.getKey());
+
+ Map.Entry e2 = map.floorEntry(m6);
+ assertEquals(m5, e2.getKey());
+
+ Map.Entry e3 = map.floorEntry(m1);
+ assertEquals(m1, e3.getKey());
+
+ Map.Entry e4 = map.floorEntry(zero);
+ assertNull(e4);
+ }
+
+ /**
+ * ceilingEntry returns next entry.
+ */
+ public void testDescendingCeilingEntry() {
+ ConcurrentNavigableMap map = dmap5();
+ Map.Entry e1 = map.ceilingEntry(m3);
+ assertEquals(m3, e1.getKey());
+
+ Map.Entry e2 = map.ceilingEntry(zero);
+ assertEquals(m1, e2.getKey());
+
+ Map.Entry e3 = map.ceilingEntry(m5);
+ assertEquals(m5, e3.getKey());
+
+ Map.Entry e4 = map.ceilingEntry(m6);
+ assertNull(e4);
+ }
+
+ /**
+ * pollFirstEntry returns entries in order
+ */
+ public void testDescendingPollFirstEntry() {
+ ConcurrentNavigableMap map = dmap5();
+ Map.Entry e = map.pollFirstEntry();
+ assertEquals(m1, e.getKey());
+ assertEquals("A", e.getValue());
+ e = map.pollFirstEntry();
+ assertEquals(m2, e.getKey());
+ map.put(m1, "A");
+ e = map.pollFirstEntry();
+ assertEquals(m1, e.getKey());
+ assertEquals("A", e.getValue());
+ e = map.pollFirstEntry();
+ assertEquals(m3, e.getKey());
+ map.remove(m4);
+ e = map.pollFirstEntry();
+ assertEquals(m5, e.getKey());
+ try {
+ e.setValue("A");
+ shouldThrow();
+ } catch (UnsupportedOperationException success) {}
+ e = map.pollFirstEntry();
+ assertNull(e);
+ }
+
+ /**
+ * pollLastEntry returns entries in order
+ */
+ public void testDescendingPollLastEntry() {
+ ConcurrentNavigableMap map = dmap5();
+ Map.Entry e = map.pollLastEntry();
+ assertEquals(m5, e.getKey());
+ assertEquals("E", e.getValue());
+ e = map.pollLastEntry();
+ assertEquals(m4, e.getKey());
+ map.put(m5, "E");
+ e = map.pollLastEntry();
+ assertEquals(m5, e.getKey());
+ assertEquals("E", e.getValue());
+ e = map.pollLastEntry();
+ assertEquals(m3, e.getKey());
+ map.remove(m2);
+ e = map.pollLastEntry();
+ assertEquals(m1, e.getKey());
+ try {
+ e.setValue("E");
+ shouldThrow();
+ } catch (UnsupportedOperationException success) {}
+ e = map.pollLastEntry();
+ assertNull(e);
+ }
+
+ /**
+ * size returns the correct values
+ */
+ public void testDescendingSize() {
+ ConcurrentNavigableMap map = dmap5();
+ ConcurrentNavigableMap empty = dmap0();
+ assertEquals(0, empty.size());
+ assertEquals(5, map.size());
+ }
+
+ /**
+ * toString contains toString of elements
+ */
+ public void testDescendingToString() {
+ ConcurrentNavigableMap map = dmap5();
+ String s = map.toString();
+ for (int i = 1; i <= 5; ++i) {
+ assertTrue(s.indexOf(String.valueOf(i)) >= 0);
+ }
+ }
+
+ // Exception testDescendings
+
+ /**
+ * get(null) of empty map throws NPE
+ */
+ public void testDescendingGet_NullPointerException() {
+ try {
+ ConcurrentNavigableMap c = dmap5();
+ c.get(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * containsKey(null) of empty map throws NPE
+ */
+ public void testDescendingContainsKey_NullPointerException() {
+ try {
+ ConcurrentNavigableMap c = dmap5();
+ c.containsKey(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * containsValue(null) throws NPE
+ */
+ public void testDescendingContainsValue_NullPointerException() {
+ try {
+ ConcurrentNavigableMap c = dmap0();
+ c.containsValue(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+
+ /**
+ * put(null,x) throws NPE
+ */
+ public void testDescendingPut1_NullPointerException() {
+ try {
+ ConcurrentNavigableMap c = dmap5();
+ c.put(null, "whatever");
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * putIfAbsent(null, x) throws NPE
+ */
+ public void testDescendingPutIfAbsent1_NullPointerException() {
+ try {
+ ConcurrentNavigableMap c = dmap5();
+ c.putIfAbsent(null, "whatever");
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * replace(null, x) throws NPE
+ */
+ public void testDescendingReplace_NullPointerException() {
+ try {
+ ConcurrentNavigableMap c = dmap5();
+ c.replace(null, "whatever");
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * replace(null, x, y) throws NPE
+ */
+ public void testDescendingReplaceValue_NullPointerException() {
+ try {
+ ConcurrentNavigableMap c = dmap5();
+ c.replace(null, m1, "whatever");
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * remove(null) throws NPE
+ */
+ public void testDescendingRemove1_NullPointerException() {
+ try {
+ ConcurrentNavigableMap c = dmap5();
+ c.remove(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * remove(null, x) throws NPE
+ */
+ public void testDescendingRemove2_NullPointerException() {
+ try {
+ ConcurrentNavigableMap c = dmap5();
+ c.remove(null, "whatever");
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * A deserialized map equals original
+ */
+ public void testDescendingSerialization() throws Exception {
+ ConcurrentNavigableMap q = dmap5();
+
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(q);
+ out.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ ConcurrentNavigableMap r = (ConcurrentNavigableMap)in.readObject();
+ assertEquals(q.size(), r.size());
+ assertTrue(q.equals(r));
+ assertTrue(r.equals(q));
+ }
+
+
+ /**
+ * subMap returns map with keys in requested range
+ */
+ public void testDescendingSubMapContents() {
+ ConcurrentNavigableMap map = dmap5();
+ SortedMap sm = map.subMap(m2, m4);
+ assertEquals(m2, sm.firstKey());
+ assertEquals(m3, sm.lastKey());
+ assertEquals(2, sm.size());
+ assertFalse(sm.containsKey(m1));
+ assertTrue(sm.containsKey(m2));
+ assertTrue(sm.containsKey(m3));
+ assertFalse(sm.containsKey(m4));
+ assertFalse(sm.containsKey(m5));
+ Iterator i = sm.keySet().iterator();
+ Object k;
+ k = (Integer)(i.next());
+ assertEquals(m2, k);
+ k = (Integer)(i.next());
+ assertEquals(m3, k);
+ assertFalse(i.hasNext());
+ Iterator j = sm.keySet().iterator();
+ j.next();
+ j.remove();
+ assertFalse(map.containsKey(m2));
+ assertEquals(4, map.size());
+ assertEquals(1, sm.size());
+ assertEquals(m3, sm.firstKey());
+ assertEquals(m3, sm.lastKey());
+ assertEquals("C", sm.remove(m3));
+ assertTrue(sm.isEmpty());
+ assertEquals(3, map.size());
+ }
+
+ public void testDescendingSubMapContents2() {
+ ConcurrentNavigableMap map = dmap5();
+ SortedMap sm = map.subMap(m2, m3);
+ assertEquals(1, sm.size());
+ assertEquals(m2, sm.firstKey());
+ assertEquals(m2, sm.lastKey());
+ assertFalse(sm.containsKey(m1));
+ assertTrue(sm.containsKey(m2));
+ assertFalse(sm.containsKey(m3));
+ assertFalse(sm.containsKey(m4));
+ assertFalse(sm.containsKey(m5));
+ Iterator i = sm.keySet().iterator();
+ Object k;
+ k = (Integer)(i.next());
+ assertEquals(m2, k);
+ assertFalse(i.hasNext());
+ Iterator j = sm.keySet().iterator();
+ j.next();
+ j.remove();
+ assertFalse(map.containsKey(m2));
+ assertEquals(4, map.size());
+ assertEquals(0, sm.size());
+ assertTrue(sm.isEmpty());
+ assertSame(sm.remove(m3), null);
+ assertEquals(4, map.size());
+ }
+
+ /**
+ * headMap returns map with keys in requested range
+ */
+ public void testDescendingHeadMapContents() {
+ ConcurrentNavigableMap map = dmap5();
+ SortedMap sm = map.headMap(m4);
+ assertTrue(sm.containsKey(m1));
+ assertTrue(sm.containsKey(m2));
+ assertTrue(sm.containsKey(m3));
+ assertFalse(sm.containsKey(m4));
+ assertFalse(sm.containsKey(m5));
+ Iterator i = sm.keySet().iterator();
+ Object k;
+ k = (Integer)(i.next());
+ assertEquals(m1, k);
+ k = (Integer)(i.next());
+ assertEquals(m2, k);
+ k = (Integer)(i.next());
+ assertEquals(m3, k);
+ assertFalse(i.hasNext());
+ sm.clear();
+ assertTrue(sm.isEmpty());
+ assertEquals(2, map.size());
+ assertEquals(m4, map.firstKey());
+ }
+
+ /**
+ * headMap returns map with keys in requested range
+ */
+ public void testDescendingTailMapContents() {
+ ConcurrentNavigableMap map = dmap5();
+ SortedMap sm = map.tailMap(m2);
+ assertFalse(sm.containsKey(m1));
+ assertTrue(sm.containsKey(m2));
+ assertTrue(sm.containsKey(m3));
+ assertTrue(sm.containsKey(m4));
+ assertTrue(sm.containsKey(m5));
+ Iterator i = sm.keySet().iterator();
+ Object k;
+ k = (Integer)(i.next());
+ assertEquals(m2, k);
+ k = (Integer)(i.next());
+ assertEquals(m3, k);
+ k = (Integer)(i.next());
+ assertEquals(m4, k);
+ k = (Integer)(i.next());
+ assertEquals(m5, k);
+ assertFalse(i.hasNext());
+
+ Iterator ei = sm.entrySet().iterator();
+ Map.Entry e;
+ e = (Map.Entry)(ei.next());
+ assertEquals(m2, e.getKey());
+ assertEquals("B", e.getValue());
+ e = (Map.Entry)(ei.next());
+ assertEquals(m3, e.getKey());
+ assertEquals("C", e.getValue());
+ e = (Map.Entry)(ei.next());
+ assertEquals(m4, e.getKey());
+ assertEquals("D", e.getValue());
+ e = (Map.Entry)(ei.next());
+ assertEquals(m5, e.getKey());
+ assertEquals("E", e.getValue());
+ assertFalse(i.hasNext());
+
+ SortedMap ssm = sm.tailMap(m4);
+ assertEquals(m4, ssm.firstKey());
+ assertEquals(m5, ssm.lastKey());
+ assertEquals("D", ssm.remove(m4));
+ assertEquals(1, ssm.size());
+ assertEquals(3, sm.size());
+ assertEquals(4, map.size());
+ }
+
+}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentSkipListSubSetTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentSkipListSubSetTest.java
new file mode 100644
index 0000000..9f0a496
--- /dev/null
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentSkipListSubSetTest.java
@@ -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 tests.api.java.util.concurrent; // android-added
+
+import junit.framework.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.io.*;
+
+public class ConcurrentSkipListSubSetTest extends JSR166TestCase {
+ public static Test suite() {
+ return new TestSuite(ConcurrentSkipListSubSetTest.class);
+ }
+
+ static class MyReverseComparator implements Comparator {
+ public int compare(Object x, Object y) {
+ return ((Comparable)y).compareTo(x);
+ }
+ }
+
+ /**
+ * Create a set of given size containing consecutive
+ * Integers 0 ... n.
+ */
+ private NavigableSet populatedSet(int n) {
+ ConcurrentSkipListSet q = new ConcurrentSkipListSet();
+ assertTrue(q.isEmpty());
+
+ for (int i = n-1; i >= 0; i-=2)
+ assertTrue(q.add(new Integer(i)));
+ for (int i = (n & 1); i < n; i+=2)
+ assertTrue(q.add(new Integer(i)));
+ assertTrue(q.add(new Integer(-n)));
+ assertTrue(q.add(new Integer(n)));
+ NavigableSet s = q.subSet(new Integer(0), true, new Integer(n), false);
+ assertFalse(s.isEmpty());
+ assertEquals(n, s.size());
+ return s;
+ }
+
+ /**
+ * Create set of first 5 ints
+ */
+ private NavigableSet set5() {
+ ConcurrentSkipListSet q = new ConcurrentSkipListSet();
+ assertTrue(q.isEmpty());
+ q.add(one);
+ q.add(two);
+ q.add(three);
+ q.add(four);
+ q.add(five);
+ q.add(zero);
+ q.add(seven);
+ NavigableSet s = q.subSet(one, true, seven, false);
+ assertEquals(5, s.size());
+ return s;
+ }
+
+ /**
+ * Create set of first 5 negative ints
+ */
+ private NavigableSet dset5() {
+ ConcurrentSkipListSet q = new ConcurrentSkipListSet();
+ assertTrue(q.isEmpty());
+ q.add(m1);
+ q.add(m2);
+ q.add(m3);
+ q.add(m4);
+ q.add(m5);
+ NavigableSet s = q.descendingSet();
+ assertEquals(5, s.size());
+ return s;
+ }
+
+ private static NavigableSet set0() {
+ ConcurrentSkipListSet set = new ConcurrentSkipListSet();
+ assertTrue(set.isEmpty());
+ return set.tailSet(m1, true);
+ }
+
+ private static NavigableSet dset0() {
+ ConcurrentSkipListSet set = new ConcurrentSkipListSet();
+ assertTrue(set.isEmpty());
+ return set;
+ }
+
+ /**
+ * A new set has unbounded capacity
+ */
+ public void testConstructor1() {
+ assertEquals(0, set0().size());
+ }
+
+
+ /**
+ * isEmpty is true before add, false after
+ */
+ public void testEmpty() {
+ NavigableSet q = set0();
+ assertTrue(q.isEmpty());
+ q.add(new Integer(1));
+ assertFalse(q.isEmpty());
+ q.add(new Integer(2));
+ q.pollFirst();
+ q.pollFirst();
+ assertTrue(q.isEmpty());
+ }
+
+ /**
+ * size changes when elements added and removed
+ */
+ public void testSize() {
+ NavigableSet q = populatedSet(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(SIZE-i, q.size());
+ q.pollFirst();
+ }
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.size());
+ q.add(new Integer(i));
+ }
+ }
+
+ /**
+ * add(null) throws NPE
+ */
+ public void testAddNull() {
+ try {
+ NavigableSet q = set0();
+ q.add(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * Add of comparable element succeeds
+ */
+ public void testAdd() {
+ NavigableSet q = set0();
+ assertTrue(q.add(six));
+ }
+
+ /**
+ * Add of duplicate element fails
+ */
+ public void testAddDup() {
+ NavigableSet q = set0();
+ assertTrue(q.add(six));
+ assertFalse(q.add(six));
+ }
+
+ /**
+ * Add of non-Comparable throws CCE
+ */
+ public void testAddNonComparable() {
+ try {
+ NavigableSet q = set0();
+ q.add(new Object());
+ q.add(new Object());
+ q.add(new Object());
+ shouldThrow();
+ } catch (ClassCastException success) {}
+ }
+
+
+ /**
+ * addAll(null) throws NPE
+ */
+ public void testAddAll1() {
+ try {
+ NavigableSet q = set0();
+ q.addAll(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+ /**
+ * addAll of a collection with null elements throws NPE
+ */
+ public void testAddAll2() {
+ try {
+ NavigableSet q = set0();
+ 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 {
+ NavigableSet q = set0();
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE-1; ++i)
+ ints[i] = new Integer(i+SIZE);
+ q.addAll(Arrays.asList(ints));
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * Set contains all elements of successful addAll
+ */
+ public void testAddAll5() {
+ Integer[] empty = new Integer[0];
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = new Integer(SIZE-1- i);
+ NavigableSet q = set0();
+ assertFalse(q.addAll(Arrays.asList(empty)));
+ assertTrue(q.addAll(Arrays.asList(ints)));
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(new Integer(i), q.pollFirst());
+ }
+
+ /**
+ * poll succeeds unless empty
+ */
+ public void testPoll() {
+ NavigableSet q = populatedSet(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.pollFirst());
+ }
+ assertNull(q.pollFirst());
+ }
+
+ /**
+ * remove(x) removes x and returns true if present
+ */
+ public void testRemoveElement() {
+ NavigableSet q = populatedSet(SIZE);
+ for (int i = 1; i < SIZE; i+=2) {
+ assertTrue(q.remove(new Integer(i)));
+ }
+ for (int i = 0; i < SIZE; i+=2) {
+ assertTrue(q.remove(new Integer(i)));
+ assertFalse(q.remove(new Integer(i+1)));
+ }
+ assertTrue(q.isEmpty());
+ }
+
+ /**
+ * contains(x) reports true when elements added but not yet removed
+ */
+ public void testContains() {
+ NavigableSet q = populatedSet(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertTrue(q.contains(new Integer(i)));
+ q.pollFirst();
+ assertFalse(q.contains(new Integer(i)));
+ }
+ }
+
+ /**
+ * clear removes all elements
+ */
+ public void testClear() {
+ NavigableSet q = populatedSet(SIZE);
+ q.clear();
+ assertTrue(q.isEmpty());
+ assertEquals(0, q.size());
+ q.add(new Integer(1));
+ assertFalse(q.isEmpty());
+ q.clear();
+ assertTrue(q.isEmpty());
+ }
+
+ /**
+ * containsAll(c) is true when c contains a subset of elements
+ */
+ public void testContainsAll() {
+ NavigableSet q = populatedSet(SIZE);
+ NavigableSet p = set0();
+ for (int i = 0; i < SIZE; ++i) {
+ assertTrue(q.containsAll(p));
+ assertFalse(p.containsAll(q));
+ p.add(new Integer(i));
+ }
+ assertTrue(p.containsAll(q));
+ }
+
+ /**
+ * retainAll(c) retains only those elements of c and reports true if changed
+ */
+ public void testRetainAll() {
+ NavigableSet q = populatedSet(SIZE);
+ NavigableSet p = populatedSet(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ boolean changed = q.retainAll(p);
+ if (i == 0)
+ assertFalse(changed);
+ else
+ assertTrue(changed);
+
+ assertTrue(q.containsAll(p));
+ assertEquals(SIZE-i, q.size());
+ p.pollFirst();
+ }
+ }
+
+ /**
+ * removeAll(c) removes only those elements of c and reports true if changed
+ */
+ public void testRemoveAll() {
+ for (int i = 1; i < SIZE; ++i) {
+ NavigableSet q = populatedSet(SIZE);
+ NavigableSet p = populatedSet(i);
+ assertTrue(q.removeAll(p));
+ assertEquals(SIZE-i, q.size());
+ for (int j = 0; j < i; ++j) {
+ Integer I = (Integer)(p.pollFirst());
+ assertFalse(q.contains(I));
+ }
+ }
+ }
+
+
+
+ /**
+ * lower returns preceding element
+ */
+ public void testLower() {
+ NavigableSet q = set5();
+ Object e1 = q.lower(three);
+ assertEquals(two, e1);
+
+ Object e2 = q.lower(six);
+ assertEquals(five, e2);
+
+ Object e3 = q.lower(one);
+ assertNull(e3);
+
+ Object e4 = q.lower(zero);
+ assertNull(e4);
+ }
+
+ /**
+ * higher returns next element
+ */
+ public void testHigher() {
+ NavigableSet q = set5();
+ Object e1 = q.higher(three);
+ assertEquals(four, e1);
+
+ Object e2 = q.higher(zero);
+ assertEquals(one, e2);
+
+ Object e3 = q.higher(five);
+ assertNull(e3);
+
+ Object e4 = q.higher(six);
+ assertNull(e4);
+ }
+
+ /**
+ * floor returns preceding element
+ */
+ public void testFloor() {
+ NavigableSet q = set5();
+ Object e1 = q.floor(three);
+ assertEquals(three, e1);
+
+ Object e2 = q.floor(six);
+ assertEquals(five, e2);
+
+ Object e3 = q.floor(one);
+ assertEquals(one, e3);
+
+ Object e4 = q.floor(zero);
+ assertNull(e4);
+ }
+
+ /**
+ * ceiling returns next element
+ */
+ public void testCeiling() {
+ NavigableSet q = set5();
+ Object e1 = q.ceiling(three);
+ assertEquals(three, e1);
+
+ Object e2 = q.ceiling(zero);
+ assertEquals(one, e2);
+
+ Object e3 = q.ceiling(five);
+ assertEquals(five, e3);
+
+ Object e4 = q.ceiling(six);
+ assertNull(e4);
+ }
+
+ /**
+ * toArray contains all elements
+ */
+ public void testToArray() {
+ NavigableSet q = populatedSet(SIZE);
+ Object[] o = q.toArray();
+ Arrays.sort(o);
+ for (int i = 0; i < o.length; i++)
+ assertEquals(o[i], q.pollFirst());
+ }
+
+ /**
+ * toArray(a) contains all elements
+ */
+ public void testToArray2() {
+ NavigableSet q = populatedSet(SIZE);
+ Integer[] ints = new Integer[SIZE];
+ ints = (Integer[])q.toArray(ints);
+ Arrays.sort(ints);
+ for (int i = 0; i < ints.length; i++)
+ assertEquals(ints[i], q.pollFirst());
+ }
+
+ /**
+ * iterator iterates through all elements
+ */
+ public void testIterator() {
+ NavigableSet q = populatedSet(SIZE);
+ int i = 0;
+ Iterator it = q.iterator();
+ while (it.hasNext()) {
+ assertTrue(q.contains(it.next()));
+ ++i;
+ }
+ assertEquals(i, SIZE);
+ }
+
+ /**
+ * iterator of empty set has no elements
+ */
+ public void testEmptyIterator() {
+ NavigableSet q = set0();
+ int i = 0;
+ Iterator it = q.iterator();
+ while (it.hasNext()) {
+ assertTrue(q.contains(it.next()));
+ ++i;
+ }
+ assertEquals(i, 0);
+ }
+
+ /**
+ * iterator.remove removes current element
+ */
+ public void testIteratorRemove () {
+ final NavigableSet q = set0();
+ q.add(new Integer(2));
+ q.add(new Integer(1));
+ q.add(new Integer(3));
+
+ Iterator it = q.iterator();
+ it.next();
+ it.remove();
+
+ it = q.iterator();
+ assertEquals(it.next(), new Integer(2));
+ assertEquals(it.next(), new Integer(3));
+ assertFalse(it.hasNext());
+ }
+
+
+ /**
+ * toString contains toStrings of elements
+ */
+ public void testToString() {
+ NavigableSet q = populatedSet(SIZE);
+ String s = q.toString();
+ for (int i = 0; i < SIZE; ++i) {
+ assertTrue(s.indexOf(String.valueOf(i)) >= 0);
+ }
+ }
+
+ /**
+ * A deserialized serialized set has same elements
+ */
+ public void testSerialization() throws Exception {
+ NavigableSet q = populatedSet(SIZE);
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(q);
+ out.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ NavigableSet r = (NavigableSet)in.readObject();
+ assertEquals(q.size(), r.size());
+ while (!q.isEmpty())
+ assertEquals(q.pollFirst(), r.pollFirst());
+ }
+
+ /**
+ * subSet returns set with keys in requested range
+ */
+ public void testSubSetContents() {
+ NavigableSet set = set5();
+ SortedSet sm = set.subSet(two, four);
+ assertEquals(two, sm.first());
+ assertEquals(three, sm.last());
+ assertEquals(2, sm.size());
+ assertFalse(sm.contains(one));
+ assertTrue(sm.contains(two));
+ assertTrue(sm.contains(three));
+ assertFalse(sm.contains(four));
+ assertFalse(sm.contains(five));
+ Iterator i = sm.iterator();
+ Object k;
+ k = (Integer)(i.next());
+ assertEquals(two, k);
+ k = (Integer)(i.next());
+ assertEquals(three, k);
+ assertFalse(i.hasNext());
+ Iterator j = sm.iterator();
+ j.next();
+ j.remove();
+ assertFalse(set.contains(two));
+ assertEquals(4, set.size());
+ assertEquals(1, sm.size());
+ assertEquals(three, sm.first());
+ assertEquals(three, sm.last());
+ assertTrue(sm.remove(three));
+ assertTrue(sm.isEmpty());
+ assertEquals(3, set.size());
+ }
+
+ public void testSubSetContents2() {
+ NavigableSet set = set5();
+ SortedSet sm = set.subSet(two, three);
+ assertEquals(1, sm.size());
+ assertEquals(two, sm.first());
+ assertEquals(two, sm.last());
+ assertFalse(sm.contains(one));
+ assertTrue(sm.contains(two));
+ assertFalse(sm.contains(three));
+ assertFalse(sm.contains(four));
+ assertFalse(sm.contains(five));
+ Iterator i = sm.iterator();
+ Object k;
+ k = (Integer)(i.next());
+ assertEquals(two, k);
+ assertFalse(i.hasNext());
+ Iterator j = sm.iterator();
+ j.next();
+ j.remove();
+ assertFalse(set.contains(two));
+ assertEquals(4, set.size());
+ assertEquals(0, sm.size());
+ assertTrue(sm.isEmpty());
+ assertFalse(sm.remove(three));
+ assertEquals(4, set.size());
+ }
+
+ /**
+ * headSet returns set with keys in requested range
+ */
+ public void testHeadSetContents() {
+ NavigableSet set = set5();
+ SortedSet sm = set.headSet(four);
+ assertTrue(sm.contains(one));
+ assertTrue(sm.contains(two));
+ assertTrue(sm.contains(three));
+ assertFalse(sm.contains(four));
+ assertFalse(sm.contains(five));
+ Iterator i = sm.iterator();
+ Object k;
+ k = (Integer)(i.next());
+ assertEquals(one, k);
+ k = (Integer)(i.next());
+ assertEquals(two, k);
+ k = (Integer)(i.next());
+ assertEquals(three, k);
+ assertFalse(i.hasNext());
+ sm.clear();
+ assertTrue(sm.isEmpty());
+ assertEquals(2, set.size());
+ assertEquals(four, set.first());
+ }
+
+ /**
+ * tailSet returns set with keys in requested range
+ */
+ public void testTailSetContents() {
+ NavigableSet set = set5();
+ SortedSet sm = set.tailSet(two);
+ assertFalse(sm.contains(one));
+ assertTrue(sm.contains(two));
+ assertTrue(sm.contains(three));
+ assertTrue(sm.contains(four));
+ assertTrue(sm.contains(five));
+ Iterator i = sm.iterator();
+ Object k;
+ k = (Integer)(i.next());
+ assertEquals(two, k);
+ k = (Integer)(i.next());
+ assertEquals(three, k);
+ k = (Integer)(i.next());
+ assertEquals(four, k);
+ k = (Integer)(i.next());
+ assertEquals(five, k);
+ assertFalse(i.hasNext());
+
+ SortedSet ssm = sm.tailSet(four);
+ assertEquals(four, ssm.first());
+ assertEquals(five, ssm.last());
+ assertTrue(ssm.remove(four));
+ assertEquals(1, ssm.size());
+ assertEquals(3, sm.size());
+ assertEquals(4, set.size());
+ }
+
+ /**
+ * size changes when elements added and removed
+ */
+ public void testDescendingSize() {
+ NavigableSet q = populatedSet(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(SIZE-i, q.size());
+ q.pollFirst();
+ }
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.size());
+ q.add(new Integer(i));
+ }
+ }
+
+ /**
+ * add(null) throws NPE
+ */
+ public void testDescendingAddNull() {
+ try {
+ NavigableSet q = dset0();
+ q.add(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * Add of comparable element succeeds
+ */
+ public void testDescendingAdd() {
+ NavigableSet q = dset0();
+ assertTrue(q.add(m6));
+ }
+
+ /**
+ * Add of duplicate element fails
+ */
+ public void testDescendingAddDup() {
+ NavigableSet q = dset0();
+ assertTrue(q.add(m6));
+ assertFalse(q.add(m6));
+ }
+
+ /**
+ * Add of non-Comparable throws CCE
+ */
+ public void testDescendingAddNonComparable() {
+ try {
+ NavigableSet q = dset0();
+ q.add(new Object());
+ q.add(new Object());
+ q.add(new Object());
+ shouldThrow();
+ } catch (ClassCastException success) {}
+ }
+
+
+ /**
+ * addAll(null) throws NPE
+ */
+ public void testDescendingAddAll1() {
+ try {
+ NavigableSet q = dset0();
+ q.addAll(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+ /**
+ * addAll of a collection with null elements throws NPE
+ */
+ public void testDescendingAddAll2() {
+ try {
+ NavigableSet q = dset0();
+ 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 testDescendingAddAll3() {
+ try {
+ NavigableSet q = dset0();
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE-1; ++i)
+ ints[i] = new Integer(i+SIZE);
+ q.addAll(Arrays.asList(ints));
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * Set contains all elements of successful addAll
+ */
+ public void testDescendingAddAll5() {
+ Integer[] empty = new Integer[0];
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = new Integer(SIZE-1- i);
+ NavigableSet q = dset0();
+ assertFalse(q.addAll(Arrays.asList(empty)));
+ assertTrue(q.addAll(Arrays.asList(ints)));
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(new Integer(i), q.pollFirst());
+ }
+
+ /**
+ * poll succeeds unless empty
+ */
+ public void testDescendingPoll() {
+ NavigableSet q = populatedSet(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.pollFirst());
+ }
+ assertNull(q.pollFirst());
+ }
+
+ /**
+ * remove(x) removes x and returns true if present
+ */
+ public void testDescendingRemoveElement() {
+ NavigableSet q = populatedSet(SIZE);
+ for (int i = 1; i < SIZE; i+=2) {
+ assertTrue(q.remove(new Integer(i)));
+ }
+ for (int i = 0; i < SIZE; i+=2) {
+ assertTrue(q.remove(new Integer(i)));
+ assertFalse(q.remove(new Integer(i+1)));
+ }
+ assertTrue(q.isEmpty());
+ }
+
+ /**
+ * contains(x) reports true when elements added but not yet removed
+ */
+ public void testDescendingContains() {
+ NavigableSet q = populatedSet(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertTrue(q.contains(new Integer(i)));
+ q.pollFirst();
+ assertFalse(q.contains(new Integer(i)));
+ }
+ }
+
+ /**
+ * clear removes all elements
+ */
+ public void testDescendingClear() {
+ NavigableSet q = populatedSet(SIZE);
+ q.clear();
+ assertTrue(q.isEmpty());
+ assertEquals(0, q.size());
+ q.add(new Integer(1));
+ assertFalse(q.isEmpty());
+ q.clear();
+ assertTrue(q.isEmpty());
+ }
+
+ /**
+ * containsAll(c) is true when c contains a subset of elements
+ */
+ public void testDescendingContainsAll() {
+ NavigableSet q = populatedSet(SIZE);
+ NavigableSet p = dset0();
+ for (int i = 0; i < SIZE; ++i) {
+ assertTrue(q.containsAll(p));
+ assertFalse(p.containsAll(q));
+ p.add(new Integer(i));
+ }
+ assertTrue(p.containsAll(q));
+ }
+
+ /**
+ * retainAll(c) retains only those elements of c and reports true if changed
+ */
+ public void testDescendingRetainAll() {
+ NavigableSet q = populatedSet(SIZE);
+ NavigableSet p = populatedSet(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ boolean changed = q.retainAll(p);
+ if (i == 0)
+ assertFalse(changed);
+ else
+ assertTrue(changed);
+
+ assertTrue(q.containsAll(p));
+ assertEquals(SIZE-i, q.size());
+ p.pollFirst();
+ }
+ }
+
+ /**
+ * removeAll(c) removes only those elements of c and reports true if changed
+ */
+ public void testDescendingRemoveAll() {
+ for (int i = 1; i < SIZE; ++i) {
+ NavigableSet q = populatedSet(SIZE);
+ NavigableSet p = populatedSet(i);
+ assertTrue(q.removeAll(p));
+ assertEquals(SIZE-i, q.size());
+ for (int j = 0; j < i; ++j) {
+ Integer I = (Integer)(p.pollFirst());
+ assertFalse(q.contains(I));
+ }
+ }
+ }
+
+
+
+ /**
+ * lower returns preceding element
+ */
+ public void testDescendingLower() {
+ NavigableSet q = dset5();
+ Object e1 = q.lower(m3);
+ assertEquals(m2, e1);
+
+ Object e2 = q.lower(m6);
+ assertEquals(m5, e2);
+
+ Object e3 = q.lower(m1);
+ assertNull(e3);
+
+ Object e4 = q.lower(zero);
+ assertNull(e4);
+ }
+
+ /**
+ * higher returns next element
+ */
+ public void testDescendingHigher() {
+ NavigableSet q = dset5();
+ Object e1 = q.higher(m3);
+ assertEquals(m4, e1);
+
+ Object e2 = q.higher(zero);
+ assertEquals(m1, e2);
+
+ Object e3 = q.higher(m5);
+ assertNull(e3);
+
+ Object e4 = q.higher(m6);
+ assertNull(e4);
+ }
+
+ /**
+ * floor returns preceding element
+ */
+ public void testDescendingFloor() {
+ NavigableSet q = dset5();
+ Object e1 = q.floor(m3);
+ assertEquals(m3, e1);
+
+ Object e2 = q.floor(m6);
+ assertEquals(m5, e2);
+
+ Object e3 = q.floor(m1);
+ assertEquals(m1, e3);
+
+ Object e4 = q.floor(zero);
+ assertNull(e4);
+ }
+
+ /**
+ * ceiling returns next element
+ */
+ public void testDescendingCeiling() {
+ NavigableSet q = dset5();
+ Object e1 = q.ceiling(m3);
+ assertEquals(m3, e1);
+
+ Object e2 = q.ceiling(zero);
+ assertEquals(m1, e2);
+
+ Object e3 = q.ceiling(m5);
+ assertEquals(m5, e3);
+
+ Object e4 = q.ceiling(m6);
+ assertNull(e4);
+ }
+
+ /**
+ * toArray contains all elements
+ */
+ public void testDescendingToArray() {
+ NavigableSet q = populatedSet(SIZE);
+ Object[] o = q.toArray();
+ Arrays.sort(o);
+ for (int i = 0; i < o.length; i++)
+ assertEquals(o[i], q.pollFirst());
+ }
+
+ /**
+ * toArray(a) contains all elements
+ */
+ public void testDescendingToArray2() {
+ NavigableSet q = populatedSet(SIZE);
+ Integer[] ints = new Integer[SIZE];
+ ints = (Integer[])q.toArray(ints);
+ Arrays.sort(ints);
+ for (int i = 0; i < ints.length; i++)
+ assertEquals(ints[i], q.pollFirst());
+ }
+
+ /**
+ * iterator iterates through all elements
+ */
+ public void testDescendingIterator() {
+ NavigableSet q = populatedSet(SIZE);
+ int i = 0;
+ Iterator it = q.iterator();
+ while (it.hasNext()) {
+ assertTrue(q.contains(it.next()));
+ ++i;
+ }
+ assertEquals(i, SIZE);
+ }
+
+ /**
+ * iterator of empty set has no elements
+ */
+ public void testDescendingEmptyIterator() {
+ NavigableSet q = dset0();
+ int i = 0;
+ Iterator it = q.iterator();
+ while (it.hasNext()) {
+ assertTrue(q.contains(it.next()));
+ ++i;
+ }
+ assertEquals(i, 0);
+ }
+
+ /**
+ * iterator.remove removes current element
+ */
+ public void testDescendingIteratorRemove () {
+ final NavigableSet q = dset0();
+ q.add(new Integer(2));
+ q.add(new Integer(1));
+ q.add(new Integer(3));
+
+ Iterator it = q.iterator();
+ it.next();
+ it.remove();
+
+ it = q.iterator();
+ assertEquals(it.next(), new Integer(2));
+ assertEquals(it.next(), new Integer(3));
+ assertFalse(it.hasNext());
+ }
+
+
+ /**
+ * toString contains toStrings of elements
+ */
+ public void testDescendingToString() {
+ NavigableSet q = populatedSet(SIZE);
+ String s = q.toString();
+ for (int i = 0; i < SIZE; ++i) {
+ assertTrue(s.indexOf(String.valueOf(i)) >= 0);
+ }
+ }
+
+ /**
+ * A deserialized serialized set has same elements
+ */
+ public void testDescendingSerialization() throws Exception {
+ NavigableSet q = populatedSet(SIZE);
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(q);
+ out.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ NavigableSet r = (NavigableSet)in.readObject();
+ assertEquals(q.size(), r.size());
+ while (!q.isEmpty())
+ assertEquals(q.pollFirst(), r.pollFirst());
+ }
+
+ /**
+ * subSet returns set with keys in requested range
+ */
+ public void testDescendingSubSetContents() {
+ NavigableSet set = dset5();
+ SortedSet sm = set.subSet(m2, m4);
+ assertEquals(m2, sm.first());
+ assertEquals(m3, sm.last());
+ assertEquals(2, sm.size());
+ assertFalse(sm.contains(m1));
+ assertTrue(sm.contains(m2));
+ assertTrue(sm.contains(m3));
+ assertFalse(sm.contains(m4));
+ assertFalse(sm.contains(m5));
+ Iterator i = sm.iterator();
+ Object k;
+ k = (Integer)(i.next());
+ assertEquals(m2, k);
+ k = (Integer)(i.next());
+ assertEquals(m3, k);
+ assertFalse(i.hasNext());
+ Iterator j = sm.iterator();
+ j.next();
+ j.remove();
+ assertFalse(set.contains(m2));
+ assertEquals(4, set.size());
+ assertEquals(1, sm.size());
+ assertEquals(m3, sm.first());
+ assertEquals(m3, sm.last());
+ assertTrue(sm.remove(m3));
+ assertTrue(sm.isEmpty());
+ assertEquals(3, set.size());
+ }
+
+ public void testDescendingSubSetContents2() {
+ NavigableSet set = dset5();
+ SortedSet sm = set.subSet(m2, m3);
+ assertEquals(1, sm.size());
+ assertEquals(m2, sm.first());
+ assertEquals(m2, sm.last());
+ assertFalse(sm.contains(m1));
+ assertTrue(sm.contains(m2));
+ assertFalse(sm.contains(m3));
+ assertFalse(sm.contains(m4));
+ assertFalse(sm.contains(m5));
+ Iterator i = sm.iterator();
+ Object k;
+ k = (Integer)(i.next());
+ assertEquals(m2, k);
+ assertFalse(i.hasNext());
+ Iterator j = sm.iterator();
+ j.next();
+ j.remove();
+ assertFalse(set.contains(m2));
+ assertEquals(4, set.size());
+ assertEquals(0, sm.size());
+ assertTrue(sm.isEmpty());
+ assertFalse(sm.remove(m3));
+ assertEquals(4, set.size());
+ }
+
+ /**
+ * headSet returns set with keys in requested range
+ */
+ public void testDescendingHeadSetContents() {
+ NavigableSet set = dset5();
+ SortedSet sm = set.headSet(m4);
+ assertTrue(sm.contains(m1));
+ assertTrue(sm.contains(m2));
+ assertTrue(sm.contains(m3));
+ assertFalse(sm.contains(m4));
+ assertFalse(sm.contains(m5));
+ Iterator i = sm.iterator();
+ Object k;
+ k = (Integer)(i.next());
+ assertEquals(m1, k);
+ k = (Integer)(i.next());
+ assertEquals(m2, k);
+ k = (Integer)(i.next());
+ assertEquals(m3, k);
+ assertFalse(i.hasNext());
+ sm.clear();
+ assertTrue(sm.isEmpty());
+ assertEquals(2, set.size());
+ assertEquals(m4, set.first());
+ }
+
+ /**
+ * tailSet returns set with keys in requested range
+ */
+ public void testDescendingTailSetContents() {
+ NavigableSet set = dset5();
+ SortedSet sm = set.tailSet(m2);
+ assertFalse(sm.contains(m1));
+ assertTrue(sm.contains(m2));
+ assertTrue(sm.contains(m3));
+ assertTrue(sm.contains(m4));
+ assertTrue(sm.contains(m5));
+ Iterator i = sm.iterator();
+ Object k;
+ k = (Integer)(i.next());
+ assertEquals(m2, k);
+ k = (Integer)(i.next());
+ assertEquals(m3, k);
+ k = (Integer)(i.next());
+ assertEquals(m4, k);
+ k = (Integer)(i.next());
+ assertEquals(m5, k);
+ assertFalse(i.hasNext());
+
+ SortedSet ssm = sm.tailSet(m4);
+ assertEquals(m4, ssm.first());
+ assertEquals(m5, ssm.last());
+ assertTrue(ssm.remove(m4));
+ assertEquals(1, ssm.size());
+ assertEquals(3, sm.size());
+ assertEquals(4, set.size());
+ }
+
+}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/CopyOnWriteArrayListTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/CopyOnWriteArrayListTest.java
index 53a1f70..90d708a 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/CopyOnWriteArrayListTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/CopyOnWriteArrayListTest.java
@@ -2,26 +2,26 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.*;
import java.util.concurrent.*;
import java.io.*;
-public class CopyOnWriteArrayListTest extends JSR166TestCase{
+public class CopyOnWriteArrayListTest extends JSR166TestCase {
public static Test suite() {
return new TestSuite(CopyOnWriteArrayListTest.class);
}
- static CopyOnWriteArrayList populatedArray(int n){
+ static CopyOnWriteArrayList populatedArray(int n) {
CopyOnWriteArrayList a = new CopyOnWriteArrayList();
assertTrue(a.isEmpty());
- for (int i = 0; i < n; ++i)
+ for (int i = 0; i < n; ++i)
a.add(new Integer(i));
assertFalse(a.isEmpty());
assertEquals(n, a.size());
@@ -45,7 +45,7 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
for (int i = 0; i < SIZE-1; ++i)
ints[i] = new Integer(i);
CopyOnWriteArrayList a = new CopyOnWriteArrayList(ints);
- for (int i = 0; i < SIZE; ++i)
+ for (int i = 0; i < SIZE; ++i)
assertEquals(ints[i], a.get(i));
}
@@ -57,10 +57,10 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
for (int i = 0; i < SIZE-1; ++i)
ints[i] = new Integer(i);
CopyOnWriteArrayList a = new CopyOnWriteArrayList(Arrays.asList(ints));
- for (int i = 0; i < SIZE; ++i)
+ for (int i = 0; i < SIZE; ++i)
assertEquals(ints[i], a.get(i));
}
-
+
/**
* addAll adds each element from the given collection
@@ -171,7 +171,7 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
assertEquals(a.hashCode(), b.hashCode());
}
-
+
/**
* containsAll returns true for collection with subset of elements
*/
@@ -186,11 +186,11 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
}
/**
- * get returns the value at the given index
+ * get returns the value at the given index
*/
public void testGet() {
CopyOnWriteArrayList full = populatedArray(3);
- assertEquals(0, ((Integer)full.get(0)).intValue());
+ assertEquals(0, full.get(0));
}
/**
@@ -223,14 +223,14 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
}
/**
- * iterator() returns an iterator containing the elements of the list
+ * iterator() returns an iterator containing the elements of the list
*/
public void testIterator() {
CopyOnWriteArrayList full = populatedArray(SIZE);
Iterator i = full.iterator();
int j;
- for(j = 0; i.hasNext(); j++)
- assertEquals(j, ((Integer)i.next()).intValue());
+ for (j = 0; i.hasNext(); j++)
+ assertEquals(j, i.next());
assertEquals(SIZE, j);
}
@@ -244,8 +244,7 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
try {
it.remove();
shouldThrow();
- }
- catch (UnsupportedOperationException success) {}
+ } catch (UnsupportedOperationException success) {}
}
/**
@@ -257,7 +256,7 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
for (int i = 0; i < 3; ++i) {
assertTrue(s.indexOf(String.valueOf(i)) >= 0);
}
- }
+ }
/**
* lastIndexOf returns the index for the given object
@@ -288,8 +287,8 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
CopyOnWriteArrayList full = populatedArray(SIZE);
ListIterator i = full.listIterator();
int j;
- for(j = 0; i.hasNext(); j++)
- assertEquals(j, ((Integer)i.next()).intValue());
+ for (j = 0; i.hasNext(); j++)
+ assertEquals(j, i.next());
assertEquals(SIZE, j);
}
@@ -300,8 +299,8 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
CopyOnWriteArrayList full = populatedArray(3);
ListIterator i = full.listIterator(1);
int j;
- for(j = 0; i.hasNext(); j++)
- assertEquals(j+1, ((Integer)i.next()).intValue());
+ for (j = 0; i.hasNext(); j++)
+ assertEquals(j+1, i.next());
assertEquals(2, j);
}
@@ -310,7 +309,7 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
*/
public void testRemove() {
CopyOnWriteArrayList full = populatedArray(3);
- assertEquals(two, full.remove(2));
+ assertEquals(2, full.remove(2));
assertEquals(2, full.size());
}
@@ -331,8 +330,8 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
*/
public void testSet() {
CopyOnWriteArrayList full = populatedArray(3);
- assertEquals(two, full.set(2, four));
- assertEquals(4, ((Integer)full.get(2)).intValue());
+ assertEquals(2, full.set(2, four));
+ assertEquals(4, full.get(2));
}
/**
@@ -352,9 +351,9 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
CopyOnWriteArrayList full = populatedArray(3);
Object[] o = full.toArray();
assertEquals(3, o.length);
- assertEquals(0, ((Integer)o[0]).intValue());
- assertEquals(1, ((Integer)o[1]).intValue());
- assertEquals(2, ((Integer)o[2]).intValue());
+ assertEquals(0, o[0]);
+ assertEquals(1, o[1]);
+ assertEquals(2, o[2]);
}
/**
@@ -378,10 +377,10 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
public void testSubList() {
CopyOnWriteArrayList a = populatedArray(10);
assertTrue(a.subList(1,1).isEmpty());
- for(int j = 0; j < 9; ++j) {
- for(int i = j ; i < 10; ++i) {
+ for (int j = 0; j < 9; ++j) {
+ for (int i = j ; i < 10; ++i) {
List b = a.subList(j,i);
- for(int k = j; k < i; ++k) {
+ for (int k = j; k < i; ++k) {
assertEquals(new Integer(k), b.get(k-j));
}
}
@@ -408,7 +407,7 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
c.add("asdadasd");
c.toArray(new Long[5]);
shouldThrow();
- } catch(ArrayStoreException e){}
+ } catch (ArrayStoreException success) {}
}
/**
@@ -419,9 +418,9 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
CopyOnWriteArrayList c = new CopyOnWriteArrayList();
c.get(-1);
shouldThrow();
- } catch(IndexOutOfBoundsException e){}
+ } catch (IndexOutOfBoundsException success) {}
}
-
+
/**
* get throws an IndexOutOfBoundsException on a too high index
*/
@@ -432,7 +431,7 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
c.add("asdad");
c.get(100);
shouldThrow();
- } catch(IndexOutOfBoundsException e){}
+ } catch (IndexOutOfBoundsException success) {}
}
/**
@@ -443,9 +442,9 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
CopyOnWriteArrayList c = new CopyOnWriteArrayList();
c.set(-1,"qwerty");
shouldThrow();
- } catch(IndexOutOfBoundsException e){}
+ } catch (IndexOutOfBoundsException success) {}
}
-
+
/**
* set throws an IndexOutOfBoundsException on a too high index
*/
@@ -456,7 +455,7 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
c.add("asdad");
c.set(100, "qwerty");
shouldThrow();
- } catch(IndexOutOfBoundsException e){}
+ } catch (IndexOutOfBoundsException success) {}
}
/**
@@ -467,9 +466,9 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
CopyOnWriteArrayList c = new CopyOnWriteArrayList();
c.add(-1,"qwerty");
shouldThrow();
- } catch(IndexOutOfBoundsException e){}
+ } catch (IndexOutOfBoundsException success) {}
}
-
+
/**
* add throws an IndexOutOfBoundsException on a too high index
*/
@@ -480,7 +479,7 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
c.add("asdasdasd");
c.add(100, "qwerty");
shouldThrow();
- } catch(IndexOutOfBoundsException e){}
+ } catch (IndexOutOfBoundsException success) {}
}
/**
@@ -491,7 +490,7 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
CopyOnWriteArrayList c = new CopyOnWriteArrayList();
c.remove(-1);
shouldThrow();
- } catch(IndexOutOfBoundsException e){}
+ } catch (IndexOutOfBoundsException success) {}
}
/**
@@ -504,9 +503,9 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
c.add("adasdasd");
c.remove(100);
shouldThrow();
- } catch(IndexOutOfBoundsException e){}
+ } catch (IndexOutOfBoundsException success) {}
}
-
+
/**
* addAll throws an IndexOutOfBoundsException on a negative index
*/
@@ -515,9 +514,9 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
CopyOnWriteArrayList c = new CopyOnWriteArrayList();
c.addAll(-1,new LinkedList());
shouldThrow();
- } catch(IndexOutOfBoundsException e){}
+ } catch (IndexOutOfBoundsException success) {}
}
-
+
/**
* addAll throws an IndexOutOfBoundsException on a too high index
*/
@@ -528,7 +527,7 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
c.add("asdasdasd");
c.addAll(100, new LinkedList());
shouldThrow();
- } catch(IndexOutOfBoundsException e){}
+ } catch (IndexOutOfBoundsException success) {}
}
/**
@@ -539,7 +538,7 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
CopyOnWriteArrayList c = new CopyOnWriteArrayList();
c.listIterator(-1);
shouldThrow();
- } catch(IndexOutOfBoundsException e){}
+ } catch (IndexOutOfBoundsException success) {}
}
/**
@@ -552,7 +551,7 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
c.add("asdasdas");
c.listIterator(100);
shouldThrow();
- } catch(IndexOutOfBoundsException e){}
+ } catch (IndexOutOfBoundsException success) {}
}
/**
@@ -562,9 +561,8 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
try {
CopyOnWriteArrayList c = new CopyOnWriteArrayList();
c.subList(-1,100);
-
shouldThrow();
- } catch(IndexOutOfBoundsException e){}
+ } catch (IndexOutOfBoundsException success) {}
}
/**
@@ -576,43 +574,38 @@ public class CopyOnWriteArrayListTest extends JSR166TestCase{
c.add("asdasd");
c.subList(1,100);
shouldThrow();
- } catch(IndexOutOfBoundsException e){}
+ } catch (IndexOutOfBoundsException success) {}
}
/**
* subList throws IndexOutOfBoundsException when the second index
- * is lower then the first
+ * is lower then the first
*/
public void testSubList3_IndexOutOfBoundsException() {
try {
CopyOnWriteArrayList c = new CopyOnWriteArrayList();
c.subList(3,1);
-
shouldThrow();
- } catch(IndexOutOfBoundsException e){}
+ } catch (IndexOutOfBoundsException success) {}
}
/**
- * a deserialized serialiszed list is equal
+ * a deserialized serialized list is equal
*/
- public void testSerialization() {
+ public void testSerialization() throws Exception {
CopyOnWriteArrayList q = populatedArray(SIZE);
- try {
- ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
- ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
- out.writeObject(q);
- out.close();
-
- ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
- ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
- CopyOnWriteArrayList r = (CopyOnWriteArrayList)in.readObject();
- assertEquals(q.size(), r.size());
- assertTrue(q.equals(r));
- assertTrue(r.equals(q));
- } catch(Exception e){
- unexpectedException();
- }
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(q);
+ out.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ CopyOnWriteArrayList r = (CopyOnWriteArrayList)in.readObject();
+ assertEquals(q.size(), r.size());
+ assertTrue(q.equals(r));
+ assertTrue(r.equals(q));
}
-
+
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/CopyOnWriteArraySetTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/CopyOnWriteArraySetTest.java
index abb33fa..c78ac50 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/CopyOnWriteArraySetTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/CopyOnWriteArraySetTest.java
@@ -2,11 +2,11 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.*;
@@ -18,10 +18,10 @@ public class CopyOnWriteArraySetTest extends JSR166TestCase {
return new TestSuite(CopyOnWriteArraySetTest.class);
}
- static CopyOnWriteArraySet populatedSet(int n){
+ static CopyOnWriteArraySet populatedSet(int n) {
CopyOnWriteArraySet a = new CopyOnWriteArraySet();
assertTrue(a.isEmpty());
- for (int i = 0; i < n; ++i)
+ for (int i = 0; i < n; ++i)
a.add(new Integer(i));
assertFalse(a.isEmpty());
assertEquals(n, a.size());
@@ -44,13 +44,13 @@ public class CopyOnWriteArraySetTest extends JSR166TestCase {
for (int i = 0; i < SIZE-1; ++i)
ints[i] = new Integer(i);
CopyOnWriteArraySet a = new CopyOnWriteArraySet(Arrays.asList(ints));
- for (int i = 0; i < SIZE; ++i)
+ for (int i = 0; i < SIZE; ++i)
assertTrue(a.contains(ints[i]));
}
-
+
/**
- * addAll adds each element from the given collection
+ * addAll adds each element from the given collection
*/
public void testAddAll() {
CopyOnWriteArraySet full = populatedSet(3);
@@ -63,7 +63,7 @@ public class CopyOnWriteArraySetTest extends JSR166TestCase {
}
/**
- * addAll adds each element from the given collection that did not
+ * addAll adds each element from the given collection that did not
* already exist in the set
*/
public void testAddAll2() {
@@ -77,7 +77,7 @@ public class CopyOnWriteArraySetTest extends JSR166TestCase {
}
/**
- * add will not add the element if it already exists in the set
+ * add will not add the element if it already exists in the set
*/
public void testAdd2() {
CopyOnWriteArraySet full = populatedSet(3);
@@ -86,8 +86,8 @@ public class CopyOnWriteArraySetTest extends JSR166TestCase {
}
/**
- * add adds the element when it does not exist
- * in the set
+ * add adds the element when it does not exist
+ * in the set
*/
public void testAdd3() {
CopyOnWriteArraySet full = populatedSet(3);
@@ -96,7 +96,7 @@ public class CopyOnWriteArraySetTest extends JSR166TestCase {
}
/**
- * clear removes all elements from the set
+ * clear removes all elements from the set
*/
public void testClear() {
CopyOnWriteArraySet full = populatedSet(3);
@@ -131,9 +131,9 @@ public class CopyOnWriteArraySetTest extends JSR166TestCase {
assertEquals(a.hashCode(), b.hashCode());
}
-
+
/**
- * containsAll returns true for collections with subset of elements
+ * containsAll returns true for collections with subset of elements
*/
public void testContainsAll() {
CopyOnWriteArraySet full = populatedSet(3);
@@ -146,7 +146,7 @@ public class CopyOnWriteArraySetTest extends JSR166TestCase {
}
/**
- * isEmpty is true when empty, else false
+ * isEmpty is true when empty, else false
*/
public void testIsEmpty() {
CopyOnWriteArraySet empty = new CopyOnWriteArraySet();
@@ -156,14 +156,14 @@ public class CopyOnWriteArraySetTest extends JSR166TestCase {
}
/**
- * iterator() returns an iterator containing the elements of the set
+ * iterator() returns an iterator containing the elements of the set
*/
public void testIterator() {
CopyOnWriteArraySet full = populatedSet(3);
Iterator i = full.iterator();
int j;
- for(j = 0; i.hasNext(); j++)
- assertEquals(j, ((Integer)i.next()).intValue());
+ for (j = 0; i.hasNext(); j++)
+ assertEquals(j, i.next());
assertEquals(3, j);
}
@@ -177,8 +177,7 @@ public class CopyOnWriteArraySetTest extends JSR166TestCase {
try {
it.remove();
shouldThrow();
- }
- catch (UnsupportedOperationException success) {}
+ } catch (UnsupportedOperationException success) {}
}
/**
@@ -190,11 +189,11 @@ public class CopyOnWriteArraySetTest extends JSR166TestCase {
for (int i = 0; i < 3; ++i) {
assertTrue(s.indexOf(String.valueOf(i)) >= 0);
}
- }
+ }
/**
- * removeAll removes all elements from the given collection
+ * removeAll removes all elements from the given collection
*/
public void testRemoveAll() {
CopyOnWriteArraySet full = populatedSet(3);
@@ -217,7 +216,7 @@ public class CopyOnWriteArraySetTest extends JSR166TestCase {
}
/**
- * size returns the number of elements
+ * size returns the number of elements
*/
public void testSize() {
CopyOnWriteArraySet empty = new CopyOnWriteArraySet();
@@ -227,29 +226,29 @@ public class CopyOnWriteArraySetTest extends JSR166TestCase {
}
/**
- * toArray returns an Object array containing all elements from the set
+ * toArray returns an Object array containing all elements from the set
*/
public void testToArray() {
CopyOnWriteArraySet full = populatedSet(3);
Object[] o = full.toArray();
assertEquals(3, o.length);
- assertEquals(0, ((Integer)o[0]).intValue());
- assertEquals(1, ((Integer)o[1]).intValue());
- assertEquals(2, ((Integer)o[2]).intValue());
+ assertEquals(0, o[0]);
+ assertEquals(1, o[1]);
+ assertEquals(2, o[2]);
}
/**
- * toArray returns an Integer array containing all elements from
- * the set
+ * toArray returns an Integer array containing all elements from
+ * the set
*/
public void testToArray2() {
CopyOnWriteArraySet full = populatedSet(3);
Integer[] i = new Integer[3];
i = (Integer[])full.toArray(i);
assertEquals(3, i.length);
- assertEquals(0, i[0].intValue());
- assertEquals(1, i[1].intValue());
- assertEquals(2, i[2].intValue());
+ assertEquals(0, (int) i[0]);
+ assertEquals(1, (int) i[1]);
+ assertEquals(2, (int) i[2]);
}
@@ -264,30 +263,26 @@ public class CopyOnWriteArraySetTest extends JSR166TestCase {
c.add("asdadasd");
c.toArray(new Long[5]);
shouldThrow();
- } catch(ArrayStoreException e){}
+ } catch (ArrayStoreException success) {}
}
/**
* A deserialized serialized set is equal
*/
- public void testSerialization() {
+ public void testSerialization() throws Exception {
CopyOnWriteArraySet q = populatedSet(SIZE);
- try {
- ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
- ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
- out.writeObject(q);
- out.close();
-
- ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
- ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
- CopyOnWriteArraySet r = (CopyOnWriteArraySet)in.readObject();
- assertEquals(q.size(), r.size());
- assertTrue(q.equals(r));
- assertTrue(r.equals(q));
- } catch(Exception e){
- unexpectedException();
- }
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(q);
+ out.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ CopyOnWriteArraySet r = (CopyOnWriteArraySet)in.readObject();
+ assertEquals(q.size(), r.size());
+ assertTrue(q.equals(r));
+ assertTrue(r.equals(q));
}
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/CountDownLatchTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/CountDownLatchTest.java
index 179c81e..b06004e 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/CountDownLatchTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/CountDownLatchTest.java
@@ -2,15 +2,16 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.*;
import java.util.concurrent.*;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
public class CountDownLatchTest extends JSR166TestCase {
public static Test suite() {
@@ -24,7 +25,7 @@ public class CountDownLatchTest extends JSR166TestCase {
try {
new CountDownLatch(-1);
shouldThrow();
- } catch(IllegalArgumentException success){}
+ } catch (IllegalArgumentException success) {}
}
/**
@@ -52,137 +53,99 @@ public class CountDownLatchTest extends JSR166TestCase {
/**
* await returns after countDown to zero, but not before
*/
- public void testAwait() {
+ public void testAwait() throws InterruptedException {
final CountDownLatch l = new CountDownLatch(2);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- threadAssertTrue(l.getCount() > 0);
- l.await();
- threadAssertTrue(l.getCount() == 0);
- } catch(InterruptedException e){
- threadUnexpectedException();
- }
- }
- });
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ threadAssertTrue(l.getCount() > 0);
+ l.await();
+ threadAssertTrue(l.getCount() == 0);
+ }});
+
t.start();
- try {
- assertEquals(l.getCount(), 2);
- Thread.sleep(SHORT_DELAY_MS);
- l.countDown();
- assertEquals(l.getCount(), 1);
- l.countDown();
- assertEquals(l.getCount(), 0);
- t.join();
- } catch (InterruptedException e){
- unexpectedException();
- }
+ assertEquals(l.getCount(), 2);
+ Thread.sleep(SHORT_DELAY_MS);
+ l.countDown();
+ assertEquals(l.getCount(), 1);
+ l.countDown();
+ assertEquals(l.getCount(), 0);
+ t.join();
}
-
+
/**
* timed await returns after countDown to zero
*/
- public void testTimedAwait() {
+ public void testTimedAwait() throws InterruptedException {
final CountDownLatch l = new CountDownLatch(2);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- threadAssertTrue(l.getCount() > 0);
- threadAssertTrue(l.await(SMALL_DELAY_MS, TimeUnit.MILLISECONDS));
- } catch(InterruptedException e){
- threadUnexpectedException();
- }
- }
- });
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ threadAssertTrue(l.getCount() > 0);
+ threadAssertTrue(l.await(SMALL_DELAY_MS, MILLISECONDS));
+ }});
+
t.start();
- try {
- assertEquals(l.getCount(), 2);
- Thread.sleep(SHORT_DELAY_MS);
- l.countDown();
- assertEquals(l.getCount(), 1);
- l.countDown();
- assertEquals(l.getCount(), 0);
- t.join();
- } catch (InterruptedException e){
- unexpectedException();
- }
+ assertEquals(l.getCount(), 2);
+ Thread.sleep(SHORT_DELAY_MS);
+ l.countDown();
+ assertEquals(l.getCount(), 1);
+ l.countDown();
+ assertEquals(l.getCount(), 0);
+ t.join();
}
-
+
/**
* await throws IE if interrupted before counted down
*/
- public void testAwait_InterruptedException() {
+ public void testAwait_InterruptedException() throws InterruptedException {
final CountDownLatch l = new CountDownLatch(1);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- threadAssertTrue(l.getCount() > 0);
- l.await();
- threadShouldThrow();
- } catch(InterruptedException success){}
- }
- });
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ threadAssertTrue(l.getCount() > 0);
+ l.await();
+ }});
+
t.start();
- try {
- assertEquals(l.getCount(), 1);
- t.interrupt();
- t.join();
- } catch (InterruptedException e){
- unexpectedException();
- }
+ assertEquals(l.getCount(), 1);
+ t.interrupt();
+ t.join();
}
/**
* timed await throws IE if interrupted before counted down
*/
- public void testTimedAwait_InterruptedException() {
+ public void testTimedAwait_InterruptedException() throws InterruptedException {
final CountDownLatch l = new CountDownLatch(1);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- threadAssertTrue(l.getCount() > 0);
- l.await(MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
- threadShouldThrow();
- } catch(InterruptedException success){}
- }
- });
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ threadAssertTrue(l.getCount() > 0);
+ l.await(MEDIUM_DELAY_MS, MILLISECONDS);
+ }});
+
t.start();
- try {
- Thread.sleep(SHORT_DELAY_MS);
- assertEquals(l.getCount(), 1);
- t.interrupt();
- t.join();
- } catch (InterruptedException e){
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(l.getCount(), 1);
+ t.interrupt();
+ t.join();
}
/**
* timed await times out if not counted down before timeout
*/
- public void testAwaitTimeout() {
+ public void testAwaitTimeout() throws InterruptedException {
final CountDownLatch l = new CountDownLatch(1);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- threadAssertTrue(l.getCount() > 0);
- threadAssertFalse(l.await(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- threadAssertTrue(l.getCount() > 0);
- } catch(InterruptedException ie){
- threadUnexpectedException();
- }
- }
- });
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ threadAssertTrue(l.getCount() > 0);
+ threadAssertFalse(l.await(SHORT_DELAY_MS, MILLISECONDS));
+ threadAssertTrue(l.getCount() > 0);
+ }});
+
t.start();
- try {
- assertEquals(l.getCount(), 1);
- t.join();
- } catch (InterruptedException e){
- unexpectedException();
- }
+ assertEquals(l.getCount(), 1);
+ t.join();
}
/**
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/CyclicBarrierTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/CyclicBarrierTest.java
index 3b99ef8..b8f8b24 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/CyclicBarrierTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/CyclicBarrierTest.java
@@ -2,19 +2,20 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
import java.util.concurrent.atomic.*;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
-public class CyclicBarrierTest extends JSR166TestCase{
+public class CyclicBarrierTest extends JSR166TestCase {
public static Test suite() {
return new TestSuite(CyclicBarrierTest.class);
}
@@ -23,7 +24,7 @@ public class CyclicBarrierTest extends JSR166TestCase{
private class MyAction implements Runnable {
public void run() { ++countAction; }
}
-
+
/**
* Creating with negative parties throws IAE
*/
@@ -31,7 +32,7 @@ public class CyclicBarrierTest extends JSR166TestCase{
try {
new CyclicBarrier(-1, (Runnable)null);
shouldThrow();
- } catch(IllegalArgumentException e){}
+ } catch (IllegalArgumentException success) {}
}
/**
@@ -41,7 +42,7 @@ public class CyclicBarrierTest extends JSR166TestCase{
try {
new CyclicBarrier(-1);
shouldThrow();
- } catch(IllegalArgumentException e){}
+ } catch (IllegalArgumentException success) {}
}
/**
@@ -56,65 +57,48 @@ public class CyclicBarrierTest extends JSR166TestCase{
/**
* A 1-party barrier triggers after single await
*/
- public void testSingleParty() {
- try {
- CyclicBarrier b = new CyclicBarrier(1);
- assertEquals(1, b.getParties());
- assertEquals(0, b.getNumberWaiting());
- b.await();
- b.await();
- assertEquals(0, b.getNumberWaiting());
- }
- catch(Exception e) {
- unexpectedException();
- }
+ public void testSingleParty() throws Exception {
+ CyclicBarrier b = new CyclicBarrier(1);
+ assertEquals(1, b.getParties());
+ assertEquals(0, b.getNumberWaiting());
+ b.await();
+ b.await();
+ assertEquals(0, b.getNumberWaiting());
}
-
+
/**
* The supplied barrier action is run at barrier
*/
- public void testBarrierAction() {
- try {
- countAction = 0;
- CyclicBarrier b = new CyclicBarrier(1, new MyAction());
- assertEquals(1, b.getParties());
- assertEquals(0, b.getNumberWaiting());
- b.await();
- b.await();
- assertEquals(0, b.getNumberWaiting());
- assertEquals(countAction, 2);
- }
- catch(Exception e) {
- unexpectedException();
- }
+ public void testBarrierAction() throws Exception {
+ countAction = 0;
+ CyclicBarrier b = new CyclicBarrier(1, new MyAction());
+ assertEquals(1, b.getParties());
+ assertEquals(0, b.getNumberWaiting());
+ b.await();
+ b.await();
+ assertEquals(0, b.getNumberWaiting());
+ assertEquals(countAction, 2);
}
/**
* A 2-party/thread barrier triggers after both threads invoke await
*/
- public void testTwoParties() {
+ public void testTwoParties() throws Exception {
final CyclicBarrier b = new CyclicBarrier(2);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- b.await();
- b.await();
- b.await();
- b.await();
- } catch(Exception e){
- threadUnexpectedException();
- }}});
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws Exception {
+ b.await();
+ b.await();
+ b.await();
+ b.await();
+ }});
- try {
- t.start();
- b.await();
- b.await();
- b.await();
- b.await();
- t.join();
- } catch(Exception e){
- unexpectedException();
- }
+ t.start();
+ b.await();
+ b.await();
+ b.await();
+ b.await();
+ t.join();
}
@@ -122,502 +106,320 @@ public class CyclicBarrierTest extends JSR166TestCase{
* An interruption in one party causes others waiting in await to
* throw BrokenBarrierException
*/
- public void testAwait1_Interrupted_BrokenBarrier() {
+ public void testAwait1_Interrupted_BrokenBarrier() throws Exception {
final CyclicBarrier c = new CyclicBarrier(3);
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- try {
- c.await();
- threadShouldThrow();
- } catch(InterruptedException success){}
- catch(Exception b){
- threadUnexpectedException();
- }
- }
- });
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- try {
- c.await();
- threadShouldThrow();
- } catch(BrokenBarrierException success){
- } catch(Exception i){
- threadUnexpectedException();
- }
- }
- });
- try {
- t1.start();
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- t1.interrupt();
- t1.join();
- t2.join();
- } catch(InterruptedException e){
- unexpectedException();
- }
+ Thread t1 = new ThreadShouldThrow(InterruptedException.class) {
+ public void realRun() throws Exception {
+ c.await();
+ }};
+ Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) {
+ public void realRun() throws Exception {
+ c.await();
+ }};
+
+ t1.start();
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t1.interrupt();
+ t1.join();
+ t2.join();
}
/**
* An interruption in one party causes others waiting in timed await to
* throw BrokenBarrierException
*/
- public void testAwait2_Interrupted_BrokenBarrier() {
+ public void testAwait2_Interrupted_BrokenBarrier() throws Exception {
final CyclicBarrier c = new CyclicBarrier(3);
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- try {
- c.await(LONG_DELAY_MS, TimeUnit.MILLISECONDS);
- threadShouldThrow();
- } catch(InterruptedException success){
- } catch(Exception b){
- threadUnexpectedException();
- }
- }
- });
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- try {
- c.await(LONG_DELAY_MS, TimeUnit.MILLISECONDS);
- threadShouldThrow();
- } catch(BrokenBarrierException success){
- } catch(Exception i){
- threadUnexpectedException();
- }
- }
- });
- try {
- t1.start();
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- t1.interrupt();
- t1.join();
- t2.join();
- } catch(InterruptedException e){
- unexpectedException();
- }
+ Thread t1 = new ThreadShouldThrow(InterruptedException.class) {
+ public void realRun() throws Exception {
+ c.await(LONG_DELAY_MS, MILLISECONDS);
+ }};
+ Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) {
+ public void realRun() throws Exception {
+ c.await(LONG_DELAY_MS, MILLISECONDS);
+ }};
+
+ t1.start();
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t1.interrupt();
+ t1.join();
+ t2.join();
}
-
+
/**
* A timeout in timed await throws TimeoutException
*/
- public void testAwait3_TimeOutException() {
+ public void testAwait3_TimeOutException() throws InterruptedException {
final CyclicBarrier c = new CyclicBarrier(2);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- c.await(SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
- threadShouldThrow();
- } catch(TimeoutException success){
- } catch(Exception b){
- threadUnexpectedException();
-
- }
- }
- });
- try {
- t.start();
- t.join();
- } catch(InterruptedException e){
- unexpectedException();
- }
+ Thread t = new ThreadShouldThrow(TimeoutException.class) {
+ public void realRun() throws Exception {
+ c.await(SHORT_DELAY_MS, MILLISECONDS);
+ }};
+
+ t.start();
+ t.join();
}
/**
* A timeout in one party causes others waiting in timed await to
* throw BrokenBarrierException
*/
- public void testAwait4_Timeout_BrokenBarrier() {
+ public void testAwait4_Timeout_BrokenBarrier() throws InterruptedException {
final CyclicBarrier c = new CyclicBarrier(3);
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- try {
- c.await(SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
- threadShouldThrow();
- } catch(TimeoutException success){
- } catch(Exception b){
- threadUnexpectedException();
- }
- }
- });
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- try {
- c.await(MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
- threadShouldThrow();
- } catch(BrokenBarrierException success){
- } catch(Exception i){
- threadUnexpectedException();
- }
- }
- });
- try {
- t1.start();
- t2.start();
- t1.join();
- t2.join();
- } catch(InterruptedException e){
- unexpectedException();
- }
+ Thread t1 = new ThreadShouldThrow(TimeoutException.class) {
+ public void realRun() throws Exception {
+ c.await(SHORT_DELAY_MS, MILLISECONDS);
+ }};
+ Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) {
+ public void realRun() throws Exception {
+ c.await(MEDIUM_DELAY_MS, MILLISECONDS);
+ }};
+
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
}
/**
* A timeout in one party causes others waiting in await to
* throw BrokenBarrierException
*/
- public void testAwait5_Timeout_BrokenBarrier() {
+ public void testAwait5_Timeout_BrokenBarrier() throws InterruptedException {
final CyclicBarrier c = new CyclicBarrier(3);
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- try {
- c.await(SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
- threadShouldThrow();
- } catch(TimeoutException success){
- } catch(Exception b){
- threadUnexpectedException();
- }
- }
- });
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- try {
- c.await();
- threadShouldThrow();
- } catch(BrokenBarrierException success){
- } catch(Exception i){
- threadUnexpectedException();
- }
- }
- });
- try {
- t1.start();
- t2.start();
- t1.join();
- t2.join();
- } catch(InterruptedException e){
- unexpectedException();
- }
+ Thread t1 = new ThreadShouldThrow(TimeoutException.class) {
+ public void realRun() throws Exception {
+ c.await(SHORT_DELAY_MS, MILLISECONDS);
+ }};
+ Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) {
+ public void realRun() throws Exception {
+ c.await();
+ }};
+
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
}
-
+
/**
* A reset of an active barrier causes waiting threads to throw
* BrokenBarrierException
*/
- public void testReset_BrokenBarrier() {
+ public void testReset_BrokenBarrier() throws InterruptedException {
final CyclicBarrier c = new CyclicBarrier(3);
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- try {
- c.await();
- threadShouldThrow();
- } catch(BrokenBarrierException success){}
- catch(Exception b){
- threadUnexpectedException();
- }
- }
- });
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- try {
- c.await();
- threadShouldThrow();
- } catch(BrokenBarrierException success){
- } catch(Exception i){
- threadUnexpectedException();
- }
- }
- });
- try {
- t1.start();
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- c.reset();
- t1.join();
- t2.join();
- } catch(InterruptedException e){
- unexpectedException();
- }
+ Thread t1 = new ThreadShouldThrow(BrokenBarrierException.class) {
+ public void realRun() throws Exception {
+ c.await();
+ }};
+ Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) {
+ public void realRun() throws Exception {
+ c.await();
+ }};
+
+ t1.start();
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ c.reset();
+ t1.join();
+ t2.join();
}
/**
* A reset before threads enter barrier does not throw
* BrokenBarrierException
*/
- public void testReset_NoBrokenBarrier() {
+ public void testReset_NoBrokenBarrier() throws Exception {
final CyclicBarrier c = new CyclicBarrier(3);
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- try {
- c.await();
- } catch(Exception b){
- threadUnexpectedException();
- }
- }
- });
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- try {
- c.await();
- } catch(Exception i){
- threadUnexpectedException();
- }
- }
- });
- try {
- c.reset();
- t1.start();
- t2.start();
- c.await();
- t1.join();
- t2.join();
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() throws Exception {
+ c.await();
+ }});
+ Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() throws Exception {
+ c.await();
+ }});
+
+ c.reset();
+ t1.start();
+ t2.start();
+ c.await();
+ t1.join();
+ t2.join();
}
/**
* All threads block while a barrier is broken.
*/
- public void testReset_Leakage() {
- try {
- final CyclicBarrier c = new CyclicBarrier(2);
- final AtomicBoolean done = new AtomicBoolean();
- Thread t = new Thread() {
- public void run() {
- while (!done.get()) {
- try {
- while (c.isBroken())
- c.reset();
-
- c.await();
- threadFail("await should not return");
- }
- catch (BrokenBarrierException e) {
- }
- catch (InterruptedException ie) {
- }
+ public void testReset_Leakage() throws InterruptedException {
+ final CyclicBarrier c = new CyclicBarrier(2);
+ final AtomicBoolean done = new AtomicBoolean();
+ Thread t = new Thread() {
+ public void run() {
+ while (!done.get()) {
+ try {
+ while (c.isBroken())
+ c.reset();
+
+ c.await();
+ threadFail("await should not return");
+ }
+ catch (BrokenBarrierException e) {
+ }
+ catch (InterruptedException ie) {
}
}
- };
-
- t.start();
- for( int i = 0; i < 4; i++) {
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- }
- done.set(true);
+ }
+ };
+
+ t.start();
+ for (int i = 0; i < 4; i++) {
+ Thread.sleep(SHORT_DELAY_MS);
t.interrupt();
}
- catch (Exception ex) {
- unexpectedException();
- }
+ done.set(true);
+ t.interrupt();
+ t.join();
}
/**
* Reset of a non-broken barrier does not break barrier
*/
- public void testResetWithoutBreakage() {
- try {
- final CyclicBarrier start = new CyclicBarrier(3);
- final CyclicBarrier barrier = new CyclicBarrier(3);
- for (int i = 0; i < 3; i++) {
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- try { start.await(); }
- catch (Exception ie) {
- threadFail("start barrier");
- }
- try { barrier.await(); }
- catch (Throwable thrown) {
- unexpectedException();
- }}});
-
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- try { start.await(); }
- catch (Exception ie) {
- threadFail("start barrier");
- }
- try { barrier.await(); }
- catch (Throwable thrown) {
- unexpectedException();
- }}});
-
-
- t1.start();
- t2.start();
- try { start.await(); }
- catch (Exception ie) { threadFail("start barrier"); }
- barrier.await();
- t1.join();
- t2.join();
- assertFalse(barrier.isBroken());
- assertEquals(0, barrier.getNumberWaiting());
- if (i == 1) barrier.reset();
- assertFalse(barrier.isBroken());
- assertEquals(0, barrier.getNumberWaiting());
- }
- }
- catch (Exception ex) {
- unexpectedException();
+ public void testResetWithoutBreakage() throws Exception {
+ final CyclicBarrier start = new CyclicBarrier(3);
+ final CyclicBarrier barrier = new CyclicBarrier(3);
+ for (int i = 0; i < 3; i++) {
+ Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() throws Exception {
+ start.await();
+ barrier.await();
+ }});
+
+ Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() throws Exception {
+ start.await();
+ barrier.await();
+ }});
+
+ t1.start();
+ t2.start();
+ start.await();
+ barrier.await();
+ t1.join();
+ t2.join();
+ assertFalse(barrier.isBroken());
+ assertEquals(0, barrier.getNumberWaiting());
+ if (i == 1) barrier.reset();
+ assertFalse(barrier.isBroken());
+ assertEquals(0, barrier.getNumberWaiting());
}
}
-
+
/**
* Reset of a barrier after interruption reinitializes it.
*/
- public void testResetAfterInterrupt() {
- try {
- final CyclicBarrier start = new CyclicBarrier(3);
- final CyclicBarrier barrier = new CyclicBarrier(3);
- for (int i = 0; i < 2; i++) {
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- try { start.await(); }
- catch (Exception ie) {
- threadFail("start barrier");
- }
- try { barrier.await(); }
- catch(InterruptedException ok) {}
- catch (Throwable thrown) {
- unexpectedException();
- }}});
-
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- try { start.await(); }
- catch (Exception ie) {
- threadFail("start barrier");
- }
- try { barrier.await(); }
- catch(BrokenBarrierException ok) {}
- catch (Throwable thrown) {
- unexpectedException();
- }}});
-
- t1.start();
- t2.start();
- try { start.await(); }
- catch (Exception ie) { threadFail("start barrier"); }
- t1.interrupt();
- t1.join();
- t2.join();
- assertTrue(barrier.isBroken());
- assertEquals(0, barrier.getNumberWaiting());
- barrier.reset();
- assertFalse(barrier.isBroken());
- assertEquals(0, barrier.getNumberWaiting());
- }
- }
- catch (Exception ex) {
- unexpectedException();
+ public void testResetAfterInterrupt() throws Exception {
+ final CyclicBarrier start = new CyclicBarrier(3);
+ final CyclicBarrier barrier = new CyclicBarrier(3);
+ for (int i = 0; i < 2; i++) {
+ Thread t1 = new ThreadShouldThrow(InterruptedException.class) {
+ public void realRun() throws Exception {
+ start.await();
+ barrier.await();
+ }};
+
+ Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) {
+ public void realRun() throws Exception {
+ start.await();
+ barrier.await();
+ }};
+
+ t1.start();
+ t2.start();
+ start.await();
+ t1.interrupt();
+ t1.join();
+ t2.join();
+ assertTrue(barrier.isBroken());
+ assertEquals(0, barrier.getNumberWaiting());
+ barrier.reset();
+ assertFalse(barrier.isBroken());
+ assertEquals(0, barrier.getNumberWaiting());
}
}
-
+
/**
* Reset of a barrier after timeout reinitializes it.
*/
- public void testResetAfterTimeout() {
- try {
- final CyclicBarrier start = new CyclicBarrier(3);
- final CyclicBarrier barrier = new CyclicBarrier(3);
- for (int i = 0; i < 2; i++) {
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- try { start.await(); }
- catch (Exception ie) {
- threadFail("start barrier");
- }
- try { barrier.await(MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS); }
- catch(TimeoutException ok) {}
- catch (Throwable thrown) {
- unexpectedException();
- }}});
-
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- try { start.await(); }
- catch (Exception ie) {
- threadFail("start barrier");
- }
- try { barrier.await(); }
- catch(BrokenBarrierException ok) {}
- catch (Throwable thrown) {
- unexpectedException();
- }}});
-
- t1.start();
- t2.start();
- try { start.await(); }
- catch (Exception ie) { threadFail("start barrier"); }
- t1.join();
- t2.join();
- assertTrue(barrier.isBroken());
- assertEquals(0, barrier.getNumberWaiting());
- barrier.reset();
- assertFalse(barrier.isBroken());
- assertEquals(0, barrier.getNumberWaiting());
- }
- }
- catch (Exception ex) {
- unexpectedException();
+ public void testResetAfterTimeout() throws Exception {
+ final CyclicBarrier start = new CyclicBarrier(3);
+ final CyclicBarrier barrier = new CyclicBarrier(3);
+ for (int i = 0; i < 2; i++) {
+ Thread t1 = new ThreadShouldThrow(TimeoutException.class) {
+ public void realRun() throws Exception {
+ start.await();
+ barrier.await(MEDIUM_DELAY_MS, MILLISECONDS);
+ }};
+
+ Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) {
+ public void realRun() throws Exception {
+ start.await();
+ barrier.await();
+ }};
+
+ t1.start();
+ t2.start();
+ start.await();
+ t1.join();
+ t2.join();
+ assertTrue(barrier.isBroken());
+ assertEquals(0, barrier.getNumberWaiting());
+ barrier.reset();
+ assertFalse(barrier.isBroken());
+ assertEquals(0, barrier.getNumberWaiting());
}
}
-
+
/**
* Reset of a barrier after a failed command reinitializes it.
*/
- public void testResetAfterCommandException() {
- try {
- final CyclicBarrier start = new CyclicBarrier(3);
- final CyclicBarrier barrier =
- new CyclicBarrier(3, new Runnable() {
- public void run() {
- throw new NullPointerException(); }});
- for (int i = 0; i < 2; i++) {
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- try { start.await(); }
- catch (Exception ie) {
- threadFail("start barrier");
- }
- try { barrier.await(); }
- catch(BrokenBarrierException ok) {}
- catch (Throwable thrown) {
- unexpectedException();
- }}});
-
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- try { start.await(); }
- catch (Exception ie) {
- threadFail("start barrier");
- }
- try { barrier.await(); }
- catch(BrokenBarrierException ok) {}
- catch (Throwable thrown) {
- unexpectedException();
- }}});
-
- t1.start();
- t2.start();
- try { start.await(); }
- catch (Exception ie) { threadFail("start barrier"); }
- while (barrier.getNumberWaiting() < 2) { Thread.yield(); }
- try { barrier.await(); }
- catch (Exception ok) { }
- t1.join();
- t2.join();
- assertTrue(barrier.isBroken());
- assertEquals(0, barrier.getNumberWaiting());
- barrier.reset();
- assertFalse(barrier.isBroken());
- assertEquals(0, barrier.getNumberWaiting());
- }
- }
- catch (Exception ex) {
- unexpectedException();
+ public void testResetAfterCommandException() throws Exception {
+ final CyclicBarrier start = new CyclicBarrier(3);
+ final CyclicBarrier barrier =
+ new CyclicBarrier(3, new Runnable() {
+ public void run() {
+ throw new NullPointerException(); }});
+ for (int i = 0; i < 2; i++) {
+ Thread t1 = new ThreadShouldThrow(BrokenBarrierException.class) {
+ public void realRun() throws Exception {
+ start.await();
+ barrier.await();
+ }};
+
+ Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) {
+ public void realRun() throws Exception {
+ start.await();
+ barrier.await();
+ }};
+
+ t1.start();
+ t2.start();
+ start.await();
+ while (barrier.getNumberWaiting() < 2) { Thread.yield(); }
+ try {
+ barrier.await();
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ t1.join();
+ t2.join();
+ assertTrue(barrier.isBroken());
+ assertEquals(0, barrier.getNumberWaiting());
+ barrier.reset();
+ assertFalse(barrier.isBroken());
+ assertEquals(0, barrier.getNumberWaiting());
}
}
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/DelayQueueTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/DelayQueueTest.java
index 3d851e8..7aeceda 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/DelayQueueTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/DelayQueueTest.java
@@ -2,26 +2,27 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.*;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.concurrent.*;
public class DelayQueueTest extends JSR166TestCase {
public static Test suite() {
- return new TestSuite(DelayQueueTest.class);
+ return new TestSuite(DelayQueueTest.class);
}
private static final int NOCAP = Integer.MAX_VALUE;
/**
* A delayed implementation for testing.
- * Most tests use Pseudodelays, where delays are all elapsed
+ * Most tests use Pseudodelays, where delays are all elapsed
* (so, no blocking solely for delays) but are still ordered
*/
static class PDelay implements Delayed {
@@ -29,25 +30,21 @@ public class DelayQueueTest extends JSR166TestCase {
PDelay(int i) { pseudodelay = Integer.MIN_VALUE + i; }
public int compareTo(PDelay y) {
int i = pseudodelay;
- int j = ((PDelay)y).pseudodelay;
+ int j = y.pseudodelay;
if (i < j) return -1;
if (i > j) return 1;
return 0;
}
public int compareTo(Delayed y) {
- int i = pseudodelay;
- int j = ((PDelay)y).pseudodelay;
- if (i < j) return -1;
- if (i > j) return 1;
- return 0;
+ return compareTo((PDelay)y);
}
public boolean equals(Object other) {
- return ((PDelay)other).pseudodelay == pseudodelay;
+ return equals((PDelay)other);
}
public boolean equals(PDelay other) {
- return ((PDelay)other).pseudodelay == pseudodelay;
+ return other.pseudodelay == pseudodelay;
}
@@ -74,25 +71,21 @@ public class DelayQueueTest extends JSR166TestCase {
}
public int compareTo(NanoDelay y) {
long i = trigger;
- long j = ((NanoDelay)y).trigger;
+ long j = y.trigger;
if (i < j) return -1;
if (i > j) return 1;
return 0;
}
public int compareTo(Delayed y) {
- long i = trigger;
- long j = ((NanoDelay)y).trigger;
- if (i < j) return -1;
- if (i > j) return 1;
- return 0;
+ return compareTo((NanoDelay)y);
}
public boolean equals(Object other) {
- return ((NanoDelay)other).trigger == trigger;
+ return equals((NanoDelay)other);
}
public boolean equals(NanoDelay other) {
- return ((NanoDelay)other).trigger == trigger;
+ return other.trigger == trigger;
}
public long getDelay(TimeUnit unit) {
@@ -117,13 +110,13 @@ public class DelayQueueTest extends JSR166TestCase {
private DelayQueue populatedQueue(int n) {
DelayQueue q = new DelayQueue();
assertTrue(q.isEmpty());
- for(int i = n-1; i >= 0; i-=2)
- assertTrue(q.offer(new PDelay(i)));
- for(int i = (n & 1); i < n; i+=2)
- assertTrue(q.offer(new PDelay(i)));
+ for (int i = n-1; i >= 0; i-=2)
+ assertTrue(q.offer(new PDelay(i)));
+ for (int i = (n & 1); i < n; i+=2)
+ assertTrue(q.offer(new PDelay(i)));
assertFalse(q.isEmpty());
assertEquals(NOCAP, q.remainingCapacity());
- assertEquals(n, q.size());
+ assertEquals(n, q.size());
return q;
}
@@ -141,8 +134,7 @@ public class DelayQueueTest extends JSR166TestCase {
try {
DelayQueue q = new DelayQueue(null);
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
@@ -153,8 +145,7 @@ public class DelayQueueTest extends JSR166TestCase {
PDelay[] ints = new PDelay[SIZE];
DelayQueue q = new DelayQueue(Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
@@ -167,23 +158,19 @@ public class DelayQueueTest extends JSR166TestCase {
ints[i] = new PDelay(i);
DelayQueue q = new DelayQueue(Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
* Queue contains all elements of collection used to initialize
*/
public void testConstructor6() {
- try {
- PDelay[] ints = new PDelay[SIZE];
- for (int i = 0; i < SIZE; ++i)
- ints[i] = new PDelay(i);
- DelayQueue q = new DelayQueue(Arrays.asList(ints));
- for (int i = 0; i < SIZE; ++i)
- assertEquals(ints[i], q.poll());
- }
- finally {}
+ PDelay[] ints = new PDelay[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = new PDelay(i);
+ DelayQueue q = new DelayQueue(Arrays.asList(ints));
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(ints[i], q.poll());
}
/**
@@ -202,7 +189,7 @@ public class DelayQueueTest extends JSR166TestCase {
}
/**
- * remainingCapacity does not change when elementa added or removed,
+ * remainingCapacity does not change when elements added or removed,
* but size does
*/
public void testRemainingCapacity() {
@@ -223,22 +210,22 @@ public class DelayQueueTest extends JSR166TestCase {
* offer(null) throws NPE
*/
public void testOfferNull() {
- try {
+ try {
DelayQueue q = new DelayQueue();
q.offer(null);
shouldThrow();
- } catch (NullPointerException success) { }
+ } catch (NullPointerException success) {}
}
/**
* add(null) throws NPE
*/
public void testAddNull() {
- try {
+ try {
DelayQueue q = new DelayQueue();
q.add(null);
shouldThrow();
- } catch (NullPointerException success) { }
+ } catch (NullPointerException success) {}
}
/**
@@ -269,8 +256,7 @@ public class DelayQueueTest extends JSR166TestCase {
DelayQueue q = new DelayQueue();
q.addAll(null);
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
@@ -282,8 +268,7 @@ public class DelayQueueTest extends JSR166TestCase {
DelayQueue q = populatedQueue(SIZE);
q.addAll(q);
shouldThrow();
- }
- catch (IllegalArgumentException success) {}
+ } catch (IllegalArgumentException success) {}
}
/**
@@ -295,8 +280,7 @@ public class DelayQueueTest extends JSR166TestCase {
PDelay[] ints = new PDelay[SIZE];
q.addAll(Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
* addAll of a collection with any null elements throws NPE after
@@ -310,179 +294,133 @@ public class DelayQueueTest extends JSR166TestCase {
ints[i] = new PDelay(i);
q.addAll(Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
* Queue contains all elements of successful addAll
*/
public void testAddAll5() {
- try {
- PDelay[] empty = new PDelay[0];
- PDelay[] ints = new PDelay[SIZE];
- for (int i = SIZE-1; i >= 0; --i)
- ints[i] = new PDelay(i);
- DelayQueue q = new DelayQueue();
- assertFalse(q.addAll(Arrays.asList(empty)));
- assertTrue(q.addAll(Arrays.asList(ints)));
- for (int i = 0; i < SIZE; ++i)
- assertEquals(ints[i], q.poll());
- }
- finally {}
+ PDelay[] empty = new PDelay[0];
+ PDelay[] ints = new PDelay[SIZE];
+ for (int i = SIZE-1; i >= 0; --i)
+ ints[i] = new PDelay(i);
+ DelayQueue q = new DelayQueue();
+ assertFalse(q.addAll(Arrays.asList(empty)));
+ assertTrue(q.addAll(Arrays.asList(ints)));
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(ints[i], q.poll());
}
/**
* put(null) throws NPE
*/
public void testPutNull() {
- try {
+ try {
DelayQueue q = new DelayQueue();
q.put(null);
shouldThrow();
- }
- catch (NullPointerException success){
- }
+ } catch (NullPointerException success) {}
}
/**
* all elements successfully put are contained
*/
public void testPut() {
- try {
- DelayQueue q = new DelayQueue();
- for (int i = 0; i < SIZE; ++i) {
- PDelay I = new PDelay(i);
- q.put(I);
- assertTrue(q.contains(I));
- }
- assertEquals(SIZE, q.size());
+ DelayQueue q = new DelayQueue();
+ for (int i = 0; i < SIZE; ++i) {
+ PDelay I = new PDelay(i);
+ q.put(I);
+ assertTrue(q.contains(I));
}
- finally {
- }
+ assertEquals(SIZE, q.size());
}
/**
* put doesn't block waiting for take
*/
- public void testPutWithTake() {
+ public void testPutWithTake() throws InterruptedException {
final DelayQueue q = new DelayQueue();
- Thread t = new Thread(new Runnable() {
- public void run() {
- int added = 0;
- try {
- q.put(new PDelay(0));
- ++added;
- q.put(new PDelay(0));
- ++added;
- q.put(new PDelay(0));
- ++added;
- q.put(new PDelay(0));
- ++added;
- threadAssertTrue(added == 4);
- } finally {
- }
- }
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- q.take();
- t.interrupt();
- t.join();
- } catch (Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ q.put(new PDelay(0));
+ q.put(new PDelay(0));
+ q.put(new PDelay(0));
+ q.put(new PDelay(0));
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ q.take();
+ t.interrupt();
+ t.join();
}
/**
* timed offer does not time out
*/
- public void testTimedOffer() {
+ public void testTimedOffer() throws InterruptedException {
final DelayQueue q = new DelayQueue();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- q.put(new PDelay(0));
- q.put(new PDelay(0));
- threadAssertTrue(q.offer(new PDelay(0), SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- threadAssertTrue(q.offer(new PDelay(0), LONG_DELAY_MS, TimeUnit.MILLISECONDS));
- } finally { }
- }
- });
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ q.put(new PDelay(0));
+ q.put(new PDelay(0));
+ assertTrue(q.offer(new PDelay(0), SHORT_DELAY_MS, MILLISECONDS));
+ assertTrue(q.offer(new PDelay(0), LONG_DELAY_MS, MILLISECONDS));
+ }});
- try {
- t.start();
- Thread.sleep(SMALL_DELAY_MS);
- t.interrupt();
- t.join();
- } catch (Exception e){
- unexpectedException();
- }
+ t.start();
+ Thread.sleep(SMALL_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* take retrieves elements in priority order
*/
- public void testTake() {
- try {
- DelayQueue q = populatedQueue(SIZE);
- for (int i = 0; i < SIZE; ++i) {
- assertEquals(new PDelay(i), ((PDelay)q.take()));
- }
- } catch (InterruptedException e){
- unexpectedException();
- }
+ public void testTake() throws InterruptedException {
+ DelayQueue q = populatedQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(new PDelay(i), ((PDelay)q.take()));
+ }
}
/**
* take blocks interruptibly when empty
*/
- public void testTakeFromEmpty() {
+ public void testTakeFromEmpty() throws InterruptedException {
final DelayQueue q = new DelayQueue();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- q.take();
- threadShouldThrow();
- } catch (InterruptedException success){ }
- }
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- } catch (Exception e){
- unexpectedException();
- }
+ Thread t = new ThreadShouldThrow(InterruptedException.class) {
+ public void realRun() throws InterruptedException {
+ q.take();
+ }};
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* Take removes existing elements until empty, then blocks interruptibly
*/
- public void testBlockingTake() {
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- DelayQueue q = populatedQueue(SIZE);
- for (int i = 0; i < SIZE; ++i) {
- threadAssertEquals(new PDelay(i), ((PDelay)q.take()));
- }
- q.take();
- threadShouldThrow();
- } catch (InterruptedException success){
- }
- }});
+ public void testBlockingTake() throws InterruptedException {
+ final DelayQueue q = populatedQueue(SIZE);
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(new PDelay(i), ((PDelay)q.take()));
+ }
+ try {
+ q.take();
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
t.start();
- try {
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- }
- catch (InterruptedException ie) {
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
@@ -494,91 +432,76 @@ public class DelayQueueTest extends JSR166TestCase {
for (int i = 0; i < SIZE; ++i) {
assertEquals(new PDelay(i), ((PDelay)q.poll()));
}
- assertNull(q.poll());
+ assertNull(q.poll());
}
/**
* timed pool with zero timeout succeeds when non-empty, else times out
*/
- public void testTimedPoll0() {
- try {
- DelayQueue q = populatedQueue(SIZE);
- for (int i = 0; i < SIZE; ++i) {
- assertEquals(new PDelay(i), ((PDelay)q.poll(0, TimeUnit.MILLISECONDS)));
- }
- assertNull(q.poll(0, TimeUnit.MILLISECONDS));
- } catch (InterruptedException e){
- unexpectedException();
- }
+ public void testTimedPoll0() throws InterruptedException {
+ DelayQueue q = populatedQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(new PDelay(i), ((PDelay)q.poll(0, MILLISECONDS)));
+ }
+ assertNull(q.poll(0, MILLISECONDS));
}
/**
* timed pool with nonzero timeout succeeds when non-empty, else times out
*/
- public void testTimedPoll() {
- try {
- DelayQueue q = populatedQueue(SIZE);
- for (int i = 0; i < SIZE; ++i) {
- assertEquals(new PDelay(i), ((PDelay)q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)));
- }
- assertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- } catch (InterruptedException e){
- unexpectedException();
- }
+ public void testTimedPoll() throws InterruptedException {
+ DelayQueue q = populatedQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(new PDelay(i), ((PDelay)q.poll(SHORT_DELAY_MS, MILLISECONDS)));
+ }
+ assertNull(q.poll(SHORT_DELAY_MS, MILLISECONDS));
}
/**
* Interrupted timed poll throws InterruptedException instead of
* returning timeout status
*/
- public void testInterruptedTimedPoll() {
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- DelayQueue q = populatedQueue(SIZE);
- for (int i = 0; i < SIZE; ++i) {
- threadAssertEquals(new PDelay(i), ((PDelay)q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)));
- }
- threadAssertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- } catch (InterruptedException success){
- }
- }});
+ public void testInterruptedTimedPoll() throws InterruptedException {
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ DelayQueue q = populatedQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(new PDelay(i), ((PDelay)q.poll(SHORT_DELAY_MS, MILLISECONDS)));
+ }
+ try {
+ q.poll(SMALL_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
t.start();
- try {
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- }
- catch (InterruptedException ie) {
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* timed poll before a delayed offer fails; after offer succeeds;
* on interruption throws
*/
- public void testTimedPollWithOffer() {
+ public void testTimedPollWithOffer() throws InterruptedException {
final DelayQueue q = new DelayQueue();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- threadAssertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- q.poll(LONG_DELAY_MS, TimeUnit.MILLISECONDS);
- q.poll(LONG_DELAY_MS, TimeUnit.MILLISECONDS);
- threadFail("Should block");
- } catch (InterruptedException success) { }
- }
- });
- try {
- t.start();
- Thread.sleep(SMALL_DELAY_MS);
- assertTrue(q.offer(new PDelay(0), SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- t.interrupt();
- t.join();
- } catch (Exception e){
- unexpectedException();
- }
+ final PDelay pdelay = new PDelay(0);
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertNull(q.poll(SHORT_DELAY_MS, MILLISECONDS));
+ assertSame(pdelay, q.poll(LONG_DELAY_MS, MILLISECONDS));
+ try {
+ q.poll(LONG_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SMALL_DELAY_MS);
+ assertTrue(q.offer(pdelay, SHORT_DELAY_MS, MILLISECONDS));
+ t.interrupt();
+ t.join();
}
@@ -589,13 +512,13 @@ public class DelayQueueTest extends JSR166TestCase {
DelayQueue q = populatedQueue(SIZE);
for (int i = 0; i < SIZE; ++i) {
assertEquals(new PDelay(i), ((PDelay)q.peek()));
- q.poll();
+ assertEquals(new PDelay(i), ((PDelay)q.poll()));
if (q.isEmpty())
assertNull(q.peek());
else
- assertTrue(i != ((PDelay)q.peek()).intValue());
+ assertFalse(new PDelay(i).equals(q.peek()));
}
- assertNull(q.peek());
+ assertNull(q.peek());
}
/**
@@ -610,8 +533,7 @@ public class DelayQueueTest extends JSR166TestCase {
try {
q.element();
shouldThrow();
- }
- catch (NoSuchElementException success) {}
+ } catch (NoSuchElementException success) {}
}
/**
@@ -625,8 +547,7 @@ public class DelayQueueTest extends JSR166TestCase {
try {
q.remove();
shouldThrow();
- } catch (NoSuchElementException success){
- }
+ } catch (NoSuchElementException success) {}
}
/**
@@ -725,32 +646,24 @@ public class DelayQueueTest extends JSR166TestCase {
/**
* toArray contains all elements
*/
- public void testToArray() {
+ public void testToArray() throws InterruptedException {
DelayQueue q = populatedQueue(SIZE);
- Object[] o = q.toArray();
+ Object[] o = q.toArray();
Arrays.sort(o);
- try {
- for(int i = 0; i < o.length; i++)
- assertEquals(o[i], q.take());
- } catch (InterruptedException e){
- unexpectedException();
- }
+ for (int i = 0; i < o.length; i++)
+ assertEquals(o[i], q.take());
}
/**
* toArray(a) contains all elements
*/
- public void testToArray2() {
+ public void testToArray2() throws InterruptedException {
DelayQueue q = populatedQueue(SIZE);
- PDelay[] ints = new PDelay[SIZE];
- ints = (PDelay[])q.toArray(ints);
+ PDelay[] ints = new PDelay[SIZE];
+ ints = (PDelay[])q.toArray(ints);
Arrays.sort(ints);
- try {
- for(int i = 0; i < ints.length; i++)
- assertEquals(ints[i], q.take());
- } catch (InterruptedException e){
- unexpectedException();
- }
+ for (int i = 0; i < ints.length; i++)
+ assertEquals(ints[i], q.take());
}
@@ -758,22 +671,22 @@ public class DelayQueueTest extends JSR166TestCase {
* toArray(null) throws NPE
*/
public void testToArray_BadArg() {
- try {
- DelayQueue q = populatedQueue(SIZE);
- Object o[] = q.toArray(null);
- shouldThrow();
- } catch(NullPointerException success){}
+ DelayQueue q = populatedQueue(SIZE);
+ try {
+ Object o[] = q.toArray(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
}
/**
* toArray with incompatible array type throws CCE
*/
public void testToArray1_BadArg() {
- try {
- DelayQueue q = populatedQueue(SIZE);
- Object o[] = q.toArray(new String[10] );
- shouldThrow();
- } catch(ArrayStoreException success){}
+ DelayQueue q = populatedQueue(SIZE);
+ try {
+ Object o[] = q.toArray(new String[10]);
+ shouldThrow();
+ } catch (ArrayStoreException success) {}
}
/**
@@ -782,8 +695,8 @@ public class DelayQueueTest extends JSR166TestCase {
public void testIterator() {
DelayQueue q = populatedQueue(SIZE);
int i = 0;
- Iterator it = q.iterator();
- while(it.hasNext()) {
+ Iterator it = q.iterator();
+ while (it.hasNext()) {
assertTrue(q.contains(it.next()));
++i;
}
@@ -825,39 +738,27 @@ public class DelayQueueTest extends JSR166TestCase {
public void testPollInExecutor() {
final DelayQueue q = new DelayQueue();
ExecutorService executor = Executors.newFixedThreadPool(2);
- executor.execute(new Runnable() {
- public void run() {
- threadAssertNull(q.poll());
- try {
- threadAssertTrue(null != q.poll(MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS));
- threadAssertTrue(q.isEmpty());
- }
- catch (InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
+ executor.execute(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertNull(q.poll());
+ assertTrue(null != q.poll(MEDIUM_DELAY_MS, MILLISECONDS));
+ assertTrue(q.isEmpty());
+ }});
+
+ executor.execute(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ Thread.sleep(SHORT_DELAY_MS);
+ q.put(new PDelay(1));
+ }});
- executor.execute(new Runnable() {
- public void run() {
- try {
- Thread.sleep(SHORT_DELAY_MS);
- q.put(new PDelay(1));
- }
- catch (InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
joinPool(executor);
-
}
/**
* Delayed actions do not occur until their delay elapses
*/
- public void testDelay() {
+ public void testDelay() throws InterruptedException {
DelayQueue q = new DelayQueue();
NanoDelay[] elements = new NanoDelay[SIZE];
for (int i = 0; i < SIZE; ++i) {
@@ -867,19 +768,14 @@ public class DelayQueueTest extends JSR166TestCase {
q.add(elements[i]);
}
- try {
- long last = 0;
- for (int i = 0; i < SIZE; ++i) {
- NanoDelay e = (NanoDelay)(q.take());
- long tt = e.getTriggerTime();
- assertTrue(tt <= System.nanoTime());
- if (i != 0)
- assertTrue(tt >= last);
- last = tt;
- }
- }
- catch(InterruptedException ie) {
- unexpectedException();
+ long last = 0;
+ for (int i = 0; i < SIZE; ++i) {
+ NanoDelay e = (NanoDelay)(q.take());
+ long tt = e.getTriggerTime();
+ assertTrue(tt <= System.nanoTime());
+ if (i != 0)
+ assertTrue(tt >= last);
+ last = tt;
}
}
@@ -905,14 +801,10 @@ public class DelayQueueTest extends JSR166TestCase {
/**
* timed poll of a non-empty queue returns null if no expired elements.
*/
- public void testTimedPollDelayed() {
+ public void testTimedPollDelayed() throws InterruptedException {
DelayQueue q = new DelayQueue();
q.add(new NanoDelay(LONG_DELAY_MS * 1000000L));
- try {
- assertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- } catch (Exception ex) {
- unexpectedException();
- }
+ assertNull(q.poll(SHORT_DELAY_MS, MILLISECONDS));
}
/**
@@ -923,8 +815,7 @@ public class DelayQueueTest extends JSR166TestCase {
try {
q.drainTo(null);
shouldThrow();
- } catch(NullPointerException success) {
- }
+ } catch (NullPointerException success) {}
}
/**
@@ -935,8 +826,7 @@ public class DelayQueueTest extends JSR166TestCase {
try {
q.drainTo(q);
shouldThrow();
- } catch(IllegalArgumentException success) {
- }
+ } catch (IllegalArgumentException success) {}
}
/**
@@ -969,53 +859,47 @@ public class DelayQueueTest extends JSR166TestCase {
/**
* drainTo empties queue
- */
- public void testDrainToWithActivePut() {
+ */
+ public void testDrainToWithActivePut() throws InterruptedException {
final DelayQueue q = populatedQueue(SIZE);
- Thread t = new Thread(new Runnable() {
- public void run() {
- q.put(new PDelay(SIZE+1));
- }
- });
- try {
- t.start();
- ArrayList l = new ArrayList();
- q.drainTo(l);
- assertTrue(l.size() >= SIZE);
- t.join();
- assertTrue(q.size() + l.size() >= SIZE);
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ q.put(new PDelay(SIZE+1));
+ }});
+
+ t.start();
+ ArrayList l = new ArrayList();
+ q.drainTo(l);
+ assertTrue(l.size() >= SIZE);
+ t.join();
+ assertTrue(q.size() + l.size() >= SIZE);
}
/**
* drainTo(null, n) throws NPE
- */
+ */
public void testDrainToNullN() {
DelayQueue q = populatedQueue(SIZE);
try {
q.drainTo(null, 0);
shouldThrow();
- } catch(NullPointerException success) {
- }
+ } catch (NullPointerException success) {}
}
/**
* drainTo(this, n) throws IAE
- */
+ */
public void testDrainToSelfN() {
DelayQueue q = populatedQueue(SIZE);
try {
q.drainTo(q, 0);
shouldThrow();
- } catch(IllegalArgumentException success) {
- }
+ } catch (IllegalArgumentException success) {}
}
/**
* drainTo(c, n) empties first max {n, size} elements of queue into c
- */
+ */
public void testDrainToN() {
for (int i = 0; i < SIZE + 2; ++i) {
DelayQueue q = populatedQueue(SIZE);
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/EntryTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/EntryTest.java
new file mode 100644
index 0000000..893fd48
--- /dev/null
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/EntryTest.java
@@ -0,0 +1,131 @@
+/*
+ * 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 tests.api.java.util.concurrent; // android-added
+
+import junit.framework.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.io.*;
+
+public class EntryTest extends JSR166TestCase {
+ public static Test suite() {
+ return new TestSuite(EntryTest.class);
+ }
+
+ static final String k1 = "1";
+ static final String v1 = "a";
+ static final String k2 = "2";
+ static final String v2 = "b";
+
+
+ /**
+ * A new SimpleEntry(k, v) holds k, v.
+ */
+ public void testConstructor1() {
+ Map.Entry e = new AbstractMap.SimpleEntry(k1, v1);
+ assertEquals(k1, e.getKey());
+ assertEquals(v1, e.getValue());
+ }
+
+ /**
+ * A new SimpleImmutableEntry(k, v) holds k, v.
+ */
+ public void testConstructor2() {
+ Map.Entry s = new AbstractMap.SimpleImmutableEntry(k1, v1);
+ assertEquals(k1, s.getKey());
+ assertEquals(v1, s.getValue());
+ }
+
+
+ /**
+ * A new SimpleEntry(entry(k, v)) holds k, v.
+ */
+ public void testConstructor3() {
+ Map.Entry e2 = new AbstractMap.SimpleEntry(k1, v1);
+ Map.Entry e = new AbstractMap.SimpleEntry(e2);
+ assertEquals(k1, e.getKey());
+ assertEquals(v1, e.getValue());
+ }
+
+ /**
+ * A new SimpleImmutableEntry(entry(k, v)) holds k, v.
+ */
+ public void testConstructor4() {
+ Map.Entry s2 = new AbstractMap.SimpleImmutableEntry(k1, v1);
+ Map.Entry s = new AbstractMap.SimpleImmutableEntry(s2);
+ assertEquals(k1, s.getKey());
+ assertEquals(v1, s.getValue());
+ }
+
+ /**
+ * Entries with same key-value pairs are equal and have same
+ * hashcodes
+ */
+ public void testEquals() {
+ Map.Entry e2 = new AbstractMap.SimpleEntry(k1, v1);
+ Map.Entry e = new AbstractMap.SimpleEntry(e2);
+ Map.Entry s2 = new AbstractMap.SimpleImmutableEntry(k1, v1);
+ Map.Entry s = new AbstractMap.SimpleImmutableEntry(s2);
+ assertEquals(e2, e);
+ assertEquals(e2.hashCode(), e.hashCode());
+ assertEquals(s2, s);
+ assertEquals(s2.hashCode(), s.hashCode());
+ assertEquals(e2, s2);
+ assertEquals(e2.hashCode(), s2.hashCode());
+ assertEquals(e, s);
+ assertEquals(e.hashCode(), s.hashCode());
+ }
+
+ /**
+ * Entries with different key-value pairs are not equal
+ */
+ public void testNotEquals() {
+ Map.Entry e2 = new AbstractMap.SimpleEntry(k1, v1);
+ Map.Entry e = new AbstractMap.SimpleEntry(k2, v1);
+ assertFalse(e2.equals( e));
+ e = new AbstractMap.SimpleEntry(k1, v2);
+ assertFalse(e2.equals( e));
+ e = new AbstractMap.SimpleEntry(k2, v2);
+ assertFalse(e2.equals( e));
+
+ Map.Entry s2 = new AbstractMap.SimpleImmutableEntry(k1, v1);
+ Map.Entry s = new AbstractMap.SimpleImmutableEntry(k2, v1);
+ assertFalse(s2.equals( s));
+ s = new AbstractMap.SimpleImmutableEntry(k1, v2);
+ assertFalse(s2.equals( s));
+ s = new AbstractMap.SimpleImmutableEntry(k2, v2);
+ assertFalse(s2.equals( s));
+ }
+
+
+ /**
+ * getValue returns last setValue for SimpleEntry
+ */
+ public void testSetValue1() {
+ Map.Entry e2 = new AbstractMap.SimpleEntry(k1, v1);
+ Map.Entry e = new AbstractMap.SimpleEntry(e2);
+ assertEquals(k1, e.getKey());
+ assertEquals(v1, e.getValue());
+ e.setValue(k2);
+ assertEquals(k2, e.getValue());
+ assertFalse(e2.equals( e));
+ }
+
+ /**
+ * setValue for SimpleImmutableEntry throws UnsupportedOperationException
+ */
+ public void testsetValue2() {
+ Map.Entry s2 = new AbstractMap.SimpleImmutableEntry(k1, v1);
+ Map.Entry s = new AbstractMap.SimpleImmutableEntry(s2);
+ assertEquals(k1, s.getKey());
+ assertEquals(v1, s.getValue());
+ try {
+ s.setValue(k2);
+ shouldThrow();
+ } catch (UnsupportedOperationException success) {}
+ }
+}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/ExchangerTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/ExchangerTest.java
index bc0df85..be1eaa3 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/ExchangerTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/ExchangerTest.java
@@ -2,15 +2,16 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.*;
import java.util.concurrent.*;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
public class ExchangerTest extends JSR166TestCase {
public static Test suite() {
@@ -20,211 +21,123 @@ public class ExchangerTest extends JSR166TestCase {
/**
* exchange exchanges objects across two threads
*/
- public void testExchange() {
+ public void testExchange() throws InterruptedException {
final Exchanger e = new Exchanger();
- Thread t1 = new Thread(new Runnable(){
- public void run(){
- try {
- Object v = e.exchange(one);
- threadAssertEquals(v, two);
- Object w = e.exchange(v);
- threadAssertEquals(w, one);
- } catch(InterruptedException e){
- threadUnexpectedException();
- }
- }
- });
- Thread t2 = new Thread(new Runnable(){
- public void run(){
- try {
- Object v = e.exchange(two);
- threadAssertEquals(v, one);
- Object w = e.exchange(v);
- threadAssertEquals(w, two);
- } catch(InterruptedException e){
- threadUnexpectedException();
- }
- }
- });
- try {
- t1.start();
- t2.start();
- t1.join();
- t2.join();
- } catch(InterruptedException ex) {
- unexpectedException();
- }
+ Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertSame(one, e.exchange(two));
+ assertSame(two, e.exchange(one));
+ }});
+ Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertSame(two, e.exchange(one));
+ assertSame(one, e.exchange(two));
+ }});
+
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
}
/**
* timed exchange exchanges objects across two threads
*/
- public void testTimedExchange() {
+ public void testTimedExchange() throws InterruptedException {
final Exchanger e = new Exchanger();
- Thread t1 = new Thread(new Runnable(){
- public void run(){
- try {
- Object v = e.exchange(one, SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
- threadAssertEquals(v, two);
- Object w = e.exchange(v, SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
- threadAssertEquals(w, one);
- } catch(InterruptedException e){
- threadUnexpectedException();
- } catch(TimeoutException toe) {
- threadUnexpectedException();
- }
- }
- });
- Thread t2 = new Thread(new Runnable(){
- public void run(){
- try {
- Object v = e.exchange(two, SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
- threadAssertEquals(v, one);
- Object w = e.exchange(v, SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
- threadAssertEquals(w, two);
- } catch(InterruptedException e){
- threadUnexpectedException();
- } catch(TimeoutException toe) {
- threadUnexpectedException();
- }
- }
- });
- try {
- t1.start();
- t2.start();
- t1.join();
- t2.join();
- } catch(InterruptedException ex) {
- unexpectedException();
- }
+ Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() throws Exception {
+ assertSame(one, e.exchange(two, SHORT_DELAY_MS, MILLISECONDS));
+ assertSame(two, e.exchange(one, SHORT_DELAY_MS, MILLISECONDS));
+ }});
+ Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() throws Exception {
+ assertSame(two, e.exchange(one, SHORT_DELAY_MS, MILLISECONDS));
+ assertSame(one, e.exchange(two, SHORT_DELAY_MS, MILLISECONDS));
+ }});
+
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
}
/**
* interrupt during wait for exchange throws IE
*/
- public void testExchange_InterruptedException(){
+ public void testExchange_InterruptedException() throws InterruptedException {
final Exchanger e = new Exchanger();
- Thread t = new Thread(new Runnable() {
- public void run(){
- try {
- e.exchange(one);
- threadShouldThrow();
- } catch(InterruptedException success){
- }
- }
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- } catch(InterruptedException ex) {
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ e.exchange(one);
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* interrupt during wait for timed exchange throws IE
*/
- public void testTimedExchange_InterruptedException(){
+ public void testTimedExchange_InterruptedException() throws InterruptedException {
final Exchanger e = new Exchanger();
- Thread t = new Thread(new Runnable() {
- public void run(){
- try {
- e.exchange(null, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
- threadShouldThrow();
- } catch(InterruptedException success){
- } catch(Exception e2){
- threadFail("should throw IE");
- }
- }
- });
- try {
- t.start();
- t.interrupt();
- t.join();
- } catch(InterruptedException ex){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws Exception {
+ e.exchange(null, SMALL_DELAY_MS, MILLISECONDS);
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* timeout during wait for timed exchange throws TOE
*/
- public void testExchange_TimeOutException(){
+ public void testExchange_TimeOutException() throws InterruptedException {
final Exchanger e = new Exchanger();
- Thread t = new Thread(new Runnable() {
- public void run(){
- try {
- e.exchange(null, SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
- threadShouldThrow();
- } catch(TimeoutException success){
- } catch(InterruptedException e2){
- threadFail("should throw TOE");
- }
- }
- });
- try {
- t.start();
- t.join();
- } catch(InterruptedException ex){
- unexpectedException();
- }
+ Thread t = new ThreadShouldThrow(TimeoutException.class) {
+ public void realRun() throws Exception {
+ e.exchange(null, SHORT_DELAY_MS, MILLISECONDS);
+ }};
+
+ t.start();
+ t.join();
}
/**
* If one exchanging thread is interrupted, another succeeds.
*/
- public void testReplacementAfterExchange() {
+ public void testReplacementAfterExchange() throws InterruptedException {
final Exchanger e = new Exchanger();
- Thread t1 = new Thread(new Runnable(){
- public void run(){
- try {
- Object v = e.exchange(one);
- threadAssertEquals(v, two);
- Object w = e.exchange(v);
- threadShouldThrow();
- } catch(InterruptedException success){
- }
- }
- });
- Thread t2 = new Thread(new Runnable(){
- public void run(){
- try {
- Object v = e.exchange(two);
- threadAssertEquals(v, one);
- Thread.sleep(SMALL_DELAY_MS);
- Object w = e.exchange(v);
- threadAssertEquals(w, three);
- } catch(InterruptedException e){
- threadUnexpectedException();
- }
- }
- });
- Thread t3 = new Thread(new Runnable(){
- public void run(){
- try {
- Thread.sleep(SMALL_DELAY_MS);
- Object w = e.exchange(three);
- threadAssertEquals(w, one);
- } catch(InterruptedException e){
- threadUnexpectedException();
- }
- }
- });
-
- try {
- t1.start();
- t2.start();
- t3.start();
- Thread.sleep(SHORT_DELAY_MS);
- t1.interrupt();
- t1.join();
- t2.join();
- t3.join();
- } catch(InterruptedException ex) {
- unexpectedException();
- }
+ Thread t1 = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertSame(two, e.exchange(one));
+ e.exchange(two);
+ }});
+ Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertSame(one, e.exchange(two));
+ Thread.sleep(SMALL_DELAY_MS);
+ assertSame(three, e.exchange(one));
+ }});
+ Thread t3 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ Thread.sleep(SMALL_DELAY_MS);
+ assertSame(one, e.exchange(three));
+ }});
+
+ t1.start();
+ t2.start();
+ t3.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t1.interrupt();
+ t1.join();
+ t2.join();
+ t3.join();
}
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/ExecutorCompletionServiceTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/ExecutorCompletionServiceTest.java
index 91bedf9..dfa8f7d 100644
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/ExecutorCompletionServiceTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/ExecutorCompletionServiceTest.java
@@ -2,20 +2,21 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.*;
import java.util.concurrent.*;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.concurrent.atomic.*;
import java.math.BigInteger;
import java.security.*;
-public class ExecutorCompletionServiceTest extends JSR166TestCase{
+public class ExecutorCompletionServiceTest extends JSR166TestCase {
public static Test suite() {
return new TestSuite(ExecutorCompletionServiceTest.class);
}
@@ -23,30 +24,28 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase{
/**
* Creating a new ECS with null Executor throw NPE
- */
+ */
public void testConstructorNPE() {
try {
ExecutorCompletionService ecs = new ExecutorCompletionService(null);
shouldThrow();
- } catch (NullPointerException success) {
- }
+ } catch (NullPointerException success) {}
}
/**
* Creating a new ECS with null queue throw NPE
- */
+ */
public void testConstructorNPE2() {
try {
ExecutorService e = Executors.newCachedThreadPool();
ExecutorCompletionService ecs = new ExecutorCompletionService(e, null);
shouldThrow();
- } catch (NullPointerException success) {
- }
+ } catch (NullPointerException success) {}
}
/**
* Submitting a null callable throws NPE
- */
+ */
public void testSubmitNPE() {
ExecutorService e = Executors.newCachedThreadPool();
ExecutorCompletionService ecs = new ExecutorCompletionService(e);
@@ -62,7 +61,7 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase{
/**
* Submitting a null runnable throws NPE
- */
+ */
public void testSubmitNPE2() {
ExecutorService e = Executors.newCachedThreadPool();
ExecutorCompletionService ecs = new ExecutorCompletionService(e);
@@ -78,8 +77,8 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase{
/**
* A taken submitted task is completed
- */
- public void testTake() {
+ */
+ public void testTake() throws InterruptedException {
ExecutorService e = Executors.newCachedThreadPool();
ExecutorCompletionService ecs = new ExecutorCompletionService(e);
try {
@@ -87,8 +86,6 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase{
ecs.submit(c);
Future f = ecs.take();
assertTrue(f.isDone());
- } catch (Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -96,8 +93,8 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase{
/**
* Take returns the same future object returned by submit
- */
- public void testTake2() {
+ */
+ public void testTake2() throws InterruptedException {
ExecutorService e = Executors.newCachedThreadPool();
ExecutorCompletionService ecs = new ExecutorCompletionService(e);
try {
@@ -105,8 +102,6 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase{
Future f1 = ecs.submit(c);
Future f2 = ecs.take();
assertSame(f1, f2);
- } catch (Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -114,8 +109,8 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase{
/**
* If poll returns non-null, the returned task is completed
- */
- public void testPoll1() {
+ */
+ public void testPoll1() throws InterruptedException {
ExecutorService e = Executors.newCachedThreadPool();
ExecutorCompletionService ecs = new ExecutorCompletionService(e);
try {
@@ -130,8 +125,6 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase{
break;
}
}
- } catch (Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -139,21 +132,85 @@ public class ExecutorCompletionServiceTest extends JSR166TestCase{
/**
* If timed poll returns non-null, the returned task is completed
- */
- public void testPoll2() {
+ */
+ public void testPoll2() throws InterruptedException {
ExecutorService e = Executors.newCachedThreadPool();
ExecutorCompletionService ecs = new ExecutorCompletionService(e);
try {
assertNull(ecs.poll());
Callable c = new StringTask();
ecs.submit(c);
- Future f = ecs.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
- if (f != null)
+ Future f = ecs.poll(SHORT_DELAY_MS, MILLISECONDS);
+ if (f != null)
assertTrue(f.isDone());
- } catch (Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
}
+ /**
+ * Submitting to underlying AES that overrides newTaskFor(Callable)
+ * returns and eventually runs Future returned by newTaskFor.
+ */
+ public void testNewTaskForCallable() throws InterruptedException {
+ final AtomicBoolean done = new AtomicBoolean(false);
+ class MyCallableFuture<V> extends FutureTask<V> {
+ MyCallableFuture(Callable<V> c) { super(c); }
+ protected void done() { done.set(true); }
+ }
+ ExecutorService e = new ThreadPoolExecutor(
+ 1, 1, 30L, TimeUnit.SECONDS,
+ new ArrayBlockingQueue<Runnable>(1)) {
+ protected <T> RunnableFuture<T> newTaskFor(Callable<T> c) {
+ return new MyCallableFuture<T>(c);
+ }
+ };
+ ExecutorCompletionService<String> ecs =
+ new ExecutorCompletionService<String>(e);
+ try {
+ assertNull(ecs.poll());
+ Callable<String> c = new StringTask();
+ Future f1 = ecs.submit(c);
+ assertTrue("submit must return MyCallableFuture",
+ f1 instanceof MyCallableFuture);
+ Future f2 = ecs.take();
+ assertSame("submit and take must return same objects", f1, f2);
+ assertTrue("completed task must have set done", done.get());
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * Submitting to underlying AES that overrides newTaskFor(Runnable,T)
+ * returns and eventually runs Future returned by newTaskFor.
+ */
+ public void testNewTaskForRunnable() throws InterruptedException {
+ final AtomicBoolean done = new AtomicBoolean(false);
+ class MyRunnableFuture<V> extends FutureTask<V> {
+ MyRunnableFuture(Runnable t, V r) { super(t, r); }
+ protected void done() { done.set(true); }
+ }
+ ExecutorService e = new ThreadPoolExecutor(
+ 1, 1, 30L, TimeUnit.SECONDS,
+ new ArrayBlockingQueue<Runnable>(1)) {
+ protected <T> RunnableFuture<T> newTaskFor(Runnable t, T r) {
+ return new MyRunnableFuture<T>(t, r);
+ }
+ };
+ ExecutorCompletionService<String> ecs =
+ new ExecutorCompletionService<String>(e);
+ try {
+ assertNull(ecs.poll());
+ Runnable r = new NoOpRunnable();
+ Future f1 = ecs.submit(r, null);
+ assertTrue("submit must return MyRunnableFuture",
+ f1 instanceof MyRunnableFuture);
+ Future f2 = ecs.take();
+ assertSame("submit and take must return same objects", f1, f2);
+ assertTrue("completed task must have set done", done.get());
+ } finally {
+ joinPool(e);
+ }
+ }
+
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/ExecutorsTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/ExecutorsTest.java
index b0a2ccd..f29a712 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/ExecutorsTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/ExecutorsTest.java
@@ -2,63 +2,24 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.*;
import java.util.concurrent.*;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.math.BigInteger;
import java.security.*;
-public class ExecutorsTest extends JSR166TestCase{
+public class ExecutorsTest extends JSR166TestCase {
public static Test suite() {
return new TestSuite(ExecutorsTest.class);
}
- static class TimedCallable<T> implements Callable<T> {
- private final ExecutorService exec;
- private final Callable<T> func;
- private final long msecs;
-
- TimedCallable(ExecutorService exec, Callable<T> func, long msecs) {
- this.exec = exec;
- this.func = func;
- this.msecs = msecs;
- }
-
- public T call() throws Exception {
- Future<T> ftask = exec.submit(func);
- try {
- return ftask.get(msecs, TimeUnit.MILLISECONDS);
- } finally {
- ftask.cancel(true);
- }
- }
- }
-
-
- private static class Fib implements Callable<BigInteger> {
- private final BigInteger n;
- Fib(long n) {
- if (n < 0) throw new IllegalArgumentException("need non-negative arg, but got " + n);
- this.n = BigInteger.valueOf(n);
- }
- public BigInteger call() {
- BigInteger f1 = BigInteger.ONE;
- BigInteger f2 = f1;
- for (BigInteger i = BigInteger.ZERO; i.compareTo(n) < 0; i = i.add(BigInteger.ONE)) {
- BigInteger t = f1.add(f2);
- f1 = f2;
- f2 = t;
- }
- return f1;
- }
- };
-
/**
* A newCachedThreadPool can execute runnables
*/
@@ -88,9 +49,7 @@ public class ExecutorsTest extends JSR166TestCase{
try {
ExecutorService e = Executors.newCachedThreadPool(null);
shouldThrow();
- }
- catch(NullPointerException success) {
- }
+ } catch (NullPointerException success) {}
}
@@ -123,9 +82,7 @@ public class ExecutorsTest extends JSR166TestCase{
try {
ExecutorService e = Executors.newSingleThreadExecutor(null);
shouldThrow();
- }
- catch(NullPointerException success) {
- }
+ } catch (NullPointerException success) {}
}
/**
@@ -135,6 +92,7 @@ public class ExecutorsTest extends JSR166TestCase{
ExecutorService e = Executors.newSingleThreadExecutor();
try {
ThreadPoolExecutor tpe = (ThreadPoolExecutor)e;
+ shouldThrow();
} catch (ClassCastException success) {
} finally {
joinPool(e);
@@ -171,9 +129,7 @@ public class ExecutorsTest extends JSR166TestCase{
try {
ExecutorService e = Executors.newFixedThreadPool(2, null);
shouldThrow();
- }
- catch(NullPointerException success) {
- }
+ } catch (NullPointerException success) {}
}
/**
@@ -183,9 +139,7 @@ public class ExecutorsTest extends JSR166TestCase{
try {
ExecutorService e = Executors.newFixedThreadPool(0);
shouldThrow();
- }
- catch(IllegalArgumentException success) {
- }
+ } catch (IllegalArgumentException success) {}
}
@@ -206,9 +160,8 @@ public class ExecutorsTest extends JSR166TestCase{
public void testunconfigurableExecutorServiceNPE() {
try {
ExecutorService e = Executors.unconfigurableExecutorService(null);
- }
- catch (NullPointerException success) {
- }
+ shouldThrow();
+ } catch (NullPointerException success) {}
}
/**
@@ -217,109 +170,82 @@ public class ExecutorsTest extends JSR166TestCase{
public void testunconfigurableScheduledExecutorServiceNPE() {
try {
ExecutorService e = Executors.unconfigurableScheduledExecutorService(null);
- }
- catch (NullPointerException success) {
- }
+ shouldThrow();
+ } catch (NullPointerException success) {}
}
/**
* a newSingleThreadScheduledExecutor successfully runs delayed task
*/
- public void testNewSingleThreadScheduledExecutor() {
- try {
- TrackedCallable callable = new TrackedCallable();
- ScheduledExecutorService p1 = Executors.newSingleThreadScheduledExecutor();
- Future f = p1.schedule(callable, SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
- assertFalse(callable.done);
- Thread.sleep(MEDIUM_DELAY_MS);
- assertTrue(callable.done);
- assertEquals(Boolean.TRUE, f.get());
- joinPool(p1);
- } catch(RejectedExecutionException e){}
- catch(Exception e){
- e.printStackTrace();
- unexpectedException();
- }
+ public void testNewSingleThreadScheduledExecutor() throws Exception {
+ TrackedCallable callable = new TrackedCallable();
+ ScheduledExecutorService p1 = Executors.newSingleThreadScheduledExecutor();
+ Future f = p1.schedule(callable, SHORT_DELAY_MS, MILLISECONDS);
+ assertFalse(callable.done);
+ Thread.sleep(MEDIUM_DELAY_MS);
+ assertTrue(callable.done);
+ assertEquals(Boolean.TRUE, f.get());
+ joinPool(p1);
}
/**
* a newScheduledThreadPool successfully runs delayed task
*/
- public void testnewScheduledThreadPool() {
- try {
- TrackedCallable callable = new TrackedCallable();
- ScheduledExecutorService p1 = Executors.newScheduledThreadPool(2);
- Future f = p1.schedule(callable, SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
- assertFalse(callable.done);
- Thread.sleep(MEDIUM_DELAY_MS);
- assertTrue(callable.done);
- assertEquals(Boolean.TRUE, f.get());
- joinPool(p1);
- } catch(RejectedExecutionException e){}
- catch(Exception e){
- e.printStackTrace();
- unexpectedException();
- }
+ public void testnewScheduledThreadPool() throws Exception {
+ TrackedCallable callable = new TrackedCallable();
+ ScheduledExecutorService p1 = Executors.newScheduledThreadPool(2);
+ Future f = p1.schedule(callable, SHORT_DELAY_MS, MILLISECONDS);
+ assertFalse(callable.done);
+ Thread.sleep(MEDIUM_DELAY_MS);
+ assertTrue(callable.done);
+ assertEquals(Boolean.TRUE, f.get());
+ joinPool(p1);
}
/**
- * an unconfigurable newScheduledThreadPool successfully runs delayed task
+ * an unconfigurable newScheduledThreadPool successfully runs delayed task
*/
- public void testunconfigurableScheduledExecutorService() {
- try {
- TrackedCallable callable = new TrackedCallable();
- ScheduledExecutorService p1 = Executors.unconfigurableScheduledExecutorService(Executors.newScheduledThreadPool(2));
- Future f = p1.schedule(callable, SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
- assertFalse(callable.done);
- Thread.sleep(MEDIUM_DELAY_MS);
- assertTrue(callable.done);
- assertEquals(Boolean.TRUE, f.get());
- joinPool(p1);
- } catch(RejectedExecutionException e){}
- catch(Exception e){
- e.printStackTrace();
- unexpectedException();
- }
+ public void testunconfigurableScheduledExecutorService() throws Exception {
+ TrackedCallable callable = new TrackedCallable();
+ ScheduledExecutorService p1 = Executors.unconfigurableScheduledExecutorService(Executors.newScheduledThreadPool(2));
+ Future f = p1.schedule(callable, SHORT_DELAY_MS, MILLISECONDS);
+ assertFalse(callable.done);
+ Thread.sleep(MEDIUM_DELAY_MS);
+ assertTrue(callable.done);
+ assertEquals(Boolean.TRUE, f.get());
+ joinPool(p1);
}
/**
- * timeouts from execute will time out if they compute too long.
+ * Future.get on submitted tasks will time out if they compute too long.
*/
- public void testTimedCallable() {
- int N = 10000;
- ExecutorService executor = Executors.newSingleThreadExecutor();
- List<Callable<BigInteger>> tasks = new ArrayList<Callable<BigInteger>>(N);
- try {
- long startTime = System.currentTimeMillis();
-
- long i = 0;
- while (tasks.size() < N) {
- tasks.add(new TimedCallable<BigInteger>(executor, new Fib(i), 1));
- i += 10;
- }
-
- int iters = 0;
- BigInteger sum = BigInteger.ZERO;
- for (Iterator<Callable<BigInteger>> it = tasks.iterator(); it.hasNext();) {
+ public void testTimedCallable() throws Exception {
+ final Runnable sleeper =
+ new RunnableShouldThrow(InterruptedException.class) {
+ public void realRun() throws InterruptedException {
+ Thread.sleep(LONG_DELAY_MS);
+ }};
+ for (ExecutorService executor :
+ new ExecutorService[] {
+ Executors.newSingleThreadExecutor(),
+ Executors.newCachedThreadPool(),
+ Executors.newFixedThreadPool(2),
+ Executors.newScheduledThreadPool(2),
+ }) {
+ try {
+ Future future = executor.submit(sleeper);
try {
- ++iters;
- sum = sum.add(it.next().call());
- }
- catch (TimeoutException success) {
- assertTrue(iters > 0);
- return;
- }
- catch (Exception e) {
- unexpectedException();
+ future.get(SHORT_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (TimeoutException success) {
+ } finally {
+ future.cancel(true);
}
}
- // if by chance we didn't ever time out, total time must be small
- long elapsed = System.currentTimeMillis() - startTime;
- assertTrue(elapsed < N);
- }
- finally {
- joinPool(executor);
+ finally {
+ joinPool(executor);
+ }
}
}
@@ -328,25 +254,25 @@ public class ExecutorsTest extends JSR166TestCase{
* ThreadPoolExecutor using defaultThreadFactory has
* specified group, priority, daemon status, and name
*/
- public void testDefaultThreadFactory() {
+ public void testDefaultThreadFactory() throws Exception {
final ThreadGroup egroup = Thread.currentThread().getThreadGroup();
Runnable r = new Runnable() {
public void run() {
- try {
- Thread current = Thread.currentThread();
- threadAssertTrue(!current.isDaemon());
- threadAssertTrue(current.getPriority() <= Thread.NORM_PRIORITY);
- ThreadGroup g = current.getThreadGroup();
- SecurityManager s = System.getSecurityManager();
- if (s != null)
- threadAssertTrue(g == s.getThreadGroup());
- else
- threadAssertTrue(g == egroup);
- String name = current.getName();
- threadAssertTrue(name.endsWith("thread-1"));
- } catch (SecurityException ok) {
- // Also pass if not allowed to change setting
- }
+ try {
+ Thread current = Thread.currentThread();
+ threadAssertTrue(!current.isDaemon());
+ threadAssertTrue(current.getPriority() <= Thread.NORM_PRIORITY);
+ ThreadGroup g = current.getThreadGroup();
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ threadAssertTrue(g == s.getThreadGroup());
+ else
+ threadAssertTrue(g == egroup);
+ String name = current.getName();
+ threadAssertTrue(name.endsWith("thread-1"));
+ } catch (SecurityException ok) {
+ // Also pass if not allowed to change setting
+ }
}
};
ExecutorService e = Executors.newSingleThreadExecutor(Executors.defaultThreadFactory());
@@ -354,13 +280,11 @@ public class ExecutorsTest extends JSR166TestCase{
e.execute(r);
try {
e.shutdown();
- } catch(SecurityException ok) {
+ } catch (SecurityException ok) {
}
try {
Thread.sleep(SHORT_DELAY_MS);
- } catch (Exception eX) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -371,61 +295,60 @@ public class ExecutorsTest extends JSR166TestCase{
* specified group, priority, daemon status, name,
* access control context and context class loader
*/
- public void testPrivilegedThreadFactory() {
- 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;
- }
- final ThreadGroup egroup = Thread.currentThread().getThreadGroup();
- final ClassLoader thisccl = Thread.currentThread().getContextClassLoader();
- final AccessControlContext thisacc = AccessController.getContext();
- Runnable r = new Runnable() {
- public void run() {
- try {
- Thread current = Thread.currentThread();
- threadAssertTrue(!current.isDaemon());
- threadAssertTrue(current.getPriority() <= Thread.NORM_PRIORITY);
- ThreadGroup g = current.getThreadGroup();
- SecurityManager s = System.getSecurityManager();
- if (s != null)
- threadAssertTrue(g == s.getThreadGroup());
- else
- threadAssertTrue(g == egroup);
- String name = current.getName();
- threadAssertTrue(name.endsWith("thread-1"));
- threadAssertTrue(thisccl == current.getContextClassLoader());
- threadAssertTrue(thisacc.equals(AccessController.getContext()));
- } catch(SecurityException ok) {
- // Also pass if not allowed to change settings
- }
- }
- };
- ExecutorService e = Executors.newSingleThreadExecutor(Executors.privilegedThreadFactory());
-
- Policy.setPolicy(savedPolicy);
- e.execute(r);
- try {
- e.shutdown();
- } catch(SecurityException ok) {
- }
- try {
- Thread.sleep(SHORT_DELAY_MS);
- } catch (Exception ex) {
- unexpectedException();
- } finally {
- joinPool(e);
+ public void testPrivilegedThreadFactory() throws Exception {
+ Runnable r = new CheckedRunnable() {
+ public void realRun() throws Exception {
+ final ThreadGroup egroup = Thread.currentThread().getThreadGroup();
+ final ClassLoader thisccl = Thread.currentThread().getContextClassLoader();
+ final AccessControlContext thisacc = AccessController.getContext();
+ Runnable r = new CheckedRunnable() {
+ public void realRun() {
+ Thread current = Thread.currentThread();
+ assertTrue(!current.isDaemon());
+ assertTrue(current.getPriority() <= Thread.NORM_PRIORITY);
+ ThreadGroup g = current.getThreadGroup();
+ SecurityManager s = System.getSecurityManager();
+ if (s != null)
+ assertTrue(g == s.getThreadGroup());
+ else
+ assertTrue(g == egroup);
+ String name = current.getName();
+ assertTrue(name.endsWith("thread-1"));
+ assertTrue(thisccl == current.getContextClassLoader());
+ assertTrue(thisacc.equals(AccessController.getContext()));
+ }};
+ ExecutorService e = Executors.newSingleThreadExecutor(Executors.privilegedThreadFactory());
+ e.execute(r);
+ e.shutdown();
+ Thread.sleep(SHORT_DELAY_MS);
+ joinPool(e);
+ }};
+
+ runWithPermissions(r,
+ new RuntimePermission("getClassLoader"),
+ new RuntimePermission("setContextClassLoader"),
+ new RuntimePermission("modifyThread"));
+ }
+
+ boolean haveCCLPermissions() {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ try {
+ sm.checkPermission(new RuntimePermission("setContextClassLoader"));
+ sm.checkPermission(new RuntimePermission("getClassLoader"));
+ } catch (AccessControlException e) {
+ return false;
+ }
}
-
+ return true;
}
void checkCCL() {
- AccessController.getContext().checkPermission(new RuntimePermission("getContextClassLoader"));
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(new RuntimePermission("setContextClassLoader"));
+ sm.checkPermission(new RuntimePermission("getClassLoader"));
+ }
}
class CheckCCL implements Callable<Object> {
@@ -441,222 +364,192 @@ public class ExecutorsTest extends JSR166TestCase{
* privilegedCallableUsingCurrentClassLoader throws ACE
*/
public void testCreatePrivilegedCallableUsingCCLWithNoPrivs() {
- Policy savedPolicy = null;
- try {
- savedPolicy = Policy.getPolicy();
- AdjustablePolicy policy = new AdjustablePolicy();
- Policy.setPolicy(policy);
- } catch (AccessControlException ok) {
- return;
- }
-
- // Check if program still has too many permissions to run test
- try {
- checkCCL();
- // too many privileges to test; so return
- Policy.setPolicy(savedPolicy);
- return;
- } catch(AccessControlException ok) {
- }
+ Runnable r = new CheckedRunnable() {
+ public void realRun() throws Exception {
+ if (System.getSecurityManager() == null)
+ return;
+ try {
+ Executors.privilegedCallableUsingCurrentClassLoader(new NoOpCallable());
+ shouldThrow();
+ } catch (AccessControlException success) {}
+ }};
- try {
- Callable task = Executors.privilegedCallableUsingCurrentClassLoader(new NoOpCallable());
- shouldThrow();
- } catch(AccessControlException success) {
- } catch(Exception ex) {
- unexpectedException();
- }
- finally {
- Policy.setPolicy(savedPolicy);
- }
+ runWithoutPermissions(r);
}
/**
* With class loader permissions, calling
* privilegedCallableUsingCurrentClassLoader does not throw ACE
*/
- public void testprivilegedCallableUsingCCLWithPrivs() {
- 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;
- }
+ public void testprivilegedCallableUsingCCLWithPrivs() throws Exception {
+ Runnable r = new CheckedRunnable() {
+ public void realRun() throws Exception {
+ Executors.privilegedCallableUsingCurrentClassLoader
+ (new NoOpCallable())
+ .call();
+ }};
- try {
- Callable task = Executors.privilegedCallableUsingCurrentClassLoader(new NoOpCallable());
- task.call();
- } catch(Exception ex) {
- unexpectedException();
- }
- finally {
- Policy.setPolicy(savedPolicy);
- }
+ runWithPermissions(r,
+ new RuntimePermission("getClassLoader"),
+ new RuntimePermission("setContextClassLoader"));
}
/**
* Without permissions, calling privilegedCallable throws ACE
*/
- public void testprivilegedCallableWithNoPrivs() {
- Callable task;
- Policy savedPolicy = null;
- AdjustablePolicy policy = null;
- AccessControlContext noprivAcc = null;
- try {
- savedPolicy = Policy.getPolicy();
- policy = new AdjustablePolicy();
- Policy.setPolicy(policy);
- noprivAcc = AccessController.getContext();
- task = Executors.privilegedCallable(new CheckCCL());
- Policy.setPolicy(savedPolicy);
- } catch (AccessControlException ok) {
- return; // program has too few permissions to set up test
- }
-
- // Make sure that program doesn't have too many permissions
- try {
- AccessController.doPrivileged(new PrivilegedAction() {
- public Object run() {
- checkCCL();
- return null;
- }}, noprivAcc);
- // too many permssions; skip test
- return;
- } catch(AccessControlException ok) {
- }
-
- try {
- task.call();
- shouldThrow();
- } catch(AccessControlException success) {
- } catch(Exception ex) {
- unexpectedException();
- }
+ public void testprivilegedCallableWithNoPrivs() throws Exception {
+ Runnable r = new CheckedRunnable() {
+ public void realRun() throws Exception {
+ if (System.getSecurityManager() == null)
+ return;
+ Callable task = Executors.privilegedCallable(new CheckCCL());
+ try {
+ task.call();
+ shouldThrow();
+ } catch (AccessControlException success) {}
+ }};
+
+ runWithoutPermissions(r);
+
+ // It seems rather difficult to test that the
+ // AccessControlContext of the privilegedCallable is used
+ // instead of its caller. Below is a failed attempt to do
+ // that, which does not work because the AccessController
+ // cannot capture the internal state of the current Policy.
+ // It would be much more work to differentiate based on,
+ // e.g. CodeSource.
+
+// final AccessControlContext[] noprivAcc = new AccessControlContext[1];
+// final Callable[] task = new Callable[1];
+
+// runWithPermissions
+// (new CheckedRunnable() {
+// public void realRun() {
+// if (System.getSecurityManager() == null)
+// return;
+// noprivAcc[0] = AccessController.getContext();
+// task[0] = Executors.privilegedCallable(new CheckCCL());
+// try {
+// AccessController.doPrivileged(new PrivilegedAction<Void>() {
+// public Void run() {
+// checkCCL();
+// return null;
+// }}, noprivAcc[0]);
+// shouldThrow();
+// } catch (AccessControlException success) {}
+// }});
+
+// runWithPermissions
+// (new CheckedRunnable() {
+// public void realRun() throws Exception {
+// if (System.getSecurityManager() == null)
+// return;
+// // Verify that we have an underprivileged ACC
+// try {
+// AccessController.doPrivileged(new PrivilegedAction<Void>() {
+// public Void run() {
+// checkCCL();
+// return null;
+// }}, noprivAcc[0]);
+// shouldThrow();
+// } catch (AccessControlException success) {}
+
+// try {
+// task[0].call();
+// shouldThrow();
+// } catch (AccessControlException success) {}
+// }},
+// new RuntimePermission("getClassLoader"),
+// new RuntimePermission("setContextClassLoader"));
}
/**
* With permissions, calling privilegedCallable succeeds
*/
- public void testprivilegedCallableWithPrivs() {
- 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;
- }
-
- Callable task = Executors.privilegedCallable(new CheckCCL());
- try {
- task.call();
- } catch(Exception ex) {
- unexpectedException();
- } finally {
- Policy.setPolicy(savedPolicy);
- }
+ public void testprivilegedCallableWithPrivs() throws Exception {
+ Runnable r = new CheckedRunnable() {
+ public void realRun() throws Exception {
+ Executors.privilegedCallable(new CheckCCL()).call();
+ }};
+
+ runWithPermissions(r,
+ new RuntimePermission("getClassLoader"),
+ new RuntimePermission("setContextClassLoader"));
}
/**
* callable(Runnable) returns null when called
- */
- public void testCallable1() {
- try {
- Callable c = Executors.callable(new NoOpRunnable());
- assertNull(c.call());
- } catch(Exception ex) {
- unexpectedException();
- }
-
+ */
+ public void testCallable1() throws Exception {
+ Callable c = Executors.callable(new NoOpRunnable());
+ assertNull(c.call());
}
/**
* callable(Runnable, result) returns result when called
- */
- public void testCallable2() {
- try {
- Callable c = Executors.callable(new NoOpRunnable(), one);
- assertEquals(one, c.call());
- } catch(Exception ex) {
- unexpectedException();
- }
+ */
+ public void testCallable2() throws Exception {
+ Callable c = Executors.callable(new NoOpRunnable(), one);
+ assertSame(one, c.call());
}
/**
* callable(PrivilegedAction) returns its result when called
- */
- public void testCallable3() {
- try {
- Callable c = Executors.callable(new PrivilegedAction() {
- public Object run() { return one; }});
- assertEquals(one, c.call());
- } catch(Exception ex) {
- unexpectedException();
- }
+ */
+ public void testCallable3() throws Exception {
+ Callable c = Executors.callable(new PrivilegedAction() {
+ public Object run() { return one; }});
+ assertSame(one, c.call());
}
/**
* callable(PrivilegedExceptionAction) returns its result when called
- */
- public void testCallable4() {
- try {
- Callable c = Executors.callable(new PrivilegedExceptionAction() {
- public Object run() { return one; }});
- assertEquals(one, c.call());
- } catch(Exception ex) {
- unexpectedException();
- }
+ */
+ public void testCallable4() throws Exception {
+ Callable c = Executors.callable(new PrivilegedExceptionAction() {
+ public Object run() { return one; }});
+ assertSame(one, c.call());
}
/**
* callable(null Runnable) throws NPE
- */
+ */
public void testCallableNPE1() {
try {
- Runnable r = null;
- Callable c = Executors.callable(r);
- } catch (NullPointerException success) {
- }
+ Callable c = Executors.callable((Runnable) null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
}
/**
* callable(null, result) throws NPE
- */
+ */
public void testCallableNPE2() {
try {
- Runnable r = null;
- Callable c = Executors.callable(r, one);
- } catch (NullPointerException success) {
- }
+ Callable c = Executors.callable((Runnable) null, one);
+ shouldThrow();
+ } catch (NullPointerException success) {}
}
/**
* callable(null PrivilegedAction) throws NPE
- */
+ */
public void testCallableNPE3() {
try {
- PrivilegedAction r = null;
- Callable c = Executors.callable(r);
- } catch (NullPointerException success) {
- }
+ Callable c = Executors.callable((PrivilegedAction) null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
}
/**
* callable(null PrivilegedExceptionAction) throws NPE
- */
+ */
public void testCallableNPE4() {
try {
- PrivilegedExceptionAction r = null;
- Callable c = Executors.callable(r);
- } catch (NullPointerException success) {
- }
+ Callable c = Executors.callable((PrivilegedExceptionAction) null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/FutureTaskTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/FutureTaskTest.java
index 2635054..b1f9f40 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/FutureTaskTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/FutureTaskTest.java
@@ -2,14 +2,15 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.concurrent.*;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.*;
public class FutureTaskTest extends JSR166TestCase {
@@ -34,9 +35,7 @@ public class FutureTaskTest extends JSR166TestCase {
try {
FutureTask task = new FutureTask(null);
shouldThrow();
- }
- catch(NullPointerException success) {
- }
+ } catch (NullPointerException success) {}
}
/**
@@ -46,16 +45,14 @@ public class FutureTaskTest extends JSR166TestCase {
try {
FutureTask task = new FutureTask(null, Boolean.TRUE);
shouldThrow();
- }
- catch(NullPointerException success) {
- }
+ } catch (NullPointerException success) {}
}
/**
* isDone is true when a task completes
*/
public void testIsDone() {
- FutureTask task = new FutureTask( new NoOpCallable());
+ FutureTask task = new FutureTask(new NoOpCallable());
task.run();
assertTrue(task.isDone());
assertFalse(task.isCancelled());
@@ -86,34 +83,24 @@ public class FutureTaskTest extends JSR166TestCase {
/**
* setting value causes get to return it
*/
- public void testSet() {
+ public void testSet() throws Exception {
PublicFutureTask task = new PublicFutureTask(new NoOpCallable());
task.set(one);
- try {
- assertEquals(task.get(), one);
- }
- catch(Exception e) {
- unexpectedException();
- }
+ assertSame(task.get(), one);
}
/**
* setException causes get to throw ExecutionException
*/
- public void testSetException() {
+ public void testSetException() throws Exception {
Exception nse = new NoSuchElementException();
PublicFutureTask task = new PublicFutureTask(new NoOpCallable());
task.setException(nse);
try {
Object x = task.get();
shouldThrow();
- }
- catch(ExecutionException ee) {
- Throwable cause = ee.getCause();
- assertEquals(cause, nse);
- }
- catch(Exception e) {
- unexpectedException();
+ } catch (ExecutionException success) {
+ assertSame(success.getCause(), nse);
}
}
@@ -121,7 +108,7 @@ public class FutureTaskTest extends JSR166TestCase {
* Cancelling before running succeeds
*/
public void testCancelBeforeRun() {
- FutureTask task = new FutureTask( new NoOpCallable());
+ FutureTask task = new FutureTask(new NoOpCallable());
assertTrue(task.cancel(false));
task.run();
assertTrue(task.isDone());
@@ -132,7 +119,7 @@ public class FutureTaskTest extends JSR166TestCase {
* Cancel(true) before run succeeds
*/
public void testCancelBeforeRun2() {
- FutureTask task = new FutureTask( new NoOpCallable());
+ FutureTask task = new FutureTask(new NoOpCallable());
assertTrue(task.cancel(true));
task.run();
assertTrue(task.isDone());
@@ -143,7 +130,7 @@ public class FutureTaskTest extends JSR166TestCase {
* cancel of a completed task fails
*/
public void testCancelAfterRun() {
- FutureTask task = new FutureTask( new NoOpCallable());
+ FutureTask task = new FutureTask(new NoOpCallable());
task.run();
assertFalse(task.cancel(false));
assertTrue(task.isDone());
@@ -153,320 +140,219 @@ public class FutureTaskTest extends JSR166TestCase {
/**
* cancel(true) interrupts a running task
*/
- public void testCancelInterrupt() {
- FutureTask task = new FutureTask( new Callable() {
- public Object call() {
- try {
- Thread.sleep(MEDIUM_DELAY_MS);
- threadShouldThrow();
- }
- catch (InterruptedException success) {}
+ public void testCancelInterrupt() throws InterruptedException {
+ final FutureTask task =
+ new FutureTask(new CheckedInterruptedCallable<Object>() {
+ public Object realCall() throws InterruptedException {
+ Thread.sleep(SMALL_DELAY_MS);
return Boolean.TRUE;
- } });
- Thread t = new Thread(task);
+ }});
+
+ Thread t = new Thread(task);
t.start();
-
- try {
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(task.cancel(true));
- t.join();
- assertTrue(task.isDone());
- assertTrue(task.isCancelled());
- } catch(InterruptedException e){
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(task.cancel(true));
+ t.join();
+ assertTrue(task.isDone());
+ assertTrue(task.isCancelled());
}
/**
* cancel(false) does not interrupt a running task
*/
- public void testCancelNoInterrupt() {
- FutureTask task = new FutureTask( new Callable() {
- public Object call() {
- try {
- Thread.sleep(MEDIUM_DELAY_MS);
- }
- catch (InterruptedException success) {
- threadFail("should not interrupt");
- }
+ public void testCancelNoInterrupt() throws InterruptedException {
+ final FutureTask task =
+ new FutureTask(new CheckedCallable<Object>() {
+ public Object realCall() throws InterruptedException {
+ Thread.sleep(MEDIUM_DELAY_MS);
return Boolean.TRUE;
- } });
- Thread t = new Thread(task);
+ }});
+
+ Thread t = new Thread(task);
t.start();
-
- try {
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(task.cancel(false));
- t.join();
- assertTrue(task.isDone());
- assertTrue(task.isCancelled());
- } catch(InterruptedException e){
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(task.cancel(false));
+ t.join();
+ assertTrue(task.isDone());
+ assertTrue(task.isCancelled());
}
/**
* set in one thread causes get in another thread to retrieve value
*/
- public void testGet1() {
- final FutureTask ft = new FutureTask(new Callable() {
- public Object call() {
- try {
- Thread.sleep(MEDIUM_DELAY_MS);
- } catch(InterruptedException e){
- threadUnexpectedException();
- }
+ public void testGet1() throws InterruptedException {
+ final FutureTask ft =
+ new FutureTask(new CheckedCallable<Object>() {
+ public Object realCall() throws InterruptedException {
return Boolean.TRUE;
- }
- });
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- ft.get();
- } catch(Exception e){
- threadUnexpectedException();
- }
- }
- });
- try {
- assertFalse(ft.isDone());
- assertFalse(ft.isCancelled());
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- ft.run();
- t.join();
- assertTrue(ft.isDone());
- assertFalse(ft.isCancelled());
- } catch(InterruptedException e){
- unexpectedException();
-
- }
+ }});
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws Exception {
+ assertSame(Boolean.TRUE, ft.get());
+ }});
+
+ assertFalse(ft.isDone());
+ assertFalse(ft.isCancelled());
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ ft.run();
+ t.join();
+ assertTrue(ft.isDone());
+ assertFalse(ft.isCancelled());
}
/**
* set in one thread causes timed get in another thread to retrieve value
*/
- public void testTimedGet1() {
- final FutureTask ft = new FutureTask(new Callable() {
- public Object call() {
- try {
- Thread.sleep(MEDIUM_DELAY_MS);
- } catch(InterruptedException e){
- threadUnexpectedException();
- }
+ public void testTimedGet1() throws InterruptedException {
+ final FutureTask ft =
+ new FutureTask(new CheckedCallable<Object>() {
+ public Object realCall() throws InterruptedException {
return Boolean.TRUE;
- }
- });
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- ft.get(SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
- } catch(TimeoutException success) {
- } catch(Exception e){
- threadUnexpectedException();
- }
- }
- });
- try {
- assertFalse(ft.isDone());
- assertFalse(ft.isCancelled());
- t.start();
- ft.run();
- t.join();
- assertTrue(ft.isDone());
- assertFalse(ft.isCancelled());
- } catch(InterruptedException e){
- unexpectedException();
-
- }
+ }});
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws Exception {
+ assertSame(Boolean.TRUE, ft.get(SMALL_DELAY_MS, MILLISECONDS));
+ }});
+
+ assertFalse(ft.isDone());
+ assertFalse(ft.isCancelled());
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ ft.run();
+ t.join();
+ assertTrue(ft.isDone());
+ assertFalse(ft.isCancelled());
}
/**
* Cancelling a task causes timed get in another thread to throw CancellationException
*/
- public void testTimedGet_Cancellation() {
- final FutureTask ft = new FutureTask(new Callable() {
- public Object call() {
- try {
- Thread.sleep(SMALL_DELAY_MS);
- threadShouldThrow();
- } catch(InterruptedException e) {
- }
+ public void testTimedGet_Cancellation() throws InterruptedException {
+ final FutureTask ft =
+ new FutureTask(new CheckedInterruptedCallable<Object>() {
+ public Object realCall() throws InterruptedException {
+ Thread.sleep(SMALL_DELAY_MS);
return Boolean.TRUE;
- }
- });
- try {
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- try {
- ft.get(MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
- threadShouldThrow();
- } catch(CancellationException success) {}
- catch(Exception e){
- threadUnexpectedException();
- }
- }
- });
- Thread t2 = new Thread(ft);
- t1.start();
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- ft.cancel(true);
- t1.join();
- t2.join();
- } catch(InterruptedException ie){
- unexpectedException();
- }
+ }});
+
+ Thread t1 = new ThreadShouldThrow(CancellationException.class) {
+ public void realRun() throws Exception {
+ ft.get(MEDIUM_DELAY_MS, MILLISECONDS);
+ }};
+ Thread t2 = new Thread(ft);
+ t1.start();
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ ft.cancel(true);
+ t1.join();
+ t2.join();
}
/**
* Cancelling a task causes get in another thread to throw CancellationException
*/
- public void testGet_Cancellation() {
- final FutureTask ft = new FutureTask(new Callable() {
- public Object call() {
- try {
- Thread.sleep(MEDIUM_DELAY_MS);
- threadShouldThrow();
- } catch(InterruptedException e){
- }
+ public void testGet_Cancellation() throws InterruptedException {
+ final FutureTask ft =
+ new FutureTask(new CheckedInterruptedCallable<Object>() {
+ public Object realCall() throws InterruptedException {
+ Thread.sleep(SMALL_DELAY_MS);
return Boolean.TRUE;
- }
- });
- try {
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- try {
- ft.get();
- threadShouldThrow();
- } catch(CancellationException success){
- }
- catch(Exception e){
- threadUnexpectedException();
- }
- }
- });
- Thread t2 = new Thread(ft);
- t1.start();
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- ft.cancel(true);
- t1.join();
- t2.join();
- } catch(InterruptedException success){
- unexpectedException();
- }
+ }});
+ Thread t1 = new ThreadShouldThrow(CancellationException.class) {
+ public void realRun() throws Exception {
+ ft.get();
+ }};
+
+ Thread t2 = new Thread(ft);
+ t1.start();
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ ft.cancel(true);
+ t1.join();
+ t2.join();
}
-
+
/**
* A runtime exception in task causes get to throw ExecutionException
*/
- public void testGet_ExecutionException() {
+ public void testGet_ExecutionException() throws InterruptedException {
final FutureTask ft = new FutureTask(new Callable() {
- public Object call() {
- int i = 5/0;
- return Boolean.TRUE;
- }
- });
+ public Object call() {
+ return 5/0;
+ }});
+
+ ft.run();
try {
- ft.run();
ft.get();
shouldThrow();
- } catch(ExecutionException success){
- }
- catch(Exception e){
- unexpectedException();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof ArithmeticException);
}
}
-
+
/**
* A runtime exception in task causes timed get to throw ExecutionException
*/
- public void testTimedGet_ExecutionException2() {
+ public void testTimedGet_ExecutionException2() throws Exception {
final FutureTask ft = new FutureTask(new Callable() {
- public Object call() {
- int i = 5/0;
- return Boolean.TRUE;
- }
- });
+ public Object call() {
+ return 5/0;
+ }});
+
+ ft.run();
try {
- ft.run();
- ft.get(SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
+ ft.get(SHORT_DELAY_MS, MILLISECONDS);
shouldThrow();
- } catch(ExecutionException success) {
- } catch(TimeoutException success) { } // unlikely but OK
- catch(Exception e){
- unexpectedException();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof ArithmeticException);
}
}
-
+
/**
* Interrupting a waiting get causes it to throw InterruptedException
*/
- public void testGet_InterruptedException() {
+ public void testGet_InterruptedException() throws InterruptedException {
final FutureTask ft = new FutureTask(new NoOpCallable());
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- ft.get();
- threadShouldThrow();
- } catch(InterruptedException success){
- } catch(Exception e){
- threadUnexpectedException();
- }
- }
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws Exception {
+ ft.get();
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* Interrupting a waiting timed get causes it to throw InterruptedException
*/
- public void testTimedGet_InterruptedException2() {
+ public void testTimedGet_InterruptedException2() throws InterruptedException {
final FutureTask ft = new FutureTask(new NoOpCallable());
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- ft.get(LONG_DELAY_MS,TimeUnit.MILLISECONDS);
- threadShouldThrow();
- } catch(InterruptedException success){}
- catch(Exception e){
- threadUnexpectedException();
- }
- }
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws Exception {
+ ft.get(LONG_DELAY_MS,MILLISECONDS);
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
-
+
/**
* A timed out timed get throws TimeoutException
*/
- public void testGet_TimeoutException() {
+ public void testGet_TimeoutException() throws Exception {
try {
FutureTask ft = new FutureTask(new NoOpCallable());
- ft.get(1,TimeUnit.MILLISECONDS);
+ ft.get(1,MILLISECONDS);
shouldThrow();
- } catch(TimeoutException success){}
- catch(Exception success){
- unexpectedException();
- }
+ } catch (TimeoutException success) {}
}
-
+
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/JSR166TestCase.java b/concurrent/src/test/java/tests/api/java/util/concurrent/JSR166TestCase.java
index 6acd363..b764855 100644
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/JSR166TestCase.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/JSR166TestCase.java
@@ -6,11 +6,12 @@
* Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.*;
import java.util.concurrent.*;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.io.*;
import java.security.*;
@@ -88,71 +89,91 @@ import java.security.*;
* </ul>
*/
public class JSR166TestCase extends TestCase {
- /**
- * Runs all JSR166 unit tests using junit.textui.TestRunner
- */
- public static void main (String[] args) {
- int iters = 1;
- if (args.length > 0)
- iters = Integer.parseInt(args[0]);
- Test s = suite();
- for (int i = 0; i < iters; ++i) {
- // junit.textui.TestRunner.run (s); android-changed
- System.gc();
- System.runFinalization();
- }
- System.exit(0);
- }
+ private static final boolean useSecurityManager =
+ Boolean.getBoolean("jsr166.useSecurityManager");
+
+ // BEGIN android-removed
+ // /**
+ // * Runs all JSR166 unit tests using junit.textui.TestRunner
+ // */
+ // public static void main(String[] args) {
+ // if (useSecurityManager) {
+ // System.err.println("Setting a permissive security manager");
+ // Policy.setPolicy(permissivePolicy());
+ // System.setSecurityManager(new SecurityManager());
+ // }
+ // int iters = 1;
+ // if (args.length > 0)
+ // iters = Integer.parseInt(args[0]);
+ // Test s = suite();
+ // for (int i = 0; i < iters; ++i) {
+ // junit.textui.TestRunner.run(s);
+ // System.gc();
+ // System.runFinalization();
+ // }
+ // System.exit(0);
+ // }
+ // END android-removed
/**
* Collects all JSR166 unit tests as one suite
*/
- public static Test suite ( ) {
- // BEGIN android-changed
+ public static Test suite() {
TestSuite suite = new TestSuite("JSR166 Unit Tests");
- suite.addTest(AbstractExecutorServiceTest.suite());
- suite.addTest(AbstractQueueTest.suite());
- suite.addTest(AbstractQueuedSynchronizerTest.suite());
- suite.addTest(ArrayBlockingQueueTest.suite());
- suite.addTest(AtomicBooleanTest.suite());
- suite.addTest(AtomicIntegerArrayTest.suite());
- suite.addTest(AtomicIntegerFieldUpdaterTest.suite());
- suite.addTest(AtomicIntegerTest.suite());
- suite.addTest(AtomicLongArrayTest.suite());
- suite.addTest(AtomicLongFieldUpdaterTest.suite());
- suite.addTest(AtomicLongTest.suite());
- suite.addTest(AtomicMarkableReferenceTest.suite());
- suite.addTest(AtomicReferenceArrayTest.suite());
- suite.addTest(AtomicReferenceFieldUpdaterTest.suite());
- suite.addTest(AtomicReferenceTest.suite());
- suite.addTest(AtomicStampedReferenceTest.suite());
- suite.addTest(ConcurrentHashMapTest.suite());
- suite.addTest(ConcurrentLinkedQueueTest.suite());
- suite.addTest(CopyOnWriteArrayListTest.suite());
- suite.addTest(CopyOnWriteArraySetTest.suite());
- suite.addTest(CountDownLatchTest.suite());
- suite.addTest(CyclicBarrierTest.suite());
- suite.addTest(DelayQueueTest.suite());
- suite.addTest(ExchangerTest.suite());
- suite.addTest(ExecutorsTest.suite());
- suite.addTest(ExecutorCompletionServiceTest.suite());
- suite.addTest(FutureTaskTest.suite());
- suite.addTest(LinkedBlockingQueueTest.suite());
- suite.addTest(LinkedListTest.suite());
- suite.addTest(LockSupportTest.suite());
- suite.addTest(PriorityBlockingQueueTest.suite());
- suite.addTest(PriorityQueueTest.suite());
- suite.addTest(ReentrantLockTest.suite());
- suite.addTest(ReentrantReadWriteLockTest.suite());
- suite.addTest(ScheduledExecutorTest.suite());
- suite.addTest(SemaphoreTest.suite());
- suite.addTest(SynchronousQueueTest.suite());
- suite.addTest(SystemTest.suite());
- suite.addTest(ThreadLocalTest.suite());
- suite.addTest(ThreadPoolExecutorTest.suite());
- suite.addTest(ThreadTest.suite());
- suite.addTest(TimeUnitTest.suite());
- // END android-changed
+
+ suite.addTest(new TestSuite(AbstractExecutorServiceTest.class));
+ suite.addTest(new TestSuite(AbstractQueueTest.class));
+ suite.addTest(new TestSuite(AbstractQueuedSynchronizerTest.class));
+ suite.addTest(new TestSuite(AbstractQueuedLongSynchronizerTest.class));
+ suite.addTest(new TestSuite(ArrayBlockingQueueTest.class));
+ suite.addTest(new TestSuite(ArrayDequeTest.class));
+ suite.addTest(new TestSuite(AtomicBooleanTest.class));
+ suite.addTest(new TestSuite(AtomicIntegerArrayTest.class));
+ suite.addTest(new TestSuite(AtomicIntegerFieldUpdaterTest.class));
+ suite.addTest(new TestSuite(AtomicIntegerTest.class));
+ suite.addTest(new TestSuite(AtomicLongArrayTest.class));
+ suite.addTest(new TestSuite(AtomicLongFieldUpdaterTest.class));
+ suite.addTest(new TestSuite(AtomicLongTest.class));
+ suite.addTest(new TestSuite(AtomicMarkableReferenceTest.class));
+ suite.addTest(new TestSuite(AtomicReferenceArrayTest.class));
+ suite.addTest(new TestSuite(AtomicReferenceFieldUpdaterTest.class));
+ suite.addTest(new TestSuite(AtomicReferenceTest.class));
+ suite.addTest(new TestSuite(AtomicStampedReferenceTest.class));
+ suite.addTest(new TestSuite(ConcurrentHashMapTest.class));
+ suite.addTest(new TestSuite(ConcurrentLinkedQueueTest.class));
+ suite.addTest(new TestSuite(ConcurrentSkipListMapTest.class));
+ suite.addTest(new TestSuite(ConcurrentSkipListSubMapTest.class));
+ suite.addTest(new TestSuite(ConcurrentSkipListSetTest.class));
+ suite.addTest(new TestSuite(ConcurrentSkipListSubSetTest.class));
+ suite.addTest(new TestSuite(CopyOnWriteArrayListTest.class));
+ suite.addTest(new TestSuite(CopyOnWriteArraySetTest.class));
+ suite.addTest(new TestSuite(CountDownLatchTest.class));
+ suite.addTest(new TestSuite(CyclicBarrierTest.class));
+ suite.addTest(new TestSuite(DelayQueueTest.class));
+ suite.addTest(new TestSuite(EntryTest.class));
+ suite.addTest(new TestSuite(ExchangerTest.class));
+ suite.addTest(new TestSuite(ExecutorsTest.class));
+ suite.addTest(new TestSuite(ExecutorCompletionServiceTest.class));
+ suite.addTest(new TestSuite(FutureTaskTest.class));
+ suite.addTest(new TestSuite(LinkedBlockingDequeTest.class));
+ suite.addTest(new TestSuite(LinkedBlockingQueueTest.class));
+ suite.addTest(new TestSuite(LinkedListTest.class));
+ suite.addTest(new TestSuite(LockSupportTest.class));
+ suite.addTest(new TestSuite(PriorityBlockingQueueTest.class));
+ suite.addTest(new TestSuite(PriorityQueueTest.class));
+ suite.addTest(new TestSuite(ReentrantLockTest.class));
+ suite.addTest(new TestSuite(ReentrantReadWriteLockTest.class));
+ suite.addTest(new TestSuite(ScheduledExecutorTest.class));
+ suite.addTest(new TestSuite(ScheduledExecutorSubclassTest.class));
+ suite.addTest(new TestSuite(SemaphoreTest.class));
+ suite.addTest(new TestSuite(SynchronousQueueTest.class));
+ suite.addTest(new TestSuite(SystemTest.class));
+ suite.addTest(new TestSuite(ThreadLocalTest.class));
+ suite.addTest(new TestSuite(ThreadPoolExecutorTest.class));
+ suite.addTest(new TestSuite(ThreadPoolExecutorSubclassTest.class));
+ suite.addTest(new TestSuite(ThreadTest.class));
+ suite.addTest(new TestSuite(TimeUnitTest.class));
+
return suite;
}
@@ -178,7 +199,7 @@ public class JSR166TestCase extends TestCase {
/**
* Sets delays as multiples of SHORT_DELAY.
*/
- protected void setDelays() {
+ protected void setDelays() {
SHORT_DELAY_MS = getShortDelay();
SMALL_DELAY_MS = SHORT_DELAY_MS * 5;
MEDIUM_DELAY_MS = SHORT_DELAY_MS * 10;
@@ -272,13 +293,16 @@ public class JSR166TestCase extends TestCase {
* threadFail with message "should throw exception"
*/
public void threadShouldThrow() {
- try {
- threadFailed = true;
- fail("should throw exception");
- } catch (AssertionFailedError e) {
- e.printStackTrace();
- throw e;
- }
+ threadFailed = true;
+ fail("should throw exception");
+ }
+
+ /**
+ * threadFail with message "should throw" + exceptionName
+ */
+ public void threadShouldThrow(String exceptionName) {
+ threadFailed = true;
+ fail("should throw " + exceptionName);
}
/**
@@ -304,11 +328,11 @@ public class JSR166TestCase extends TestCase {
public void joinPool(ExecutorService exec) {
try {
exec.shutdown();
- assertTrue(exec.awaitTermination(LONG_DELAY_MS, TimeUnit.MILLISECONDS));
- } catch(SecurityException ok) {
+ assertTrue(exec.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
+ } catch (SecurityException ok) {
// Allowed in case test doesn't have privs
- } catch(InterruptedException ie) {
- fail("Unexpected exception");
+ } catch (InterruptedException ie) {
+ fail("Unexpected InterruptedException");
}
}
@@ -321,46 +345,105 @@ public class JSR166TestCase extends TestCase {
}
/**
+ * fail with message "should throw " + exceptionName
+ */
+ public void shouldThrow(String exceptionName) {
+ fail("Should throw " + exceptionName);
+ }
+
+ /**
* fail with message "Unexpected exception"
*/
public void unexpectedException() {
fail("Unexpected exception");
}
+ /**
+ * fail with message "Unexpected exception", with argument
+ */
+ public void unexpectedException(Throwable ex) {
+ ex.printStackTrace();
+ fail("Unexpected exception: " + ex);
+ }
+
/**
* The number of elements to place in collections, arrays, etc.
*/
- static final int SIZE = 20;
+ public static final int SIZE = 20;
// Some convenient Integer constants
- static final Integer zero = new Integer(0);
- static final Integer one = new Integer(1);
- static final Integer two = new Integer(2);
- static final Integer three = new Integer(3);
- static final Integer four = new Integer(4);
- static final Integer five = new Integer(5);
- static final Integer six = new Integer(6);
- static final Integer seven = new Integer(7);
- static final Integer eight = new Integer(8);
- static final Integer nine = new Integer(9);
- static final Integer m1 = new Integer(-1);
- static final Integer m2 = new Integer(-2);
- static final Integer m3 = new Integer(-3);
- static final Integer m4 = new Integer(-4);
- static final Integer m5 = new Integer(-5);
- static final Integer m6 = new Integer(-6);
- static final Integer m10 = new Integer(-10);
+ public static final Integer zero = new Integer(0);
+ public static final Integer one = new Integer(1);
+ public static final Integer two = new Integer(2);
+ public static final Integer three = new Integer(3);
+ public static final Integer four = new Integer(4);
+ public static final Integer five = new Integer(5);
+ public static final Integer six = new Integer(6);
+ public static final Integer seven = new Integer(7);
+ public static final Integer eight = new Integer(8);
+ public static final Integer nine = new Integer(9);
+ public static final Integer m1 = new Integer(-1);
+ public static final Integer m2 = new Integer(-2);
+ public static final Integer m3 = new Integer(-3);
+ public static final Integer m4 = new Integer(-4);
+ public static final Integer m5 = new Integer(-5);
+ public static final Integer m6 = new Integer(-6);
+ public static final Integer m10 = new Integer(-10);
+
+
+ /**
+ * Runs Runnable r with a security policy that permits precisely
+ * the specified permissions. If there is no current security
+ * manager, the runnable is run twice, both with and without a
+ * security manager. We require that any security manager permit
+ * getPolicy/setPolicy.
+ */
+ public void runWithPermissions(Runnable r, Permission... permissions) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm == null) {
+ r.run();
+ Policy savedPolicy = Policy.getPolicy();
+ try {
+ Policy.setPolicy(permissivePolicy());
+ System.setSecurityManager(new SecurityManager());
+ runWithPermissions(r, permissions);
+ } finally {
+ System.setSecurityManager(null);
+ Policy.setPolicy(savedPolicy);
+ }
+ } else {
+ Policy savedPolicy = Policy.getPolicy();
+ AdjustablePolicy policy = new AdjustablePolicy(permissions);
+ Policy.setPolicy(policy);
+ try {
+ r.run();
+ } finally {
+ policy.addPermission(new SecurityPermission("setPolicy"));
+ Policy.setPolicy(savedPolicy);
+ }
+ }
+ }
+
+ /**
+ * Runs a runnable without any permissions.
+ */
+ public void runWithoutPermissions(Runnable r) {
+ runWithPermissions(r);
+ }
/**
* A security policy where new permissions can be dynamically added
* or all cleared.
*/
- static class AdjustablePolicy extends java.security.Policy {
+ public static class AdjustablePolicy extends java.security.Policy {
Permissions perms = new Permissions();
- AdjustablePolicy() { }
+ AdjustablePolicy(Permission... permissions) {
+ for (Permission permission : permissions)
+ perms.add(permission);
+ }
void addPermission(Permission perm) { perms.add(perm); }
void clearPermissions() { perms = new Permissions(); }
public PermissionCollection getPermissions(CodeSource cs) {
@@ -375,197 +458,293 @@ public class JSR166TestCase extends TestCase {
public void refresh() {}
}
+ /**
+ * Returns a policy containing all the permissions we ever need.
+ */
+ public static Policy permissivePolicy() {
+ return new AdjustablePolicy
+ // Permissions j.u.c. needs directly
+ (new RuntimePermission("modifyThread"),
+ new RuntimePermission("getClassLoader"),
+ new RuntimePermission("setContextClassLoader"),
+ // Permissions needed to change permissions!
+ new SecurityPermission("getPolicy"),
+ new SecurityPermission("setPolicy"),
+ new RuntimePermission("setSecurityManager"),
+ // Permissions needed by the junit test harness
+ new RuntimePermission("accessDeclaredMembers"),
+ new PropertyPermission("*", "read"),
+ new java.io.FilePermission("<<ALL FILES>>", "read"));
+ }
- // Some convenient Runnable classes
-
- static class NoOpRunnable implements Runnable {
- public void run() {}
+ /**
+ * Sleep until the timeout has elapsed, or interrupted.
+ * Does <em>NOT</em> throw InterruptedException.
+ */
+ void sleepTillInterrupted(long timeoutMillis) {
+ try {
+ Thread.sleep(timeoutMillis);
+ } catch (InterruptedException wakeup) {}
}
- static class NoOpCallable implements Callable {
- public Object call() { return Boolean.TRUE; }
+ /**
+ * Returns a new started Thread running the given runnable.
+ */
+ Thread newStartedThread(Runnable runnable) {
+ Thread t = new Thread(runnable);
+ t.start();
+ return t;
}
- static final String TEST_STRING = "a test string";
+ // Some convenient Runnable classes
- static class StringTask implements Callable<String> {
- public String call() { return TEST_STRING; }
- }
+ public abstract class CheckedRunnable implements Runnable {
+ protected abstract void realRun() throws Throwable;
- static class NPETask implements Callable<String> {
- public String call() { throw new NullPointerException(); }
+ public final void run() {
+ try {
+ realRun();
+ } catch (Throwable t) {
+ threadUnexpectedException(t);
+ }
+ }
}
- static class CallableOne implements Callable<Integer> {
- public Integer call() { return one; }
- }
+ public abstract class RunnableShouldThrow implements Runnable {
+ protected abstract void realRun() throws Throwable;
- class ShortRunnable implements Runnable {
- public void run() {
+ final Class<?> exceptionClass;
+
+ <T extends Throwable> RunnableShouldThrow(Class<T> exceptionClass) {
+ this.exceptionClass = exceptionClass;
+ }
+
+ public final void run() {
try {
- Thread.sleep(SHORT_DELAY_MS);
- }
- catch(Exception e) {
- threadUnexpectedException(e);
+ realRun();
+ threadShouldThrow(exceptionClass.getSimpleName());
+ } catch (Throwable t) {
+ if (! exceptionClass.isInstance(t))
+ threadUnexpectedException(t);
}
}
}
- class ShortInterruptedRunnable implements Runnable {
- public void run() {
+ public abstract class ThreadShouldThrow extends Thread {
+ protected abstract void realRun() throws Throwable;
+
+ final Class<?> exceptionClass;
+
+ <T extends Throwable> ThreadShouldThrow(Class<T> exceptionClass) {
+ this.exceptionClass = exceptionClass;
+ }
+
+ public final void run() {
try {
- Thread.sleep(SHORT_DELAY_MS);
- threadShouldThrow();
- }
- catch(InterruptedException success) {
+ realRun();
+ threadShouldThrow(exceptionClass.getSimpleName());
+ } catch (Throwable t) {
+ if (! exceptionClass.isInstance(t))
+ threadUnexpectedException(t);
}
}
}
- class SmallRunnable implements Runnable {
- public void run() {
+ public abstract class CheckedInterruptedRunnable implements Runnable {
+ protected abstract void realRun() throws Throwable;
+
+ public final void run() {
try {
- Thread.sleep(SMALL_DELAY_MS);
- }
- catch(Exception e) {
- threadUnexpectedException(e);
+ realRun();
+ threadShouldThrow("InterruptedException");
+ } catch (InterruptedException success) {
+ } catch (Throwable t) {
+ threadUnexpectedException(t);
}
}
}
- class SmallPossiblyInterruptedRunnable implements Runnable {
- public void run() {
+ public abstract class CheckedCallable<T> implements Callable<T> {
+ protected abstract T realCall() throws Throwable;
+
+ public final T call() {
try {
- Thread.sleep(SMALL_DELAY_MS);
- }
- catch(Exception e) {
+ return realCall();
+ } catch (Throwable t) {
+ threadUnexpectedException(t);
}
+ return null;
}
}
- class SmallCallable implements Callable {
- public Object call() {
+ public abstract class CheckedInterruptedCallable<T> implements Callable<T> {
+ protected abstract T realCall() throws Throwable;
+
+ public final T call() {
try {
- Thread.sleep(SMALL_DELAY_MS);
- }
- catch(Exception e) {
- threadUnexpectedException(e);
+ T result = realCall();
+ threadShouldThrow("InterruptedException");
+ return result;
+ } catch (InterruptedException success) {
+ } catch (Throwable t) {
+ threadUnexpectedException(t);
}
- return Boolean.TRUE;
+ return null;
}
}
- class SmallInterruptedRunnable implements Runnable {
- public void run() {
+ public static class NoOpRunnable implements Runnable {
+ public void run() {}
+ }
+
+ public static class NoOpCallable implements Callable {
+ public Object call() { return Boolean.TRUE; }
+ }
+
+ public static final String TEST_STRING = "a test string";
+
+ public static class StringTask implements Callable<String> {
+ public String call() { return TEST_STRING; }
+ }
+
+ public Callable<String> latchAwaitingStringTask(final CountDownLatch latch) {
+ return new CheckedCallable<String>() {
+ public String realCall() {
+ try {
+ latch.await();
+ } catch (InterruptedException quittingTime) {}
+ return TEST_STRING;
+ }};
+ }
+
+ public static class NPETask implements Callable<String> {
+ public String call() { throw new NullPointerException(); }
+ }
+
+ public static class CallableOne implements Callable<Integer> {
+ public Integer call() { return one; }
+ }
+
+ public class ShortRunnable extends CheckedRunnable {
+ protected void realRun() throws Throwable {
+ Thread.sleep(SHORT_DELAY_MS);
+ }
+ }
+
+ public class ShortInterruptedRunnable extends CheckedInterruptedRunnable {
+ protected void realRun() throws InterruptedException {
+ Thread.sleep(SHORT_DELAY_MS);
+ }
+ }
+
+ public class SmallRunnable extends CheckedRunnable {
+ protected void realRun() throws Throwable {
+ Thread.sleep(SMALL_DELAY_MS);
+ }
+ }
+
+ public class SmallPossiblyInterruptedRunnable extends CheckedRunnable {
+ protected void realRun() {
try {
Thread.sleep(SMALL_DELAY_MS);
- threadShouldThrow();
- }
- catch(InterruptedException success) {
- }
+ } catch (InterruptedException ok) {}
}
}
+ public class SmallCallable extends CheckedCallable {
+ protected Object realCall() throws InterruptedException {
+ Thread.sleep(SMALL_DELAY_MS);
+ return Boolean.TRUE;
+ }
+ }
- class MediumRunnable implements Runnable {
- public void run() {
- try {
- Thread.sleep(MEDIUM_DELAY_MS);
- }
- catch(Exception e) {
- threadUnexpectedException(e);
- }
+ public class SmallInterruptedRunnable extends CheckedInterruptedRunnable {
+ protected void realRun() throws InterruptedException {
+ Thread.sleep(SMALL_DELAY_MS);
}
}
- class MediumInterruptedRunnable implements Runnable {
- public void run() {
- try {
- Thread.sleep(MEDIUM_DELAY_MS);
- threadShouldThrow();
- }
- catch(InterruptedException success) {
- }
+ public class MediumRunnable extends CheckedRunnable {
+ protected void realRun() throws Throwable {
+ Thread.sleep(MEDIUM_DELAY_MS);
}
}
- class MediumPossiblyInterruptedRunnable implements Runnable {
- public void run() {
+ public class MediumInterruptedRunnable extends CheckedInterruptedRunnable {
+ protected void realRun() throws InterruptedException {
+ Thread.sleep(MEDIUM_DELAY_MS);
+ }
+ }
+
+ public class MediumPossiblyInterruptedRunnable extends CheckedRunnable {
+ protected void realRun() {
try {
Thread.sleep(MEDIUM_DELAY_MS);
- }
- catch(InterruptedException success) {
- }
+ } catch (InterruptedException ok) {}
}
}
- class LongPossiblyInterruptedRunnable implements Runnable {
- public void run() {
+ public class LongPossiblyInterruptedRunnable extends CheckedRunnable {
+ protected void realRun() {
try {
Thread.sleep(LONG_DELAY_MS);
- }
- catch(InterruptedException success) {
- }
+ } catch (InterruptedException ok) {}
}
}
/**
* For use as ThreadFactory in constructors
*/
- static class SimpleThreadFactory implements ThreadFactory{
- public Thread newThread(Runnable r){
+ public static class SimpleThreadFactory implements ThreadFactory {
+ public Thread newThread(Runnable r) {
return new Thread(r);
}
}
- static class TrackedShortRunnable implements Runnable {
- volatile boolean done = false;
+ public static class TrackedShortRunnable implements Runnable {
+ public volatile boolean done = false;
public void run() {
try {
Thread.sleep(SMALL_DELAY_MS);
done = true;
- } catch(Exception e){
- }
+ } catch (InterruptedException ok) {}
}
}
- static class TrackedMediumRunnable implements Runnable {
- volatile boolean done = false;
+ public static class TrackedMediumRunnable implements Runnable {
+ public volatile boolean done = false;
public void run() {
try {
Thread.sleep(MEDIUM_DELAY_MS);
done = true;
- } catch(Exception e){
- }
+ } catch (InterruptedException ok) {}
}
}
- static class TrackedLongRunnable implements Runnable {
- volatile boolean done = false;
+ public static class TrackedLongRunnable implements Runnable {
+ public volatile boolean done = false;
public void run() {
try {
Thread.sleep(LONG_DELAY_MS);
done = true;
- } catch(Exception e){
- }
+ } catch (InterruptedException ok) {}
}
}
- static class TrackedNoOpRunnable implements Runnable {
- volatile boolean done = false;
+ public static class TrackedNoOpRunnable implements Runnable {
+ public volatile boolean done = false;
public void run() {
done = true;
}
}
- static class TrackedCallable implements Callable {
- volatile boolean done = false;
+ public static class TrackedCallable implements Callable {
+ public volatile boolean done = false;
public Object call() {
try {
Thread.sleep(SMALL_DELAY_MS);
done = true;
- } catch(Exception e){
- }
+ } catch (InterruptedException ok) {}
return Boolean.TRUE;
}
}
@@ -574,9 +753,9 @@ public class JSR166TestCase extends TestCase {
/**
* For use as RejectedExecutionHandler in constructors
*/
- static class NoOpREHandler implements RejectedExecutionHandler{
- public void rejectedExecution(Runnable r, ThreadPoolExecutor executor){}
+ public static class NoOpREHandler implements RejectedExecutionHandler {
+ public void rejectedExecution(Runnable r,
+ ThreadPoolExecutor executor) {}
}
-
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/LinkedBlockingDequeTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/LinkedBlockingDequeTest.java
new file mode 100644
index 0000000..a858bb9
--- /dev/null
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/LinkedBlockingDequeTest.java
@@ -0,0 +1,1671 @@
+/*
+ * 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 tests.api.java.util.concurrent; // android-added
+
+import junit.framework.*;
+import java.util.*;
+import java.util.concurrent.*;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import java.io.*;
+
+public class LinkedBlockingDequeTest extends JSR166TestCase {
+ public static Test suite() {
+ return new TestSuite(LinkedBlockingDequeTest.class);
+ }
+
+ /**
+ * Create a deque of given size containing consecutive
+ * Integers 0 ... n.
+ */
+ private LinkedBlockingDeque populatedDeque(int n) {
+ LinkedBlockingDeque q = new LinkedBlockingDeque(n);
+ assertTrue(q.isEmpty());
+ for (int i = 0; i < n; i++)
+ assertTrue(q.offer(new Integer(i)));
+ assertFalse(q.isEmpty());
+ assertEquals(0, q.remainingCapacity());
+ assertEquals(n, q.size());
+ return q;
+ }
+
+ /**
+ * isEmpty is true before add, false after
+ */
+ public void testEmpty() {
+ LinkedBlockingDeque q = new LinkedBlockingDeque();
+ assertTrue(q.isEmpty());
+ q.add(new Integer(1));
+ assertFalse(q.isEmpty());
+ q.add(new Integer(2));
+ q.removeFirst();
+ q.removeFirst();
+ assertTrue(q.isEmpty());
+ }
+
+ /**
+ * size changes when elements added and removed
+ */
+ public void testSize() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(SIZE-i, q.size());
+ q.removeFirst();
+ }
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.size());
+ q.add(new Integer(i));
+ }
+ }
+
+ /**
+ * offer(null) throws NPE
+ */
+ public void testOfferFirstNull() {
+ try {
+ LinkedBlockingDeque q = new LinkedBlockingDeque();
+ q.offerFirst(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * OfferFirst succeeds
+ */
+ public void testOfferFirst() {
+ LinkedBlockingDeque q = new LinkedBlockingDeque();
+ assertTrue(q.offerFirst(new Integer(0)));
+ assertTrue(q.offerFirst(new Integer(1)));
+ }
+
+ /**
+ * OfferLast succeeds
+ */
+ public void testOfferLast() {
+ LinkedBlockingDeque q = new LinkedBlockingDeque();
+ assertTrue(q.offerLast(new Integer(0)));
+ assertTrue(q.offerLast(new Integer(1)));
+ }
+
+ /**
+ * pollFirst succeeds unless empty
+ */
+ public void testPollFirst() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.pollFirst());
+ }
+ assertNull(q.pollFirst());
+ }
+
+ /**
+ * pollLast succeeds unless empty
+ */
+ public void testPollLast() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = SIZE-1; i >= 0; --i) {
+ assertEquals(i, q.pollLast());
+ }
+ assertNull(q.pollLast());
+ }
+
+ /**
+ * peekFirst returns next element, or null if empty
+ */
+ public void testPeekFirst() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.peekFirst());
+ assertEquals(i, q.pollFirst());
+ assertTrue(q.peekFirst() == null ||
+ !q.peekFirst().equals(i));
+ }
+ assertNull(q.peekFirst());
+ }
+
+ /**
+ * peek returns next element, or null if empty
+ */
+ public void testPeek() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.peek());
+ assertEquals(i, q.pollFirst());
+ assertTrue(q.peek() == null ||
+ !q.peek().equals(i));
+ }
+ assertNull(q.peek());
+ }
+
+ /**
+ * peekLast returns next element, or null if empty
+ */
+ public void testPeekLast() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = SIZE-1; i >= 0; --i) {
+ assertEquals(i, q.peekLast());
+ assertEquals(i, q.pollLast());
+ assertTrue(q.peekLast() == null ||
+ !q.peekLast().equals(i));
+ }
+ assertNull(q.peekLast());
+ }
+
+ /**
+ * getFirst returns next getFirst, or throws NSEE if empty
+ */
+ public void testFirstElement() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.getFirst());
+ assertEquals(i, q.pollFirst());
+ }
+ try {
+ q.getFirst();
+ shouldThrow();
+ } catch (NoSuchElementException success) {}
+ assertNull(q.peekFirst());
+ }
+
+ /**
+ * getLast returns next element, or throws NSEE if empty
+ */
+ public void testLastElement() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = SIZE-1; i >= 0; --i) {
+ assertEquals(i, q.getLast());
+ assertEquals(i, q.pollLast());
+ }
+ try {
+ q.getLast();
+ shouldThrow();
+ } catch (NoSuchElementException success) {}
+ assertNull(q.peekLast());
+ }
+
+ /**
+ * removeFirst removes next element, or throws NSEE if empty
+ */
+ public void testRemoveFirst() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.removeFirst());
+ }
+ try {
+ q.removeFirst();
+ shouldThrow();
+ } catch (NoSuchElementException success) {}
+ assertNull(q.peekFirst());
+ }
+
+ /**
+ * removeLast removes last element, or throws NSEE if empty
+ */
+ public void testRemoveLast() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = SIZE - 1; i >= 0; --i) {
+ assertEquals(i, q.removeLast());
+ }
+ try {
+ q.removeLast();
+ shouldThrow();
+ } catch (NoSuchElementException success) {}
+ assertNull(q.peekLast());
+ }
+
+ /**
+ * remove removes next element, or throws NSEE if empty
+ */
+ public void testRemove() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.remove());
+ }
+ try {
+ q.remove();
+ shouldThrow();
+ } catch (NoSuchElementException success) {}
+ }
+
+ /**
+ * removeFirstOccurrence(x) removes x and returns true if present
+ */
+ public void testRemoveFirstOccurrence() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 1; i < SIZE; i+=2) {
+ assertTrue(q.removeFirstOccurrence(new Integer(i)));
+ }
+ for (int i = 0; i < SIZE; i+=2) {
+ assertTrue(q.removeFirstOccurrence(new Integer(i)));
+ assertFalse(q.removeFirstOccurrence(new Integer(i+1)));
+ }
+ assertTrue(q.isEmpty());
+ }
+
+ /**
+ * removeLastOccurrence(x) removes x and returns true if present
+ */
+ public void testRemoveLastOccurrence() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 1; i < SIZE; i+=2) {
+ assertTrue(q.removeLastOccurrence(new Integer(i)));
+ }
+ for (int i = 0; i < SIZE; i+=2) {
+ assertTrue(q.removeLastOccurrence(new Integer(i)));
+ assertFalse(q.removeLastOccurrence(new Integer(i+1)));
+ }
+ assertTrue(q.isEmpty());
+ }
+
+ /**
+ * peekFirst returns element inserted with addFirst
+ */
+ public void testAddFirst() {
+ LinkedBlockingDeque q = populatedDeque(3);
+ q.pollLast();
+ q.addFirst(four);
+ assertSame(four, q.peekFirst());
+ }
+
+ /**
+ * peekLast returns element inserted with addLast
+ */
+ public void testAddLast() {
+ LinkedBlockingDeque q = populatedDeque(3);
+ q.pollLast();
+ q.addLast(four);
+ assertSame(four, q.peekLast());
+ }
+
+
+ /**
+ * A new deque has the indicated capacity, or Integer.MAX_VALUE if
+ * none given
+ */
+ public void testConstructor1() {
+ assertEquals(SIZE, new LinkedBlockingDeque(SIZE).remainingCapacity());
+ assertEquals(Integer.MAX_VALUE, new LinkedBlockingDeque().remainingCapacity());
+ }
+
+ /**
+ * Constructor throws IAE if capacity argument nonpositive
+ */
+ public void testConstructor2() {
+ try {
+ LinkedBlockingDeque q = new LinkedBlockingDeque(0);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * Initializing from null Collection throws NPE
+ */
+ public void testConstructor3() {
+ try {
+ LinkedBlockingDeque q = new LinkedBlockingDeque(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * Initializing from Collection of null elements throws NPE
+ */
+ public void testConstructor4() {
+ try {
+ Integer[] ints = new Integer[SIZE];
+ LinkedBlockingDeque q = new LinkedBlockingDeque(Arrays.asList(ints));
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * Initializing from Collection with some null elements throws NPE
+ */
+ public void testConstructor5() {
+ try {
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE-1; ++i)
+ ints[i] = new Integer(i);
+ LinkedBlockingDeque q = new LinkedBlockingDeque(Arrays.asList(ints));
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * Deque contains all elements of collection used to initialize
+ */
+ public void testConstructor6() {
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = new Integer(i);
+ LinkedBlockingDeque q = new LinkedBlockingDeque(Arrays.asList(ints));
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(ints[i], q.poll());
+ }
+
+ /**
+ * Deque transitions from empty to full when elements added
+ */
+ public void testEmptyFull() {
+ LinkedBlockingDeque q = new LinkedBlockingDeque(2);
+ assertTrue(q.isEmpty());
+ assertEquals("should have room for 2", 2, q.remainingCapacity());
+ q.add(one);
+ assertFalse(q.isEmpty());
+ q.add(two);
+ assertFalse(q.isEmpty());
+ assertEquals(0, q.remainingCapacity());
+ assertFalse(q.offer(three));
+ }
+
+ /**
+ * remainingCapacity decreases on add, increases on remove
+ */
+ public void testRemainingCapacity() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.remainingCapacity());
+ assertEquals(SIZE-i, q.size());
+ q.remove();
+ }
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(SIZE-i, q.remainingCapacity());
+ assertEquals(i, q.size());
+ q.add(new Integer(i));
+ }
+ }
+
+ /**
+ * offer(null) throws NPE
+ */
+ public void testOfferNull() {
+ try {
+ LinkedBlockingDeque q = new LinkedBlockingDeque(1);
+ q.offer(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * add(null) throws NPE
+ */
+ public void testAddNull() {
+ try {
+ LinkedBlockingDeque q = new LinkedBlockingDeque(1);
+ q.add(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * push(null) throws NPE
+ */
+ public void testPushNull() {
+ try {
+ LinkedBlockingDeque q = new LinkedBlockingDeque(1);
+ q.push(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * push succeeds if not full; throws ISE if full
+ */
+ public void testPush() {
+ try {
+ LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ Integer I = new Integer(i);
+ q.push(I);
+ assertEquals(I, q.peek());
+ }
+ assertEquals(0, q.remainingCapacity());
+ q.push(new Integer(SIZE));
+ shouldThrow();
+ } catch (IllegalStateException success) {}
+ }
+
+ /**
+ * peekFirst returns element inserted with push
+ */
+ public void testPushWithPeek() {
+ LinkedBlockingDeque q = populatedDeque(3);
+ q.pollLast();
+ q.push(four);
+ assertSame(four, q.peekFirst());
+ }
+
+
+ /**
+ * pop removes next element, or throws NSEE if empty
+ */
+ public void testPop() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.pop());
+ }
+ try {
+ q.pop();
+ shouldThrow();
+ } catch (NoSuchElementException success) {}
+ }
+
+
+ /**
+ * Offer succeeds if not full; fails if full
+ */
+ public void testOffer() {
+ LinkedBlockingDeque q = new LinkedBlockingDeque(1);
+ assertTrue(q.offer(zero));
+ assertFalse(q.offer(one));
+ }
+
+ /**
+ * add succeeds if not full; throws ISE if full
+ */
+ public void testAdd() {
+ try {
+ LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertTrue(q.add(new Integer(i)));
+ }
+ assertEquals(0, q.remainingCapacity());
+ q.add(new Integer(SIZE));
+ shouldThrow();
+ } catch (IllegalStateException success) {}
+ }
+
+ /**
+ * addAll(null) throws NPE
+ */
+ public void testAddAll1() {
+ try {
+ LinkedBlockingDeque q = new LinkedBlockingDeque(1);
+ q.addAll(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * addAll(this) throws IAE
+ */
+ public void testAddAllSelf() {
+ try {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ q.addAll(q);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * addAll of a collection with null elements throws NPE
+ */
+ public void testAddAll2() {
+ try {
+ LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE);
+ 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 {
+ LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE);
+ 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 not enough room
+ */
+ public void testAddAll4() {
+ try {
+ LinkedBlockingDeque q = new LinkedBlockingDeque(1);
+ 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) {}
+ }
+
+ /**
+ * Deque contains all elements, in traversal order, of successful addAll
+ */
+ public void testAddAll5() {
+ Integer[] empty = new Integer[0];
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = new Integer(i);
+ LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE);
+ assertFalse(q.addAll(Arrays.asList(empty)));
+ assertTrue(q.addAll(Arrays.asList(ints)));
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(ints[i], q.poll());
+ }
+
+
+ /**
+ * put(null) throws NPE
+ */
+ public void testPutNull() throws InterruptedException {
+ try {
+ LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE);
+ q.put(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * all elements successfully put are contained
+ */
+ public void testPut() throws InterruptedException {
+ LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ Integer I = new Integer(i);
+ q.put(I);
+ assertTrue(q.contains(I));
+ }
+ assertEquals(0, q.remainingCapacity());
+ }
+
+ /**
+ * put blocks interruptibly if full
+ */
+ public void testBlockingPut() throws InterruptedException {
+ final LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE);
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ for (int i = 0; i < SIZE; ++i)
+ q.put(i);
+ assertEquals(SIZE, q.size());
+ assertEquals(0, q.remainingCapacity());
+ try {
+ q.put(99);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
+ assertEquals(SIZE, q.size());
+ assertEquals(0, q.remainingCapacity());
+ }
+
+ /**
+ * put blocks waiting for take when full
+ */
+ public void testPutWithTake() throws InterruptedException {
+ final int capacity = 2;
+ final LinkedBlockingDeque q = new LinkedBlockingDeque(capacity);
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ for (int i = 0; i < capacity + 1; i++)
+ q.put(i);
+ try {
+ q.put(99);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(q.remainingCapacity(), 0);
+ assertEquals(0, q.take());
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
+ assertEquals(q.remainingCapacity(), 0);
+ }
+
+ /**
+ * timed offer times out if full and elements not taken
+ */
+ public void testTimedOffer() throws InterruptedException {
+ final LinkedBlockingDeque q = new LinkedBlockingDeque(2);
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ q.put(new Object());
+ q.put(new Object());
+ assertFalse(q.offer(new Object(), SHORT_DELAY_MS, MILLISECONDS));
+ try {
+ q.offer(new Object(), LONG_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SMALL_DELAY_MS);
+ t.interrupt();
+ t.join();
+ }
+
+ /**
+ * take retrieves elements in FIFO order
+ */
+ public void testTake() throws InterruptedException {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.take());
+ }
+ }
+
+ /**
+ * take blocks interruptibly when empty
+ */
+ public void testTakeFromEmpty() throws InterruptedException {
+ final LinkedBlockingDeque q = new LinkedBlockingDeque(2);
+ Thread t = new ThreadShouldThrow(InterruptedException.class) {
+ public void realRun() throws InterruptedException {
+ q.take();
+ }};
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
+ }
+
+ /**
+ * Take removes existing elements until empty, then blocks interruptibly
+ */
+ public void testBlockingTake() throws InterruptedException {
+ final LinkedBlockingDeque q = populatedDeque(SIZE);
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.take());
+ }
+ try {
+ q.take();
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
+ }
+
+
+ /**
+ * poll succeeds unless empty
+ */
+ public void testPoll() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.poll());
+ }
+ assertNull(q.poll());
+ }
+
+ /**
+ * timed poll with zero timeout succeeds when non-empty, else times out
+ */
+ public void testTimedPoll0() throws InterruptedException {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.poll(0, MILLISECONDS));
+ }
+ assertNull(q.poll(0, MILLISECONDS));
+ }
+
+ /**
+ * timed poll with nonzero timeout succeeds when non-empty, else times out
+ */
+ public void testTimedPoll() throws InterruptedException {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.poll(SHORT_DELAY_MS, MILLISECONDS));
+ }
+ assertNull(q.poll(SHORT_DELAY_MS, MILLISECONDS));
+ }
+
+ /**
+ * Interrupted timed poll throws InterruptedException instead of
+ * returning timeout status
+ */
+ public void testInterruptedTimedPoll() throws InterruptedException {
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.poll(SHORT_DELAY_MS, MILLISECONDS));
+ }
+ try {
+ q.poll(SMALL_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
+ }
+
+ /**
+ * timed poll before a delayed offer fails; after offer succeeds;
+ * on interruption throws
+ */
+ public void testTimedPollWithOffer() throws InterruptedException {
+ final LinkedBlockingDeque q = new LinkedBlockingDeque(2);
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertNull(q.poll(SHORT_DELAY_MS, MILLISECONDS));
+ assertSame(zero, q.poll(LONG_DELAY_MS, MILLISECONDS));
+ try {
+ q.poll(LONG_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SMALL_DELAY_MS);
+ assertTrue(q.offer(zero, SHORT_DELAY_MS, MILLISECONDS));
+ t.interrupt();
+ t.join();
+ }
+
+
+ /**
+ * putFirst(null) throws NPE
+ */
+ public void testPutFirstNull() throws InterruptedException {
+ try {
+ LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE);
+ q.putFirst(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * all elements successfully putFirst are contained
+ */
+ public void testPutFirst() throws InterruptedException {
+ LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ Integer I = new Integer(i);
+ q.putFirst(I);
+ assertTrue(q.contains(I));
+ }
+ assertEquals(0, q.remainingCapacity());
+ }
+
+ /**
+ * putFirst blocks interruptibly if full
+ */
+ public void testBlockingPutFirst() throws InterruptedException {
+ final LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE);
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ for (int i = 0; i < SIZE; ++i)
+ q.putFirst(i);
+ assertEquals(SIZE, q.size());
+ assertEquals(0, q.remainingCapacity());
+ try {
+ q.putFirst(99);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
+ assertEquals(SIZE, q.size());
+ assertEquals(0, q.remainingCapacity());
+ }
+
+ /**
+ * putFirst blocks waiting for take when full
+ */
+ public void testPutFirstWithTake() throws InterruptedException {
+ final int capacity = 2;
+ final LinkedBlockingDeque q = new LinkedBlockingDeque(capacity);
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ for (int i = 0; i < capacity + 1; i++)
+ q.putFirst(i);
+ try {
+ q.putFirst(99);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(q.remainingCapacity(), 0);
+ assertEquals(capacity - 1, q.take());
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
+ assertEquals(q.remainingCapacity(), 0);
+ }
+
+ /**
+ * timed offerFirst times out if full and elements not taken
+ */
+ public void testTimedOfferFirst() throws InterruptedException {
+ final LinkedBlockingDeque q = new LinkedBlockingDeque(2);
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ q.putFirst(new Object());
+ q.putFirst(new Object());
+ assertFalse(q.offerFirst(new Object(), SHORT_DELAY_MS, MILLISECONDS));
+ try {
+ q.offerFirst(new Object(), LONG_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SMALL_DELAY_MS);
+ t.interrupt();
+ t.join();
+ }
+
+ /**
+ * take retrieves elements in FIFO order
+ */
+ public void testTakeFirst() throws InterruptedException {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.takeFirst());
+ }
+ }
+
+ /**
+ * takeFirst blocks interruptibly when empty
+ */
+ public void testTakeFirstFromEmpty() throws InterruptedException {
+ final LinkedBlockingDeque q = new LinkedBlockingDeque(2);
+ Thread t = new ThreadShouldThrow(InterruptedException.class) {
+ public void realRun() throws InterruptedException {
+ q.takeFirst();
+ }};
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
+ }
+
+ /**
+ * TakeFirst removes existing elements until empty, then blocks interruptibly
+ */
+ public void testBlockingTakeFirst() throws InterruptedException {
+ final LinkedBlockingDeque q = populatedDeque(SIZE);
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(i, q.takeFirst());
+ try {
+ q.takeFirst();
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
+ }
+
+
+ /**
+ * timed pollFirst with zero timeout succeeds when non-empty, else times out
+ */
+ public void testTimedPollFirst0() throws InterruptedException {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.pollFirst(0, MILLISECONDS));
+ }
+ assertNull(q.pollFirst(0, MILLISECONDS));
+ }
+
+ /**
+ * timed pollFirst with nonzero timeout succeeds when non-empty, else times out
+ */
+ public void testTimedPollFirst() throws InterruptedException {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.pollFirst(SHORT_DELAY_MS, MILLISECONDS));
+ }
+ assertNull(q.pollFirst(SHORT_DELAY_MS, MILLISECONDS));
+ }
+
+ /**
+ * Interrupted timed pollFirst throws InterruptedException instead of
+ * returning timeout status
+ */
+ public void testInterruptedTimedPollFirst() throws InterruptedException {
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.pollFirst(SHORT_DELAY_MS, MILLISECONDS));
+ }
+ try {
+ q.pollFirst(SMALL_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
+ }
+
+ /**
+ * timed pollFirst before a delayed offerFirst fails; after offerFirst succeeds;
+ * on interruption throws
+ */
+ public void testTimedPollFirstWithOfferFirst() throws InterruptedException {
+ final LinkedBlockingDeque q = new LinkedBlockingDeque(2);
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertNull(q.pollFirst(SHORT_DELAY_MS, MILLISECONDS));
+ assertSame(zero, q.pollFirst(LONG_DELAY_MS, MILLISECONDS));
+ try {
+ q.pollFirst(LONG_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SMALL_DELAY_MS);
+ assertTrue(q.offerFirst(zero, SHORT_DELAY_MS, MILLISECONDS));
+ t.interrupt();
+ t.join();
+ }
+
+ /**
+ * putLast(null) throws NPE
+ */
+ public void testPutLastNull() throws InterruptedException {
+ try {
+ LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE);
+ q.putLast(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * all elements successfully putLast are contained
+ */
+ public void testPutLast() throws InterruptedException {
+ LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ Integer I = new Integer(i);
+ q.putLast(I);
+ assertTrue(q.contains(I));
+ }
+ assertEquals(0, q.remainingCapacity());
+ }
+
+ /**
+ * putLast blocks interruptibly if full
+ */
+ public void testBlockingPutLast() throws InterruptedException {
+ final LinkedBlockingDeque q = new LinkedBlockingDeque(SIZE);
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ for (int i = 0; i < SIZE; ++i)
+ q.putLast(i);
+ assertEquals(SIZE, q.size());
+ assertEquals(0, q.remainingCapacity());
+ try {
+ q.putLast(99);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
+ assertEquals(SIZE, q.size());
+ assertEquals(0, q.remainingCapacity());
+ }
+
+ /**
+ * putLast blocks waiting for take when full
+ */
+ public void testPutLastWithTake() throws InterruptedException {
+ final int capacity = 2;
+ final LinkedBlockingDeque q = new LinkedBlockingDeque(capacity);
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ for (int i = 0; i < capacity + 1; i++)
+ q.putLast(i);
+ try {
+ q.putLast(99);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(q.remainingCapacity(), 0);
+ assertEquals(0, q.take());
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
+ assertEquals(q.remainingCapacity(), 0);
+ }
+
+ /**
+ * timed offerLast times out if full and elements not taken
+ */
+ public void testTimedOfferLast() throws InterruptedException {
+ final LinkedBlockingDeque q = new LinkedBlockingDeque(2);
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ q.putLast(new Object());
+ q.putLast(new Object());
+ assertFalse(q.offerLast(new Object(), SHORT_DELAY_MS, MILLISECONDS));
+ try {
+ q.offerLast(new Object(), LONG_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SMALL_DELAY_MS);
+ t.interrupt();
+ t.join();
+ }
+
+ /**
+ * takeLast retrieves elements in FIFO order
+ */
+ public void testTakeLast() throws InterruptedException {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(SIZE-i-1, q.takeLast());
+ }
+ }
+
+ /**
+ * takeLast blocks interruptibly when empty
+ */
+ public void testTakeLastFromEmpty() throws InterruptedException {
+ final LinkedBlockingDeque q = new LinkedBlockingDeque(2);
+ Thread t = new ThreadShouldThrow(InterruptedException.class) {
+ public void realRun() throws InterruptedException {
+ q.takeLast();
+ }};
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
+ }
+
+ /**
+ * TakeLast removes existing elements until empty, then blocks interruptibly
+ */
+ public void testBlockingTakeLast() throws InterruptedException {
+ final LinkedBlockingDeque q = populatedDeque(SIZE);
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(SIZE - 1 - i, q.takeLast());
+ try {
+ q.takeLast();
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
+ }
+
+ /**
+ * timed pollLast with zero timeout succeeds when non-empty, else times out
+ */
+ public void testTimedPollLast0() throws InterruptedException {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(SIZE-i-1, q.pollLast(0, MILLISECONDS));
+ }
+ assertNull(q.pollLast(0, MILLISECONDS));
+ }
+
+ /**
+ * timed pollLast with nonzero timeout succeeds when non-empty, else times out
+ */
+ public void testTimedPollLast() throws InterruptedException {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(SIZE-i-1, q.pollLast(SHORT_DELAY_MS, MILLISECONDS));
+ }
+ assertNull(q.pollLast(SHORT_DELAY_MS, MILLISECONDS));
+ }
+
+ /**
+ * Interrupted timed pollLast throws InterruptedException instead of
+ * returning timeout status
+ */
+ public void testInterruptedTimedPollLast() throws InterruptedException {
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(SIZE-i-1, q.pollLast(SHORT_DELAY_MS, MILLISECONDS));
+ }
+ try {
+ q.pollLast(SMALL_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
+ }
+
+ /**
+ * timed poll before a delayed offerLast fails; after offerLast succeeds;
+ * on interruption throws
+ */
+ public void testTimedPollWithOfferLast() throws InterruptedException {
+ final LinkedBlockingDeque q = new LinkedBlockingDeque(2);
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertNull(q.poll(SHORT_DELAY_MS, MILLISECONDS));
+ assertSame(zero, q.poll(LONG_DELAY_MS, MILLISECONDS));
+ try {
+ q.poll(LONG_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SMALL_DELAY_MS);
+ assertTrue(q.offerLast(zero, SHORT_DELAY_MS, MILLISECONDS));
+ t.interrupt();
+ t.join();
+ }
+
+
+ /**
+ * element returns next element, or throws NSEE if empty
+ */
+ public void testElement() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.element());
+ q.poll();
+ }
+ try {
+ q.element();
+ shouldThrow();
+ } catch (NoSuchElementException success) {}
+ }
+
+ /**
+ * remove(x) removes x and returns true if present
+ */
+ public void testRemoveElement() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 1; i < SIZE; i+=2) {
+ assertTrue(q.remove(new Integer(i)));
+ }
+ for (int i = 0; i < SIZE; i+=2) {
+ assertTrue(q.remove(new Integer(i)));
+ assertFalse(q.remove(new Integer(i+1)));
+ }
+ assertTrue(q.isEmpty());
+ }
+
+ /**
+ * contains(x) reports true when elements added but not yet removed
+ */
+ public void testContains() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertTrue(q.contains(new Integer(i)));
+ q.poll();
+ assertFalse(q.contains(new Integer(i)));
+ }
+ }
+
+ /**
+ * clear removes all elements
+ */
+ public void testClear() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ q.clear();
+ assertTrue(q.isEmpty());
+ assertEquals(0, q.size());
+ assertEquals(SIZE, q.remainingCapacity());
+ q.add(one);
+ assertFalse(q.isEmpty());
+ assertTrue(q.contains(one));
+ q.clear();
+ assertTrue(q.isEmpty());
+ }
+
+ /**
+ * containsAll(c) is true when c contains a subset of elements
+ */
+ public void testContainsAll() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ LinkedBlockingDeque p = new LinkedBlockingDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertTrue(q.containsAll(p));
+ assertFalse(p.containsAll(q));
+ p.add(new Integer(i));
+ }
+ assertTrue(p.containsAll(q));
+ }
+
+ /**
+ * retainAll(c) retains only those elements of c and reports true if changed
+ */
+ public void testRetainAll() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ LinkedBlockingDeque p = populatedDeque(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ boolean changed = q.retainAll(p);
+ if (i == 0)
+ assertFalse(changed);
+ else
+ assertTrue(changed);
+
+ assertTrue(q.containsAll(p));
+ assertEquals(SIZE-i, q.size());
+ p.remove();
+ }
+ }
+
+ /**
+ * removeAll(c) removes only those elements of c and reports true if changed
+ */
+ public void testRemoveAll() {
+ for (int i = 1; i < SIZE; ++i) {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ LinkedBlockingDeque p = populatedDeque(i);
+ assertTrue(q.removeAll(p));
+ assertEquals(SIZE-i, q.size());
+ for (int j = 0; j < i; ++j) {
+ Integer I = (Integer)(p.remove());
+ assertFalse(q.contains(I));
+ }
+ }
+ }
+
+ /**
+ * toArray contains all elements
+ */
+ public void testToArray() throws InterruptedException{
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ Object[] o = q.toArray();
+ for (int i = 0; i < o.length; i++)
+ assertEquals(o[i], q.take());
+ }
+
+ /**
+ * toArray(a) contains all elements
+ */
+ public void testToArray2() throws InterruptedException {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ Integer[] ints = new Integer[SIZE];
+ ints = (Integer[])q.toArray(ints);
+ for (int i = 0; i < ints.length; i++)
+ assertEquals(ints[i], q.take());
+ }
+
+ /**
+ * toArray(null) throws NPE
+ */
+ public void testToArray_BadArg() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ try {
+ Object o[] = q.toArray(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * toArray with incompatible array type throws CCE
+ */
+ public void testToArray1_BadArg() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ try {
+ Object o[] = q.toArray(new String[10]);
+ shouldThrow();
+ } catch (ArrayStoreException success) {}
+ }
+
+
+ /**
+ * iterator iterates through all elements
+ */
+ public void testIterator() throws InterruptedException {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ Iterator it = q.iterator();
+ while (it.hasNext()) {
+ assertEquals(it.next(), q.take());
+ }
+ }
+
+ /**
+ * iterator.remove removes current element
+ */
+ public void testIteratorRemove () {
+ final LinkedBlockingDeque q = new LinkedBlockingDeque(3);
+ q.add(two);
+ q.add(one);
+ q.add(three);
+
+ Iterator it = q.iterator();
+ it.next();
+ it.remove();
+
+ it = q.iterator();
+ assertSame(it.next(), one);
+ assertSame(it.next(), three);
+ assertFalse(it.hasNext());
+ }
+
+
+ /**
+ * iterator ordering is FIFO
+ */
+ public void testIteratorOrdering() {
+ final LinkedBlockingDeque q = new LinkedBlockingDeque(3);
+ q.add(one);
+ q.add(two);
+ q.add(three);
+ assertEquals(0, q.remainingCapacity());
+ int k = 0;
+ for (Iterator it = q.iterator(); it.hasNext();) {
+ assertEquals(++k, it.next());
+ }
+ assertEquals(3, k);
+ }
+
+ /**
+ * Modifications do not cause iterators to fail
+ */
+ public void testWeaklyConsistentIteration () {
+ final LinkedBlockingDeque q = new LinkedBlockingDeque(3);
+ q.add(one);
+ q.add(two);
+ q.add(three);
+ for (Iterator it = q.iterator(); it.hasNext();) {
+ q.remove();
+ it.next();
+ }
+ assertEquals(0, q.size());
+ }
+
+
+ /**
+ * Descending iterator iterates through all elements
+ */
+ public void testDescendingIterator() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ int i = 0;
+ Iterator it = q.descendingIterator();
+ while (it.hasNext()) {
+ assertTrue(q.contains(it.next()));
+ ++i;
+ }
+ assertEquals(i, SIZE);
+ assertFalse(it.hasNext());
+ try {
+ it.next();
+ shouldThrow();
+ } catch (NoSuchElementException success) {}
+ }
+
+ /**
+ * Descending iterator ordering is reverse FIFO
+ */
+ public void testDescendingIteratorOrdering() {
+ final LinkedBlockingDeque q = new LinkedBlockingDeque();
+ for (int iters = 0; iters < 100; ++iters) {
+ q.add(new Integer(3));
+ q.add(new Integer(2));
+ q.add(new Integer(1));
+ int k = 0;
+ for (Iterator it = q.descendingIterator(); it.hasNext();) {
+ assertEquals(++k, it.next());
+ }
+
+ assertEquals(3, k);
+ q.remove();
+ q.remove();
+ q.remove();
+ }
+ }
+
+ /**
+ * descendingIterator.remove removes current element
+ */
+ public void testDescendingIteratorRemove () {
+ final LinkedBlockingDeque q = new LinkedBlockingDeque();
+ for (int iters = 0; iters < 100; ++iters) {
+ q.add(new Integer(3));
+ q.add(new Integer(2));
+ q.add(new Integer(1));
+ Iterator it = q.descendingIterator();
+ assertEquals(it.next(), new Integer(1));
+ it.remove();
+ assertEquals(it.next(), new Integer(2));
+ it = q.descendingIterator();
+ assertEquals(it.next(), new Integer(2));
+ assertEquals(it.next(), new Integer(3));
+ it.remove();
+ assertFalse(it.hasNext());
+ q.remove();
+ }
+ }
+
+
+ /**
+ * toString contains toStrings of elements
+ */
+ public void testToString() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ String s = q.toString();
+ for (int i = 0; i < SIZE; ++i) {
+ assertTrue(s.indexOf(String.valueOf(i)) >= 0);
+ }
+ }
+
+
+ /**
+ * offer transfers elements across Executor tasks
+ */
+ public void testOfferInExecutor() {
+ final LinkedBlockingDeque q = new LinkedBlockingDeque(2);
+ q.add(one);
+ q.add(two);
+ ExecutorService executor = Executors.newFixedThreadPool(2);
+ executor.execute(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertFalse(q.offer(three));
+ assertTrue(q.offer(three, MEDIUM_DELAY_MS, MILLISECONDS));
+ assertEquals(0, q.remainingCapacity());
+ }});
+
+ executor.execute(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ Thread.sleep(SMALL_DELAY_MS);
+ assertSame(one, q.take());
+ }});
+
+ joinPool(executor);
+ }
+
+ /**
+ * poll retrieves elements across Executor threads
+ */
+ public void testPollInExecutor() {
+ final LinkedBlockingDeque q = new LinkedBlockingDeque(2);
+ ExecutorService executor = Executors.newFixedThreadPool(2);
+ executor.execute(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertNull(q.poll());
+ assertSame(one, q.poll(MEDIUM_DELAY_MS, MILLISECONDS));
+ assertTrue(q.isEmpty());
+ }});
+
+ executor.execute(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ Thread.sleep(SMALL_DELAY_MS);
+ q.put(one);
+ }});
+
+ joinPool(executor);
+ }
+
+ /**
+ * A deserialized serialized deque has same elements in same order
+ */
+ public void testSerialization() throws Exception {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(q);
+ out.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ LinkedBlockingDeque r = (LinkedBlockingDeque)in.readObject();
+ assertEquals(q.size(), r.size());
+ while (!q.isEmpty())
+ assertEquals(q.remove(), r.remove());
+ }
+
+ /**
+ * drainTo(null) throws NPE
+ */
+ public void testDrainToNull() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ try {
+ q.drainTo(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * drainTo(this) throws IAE
+ */
+ public void testDrainToSelf() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ try {
+ q.drainTo(q);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * drainTo(c) empties deque into another collection c
+ */
+ public void testDrainTo() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ ArrayList l = new ArrayList();
+ q.drainTo(l);
+ assertEquals(q.size(), 0);
+ assertEquals(l.size(), SIZE);
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(l.get(i), new Integer(i));
+ q.add(zero);
+ q.add(one);
+ assertFalse(q.isEmpty());
+ assertTrue(q.contains(zero));
+ assertTrue(q.contains(one));
+ l.clear();
+ q.drainTo(l);
+ assertEquals(q.size(), 0);
+ assertEquals(l.size(), 2);
+ for (int i = 0; i < 2; ++i)
+ assertEquals(l.get(i), new Integer(i));
+ }
+
+ /**
+ * drainTo empties full deque, unblocking a waiting put.
+ */
+ public void testDrainToWithActivePut() throws InterruptedException {
+ final LinkedBlockingDeque q = populatedDeque(SIZE);
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ q.put(new Integer(SIZE+1));
+ }});
+
+ t.start();
+ ArrayList l = new ArrayList();
+ q.drainTo(l);
+ assertTrue(l.size() >= SIZE);
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(l.get(i), new Integer(i));
+ t.join();
+ assertTrue(q.size() + l.size() >= SIZE);
+ }
+
+ /**
+ * drainTo(null, n) throws NPE
+ */
+ public void testDrainToNullN() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ try {
+ q.drainTo(null, 0);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * drainTo(this, n) throws IAE
+ */
+ public void testDrainToSelfN() {
+ LinkedBlockingDeque q = populatedDeque(SIZE);
+ try {
+ q.drainTo(q, 0);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * drainTo(c, n) empties first max {n, size} elements of deque into c
+ */
+ public void testDrainToN() {
+ LinkedBlockingDeque q = new LinkedBlockingDeque();
+ for (int i = 0; i < SIZE + 2; ++i) {
+ for (int j = 0; j < SIZE; j++)
+ assertTrue(q.offer(new Integer(j)));
+ ArrayList l = new ArrayList();
+ q.drainTo(l, i);
+ int k = (i < SIZE)? i : SIZE;
+ assertEquals(l.size(), k);
+ assertEquals(q.size(), SIZE-k);
+ for (int j = 0; j < k; ++j)
+ assertEquals(l.get(j), new Integer(j));
+ while (q.poll() != null) ;
+ }
+ }
+
+}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/LinkedBlockingQueueTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/LinkedBlockingQueueTest.java
index dd6be9a..a98dc21 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/LinkedBlockingQueueTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/LinkedBlockingQueueTest.java
@@ -2,15 +2,16 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.*;
import java.util.concurrent.*;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.io.*;
public class LinkedBlockingQueueTest extends JSR166TestCase {
@@ -26,7 +27,7 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
private LinkedBlockingQueue populatedQueue(int n) {
LinkedBlockingQueue q = new LinkedBlockingQueue(n);
assertTrue(q.isEmpty());
- for(int i = 0; i < n; i++)
+ for (int i = 0; i < n; i++)
assertTrue(q.offer(new Integer(i)));
assertFalse(q.isEmpty());
assertEquals(0, q.remainingCapacity());
@@ -44,14 +45,13 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
}
/**
- * Constructor throws IAE if capacity argument nonpositive
+ * Constructor throws IAE if capacity argument nonpositive
*/
public void testConstructor2() {
try {
LinkedBlockingQueue q = new LinkedBlockingQueue(0);
shouldThrow();
- }
- catch (IllegalArgumentException success) {}
+ } catch (IllegalArgumentException success) {}
}
/**
@@ -61,8 +61,7 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
try {
LinkedBlockingQueue q = new LinkedBlockingQueue(null);
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
@@ -73,8 +72,7 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
Integer[] ints = new Integer[SIZE];
LinkedBlockingQueue q = new LinkedBlockingQueue(Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
@@ -87,23 +85,19 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
ints[i] = new Integer(i);
LinkedBlockingQueue q = new LinkedBlockingQueue(Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
* Queue contains all elements of collection used to initialize
*/
public void testConstructor6() {
- try {
- Integer[] ints = new Integer[SIZE];
- for (int i = 0; i < SIZE; ++i)
- ints[i] = new Integer(i);
- LinkedBlockingQueue q = new LinkedBlockingQueue(Arrays.asList(ints));
- for (int i = 0; i < SIZE; ++i)
- assertEquals(ints[i], q.poll());
- }
- finally {}
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = new Integer(i);
+ LinkedBlockingQueue q = new LinkedBlockingQueue(Arrays.asList(ints));
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(ints[i], q.poll());
}
/**
@@ -146,7 +140,7 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
LinkedBlockingQueue q = new LinkedBlockingQueue(1);
q.offer(null);
shouldThrow();
- } catch (NullPointerException success) { }
+ } catch (NullPointerException success) {}
}
/**
@@ -157,7 +151,7 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
LinkedBlockingQueue q = new LinkedBlockingQueue(1);
q.add(null);
shouldThrow();
- } catch (NullPointerException success) { }
+ } catch (NullPointerException success) {}
}
/**
@@ -180,8 +174,8 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
}
assertEquals(0, q.remainingCapacity());
q.add(new Integer(SIZE));
- } catch (IllegalStateException success){
- }
+ shouldThrow();
+ } catch (IllegalStateException success) {}
}
/**
@@ -192,8 +186,7 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
LinkedBlockingQueue q = new LinkedBlockingQueue(1);
q.addAll(null);
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
@@ -204,8 +197,7 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
LinkedBlockingQueue q = populatedQueue(SIZE);
q.addAll(q);
shouldThrow();
- }
- catch (IllegalArgumentException success) {}
+ } catch (IllegalArgumentException success) {}
}
/**
@@ -217,8 +209,7 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
Integer[] ints = new Integer[SIZE];
q.addAll(Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
* addAll of a collection with any null elements throws NPE after
@@ -232,8 +223,7 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
ints[i] = new Integer(i);
q.addAll(Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
* addAll throws ISE if not enough room
@@ -246,224 +236,175 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
ints[i] = new Integer(i);
q.addAll(Arrays.asList(ints));
shouldThrow();
- }
- catch (IllegalStateException success) {}
+ } catch (IllegalStateException success) {}
}
/**
* Queue contains all elements, in traversal order, of successful addAll
*/
public void testAddAll5() {
- try {
- Integer[] empty = new Integer[0];
- Integer[] ints = new Integer[SIZE];
- for (int i = 0; i < SIZE; ++i)
- ints[i] = new Integer(i);
- LinkedBlockingQueue q = new LinkedBlockingQueue(SIZE);
- assertFalse(q.addAll(Arrays.asList(empty)));
- assertTrue(q.addAll(Arrays.asList(ints)));
- for (int i = 0; i < SIZE; ++i)
- assertEquals(ints[i], q.poll());
- }
- finally {}
+ Integer[] empty = new Integer[0];
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = new Integer(i);
+ LinkedBlockingQueue q = new LinkedBlockingQueue(SIZE);
+ assertFalse(q.addAll(Arrays.asList(empty)));
+ assertTrue(q.addAll(Arrays.asList(ints)));
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(ints[i], q.poll());
}
/**
* put(null) throws NPE
*/
- public void testPutNull() {
+ public void testPutNull() throws InterruptedException {
try {
LinkedBlockingQueue q = new LinkedBlockingQueue(SIZE);
q.put(null);
shouldThrow();
- }
- catch (NullPointerException success){
- }
- catch (InterruptedException ie) {
- unexpectedException();
- }
+ } catch (NullPointerException success) {}
}
/**
* all elements successfully put are contained
*/
- public void testPut() {
- try {
- LinkedBlockingQueue q = new LinkedBlockingQueue(SIZE);
- for (int i = 0; i < SIZE; ++i) {
- Integer I = new Integer(i);
- q.put(I);
- assertTrue(q.contains(I));
- }
- assertEquals(0, q.remainingCapacity());
- }
- catch (InterruptedException ie) {
- unexpectedException();
+ public void testPut() throws InterruptedException {
+ LinkedBlockingQueue q = new LinkedBlockingQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ Integer I = new Integer(i);
+ q.put(I);
+ assertTrue(q.contains(I));
}
+ assertEquals(0, q.remainingCapacity());
}
/**
* put blocks interruptibly if full
*/
- public void testBlockingPut() {
- Thread t = new Thread(new Runnable() {
- public void run() {
- int added = 0;
- try {
- LinkedBlockingQueue q = new LinkedBlockingQueue(SIZE);
- for (int i = 0; i < SIZE; ++i) {
- q.put(new Integer(i));
- ++added;
- }
- q.put(new Integer(SIZE));
- threadShouldThrow();
- } catch (InterruptedException ie){
- threadAssertEquals(added, SIZE);
- }
- }});
+ public void testBlockingPut() throws InterruptedException {
+ final LinkedBlockingQueue q = new LinkedBlockingQueue(SIZE);
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ for (int i = 0; i < SIZE; ++i)
+ q.put(i);
+ assertEquals(SIZE, q.size());
+ assertEquals(0, q.remainingCapacity());
+ try {
+ q.put(99);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
t.start();
- try {
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- }
- catch (InterruptedException ie) {
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
+ assertEquals(SIZE, q.size());
+ assertEquals(0, q.remainingCapacity());
}
/**
* put blocks waiting for take when full
*/
- public void testPutWithTake() {
+ public void testPutWithTake() throws InterruptedException {
+ final int capacity = 2;
final LinkedBlockingQueue q = new LinkedBlockingQueue(2);
- Thread t = new Thread(new Runnable() {
- public void run() {
- int added = 0;
- try {
- q.put(new Object());
- ++added;
- q.put(new Object());
- ++added;
- q.put(new Object());
- ++added;
- q.put(new Object());
- ++added;
- threadShouldThrow();
- } catch (InterruptedException e){
- threadAssertTrue(added >= 2);
- }
- }
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- q.take();
- t.interrupt();
- t.join();
- } catch (Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ for (int i = 0; i < capacity + 1; i++)
+ q.put(i);
+ try {
+ q.put(99);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(q.remainingCapacity(), 0);
+ assertEquals(0, q.take());
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
+ assertEquals(q.remainingCapacity(), 0);
}
/**
* timed offer times out if full and elements not taken
*/
- public void testTimedOffer() {
+ public void testTimedOffer() throws InterruptedException {
final LinkedBlockingQueue q = new LinkedBlockingQueue(2);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- q.put(new Object());
- q.put(new Object());
- threadAssertFalse(q.offer(new Object(), SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- q.offer(new Object(), LONG_DELAY_MS, TimeUnit.MILLISECONDS);
- threadShouldThrow();
- } catch (InterruptedException success){}
- }
- });
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ q.put(new Object());
+ q.put(new Object());
+ assertFalse(q.offer(new Object(), SHORT_DELAY_MS, MILLISECONDS));
+ try {
+ q.offer(new Object(), LONG_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
- try {
- t.start();
- Thread.sleep(SMALL_DELAY_MS);
- t.interrupt();
- t.join();
- } catch (Exception e){
- unexpectedException();
- }
+ t.start();
+ Thread.sleep(SMALL_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* take retrieves elements in FIFO order
*/
- public void testTake() {
- try {
- LinkedBlockingQueue q = populatedQueue(SIZE);
- for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.take()).intValue());
- }
- } catch (InterruptedException e){
- unexpectedException();
+ public void testTake() throws InterruptedException {
+ LinkedBlockingQueue q = populatedQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.take());
}
}
/**
* take blocks interruptibly when empty
*/
- public void testTakeFromEmpty() {
+ public void testTakeFromEmpty() throws InterruptedException {
final LinkedBlockingQueue q = new LinkedBlockingQueue(2);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- q.take();
- threadShouldThrow();
- } catch (InterruptedException success){ }
- }
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- } catch (Exception e){
- unexpectedException();
- }
+ Thread t = new ThreadShouldThrow(InterruptedException.class) {
+ public void realRun() throws InterruptedException {
+ q.take();
+ }};
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* Take removes existing elements until empty, then blocks interruptibly
*/
- public void testBlockingTake() {
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- LinkedBlockingQueue q = populatedQueue(SIZE);
- for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.take()).intValue());
- }
- q.take();
- threadShouldThrow();
- } catch (InterruptedException success){
- }
- }});
+ public void testBlockingTake() throws InterruptedException {
+ final LinkedBlockingQueue q = populatedQueue(SIZE);
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.take());
+ }
+ try {
+ q.take();
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
t.start();
- try {
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- }
- catch (InterruptedException ie) {
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
-
/**
* poll succeeds unless empty
*/
public void testPoll() {
LinkedBlockingQueue q = populatedQueue(SIZE);
for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.poll()).intValue());
+ assertEquals(i, q.poll());
}
assertNull(q.poll());
}
@@ -471,85 +412,69 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
/**
* timed pool with zero timeout succeeds when non-empty, else times out
*/
- public void testTimedPoll0() {
- try {
- LinkedBlockingQueue q = populatedQueue(SIZE);
- for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.poll(0, TimeUnit.MILLISECONDS)).intValue());
- }
- assertNull(q.poll(0, TimeUnit.MILLISECONDS));
- } catch (InterruptedException e){
- unexpectedException();
+ public void testTimedPoll0() throws InterruptedException {
+ LinkedBlockingQueue q = populatedQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.poll(0, MILLISECONDS));
}
+ assertNull(q.poll(0, MILLISECONDS));
}
/**
* timed pool with nonzero timeout succeeds when non-empty, else times out
*/
- public void testTimedPoll() {
- try {
- LinkedBlockingQueue q = populatedQueue(SIZE);
- for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)).intValue());
- }
- assertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- } catch (InterruptedException e){
- unexpectedException();
+ public void testTimedPoll() throws InterruptedException {
+ LinkedBlockingQueue q = populatedQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.poll(SHORT_DELAY_MS, MILLISECONDS));
}
+ assertNull(q.poll(SHORT_DELAY_MS, MILLISECONDS));
}
/**
* Interrupted timed poll throws InterruptedException instead of
* returning timeout status
*/
- public void testInterruptedTimedPoll() {
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- LinkedBlockingQueue q = populatedQueue(SIZE);
- for (int i = 0; i < SIZE; ++i) {
- threadAssertEquals(i, ((Integer)q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)).intValue());
- }
- threadAssertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- } catch (InterruptedException success){
- }
- }});
+ public void testInterruptedTimedPoll() throws InterruptedException {
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ LinkedBlockingQueue q = populatedQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.poll(SHORT_DELAY_MS, MILLISECONDS));
+ }
+ try {
+ q.poll(SMALL_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
t.start();
- try {
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- }
- catch (InterruptedException ie) {
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* timed poll before a delayed offer fails; after offer succeeds;
* on interruption throws
*/
- public void testTimedPollWithOffer() {
+ public void testTimedPollWithOffer() throws InterruptedException {
final LinkedBlockingQueue q = new LinkedBlockingQueue(2);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- threadAssertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- q.poll(LONG_DELAY_MS, TimeUnit.MILLISECONDS);
- q.poll(LONG_DELAY_MS, TimeUnit.MILLISECONDS);
- threadShouldThrow();
- } catch (InterruptedException success) { }
- }
- });
- try {
- t.start();
- Thread.sleep(SMALL_DELAY_MS);
- assertTrue(q.offer(zero, SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- t.interrupt();
- t.join();
- } catch (Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertNull(q.poll(SHORT_DELAY_MS, MILLISECONDS));
+ assertSame(zero, q.poll(LONG_DELAY_MS, MILLISECONDS));
+ try {
+ q.poll(LONG_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SMALL_DELAY_MS);
+ assertTrue(q.offer(zero, SHORT_DELAY_MS, MILLISECONDS));
+ t.interrupt();
+ t.join();
}
/**
@@ -558,10 +483,10 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
public void testPeek() {
LinkedBlockingQueue q = populatedQueue(SIZE);
for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.peek()).intValue());
- q.poll();
+ assertEquals(i, q.peek());
+ assertEquals(i, q.poll());
assertTrue(q.peek() == null ||
- i != ((Integer)q.peek()).intValue());
+ !q.peek().equals(i));
}
assertNull(q.peek());
}
@@ -572,14 +497,13 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
public void testElement() {
LinkedBlockingQueue q = populatedQueue(SIZE);
for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.element()).intValue());
- q.poll();
+ assertEquals(i, q.element());
+ assertEquals(i, q.poll());
}
try {
q.element();
shouldThrow();
- }
- catch (NoSuchElementException success) {}
+ } catch (NoSuchElementException success) {}
}
/**
@@ -588,13 +512,12 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
public void testRemove() {
LinkedBlockingQueue q = populatedQueue(SIZE);
for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.remove()).intValue());
+ assertEquals(i, q.remove());
}
try {
q.remove();
shouldThrow();
- } catch (NoSuchElementException success){
- }
+ } catch (NoSuchElementException success) {}
}
/**
@@ -615,18 +538,14 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
/**
* An add following remove(x) succeeds
*/
- public void testRemoveElementAndAdd() {
- try {
- LinkedBlockingQueue q = new LinkedBlockingQueue();
- assertTrue(q.add(new Integer(1)));
- assertTrue(q.add(new Integer(2)));
- assertTrue(q.remove(new Integer(1)));
- assertTrue(q.remove(new Integer(2)));
- assertTrue(q.add(new Integer(3)));
- assertTrue(q.take() != null);
- } catch (Exception e){
- unexpectedException();
- }
+ public void testRemoveElementAndAdd() throws InterruptedException {
+ LinkedBlockingQueue q = new LinkedBlockingQueue();
+ assertTrue(q.add(new Integer(1)));
+ assertTrue(q.add(new Integer(2)));
+ assertTrue(q.remove(new Integer(1)));
+ assertTrue(q.remove(new Integer(2)));
+ assertTrue(q.add(new Integer(3)));
+ assertTrue(q.take() != null);
}
/**
@@ -709,67 +628,55 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
/**
* toArray contains all elements
*/
- public void testToArray() {
+ public void testToArray() throws InterruptedException {
LinkedBlockingQueue q = populatedQueue(SIZE);
Object[] o = q.toArray();
- try {
- for(int i = 0; i < o.length; i++)
+ for (int i = 0; i < o.length; i++)
assertEquals(o[i], q.take());
- } catch (InterruptedException e){
- unexpectedException();
- }
}
/**
* toArray(a) contains all elements
*/
- public void testToArray2() {
+ public void testToArray2() throws InterruptedException {
LinkedBlockingQueue q = populatedQueue(SIZE);
Integer[] ints = new Integer[SIZE];
ints = (Integer[])q.toArray(ints);
- try {
- for(int i = 0; i < ints.length; i++)
- assertEquals(ints[i], q.take());
- } catch (InterruptedException e){
- unexpectedException();
- }
+ for (int i = 0; i < ints.length; i++)
+ assertEquals(ints[i], q.take());
}
/**
* toArray(null) throws NPE
*/
public void testToArray_BadArg() {
+ LinkedBlockingQueue q = populatedQueue(SIZE);
try {
- LinkedBlockingQueue q = populatedQueue(SIZE);
Object o[] = q.toArray(null);
shouldThrow();
- } catch(NullPointerException success){}
+ } catch (NullPointerException success) {}
}
/**
* toArray with incompatible array type throws CCE
*/
public void testToArray1_BadArg() {
+ LinkedBlockingQueue q = populatedQueue(SIZE);
try {
- LinkedBlockingQueue q = populatedQueue(SIZE);
- Object o[] = q.toArray(new String[10] );
+ Object o[] = q.toArray(new String[10]);
shouldThrow();
- } catch(ArrayStoreException success){}
+ } catch (ArrayStoreException success) {}
}
/**
* iterator iterates through all elements
*/
- public void testIterator() {
+ public void testIterator() throws InterruptedException {
LinkedBlockingQueue q = populatedQueue(SIZE);
Iterator it = q.iterator();
- try {
- while(it.hasNext()){
- assertEquals(it.next(), q.take());
- }
- } catch (InterruptedException e){
- unexpectedException();
+ while (it.hasNext()) {
+ assertEquals(it.next(), q.take());
}
}
@@ -787,8 +694,8 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
it.remove();
it = q.iterator();
- assertEquals(it.next(), one);
- assertEquals(it.next(), three);
+ assertSame(it.next(), one);
+ assertSame(it.next(), three);
assertFalse(it.hasNext());
}
@@ -804,8 +711,7 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
assertEquals(0, q.remainingCapacity());
int k = 0;
for (Iterator it = q.iterator(); it.hasNext();) {
- int i = ((Integer)(it.next())).intValue();
- assertEquals(++k, i);
+ assertEquals(++k, it.next());
}
assertEquals(3, k);
}
@@ -818,14 +724,9 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
q.add(one);
q.add(two);
q.add(three);
- try {
- for (Iterator it = q.iterator(); it.hasNext();) {
- q.remove();
- it.next();
- }
- }
- catch (ConcurrentModificationException e) {
- unexpectedException();
+ for (Iterator it = q.iterator(); it.hasNext();) {
+ q.remove();
+ it.next();
}
assertEquals(0, q.size());
}
@@ -851,30 +752,18 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
q.add(one);
q.add(two);
ExecutorService executor = Executors.newFixedThreadPool(2);
- executor.execute(new Runnable() {
- public void run() {
- threadAssertFalse(q.offer(three));
- try {
- threadAssertTrue(q.offer(three, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS));
- threadAssertEquals(0, q.remainingCapacity());
- }
- catch (InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
-
- executor.execute(new Runnable() {
- public void run() {
- try {
- Thread.sleep(SMALL_DELAY_MS);
- threadAssertEquals(one, q.take());
- }
- catch (InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
+ executor.execute(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertFalse(q.offer(three));
+ assertTrue(q.offer(three, MEDIUM_DELAY_MS, MILLISECONDS));
+ assertEquals(0, q.remainingCapacity());
+ }});
+
+ executor.execute(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ Thread.sleep(SMALL_DELAY_MS);
+ assertSame(one, q.take());
+ }});
joinPool(executor);
}
@@ -885,30 +774,18 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
public void testPollInExecutor() {
final LinkedBlockingQueue q = new LinkedBlockingQueue(2);
ExecutorService executor = Executors.newFixedThreadPool(2);
- executor.execute(new Runnable() {
- public void run() {
- threadAssertNull(q.poll());
- try {
- threadAssertTrue(null != q.poll(MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS));
- threadAssertTrue(q.isEmpty());
- }
- catch (InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
-
- executor.execute(new Runnable() {
- public void run() {
- try {
- Thread.sleep(SMALL_DELAY_MS);
- q.put(one);
- }
- catch (InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
+ executor.execute(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertNull(q.poll());
+ assertSame(one, q.poll(MEDIUM_DELAY_MS, MILLISECONDS));
+ assertTrue(q.isEmpty());
+ }});
+
+ executor.execute(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ Thread.sleep(SMALL_DELAY_MS);
+ q.put(one);
+ }});
joinPool(executor);
}
@@ -916,24 +793,20 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
/**
* A deserialized serialized queue has same elements in same order
*/
- public void testSerialization() {
+ public void testSerialization() throws Exception {
LinkedBlockingQueue q = populatedQueue(SIZE);
- try {
- ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
- ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
- out.writeObject(q);
- out.close();
-
- ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
- ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
- LinkedBlockingQueue r = (LinkedBlockingQueue)in.readObject();
- assertEquals(q.size(), r.size());
- while (!q.isEmpty())
- assertEquals(q.remove(), r.remove());
- } catch(Exception e){
- unexpectedException();
- }
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(q);
+ out.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ LinkedBlockingQueue r = (LinkedBlockingQueue)in.readObject();
+ assertEquals(q.size(), r.size());
+ while (!q.isEmpty())
+ assertEquals(q.remove(), r.remove());
}
/**
@@ -944,8 +817,7 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
try {
q.drainTo(null);
shouldThrow();
- } catch(NullPointerException success) {
- }
+ } catch (NullPointerException success) {}
}
/**
@@ -956,8 +828,7 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
try {
q.drainTo(q);
shouldThrow();
- } catch(IllegalArgumentException success) {
- }
+ } catch (IllegalArgumentException success) {}
}
/**
@@ -987,29 +858,21 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
/**
* drainTo empties full queue, unblocking a waiting put.
*/
- public void testDrainToWithActivePut() {
+ public void testDrainToWithActivePut() throws InterruptedException {
final LinkedBlockingQueue q = populatedQueue(SIZE);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- q.put(new Integer(SIZE+1));
- } catch (InterruptedException ie){
- threadUnexpectedException();
- }
- }
- });
- try {
- t.start();
- ArrayList l = new ArrayList();
- q.drainTo(l);
- assertTrue(l.size() >= SIZE);
- for (int i = 0; i < SIZE; ++i)
- assertEquals(l.get(i), new Integer(i));
- t.join();
- assertTrue(q.size() + l.size() >= SIZE);
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ q.put(new Integer(SIZE+1));
+ }});
+
+ t.start();
+ ArrayList l = new ArrayList();
+ q.drainTo(l);
+ assertTrue(l.size() >= SIZE);
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(l.get(i), new Integer(i));
+ t.join();
+ assertTrue(q.size() + l.size() >= SIZE);
}
/**
@@ -1020,8 +883,7 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
try {
q.drainTo(null, 0);
shouldThrow();
- } catch(NullPointerException success) {
- }
+ } catch (NullPointerException success) {}
}
/**
@@ -1032,8 +894,7 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
try {
q.drainTo(q, 0);
shouldThrow();
- } catch(IllegalArgumentException success) {
- }
+ } catch (IllegalArgumentException success) {}
}
/**
@@ -1042,7 +903,7 @@ public class LinkedBlockingQueueTest extends JSR166TestCase {
public void testDrainToN() {
LinkedBlockingQueue q = new LinkedBlockingQueue();
for (int i = 0; i < SIZE + 2; ++i) {
- for(int j = 0; j < SIZE; j++)
+ for (int j = 0; j < SIZE; j++)
assertTrue(q.offer(new Integer(j)));
ArrayList l = new ArrayList();
q.drainTo(l, i);
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/LockSupportTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/LockSupportTest.java
index 0a74f91..1052a24 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/LockSupportTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/LockSupportTest.java
@@ -2,18 +2,18 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
-public class LockSupportTest extends JSR166TestCase{
+public class LockSupportTest extends JSR166TestCase {
public static Test suite() {
return new TestSuite(LockSupportTest.class);
}
@@ -21,145 +21,92 @@ public class LockSupportTest extends JSR166TestCase{
/**
* park is released by unpark occurring after park
*/
- public void testPark() {
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- LockSupport.park();
- } catch(Exception e){
- threadUnexpectedException();
- }
- }
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- LockSupport.unpark(t);
- t.join();
- }
- catch(Exception e) {
- unexpectedException();
- }
+ public void testPark() throws InterruptedException {
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ LockSupport.park();
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ LockSupport.unpark(t);
+ t.join();
}
/**
* park is released by unpark occurring before park
*/
- public void testPark2() {
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- Thread.sleep(SHORT_DELAY_MS);
- LockSupport.park();
- } catch(Exception e){
- threadUnexpectedException();
- }
- }
- });
- try {
- t.start();
- LockSupport.unpark(t);
- t.join();
- }
- catch(Exception e) {
- unexpectedException();
- }
+ public void testPark2() throws InterruptedException {
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ Thread.sleep(SHORT_DELAY_MS);
+ LockSupport.park();
+ }});
+
+ t.start();
+ LockSupport.unpark(t);
+ t.join();
}
/**
* park is released by interrupt
*/
- public void testPark3() {
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- LockSupport.park();
- } catch(Exception e){
- threadUnexpectedException();
- }
- }
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- }
- catch(Exception e) {
- unexpectedException();
- }
+ public void testPark3() throws InterruptedException {
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ LockSupport.park();
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* park returns if interrupted before park
*/
- public void testPark4() {
+ public void testPark4() throws InterruptedException {
final ReentrantLock lock = new ReentrantLock();
lock.lock();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- lock.lock();
- LockSupport.park();
- } catch(Exception e){
- threadUnexpectedException();
- }
- }
- });
- try {
- t.start();
- t.interrupt();
- lock.unlock();
- t.join();
- }
- catch(Exception e) {
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ lock.lock();
+ LockSupport.park();
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ lock.unlock();
+ t.join();
}
/**
* parkNanos times out if not unparked
*/
- public void testParkNanos() {
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- LockSupport.parkNanos(1000);
- } catch(Exception e){
- threadUnexpectedException();
- }
- }
- });
- try {
- t.start();
- t.join();
- }
- catch(Exception e) {
- unexpectedException();
- }
+ public void testParkNanos() throws InterruptedException {
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ LockSupport.parkNanos(1000);
+ }});
+
+ t.start();
+ t.join();
}
/**
* parkUntil times out if not unparked
*/
- public void testParkUntil() {
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- long d = new Date().getTime() + 100;
- LockSupport.parkUntil(d);
- } catch(Exception e){
- threadUnexpectedException();
- }
- }
- });
- try {
- t.start();
- t.join();
- }
- catch(Exception e) {
- unexpectedException();
- }
+ public void testParkUntil() throws InterruptedException {
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ long d = new Date().getTime() + 100;
+ LockSupport.parkUntil(d);
+ }});
+
+ t.start();
+ t.join();
}
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/PriorityBlockingQueueTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/PriorityBlockingQueueTest.java
index a764866..f1dd88d 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/PriorityBlockingQueueTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/PriorityBlockingQueueTest.java
@@ -2,15 +2,16 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.*;
import java.util.concurrent.*;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.io.*;
public class PriorityBlockingQueueTest extends JSR166TestCase {
@@ -21,13 +22,9 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
private static final int NOCAP = Integer.MAX_VALUE;
/** Sample Comparator */
- static class MyReverseComparator implements Comparator {
+ static class MyReverseComparator implements Comparator {
public int compare(Object x, Object y) {
- int i = ((Integer)x).intValue();
- int j = ((Integer)y).intValue();
- if (i < j) return 1;
- if (i > j) return -1;
- return 0;
+ return ((Comparable)y).compareTo(x);
}
}
@@ -38,16 +35,16 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
private PriorityBlockingQueue populatedQueue(int n) {
PriorityBlockingQueue q = new PriorityBlockingQueue(n);
assertTrue(q.isEmpty());
- for(int i = n-1; i >= 0; i-=2)
+ for (int i = n-1; i >= 0; i-=2)
assertTrue(q.offer(new Integer(i)));
- for(int i = (n & 1); i < n; i+=2)
+ for (int i = (n & 1); i < n; i+=2)
assertTrue(q.offer(new Integer(i)));
assertFalse(q.isEmpty());
assertEquals(NOCAP, q.remainingCapacity());
assertEquals(n, q.size());
return q;
}
-
+
/**
* A new queue has unbounded capacity
*/
@@ -56,14 +53,13 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
}
/**
- * Constructor throws IAE if capacity argument nonpositive
+ * Constructor throws IAE if capacity argument nonpositive
*/
public void testConstructor2() {
try {
PriorityBlockingQueue q = new PriorityBlockingQueue(0);
shouldThrow();
- }
- catch (IllegalArgumentException success) {}
+ } catch (IllegalArgumentException success) {}
}
/**
@@ -73,8 +69,7 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
try {
PriorityBlockingQueue q = new PriorityBlockingQueue(null);
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
@@ -85,8 +80,7 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
Integer[] ints = new Integer[SIZE];
PriorityBlockingQueue q = new PriorityBlockingQueue(Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
@@ -99,41 +93,34 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
ints[i] = new Integer(i);
PriorityBlockingQueue q = new PriorityBlockingQueue(Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
* Queue contains all elements of collection used to initialize
*/
public void testConstructor6() {
- try {
- Integer[] ints = new Integer[SIZE];
- for (int i = 0; i < SIZE; ++i)
- ints[i] = new Integer(i);
- PriorityBlockingQueue q = new PriorityBlockingQueue(Arrays.asList(ints));
- for (int i = 0; i < SIZE; ++i)
- assertEquals(ints[i], q.poll());
- }
- finally {}
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = new Integer(i);
+ PriorityBlockingQueue q = new PriorityBlockingQueue(Arrays.asList(ints));
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(ints[i], q.poll());
}
/**
* The comparator used in constructor is used
*/
public void testConstructor7() {
- try {
- MyReverseComparator cmp = new MyReverseComparator();
- PriorityBlockingQueue q = new PriorityBlockingQueue(SIZE, cmp);
- assertEquals(cmp, q.comparator());
- Integer[] ints = new Integer[SIZE];
- for (int i = 0; i < SIZE; ++i)
- ints[i] = new Integer(i);
- q.addAll(Arrays.asList(ints));
- for (int i = SIZE-1; i >= 0; --i)
- assertEquals(ints[i], q.poll());
- }
- finally {}
+ MyReverseComparator cmp = new MyReverseComparator();
+ PriorityBlockingQueue q = new PriorityBlockingQueue(SIZE, cmp);
+ assertEquals(cmp, q.comparator());
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = new Integer(i);
+ q.addAll(Arrays.asList(ints));
+ for (int i = SIZE-1; i >= 0; --i)
+ assertEquals(ints[i], q.poll());
}
/**
@@ -177,7 +164,7 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
PriorityBlockingQueue q = new PriorityBlockingQueue(1);
q.offer(null);
shouldThrow();
- } catch (NullPointerException success) { }
+ } catch (NullPointerException success) {}
}
/**
@@ -188,7 +175,7 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
PriorityBlockingQueue q = new PriorityBlockingQueue(1);
q.add(null);
shouldThrow();
- } catch (NullPointerException success) { }
+ } catch (NullPointerException success) {}
}
/**
@@ -210,8 +197,7 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
q.offer(new Object());
q.offer(new Object());
shouldThrow();
- }
- catch(ClassCastException success) {}
+ } catch (ClassCastException success) {}
}
/**
@@ -233,8 +219,7 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
PriorityBlockingQueue q = new PriorityBlockingQueue(1);
q.addAll(null);
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
@@ -245,8 +230,7 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
PriorityBlockingQueue q = populatedQueue(SIZE);
q.addAll(q);
shouldThrow();
- }
- catch (IllegalArgumentException success) {}
+ } catch (IllegalArgumentException success) {}
}
/**
@@ -258,8 +242,7 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
Integer[] ints = new Integer[SIZE];
q.addAll(Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
* addAll of a collection with any null elements throws NPE after
@@ -273,26 +256,22 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
ints[i] = new Integer(i);
q.addAll(Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
* Queue contains all elements of successful addAll
*/
public void testAddAll5() {
- try {
- Integer[] empty = new Integer[0];
- Integer[] ints = new Integer[SIZE];
- for (int i = SIZE-1; i >= 0; --i)
- ints[i] = new Integer(i);
- PriorityBlockingQueue q = new PriorityBlockingQueue(SIZE);
- assertFalse(q.addAll(Arrays.asList(empty)));
- assertTrue(q.addAll(Arrays.asList(ints)));
- for (int i = 0; i < SIZE; ++i)
- assertEquals(ints[i], q.poll());
- }
- finally {}
+ Integer[] empty = new Integer[0];
+ Integer[] ints = new Integer[SIZE];
+ for (int i = SIZE-1; i >= 0; --i)
+ ints[i] = new Integer(i);
+ PriorityBlockingQueue q = new PriorityBlockingQueue(SIZE);
+ assertFalse(q.addAll(Arrays.asList(empty)));
+ assertTrue(q.addAll(Arrays.asList(ints)));
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(ints[i], q.poll());
}
/**
@@ -303,149 +282,107 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
PriorityBlockingQueue q = new PriorityBlockingQueue(SIZE);
q.put(null);
shouldThrow();
- }
- catch (NullPointerException success){
- }
+ } catch (NullPointerException success) {}
}
/**
* all elements successfully put are contained
*/
public void testPut() {
- try {
- PriorityBlockingQueue q = new PriorityBlockingQueue(SIZE);
- for (int i = 0; i < SIZE; ++i) {
- Integer I = new Integer(i);
- q.put(I);
- assertTrue(q.contains(I));
- }
- assertEquals(SIZE, q.size());
+ PriorityBlockingQueue q = new PriorityBlockingQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ Integer I = new Integer(i);
+ q.put(I);
+ assertTrue(q.contains(I));
}
- finally {
- }
+ assertEquals(SIZE, q.size());
}
/**
* put doesn't block waiting for take
*/
- public void testPutWithTake() {
+ public void testPutWithTake() throws InterruptedException {
final PriorityBlockingQueue q = new PriorityBlockingQueue(2);
- Thread t = new Thread(new Runnable() {
- public void run() {
- int added = 0;
- try {
- q.put(new Integer(0));
- ++added;
- q.put(new Integer(0));
- ++added;
- q.put(new Integer(0));
- ++added;
- q.put(new Integer(0));
- ++added;
- threadAssertTrue(added == 4);
- } finally {
- }
- }
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- q.take();
- t.interrupt();
- t.join();
- } catch (Exception e){
- unexpectedException();
- }
+ final int size = 4;
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ for (int i = 0; i < size; i++)
+ q.put(new Integer(0));
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(q.size(), size);
+ q.take();
+ t.interrupt();
+ t.join();
}
/**
* timed offer does not time out
*/
- public void testTimedOffer() {
+ public void testTimedOffer() throws InterruptedException {
final PriorityBlockingQueue q = new PriorityBlockingQueue(2);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- q.put(new Integer(0));
- q.put(new Integer(0));
- threadAssertTrue(q.offer(new Integer(0), SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- threadAssertTrue(q.offer(new Integer(0), LONG_DELAY_MS, TimeUnit.MILLISECONDS));
- } finally { }
- }
- });
-
- try {
- t.start();
- Thread.sleep(SMALL_DELAY_MS);
- t.interrupt();
- t.join();
- } catch (Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ q.put(new Integer(0));
+ q.put(new Integer(0));
+ assertTrue(q.offer(new Integer(0), SHORT_DELAY_MS, MILLISECONDS));
+ assertTrue(q.offer(new Integer(0), LONG_DELAY_MS, MILLISECONDS));
+ }});
+
+ t.start();
+ Thread.sleep(SMALL_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* take retrieves elements in priority order
*/
- public void testTake() {
- try {
- PriorityBlockingQueue q = populatedQueue(SIZE);
- for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.take()).intValue());
- }
- } catch (InterruptedException e){
- unexpectedException();
- }
+ public void testTake() throws InterruptedException {
+ PriorityBlockingQueue q = populatedQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.take());
+ }
}
/**
* take blocks interruptibly when empty
*/
- public void testTakeFromEmpty() {
+ public void testTakeFromEmpty() throws InterruptedException {
final PriorityBlockingQueue q = new PriorityBlockingQueue(2);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- q.take();
- threadShouldThrow();
- } catch (InterruptedException success){ }
- }
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- } catch (Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ q.take();
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* Take removes existing elements until empty, then blocks interruptibly
*/
- public void testBlockingTake() {
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- PriorityBlockingQueue q = populatedQueue(SIZE);
- for (int i = 0; i < SIZE; ++i) {
- threadAssertEquals(i, ((Integer)q.take()).intValue());
- }
- q.take();
- threadShouldThrow();
- } catch (InterruptedException success){
- }
- }});
+ public void testBlockingTake() throws InterruptedException {
+ final PriorityBlockingQueue q = populatedQueue(SIZE);
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.take());
+ }
+ try {
+ q.take();
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
t.start();
- try {
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- }
- catch (InterruptedException ie) {
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
@@ -455,7 +392,7 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
public void testPoll() {
PriorityBlockingQueue q = populatedQueue(SIZE);
for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.poll()).intValue());
+ assertEquals(i, q.poll());
}
assertNull(q.poll());
}
@@ -463,86 +400,70 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
/**
* timed pool with zero timeout succeeds when non-empty, else times out
*/
- public void testTimedPoll0() {
- try {
- PriorityBlockingQueue q = populatedQueue(SIZE);
- for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.poll(0, TimeUnit.MILLISECONDS)).intValue());
- }
- assertNull(q.poll(0, TimeUnit.MILLISECONDS));
- } catch (InterruptedException e){
- unexpectedException();
- }
+ public void testTimedPoll0() throws InterruptedException {
+ PriorityBlockingQueue q = populatedQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.poll(0, MILLISECONDS));
+ }
+ assertNull(q.poll(0, MILLISECONDS));
}
/**
* timed pool with nonzero timeout succeeds when non-empty, else times out
*/
- public void testTimedPoll() {
- try {
- PriorityBlockingQueue q = populatedQueue(SIZE);
- for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)).intValue());
- }
- assertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- } catch (InterruptedException e){
- unexpectedException();
- }
+ public void testTimedPoll() throws InterruptedException {
+ PriorityBlockingQueue q = populatedQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.poll(SHORT_DELAY_MS, MILLISECONDS));
+ }
+ assertNull(q.poll(SHORT_DELAY_MS, MILLISECONDS));
}
/**
* Interrupted timed poll throws InterruptedException instead of
* returning timeout status
*/
- public void testInterruptedTimedPoll() {
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- PriorityBlockingQueue q = populatedQueue(SIZE);
- for (int i = 0; i < SIZE; ++i) {
- threadAssertEquals(i, ((Integer)q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)).intValue());
- }
- threadAssertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- } catch (InterruptedException success){
- }
- }});
+ public void testInterruptedTimedPoll() throws InterruptedException {
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ PriorityBlockingQueue q = populatedQueue(SIZE);
+ for (int i = 0; i < SIZE; ++i) {
+ assertEquals(i, q.poll(SHORT_DELAY_MS, MILLISECONDS));
+ }
+ try {
+ q.poll(SMALL_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
t.start();
- try {
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- }
- catch (InterruptedException ie) {
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* timed poll before a delayed offer fails; after offer succeeds;
* on interruption throws
*/
- public void testTimedPollWithOffer() {
+ public void testTimedPollWithOffer() throws InterruptedException {
final PriorityBlockingQueue q = new PriorityBlockingQueue(2);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- threadAssertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- q.poll(LONG_DELAY_MS, TimeUnit.MILLISECONDS);
- q.poll(LONG_DELAY_MS, TimeUnit.MILLISECONDS);
- threadShouldThrow();
- } catch (InterruptedException success) { }
- }
- });
- try {
- t.start();
- Thread.sleep(SMALL_DELAY_MS);
- assertTrue(q.offer(new Integer(0), SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- t.interrupt();
- t.join();
- } catch (Exception e){
- unexpectedException();
- }
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertNull(q.poll(SHORT_DELAY_MS, MILLISECONDS));
+ assertSame(zero, q.poll(MEDIUM_DELAY_MS, MILLISECONDS));
+ try {
+ q.poll(LONG_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SMALL_DELAY_MS);
+ assertTrue(q.offer(zero, SHORT_DELAY_MS, MILLISECONDS));
+ t.interrupt();
+ t.join();
+ }
/**
@@ -551,10 +472,10 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
public void testPeek() {
PriorityBlockingQueue q = populatedQueue(SIZE);
for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.peek()).intValue());
- q.poll();
+ assertEquals(i, q.peek());
+ assertEquals(i, q.poll());
assertTrue(q.peek() == null ||
- i != ((Integer)q.peek()).intValue());
+ !q.peek().equals(i));
}
assertNull(q.peek());
}
@@ -565,14 +486,13 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
public void testElement() {
PriorityBlockingQueue q = populatedQueue(SIZE);
for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.element()).intValue());
- q.poll();
+ assertEquals(i, q.element());
+ assertEquals(i, q.poll());
}
try {
q.element();
shouldThrow();
- }
- catch (NoSuchElementException success) {}
+ } catch (NoSuchElementException success) {}
}
/**
@@ -581,13 +501,12 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
public void testRemove() {
PriorityBlockingQueue q = populatedQueue(SIZE);
for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.remove()).intValue());
+ assertEquals(i, q.remove());
}
try {
q.remove();
shouldThrow();
- } catch (NoSuchElementException success){
- }
+ } catch (NoSuchElementException success) {}
}
/**
@@ -604,7 +523,7 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
}
assertTrue(q.isEmpty());
}
-
+
/**
* contains(x) reports true when elements added but not yet removed
*/
@@ -684,56 +603,48 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
/**
* toArray contains all elements
*/
- public void testToArray() {
+ public void testToArray() throws InterruptedException {
PriorityBlockingQueue q = populatedQueue(SIZE);
Object[] o = q.toArray();
Arrays.sort(o);
- try {
- for(int i = 0; i < o.length; i++)
+ for (int i = 0; i < o.length; i++)
assertEquals(o[i], q.take());
- } catch (InterruptedException e){
- unexpectedException();
- }
}
/**
* toArray(a) contains all elements
*/
- public void testToArray2() {
+ public void testToArray2() throws InterruptedException {
PriorityBlockingQueue q = populatedQueue(SIZE);
Integer[] ints = new Integer[SIZE];
ints = (Integer[])q.toArray(ints);
Arrays.sort(ints);
- try {
- for(int i = 0; i < ints.length; i++)
- assertEquals(ints[i], q.take());
- } catch (InterruptedException e){
- unexpectedException();
- }
+ for (int i = 0; i < ints.length; i++)
+ assertEquals(ints[i], q.take());
}
/**
* toArray(null) throws NPE
*/
public void testToArray_BadArg() {
+ PriorityBlockingQueue q = populatedQueue(SIZE);
try {
- PriorityBlockingQueue q = populatedQueue(SIZE);
Object o[] = q.toArray(null);
shouldThrow();
- } catch(NullPointerException success){}
+ } catch (NullPointerException success) {}
}
/**
* toArray with incompatible array type throws CCE
*/
public void testToArray1_BadArg() {
+ PriorityBlockingQueue q = populatedQueue(SIZE);
try {
- PriorityBlockingQueue q = populatedQueue(SIZE);
- Object o[] = q.toArray(new String[10] );
+ Object o[] = q.toArray(new String[10]);
shouldThrow();
- } catch(ArrayStoreException success){}
+ } catch (ArrayStoreException success) {}
}
-
+
/**
* iterator iterates through all elements
*/
@@ -741,7 +652,7 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
PriorityBlockingQueue q = populatedQueue(SIZE);
int i = 0;
Iterator it = q.iterator();
- while(it.hasNext()) {
+ while (it.hasNext()) {
assertTrue(q.contains(it.next()));
++i;
}
@@ -777,7 +688,7 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
for (int i = 0; i < SIZE; ++i) {
assertTrue(s.indexOf(String.valueOf(i)) >= 0);
}
- }
+ }
/**
* offer transfers elements across Executor tasks
@@ -785,90 +696,72 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
public void testPollInExecutor() {
final PriorityBlockingQueue q = new PriorityBlockingQueue(2);
ExecutorService executor = Executors.newFixedThreadPool(2);
- executor.execute(new Runnable() {
- public void run() {
- threadAssertNull(q.poll());
- try {
- threadAssertTrue(null != q.poll(MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS));
- threadAssertTrue(q.isEmpty());
- }
- catch (InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
+ executor.execute(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertNull(q.poll());
+ assertSame(one, q.poll(MEDIUM_DELAY_MS, MILLISECONDS));
+ assertTrue(q.isEmpty());
+ }});
+
+ executor.execute(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ Thread.sleep(SMALL_DELAY_MS);
+ q.put(one);
+ }});
- executor.execute(new Runnable() {
- public void run() {
- try {
- Thread.sleep(SMALL_DELAY_MS);
- q.put(new Integer(1));
- }
- catch (InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
-
joinPool(executor);
}
/**
- * A deserialized serialized queue has same elements
+ * A deserialized serialized queue has same elements
*/
- public void testSerialization() {
+ public void testSerialization() throws Exception {
PriorityBlockingQueue q = populatedQueue(SIZE);
- try {
- ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
- ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
- out.writeObject(q);
- out.close();
-
- ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
- ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
- PriorityBlockingQueue r = (PriorityBlockingQueue)in.readObject();
- assertEquals(q.size(), r.size());
- while (!q.isEmpty())
- assertEquals(q.remove(), r.remove());
- } catch(Exception e){
- unexpectedException();
- }
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(q);
+ out.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ PriorityBlockingQueue r = (PriorityBlockingQueue)in.readObject();
+ assertEquals(q.size(), r.size());
+ while (!q.isEmpty())
+ assertEquals(q.remove(), r.remove());
}
/**
* drainTo(null) throws NPE
- */
+ */
public void testDrainToNull() {
PriorityBlockingQueue q = populatedQueue(SIZE);
try {
q.drainTo(null);
shouldThrow();
- } catch(NullPointerException success) {
- }
+ } catch (NullPointerException success) {}
}
/**
* drainTo(this) throws IAE
- */
+ */
public void testDrainToSelf() {
PriorityBlockingQueue q = populatedQueue(SIZE);
try {
q.drainTo(q);
shouldThrow();
- } catch(IllegalArgumentException success) {
- }
+ } catch (IllegalArgumentException success) {}
}
/**
* drainTo(c) empties queue into another collection c
- */
+ */
public void testDrainTo() {
PriorityBlockingQueue q = populatedQueue(SIZE);
ArrayList l = new ArrayList();
q.drainTo(l);
assertEquals(q.size(), 0);
assertEquals(l.size(), SIZE);
- for (int i = 0; i < SIZE; ++i)
+ for (int i = 0; i < SIZE; ++i)
assertEquals(l.get(i), new Integer(i));
q.add(zero);
q.add(one);
@@ -879,76 +772,69 @@ public class PriorityBlockingQueueTest extends JSR166TestCase {
q.drainTo(l);
assertEquals(q.size(), 0);
assertEquals(l.size(), 2);
- for (int i = 0; i < 2; ++i)
+ for (int i = 0; i < 2; ++i)
assertEquals(l.get(i), new Integer(i));
}
/**
* drainTo empties queue
- */
- public void testDrainToWithActivePut() {
+ */
+ public void testDrainToWithActivePut() throws InterruptedException {
final PriorityBlockingQueue q = populatedQueue(SIZE);
- Thread t = new Thread(new Runnable() {
- public void run() {
- q.put(new Integer(SIZE+1));
- }
- });
- try {
- t.start();
- ArrayList l = new ArrayList();
- q.drainTo(l);
- assertTrue(l.size() >= SIZE);
- for (int i = 0; i < SIZE; ++i)
- assertEquals(l.get(i), new Integer(i));
- t.join();
- assertTrue(q.size() + l.size() >= SIZE);
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ q.put(new Integer(SIZE+1));
+ }});
+
+ t.start();
+ ArrayList l = new ArrayList();
+ q.drainTo(l);
+ assertTrue(l.size() >= SIZE);
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(l.get(i), new Integer(i));
+ t.join();
+ assertTrue(q.size() + l.size() >= SIZE);
}
/**
* drainTo(null, n) throws NPE
- */
+ */
public void testDrainToNullN() {
PriorityBlockingQueue q = populatedQueue(SIZE);
try {
q.drainTo(null, 0);
shouldThrow();
- } catch(NullPointerException success) {
- }
+ } catch (NullPointerException success) {}
}
/**
* drainTo(this, n) throws IAE
- */
+ */
public void testDrainToSelfN() {
PriorityBlockingQueue q = populatedQueue(SIZE);
try {
q.drainTo(q, 0);
shouldThrow();
- } catch(IllegalArgumentException success) {
- }
+ } catch (IllegalArgumentException success) {}
}
/**
* drainTo(c, n) empties first max {n, size} elements of queue into c
- */
+ */
public void testDrainToN() {
PriorityBlockingQueue q = new PriorityBlockingQueue(SIZE*2);
for (int i = 0; i < SIZE + 2; ++i) {
- for(int j = 0; j < SIZE; j++)
+ for (int j = 0; j < SIZE; j++)
assertTrue(q.offer(new Integer(j)));
ArrayList l = new ArrayList();
q.drainTo(l, i);
int k = (i < SIZE)? i : SIZE;
assertEquals(l.size(), k);
assertEquals(q.size(), SIZE-k);
- for (int j = 0; j < k; ++j)
+ for (int j = 0; j < k; ++j)
assertEquals(l.get(j), new Integer(j));
while (q.poll() != null) ;
}
}
-
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/PriorityQueueTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/PriorityQueueTest.java
index 3d3c1be..12ddef4 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/PriorityQueueTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/PriorityQueueTest.java
@@ -2,11 +2,11 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.*;
@@ -18,13 +18,9 @@ public class PriorityQueueTest extends JSR166TestCase {
return new TestSuite(PriorityQueueTest.class);
}
- static class MyReverseComparator implements Comparator {
+ static class MyReverseComparator implements Comparator {
public int compare(Object x, Object y) {
- int i = ((Integer)x).intValue();
- int j = ((Integer)y).intValue();
- if (i < j) return 1;
- if (i > j) return -1;
- return 0;
+ return ((Comparable)y).compareTo(x);
}
}
@@ -35,15 +31,15 @@ public class PriorityQueueTest extends JSR166TestCase {
private PriorityQueue populatedQueue(int n) {
PriorityQueue q = new PriorityQueue(n);
assertTrue(q.isEmpty());
- for(int i = n-1; i >= 0; i-=2)
+ for (int i = n-1; i >= 0; i-=2)
assertTrue(q.offer(new Integer(i)));
- for(int i = (n & 1); i < n; i+=2)
+ for (int i = (n & 1); i < n; i+=2)
assertTrue(q.offer(new Integer(i)));
assertFalse(q.isEmpty());
assertEquals(n, q.size());
return q;
}
-
+
/**
* A new queue has unbounded capacity
*/
@@ -52,14 +48,13 @@ public class PriorityQueueTest extends JSR166TestCase {
}
/**
- * Constructor throws IAE if capacity argument nonpositive
+ * Constructor throws IAE if capacity argument nonpositive
*/
public void testConstructor2() {
try {
PriorityQueue q = new PriorityQueue(0);
shouldThrow();
- }
- catch (IllegalArgumentException success) {}
+ } catch (IllegalArgumentException success) {}
}
/**
@@ -69,8 +64,7 @@ public class PriorityQueueTest extends JSR166TestCase {
try {
PriorityQueue q = new PriorityQueue((Collection)null);
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
@@ -81,8 +75,7 @@ public class PriorityQueueTest extends JSR166TestCase {
Integer[] ints = new Integer[SIZE];
PriorityQueue q = new PriorityQueue(Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
@@ -95,41 +88,34 @@ public class PriorityQueueTest extends JSR166TestCase {
ints[i] = new Integer(i);
PriorityQueue q = new PriorityQueue(Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
* Queue contains all elements of collection used to initialize
*/
public void testConstructor6() {
- try {
- Integer[] ints = new Integer[SIZE];
- for (int i = 0; i < SIZE; ++i)
- ints[i] = new Integer(i);
- PriorityQueue q = new PriorityQueue(Arrays.asList(ints));
- for (int i = 0; i < SIZE; ++i)
- assertEquals(ints[i], q.poll());
- }
- finally {}
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = new Integer(i);
+ PriorityQueue q = new PriorityQueue(Arrays.asList(ints));
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(ints[i], q.poll());
}
/**
* The comparator used in constructor is used
*/
public void testConstructor7() {
- try {
- MyReverseComparator cmp = new MyReverseComparator();
- PriorityQueue q = new PriorityQueue(SIZE, cmp);
- assertEquals(cmp, q.comparator());
- Integer[] ints = new Integer[SIZE];
- for (int i = 0; i < SIZE; ++i)
- ints[i] = new Integer(i);
- q.addAll(Arrays.asList(ints));
- for (int i = SIZE-1; i >= 0; --i)
- assertEquals(ints[i], q.poll());
- }
- finally {}
+ MyReverseComparator cmp = new MyReverseComparator();
+ PriorityQueue q = new PriorityQueue(SIZE, cmp);
+ assertEquals(cmp, q.comparator());
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = new Integer(i);
+ q.addAll(Arrays.asList(ints));
+ for (int i = SIZE-1; i >= 0; --i)
+ assertEquals(ints[i], q.poll());
}
/**
@@ -169,7 +155,7 @@ public class PriorityQueueTest extends JSR166TestCase {
PriorityQueue q = new PriorityQueue(1);
q.offer(null);
shouldThrow();
- } catch (NullPointerException success) { }
+ } catch (NullPointerException success) {}
}
/**
@@ -180,7 +166,7 @@ public class PriorityQueueTest extends JSR166TestCase {
PriorityQueue q = new PriorityQueue(1);
q.add(null);
shouldThrow();
- } catch (NullPointerException success) { }
+ } catch (NullPointerException success) {}
}
/**
@@ -202,8 +188,7 @@ public class PriorityQueueTest extends JSR166TestCase {
q.offer(new Object());
q.offer(new Object());
shouldThrow();
- }
- catch(ClassCastException success) {}
+ } catch (ClassCastException success) {}
}
/**
@@ -225,8 +210,7 @@ public class PriorityQueueTest extends JSR166TestCase {
PriorityQueue q = new PriorityQueue(1);
q.addAll(null);
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
* addAll of a collection with null elements throws NPE
@@ -237,8 +221,7 @@ public class PriorityQueueTest extends JSR166TestCase {
Integer[] ints = new Integer[SIZE];
q.addAll(Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
* addAll of a collection with any null elements throws NPE after
@@ -252,26 +235,22 @@ public class PriorityQueueTest extends JSR166TestCase {
ints[i] = new Integer(i);
q.addAll(Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
* Queue contains all elements of successful addAll
*/
public void testAddAll5() {
- try {
- Integer[] empty = new Integer[0];
- Integer[] ints = new Integer[SIZE];
- for (int i = 0; i < SIZE; ++i)
- ints[i] = new Integer(SIZE-1-i);
- PriorityQueue q = new PriorityQueue(SIZE);
- assertFalse(q.addAll(Arrays.asList(empty)));
- assertTrue(q.addAll(Arrays.asList(ints)));
- for (int i = 0; i < SIZE; ++i)
- assertEquals(new Integer(i), q.poll());
- }
- finally {}
+ Integer[] empty = new Integer[0];
+ Integer[] ints = new Integer[SIZE];
+ for (int i = 0; i < SIZE; ++i)
+ ints[i] = new Integer(SIZE-1-i);
+ PriorityQueue q = new PriorityQueue(SIZE);
+ assertFalse(q.addAll(Arrays.asList(empty)));
+ assertTrue(q.addAll(Arrays.asList(ints)));
+ for (int i = 0; i < SIZE; ++i)
+ assertEquals(new Integer(i), q.poll());
}
/**
@@ -280,7 +259,7 @@ public class PriorityQueueTest extends JSR166TestCase {
public void testPoll() {
PriorityQueue q = populatedQueue(SIZE);
for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.poll()).intValue());
+ assertEquals(i, q.poll());
}
assertNull(q.poll());
}
@@ -291,10 +270,10 @@ public class PriorityQueueTest extends JSR166TestCase {
public void testPeek() {
PriorityQueue q = populatedQueue(SIZE);
for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.peek()).intValue());
- q.poll();
+ assertEquals(i, q.peek());
+ assertEquals(i, q.poll());
assertTrue(q.peek() == null ||
- i != ((Integer)q.peek()).intValue());
+ !q.peek().equals(i));
}
assertNull(q.peek());
}
@@ -305,14 +284,13 @@ public class PriorityQueueTest extends JSR166TestCase {
public void testElement() {
PriorityQueue q = populatedQueue(SIZE);
for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.element()).intValue());
- q.poll();
+ assertEquals(i, q.element());
+ assertEquals(i, q.poll());
}
try {
q.element();
shouldThrow();
- }
- catch (NoSuchElementException success) {}
+ } catch (NoSuchElementException success) {}
}
/**
@@ -321,13 +299,12 @@ public class PriorityQueueTest extends JSR166TestCase {
public void testRemove() {
PriorityQueue q = populatedQueue(SIZE);
for (int i = 0; i < SIZE; ++i) {
- assertEquals(i, ((Integer)q.remove()).intValue());
+ assertEquals(i, q.remove());
}
try {
q.remove();
shouldThrow();
- } catch (NoSuchElementException success){
- }
+ } catch (NoSuchElementException success) {}
}
/**
@@ -344,7 +321,7 @@ public class PriorityQueueTest extends JSR166TestCase {
}
assertTrue(q.isEmpty());
}
-
+
/**
* contains(x) reports true when elements added but not yet removed
*/
@@ -427,7 +404,7 @@ public class PriorityQueueTest extends JSR166TestCase {
PriorityQueue q = populatedQueue(SIZE);
Object[] o = q.toArray();
Arrays.sort(o);
- for(int i = 0; i < o.length; i++)
+ for (int i = 0; i < o.length; i++)
assertEquals(o[i], q.poll());
}
@@ -439,10 +416,10 @@ public class PriorityQueueTest extends JSR166TestCase {
Integer[] ints = new Integer[SIZE];
ints = (Integer[])q.toArray(ints);
Arrays.sort(ints);
- for(int i = 0; i < ints.length; i++)
+ for (int i = 0; i < ints.length; i++)
assertEquals(ints[i], q.poll());
}
-
+
/**
* iterator iterates through all elements
*/
@@ -450,7 +427,7 @@ public class PriorityQueueTest extends JSR166TestCase {
PriorityQueue q = populatedQueue(SIZE);
int i = 0;
Iterator it = q.iterator();
- while(it.hasNext()) {
+ while (it.hasNext()) {
assertTrue(q.contains(it.next()));
++i;
}
@@ -486,27 +463,23 @@ public class PriorityQueueTest extends JSR166TestCase {
for (int i = 0; i < SIZE; ++i) {
assertTrue(s.indexOf(String.valueOf(i)) >= 0);
}
- }
+ }
/**
- * A deserialized serialized queue has same elements
+ * A deserialized serialized queue has same elements
*/
- public void testSerialization() {
+ public void testSerialization() throws Exception {
PriorityQueue q = populatedQueue(SIZE);
- try {
- ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
- ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
- out.writeObject(q);
- out.close();
-
- ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
- ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
- PriorityQueue r = (PriorityQueue)in.readObject();
- assertEquals(q.size(), r.size());
- while (!q.isEmpty())
- assertEquals(q.remove(), r.remove());
- } catch(Exception e){
- unexpectedException();
- }
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(q);
+ out.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ PriorityQueue r = (PriorityQueue)in.readObject();
+ assertEquals(q.size(), r.size());
+ while (!q.isEmpty())
+ assertEquals(q.remove(), r.remove());
}
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/ReentrantLockTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/ReentrantLockTest.java
index 8372251..d6b434e 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/ReentrantLockTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/ReentrantLockTest.java
@@ -2,15 +2,16 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.concurrent.locks.*;
import java.util.concurrent.*;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.*;
import java.io.*;
@@ -22,13 +23,11 @@ public class ReentrantLockTest extends JSR166TestCase {
/**
* A runnable calling lockInterruptibly
*/
- class InterruptibleLockRunnable implements Runnable {
+ class InterruptibleLockRunnable extends CheckedRunnable {
final ReentrantLock lock;
InterruptibleLockRunnable(ReentrantLock l) { lock = l; }
- public void run() {
- try {
- lock.lockInterruptibly();
- } catch(InterruptedException success){}
+ public void realRun() throws InterruptedException {
+ lock.lockInterruptibly();
}
}
@@ -37,14 +36,11 @@ public class ReentrantLockTest extends JSR166TestCase {
* A runnable calling lockInterruptibly that expects to be
* interrupted
*/
- class InterruptedLockRunnable implements Runnable {
+ class InterruptedLockRunnable extends CheckedInterruptedRunnable {
final ReentrantLock lock;
InterruptedLockRunnable(ReentrantLock l) { lock = l; }
- public void run() {
- try {
- lock.lockInterruptibly();
- threadShouldThrow();
- } catch(InterruptedException success){}
+ public void realRun() throws InterruptedException {
+ lock.lockInterruptibly();
}
}
@@ -59,18 +55,15 @@ public class ReentrantLockTest extends JSR166TestCase {
public Collection<Thread> getWaitingThreads(Condition c) {
return super.getWaitingThreads(c);
}
-
-
}
/**
* Constructor sets given fairness
*/
public void testConstructor() {
- ReentrantLock rl = new ReentrantLock();
- assertFalse(rl.isFair());
- ReentrantLock r2 = new ReentrantLock(true);
- assertTrue(r2.isFair());
+ assertFalse(new ReentrantLock().isFair());
+ assertFalse(new ReentrantLock(false).isFair());
+ assertTrue(new ReentrantLock(true).isFair());
}
/**
@@ -81,6 +74,7 @@ public class ReentrantLockTest extends JSR166TestCase {
rl.lock();
assertTrue(rl.isLocked());
rl.unlock();
+ assertFalse(rl.isLocked());
}
/**
@@ -101,8 +95,7 @@ public class ReentrantLockTest extends JSR166TestCase {
try {
rl.unlock();
shouldThrow();
-
- } catch(IllegalMonitorStateException success){}
+ } catch (IllegalMonitorStateException success) {}
}
/**
@@ -119,88 +112,76 @@ public class ReentrantLockTest extends JSR166TestCase {
/**
* hasQueuedThreads reports whether there are waiting threads
*/
- public void testhasQueuedThreads() {
+ public void testhasQueuedThreads() throws InterruptedException {
final ReentrantLock lock = new ReentrantLock();
Thread t1 = new Thread(new InterruptedLockRunnable(lock));
Thread t2 = new Thread(new InterruptibleLockRunnable(lock));
- try {
- assertFalse(lock.hasQueuedThreads());
- lock.lock();
- t1.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(lock.hasQueuedThreads());
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(lock.hasQueuedThreads());
- t1.interrupt();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(lock.hasQueuedThreads());
- lock.unlock();
- Thread.sleep(SHORT_DELAY_MS);
- assertFalse(lock.hasQueuedThreads());
- t1.join();
- t2.join();
- } catch(Exception e){
- unexpectedException();
- }
+ assertFalse(lock.hasQueuedThreads());
+ lock.lock();
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(lock.hasQueuedThreads());
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(lock.hasQueuedThreads());
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(lock.hasQueuedThreads());
+ lock.unlock();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(lock.hasQueuedThreads());
+ t1.join();
+ t2.join();
}
/**
* getQueueLength reports number of waiting threads
*/
- public void testGetQueueLength() {
+ public void testGetQueueLength() throws InterruptedException {
final ReentrantLock lock = new ReentrantLock();
Thread t1 = new Thread(new InterruptedLockRunnable(lock));
Thread t2 = new Thread(new InterruptibleLockRunnable(lock));
- try {
- assertEquals(0, lock.getQueueLength());
- lock.lock();
- t1.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertEquals(1, lock.getQueueLength());
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertEquals(2, lock.getQueueLength());
- t1.interrupt();
- Thread.sleep(SHORT_DELAY_MS);
- assertEquals(1, lock.getQueueLength());
- lock.unlock();
- Thread.sleep(SHORT_DELAY_MS);
- assertEquals(0, lock.getQueueLength());
- t1.join();
- t2.join();
- } catch(Exception e){
- unexpectedException();
- }
+ assertEquals(0, lock.getQueueLength());
+ lock.lock();
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(1, lock.getQueueLength());
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(2, lock.getQueueLength());
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(1, lock.getQueueLength());
+ lock.unlock();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(0, lock.getQueueLength());
+ t1.join();
+ t2.join();
}
/**
* getQueueLength reports number of waiting threads
*/
- public void testGetQueueLength_fair() {
+ public void testGetQueueLength_fair() throws InterruptedException {
final ReentrantLock lock = new ReentrantLock(true);
Thread t1 = new Thread(new InterruptedLockRunnable(lock));
Thread t2 = new Thread(new InterruptibleLockRunnable(lock));
- try {
- assertEquals(0, lock.getQueueLength());
- lock.lock();
- t1.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertEquals(1, lock.getQueueLength());
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertEquals(2, lock.getQueueLength());
- t1.interrupt();
- Thread.sleep(SHORT_DELAY_MS);
- assertEquals(1, lock.getQueueLength());
- lock.unlock();
- Thread.sleep(SHORT_DELAY_MS);
- assertEquals(0, lock.getQueueLength());
- t1.join();
- t2.join();
- } catch(Exception e){
- unexpectedException();
- }
+ assertEquals(0, lock.getQueueLength());
+ lock.lock();
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(1, lock.getQueueLength());
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(2, lock.getQueueLength());
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(1, lock.getQueueLength());
+ lock.unlock();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(0, lock.getQueueLength());
+ t1.join();
+ t2.join();
}
/**
@@ -211,143 +192,117 @@ public class ReentrantLockTest extends JSR166TestCase {
try {
sync.hasQueuedThread(null);
shouldThrow();
- } catch (NullPointerException success) {
- }
+ } catch (NullPointerException success) {}
}
/**
* hasQueuedThread reports whether a thread is queued.
*/
- public void testHasQueuedThread() {
+ public void testHasQueuedThread() throws InterruptedException {
final ReentrantLock sync = new ReentrantLock();
Thread t1 = new Thread(new InterruptedLockRunnable(sync));
Thread t2 = new Thread(new InterruptibleLockRunnable(sync));
- try {
- assertFalse(sync.hasQueuedThread(t1));
- assertFalse(sync.hasQueuedThread(t2));
- sync.lock();
- t1.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(sync.hasQueuedThread(t1));
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(sync.hasQueuedThread(t1));
- assertTrue(sync.hasQueuedThread(t2));
- t1.interrupt();
- Thread.sleep(SHORT_DELAY_MS);
- assertFalse(sync.hasQueuedThread(t1));
- assertTrue(sync.hasQueuedThread(t2));
- sync.unlock();
- Thread.sleep(SHORT_DELAY_MS);
- assertFalse(sync.hasQueuedThread(t1));
- Thread.sleep(SHORT_DELAY_MS);
- assertFalse(sync.hasQueuedThread(t2));
- t1.join();
- t2.join();
- } catch(Exception e){
- unexpectedException();
- }
+ assertFalse(sync.hasQueuedThread(t1));
+ assertFalse(sync.hasQueuedThread(t2));
+ sync.lock();
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.hasQueuedThread(t1));
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.hasQueuedThread(t1));
+ assertTrue(sync.hasQueuedThread(t2));
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(sync.hasQueuedThread(t1));
+ assertTrue(sync.hasQueuedThread(t2));
+ sync.unlock();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(sync.hasQueuedThread(t1));
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(sync.hasQueuedThread(t2));
+ t1.join();
+ t2.join();
}
/**
* getQueuedThreads includes waiting threads
*/
- public void testGetQueuedThreads() {
+ public void testGetQueuedThreads() throws InterruptedException {
final PublicReentrantLock lock = new PublicReentrantLock();
Thread t1 = new Thread(new InterruptedLockRunnable(lock));
Thread t2 = new Thread(new InterruptibleLockRunnable(lock));
- try {
- assertTrue(lock.getQueuedThreads().isEmpty());
- lock.lock();
- assertTrue(lock.getQueuedThreads().isEmpty());
- t1.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(lock.getQueuedThreads().contains(t1));
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(lock.getQueuedThreads().contains(t1));
- assertTrue(lock.getQueuedThreads().contains(t2));
- t1.interrupt();
- Thread.sleep(SHORT_DELAY_MS);
- assertFalse(lock.getQueuedThreads().contains(t1));
- assertTrue(lock.getQueuedThreads().contains(t2));
- lock.unlock();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(lock.getQueuedThreads().isEmpty());
- t1.join();
- t2.join();
- } catch(Exception e){
- unexpectedException();
- }
+ assertTrue(lock.getQueuedThreads().isEmpty());
+ lock.lock();
+ assertTrue(lock.getQueuedThreads().isEmpty());
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(lock.getQueuedThreads().contains(t1));
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(lock.getQueuedThreads().contains(t1));
+ assertTrue(lock.getQueuedThreads().contains(t2));
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(lock.getQueuedThreads().contains(t1));
+ assertTrue(lock.getQueuedThreads().contains(t2));
+ lock.unlock();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(lock.getQueuedThreads().isEmpty());
+ t1.join();
+ t2.join();
}
/**
* timed tryLock is interruptible.
*/
- public void testInterruptedException2() {
+ public void testInterruptedException2() throws InterruptedException {
final ReentrantLock lock = new ReentrantLock();
lock.lock();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- lock.tryLock(MEDIUM_DELAY_MS,TimeUnit.MILLISECONDS);
- threadShouldThrow();
- } catch(InterruptedException success){}
- }
- });
- try {
- t.start();
- t.interrupt();
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.tryLock(MEDIUM_DELAY_MS,MILLISECONDS);
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* TryLock on a locked lock fails
*/
- public void testTryLockWhenLocked() {
+ public void testTryLockWhenLocked() throws InterruptedException {
final ReentrantLock lock = new ReentrantLock();
lock.lock();
- Thread t = new Thread(new Runnable() {
- public void run() {
- threadAssertFalse(lock.tryLock());
- }
- });
- try {
- t.start();
- t.join();
- lock.unlock();
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ threadAssertFalse(lock.tryLock());
+ }});
+
+ t.start();
+ t.join();
+ lock.unlock();
}
/**
* Timed tryLock on a locked lock times out
*/
- public void testTryLock_Timeout() {
+ public void testTryLock_Timeout() throws InterruptedException {
final ReentrantLock lock = new ReentrantLock();
lock.lock();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- threadAssertFalse(lock.tryLock(1, TimeUnit.MILLISECONDS));
- } catch (Exception ex) {
- threadUnexpectedException();
- }
- }
- });
- try {
- t.start();
- t.join();
- lock.unlock();
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ threadAssertFalse(lock.tryLock(1, MILLISECONDS));
+ }});
+
+ t.start();
+ t.join();
+ lock.unlock();
}
/**
@@ -355,13 +310,13 @@ public class ReentrantLockTest extends JSR166TestCase {
*/
public void testGetHoldCount() {
ReentrantLock lock = new ReentrantLock();
- for(int i = 1; i <= SIZE; i++) {
+ for (int i = 1; i <= SIZE; i++) {
lock.lock();
- assertEquals(i,lock.getHoldCount());
+ assertEquals(i, lock.getHoldCount());
}
- for(int i = SIZE; i > 0; i--) {
+ for (int i = SIZE; i > 0; i--) {
lock.unlock();
- assertEquals(i-1,lock.getHoldCount());
+ assertEquals(i-1, lock.getHoldCount());
}
}
@@ -369,92 +324,67 @@ public class ReentrantLockTest extends JSR166TestCase {
/**
* isLocked is true when locked and false when not
*/
- public void testIsLocked() {
+ public void testIsLocked() throws InterruptedException {
final ReentrantLock lock = new ReentrantLock();
lock.lock();
assertTrue(lock.isLocked());
lock.unlock();
assertFalse(lock.isLocked());
- Thread t = new Thread(new Runnable() {
- public void run() {
- lock.lock();
- try {
- Thread.sleep(SMALL_DELAY_MS);
- }
- catch(Exception e) {
- threadUnexpectedException();
- }
- lock.unlock();
- }
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(lock.isLocked());
- t.join();
- assertFalse(lock.isLocked());
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.lock();
+ Thread.sleep(SMALL_DELAY_MS);
+ lock.unlock();
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(lock.isLocked());
+ t.join();
+ assertFalse(lock.isLocked());
}
/**
* lockInterruptibly is interruptible.
*/
- public void testLockInterruptibly1() {
+ public void testLockInterruptibly1() throws InterruptedException {
final ReentrantLock lock = new ReentrantLock();
lock.lock();
Thread t = new Thread(new InterruptedLockRunnable(lock));
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- Thread.sleep(SHORT_DELAY_MS);
- lock.unlock();
- t.join();
- } catch(Exception e){
- unexpectedException();
- }
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.unlock();
+ t.join();
}
/**
* lockInterruptibly succeeds when unlocked, else is interruptible
*/
- public void testLockInterruptibly2() {
+ public void testLockInterruptibly2() throws InterruptedException {
final ReentrantLock lock = new ReentrantLock();
- try {
- lock.lockInterruptibly();
- } catch(Exception e) {
- unexpectedException();
- }
+ lock.lockInterruptibly();
Thread t = new Thread(new InterruptedLockRunnable(lock));
- try {
- t.start();
- t.interrupt();
- assertTrue(lock.isLocked());
- assertTrue(lock.isHeldByCurrentThread());
- t.join();
- } catch(Exception e){
- unexpectedException();
- }
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ assertTrue(lock.isLocked());
+ assertTrue(lock.isHeldByCurrentThread());
+ t.join();
}
/**
* Calling await without holding lock throws IllegalMonitorStateException
*/
- public void testAwait_IllegalMonitor() {
+ public void testAwait_IllegalMonitor() throws InterruptedException {
final ReentrantLock lock = new ReentrantLock();
final Condition c = lock.newCondition();
try {
c.await();
shouldThrow();
- }
- catch (IllegalMonitorStateException success) {
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ } catch (IllegalMonitorStateException success) {}
}
/**
@@ -466,95 +396,64 @@ public class ReentrantLockTest extends JSR166TestCase {
try {
c.signal();
shouldThrow();
- }
- catch (IllegalMonitorStateException success) {
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ } catch (IllegalMonitorStateException success) {}
}
/**
* awaitNanos without a signal times out
*/
- public void testAwaitNanos_Timeout() {
+ public void testAwaitNanos_Timeout() throws InterruptedException {
final ReentrantLock lock = new ReentrantLock();
final Condition c = lock.newCondition();
- try {
- lock.lock();
- long t = c.awaitNanos(100);
- assertTrue(t <= 0);
- lock.unlock();
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ lock.lock();
+ long t = c.awaitNanos(100);
+ assertTrue(t <= 0);
+ lock.unlock();
}
/**
* timed await without a signal times out
*/
- public void testAwait_Timeout() {
+ public void testAwait_Timeout() throws InterruptedException {
final ReentrantLock lock = new ReentrantLock();
final Condition c = lock.newCondition();
- try {
- lock.lock();
- c.await(SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
- lock.unlock();
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ lock.lock();
+ assertFalse(c.await(SHORT_DELAY_MS, MILLISECONDS));
+ lock.unlock();
}
/**
* awaitUntil without a signal times out
*/
- public void testAwaitUntil_Timeout() {
+ public void testAwaitUntil_Timeout() throws InterruptedException {
final ReentrantLock lock = new ReentrantLock();
final Condition c = lock.newCondition();
- try {
- lock.lock();
- java.util.Date d = new java.util.Date();
- c.awaitUntil(new java.util.Date(d.getTime() + 10));
- lock.unlock();
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ lock.lock();
+ java.util.Date d = new java.util.Date();
+ assertFalse(c.awaitUntil(new java.util.Date(d.getTime() + 10)));
+ lock.unlock();
}
/**
* await returns when signalled
*/
- public void testAwait() {
+ public void testAwait() throws InterruptedException {
final ReentrantLock lock = new ReentrantLock();
final Condition c = lock.newCondition();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- lock.lock();
- c.await();
- lock.unlock();
- }
- catch(InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.lock();
+ c.await();
+ lock.unlock();
+ }});
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- lock.lock();
- c.signal();
- lock.unlock();
- t.join(SHORT_DELAY_MS);
- assertFalse(t.isAlive());
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.lock();
+ c.signal();
+ lock.unlock();
+ t.join(SHORT_DELAY_MS);
+ assertFalse(t.isAlive());
}
/**
@@ -565,10 +464,7 @@ public class ReentrantLockTest extends JSR166TestCase {
try {
lock.hasWaiters(null);
shouldThrow();
- } catch (NullPointerException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (NullPointerException success) {}
}
/**
@@ -579,10 +475,7 @@ public class ReentrantLockTest extends JSR166TestCase {
try {
lock.getWaitQueueLength(null);
shouldThrow();
- } catch (NullPointerException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (NullPointerException success) {}
}
@@ -594,10 +487,7 @@ public class ReentrantLockTest extends JSR166TestCase {
try {
lock.getWaitingThreads(null);
shouldThrow();
- } catch (NullPointerException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (NullPointerException success) {}
}
@@ -606,15 +496,12 @@ public class ReentrantLockTest extends JSR166TestCase {
*/
public void testHasWaitersIAE() {
final ReentrantLock lock = new ReentrantLock();
- final Condition c = (lock.newCondition());
+ final Condition c = lock.newCondition();
final ReentrantLock lock2 = new ReentrantLock();
try {
lock2.hasWaiters(c);
shouldThrow();
- } catch (IllegalArgumentException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (IllegalArgumentException success) {}
}
/**
@@ -622,14 +509,11 @@ public class ReentrantLockTest extends JSR166TestCase {
*/
public void testHasWaitersIMSE() {
final ReentrantLock lock = new ReentrantLock();
- final Condition c = (lock.newCondition());
+ final Condition c = lock.newCondition();
try {
lock.hasWaiters(c);
shouldThrow();
- } catch (IllegalMonitorStateException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (IllegalMonitorStateException success) {}
}
@@ -638,15 +522,12 @@ public class ReentrantLockTest extends JSR166TestCase {
*/
public void testGetWaitQueueLengthIAE() {
final ReentrantLock lock = new ReentrantLock();
- final Condition c = (lock.newCondition());
+ final Condition c = lock.newCondition();
final ReentrantLock lock2 = new ReentrantLock();
try {
lock2.getWaitQueueLength(c);
shouldThrow();
- } catch (IllegalArgumentException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (IllegalArgumentException success) {}
}
/**
@@ -654,14 +535,11 @@ public class ReentrantLockTest extends JSR166TestCase {
*/
public void testGetWaitQueueLengthIMSE() {
final ReentrantLock lock = new ReentrantLock();
- final Condition c = (lock.newCondition());
+ final Condition c = lock.newCondition();
try {
lock.getWaitQueueLength(c);
shouldThrow();
- } catch (IllegalMonitorStateException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (IllegalMonitorStateException success) {}
}
@@ -670,15 +548,12 @@ public class ReentrantLockTest extends JSR166TestCase {
*/
public void testGetWaitingThreadsIAE() {
final PublicReentrantLock lock = new PublicReentrantLock();
- final Condition c = (lock.newCondition());
+ final Condition c = lock.newCondition();
final PublicReentrantLock lock2 = new PublicReentrantLock();
try {
lock2.getWaitingThreads(c);
shouldThrow();
- } catch (IllegalArgumentException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (IllegalArgumentException success) {}
}
/**
@@ -686,186 +561,137 @@ public class ReentrantLockTest extends JSR166TestCase {
*/
public void testGetWaitingThreadsIMSE() {
final PublicReentrantLock lock = new PublicReentrantLock();
- final Condition c = (lock.newCondition());
+ final Condition c = lock.newCondition();
try {
lock.getWaitingThreads(c);
shouldThrow();
- } catch (IllegalMonitorStateException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (IllegalMonitorStateException success) {}
}
-
/**
* hasWaiters returns true when a thread is waiting, else false
*/
- public void testHasWaiters() {
+ public void testHasWaiters() throws InterruptedException {
final ReentrantLock lock = new ReentrantLock();
final Condition c = lock.newCondition();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- lock.lock();
- threadAssertFalse(lock.hasWaiters(c));
- threadAssertEquals(0, lock.getWaitQueueLength(c));
- c.await();
- lock.unlock();
- }
- catch(InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.lock();
+ threadAssertFalse(lock.hasWaiters(c));
+ threadAssertEquals(0, lock.getWaitQueueLength(c));
+ c.await();
+ lock.unlock();
+ }});
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- lock.lock();
- assertTrue(lock.hasWaiters(c));
- assertEquals(1, lock.getWaitQueueLength(c));
- c.signal();
- lock.unlock();
- Thread.sleep(SHORT_DELAY_MS);
- lock.lock();
- assertFalse(lock.hasWaiters(c));
- assertEquals(0, lock.getWaitQueueLength(c));
- lock.unlock();
- t.join(SHORT_DELAY_MS);
- assertFalse(t.isAlive());
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.lock();
+ assertTrue(lock.hasWaiters(c));
+ assertEquals(1, lock.getWaitQueueLength(c));
+ c.signal();
+ lock.unlock();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.lock();
+ assertFalse(lock.hasWaiters(c));
+ assertEquals(0, lock.getWaitQueueLength(c));
+ lock.unlock();
+ t.join(SHORT_DELAY_MS);
+ assertFalse(t.isAlive());
}
/**
* getWaitQueueLength returns number of waiting threads
*/
- public void testGetWaitQueueLength() {
+ public void testGetWaitQueueLength() throws InterruptedException {
final ReentrantLock lock = new ReentrantLock();
final Condition c = lock.newCondition();
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- try {
- lock.lock();
- threadAssertFalse(lock.hasWaiters(c));
- threadAssertEquals(0, lock.getWaitQueueLength(c));
- c.await();
- lock.unlock();
- }
- catch(InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
-
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- try {
- lock.lock();
- threadAssertTrue(lock.hasWaiters(c));
- threadAssertEquals(1, lock.getWaitQueueLength(c));
- c.await();
- lock.unlock();
- }
- catch(InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
+ Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.lock();
+ threadAssertFalse(lock.hasWaiters(c));
+ threadAssertEquals(0, lock.getWaitQueueLength(c));
+ c.await();
+ lock.unlock();
+ }});
+
+ Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.lock();
+ threadAssertTrue(lock.hasWaiters(c));
+ threadAssertEquals(1, lock.getWaitQueueLength(c));
+ c.await();
+ lock.unlock();
+ }});
- try {
- t1.start();
- Thread.sleep(SHORT_DELAY_MS);
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- lock.lock();
- assertTrue(lock.hasWaiters(c));
- assertEquals(2, lock.getWaitQueueLength(c));
- c.signalAll();
- lock.unlock();
- Thread.sleep(SHORT_DELAY_MS);
- lock.lock();
- assertFalse(lock.hasWaiters(c));
- assertEquals(0, lock.getWaitQueueLength(c));
- lock.unlock();
- t1.join(SHORT_DELAY_MS);
- t2.join(SHORT_DELAY_MS);
- assertFalse(t1.isAlive());
- assertFalse(t2.isAlive());
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.lock();
+ assertTrue(lock.hasWaiters(c));
+ assertEquals(2, lock.getWaitQueueLength(c));
+ c.signalAll();
+ lock.unlock();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.lock();
+ assertFalse(lock.hasWaiters(c));
+ assertEquals(0, lock.getWaitQueueLength(c));
+ lock.unlock();
+ t1.join(SHORT_DELAY_MS);
+ t2.join(SHORT_DELAY_MS);
+ assertFalse(t1.isAlive());
+ assertFalse(t2.isAlive());
}
/**
* getWaitingThreads returns only and all waiting threads
*/
- public void testGetWaitingThreads() {
+ public void testGetWaitingThreads() throws InterruptedException {
final PublicReentrantLock lock = new PublicReentrantLock();
final Condition c = lock.newCondition();
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- try {
- lock.lock();
- threadAssertTrue(lock.getWaitingThreads(c).isEmpty());
- c.await();
- lock.unlock();
- }
- catch(InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
-
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- try {
- lock.lock();
- threadAssertFalse(lock.getWaitingThreads(c).isEmpty());
- c.await();
- lock.unlock();
- }
- catch(InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
+ Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.lock();
+ threadAssertTrue(lock.getWaitingThreads(c).isEmpty());
+ c.await();
+ lock.unlock();
+ }});
- try {
- lock.lock();
- assertTrue(lock.getWaitingThreads(c).isEmpty());
- lock.unlock();
- t1.start();
- Thread.sleep(SHORT_DELAY_MS);
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- lock.lock();
- assertTrue(lock.hasWaiters(c));
- assertTrue(lock.getWaitingThreads(c).contains(t1));
- assertTrue(lock.getWaitingThreads(c).contains(t2));
- c.signalAll();
- lock.unlock();
- Thread.sleep(SHORT_DELAY_MS);
- lock.lock();
- assertFalse(lock.hasWaiters(c));
- assertTrue(lock.getWaitingThreads(c).isEmpty());
- lock.unlock();
- t1.join(SHORT_DELAY_MS);
- t2.join(SHORT_DELAY_MS);
- assertFalse(t1.isAlive());
- assertFalse(t2.isAlive());
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.lock();
+ threadAssertFalse(lock.getWaitingThreads(c).isEmpty());
+ c.await();
+ lock.unlock();
+ }});
+
+ lock.lock();
+ assertTrue(lock.getWaitingThreads(c).isEmpty());
+ lock.unlock();
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.lock();
+ assertTrue(lock.hasWaiters(c));
+ assertTrue(lock.getWaitingThreads(c).contains(t1));
+ assertTrue(lock.getWaitingThreads(c).contains(t2));
+ c.signalAll();
+ lock.unlock();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.lock();
+ assertFalse(lock.hasWaiters(c));
+ assertTrue(lock.getWaitingThreads(c).isEmpty());
+ lock.unlock();
+ t1.join(SHORT_DELAY_MS);
+ t2.join(SHORT_DELAY_MS);
+ assertFalse(t1.isAlive());
+ assertFalse(t2.isAlive());
}
/** A helper class for uninterruptible wait tests */
- class UninterruptableThread extends Thread {
+ class UninterruptibleThread extends Thread {
private ReentrantLock lock;
private Condition c;
@@ -873,7 +699,7 @@ public class ReentrantLockTest extends JSR166TestCase {
public volatile boolean interrupted = false;
public volatile boolean lockStarted = false;
- public UninterruptableThread(ReentrantLock lock, Condition c) {
+ public UninterruptibleThread(ReentrantLock lock, Condition c) {
this.lock = lock;
this.c = c;
}
@@ -894,256 +720,180 @@ public class ReentrantLockTest extends JSR166TestCase {
/**
* awaitUninterruptibly doesn't abort on interrupt
*/
- public void testAwaitUninterruptibly() {
+ public void testAwaitUninterruptibly() throws InterruptedException {
final ReentrantLock lock = new ReentrantLock();
final Condition c = lock.newCondition();
- UninterruptableThread thread = new UninterruptableThread(lock, c);
+ UninterruptibleThread thread = new UninterruptibleThread(lock, c);
- try {
- thread.start();
+ thread.start();
- while (!thread.lockStarted) {
- Thread.sleep(100);
- }
-
- lock.lock();
- try {
- thread.interrupt();
- thread.canAwake = true;
- c.signal();
- } finally {
- lock.unlock();
- }
+ while (!thread.lockStarted) {
+ Thread.sleep(100);
+ }
- thread.join();
- assertTrue(thread.interrupted);
- assertFalse(thread.isAlive());
- } catch (Exception ex) {
- unexpectedException();
+ lock.lock();
+ try {
+ thread.interrupt();
+ thread.canAwake = true;
+ c.signal();
+ } finally {
+ lock.unlock();
}
+
+ thread.join();
+ assertTrue(thread.interrupted);
+ assertFalse(thread.isAlive());
}
/**
* await is interruptible
*/
- public void testAwait_Interrupt() {
+ public void testAwait_Interrupt() throws InterruptedException {
final ReentrantLock lock = new ReentrantLock();
final Condition c = lock.newCondition();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- lock.lock();
- c.await();
- lock.unlock();
- threadShouldThrow();
- }
- catch(InterruptedException success) {
- }
- }
- });
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.lock();
+ c.await();
+ }});
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join(SHORT_DELAY_MS);
- assertFalse(t.isAlive());
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join(SHORT_DELAY_MS);
+ assertFalse(t.isAlive());
}
/**
* awaitNanos is interruptible
*/
- public void testAwaitNanos_Interrupt() {
+ public void testAwaitNanos_Interrupt() throws InterruptedException {
final ReentrantLock lock = new ReentrantLock();
final Condition c = lock.newCondition();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- lock.lock();
- c.awaitNanos(1000 * 1000 * 1000); // 1 sec
- lock.unlock();
- threadShouldThrow();
- }
- catch(InterruptedException success) {
- }
- }
- });
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.lock();
+ c.awaitNanos(MILLISECONDS.toNanos(LONG_DELAY_MS));
+ }});
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join(SHORT_DELAY_MS);
- assertFalse(t.isAlive());
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join(SHORT_DELAY_MS);
+ assertFalse(t.isAlive());
}
/**
* awaitUntil is interruptible
*/
- public void testAwaitUntil_Interrupt() {
+ public void testAwaitUntil_Interrupt() throws InterruptedException {
final ReentrantLock lock = new ReentrantLock();
final Condition c = lock.newCondition();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- lock.lock();
- java.util.Date d = new java.util.Date();
- c.awaitUntil(new java.util.Date(d.getTime() + 10000));
- lock.unlock();
- threadShouldThrow();
- }
- catch(InterruptedException success) {
- }
- }
- });
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.lock();
+ java.util.Date d = new java.util.Date();
+ c.awaitUntil(new java.util.Date(d.getTime() + 10000));
+ }});
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join(SHORT_DELAY_MS);
- assertFalse(t.isAlive());
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join(SHORT_DELAY_MS);
+ assertFalse(t.isAlive());
}
/**
* signalAll wakes up all threads
*/
- public void testSignalAll() {
+ public void testSignalAll() throws InterruptedException {
final ReentrantLock lock = new ReentrantLock();
final Condition c = lock.newCondition();
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- try {
- lock.lock();
- c.await();
- lock.unlock();
- }
- catch(InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
-
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- try {
- lock.lock();
- c.await();
- lock.unlock();
- }
- catch(InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
+ Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.lock();
+ c.await();
+ lock.unlock();
+ }});
- try {
- t1.start();
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- lock.lock();
- c.signalAll();
- lock.unlock();
- t1.join(SHORT_DELAY_MS);
- t2.join(SHORT_DELAY_MS);
- assertFalse(t1.isAlive());
- assertFalse(t2.isAlive());
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.lock();
+ c.await();
+ lock.unlock();
+ }});
+
+ t1.start();
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.lock();
+ c.signalAll();
+ lock.unlock();
+ t1.join(SHORT_DELAY_MS);
+ t2.join(SHORT_DELAY_MS);
+ assertFalse(t1.isAlive());
+ assertFalse(t2.isAlive());
}
/**
* await after multiple reentrant locking preserves lock count
*/
- public void testAwaitLockCount() {
- final ReentrantLock lock = new ReentrantLock();
+ public void testAwaitLockCount() throws InterruptedException {
+ final ReentrantLock lock = new ReentrantLock();
final Condition c = lock.newCondition();
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- try {
- lock.lock();
- threadAssertEquals(1, lock.getHoldCount());
- c.await();
- threadAssertEquals(1, lock.getHoldCount());
- lock.unlock();
- }
- catch(InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
-
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- try {
- lock.lock();
- lock.lock();
- threadAssertEquals(2, lock.getHoldCount());
- c.await();
- threadAssertEquals(2, lock.getHoldCount());
- lock.unlock();
- lock.unlock();
- }
- catch(InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
+ Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.lock();
+ threadAssertEquals(1, lock.getHoldCount());
+ c.await();
+ threadAssertEquals(1, lock.getHoldCount());
+ lock.unlock();
+ }});
+
+ Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.lock();
+ lock.lock();
+ threadAssertEquals(2, lock.getHoldCount());
+ c.await();
+ threadAssertEquals(2, lock.getHoldCount());
+ lock.unlock();
+ lock.unlock();
+ }});
- try {
- t1.start();
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- lock.lock();
- c.signalAll();
- lock.unlock();
- t1.join(SHORT_DELAY_MS);
- t2.join(SHORT_DELAY_MS);
- assertFalse(t1.isAlive());
- assertFalse(t2.isAlive());
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ t1.start();
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.lock();
+ c.signalAll();
+ lock.unlock();
+ t1.join(SHORT_DELAY_MS);
+ t2.join(SHORT_DELAY_MS);
+ assertFalse(t1.isAlive());
+ assertFalse(t2.isAlive());
}
/**
* A serialized lock deserializes as unlocked
*/
- public void testSerialization() {
+ public void testSerialization() throws Exception {
ReentrantLock l = new ReentrantLock();
l.lock();
l.unlock();
- try {
- ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
- ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
- out.writeObject(l);
- out.close();
-
- ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
- ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
- ReentrantLock r = (ReentrantLock) in.readObject();
- r.lock();
- r.unlock();
- } catch(Exception e){
- e.printStackTrace();
- unexpectedException();
- }
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out =
+ new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(l);
+ out.close();
+
+ ByteArrayInputStream bin =
+ new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in =
+ new ObjectInputStream(new BufferedInputStream(bin));
+ ReentrantLock r = (ReentrantLock) in.readObject();
+ r.lock();
+ r.unlock();
}
/**
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/ReentrantReadWriteLockTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/ReentrantReadWriteLockTest.java
index 4191a13..eb20255 100644
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/ReentrantReadWriteLockTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/ReentrantReadWriteLockTest.java
@@ -2,15 +2,16 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.concurrent.locks.*;
import java.util.concurrent.*;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.io.*;
import java.util.*;
@@ -22,13 +23,11 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
/**
* A runnable calling lockInterruptibly
*/
- class InterruptibleLockRunnable implements Runnable {
+ class InterruptibleLockRunnable extends CheckedRunnable {
final ReentrantReadWriteLock lock;
InterruptibleLockRunnable(ReentrantReadWriteLock l) { lock = l; }
- public void run() {
- try {
- lock.writeLock().lockInterruptibly();
- } catch(InterruptedException success){}
+ public void realRun() throws InterruptedException {
+ lock.writeLock().lockInterruptibly();
}
}
@@ -37,14 +36,11 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
* A runnable calling lockInterruptibly that expects to be
* interrupted
*/
- class InterruptedLockRunnable implements Runnable {
+ class InterruptedLockRunnable extends CheckedInterruptedRunnable {
final ReentrantReadWriteLock lock;
InterruptedLockRunnable(ReentrantReadWriteLock l) { lock = l; }
- public void run() {
- try {
- lock.writeLock().lockInterruptibly();
- threadShouldThrow();
- } catch(InterruptedException success){}
+ public void realRun() throws InterruptedException {
+ lock.writeLock().lockInterruptibly();
}
}
@@ -73,6 +69,10 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
assertTrue(r2.isFair());
assertFalse(r2.isWriteLocked());
assertEquals(0, r2.getReadLockCount());
+ ReentrantReadWriteLock r3 = new ReentrantReadWriteLock(false);
+ assertFalse(r3.isFair());
+ assertFalse(r3.isWriteLocked());
+ assertEquals(0, r3.getReadLockCount());
}
/**
@@ -83,10 +83,12 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
rl.writeLock().lock();
assertTrue(rl.isWriteLocked());
assertTrue(rl.isWriteLockedByCurrentThread());
+ assertTrue(rl.writeLock().isHeldByCurrentThread());
assertEquals(0, rl.getReadLockCount());
rl.writeLock().unlock();
assertFalse(rl.isWriteLocked());
assertFalse(rl.isWriteLockedByCurrentThread());
+ assertFalse(rl.writeLock().isHeldByCurrentThread());
assertEquals(0, rl.getReadLockCount());
rl.readLock().lock();
assertFalse(rl.isWriteLocked());
@@ -107,10 +109,12 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
rl.writeLock().lock();
assertTrue(rl.isWriteLocked());
assertTrue(rl.isWriteLockedByCurrentThread());
+ assertTrue(rl.writeLock().isHeldByCurrentThread());
assertEquals(0, rl.getReadLockCount());
rl.writeLock().unlock();
assertFalse(rl.isWriteLocked());
assertFalse(rl.isWriteLockedByCurrentThread());
+ assertFalse(rl.writeLock().isHeldByCurrentThread());
assertEquals(0, rl.getReadLockCount());
rl.readLock().lock();
assertFalse(rl.isWriteLocked());
@@ -126,15 +130,45 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
* getWriteHoldCount returns number of recursive holds
*/
public void testGetWriteHoldCount() {
- ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
- for(int i = 1; i <= SIZE; i++) {
- lock.writeLock().lock();
- assertEquals(i,lock.getWriteHoldCount());
- }
- for(int i = SIZE; i > 0; i--) {
- lock.writeLock().unlock();
- assertEquals(i-1,lock.getWriteHoldCount());
- }
+ ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+ for (int i = 1; i <= SIZE; i++) {
+ lock.writeLock().lock();
+ assertEquals(i,lock.getWriteHoldCount());
+ }
+ for (int i = SIZE; i > 0; i--) {
+ lock.writeLock().unlock();
+ assertEquals(i-1,lock.getWriteHoldCount());
+ }
+ }
+
+ /**
+ * WriteLock.getHoldCount returns number of recursive holds
+ */
+ public void testGetHoldCount() {
+ ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+ for (int i = 1; i <= SIZE; i++) {
+ lock.writeLock().lock();
+ assertEquals(i,lock.writeLock().getHoldCount());
+ }
+ for (int i = SIZE; i > 0; i--) {
+ lock.writeLock().unlock();
+ assertEquals(i-1,lock.writeLock().getHoldCount());
+ }
+ }
+
+ /**
+ * getReadHoldCount returns number of recursive holds
+ */
+ public void testGetReadHoldCount() {
+ ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+ for (int i = 1; i <= SIZE; i++) {
+ lock.readLock().lock();
+ assertEquals(i,lock.getReadHoldCount());
+ }
+ for (int i = SIZE; i > 0; i--) {
+ lock.readLock().unlock();
+ assertEquals(i-1,lock.getReadHoldCount());
+ }
}
@@ -146,245 +180,196 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
try {
rl.writeLock().unlock();
shouldThrow();
- } catch(IllegalMonitorStateException success){}
+ } catch (IllegalMonitorStateException success) {}
}
/**
* write-lockInterruptibly is interruptible
*/
- public void testWriteLockInterruptibly_Interrupted() {
+ public void testWriteLockInterruptibly_Interrupted() throws Exception {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- lock.writeLock().lockInterruptibly();
- lock.writeLock().unlock();
- lock.writeLock().lockInterruptibly();
- lock.writeLock().unlock();
- } catch(InterruptedException success){}
- }
- });
- try {
- lock.writeLock().lock();
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- Thread.sleep(SHORT_DELAY_MS);
- lock.writeLock().unlock();
- t.join();
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.writeLock().lockInterruptibly();
+ lock.writeLock().unlock();
+ lock.writeLock().lockInterruptibly();
+ lock.writeLock().unlock();
+ }});
+
+ lock.writeLock().lock();
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.writeLock().unlock();
+ t.join();
}
/**
* timed write-tryLock is interruptible
*/
- public void testWriteTryLock_Interrupted() {
+ public void testWriteTryLock_Interrupted() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
lock.writeLock().lock();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- lock.writeLock().tryLock(1000,TimeUnit.MILLISECONDS);
- } catch(InterruptedException success){}
- }
- });
- try {
- t.start();
- t.interrupt();
- lock.writeLock().unlock();
- t.join();
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.writeLock().tryLock(SMALL_DELAY_MS, MILLISECONDS);
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ lock.writeLock().unlock();
+ t.join();
}
/**
* read-lockInterruptibly is interruptible
*/
- public void testReadLockInterruptibly_Interrupted() {
+ public void testReadLockInterruptibly_Interrupted() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
lock.writeLock().lock();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- lock.readLock().lockInterruptibly();
- } catch(InterruptedException success){}
- }
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- Thread.sleep(SHORT_DELAY_MS);
- lock.writeLock().unlock();
- t.join();
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.readLock().lockInterruptibly();
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.writeLock().unlock();
+ t.join();
}
/**
* timed read-tryLock is interruptible
*/
- public void testReadTryLock_Interrupted() {
+ public void testReadTryLock_Interrupted() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
lock.writeLock().lock();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- lock.readLock().tryLock(1000,TimeUnit.MILLISECONDS);
- threadShouldThrow();
- } catch(InterruptedException success){}
- }
- });
- try {
- t.start();
- t.interrupt();
- t.join();
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.readLock().tryLock(LONG_DELAY_MS, MILLISECONDS);
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* write-tryLock fails if locked
*/
- public void testWriteTryLockWhenLocked() {
+ public void testWriteTryLockWhenLocked() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
lock.writeLock().lock();
- Thread t = new Thread(new Runnable() {
- public void run() {
- threadAssertFalse(lock.writeLock().tryLock());
- }
- });
- try {
- t.start();
- t.join();
- lock.writeLock().unlock();
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ threadAssertFalse(lock.writeLock().tryLock());
+ }});
+
+ t.start();
+ t.join();
+ lock.writeLock().unlock();
}
/**
* read-tryLock fails if locked
*/
- public void testReadTryLockWhenLocked() {
+ public void testReadTryLockWhenLocked() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
lock.writeLock().lock();
- Thread t = new Thread(new Runnable() {
- public void run() {
- threadAssertFalse(lock.readLock().tryLock());
- }
- });
- try {
- t.start();
- t.join();
- lock.writeLock().unlock();
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ threadAssertFalse(lock.readLock().tryLock());
+ }});
+
+ t.start();
+ t.join();
+ lock.writeLock().unlock();
}
/**
* Multiple threads can hold a read lock when not write-locked
*/
- public void testMultipleReadLocks() {
+ public void testMultipleReadLocks() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
lock.readLock().lock();
- Thread t = new Thread(new Runnable() {
- public void run() {
- threadAssertTrue(lock.readLock().tryLock());
- lock.readLock().unlock();
- }
- });
- try {
- t.start();
- t.join();
- lock.readLock().unlock();
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ threadAssertTrue(lock.readLock().tryLock());
+ lock.readLock().unlock();
+ }});
+
+ t.start();
+ t.join();
+ lock.readLock().unlock();
}
/**
* A writelock succeeds after reading threads unlock
*/
- public void testWriteAfterMultipleReadLocks() {
+ public void testWriteAfterMultipleReadLocks() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
lock.readLock().lock();
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- lock.readLock().lock();
- lock.readLock().unlock();
- }
- });
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- lock.writeLock().lock();
- lock.writeLock().unlock();
- }
- });
-
- try {
- t1.start();
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- lock.readLock().unlock();
- t1.join(MEDIUM_DELAY_MS);
- t2.join(MEDIUM_DELAY_MS);
- assertTrue(!t1.isAlive());
- assertTrue(!t2.isAlive());
+ Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ lock.readLock().lock();
+ lock.readLock().unlock();
+ }});
+ Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ lock.writeLock().lock();
+ lock.writeLock().unlock();
+ }});
- } catch(Exception e){
- unexpectedException();
- }
+ t1.start();
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.readLock().unlock();
+ t1.join(MEDIUM_DELAY_MS);
+ t2.join(MEDIUM_DELAY_MS);
+ assertTrue(!t1.isAlive());
+ assertTrue(!t2.isAlive());
}
/**
* Readlocks succeed after a writing thread unlocks
*/
- public void testReadAfterWriteLock() {
+ public void testReadAfterWriteLock() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
lock.writeLock().lock();
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- lock.readLock().lock();
- lock.readLock().unlock();
- }
- });
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- lock.readLock().lock();
- lock.readLock().unlock();
- }
- });
-
- try {
- t1.start();
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- lock.writeLock().unlock();
- t1.join(MEDIUM_DELAY_MS);
- t2.join(MEDIUM_DELAY_MS);
- assertTrue(!t1.isAlive());
- assertTrue(!t2.isAlive());
-
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ lock.readLock().lock();
+ lock.readLock().unlock();
+ }});
+ Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ lock.readLock().lock();
+ lock.readLock().unlock();
+ }});
+
+ t1.start();
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.writeLock().unlock();
+ t1.join(MEDIUM_DELAY_MS);
+ t2.join(MEDIUM_DELAY_MS);
+ assertTrue(!t1.isAlive());
+ assertTrue(!t2.isAlive());
}
/**
* Read trylock succeeds if write locked by current thread
*/
public void testReadHoldingWriteLock() {
- final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
- lock.writeLock().lock();
+ final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+ lock.writeLock().lock();
assertTrue(lock.readLock().tryLock());
lock.readLock().unlock();
lock.writeLock().unlock();
@@ -394,78 +379,64 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
* Read lock succeeds if write locked by current thread even if
* other threads are waiting for readlock
*/
- public void testReadHoldingWriteLock2() {
- final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
- lock.writeLock().lock();
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- lock.readLock().lock();
- lock.readLock().unlock();
- }
- });
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- lock.readLock().lock();
- lock.readLock().unlock();
- }
- });
-
- try {
- t1.start();
- t2.start();
- lock.readLock().lock();
- lock.readLock().unlock();
- Thread.sleep(SHORT_DELAY_MS);
- lock.readLock().lock();
- lock.readLock().unlock();
- lock.writeLock().unlock();
- t1.join(MEDIUM_DELAY_MS);
- t2.join(MEDIUM_DELAY_MS);
- assertTrue(!t1.isAlive());
- assertTrue(!t2.isAlive());
-
- } catch(Exception e){
- unexpectedException();
- }
+ public void testReadHoldingWriteLock2() throws InterruptedException {
+ final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+ lock.writeLock().lock();
+ Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ lock.readLock().lock();
+ lock.readLock().unlock();
+ }});
+ Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ lock.readLock().lock();
+ lock.readLock().unlock();
+ }});
+
+ t1.start();
+ t2.start();
+ lock.readLock().lock();
+ lock.readLock().unlock();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.readLock().lock();
+ lock.readLock().unlock();
+ lock.writeLock().unlock();
+ t1.join(MEDIUM_DELAY_MS);
+ t2.join(MEDIUM_DELAY_MS);
+ assertTrue(!t1.isAlive());
+ assertTrue(!t2.isAlive());
}
/**
* Read lock succeeds if write locked by current thread even if
* other threads are waiting for writelock
*/
- public void testReadHoldingWriteLock3() {
- final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
- lock.writeLock().lock();
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- lock.writeLock().lock();
- lock.writeLock().unlock();
- }
- });
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- lock.writeLock().lock();
- lock.writeLock().unlock();
- }
- });
-
- try {
- t1.start();
- t2.start();
- lock.readLock().lock();
- lock.readLock().unlock();
- Thread.sleep(SHORT_DELAY_MS);
- lock.readLock().lock();
- lock.readLock().unlock();
- lock.writeLock().unlock();
- t1.join(MEDIUM_DELAY_MS);
- t2.join(MEDIUM_DELAY_MS);
- assertTrue(!t1.isAlive());
- assertTrue(!t2.isAlive());
+ public void testReadHoldingWriteLock3() throws InterruptedException {
+ final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+ lock.writeLock().lock();
+ Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ lock.writeLock().lock();
+ lock.writeLock().unlock();
+ }});
+ Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ lock.writeLock().lock();
+ lock.writeLock().unlock();
+ }});
- } catch(Exception e){
- unexpectedException();
- }
+ t1.start();
+ t2.start();
+ lock.readLock().lock();
+ lock.readLock().unlock();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.readLock().lock();
+ lock.readLock().unlock();
+ lock.writeLock().unlock();
+ t1.join(MEDIUM_DELAY_MS);
+ t2.join(MEDIUM_DELAY_MS);
+ assertTrue(!t1.isAlive());
+ assertTrue(!t2.isAlive());
}
@@ -473,39 +444,32 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
* Write lock succeeds if write locked by current thread even if
* other threads are waiting for writelock
*/
- public void testWriteHoldingWriteLock4() {
- final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
- lock.writeLock().lock();
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- lock.writeLock().lock();
- lock.writeLock().unlock();
- }
- });
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- lock.writeLock().lock();
- lock.writeLock().unlock();
- }
- });
-
- try {
- t1.start();
- t2.start();
- lock.writeLock().lock();
- lock.writeLock().unlock();
- Thread.sleep(SHORT_DELAY_MS);
- lock.writeLock().lock();
- lock.writeLock().unlock();
- lock.writeLock().unlock();
- t1.join(MEDIUM_DELAY_MS);
- t2.join(MEDIUM_DELAY_MS);
- assertTrue(!t1.isAlive());
- assertTrue(!t2.isAlive());
+ public void testWriteHoldingWriteLock4() throws InterruptedException {
+ final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+ lock.writeLock().lock();
+ Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ lock.writeLock().lock();
+ lock.writeLock().unlock();
+ }});
+ Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ lock.writeLock().lock();
+ lock.writeLock().unlock();
+ }});
- } catch(Exception e){
- unexpectedException();
- }
+ t1.start();
+ t2.start();
+ lock.writeLock().lock();
+ lock.writeLock().unlock();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.writeLock().lock();
+ lock.writeLock().unlock();
+ lock.writeLock().unlock();
+ t1.join(MEDIUM_DELAY_MS);
+ t2.join(MEDIUM_DELAY_MS);
+ assertTrue(!t1.isAlive());
+ assertTrue(!t2.isAlive());
}
@@ -513,8 +477,8 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
* Fair Read trylock succeeds if write locked by current thread
*/
public void testReadHoldingWriteLockFair() {
- final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
- lock.writeLock().lock();
+ final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
+ lock.writeLock().lock();
assertTrue(lock.readLock().tryLock());
lock.readLock().unlock();
lock.writeLock().unlock();
@@ -524,39 +488,32 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
* Fair Read lock succeeds if write locked by current thread even if
* other threads are waiting for readlock
*/
- public void testReadHoldingWriteLockFair2() {
- final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
- lock.writeLock().lock();
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- lock.readLock().lock();
- lock.readLock().unlock();
- }
- });
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- lock.readLock().lock();
- lock.readLock().unlock();
- }
- });
-
- try {
- t1.start();
- t2.start();
- lock.readLock().lock();
- lock.readLock().unlock();
- Thread.sleep(SHORT_DELAY_MS);
- lock.readLock().lock();
- lock.readLock().unlock();
- lock.writeLock().unlock();
- t1.join(MEDIUM_DELAY_MS);
- t2.join(MEDIUM_DELAY_MS);
- assertTrue(!t1.isAlive());
- assertTrue(!t2.isAlive());
-
- } catch(Exception e){
- unexpectedException();
- }
+ public void testReadHoldingWriteLockFair2() throws InterruptedException {
+ final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
+ lock.writeLock().lock();
+ Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ lock.readLock().lock();
+ lock.readLock().unlock();
+ }});
+ Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ lock.readLock().lock();
+ lock.readLock().unlock();
+ }});
+
+ t1.start();
+ t2.start();
+ lock.readLock().lock();
+ lock.readLock().unlock();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.readLock().lock();
+ lock.readLock().unlock();
+ lock.writeLock().unlock();
+ t1.join(MEDIUM_DELAY_MS);
+ t2.join(MEDIUM_DELAY_MS);
+ assertTrue(!t1.isAlive());
+ assertTrue(!t2.isAlive());
}
@@ -564,39 +521,32 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
* Fair Read lock succeeds if write locked by current thread even if
* other threads are waiting for writelock
*/
- public void testReadHoldingWriteLockFair3() {
- final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
- lock.writeLock().lock();
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- lock.writeLock().lock();
- lock.writeLock().unlock();
- }
- });
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- lock.writeLock().lock();
- lock.writeLock().unlock();
- }
- });
-
- try {
- t1.start();
- t2.start();
- lock.readLock().lock();
- lock.readLock().unlock();
- Thread.sleep(SHORT_DELAY_MS);
- lock.readLock().lock();
- lock.readLock().unlock();
- lock.writeLock().unlock();
- t1.join(MEDIUM_DELAY_MS);
- t2.join(MEDIUM_DELAY_MS);
- assertTrue(!t1.isAlive());
- assertTrue(!t2.isAlive());
+ public void testReadHoldingWriteLockFair3() throws InterruptedException {
+ final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
+ lock.writeLock().lock();
+ Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ lock.writeLock().lock();
+ lock.writeLock().unlock();
+ }});
+ Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ lock.writeLock().lock();
+ lock.writeLock().unlock();
+ }});
- } catch(Exception e){
- unexpectedException();
- }
+ t1.start();
+ t2.start();
+ lock.readLock().lock();
+ lock.readLock().unlock();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.readLock().lock();
+ lock.readLock().unlock();
+ lock.writeLock().unlock();
+ t1.join(MEDIUM_DELAY_MS);
+ t2.join(MEDIUM_DELAY_MS);
+ assertTrue(!t1.isAlive());
+ assertTrue(!t2.isAlive());
}
@@ -604,64 +554,53 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
* Fair Write lock succeeds if write locked by current thread even if
* other threads are waiting for writelock
*/
- public void testWriteHoldingWriteLockFair4() {
- final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
- lock.writeLock().lock();
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- lock.writeLock().lock();
- lock.writeLock().unlock();
- }
- });
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- lock.writeLock().lock();
- lock.writeLock().unlock();
- }
- });
-
- try {
- t1.start();
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(lock.isWriteLockedByCurrentThread());
- assertTrue(lock.getWriteHoldCount() == 1);
- lock.writeLock().lock();
- assertTrue(lock.getWriteHoldCount() == 2);
- lock.writeLock().unlock();
- lock.writeLock().lock();
- lock.writeLock().unlock();
- lock.writeLock().unlock();
- t1.join(MEDIUM_DELAY_MS);
- t2.join(MEDIUM_DELAY_MS);
- assertTrue(!t1.isAlive());
- assertTrue(!t2.isAlive());
+ public void testWriteHoldingWriteLockFair4() throws InterruptedException {
+ final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
+ lock.writeLock().lock();
+ Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ lock.writeLock().lock();
+ lock.writeLock().unlock();
+ }});
+ Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ lock.writeLock().lock();
+ lock.writeLock().unlock();
+ }});
- } catch(Exception e){
- unexpectedException();
- }
+ t1.start();
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(lock.isWriteLockedByCurrentThread());
+ assertTrue(lock.getWriteHoldCount() == 1);
+ lock.writeLock().lock();
+ assertTrue(lock.getWriteHoldCount() == 2);
+ lock.writeLock().unlock();
+ lock.writeLock().lock();
+ lock.writeLock().unlock();
+ lock.writeLock().unlock();
+ t1.join(MEDIUM_DELAY_MS);
+ t2.join(MEDIUM_DELAY_MS);
+ assertTrue(!t1.isAlive());
+ assertTrue(!t2.isAlive());
}
/**
* Read tryLock succeeds if readlocked but not writelocked
*/
- public void testTryLockWhenReadLocked() {
+ public void testTryLockWhenReadLocked() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
lock.readLock().lock();
- Thread t = new Thread(new Runnable() {
- public void run() {
- threadAssertTrue(lock.readLock().tryLock());
- lock.readLock().unlock();
- }
- });
- try {
- t.start();
- t.join();
- lock.readLock().unlock();
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ threadAssertTrue(lock.readLock().tryLock());
+ lock.readLock().unlock();
+ }});
+
+ t.start();
+ t.join();
+ lock.readLock().unlock();
}
@@ -669,43 +608,35 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
/**
* write tryLock fails when readlocked
*/
- public void testWriteTryLockWhenReadLocked() {
+ public void testWriteTryLockWhenReadLocked() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
lock.readLock().lock();
- Thread t = new Thread(new Runnable() {
- public void run() {
- threadAssertFalse(lock.writeLock().tryLock());
- }
- });
- try {
- t.start();
- t.join();
- lock.readLock().unlock();
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ threadAssertFalse(lock.writeLock().tryLock());
+ }});
+
+ t.start();
+ t.join();
+ lock.readLock().unlock();
}
/**
* Fair Read tryLock succeeds if readlocked but not writelocked
*/
- public void testTryLockWhenReadLockedFair() {
- final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
- lock.readLock().lock();
- Thread t = new Thread(new Runnable() {
- public void run() {
- threadAssertTrue(lock.readLock().tryLock());
- lock.readLock().unlock();
- }
- });
- try {
- t.start();
- t.join();
- lock.readLock().unlock();
- } catch(Exception e){
- unexpectedException();
- }
+ public void testTryLockWhenReadLockedFair() throws InterruptedException {
+ final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
+ lock.readLock().lock();
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ threadAssertTrue(lock.readLock().tryLock());
+ lock.readLock().unlock();
+ }});
+
+ t.start();
+ t.join();
+ lock.readLock().unlock();
}
@@ -713,21 +644,17 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
/**
* Fair write tryLock fails when readlocked
*/
- public void testWriteTryLockWhenReadLockedFair() {
- final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
- lock.readLock().lock();
- Thread t = new Thread(new Runnable() {
- public void run() {
- threadAssertFalse(lock.writeLock().tryLock());
- }
- });
- try {
- t.start();
- t.join();
- lock.readLock().unlock();
- } catch(Exception e){
- unexpectedException();
- }
+ public void testWriteTryLockWhenReadLockedFair() throws InterruptedException {
+ final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
+ lock.readLock().lock();
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() {
+ threadAssertFalse(lock.writeLock().tryLock());
+ }});
+
+ t.start();
+ t.join();
+ lock.readLock().unlock();
}
@@ -735,130 +662,85 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
/**
* write timed tryLock times out if locked
*/
- public void testWriteTryLock_Timeout() {
+ public void testWriteTryLock_Timeout() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
lock.writeLock().lock();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- threadAssertFalse(lock.writeLock().tryLock(1, TimeUnit.MILLISECONDS));
- } catch (Exception ex) {
- threadUnexpectedException();
- }
- }
- });
- try {
- t.start();
- t.join();
- lock.writeLock().unlock();
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ threadAssertFalse(lock.writeLock().tryLock(1, MILLISECONDS));
+ }});
+
+ t.start();
+ t.join();
+ assertTrue(lock.writeLock().isHeldByCurrentThread());
+ lock.writeLock().unlock();
}
/**
* read timed tryLock times out if write-locked
*/
- public void testReadTryLock_Timeout() {
+ public void testReadTryLock_Timeout() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
lock.writeLock().lock();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- threadAssertFalse(lock.readLock().tryLock(1, TimeUnit.MILLISECONDS));
- } catch (Exception ex) {
- threadUnexpectedException();
- }
- }
- });
- try {
- t.start();
- t.join();
- lock.writeLock().unlock();
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ threadAssertFalse(lock.readLock().tryLock(1, MILLISECONDS));
+ }});
+
+ t.start();
+ t.join();
+ assertTrue(lock.writeLock().isHeldByCurrentThread());
+ lock.writeLock().unlock();
}
/**
* write lockInterruptibly succeeds if lock free else is interruptible
*/
- public void testWriteLockInterruptibly() {
+ public void testWriteLockInterruptibly() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
- try {
- lock.writeLock().lockInterruptibly();
- } catch(Exception e) {
- unexpectedException();
- }
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- lock.writeLock().lockInterruptibly();
- threadShouldThrow();
- }
- catch(InterruptedException success) {
- }
- }
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- Thread.sleep(SHORT_DELAY_MS);
- t.join();
- lock.writeLock().unlock();
- } catch(Exception e){
- unexpectedException();
- }
+ lock.writeLock().lockInterruptibly();
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.writeLock().lockInterruptibly();
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.join();
+ lock.writeLock().unlock();
}
/**
* read lockInterruptibly succeeds if lock free else is interruptible
*/
- public void testReadLockInterruptibly() {
+ public void testReadLockInterruptibly() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
- try {
- lock.writeLock().lockInterruptibly();
- } catch(Exception e) {
- unexpectedException();
- }
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- lock.readLock().lockInterruptibly();
- threadShouldThrow();
- }
- catch(InterruptedException success) {
- }
- }
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- lock.writeLock().unlock();
- } catch(Exception e){
- unexpectedException();
- }
+ lock.writeLock().lockInterruptibly();
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.readLock().lockInterruptibly();
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
+ lock.writeLock().unlock();
}
/**
* Calling await without holding lock throws IllegalMonitorStateException
*/
- public void testAwait_IllegalMonitor() {
+ public void testAwait_IllegalMonitor() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
final Condition c = lock.writeLock().newCondition();
try {
c.await();
shouldThrow();
- }
- catch (IllegalMonitorStateException success) {
- }
- catch (Exception ex) {
- shouldThrow();
- }
+ } catch (IllegalMonitorStateException success) {}
}
/**
@@ -870,94 +752,66 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
try {
c.signal();
shouldThrow();
- }
- catch (IllegalMonitorStateException success) {
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ } catch (IllegalMonitorStateException success) {}
}
/**
* awaitNanos without a signal times out
*/
- public void testAwaitNanos_Timeout() {
+ public void testAwaitNanos_Timeout() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
final Condition c = lock.writeLock().newCondition();
- try {
- lock.writeLock().lock();
- long t = c.awaitNanos(100);
- assertTrue(t <= 0);
- lock.writeLock().unlock();
- }
- catch (Exception ex) {
- unexpectedException();
- }
+
+ lock.writeLock().lock();
+ long t = c.awaitNanos(100);
+ assertTrue(t <= 0);
+ lock.writeLock().unlock();
}
/**
* timed await without a signal times out
*/
- public void testAwait_Timeout() {
+ public void testAwait_Timeout() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
final Condition c = lock.writeLock().newCondition();
- try {
- lock.writeLock().lock();
- lock.writeLock().unlock();
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ lock.writeLock().lock();
+ assertFalse(c.await(SHORT_DELAY_MS, MILLISECONDS));
+ lock.writeLock().unlock();
}
/**
* awaitUntil without a signal times out
*/
- public void testAwaitUntil_Timeout() {
+ public void testAwaitUntil_Timeout() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
final Condition c = lock.writeLock().newCondition();
- try {
- lock.writeLock().lock();
- java.util.Date d = new java.util.Date();
- lock.writeLock().unlock();
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ lock.writeLock().lock();
+ java.util.Date d = new java.util.Date();
+ assertFalse(c.awaitUntil(new java.util.Date(d.getTime() + 10)));
+ lock.writeLock().unlock();
}
/**
* await returns when signalled
*/
- public void testAwait() {
+ public void testAwait() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
final Condition c = lock.writeLock().newCondition();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- lock.writeLock().lock();
- c.await();
- lock.writeLock().unlock();
- }
- catch(InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.writeLock().lock();
+ c.await();
+ lock.writeLock().unlock();
+ }});
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- lock.writeLock().lock();
- c.signal();
- lock.writeLock().unlock();
- t.join(SHORT_DELAY_MS);
- assertFalse(t.isAlive());
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.writeLock().lock();
+ c.signal();
+ lock.writeLock().unlock();
+ t.join(SHORT_DELAY_MS);
+ assertFalse(t.isAlive());
}
/** A helper class for uninterruptible wait tests */
@@ -990,230 +844,167 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
/**
* awaitUninterruptibly doesn't abort on interrupt
*/
- public void testAwaitUninterruptibly() {
+ public void testAwaitUninterruptibly() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
final Condition c = lock.writeLock().newCondition();
UninterruptableThread thread = new UninterruptableThread(lock.writeLock(), c);
- try {
- thread.start();
+ thread.start();
- while (!thread.lockStarted) {
- Thread.sleep(100);
- }
-
- lock.writeLock().lock();
- try {
- thread.interrupt();
- thread.canAwake = true;
- c.signal();
- } finally {
- lock.writeLock().unlock();
- }
+ while (!thread.lockStarted) {
+ Thread.sleep(100);
+ }
- thread.join();
- assertTrue(thread.interrupted);
- assertFalse(thread.isAlive());
- } catch (Exception ex) {
- unexpectedException();
+ lock.writeLock().lock();
+ try {
+ thread.interrupt();
+ thread.canAwake = true;
+ c.signal();
+ } finally {
+ lock.writeLock().unlock();
}
+
+ thread.join();
+ assertTrue(thread.interrupted);
+ assertFalse(thread.isAlive());
}
/**
* await is interruptible
*/
- public void testAwait_Interrupt() {
+ public void testAwait_Interrupt() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
final Condition c = lock.writeLock().newCondition();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- lock.writeLock().lock();
- c.await();
- lock.writeLock().unlock();
- threadShouldThrow();
- }
- catch(InterruptedException success) {
- }
- }
- });
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.writeLock().lock();
+ c.await();
+ lock.writeLock().unlock();
+ }});
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join(SHORT_DELAY_MS);
- assertFalse(t.isAlive());
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join(SHORT_DELAY_MS);
+ assertFalse(t.isAlive());
}
/**
* awaitNanos is interruptible
*/
- public void testAwaitNanos_Interrupt() {
+ public void testAwaitNanos_Interrupt() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
final Condition c = lock.writeLock().newCondition();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- lock.writeLock().lock();
- c.awaitNanos(SHORT_DELAY_MS * 2 * 1000000);
- lock.writeLock().unlock();
- threadShouldThrow();
- }
- catch(InterruptedException success) {
- }
- }
- });
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.writeLock().lock();
+ c.awaitNanos(MILLISECONDS.toNanos(LONG_DELAY_MS));
+ lock.writeLock().unlock();
+ }});
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join(SHORT_DELAY_MS);
- assertFalse(t.isAlive());
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join(SHORT_DELAY_MS);
+ assertFalse(t.isAlive());
}
/**
* awaitUntil is interruptible
*/
- public void testAwaitUntil_Interrupt() {
+ public void testAwaitUntil_Interrupt() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
final Condition c = lock.writeLock().newCondition();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- lock.writeLock().lock();
- java.util.Date d = new java.util.Date();
- c.awaitUntil(new java.util.Date(d.getTime() + 10000));
- lock.writeLock().unlock();
- threadShouldThrow();
- }
- catch(InterruptedException success) {
- }
- }
- });
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.writeLock().lock();
+ java.util.Date d = new java.util.Date();
+ c.awaitUntil(new java.util.Date(d.getTime() + 10000));
+ lock.writeLock().unlock();
+ }});
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join(SHORT_DELAY_MS);
- assertFalse(t.isAlive());
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join(SHORT_DELAY_MS);
+ assertFalse(t.isAlive());
}
/**
* signalAll wakes up all threads
*/
- public void testSignalAll() {
+ public void testSignalAll() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
final Condition c = lock.writeLock().newCondition();
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- try {
- lock.writeLock().lock();
- c.await();
- lock.writeLock().unlock();
- }
- catch(InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
-
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- try {
- lock.writeLock().lock();
- c.await();
- lock.writeLock().unlock();
- }
- catch(InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
+ Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.writeLock().lock();
+ c.await();
+ lock.writeLock().unlock();
+ }});
- try {
- t1.start();
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- lock.writeLock().lock();
- c.signalAll();
- lock.writeLock().unlock();
- t1.join(SHORT_DELAY_MS);
- t2.join(SHORT_DELAY_MS);
- assertFalse(t1.isAlive());
- assertFalse(t2.isAlive());
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.writeLock().lock();
+ c.await();
+ lock.writeLock().unlock();
+ }});
+
+ t1.start();
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.writeLock().lock();
+ c.signalAll();
+ lock.writeLock().unlock();
+ t1.join(SHORT_DELAY_MS);
+ t2.join(SHORT_DELAY_MS);
+ assertFalse(t1.isAlive());
+ assertFalse(t2.isAlive());
}
/**
* A serialized lock deserializes as unlocked
*/
- public void testSerialization() {
+ public void testSerialization() throws Exception {
ReentrantReadWriteLock l = new ReentrantReadWriteLock();
l.readLock().lock();
l.readLock().unlock();
- try {
- ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
- ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
- out.writeObject(l);
- out.close();
-
- ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
- ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
- ReentrantReadWriteLock r = (ReentrantReadWriteLock) in.readObject();
- r.readLock().lock();
- r.readLock().unlock();
- } catch(Exception e){
- e.printStackTrace();
- unexpectedException();
- }
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(l);
+ out.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ ReentrantReadWriteLock r = (ReentrantReadWriteLock) in.readObject();
+ r.readLock().lock();
+ r.readLock().unlock();
}
/**
* hasQueuedThreads reports whether there are waiting threads
*/
- public void testhasQueuedThreads() {
+ public void testhasQueuedThreads() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
Thread t1 = new Thread(new InterruptedLockRunnable(lock));
Thread t2 = new Thread(new InterruptibleLockRunnable(lock));
- try {
- assertFalse(lock.hasQueuedThreads());
- lock.writeLock().lock();
- t1.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(lock.hasQueuedThreads());
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(lock.hasQueuedThreads());
- t1.interrupt();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(lock.hasQueuedThreads());
- lock.writeLock().unlock();
- Thread.sleep(SHORT_DELAY_MS);
- assertFalse(lock.hasQueuedThreads());
- t1.join();
- t2.join();
- } catch(Exception e){
- unexpectedException();
- }
+ assertFalse(lock.hasQueuedThreads());
+ lock.writeLock().lock();
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(lock.hasQueuedThreads());
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(lock.hasQueuedThreads());
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(lock.hasQueuedThreads());
+ lock.writeLock().unlock();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(lock.hasQueuedThreads());
+ t1.join();
+ t2.join();
}
/**
@@ -1224,104 +1015,91 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
try {
sync.hasQueuedThread(null);
shouldThrow();
- } catch (NullPointerException success) {
- }
+ } catch (NullPointerException success) {}
}
/**
* hasQueuedThread reports whether a thread is queued.
*/
- public void testHasQueuedThread() {
+ public void testHasQueuedThread() throws InterruptedException {
final ReentrantReadWriteLock sync = new ReentrantReadWriteLock();
Thread t1 = new Thread(new InterruptedLockRunnable(sync));
Thread t2 = new Thread(new InterruptibleLockRunnable(sync));
- try {
- assertFalse(sync.hasQueuedThread(t1));
- assertFalse(sync.hasQueuedThread(t2));
- sync.writeLock().lock();
- t1.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(sync.hasQueuedThread(t1));
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(sync.hasQueuedThread(t1));
- assertTrue(sync.hasQueuedThread(t2));
- t1.interrupt();
- Thread.sleep(SHORT_DELAY_MS);
- assertFalse(sync.hasQueuedThread(t1));
- assertTrue(sync.hasQueuedThread(t2));
- sync.writeLock().unlock();
- Thread.sleep(SHORT_DELAY_MS);
- assertFalse(sync.hasQueuedThread(t1));
- Thread.sleep(SHORT_DELAY_MS);
- assertFalse(sync.hasQueuedThread(t2));
- t1.join();
- t2.join();
- } catch(Exception e){
- unexpectedException();
- }
+ assertFalse(sync.hasQueuedThread(t1));
+ assertFalse(sync.hasQueuedThread(t2));
+ sync.writeLock().lock();
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.hasQueuedThread(t1));
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(sync.hasQueuedThread(t1));
+ assertTrue(sync.hasQueuedThread(t2));
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(sync.hasQueuedThread(t1));
+ assertTrue(sync.hasQueuedThread(t2));
+ sync.writeLock().unlock();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(sync.hasQueuedThread(t1));
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(sync.hasQueuedThread(t2));
+ t1.join();
+ t2.join();
}
/**
* getQueueLength reports number of waiting threads
*/
- public void testGetQueueLength() {
+ public void testGetQueueLength() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
Thread t1 = new Thread(new InterruptedLockRunnable(lock));
Thread t2 = new Thread(new InterruptibleLockRunnable(lock));
- try {
- assertEquals(0, lock.getQueueLength());
- lock.writeLock().lock();
- t1.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertEquals(1, lock.getQueueLength());
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertEquals(2, lock.getQueueLength());
- t1.interrupt();
- Thread.sleep(SHORT_DELAY_MS);
- assertEquals(1, lock.getQueueLength());
- lock.writeLock().unlock();
- Thread.sleep(SHORT_DELAY_MS);
- assertEquals(0, lock.getQueueLength());
- t1.join();
- t2.join();
- } catch(Exception e){
- unexpectedException();
- }
+ assertEquals(0, lock.getQueueLength());
+ lock.writeLock().lock();
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(1, lock.getQueueLength());
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(2, lock.getQueueLength());
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(1, lock.getQueueLength());
+ lock.writeLock().unlock();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(0, lock.getQueueLength());
+ t1.join();
+ t2.join();
}
/**
* getQueuedThreads includes waiting threads
*/
- public void testGetQueuedThreads() {
+ public void testGetQueuedThreads() throws InterruptedException {
final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
Thread t1 = new Thread(new InterruptedLockRunnable(lock));
Thread t2 = new Thread(new InterruptibleLockRunnable(lock));
- try {
- assertTrue(lock.getQueuedThreads().isEmpty());
- lock.writeLock().lock();
- assertTrue(lock.getQueuedThreads().isEmpty());
- t1.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(lock.getQueuedThreads().contains(t1));
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(lock.getQueuedThreads().contains(t1));
- assertTrue(lock.getQueuedThreads().contains(t2));
- t1.interrupt();
- Thread.sleep(SHORT_DELAY_MS);
- assertFalse(lock.getQueuedThreads().contains(t1));
- assertTrue(lock.getQueuedThreads().contains(t2));
- lock.writeLock().unlock();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(lock.getQueuedThreads().isEmpty());
- t1.join();
- t2.join();
- } catch(Exception e){
- unexpectedException();
- }
+ assertTrue(lock.getQueuedThreads().isEmpty());
+ lock.writeLock().lock();
+ assertTrue(lock.getQueuedThreads().isEmpty());
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(lock.getQueuedThreads().contains(t1));
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(lock.getQueuedThreads().contains(t1));
+ assertTrue(lock.getQueuedThreads().contains(t2));
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(lock.getQueuedThreads().contains(t1));
+ assertTrue(lock.getQueuedThreads().contains(t2));
+ lock.writeLock().unlock();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(lock.getQueuedThreads().isEmpty());
+ t1.join();
+ t2.join();
}
/**
@@ -1332,10 +1110,7 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
try {
lock.hasWaiters(null);
shouldThrow();
- } catch (NullPointerException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (NullPointerException success) {}
}
/**
@@ -1346,10 +1121,7 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
try {
lock.getWaitQueueLength(null);
shouldThrow();
- } catch (NullPointerException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (NullPointerException success) {}
}
@@ -1361,10 +1133,7 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
try {
lock.getWaitingThreads(null);
shouldThrow();
- } catch (NullPointerException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (NullPointerException success) {}
}
/**
@@ -1372,15 +1141,12 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
*/
public void testHasWaitersIAE() {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
- final Condition c = (lock.writeLock().newCondition());
+ final Condition c = lock.writeLock().newCondition();
final ReentrantReadWriteLock lock2 = new ReentrantReadWriteLock();
try {
lock2.hasWaiters(c);
shouldThrow();
- } catch (IllegalArgumentException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (IllegalArgumentException success) {}
}
/**
@@ -1388,14 +1154,11 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
*/
public void testHasWaitersIMSE() {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
- final Condition c = (lock.writeLock().newCondition());
+ final Condition c = lock.writeLock().newCondition();
try {
lock.hasWaiters(c);
shouldThrow();
- } catch (IllegalMonitorStateException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (IllegalMonitorStateException success) {}
}
@@ -1404,15 +1167,12 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
*/
public void testGetWaitQueueLengthIAE() {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
- final Condition c = (lock.writeLock().newCondition());
+ final Condition c = lock.writeLock().newCondition();
final ReentrantReadWriteLock lock2 = new ReentrantReadWriteLock();
try {
lock2.getWaitQueueLength(c);
shouldThrow();
- } catch (IllegalArgumentException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (IllegalArgumentException success) {}
}
/**
@@ -1420,14 +1180,11 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
*/
public void testGetWaitQueueLengthIMSE() {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
- final Condition c = (lock.writeLock().newCondition());
+ final Condition c = lock.writeLock().newCondition();
try {
lock.getWaitQueueLength(c);
shouldThrow();
- } catch (IllegalMonitorStateException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (IllegalMonitorStateException success) {}
}
@@ -1436,15 +1193,12 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
*/
public void testGetWaitingThreadsIAE() {
final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
- final Condition c = (lock.writeLock().newCondition());
+ final Condition c = lock.writeLock().newCondition();
final PublicReentrantReadWriteLock lock2 = new PublicReentrantReadWriteLock();
try {
lock2.getWaitingThreads(c);
shouldThrow();
- } catch (IllegalArgumentException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (IllegalArgumentException success) {}
}
/**
@@ -1452,163 +1206,121 @@ public class ReentrantReadWriteLockTest extends JSR166TestCase {
*/
public void testGetWaitingThreadsIMSE() {
final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
- final Condition c = (lock.writeLock().newCondition());
+ final Condition c = lock.writeLock().newCondition();
try {
lock.getWaitingThreads(c);
shouldThrow();
- } catch (IllegalMonitorStateException success) {
- } catch (Exception ex) {
- unexpectedException();
- }
+ } catch (IllegalMonitorStateException success) {}
}
/**
* hasWaiters returns true when a thread is waiting, else false
*/
- public void testHasWaiters() {
+ public void testHasWaiters() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
- final Condition c = (lock.writeLock().newCondition());
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- lock.writeLock().lock();
- threadAssertFalse(lock.hasWaiters(c));
- threadAssertEquals(0, lock.getWaitQueueLength(c));
- c.await();
- lock.writeLock().unlock();
- }
- catch(InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
+ final Condition c = lock.writeLock().newCondition();
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.writeLock().lock();
+ threadAssertFalse(lock.hasWaiters(c));
+ threadAssertEquals(0, lock.getWaitQueueLength(c));
+ c.await();
+ lock.writeLock().unlock();
+ }});
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- lock.writeLock().lock();
- assertTrue(lock.hasWaiters(c));
- assertEquals(1, lock.getWaitQueueLength(c));
- c.signal();
- lock.writeLock().unlock();
- Thread.sleep(SHORT_DELAY_MS);
- lock.writeLock().lock();
- assertFalse(lock.hasWaiters(c));
- assertEquals(0, lock.getWaitQueueLength(c));
- lock.writeLock().unlock();
- t.join(SHORT_DELAY_MS);
- assertFalse(t.isAlive());
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.writeLock().lock();
+ assertTrue(lock.hasWaiters(c));
+ assertEquals(1, lock.getWaitQueueLength(c));
+ c.signal();
+ lock.writeLock().unlock();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.writeLock().lock();
+ assertFalse(lock.hasWaiters(c));
+ assertEquals(0, lock.getWaitQueueLength(c));
+ lock.writeLock().unlock();
+ t.join(SHORT_DELAY_MS);
+ assertFalse(t.isAlive());
}
/**
* getWaitQueueLength returns number of waiting threads
*/
- public void testGetWaitQueueLength() {
+ public void testGetWaitQueueLength() throws InterruptedException {
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
- final Condition c = (lock.writeLock().newCondition());
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- lock.writeLock().lock();
- threadAssertFalse(lock.hasWaiters(c));
- threadAssertEquals(0, lock.getWaitQueueLength(c));
- c.await();
- lock.writeLock().unlock();
- }
- catch(InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
+ final Condition c = lock.writeLock().newCondition();
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.writeLock().lock();
+ threadAssertFalse(lock.hasWaiters(c));
+ threadAssertEquals(0, lock.getWaitQueueLength(c));
+ c.await();
+ lock.writeLock().unlock();
+ }});
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- lock.writeLock().lock();
- assertTrue(lock.hasWaiters(c));
- assertEquals(1, lock.getWaitQueueLength(c));
- c.signal();
- lock.writeLock().unlock();
- Thread.sleep(SHORT_DELAY_MS);
- lock.writeLock().lock();
- assertFalse(lock.hasWaiters(c));
- assertEquals(0, lock.getWaitQueueLength(c));
- lock.writeLock().unlock();
- t.join(SHORT_DELAY_MS);
- assertFalse(t.isAlive());
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.writeLock().lock();
+ assertTrue(lock.hasWaiters(c));
+ assertEquals(1, lock.getWaitQueueLength(c));
+ c.signal();
+ lock.writeLock().unlock();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.writeLock().lock();
+ assertFalse(lock.hasWaiters(c));
+ assertEquals(0, lock.getWaitQueueLength(c));
+ lock.writeLock().unlock();
+ t.join(SHORT_DELAY_MS);
+ assertFalse(t.isAlive());
}
/**
* getWaitingThreads returns only and all waiting threads
*/
- public void testGetWaitingThreads() {
+ public void testGetWaitingThreads() throws InterruptedException {
final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
final Condition c = lock.writeLock().newCondition();
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- try {
- lock.writeLock().lock();
- threadAssertTrue(lock.getWaitingThreads(c).isEmpty());
- c.await();
- lock.writeLock().unlock();
- }
- catch(InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
-
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- try {
- lock.writeLock().lock();
- threadAssertFalse(lock.getWaitingThreads(c).isEmpty());
- c.await();
- lock.writeLock().unlock();
- }
- catch(InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
+ Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.writeLock().lock();
+ threadAssertTrue(lock.getWaitingThreads(c).isEmpty());
+ c.await();
+ lock.writeLock().unlock();
+ }});
- try {
- lock.writeLock().lock();
- assertTrue(lock.getWaitingThreads(c).isEmpty());
- lock.writeLock().unlock();
- t1.start();
- Thread.sleep(SHORT_DELAY_MS);
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- lock.writeLock().lock();
- assertTrue(lock.hasWaiters(c));
- assertTrue(lock.getWaitingThreads(c).contains(t1));
- assertTrue(lock.getWaitingThreads(c).contains(t2));
- c.signalAll();
- lock.writeLock().unlock();
- Thread.sleep(SHORT_DELAY_MS);
- lock.writeLock().lock();
- assertFalse(lock.hasWaiters(c));
- assertTrue(lock.getWaitingThreads(c).isEmpty());
- lock.writeLock().unlock();
- t1.join(SHORT_DELAY_MS);
- t2.join(SHORT_DELAY_MS);
- assertFalse(t1.isAlive());
- assertFalse(t2.isAlive());
- }
- catch (Exception ex) {
- unexpectedException();
- }
+ Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ lock.writeLock().lock();
+ threadAssertFalse(lock.getWaitingThreads(c).isEmpty());
+ c.await();
+ lock.writeLock().unlock();
+ }});
+
+ lock.writeLock().lock();
+ assertTrue(lock.getWaitingThreads(c).isEmpty());
+ lock.writeLock().unlock();
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.writeLock().lock();
+ assertTrue(lock.hasWaiters(c));
+ assertTrue(lock.getWaitingThreads(c).contains(t1));
+ assertTrue(lock.getWaitingThreads(c).contains(t2));
+ c.signalAll();
+ lock.writeLock().unlock();
+ Thread.sleep(SHORT_DELAY_MS);
+ lock.writeLock().lock();
+ assertFalse(lock.hasWaiters(c));
+ assertTrue(lock.getWaitingThreads(c).isEmpty());
+ lock.writeLock().unlock();
+ t1.join(SHORT_DELAY_MS);
+ t2.join(SHORT_DELAY_MS);
+ assertFalse(t1.isAlive());
+ assertFalse(t2.isAlive());
}
/**
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/ScheduledExecutorSubclassTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/ScheduledExecutorSubclassTest.java
new file mode 100644
index 0000000..21f4ced
--- /dev/null
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/ScheduledExecutorSubclassTest.java
@@ -0,0 +1,1060 @@
+/*
+ * 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 tests.api.java.util.concurrent; // android-added
+
+import junit.framework.*;
+import java.util.*;
+import java.util.concurrent.*;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import java.util.concurrent.atomic.*;
+
+public class ScheduledExecutorSubclassTest extends JSR166TestCase {
+ public static Test suite() {
+ return new TestSuite(ScheduledExecutorSubclassTest.class);
+ }
+
+ static class CustomTask<V> implements RunnableScheduledFuture<V> {
+ RunnableScheduledFuture<V> task;
+ volatile boolean ran;
+ CustomTask(RunnableScheduledFuture<V> t) { task = t; }
+ public boolean isPeriodic() { return task.isPeriodic(); }
+ public void run() {
+ ran = true;
+ task.run();
+ }
+ public long getDelay(TimeUnit unit) { return task.getDelay(unit); }
+ public int compareTo(Delayed t) {
+ return task.compareTo(((CustomTask)t).task);
+ }
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ return task.cancel(mayInterruptIfRunning);
+ }
+ public boolean isCancelled() { return task.isCancelled(); }
+ public boolean isDone() { return task.isDone(); }
+ public V get() throws InterruptedException, ExecutionException {
+ V v = task.get();
+ assertTrue(ran);
+ return v;
+ }
+ public V get(long time, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+ V v = task.get(time, unit);
+ assertTrue(ran);
+ return v;
+ }
+ }
+
+
+ public class CustomExecutor extends ScheduledThreadPoolExecutor {
+
+ protected <V> RunnableScheduledFuture<V> decorateTask(Runnable r, RunnableScheduledFuture<V> task) {
+ return new CustomTask<V>(task);
+ }
+
+ protected <V> RunnableScheduledFuture<V> decorateTask(Callable<V> c, RunnableScheduledFuture<V> task) {
+ return new CustomTask<V>(task);
+ }
+ CustomExecutor(int corePoolSize) { super(corePoolSize);}
+ CustomExecutor(int corePoolSize, RejectedExecutionHandler handler) {
+ super(corePoolSize, handler);
+ }
+
+ CustomExecutor(int corePoolSize, ThreadFactory threadFactory) {
+ super(corePoolSize, threadFactory);
+ }
+ CustomExecutor(int corePoolSize, ThreadFactory threadFactory,
+ RejectedExecutionHandler handler) {
+ super(corePoolSize, threadFactory, handler);
+ }
+
+ }
+
+
+ /**
+ * execute successfully executes a runnable
+ */
+ public void testExecute() throws InterruptedException {
+ TrackedShortRunnable runnable =new TrackedShortRunnable();
+ CustomExecutor p1 = new CustomExecutor(1);
+ p1.execute(runnable);
+ assertFalse(runnable.done);
+ Thread.sleep(SHORT_DELAY_MS);
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
+ Thread.sleep(MEDIUM_DELAY_MS);
+ assertTrue(runnable.done);
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
+ joinPool(p1);
+ }
+
+
+ /**
+ * delayed schedule of callable successfully executes after delay
+ */
+ public void testSchedule1() throws Exception {
+ TrackedCallable callable = new TrackedCallable();
+ CustomExecutor p1 = new CustomExecutor(1);
+ Future f = p1.schedule(callable, SHORT_DELAY_MS, MILLISECONDS);
+ assertFalse(callable.done);
+ Thread.sleep(MEDIUM_DELAY_MS);
+ assertTrue(callable.done);
+ assertEquals(Boolean.TRUE, f.get());
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
+ joinPool(p1);
+ }
+
+ /**
+ * delayed schedule of runnable successfully executes after delay
+ */
+ public void testSchedule3() throws InterruptedException {
+ TrackedShortRunnable runnable = new TrackedShortRunnable();
+ CustomExecutor p1 = new CustomExecutor(1);
+ p1.schedule(runnable, SMALL_DELAY_MS, MILLISECONDS);
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(runnable.done);
+ Thread.sleep(MEDIUM_DELAY_MS);
+ assertTrue(runnable.done);
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
+ joinPool(p1);
+ }
+
+ /**
+ * scheduleAtFixedRate executes runnable after given initial delay
+ */
+ public void testSchedule4() throws InterruptedException {
+ TrackedShortRunnable runnable = new TrackedShortRunnable();
+ CustomExecutor p1 = new CustomExecutor(1);
+ ScheduledFuture h = p1.scheduleAtFixedRate(runnable, SHORT_DELAY_MS, SHORT_DELAY_MS, MILLISECONDS);
+ assertFalse(runnable.done);
+ Thread.sleep(MEDIUM_DELAY_MS);
+ assertTrue(runnable.done);
+ h.cancel(true);
+ joinPool(p1);
+ }
+
+ static class RunnableCounter implements Runnable {
+ AtomicInteger count = new AtomicInteger(0);
+ public void run() { count.getAndIncrement(); }
+ }
+
+ /**
+ * scheduleWithFixedDelay executes runnable after given initial delay
+ */
+ public void testSchedule5() throws InterruptedException {
+ TrackedShortRunnable runnable = new TrackedShortRunnable();
+ CustomExecutor p1 = new CustomExecutor(1);
+ ScheduledFuture h = p1.scheduleWithFixedDelay(runnable, SHORT_DELAY_MS, SHORT_DELAY_MS, MILLISECONDS);
+ assertFalse(runnable.done);
+ Thread.sleep(MEDIUM_DELAY_MS);
+ assertTrue(runnable.done);
+ h.cancel(true);
+ joinPool(p1);
+ }
+
+ /**
+ * scheduleAtFixedRate executes series of tasks at given rate
+ */
+ public void testFixedRateSequence() throws InterruptedException {
+ CustomExecutor p1 = new CustomExecutor(1);
+ RunnableCounter counter = new RunnableCounter();
+ ScheduledFuture h =
+ p1.scheduleAtFixedRate(counter, 0, 1, MILLISECONDS);
+ Thread.sleep(SMALL_DELAY_MS);
+ h.cancel(true);
+ int c = counter.count.get();
+ // By time scaling conventions, we must have at least
+ // an execution per SHORT delay, but no more than one SHORT more
+ assertTrue(c >= SMALL_DELAY_MS / SHORT_DELAY_MS);
+ assertTrue(c <= SMALL_DELAY_MS + SHORT_DELAY_MS);
+ joinPool(p1);
+ }
+
+ /**
+ * scheduleWithFixedDelay executes series of tasks with given period
+ */
+ public void testFixedDelaySequence() throws InterruptedException {
+ CustomExecutor p1 = new CustomExecutor(1);
+ RunnableCounter counter = new RunnableCounter();
+ ScheduledFuture h =
+ p1.scheduleWithFixedDelay(counter, 0, 1, MILLISECONDS);
+ Thread.sleep(SMALL_DELAY_MS);
+ h.cancel(true);
+ int c = counter.count.get();
+ assertTrue(c >= SMALL_DELAY_MS / SHORT_DELAY_MS);
+ assertTrue(c <= SMALL_DELAY_MS + SHORT_DELAY_MS);
+ joinPool(p1);
+ }
+
+
+ /**
+ * execute (null) throws NPE
+ */
+ public void testExecuteNull() throws InterruptedException {
+ CustomExecutor se = new CustomExecutor(1);
+ try {
+ se.execute(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ joinPool(se);
+ }
+
+ /**
+ * schedule (null) throws NPE
+ */
+ public void testScheduleNull() throws InterruptedException {
+ CustomExecutor se = new CustomExecutor(1);
+ try {
+ TrackedCallable callable = null;
+ Future f = se.schedule(callable, SHORT_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ joinPool(se);
+ }
+
+ /**
+ * execute throws RejectedExecutionException if shutdown
+ */
+ public void testSchedule1_RejectedExecutionException() {
+ CustomExecutor se = new CustomExecutor(1);
+ try {
+ se.shutdown();
+ se.schedule(new NoOpRunnable(),
+ MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (RejectedExecutionException success) {
+ } catch (SecurityException ok) {
+ }
+
+ joinPool(se);
+ }
+
+ /**
+ * schedule throws RejectedExecutionException if shutdown
+ */
+ public void testSchedule2_RejectedExecutionException() {
+ CustomExecutor se = new CustomExecutor(1);
+ try {
+ se.shutdown();
+ se.schedule(new NoOpCallable(),
+ MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (RejectedExecutionException success) {
+ } catch (SecurityException ok) {
+ }
+ joinPool(se);
+ }
+
+ /**
+ * schedule callable throws RejectedExecutionException if shutdown
+ */
+ public void testSchedule3_RejectedExecutionException() {
+ CustomExecutor se = new CustomExecutor(1);
+ try {
+ se.shutdown();
+ se.schedule(new NoOpCallable(),
+ MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (RejectedExecutionException success) {
+ } catch (SecurityException ok) {
+ }
+ joinPool(se);
+ }
+
+ /**
+ * scheduleAtFixedRate throws RejectedExecutionException if shutdown
+ */
+ public void testScheduleAtFixedRate1_RejectedExecutionException() {
+ CustomExecutor se = new CustomExecutor(1);
+ try {
+ se.shutdown();
+ se.scheduleAtFixedRate(new NoOpRunnable(),
+ MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (RejectedExecutionException success) {
+ } catch (SecurityException ok) {
+ }
+ joinPool(se);
+ }
+
+ /**
+ * scheduleWithFixedDelay throws RejectedExecutionException if shutdown
+ */
+ public void testScheduleWithFixedDelay1_RejectedExecutionException() {
+ CustomExecutor se = new CustomExecutor(1);
+ try {
+ se.shutdown();
+ se.scheduleWithFixedDelay(new NoOpRunnable(),
+ MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (RejectedExecutionException success) {
+ } catch (SecurityException ok) {
+ }
+ joinPool(se);
+ }
+
+ /**
+ * getActiveCount increases but doesn't overestimate, when a
+ * thread becomes active
+ */
+ public void testGetActiveCount() throws InterruptedException {
+ CustomExecutor p2 = new CustomExecutor(2);
+ assertEquals(0, p2.getActiveCount());
+ p2.execute(new SmallRunnable());
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(1, p2.getActiveCount());
+ joinPool(p2);
+ }
+
+ /**
+ * getCompletedTaskCount increases, but doesn't overestimate,
+ * when tasks complete
+ */
+ public void testGetCompletedTaskCount() throws InterruptedException {
+ CustomExecutor p2 = new CustomExecutor(2);
+ assertEquals(0, p2.getCompletedTaskCount());
+ p2.execute(new SmallRunnable());
+ Thread.sleep(MEDIUM_DELAY_MS);
+ assertEquals(1, p2.getCompletedTaskCount());
+ joinPool(p2);
+ }
+
+ /**
+ * getCorePoolSize returns size given in constructor if not otherwise set
+ */
+ public void testGetCorePoolSize() {
+ CustomExecutor p1 = new CustomExecutor(1);
+ assertEquals(1, p1.getCorePoolSize());
+ joinPool(p1);
+ }
+
+ /**
+ * getLargestPoolSize increases, but doesn't overestimate, when
+ * multiple threads active
+ */
+ public void testGetLargestPoolSize() throws InterruptedException {
+ CustomExecutor p2 = new CustomExecutor(2);
+ assertEquals(0, p2.getLargestPoolSize());
+ p2.execute(new SmallRunnable());
+ p2.execute(new SmallRunnable());
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(2, p2.getLargestPoolSize());
+ joinPool(p2);
+ }
+
+ /**
+ * getPoolSize increases, but doesn't overestimate, when threads
+ * become active
+ */
+ public void testGetPoolSize() {
+ CustomExecutor p1 = new CustomExecutor(1);
+ assertEquals(0, p1.getPoolSize());
+ p1.execute(new SmallRunnable());
+ assertEquals(1, p1.getPoolSize());
+ joinPool(p1);
+ }
+
+ /**
+ * getTaskCount increases, but doesn't overestimate, when tasks
+ * submitted
+ */
+ public void testGetTaskCount() throws InterruptedException {
+ CustomExecutor p1 = new CustomExecutor(1);
+ assertEquals(0, p1.getTaskCount());
+ for (int i = 0; i < 5; i++)
+ p1.execute(new SmallRunnable());
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(5, p1.getTaskCount());
+ joinPool(p1);
+ }
+
+ /**
+ * getThreadFactory returns factory in constructor if not set
+ */
+ public void testGetThreadFactory() {
+ ThreadFactory tf = new SimpleThreadFactory();
+ CustomExecutor p = new CustomExecutor(1, tf);
+ assertSame(tf, p.getThreadFactory());
+ joinPool(p);
+ }
+
+ /**
+ * setThreadFactory sets the thread factory returned by getThreadFactory
+ */
+ public void testSetThreadFactory() {
+ ThreadFactory tf = new SimpleThreadFactory();
+ CustomExecutor p = new CustomExecutor(1);
+ p.setThreadFactory(tf);
+ assertSame(tf, p.getThreadFactory());
+ joinPool(p);
+ }
+
+ /**
+ * setThreadFactory(null) throws NPE
+ */
+ public void testSetThreadFactoryNull() {
+ CustomExecutor p = new CustomExecutor(1);
+ try {
+ p.setThreadFactory(null);
+ shouldThrow();
+ } catch (NullPointerException success) {
+ } finally {
+ joinPool(p);
+ }
+ }
+
+ /**
+ * is isShutDown is false before shutdown, true after
+ */
+ public void testIsShutdown() {
+ CustomExecutor p1 = new CustomExecutor(1);
+ try {
+ assertFalse(p1.isShutdown());
+ }
+ finally {
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
+ }
+ assertTrue(p1.isShutdown());
+ }
+
+
+ /**
+ * isTerminated is false before termination, true after
+ */
+ public void testIsTerminated() throws InterruptedException {
+ CustomExecutor p1 = new CustomExecutor(1);
+ try {
+ p1.execute(new SmallRunnable());
+ } finally {
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
+ }
+ assertTrue(p1.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
+ assertTrue(p1.isTerminated());
+ }
+
+ /**
+ * isTerminating is not true when running or when terminated
+ */
+ public void testIsTerminating() throws InterruptedException {
+ CustomExecutor p1 = new CustomExecutor(1);
+ assertFalse(p1.isTerminating());
+ try {
+ p1.execute(new SmallRunnable());
+ assertFalse(p1.isTerminating());
+ } finally {
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
+ }
+ assertTrue(p1.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
+ assertTrue(p1.isTerminated());
+ assertFalse(p1.isTerminating());
+ }
+
+ /**
+ * getQueue returns the work queue, which contains queued tasks
+ */
+ public void testGetQueue() throws InterruptedException {
+ CustomExecutor p1 = new CustomExecutor(1);
+ ScheduledFuture[] tasks = new ScheduledFuture[5];
+ for (int i = 0; i < 5; i++) {
+ tasks[i] = p1.schedule(new SmallPossiblyInterruptedRunnable(), 1, MILLISECONDS);
+ }
+ try {
+ Thread.sleep(SHORT_DELAY_MS);
+ BlockingQueue<Runnable> q = p1.getQueue();
+ assertTrue(q.contains(tasks[4]));
+ assertFalse(q.contains(tasks[0]));
+ } finally {
+ joinPool(p1);
+ }
+ }
+
+ /**
+ * remove(task) removes queued task, and fails to remove active task
+ */
+ public void testRemove() throws InterruptedException {
+ CustomExecutor p1 = new CustomExecutor(1);
+ ScheduledFuture[] tasks = new ScheduledFuture[5];
+ for (int i = 0; i < 5; i++) {
+ tasks[i] = p1.schedule(new SmallPossiblyInterruptedRunnable(), 1, MILLISECONDS);
+ }
+ try {
+ Thread.sleep(SHORT_DELAY_MS);
+ BlockingQueue<Runnable> q = p1.getQueue();
+ assertFalse(p1.remove((Runnable)tasks[0]));
+ assertTrue(q.contains((Runnable)tasks[4]));
+ assertTrue(q.contains((Runnable)tasks[3]));
+ assertTrue(p1.remove((Runnable)tasks[4]));
+ assertFalse(p1.remove((Runnable)tasks[4]));
+ assertFalse(q.contains((Runnable)tasks[4]));
+ assertTrue(q.contains((Runnable)tasks[3]));
+ assertTrue(p1.remove((Runnable)tasks[3]));
+ assertFalse(q.contains((Runnable)tasks[3]));
+ } finally {
+ joinPool(p1);
+ }
+ }
+
+ /**
+ * purge removes cancelled tasks from the queue
+ */
+ public void testPurge() throws InterruptedException {
+ CustomExecutor p1 = new CustomExecutor(1);
+ ScheduledFuture[] tasks = new ScheduledFuture[5];
+ for (int i = 0; i < 5; i++) {
+ tasks[i] = p1.schedule(new SmallPossiblyInterruptedRunnable(), SHORT_DELAY_MS, MILLISECONDS);
+ }
+ try {
+ int max = 5;
+ if (tasks[4].cancel(true)) --max;
+ if (tasks[3].cancel(true)) --max;
+ // There must eventually be an interference-free point at
+ // which purge will not fail. (At worst, when queue is empty.)
+ int k;
+ for (k = 0; k < SMALL_DELAY_MS; ++k) {
+ p1.purge();
+ long count = p1.getTaskCount();
+ if (count >= 0 && count <= max)
+ break;
+ Thread.sleep(1);
+ }
+ assertTrue(k < SMALL_DELAY_MS);
+ } finally {
+ joinPool(p1);
+ }
+ }
+
+ /**
+ * shutDownNow returns a list containing tasks that were not run
+ */
+ public void testShutDownNow() {
+ CustomExecutor p1 = new CustomExecutor(1);
+ for (int i = 0; i < 5; i++)
+ p1.schedule(new SmallPossiblyInterruptedRunnable(), SHORT_DELAY_MS, MILLISECONDS);
+ List l;
+ try {
+ l = p1.shutdownNow();
+ } catch (SecurityException ok) {
+ return;
+ }
+ assertTrue(p1.isShutdown());
+ assertTrue(l.size() > 0 && l.size() <= 5);
+ joinPool(p1);
+ }
+
+ /**
+ * In default setting, shutdown cancels periodic but not delayed
+ * tasks at shutdown
+ */
+ public void testShutDown1() throws InterruptedException {
+ CustomExecutor p1 = new CustomExecutor(1);
+ assertTrue(p1.getExecuteExistingDelayedTasksAfterShutdownPolicy());
+ assertFalse(p1.getContinueExistingPeriodicTasksAfterShutdownPolicy());
+
+ ScheduledFuture[] tasks = new ScheduledFuture[5];
+ for (int i = 0; i < 5; i++)
+ tasks[i] = p1.schedule(new NoOpRunnable(), SHORT_DELAY_MS, MILLISECONDS);
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
+ BlockingQueue q = p1.getQueue();
+ for (Iterator it = q.iterator(); it.hasNext();) {
+ ScheduledFuture t = (ScheduledFuture)it.next();
+ assertFalse(t.isCancelled());
+ }
+ assertTrue(p1.isShutdown());
+ Thread.sleep(SMALL_DELAY_MS);
+ for (int i = 0; i < 5; ++i) {
+ assertTrue(tasks[i].isDone());
+ assertFalse(tasks[i].isCancelled());
+ }
+ }
+
+
+ /**
+ * If setExecuteExistingDelayedTasksAfterShutdownPolicy is false,
+ * delayed tasks are cancelled at shutdown
+ */
+ public void testShutDown2() throws InterruptedException {
+ CustomExecutor p1 = new CustomExecutor(1);
+ p1.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
+ ScheduledFuture[] tasks = new ScheduledFuture[5];
+ for (int i = 0; i < 5; i++)
+ tasks[i] = p1.schedule(new NoOpRunnable(), SHORT_DELAY_MS, MILLISECONDS);
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
+ assertTrue(p1.isShutdown());
+ BlockingQueue q = p1.getQueue();
+ assertTrue(q.isEmpty());
+ Thread.sleep(SMALL_DELAY_MS);
+ assertTrue(p1.isTerminated());
+ }
+
+
+ /**
+ * If setContinueExistingPeriodicTasksAfterShutdownPolicy is set false,
+ * periodic tasks are not cancelled at shutdown
+ */
+ public void testShutDown3() throws InterruptedException {
+ CustomExecutor p1 = new CustomExecutor(1);
+ p1.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
+ ScheduledFuture task =
+ p1.scheduleAtFixedRate(new NoOpRunnable(), 5, 5, MILLISECONDS);
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
+ assertTrue(p1.isShutdown());
+ BlockingQueue q = p1.getQueue();
+ assertTrue(q.isEmpty());
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(p1.isTerminated());
+ }
+
+ /**
+ * if setContinueExistingPeriodicTasksAfterShutdownPolicy is true,
+ * periodic tasks are cancelled at shutdown
+ */
+ public void testShutDown4() throws InterruptedException {
+ CustomExecutor p1 = new CustomExecutor(1);
+ try {
+ p1.setContinueExistingPeriodicTasksAfterShutdownPolicy(true);
+ ScheduledFuture task =
+ p1.scheduleAtFixedRate(new NoOpRunnable(), 1, 1, MILLISECONDS);
+ assertFalse(task.isCancelled());
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
+ assertFalse(task.isCancelled());
+ assertFalse(p1.isTerminated());
+ assertTrue(p1.isShutdown());
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(task.isCancelled());
+ assertTrue(task.cancel(true));
+ assertTrue(task.isDone());
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(p1.isTerminated());
+ }
+ finally {
+ joinPool(p1);
+ }
+ }
+
+ /**
+ * completed submit of callable returns result
+ */
+ public void testSubmitCallable() throws Exception {
+ ExecutorService e = new CustomExecutor(2);
+ try {
+ Future<String> future = e.submit(new StringTask());
+ String result = future.get();
+ assertSame(TEST_STRING, result);
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * completed submit of runnable returns successfully
+ */
+ public void testSubmitRunnable() throws Exception {
+ ExecutorService e = new CustomExecutor(2);
+ try {
+ Future<?> future = e.submit(new NoOpRunnable());
+ future.get();
+ assertTrue(future.isDone());
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * completed submit of (runnable, result) returns result
+ */
+ public void testSubmitRunnable2() throws Exception {
+ ExecutorService e = new CustomExecutor(2);
+ try {
+ Future<String> future = e.submit(new NoOpRunnable(), TEST_STRING);
+ String result = future.get();
+ assertSame(TEST_STRING, result);
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * invokeAny(null) throws NPE
+ */
+ public void testInvokeAny1() throws Exception {
+ ExecutorService e = new CustomExecutor(2);
+ try {
+ e.invokeAny(null);
+ shouldThrow();
+ } catch (NullPointerException success) {
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * invokeAny(empty collection) throws IAE
+ */
+ public void testInvokeAny2() throws Exception {
+ ExecutorService e = new CustomExecutor(2);
+ try {
+ e.invokeAny(new ArrayList<Callable<String>>());
+ shouldThrow();
+ } catch (IllegalArgumentException success) {
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * invokeAny(c) throws NPE if c has null elements
+ */
+ public void testInvokeAny3() throws Exception {
+ CountDownLatch latch = new CountDownLatch(1);
+ ExecutorService e = new CustomExecutor(2);
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(latchAwaitingStringTask(latch));
+ l.add(null);
+ try {
+ e.invokeAny(l);
+ shouldThrow();
+ } catch (NullPointerException success) {
+ } finally {
+ latch.countDown();
+ joinPool(e);
+ }
+ }
+
+ /**
+ * invokeAny(c) throws ExecutionException if no task completes
+ */
+ public void testInvokeAny4() throws Exception {
+ ExecutorService e = new CustomExecutor(2);
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new NPETask());
+ try {
+ e.invokeAny(l);
+ shouldThrow();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof NullPointerException);
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * invokeAny(c) returns result of some task
+ */
+ public void testInvokeAny5() throws Exception {
+ ExecutorService e = new CustomExecutor(2);
+ try {
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(new StringTask());
+ String result = e.invokeAny(l);
+ assertSame(TEST_STRING, result);
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * invokeAll(null) throws NPE
+ */
+ public void testInvokeAll1() throws Exception {
+ ExecutorService e = new CustomExecutor(2);
+ try {
+ e.invokeAll(null);
+ shouldThrow();
+ } catch (NullPointerException success) {
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * invokeAll(empty collection) returns empty collection
+ */
+ public void testInvokeAll2() throws Exception {
+ ExecutorService e = new CustomExecutor(2);
+ try {
+ List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>());
+ assertTrue(r.isEmpty());
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * invokeAll(c) throws NPE if c has null elements
+ */
+ public void testInvokeAll3() throws Exception {
+ ExecutorService e = new CustomExecutor(2);
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(null);
+ try {
+ e.invokeAll(l);
+ shouldThrow();
+ } catch (NullPointerException success) {
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * get of invokeAll(c) throws exception on failed task
+ */
+ public void testInvokeAll4() throws Exception {
+ ExecutorService e = new CustomExecutor(2);
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new NPETask());
+ List<Future<String>> futures = e.invokeAll(l);
+ assertEquals(1, futures.size());
+ try {
+ futures.get(0).get();
+ shouldThrow();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof NullPointerException);
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * invokeAll(c) returns results of all completed tasks
+ */
+ public void testInvokeAll5() throws Exception {
+ ExecutorService e = new CustomExecutor(2);
+ try {
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(new StringTask());
+ List<Future<String>> futures = e.invokeAll(l);
+ assertEquals(2, futures.size());
+ for (Future<String> future : futures)
+ assertSame(TEST_STRING, future.get());
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAny(null) throws NPE
+ */
+ public void testTimedInvokeAny1() throws Exception {
+ ExecutorService e = new CustomExecutor(2);
+ try {
+ e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (NullPointerException success) {
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAny(,,null) throws NPE
+ */
+ public void testTimedInvokeAnyNullTimeUnit() throws Exception {
+ ExecutorService e = new CustomExecutor(2);
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ try {
+ e.invokeAny(l, MEDIUM_DELAY_MS, null);
+ shouldThrow();
+ } catch (NullPointerException success) {
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAny(empty collection) throws IAE
+ */
+ public void testTimedInvokeAny2() throws Exception {
+ ExecutorService e = new CustomExecutor(2);
+ try {
+ e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAny(c) throws NPE if c has null elements
+ */
+ public void testTimedInvokeAny3() throws Exception {
+ CountDownLatch latch = new CountDownLatch(1);
+ ExecutorService e = new CustomExecutor(2);
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(latchAwaitingStringTask(latch));
+ l.add(null);
+ try {
+ e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (NullPointerException success) {
+ } finally {
+ latch.countDown();
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAny(c) throws ExecutionException if no task completes
+ */
+ public void testTimedInvokeAny4() throws Exception {
+ ExecutorService e = new CustomExecutor(2);
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new NPETask());
+ try {
+ e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof NullPointerException);
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAny(c) returns result of some task
+ */
+ public void testTimedInvokeAny5() throws Exception {
+ ExecutorService e = new CustomExecutor(2);
+ try {
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(new StringTask());
+ String result = e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ assertSame(TEST_STRING, result);
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAll(null) throws NPE
+ */
+ public void testTimedInvokeAll1() throws Exception {
+ ExecutorService e = new CustomExecutor(2);
+ try {
+ e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (NullPointerException success) {
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAll(,,null) throws NPE
+ */
+ public void testTimedInvokeAllNullTimeUnit() throws Exception {
+ ExecutorService e = new CustomExecutor(2);
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ try {
+ e.invokeAll(l, MEDIUM_DELAY_MS, null);
+ shouldThrow();
+ } catch (NullPointerException success) {
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAll(empty collection) returns empty collection
+ */
+ public void testTimedInvokeAll2() throws Exception {
+ ExecutorService e = new CustomExecutor(2);
+ try {
+ List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
+ assertTrue(r.isEmpty());
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAll(c) throws NPE if c has null elements
+ */
+ public void testTimedInvokeAll3() throws Exception {
+ ExecutorService e = new CustomExecutor(2);
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(null);
+ try {
+ e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (NullPointerException success) {
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * get of element of invokeAll(c) throws exception on failed task
+ */
+ public void testTimedInvokeAll4() throws Exception {
+ ExecutorService e = new CustomExecutor(2);
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new NPETask());
+ List<Future<String>> futures =
+ e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ assertEquals(1, futures.size());
+ try {
+ futures.get(0).get();
+ shouldThrow();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof NullPointerException);
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAll(c) returns results of all completed tasks
+ */
+ public void testTimedInvokeAll5() throws Exception {
+ ExecutorService e = new CustomExecutor(2);
+ try {
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(new StringTask());
+ List<Future<String>> futures =
+ e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ assertEquals(2, futures.size());
+ for (Future<String> future : futures)
+ assertSame(TEST_STRING, future.get());
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAll(c) cancels tasks not completed by timeout
+ */
+ public void testTimedInvokeAll6() throws Exception {
+ ExecutorService e = new CustomExecutor(2);
+ try {
+ List<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>> futures =
+ e.invokeAll(l, SHORT_DELAY_MS, MILLISECONDS);
+ assertEquals(3, futures.size());
+ Iterator<Future<String>> it = futures.iterator();
+ Future<String> f1 = it.next();
+ Future<String> f2 = it.next();
+ Future<String> f3 = it.next();
+ assertTrue(f1.isDone());
+ assertTrue(f2.isDone());
+ assertTrue(f3.isDone());
+ assertFalse(f1.isCancelled());
+ assertTrue(f2.isCancelled());
+ } finally {
+ joinPool(e);
+ }
+ }
+
+}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/ScheduledExecutorTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/ScheduledExecutorTest.java
index 14e98b4..ff1796e 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/ScheduledExecutorTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/ScheduledExecutorTest.java
@@ -2,15 +2,16 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.*;
import java.util.concurrent.*;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.concurrent.atomic.*;
public class ScheduledExecutorTest extends JSR166TestCase {
@@ -22,86 +23,62 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* execute successfully executes a runnable
*/
- public void testExecute() {
- try {
- TrackedShortRunnable runnable =new TrackedShortRunnable();
- ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
- p1.execute(runnable);
- assertFalse(runnable.done);
- Thread.sleep(SHORT_DELAY_MS);
- try { p1.shutdown(); } catch(SecurityException ok) { return; }
- try {
- Thread.sleep(MEDIUM_DELAY_MS);
- } catch(InterruptedException e){
- unexpectedException();
- }
- assertTrue(runnable.done);
- try { p1.shutdown(); } catch(SecurityException ok) { return; }
- joinPool(p1);
- }
- catch(Exception e){
- unexpectedException();
- }
-
+ public void testExecute() throws InterruptedException {
+ TrackedShortRunnable runnable =new TrackedShortRunnable();
+ ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
+ p1.execute(runnable);
+ assertFalse(runnable.done);
+ Thread.sleep(SHORT_DELAY_MS);
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
+ Thread.sleep(MEDIUM_DELAY_MS);
+ assertTrue(runnable.done);
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
+ joinPool(p1);
}
/**
* delayed schedule of callable successfully executes after delay
*/
- public void testSchedule1() {
- try {
- TrackedCallable callable = new TrackedCallable();
- ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
- Future f = p1.schedule(callable, SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
- assertFalse(callable.done);
- Thread.sleep(MEDIUM_DELAY_MS);
- assertTrue(callable.done);
- assertEquals(Boolean.TRUE, f.get());
- try { p1.shutdown(); } catch(SecurityException ok) { return; }
- joinPool(p1);
- } catch(RejectedExecutionException e){}
- catch(Exception e){
- e.printStackTrace();
- unexpectedException();
- }
+ public void testSchedule1() throws Exception {
+ TrackedCallable callable = new TrackedCallable();
+ ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
+ Future f = p1.schedule(callable, SHORT_DELAY_MS, MILLISECONDS);
+ assertFalse(callable.done);
+ Thread.sleep(MEDIUM_DELAY_MS);
+ assertTrue(callable.done);
+ assertEquals(Boolean.TRUE, f.get());
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
+ joinPool(p1);
}
/**
* delayed schedule of runnable successfully executes after delay
*/
- public void testSchedule3() {
- try {
- TrackedShortRunnable runnable = new TrackedShortRunnable();
- ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
- p1.schedule(runnable, SMALL_DELAY_MS, TimeUnit.MILLISECONDS);
- Thread.sleep(SHORT_DELAY_MS);
- assertFalse(runnable.done);
- Thread.sleep(MEDIUM_DELAY_MS);
- assertTrue(runnable.done);
- try { p1.shutdown(); } catch(SecurityException ok) { return; }
- joinPool(p1);
- } catch(Exception e){
- unexpectedException();
- }
+ public void testSchedule3() throws InterruptedException {
+ TrackedShortRunnable runnable = new TrackedShortRunnable();
+ ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
+ p1.schedule(runnable, SMALL_DELAY_MS, MILLISECONDS);
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(runnable.done);
+ Thread.sleep(MEDIUM_DELAY_MS);
+ assertTrue(runnable.done);
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
+ joinPool(p1);
}
-
+
/**
* scheduleAtFixedRate executes runnable after given initial delay
*/
- public void testSchedule4() {
- try {
- TrackedShortRunnable runnable = new TrackedShortRunnable();
- ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
- ScheduledFuture h = p1.scheduleAtFixedRate(runnable, SHORT_DELAY_MS, SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
- assertFalse(runnable.done);
- Thread.sleep(MEDIUM_DELAY_MS);
- assertTrue(runnable.done);
- h.cancel(true);
- joinPool(p1);
- } catch(Exception e){
- unexpectedException();
- }
+ public void testSchedule4() throws InterruptedException {
+ TrackedShortRunnable runnable = new TrackedShortRunnable();
+ ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
+ ScheduledFuture h = p1.scheduleAtFixedRate(runnable, SHORT_DELAY_MS, SHORT_DELAY_MS, MILLISECONDS);
+ assertFalse(runnable.done);
+ Thread.sleep(MEDIUM_DELAY_MS);
+ assertTrue(runnable.done);
+ h.cancel(true);
+ joinPool(p1);
}
static class RunnableCounter implements Runnable {
@@ -112,126 +89,107 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* scheduleWithFixedDelay executes runnable after given initial delay
*/
- public void testSchedule5() {
- try {
- TrackedShortRunnable runnable = new TrackedShortRunnable();
- ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
- ScheduledFuture h = p1.scheduleWithFixedDelay(runnable, SHORT_DELAY_MS, SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
- assertFalse(runnable.done);
- Thread.sleep(MEDIUM_DELAY_MS);
- assertTrue(runnable.done);
- h.cancel(true);
- joinPool(p1);
- } catch(Exception e){
- unexpectedException();
- }
+ public void testSchedule5() throws InterruptedException {
+ TrackedShortRunnable runnable = new TrackedShortRunnable();
+ ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
+ ScheduledFuture h = p1.scheduleWithFixedDelay(runnable, SHORT_DELAY_MS, SHORT_DELAY_MS, MILLISECONDS);
+ assertFalse(runnable.done);
+ Thread.sleep(MEDIUM_DELAY_MS);
+ assertTrue(runnable.done);
+ h.cancel(true);
+ joinPool(p1);
}
-
+
/**
* scheduleAtFixedRate executes series of tasks at given rate
*/
- public void testFixedRateSequence() {
- try {
- ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
- RunnableCounter counter = new RunnableCounter();
- ScheduledFuture h =
- p1.scheduleAtFixedRate(counter, 0, 1, TimeUnit.MILLISECONDS);
- Thread.sleep(SMALL_DELAY_MS);
- h.cancel(true);
- int c = counter.count.get();
- // By time scaling conventions, we must have at least
- // an execution per SHORT delay, but no more than one SHORT more
- assertTrue(c >= SMALL_DELAY_MS / SHORT_DELAY_MS);
- assertTrue(c <= SMALL_DELAY_MS + SHORT_DELAY_MS);
- joinPool(p1);
- } catch(Exception e){
- unexpectedException();
- }
+ public void testFixedRateSequence() throws InterruptedException {
+ ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
+ RunnableCounter counter = new RunnableCounter();
+ ScheduledFuture h =
+ p1.scheduleAtFixedRate(counter, 0, 1, MILLISECONDS);
+ Thread.sleep(SMALL_DELAY_MS);
+ h.cancel(true);
+ int c = counter.count.get();
+ // By time scaling conventions, we must have at least
+ // an execution per SHORT delay, but no more than one SHORT more
+ assertTrue(c >= SMALL_DELAY_MS / SHORT_DELAY_MS);
+ assertTrue(c <= SMALL_DELAY_MS + SHORT_DELAY_MS);
+ joinPool(p1);
}
/**
* scheduleWithFixedDelay executes series of tasks with given period
*/
- public void testFixedDelaySequence() {
- try {
- ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
- RunnableCounter counter = new RunnableCounter();
- ScheduledFuture h =
- p1.scheduleWithFixedDelay(counter, 0, 1, TimeUnit.MILLISECONDS);
- Thread.sleep(SMALL_DELAY_MS);
- h.cancel(true);
- int c = counter.count.get();
- assertTrue(c >= SMALL_DELAY_MS / SHORT_DELAY_MS);
- assertTrue(c <= SMALL_DELAY_MS + SHORT_DELAY_MS);
- joinPool(p1);
- } catch(Exception e){
- unexpectedException();
- }
+ public void testFixedDelaySequence() throws InterruptedException {
+ ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
+ RunnableCounter counter = new RunnableCounter();
+ ScheduledFuture h =
+ p1.scheduleWithFixedDelay(counter, 0, 1, MILLISECONDS);
+ Thread.sleep(SMALL_DELAY_MS);
+ h.cancel(true);
+ int c = counter.count.get();
+ assertTrue(c >= SMALL_DELAY_MS / SHORT_DELAY_MS);
+ assertTrue(c <= SMALL_DELAY_MS + SHORT_DELAY_MS);
+ joinPool(p1);
}
/**
* execute (null) throws NPE
*/
- public void testExecuteNull() {
+ public void testExecuteNull() throws InterruptedException {
ScheduledThreadPoolExecutor se = null;
try {
se = new ScheduledThreadPoolExecutor(1);
se.execute(null);
shouldThrow();
- } catch(NullPointerException success){}
- catch(Exception e){
- unexpectedException();
- }
-
+ } catch (NullPointerException success) {}
+
joinPool(se);
}
/**
* schedule (null) throws NPE
*/
- public void testScheduleNull() {
+ public void testScheduleNull() throws InterruptedException {
ScheduledThreadPoolExecutor se = new ScheduledThreadPoolExecutor(1);
try {
TrackedCallable callable = null;
- Future f = se.schedule(callable, SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
+ Future f = se.schedule(callable, SHORT_DELAY_MS, MILLISECONDS);
shouldThrow();
- } catch(NullPointerException success){}
- catch(Exception e){
- unexpectedException();
- }
+ } catch (NullPointerException success) {}
joinPool(se);
}
-
+
/**
* execute throws RejectedExecutionException if shutdown
*/
- public void testSchedule1_RejectedExecutionException() {
+ public void testSchedule1_RejectedExecutionException() throws InterruptedException {
ScheduledThreadPoolExecutor se = new ScheduledThreadPoolExecutor(1);
try {
se.shutdown();
se.schedule(new NoOpRunnable(),
- MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ MEDIUM_DELAY_MS, MILLISECONDS);
shouldThrow();
- } catch(RejectedExecutionException success){
+ } catch (RejectedExecutionException success) {
} catch (SecurityException ok) {
}
-
- joinPool(se);
+ joinPool(se);
}
/**
* schedule throws RejectedExecutionException if shutdown
*/
- public void testSchedule2_RejectedExecutionException() {
+ public void testSchedule2_RejectedExecutionException() throws InterruptedException {
ScheduledThreadPoolExecutor se = new ScheduledThreadPoolExecutor(1);
try {
se.shutdown();
se.schedule(new NoOpCallable(),
- MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ MEDIUM_DELAY_MS, MILLISECONDS);
shouldThrow();
- } catch(RejectedExecutionException success){
+ } catch (RejectedExecutionException success) {
} catch (SecurityException ok) {
}
joinPool(se);
@@ -240,14 +198,14 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* schedule callable throws RejectedExecutionException if shutdown
*/
- public void testSchedule3_RejectedExecutionException() {
+ public void testSchedule3_RejectedExecutionException() throws InterruptedException {
ScheduledThreadPoolExecutor se = new ScheduledThreadPoolExecutor(1);
try {
se.shutdown();
se.schedule(new NoOpCallable(),
- MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ MEDIUM_DELAY_MS, MILLISECONDS);
shouldThrow();
- } catch(RejectedExecutionException success){
+ } catch (RejectedExecutionException success) {
} catch (SecurityException ok) {
}
joinPool(se);
@@ -256,32 +214,32 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* scheduleAtFixedRate throws RejectedExecutionException if shutdown
*/
- public void testScheduleAtFixedRate1_RejectedExecutionException() {
+ public void testScheduleAtFixedRate1_RejectedExecutionException() throws InterruptedException {
ScheduledThreadPoolExecutor se = new ScheduledThreadPoolExecutor(1);
try {
se.shutdown();
se.scheduleAtFixedRate(new NoOpRunnable(),
- MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS);
shouldThrow();
- } catch(RejectedExecutionException success){
+ } catch (RejectedExecutionException success) {
} catch (SecurityException ok) {
- }
+ }
joinPool(se);
}
-
+
/**
* scheduleWithFixedDelay throws RejectedExecutionException if shutdown
*/
- public void testScheduleWithFixedDelay1_RejectedExecutionException() {
+ public void testScheduleWithFixedDelay1_RejectedExecutionException() throws InterruptedException {
ScheduledThreadPoolExecutor se = new ScheduledThreadPoolExecutor(1);
try {
se.shutdown();
se.scheduleWithFixedDelay(new NoOpRunnable(),
- MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ MEDIUM_DELAY_MS, MEDIUM_DELAY_MS, MILLISECONDS);
shouldThrow();
- } catch(RejectedExecutionException success){
+ } catch (RejectedExecutionException success) {
} catch (SecurityException ok) {
- }
+ }
joinPool(se);
}
@@ -289,107 +247,91 @@ public class ScheduledExecutorTest extends JSR166TestCase {
* getActiveCount increases but doesn't overestimate, when a
* thread becomes active
*/
- public void testGetActiveCount() {
+ public void testGetActiveCount() throws InterruptedException {
ScheduledThreadPoolExecutor p2 = new ScheduledThreadPoolExecutor(2);
assertEquals(0, p2.getActiveCount());
p2.execute(new SmallRunnable());
- try {
- Thread.sleep(SHORT_DELAY_MS);
- } catch(Exception e){
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
assertEquals(1, p2.getActiveCount());
joinPool(p2);
}
-
+
/**
* getCompletedTaskCount increases, but doesn't overestimate,
* when tasks complete
*/
- public void testGetCompletedTaskCount() {
+ public void testGetCompletedTaskCount() throws InterruptedException {
ScheduledThreadPoolExecutor p2 = new ScheduledThreadPoolExecutor(2);
assertEquals(0, p2.getCompletedTaskCount());
p2.execute(new SmallRunnable());
- try {
- Thread.sleep(MEDIUM_DELAY_MS);
- } catch(Exception e){
- unexpectedException();
- }
+ Thread.sleep(MEDIUM_DELAY_MS);
assertEquals(1, p2.getCompletedTaskCount());
joinPool(p2);
}
-
+
/**
- * getCorePoolSize returns size given in constructor if not otherwise set
+ * getCorePoolSize returns size given in constructor if not otherwise set
*/
- public void testGetCorePoolSize() {
+ public void testGetCorePoolSize() throws InterruptedException {
ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
assertEquals(1, p1.getCorePoolSize());
joinPool(p1);
}
-
+
/**
* getLargestPoolSize increases, but doesn't overestimate, when
* multiple threads active
*/
- public void testGetLargestPoolSize() {
+ public void testGetLargestPoolSize() throws InterruptedException {
ScheduledThreadPoolExecutor p2 = new ScheduledThreadPoolExecutor(2);
assertEquals(0, p2.getLargestPoolSize());
p2.execute(new SmallRunnable());
p2.execute(new SmallRunnable());
- try {
- Thread.sleep(SHORT_DELAY_MS);
- } catch(Exception e){
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
assertEquals(2, p2.getLargestPoolSize());
joinPool(p2);
}
-
+
/**
* getPoolSize increases, but doesn't overestimate, when threads
* become active
*/
- public void testGetPoolSize() {
+ public void testGetPoolSize() throws InterruptedException {
ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
assertEquals(0, p1.getPoolSize());
p1.execute(new SmallRunnable());
assertEquals(1, p1.getPoolSize());
joinPool(p1);
}
-
+
/**
* getTaskCount increases, but doesn't overestimate, when tasks
* submitted
*/
- public void testGetTaskCount() {
+ public void testGetTaskCount() throws InterruptedException {
ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
assertEquals(0, p1.getTaskCount());
- for(int i = 0; i < 5; i++)
+ for (int i = 0; i < 5; i++)
p1.execute(new SmallRunnable());
- try {
- Thread.sleep(SHORT_DELAY_MS);
- } catch(Exception e){
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
assertEquals(5, p1.getTaskCount());
joinPool(p1);
}
- /**
+ /**
* getThreadFactory returns factory in constructor if not set
*/
- public void testGetThreadFactory() {
+ public void testGetThreadFactory() throws InterruptedException {
ThreadFactory tf = new SimpleThreadFactory();
ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1, tf);
assertSame(tf, p.getThreadFactory());
joinPool(p);
}
- /**
+ /**
* setThreadFactory sets the thread factory returned by getThreadFactory
*/
- public void testSetThreadFactory() {
+ public void testSetThreadFactory() throws InterruptedException {
ThreadFactory tf = new SimpleThreadFactory();
ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
p.setThreadFactory(tf);
@@ -397,10 +339,10 @@ public class ScheduledExecutorTest extends JSR166TestCase {
joinPool(p);
}
- /**
+ /**
* setThreadFactory(null) throws NPE
*/
- public void testSetThreadFactoryNull() {
+ public void testSetThreadFactoryNull() throws InterruptedException {
ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1);
try {
p.setThreadFactory(null);
@@ -410,78 +352,69 @@ public class ScheduledExecutorTest extends JSR166TestCase {
joinPool(p);
}
}
-
+
/**
* is isShutDown is false before shutdown, true after
*/
public void testIsShutdown() {
-
+
ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
try {
assertFalse(p1.isShutdown());
}
finally {
- try { p1.shutdown(); } catch(SecurityException ok) { return; }
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
}
assertTrue(p1.isShutdown());
}
-
+
/**
* isTerminated is false before termination, true after
*/
- public void testIsTerminated() {
+ public void testIsTerminated() throws InterruptedException {
ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
try {
p1.execute(new SmallRunnable());
} finally {
- try { p1.shutdown(); } catch(SecurityException ok) { return; }
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
}
- try {
- assertTrue(p1.awaitTermination(LONG_DELAY_MS, TimeUnit.MILLISECONDS));
- assertTrue(p1.isTerminated());
- } catch(Exception e){
- unexpectedException();
- }
+ assertTrue(p1.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
+ assertTrue(p1.isTerminated());
}
/**
* isTerminating is not true when running or when terminated
*/
- public void testIsTerminating() {
+ public void testIsTerminating() throws InterruptedException {
ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
assertFalse(p1.isTerminating());
try {
p1.execute(new SmallRunnable());
assertFalse(p1.isTerminating());
} finally {
- try { p1.shutdown(); } catch(SecurityException ok) { return; }
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
}
- try {
- assertTrue(p1.awaitTermination(LONG_DELAY_MS, TimeUnit.MILLISECONDS));
- assertTrue(p1.isTerminated());
- assertFalse(p1.isTerminating());
- } catch(Exception e){
- unexpectedException();
- }
+
+ assertTrue(p1.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
+ assertTrue(p1.isTerminated());
+ assertFalse(p1.isTerminating());
}
/**
* getQueue returns the work queue, which contains queued tasks
*/
- public void testGetQueue() {
+ public void testGetQueue() throws InterruptedException {
ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
ScheduledFuture[] tasks = new ScheduledFuture[5];
- for(int i = 0; i < 5; i++){
- tasks[i] = p1.schedule(new SmallPossiblyInterruptedRunnable(), 1, TimeUnit.MILLISECONDS);
+ for (int i = 0; i < 5; i++) {
+ tasks[i] = p1.schedule(new SmallPossiblyInterruptedRunnable(), 1, MILLISECONDS);
}
try {
Thread.sleep(SHORT_DELAY_MS);
BlockingQueue<Runnable> q = p1.getQueue();
assertTrue(q.contains(tasks[4]));
assertFalse(q.contains(tasks[0]));
- } catch(Exception e) {
- unexpectedException();
} finally {
joinPool(p1);
}
@@ -490,11 +423,11 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* remove(task) removes queued task, and fails to remove active task
*/
- public void testRemove() {
+ public void testRemove() throws InterruptedException {
ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
ScheduledFuture[] tasks = new ScheduledFuture[5];
- for(int i = 0; i < 5; i++){
- tasks[i] = p1.schedule(new SmallPossiblyInterruptedRunnable(), 1, TimeUnit.MILLISECONDS);
+ for (int i = 0; i < 5; i++) {
+ tasks[i] = p1.schedule(new SmallPossiblyInterruptedRunnable(), 1, MILLISECONDS);
}
try {
Thread.sleep(SHORT_DELAY_MS);
@@ -508,8 +441,6 @@ public class ScheduledExecutorTest extends JSR166TestCase {
assertTrue(q.contains((Runnable)tasks[3]));
assertTrue(p1.remove((Runnable)tasks[3]));
assertFalse(q.contains((Runnable)tasks[3]));
- } catch(Exception e) {
- unexpectedException();
} finally {
joinPool(p1);
}
@@ -518,11 +449,11 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* purge removes cancelled tasks from the queue
*/
- public void testPurge() {
+ public void testPurge() throws InterruptedException {
ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
ScheduledFuture[] tasks = new ScheduledFuture[5];
- for(int i = 0; i < 5; i++){
- tasks[i] = p1.schedule(new SmallPossiblyInterruptedRunnable(), SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
+ for (int i = 0; i < 5; i++) {
+ tasks[i] = p1.schedule(new SmallPossiblyInterruptedRunnable(), SHORT_DELAY_MS, MILLISECONDS);
}
try {
int max = 5;
@@ -539,8 +470,6 @@ public class ScheduledExecutorTest extends JSR166TestCase {
Thread.sleep(1);
}
assertTrue(k < SMALL_DELAY_MS);
- } catch(Exception e) {
- unexpectedException();
} finally {
joinPool(p1);
}
@@ -549,14 +478,14 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* shutDownNow returns a list containing tasks that were not run
*/
- public void testShutDownNow() {
+ public void testShutDownNow() throws InterruptedException {
ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
- for(int i = 0; i < 5; i++)
- p1.schedule(new SmallPossiblyInterruptedRunnable(), SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
+ for (int i = 0; i < 5; i++)
+ p1.schedule(new SmallPossiblyInterruptedRunnable(), SHORT_DELAY_MS, MILLISECONDS);
List l;
try {
l = p1.shutdownNow();
- } catch (SecurityException ok) {
+ } catch (SecurityException ok) {
return;
}
assertTrue(p1.isShutdown());
@@ -568,31 +497,25 @@ public class ScheduledExecutorTest extends JSR166TestCase {
* In default setting, shutdown cancels periodic but not delayed
* tasks at shutdown
*/
- public void testShutDown1() {
- try {
- ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
- assertTrue(p1.getExecuteExistingDelayedTasksAfterShutdownPolicy());
- assertFalse(p1.getContinueExistingPeriodicTasksAfterShutdownPolicy());
-
- ScheduledFuture[] tasks = new ScheduledFuture[5];
- for(int i = 0; i < 5; i++)
- tasks[i] = p1.schedule(new NoOpRunnable(), SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
- try { p1.shutdown(); } catch(SecurityException ok) { return; }
- BlockingQueue q = p1.getQueue();
- for (Iterator it = q.iterator(); it.hasNext();) {
- ScheduledFuture t = (ScheduledFuture)it.next();
- assertFalse(t.isCancelled());
- }
- assertTrue(p1.isShutdown());
- Thread.sleep(SMALL_DELAY_MS);
- for (int i = 0; i < 5; ++i) {
- assertTrue(tasks[i].isDone());
- assertFalse(tasks[i].isCancelled());
- }
-
+ public void testShutDown1() throws InterruptedException {
+ ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
+ assertTrue(p1.getExecuteExistingDelayedTasksAfterShutdownPolicy());
+ assertFalse(p1.getContinueExistingPeriodicTasksAfterShutdownPolicy());
+
+ ScheduledFuture[] tasks = new ScheduledFuture[5];
+ for (int i = 0; i < 5; i++)
+ tasks[i] = p1.schedule(new NoOpRunnable(), SHORT_DELAY_MS, MILLISECONDS);
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
+ BlockingQueue q = p1.getQueue();
+ for (Iterator it = q.iterator(); it.hasNext();) {
+ ScheduledFuture t = (ScheduledFuture)it.next();
+ assertFalse(t.isCancelled());
}
- catch(Exception ex) {
- unexpectedException();
+ assertTrue(p1.isShutdown());
+ Thread.sleep(SMALL_DELAY_MS);
+ for (int i = 0; i < 5; ++i) {
+ assertTrue(tasks[i].isDone());
+ assertFalse(tasks[i].isCancelled());
}
}
@@ -601,23 +524,18 @@ public class ScheduledExecutorTest extends JSR166TestCase {
* If setExecuteExistingDelayedTasksAfterShutdownPolicy is false,
* delayed tasks are cancelled at shutdown
*/
- public void testShutDown2() {
- try {
- ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
- p1.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
- ScheduledFuture[] tasks = new ScheduledFuture[5];
- for(int i = 0; i < 5; i++)
- tasks[i] = p1.schedule(new NoOpRunnable(), SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
- try { p1.shutdown(); } catch(SecurityException ok) { return; }
- assertTrue(p1.isShutdown());
- BlockingQueue q = p1.getQueue();
- assertTrue(q.isEmpty());
- Thread.sleep(SMALL_DELAY_MS);
- assertTrue(p1.isTerminated());
- }
- catch(Exception ex) {
- unexpectedException();
- }
+ public void testShutDown2() throws InterruptedException {
+ ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
+ p1.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
+ ScheduledFuture[] tasks = new ScheduledFuture[5];
+ for (int i = 0; i < 5; i++)
+ tasks[i] = p1.schedule(new NoOpRunnable(), SHORT_DELAY_MS, MILLISECONDS);
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
+ assertTrue(p1.isShutdown());
+ BlockingQueue q = p1.getQueue();
+ assertTrue(q.isEmpty());
+ Thread.sleep(SMALL_DELAY_MS);
+ assertTrue(p1.isTerminated());
}
@@ -625,36 +543,31 @@ public class ScheduledExecutorTest extends JSR166TestCase {
* If setContinueExistingPeriodicTasksAfterShutdownPolicy is set false,
* periodic tasks are not cancelled at shutdown
*/
- public void testShutDown3() {
- try {
- ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
- p1.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
- ScheduledFuture task =
- p1.scheduleAtFixedRate(new NoOpRunnable(), 5, 5, TimeUnit.MILLISECONDS);
- try { p1.shutdown(); } catch(SecurityException ok) { return; }
- assertTrue(p1.isShutdown());
- BlockingQueue q = p1.getQueue();
- assertTrue(q.isEmpty());
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(p1.isTerminated());
- }
- catch(Exception ex) {
- unexpectedException();
- }
+ public void testShutDown3() throws InterruptedException {
+ ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
+ p1.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
+ ScheduledFuture task =
+ p1.scheduleAtFixedRate(new NoOpRunnable(), 5, 5, MILLISECONDS);
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
+ assertTrue(p1.isShutdown());
+ BlockingQueue q = p1.getQueue();
+ assertTrue(q.isEmpty());
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(p1.isTerminated());
}
/**
* if setContinueExistingPeriodicTasksAfterShutdownPolicy is true,
* periodic tasks are cancelled at shutdown
*/
- public void testShutDown4() {
+ public void testShutDown4() throws InterruptedException {
ScheduledThreadPoolExecutor p1 = new ScheduledThreadPoolExecutor(1);
try {
p1.setContinueExistingPeriodicTasksAfterShutdownPolicy(true);
ScheduledFuture task =
- p1.scheduleAtFixedRate(new NoOpRunnable(), 1, 1, TimeUnit.MILLISECONDS);
+ p1.scheduleAtFixedRate(new NoOpRunnable(), 1, 1, MILLISECONDS);
assertFalse(task.isCancelled());
- try { p1.shutdown(); } catch(SecurityException ok) { return; }
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
assertFalse(task.isCancelled());
assertFalse(p1.isTerminated());
assertTrue(p1.isShutdown());
@@ -665,10 +578,7 @@ public class ScheduledExecutorTest extends JSR166TestCase {
Thread.sleep(SHORT_DELAY_MS);
assertTrue(p1.isTerminated());
}
- catch(Exception ex) {
- unexpectedException();
- }
- finally {
+ finally {
joinPool(p1);
}
}
@@ -676,18 +586,12 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* completed submit of callable returns result
*/
- public void testSubmitCallable() {
+ public void testSubmitCallable() throws Exception {
ExecutorService e = new ScheduledThreadPoolExecutor(2);
try {
Future<String> future = e.submit(new StringTask());
String result = future.get();
assertSame(TEST_STRING, result);
- }
- catch (ExecutionException ex) {
- unexpectedException();
- }
- catch (InterruptedException ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -696,18 +600,12 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* completed submit of runnable returns successfully
*/
- public void testSubmitRunnable() {
+ public void testSubmitRunnable() throws Exception {
ExecutorService e = new ScheduledThreadPoolExecutor(2);
try {
Future<?> future = e.submit(new NoOpRunnable());
future.get();
assertTrue(future.isDone());
- }
- catch (ExecutionException ex) {
- unexpectedException();
- }
- catch (InterruptedException ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -716,18 +614,12 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* completed submit of (runnable, result) returns result
*/
- public void testSubmitRunnable2() {
+ public void testSubmitRunnable2() throws Exception {
ExecutorService e = new ScheduledThreadPoolExecutor(2);
try {
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();
} finally {
joinPool(e);
}
@@ -736,13 +628,12 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* invokeAny(null) throws NPE
*/
- public void testInvokeAny1() {
+ public void testInvokeAny1() throws Exception {
ExecutorService e = new ScheduledThreadPoolExecutor(2);
try {
e.invokeAny(null);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -751,13 +642,12 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* invokeAny(empty collection) throws IAE
*/
- public void testInvokeAny2() {
+ public void testInvokeAny2() throws Exception {
ExecutorService e = new ScheduledThreadPoolExecutor(2);
try {
e.invokeAny(new ArrayList<Callable<String>>());
+ shouldThrow();
} catch (IllegalArgumentException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -766,17 +656,18 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* invokeAny(c) throws NPE if c has null elements
*/
- public void testInvokeAny3() {
+ public void testInvokeAny3() throws Exception {
+ CountDownLatch latch = new CountDownLatch(1);
ExecutorService e = new ScheduledThreadPoolExecutor(2);
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(latchAwaitingStringTask(latch));
+ l.add(null);
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
- l.add(new StringTask());
- l.add(null);
e.invokeAny(l);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
+ latch.countDown();
joinPool(e);
}
}
@@ -784,15 +675,15 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* invokeAny(c) throws ExecutionException if no task completes
*/
- public void testInvokeAny4() {
+ public void testInvokeAny4() throws Exception {
ExecutorService e = new ScheduledThreadPoolExecutor(2);
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new NPETask());
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
- l.add(new NPETask());
e.invokeAny(l);
+ shouldThrow();
} catch (ExecutionException success) {
- } catch(Exception ex) {
- unexpectedException();
+ assertTrue(success.getCause() instanceof NullPointerException);
} finally {
joinPool(e);
}
@@ -801,17 +692,14 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* invokeAny(c) returns result of some task
*/
- public void testInvokeAny5() {
+ public void testInvokeAny5() throws Exception {
ExecutorService e = new ScheduledThreadPoolExecutor(2);
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<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);
}
@@ -820,13 +708,12 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* invokeAll(null) throws NPE
*/
- public void testInvokeAll1() {
+ public void testInvokeAll1() throws Exception {
ExecutorService e = new ScheduledThreadPoolExecutor(2);
try {
e.invokeAll(null);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -835,13 +722,11 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* invokeAll(empty collection) returns empty collection
*/
- public void testInvokeAll2() {
+ public void testInvokeAll2() throws Exception {
ExecutorService e = new ScheduledThreadPoolExecutor(2);
try {
List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>());
assertTrue(r.isEmpty());
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -850,16 +735,15 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* invokeAll(c) throws NPE if c has null elements
*/
- public void testInvokeAll3() {
+ public void testInvokeAll3() throws Exception {
ExecutorService e = new ScheduledThreadPoolExecutor(2);
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(null);
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
- l.add(new StringTask());
- l.add(null);
e.invokeAll(l);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -868,18 +752,17 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* get of invokeAll(c) throws exception on failed task
*/
- public void testInvokeAll4() {
+ public void testInvokeAll4() throws Exception {
ExecutorService e = new ScheduledThreadPoolExecutor(2);
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new NPETask());
+ List<Future<String>> futures = e.invokeAll(l);
+ assertEquals(1, futures.size());
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();
+ futures.get(0).get();
+ shouldThrow();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof NullPointerException);
} finally {
joinPool(e);
}
@@ -888,19 +771,16 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* invokeAll(c) returns results of all completed tasks
*/
- public void testInvokeAll5() {
+ public void testInvokeAll5() throws Exception {
ExecutorService e = new ScheduledThreadPoolExecutor(2);
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<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();
+ List<Future<String>> futures = e.invokeAll(l);
+ assertEquals(2, futures.size());
+ for (Future<String> future : futures)
+ assertSame(TEST_STRING, future.get());
} finally {
joinPool(e);
}
@@ -909,13 +789,12 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* timed invokeAny(null) throws NPE
*/
- public void testTimedInvokeAny1() {
+ public void testTimedInvokeAny1() throws Exception {
ExecutorService e = new ScheduledThreadPoolExecutor(2);
try {
- e.invokeAny(null, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -924,15 +803,14 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* timed invokeAny(,,null) throws NPE
*/
- public void testTimedInvokeAnyNullTimeUnit() {
+ public void testTimedInvokeAnyNullTimeUnit() throws Exception {
ExecutorService e = new ScheduledThreadPoolExecutor(2);
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
- l.add(new StringTask());
e.invokeAny(l, MEDIUM_DELAY_MS, null);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -941,13 +819,12 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* timed invokeAny(empty collection) throws IAE
*/
- public void testTimedInvokeAny2() {
+ public void testTimedInvokeAny2() throws Exception {
ExecutorService e = new ScheduledThreadPoolExecutor(2);
try {
- e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
} catch (IllegalArgumentException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -956,18 +833,18 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* timed invokeAny(c) throws NPE if c has null elements
*/
- public void testTimedInvokeAny3() {
+ public void testTimedInvokeAny3() throws Exception {
+ CountDownLatch latch = new CountDownLatch(1);
ExecutorService e = new ScheduledThreadPoolExecutor(2);
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(latchAwaitingStringTask(latch));
+ l.add(null);
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
- l.add(new StringTask());
- l.add(null);
- e.invokeAny(l, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- ex.printStackTrace();
- unexpectedException();
} finally {
+ latch.countDown();
joinPool(e);
}
}
@@ -975,15 +852,15 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* timed invokeAny(c) throws ExecutionException if no task completes
*/
- public void testTimedInvokeAny4() {
+ public void testTimedInvokeAny4() throws Exception {
ExecutorService e = new ScheduledThreadPoolExecutor(2);
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new NPETask());
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();
+ e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof NullPointerException);
} finally {
joinPool(e);
}
@@ -992,17 +869,14 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* timed invokeAny(c) returns result of some task
*/
- public void testTimedInvokeAny5() {
+ public void testTimedInvokeAny5() throws Exception {
ExecutorService e = new ScheduledThreadPoolExecutor(2);
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<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);
+ String result = e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
assertSame(TEST_STRING, result);
- } catch (ExecutionException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -1011,13 +885,12 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* timed invokeAll(null) throws NPE
*/
- public void testTimedInvokeAll1() {
+ public void testTimedInvokeAll1() throws Exception {
ExecutorService e = new ScheduledThreadPoolExecutor(2);
try {
- e.invokeAll(null, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -1026,15 +899,14 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* timed invokeAll(,,null) throws NPE
*/
- public void testTimedInvokeAllNullTimeUnit() {
+ public void testTimedInvokeAllNullTimeUnit() throws Exception {
ExecutorService e = new ScheduledThreadPoolExecutor(2);
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
- l.add(new StringTask());
e.invokeAll(l, MEDIUM_DELAY_MS, null);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -1043,13 +915,11 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* timed invokeAll(empty collection) returns empty collection
*/
- public void testTimedInvokeAll2() {
+ public void testTimedInvokeAll2() throws Exception {
ExecutorService e = new ScheduledThreadPoolExecutor(2);
try {
- List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
assertTrue(r.isEmpty());
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -1058,16 +928,15 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* timed invokeAll(c) throws NPE if c has null elements
*/
- public void testTimedInvokeAll3() {
+ public void testTimedInvokeAll3() throws Exception {
ExecutorService e = new ScheduledThreadPoolExecutor(2);
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(null);
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
- l.add(new StringTask());
- l.add(null);
- e.invokeAll(l, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -1076,18 +945,18 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* get of element of invokeAll(c) throws exception on failed task
*/
- public void testTimedInvokeAll4() {
+ public void testTimedInvokeAll4() throws Exception {
ExecutorService e = new ScheduledThreadPoolExecutor(2);
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new NPETask());
+ List<Future<String>> futures =
+ e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ assertEquals(1, futures.size());
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();
+ futures.get(0).get();
+ shouldThrow();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof NullPointerException);
} finally {
joinPool(e);
}
@@ -1096,19 +965,17 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* timed invokeAll(c) returns results of all completed tasks
*/
- public void testTimedInvokeAll5() {
+ public void testTimedInvokeAll5() throws Exception {
ExecutorService e = new ScheduledThreadPoolExecutor(2);
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<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();
+ List<Future<String>> futures =
+ e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ assertEquals(2, futures.size());
+ for (Future<String> future : futures)
+ assertSame(TEST_STRING, future.get());
} finally {
joinPool(e);
}
@@ -1117,16 +984,17 @@ public class ScheduledExecutorTest extends JSR166TestCase {
/**
* timed invokeAll(c) cancels tasks not completed by timeout
*/
- public void testTimedInvokeAll6() {
+ public void testTimedInvokeAll6() throws Exception {
ExecutorService e = new ScheduledThreadPoolExecutor(2);
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<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, SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
- assertEquals(3, result.size());
- Iterator<Future<String>> it = result.iterator();
+ List<Future<String>> futures =
+ e.invokeAll(l, SHORT_DELAY_MS, MILLISECONDS);
+ assertEquals(3, futures.size());
+ Iterator<Future<String>> it = futures.iterator();
Future<String> f1 = it.next();
Future<String> f2 = it.next();
Future<String> f3 = it.next();
@@ -1135,8 +1003,6 @@ public class ScheduledExecutorTest extends JSR166TestCase {
assertTrue(f3.isDone());
assertFalse(f1.isCancelled());
assertTrue(f2.isCancelled());
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/SemaphoreTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/SemaphoreTest.java
index 3f2ff33..c27893c 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/SemaphoreTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/SemaphoreTest.java
@@ -2,15 +2,16 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.*;
import java.util.concurrent.*;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.io.*;
public class SemaphoreTest extends JSR166TestCase {
@@ -23,10 +24,10 @@ public class SemaphoreTest extends JSR166TestCase {
*/
static class PublicSemaphore extends Semaphore {
PublicSemaphore(int p, boolean f) { super(p, f); }
- public Collection<Thread> getQueuedThreads() {
- return super.getQueuedThreads();
+ public Collection<Thread> getQueuedThreads() {
+ return super.getQueuedThreads();
}
- public void reducePermits(int p) {
+ public void reducePermits(int p) {
super.reducePermits(p);
}
}
@@ -34,29 +35,26 @@ public class SemaphoreTest extends JSR166TestCase {
/**
* A runnable calling acquire
*/
- class InterruptibleLockRunnable implements Runnable {
+ class InterruptibleLockRunnable extends CheckedRunnable {
final Semaphore lock;
InterruptibleLockRunnable(Semaphore l) { lock = l; }
- public void run() {
+ public void realRun() {
try {
lock.acquire();
- } catch(InterruptedException success){}
+ }
+ catch (InterruptedException ignored) {}
}
}
/**
- * A runnable calling acquire that expects to be
- * interrupted
+ * A runnable calling acquire that expects to be interrupted
*/
- class InterruptedLockRunnable implements Runnable {
+ class InterruptedLockRunnable extends CheckedInterruptedRunnable {
final Semaphore lock;
InterruptedLockRunnable(Semaphore l) { lock = l; }
- public void run() {
- try {
- lock.acquire();
- threadShouldThrow();
- } catch(InterruptedException success){}
+ public void realRun() throws InterruptedException {
+ lock.acquire();
}
}
@@ -64,30 +62,24 @@ public class SemaphoreTest extends JSR166TestCase {
* Zero, negative, and positive initial values are allowed in constructor
*/
public void testConstructor() {
- Semaphore s0 = new Semaphore(0, false);
- assertEquals(0, s0.availablePermits());
- assertFalse(s0.isFair());
- Semaphore s1 = new Semaphore(-1, false);
- assertEquals(-1, s1.availablePermits());
- assertFalse(s1.isFair());
- Semaphore s2 = new Semaphore(-1, false);
- assertEquals(-1, s2.availablePermits());
- assertFalse(s2.isFair());
+ for (int permits : new int[] { -1, 0, 1 }) {
+ for (boolean fair : new boolean[] { false, true }) {
+ Semaphore s = new Semaphore(permits, fair);
+ assertEquals(permits, s.availablePermits());
+ assertEquals(fair, s.isFair());
+ }
+ }
}
/**
* Constructor without fairness argument behaves as nonfair
*/
public void testConstructor2() {
- Semaphore s0 = new Semaphore(0);
- assertEquals(0, s0.availablePermits());
- assertFalse(s0.isFair());
- Semaphore s1 = new Semaphore(-1);
- assertEquals(-1, s1.availablePermits());
- assertFalse(s1.isFair());
- Semaphore s2 = new Semaphore(-1);
- assertEquals(-1, s2.availablePermits());
- assertFalse(s2.isFair());
+ for (int permits : new int[] { -1, 0, 1 }) {
+ Semaphore s = new Semaphore(permits);
+ assertEquals(permits, s.availablePermits());
+ assertFalse(s.isFair());
+ }
}
/**
@@ -105,296 +97,245 @@ public class SemaphoreTest extends JSR166TestCase {
/**
* Acquire and release of semaphore succeed if initially available
*/
- public void testAcquireReleaseInSameThread() {
+ public void testAcquireReleaseInSameThread()
+ throws InterruptedException {
Semaphore s = new Semaphore(1, false);
- try {
- s.acquire();
- s.release();
- s.acquire();
- s.release();
- s.acquire();
- s.release();
- s.acquire();
- s.release();
- s.acquire();
- s.release();
- assertEquals(1, s.availablePermits());
- } catch( InterruptedException e){
- unexpectedException();
- }
+ s.acquire();
+ s.release();
+ s.acquire();
+ s.release();
+ s.acquire();
+ s.release();
+ s.acquire();
+ s.release();
+ s.acquire();
+ s.release();
+ assertEquals(1, s.availablePermits());
}
/**
* Uninterruptible acquire and release of semaphore succeed if
* initially available
*/
- public void testAcquireUninterruptiblyReleaseInSameThread() {
+ public void testAcquireUninterruptiblyReleaseInSameThread()
+ throws InterruptedException {
Semaphore s = new Semaphore(1, false);
- try {
- s.acquireUninterruptibly();
- s.release();
- s.acquireUninterruptibly();
- s.release();
- s.acquireUninterruptibly();
- s.release();
- s.acquireUninterruptibly();
- s.release();
- s.acquireUninterruptibly();
- s.release();
- assertEquals(1, s.availablePermits());
- } finally {
- }
+ s.acquireUninterruptibly();
+ s.release();
+ s.acquireUninterruptibly();
+ s.release();
+ s.acquireUninterruptibly();
+ s.release();
+ s.acquireUninterruptibly();
+ s.release();
+ s.acquireUninterruptibly();
+ s.release();
+ assertEquals(1, s.availablePermits());
}
/**
* Timed Acquire and release of semaphore succeed if
* initially available
*/
- public void testTimedAcquireReleaseInSameThread() {
+ public void testTimedAcquireReleaseInSameThread()
+ throws InterruptedException {
Semaphore s = new Semaphore(1, false);
- try {
- assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- s.release();
- assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- s.release();
- assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- s.release();
- assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- s.release();
- assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- s.release();
- assertEquals(1, s.availablePermits());
- } catch( InterruptedException e){
- unexpectedException();
- }
+ assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS));
+ s.release();
+ assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS));
+ s.release();
+ assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS));
+ s.release();
+ assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS));
+ s.release();
+ assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS));
+ s.release();
+ assertEquals(1, s.availablePermits());
}
/**
* A release in one thread enables an acquire in another thread
*/
- public void testAcquireReleaseInDifferentThreads() {
+ public void testAcquireReleaseInDifferentThreads()
+ throws InterruptedException {
final Semaphore s = new Semaphore(0, false);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- s.acquire();
- s.release();
- s.release();
- s.acquire();
- } catch(InterruptedException ie){
- threadUnexpectedException();
- }
- }
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- s.release();
- s.release();
- s.acquire();
- s.acquire();
- s.release();
- t.join();
- } catch( InterruptedException e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ s.acquire();
+ s.release();
+ s.release();
+ s.acquire();
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ s.release();
+ s.release();
+ s.acquire();
+ s.acquire();
+ s.release();
+ t.join();
}
/**
* A release in one thread enables an uninterruptible acquire in another thread
*/
- public void testUninterruptibleAcquireReleaseInDifferentThreads() {
+ public void testUninterruptibleAcquireReleaseInDifferentThreads()
+ throws InterruptedException {
final Semaphore s = new Semaphore(0, false);
- Thread t = new Thread(new Runnable() {
- public void run() {
- s.acquireUninterruptibly();
- s.release();
- s.release();
- s.acquireUninterruptibly();
- }
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- s.release();
- s.release();
- s.acquireUninterruptibly();
- s.acquireUninterruptibly();
- s.release();
- t.join();
- } catch( InterruptedException e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ s.acquireUninterruptibly();
+ s.release();
+ s.release();
+ s.acquireUninterruptibly();
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ s.release();
+ s.release();
+ s.acquireUninterruptibly();
+ s.acquireUninterruptibly();
+ s.release();
+ t.join();
}
/**
* A release in one thread enables a timed acquire in another thread
*/
- public void testTimedAcquireReleaseInDifferentThreads() {
+ public void testTimedAcquireReleaseInDifferentThreads()
+ throws InterruptedException {
final Semaphore s = new Semaphore(1, false);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- s.release();
- threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- s.release();
- threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
-
- } catch(InterruptedException ie){
- threadUnexpectedException();
- }
- }
- });
- try {
- t.start();
- assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- s.release();
- assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- s.release();
- s.release();
- t.join();
- } catch( InterruptedException e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ s.release();
+ assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS));
+ s.release();
+ assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS));
+ }});
+
+ t.start();
+ assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS));
+ s.release();
+ assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS));
+ s.release();
+ s.release();
+ t.join();
}
/**
* A waiting acquire blocks interruptibly
*/
- public void testAcquire_InterruptedException() {
+ public void testAcquire_InterruptedException()
+ throws InterruptedException {
final Semaphore s = new Semaphore(0, false);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- s.acquire();
- threadShouldThrow();
- } catch(InterruptedException success){}
- }
- });
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ s.acquire();
+ }});
+
t.start();
- try {
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- } catch(InterruptedException e){
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
-
+
/**
* A waiting timed acquire blocks interruptibly
*/
- public void testTryAcquire_InterruptedException() {
+ public void testTryAcquire_InterruptedException()
+ throws InterruptedException {
final Semaphore s = new Semaphore(0, false);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- s.tryAcquire(MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
- threadShouldThrow();
- } catch(InterruptedException success){
- }
- }
- });
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ s.tryAcquire(MEDIUM_DELAY_MS, MILLISECONDS);
+ }});
+
t.start();
- try {
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- } catch(InterruptedException e){
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* hasQueuedThreads reports whether there are waiting threads
*/
- public void testHasQueuedThreads() {
+ public void testHasQueuedThreads() throws InterruptedException {
final Semaphore lock = new Semaphore(1, false);
Thread t1 = new Thread(new InterruptedLockRunnable(lock));
Thread t2 = new Thread(new InterruptibleLockRunnable(lock));
- try {
- assertFalse(lock.hasQueuedThreads());
- lock.acquireUninterruptibly();
- t1.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(lock.hasQueuedThreads());
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(lock.hasQueuedThreads());
- t1.interrupt();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(lock.hasQueuedThreads());
- lock.release();
- Thread.sleep(SHORT_DELAY_MS);
- assertFalse(lock.hasQueuedThreads());
- t1.join();
- t2.join();
- } catch(Exception e){
- unexpectedException();
- }
- }
+ assertFalse(lock.hasQueuedThreads());
+ lock.acquireUninterruptibly();
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(lock.hasQueuedThreads());
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(lock.hasQueuedThreads());
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(lock.hasQueuedThreads());
+ lock.release();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(lock.hasQueuedThreads());
+ t1.join();
+ t2.join();
+ }
/**
* getQueueLength reports number of waiting threads
*/
- public void testGetQueueLength() {
+ public void testGetQueueLength() throws InterruptedException {
final Semaphore lock = new Semaphore(1, false);
Thread t1 = new Thread(new InterruptedLockRunnable(lock));
Thread t2 = new Thread(new InterruptibleLockRunnable(lock));
- try {
- assertEquals(0, lock.getQueueLength());
- lock.acquireUninterruptibly();
- t1.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertEquals(1, lock.getQueueLength());
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertEquals(2, lock.getQueueLength());
- t1.interrupt();
- Thread.sleep(SHORT_DELAY_MS);
- assertEquals(1, lock.getQueueLength());
- lock.release();
- Thread.sleep(SHORT_DELAY_MS);
- assertEquals(0, lock.getQueueLength());
- t1.join();
- t2.join();
- } catch(Exception e){
- unexpectedException();
- }
- }
+ assertEquals(0, lock.getQueueLength());
+ lock.acquireUninterruptibly();
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(1, lock.getQueueLength());
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(2, lock.getQueueLength());
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(1, lock.getQueueLength());
+ lock.release();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(0, lock.getQueueLength());
+ t1.join();
+ t2.join();
+ }
/**
* getQueuedThreads includes waiting threads
*/
- public void testGetQueuedThreads() {
+ public void testGetQueuedThreads() throws InterruptedException {
final PublicSemaphore lock = new PublicSemaphore(1, false);
Thread t1 = new Thread(new InterruptedLockRunnable(lock));
Thread t2 = new Thread(new InterruptibleLockRunnable(lock));
- try {
- assertTrue(lock.getQueuedThreads().isEmpty());
- lock.acquireUninterruptibly();
- assertTrue(lock.getQueuedThreads().isEmpty());
- t1.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(lock.getQueuedThreads().contains(t1));
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(lock.getQueuedThreads().contains(t1));
- assertTrue(lock.getQueuedThreads().contains(t2));
- t1.interrupt();
- Thread.sleep(SHORT_DELAY_MS);
- assertFalse(lock.getQueuedThreads().contains(t1));
- assertTrue(lock.getQueuedThreads().contains(t2));
- lock.release();
- Thread.sleep(SHORT_DELAY_MS);
- assertTrue(lock.getQueuedThreads().isEmpty());
- t1.join();
- t2.join();
- } catch(Exception e){
- unexpectedException();
- }
- }
+ assertTrue(lock.getQueuedThreads().isEmpty());
+ lock.acquireUninterruptibly();
+ assertTrue(lock.getQueuedThreads().isEmpty());
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(lock.getQueuedThreads().contains(t1));
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(lock.getQueuedThreads().contains(t1));
+ assertTrue(lock.getQueuedThreads().contains(t2));
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(lock.getQueuedThreads().contains(t1));
+ assertTrue(lock.getQueuedThreads().contains(t2));
+ lock.release();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(lock.getQueuedThreads().isEmpty());
+ t1.join();
+ t2.join();
+ }
/**
* drainPermits reports and removes given number of permits
@@ -425,26 +366,22 @@ public class SemaphoreTest extends JSR166TestCase {
/**
* a deserialized serialized semaphore has same number of permits
*/
- public void testSerialization() {
+ public void testSerialization() throws Exception {
Semaphore l = new Semaphore(3, false);
- try {
- l.acquire();
- l.release();
- ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
- ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
- out.writeObject(l);
- out.close();
-
- ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
- ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
- Semaphore r = (Semaphore) in.readObject();
- assertEquals(3, r.availablePermits());
- assertFalse(r.isFair());
- r.acquire();
- r.release();
- } catch(Exception e){
- unexpectedException();
- }
+ l.acquire();
+ l.release();
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(l);
+ out.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ Semaphore r = (Semaphore) in.readObject();
+ assertEquals(3, r.availablePermits());
+ assertFalse(r.isFair());
+ r.acquire();
+ r.release();
}
@@ -487,45 +424,39 @@ public class SemaphoreTest extends JSR166TestCase {
/**
* Acquire and release of semaphore succeed if initially available
*/
- public void testAcquireReleaseInSameThread_fair() {
+ public void testAcquireReleaseInSameThread_fair()
+ throws InterruptedException {
Semaphore s = new Semaphore(1, true);
- try {
- s.acquire();
- s.release();
- s.acquire();
- s.release();
- s.acquire();
- s.release();
- s.acquire();
- s.release();
- s.acquire();
- s.release();
- assertEquals(1, s.availablePermits());
- } catch( InterruptedException e){
- unexpectedException();
- }
+ s.acquire();
+ s.release();
+ s.acquire();
+ s.release();
+ s.acquire();
+ s.release();
+ s.acquire();
+ s.release();
+ s.acquire();
+ s.release();
+ assertEquals(1, s.availablePermits());
}
/**
* Acquire(n) and release(n) of semaphore succeed if initially available
*/
- public void testAcquireReleaseNInSameThread_fair() {
+ public void testAcquireReleaseNInSameThread_fair()
+ throws InterruptedException {
Semaphore s = new Semaphore(1, true);
- try {
- s.release(1);
- s.acquire(1);
- s.release(2);
- s.acquire(2);
- s.release(3);
- s.acquire(3);
- s.release(4);
- s.acquire(4);
- s.release(5);
- s.acquire(5);
- assertEquals(1, s.availablePermits());
- } catch( InterruptedException e){
- unexpectedException();
- }
+ s.release(1);
+ s.acquire(1);
+ s.release(2);
+ s.acquire(2);
+ s.release(3);
+ s.acquire(3);
+ s.release(4);
+ s.acquire(4);
+ s.release(5);
+ s.acquire(5);
+ assertEquals(1, s.availablePermits());
}
/**
@@ -533,369 +464,287 @@ public class SemaphoreTest extends JSR166TestCase {
*/
public void testAcquireUninterruptiblyReleaseNInSameThread_fair() {
Semaphore s = new Semaphore(1, true);
- try {
- s.release(1);
- s.acquireUninterruptibly(1);
- s.release(2);
- s.acquireUninterruptibly(2);
- s.release(3);
- s.acquireUninterruptibly(3);
- s.release(4);
- s.acquireUninterruptibly(4);
- s.release(5);
- s.acquireUninterruptibly(5);
- assertEquals(1, s.availablePermits());
- } finally {
- }
+ s.release(1);
+ s.acquireUninterruptibly(1);
+ s.release(2);
+ s.acquireUninterruptibly(2);
+ s.release(3);
+ s.acquireUninterruptibly(3);
+ s.release(4);
+ s.acquireUninterruptibly(4);
+ s.release(5);
+ s.acquireUninterruptibly(5);
+ assertEquals(1, s.availablePermits());
}
/**
* release(n) in one thread enables timed acquire(n) in another thread
*/
- public void testTimedAcquireReleaseNInSameThread_fair() {
+ public void testTimedAcquireReleaseNInSameThread_fair()
+ throws InterruptedException {
Semaphore s = new Semaphore(1, true);
- try {
- s.release(1);
- assertTrue(s.tryAcquire(1, SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- s.release(2);
- assertTrue(s.tryAcquire(2, SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- s.release(3);
- assertTrue(s.tryAcquire(3, SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- s.release(4);
- assertTrue(s.tryAcquire(4, SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- s.release(5);
- assertTrue(s.tryAcquire(5, SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- assertEquals(1, s.availablePermits());
- } catch( InterruptedException e){
- unexpectedException();
- }
+ s.release(1);
+ assertTrue(s.tryAcquire(1, SHORT_DELAY_MS, MILLISECONDS));
+ s.release(2);
+ assertTrue(s.tryAcquire(2, SHORT_DELAY_MS, MILLISECONDS));
+ s.release(3);
+ assertTrue(s.tryAcquire(3, SHORT_DELAY_MS, MILLISECONDS));
+ s.release(4);
+ assertTrue(s.tryAcquire(4, SHORT_DELAY_MS, MILLISECONDS));
+ s.release(5);
+ assertTrue(s.tryAcquire(5, SHORT_DELAY_MS, MILLISECONDS));
+ assertEquals(1, s.availablePermits());
}
/**
* release in one thread enables timed acquire in another thread
*/
- public void testTimedAcquireReleaseInSameThread_fair() {
+ public void testTimedAcquireReleaseInSameThread_fair()
+ throws InterruptedException {
Semaphore s = new Semaphore(1, true);
- try {
- assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- s.release();
- assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- s.release();
- assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- s.release();
- assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- s.release();
- assertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- s.release();
- assertEquals(1, s.availablePermits());
- } catch( InterruptedException e){
- unexpectedException();
- }
+ assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS));
+ s.release();
+ assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS));
+ s.release();
+ assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS));
+ s.release();
+ assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS));
+ s.release();
+ assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS));
+ s.release();
+ assertEquals(1, s.availablePermits());
}
/**
* A release in one thread enables an acquire in another thread
*/
- public void testAcquireReleaseInDifferentThreads_fair() {
+ public void testAcquireReleaseInDifferentThreads_fair()
+ throws InterruptedException {
final Semaphore s = new Semaphore(0, true);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- s.acquire();
- s.acquire();
- s.acquire();
- s.acquire();
- } catch(InterruptedException ie){
- threadUnexpectedException();
- }
- }
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- s.release();
- s.release();
- s.release();
- s.release();
- s.release();
- s.release();
- t.join();
- assertEquals(2, s.availablePermits());
- } catch( InterruptedException e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ s.acquire();
+ s.acquire();
+ s.acquire();
+ s.acquire();
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ s.release();
+ s.release();
+ s.release();
+ s.release();
+ s.release();
+ s.release();
+ t.join();
+ assertEquals(2, s.availablePermits());
}
/**
* release(n) in one thread enables acquire(n) in another thread
*/
- public void testAcquireReleaseNInDifferentThreads_fair() {
+ public void testAcquireReleaseNInDifferentThreads_fair()
+ throws InterruptedException {
final Semaphore s = new Semaphore(0, true);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- s.acquire();
- s.release(2);
- s.acquire();
- } catch(InterruptedException ie){
- threadUnexpectedException();
- }
- }
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- s.release(2);
- s.acquire(2);
- s.release(1);
- t.join();
- } catch( InterruptedException e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ s.acquire();
+ s.release(2);
+ s.acquire();
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ s.release(2);
+ s.acquire(2);
+ s.release(1);
+ t.join();
}
/**
* release(n) in one thread enables acquire(n) in another thread
*/
- public void testAcquireReleaseNInDifferentThreads_fair2() {
+ public void testAcquireReleaseNInDifferentThreads_fair2()
+ throws InterruptedException {
final Semaphore s = new Semaphore(0, true);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- s.acquire(2);
- s.acquire(2);
- s.release(4);
- } catch(InterruptedException ie){
- threadUnexpectedException();
- }
- }
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- s.release(6);
- s.acquire(2);
- s.acquire(2);
- s.release(2);
- t.join();
- } catch( InterruptedException e){
- unexpectedException();
- }
- }
-
-
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ s.acquire(2);
+ s.acquire(2);
+ s.release(4);
+ }});
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ s.release(6);
+ s.acquire(2);
+ s.acquire(2);
+ s.release(2);
+ t.join();
+ }
/**
* release in one thread enables timed acquire in another thread
*/
- public void testTimedAcquireReleaseInDifferentThreads_fair() {
+ public void testTimedAcquireReleaseInDifferentThreads_fair()
+ throws InterruptedException {
final Semaphore s = new Semaphore(1, true);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- threadAssertTrue(s.tryAcquire(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
-
- } catch(InterruptedException ie){
- threadUnexpectedException();
- }
- }
- });
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS));
+ assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS));
+ assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS));
+ assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS));
+ assertTrue(s.tryAcquire(SHORT_DELAY_MS, MILLISECONDS));
+ }});
+
t.start();
- try {
- s.release();
- s.release();
- s.release();
- s.release();
- s.release();
- t.join();
- } catch( InterruptedException e){
- unexpectedException();
- }
+ s.release();
+ s.release();
+ s.release();
+ s.release();
+ s.release();
+ t.join();
}
/**
* release(n) in one thread enables timed acquire(n) in another thread
*/
- public void testTimedAcquireReleaseNInDifferentThreads_fair() {
+ public void testTimedAcquireReleaseNInDifferentThreads_fair()
+ throws InterruptedException {
final Semaphore s = new Semaphore(2, true);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- threadAssertTrue(s.tryAcquire(2, SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- s.release(2);
- threadAssertTrue(s.tryAcquire(2, SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- s.release(2);
- } catch(InterruptedException ie){
- threadUnexpectedException();
- }
- }
- });
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertTrue(s.tryAcquire(2, SHORT_DELAY_MS, MILLISECONDS));
+ s.release(2);
+ assertTrue(s.tryAcquire(2, SHORT_DELAY_MS, MILLISECONDS));
+ s.release(2);
+ }});
+
t.start();
- try {
- assertTrue(s.tryAcquire(2, SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- s.release(2);
- assertTrue(s.tryAcquire(2, SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- s.release(2);
- t.join();
- } catch( InterruptedException e){
- unexpectedException();
- }
+ assertTrue(s.tryAcquire(2, SHORT_DELAY_MS, MILLISECONDS));
+ s.release(2);
+ assertTrue(s.tryAcquire(2, SHORT_DELAY_MS, MILLISECONDS));
+ s.release(2);
+ t.join();
}
/**
* A waiting acquire blocks interruptibly
*/
- public void testAcquire_InterruptedException_fair() {
+ public void testAcquire_InterruptedException_fair()
+ throws InterruptedException {
final Semaphore s = new Semaphore(0, true);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- s.acquire();
- threadShouldThrow();
- } catch(InterruptedException success){}
- }
- });
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ s.acquire();
+ }});
+
t.start();
- try {
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- } catch(InterruptedException e){
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* A waiting acquire(n) blocks interruptibly
*/
- public void testAcquireN_InterruptedException_fair() {
+ public void testAcquireN_InterruptedException_fair()
+ throws InterruptedException {
final Semaphore s = new Semaphore(2, true);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- s.acquire(3);
- threadShouldThrow();
- } catch(InterruptedException success){}
- }
- });
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ s.acquire(3);
+ }});
+
t.start();
- try {
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- } catch(InterruptedException e){
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
-
+
/**
* A waiting tryAcquire blocks interruptibly
*/
- public void testTryAcquire_InterruptedException_fair() {
+ public void testTryAcquire_InterruptedException_fair()
+ throws InterruptedException {
final Semaphore s = new Semaphore(0, true);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- s.tryAcquire(MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
- threadShouldThrow();
- } catch(InterruptedException success){
- }
- }
- });
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ s.tryAcquire(MEDIUM_DELAY_MS, MILLISECONDS);
+ }});
+
t.start();
- try {
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- } catch(InterruptedException e){
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* A waiting tryAcquire(n) blocks interruptibly
*/
- public void testTryAcquireN_InterruptedException_fair() {
+ public void testTryAcquireN_InterruptedException_fair()
+ throws InterruptedException {
final Semaphore s = new Semaphore(1, true);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- s.tryAcquire(4, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
- threadShouldThrow();
- } catch(InterruptedException success){
- }
- }
- });
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ s.tryAcquire(4, MEDIUM_DELAY_MS, MILLISECONDS);
+ }});
+
t.start();
- try {
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- } catch(InterruptedException e){
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* getQueueLength reports number of waiting threads
*/
- public void testGetQueueLength_fair() {
+ public void testGetQueueLength_fair() throws InterruptedException {
final Semaphore lock = new Semaphore(1, true);
Thread t1 = new Thread(new InterruptedLockRunnable(lock));
Thread t2 = new Thread(new InterruptibleLockRunnable(lock));
- try {
- assertEquals(0, lock.getQueueLength());
- lock.acquireUninterruptibly();
- t1.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertEquals(1, lock.getQueueLength());
- t2.start();
- Thread.sleep(SHORT_DELAY_MS);
- assertEquals(2, lock.getQueueLength());
- t1.interrupt();
- Thread.sleep(SHORT_DELAY_MS);
- assertEquals(1, lock.getQueueLength());
- lock.release();
- Thread.sleep(SHORT_DELAY_MS);
- assertEquals(0, lock.getQueueLength());
- t1.join();
- t2.join();
- } catch(Exception e){
- unexpectedException();
- }
- }
+ assertEquals(0, lock.getQueueLength());
+ lock.acquireUninterruptibly();
+ t1.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(1, lock.getQueueLength());
+ t2.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(2, lock.getQueueLength());
+ t1.interrupt();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(1, lock.getQueueLength());
+ lock.release();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(0, lock.getQueueLength());
+ t1.join();
+ t2.join();
+ }
/**
* a deserialized serialized semaphore has same number of permits
*/
- public void testSerialization_fair() {
+ public void testSerialization_fair() throws Exception {
Semaphore l = new Semaphore(3, true);
- try {
- l.acquire();
- l.release();
- ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
- ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
- out.writeObject(l);
- out.close();
-
- ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
- ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
- Semaphore r = (Semaphore) in.readObject();
- assertEquals(3, r.availablePermits());
- assertTrue(r.isFair());
- r.acquire();
- r.release();
- } catch(Exception e){
- unexpectedException();
- }
+ l.acquire();
+ l.release();
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(l);
+ out.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ Semaphore r = (Semaphore) in.readObject();
+ assertEquals(3, r.availablePermits());
+ assertTrue(r.isFair());
+ r.acquire();
+ r.release();
}
/**
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/SynchronousQueueTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/SynchronousQueueTest.java
index c2ae396..9393c5c 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/SynchronousQueueTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/SynchronousQueueTest.java
@@ -2,15 +2,16 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.*;
import java.util.concurrent.*;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.io.*;
public class SynchronousQueueTest extends JSR166TestCase {
@@ -48,7 +49,7 @@ public class SynchronousQueueTest extends JSR166TestCase {
SynchronousQueue q = new SynchronousQueue();
q.offer(null);
shouldThrow();
- } catch (NullPointerException success) { }
+ } catch (NullPointerException success) {}
}
/**
@@ -59,7 +60,7 @@ public class SynchronousQueueTest extends JSR166TestCase {
SynchronousQueue q = new SynchronousQueue();
q.add(null);
shouldThrow();
- } catch (NullPointerException success) { }
+ } catch (NullPointerException success) {}
}
/**
@@ -79,8 +80,7 @@ public class SynchronousQueueTest extends JSR166TestCase {
assertEquals(0, q.remainingCapacity());
q.add(one);
shouldThrow();
- } catch (IllegalStateException success){
- }
+ } catch (IllegalStateException success) {}
}
/**
@@ -91,8 +91,7 @@ public class SynchronousQueueTest extends JSR166TestCase {
SynchronousQueue q = new SynchronousQueue();
q.addAll(null);
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
@@ -103,8 +102,7 @@ public class SynchronousQueueTest extends JSR166TestCase {
SynchronousQueue q = new SynchronousQueue();
q.addAll(q);
shouldThrow();
- }
- catch (IllegalArgumentException success) {}
+ } catch (IllegalArgumentException success) {}
}
/**
@@ -116,8 +114,7 @@ public class SynchronousQueueTest extends JSR166TestCase {
Integer[] ints = new Integer[1];
q.addAll(Arrays.asList(ints));
shouldThrow();
- }
- catch (NullPointerException success) {}
+ } catch (NullPointerException success) {}
}
/**
* addAll throws ISE if no active taker
@@ -130,243 +127,171 @@ public class SynchronousQueueTest extends JSR166TestCase {
ints[i] = new Integer(i);
q.addAll(Arrays.asList(ints));
shouldThrow();
- }
- catch (IllegalStateException success) {}
+ } catch (IllegalStateException success) {}
}
/**
* put(null) throws NPE
*/
- public void testPutNull() {
+ public void testPutNull() throws InterruptedException {
try {
SynchronousQueue q = new SynchronousQueue();
q.put(null);
shouldThrow();
- }
- catch (NullPointerException success){
- }
- catch (InterruptedException ie) {
- unexpectedException();
- }
+ } catch (NullPointerException success) {}
}
/**
* put blocks interruptibly if no active taker
*/
- public void testBlockingPut() {
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- SynchronousQueue q = new SynchronousQueue();
- q.put(zero);
- threadShouldThrow();
- } catch (InterruptedException ie){
- }
- }});
+ public void testBlockingPut() throws InterruptedException {
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ SynchronousQueue q = new SynchronousQueue();
+ q.put(zero);
+ }});
+
t.start();
- try {
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- }
- catch (InterruptedException ie) {
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
- * put blocks waiting for take
+ * put blocks waiting for take
*/
- public void testPutWithTake() {
+ public void testPutWithTake() throws InterruptedException {
final SynchronousQueue q = new SynchronousQueue();
- Thread t = new Thread(new Runnable() {
- public void run() {
- int added = 0;
- try {
- q.put(new Object());
- ++added;
- q.put(new Object());
- ++added;
- q.put(new Object());
- ++added;
- q.put(new Object());
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ int added = 0;
+ try {
+ while (true) {
+ q.put(added);
++added;
- threadShouldThrow();
- } catch (InterruptedException e){
- assertTrue(added >= 1);
}
+ } catch (InterruptedException success) {
+ assertTrue(added == 1);
}
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- q.take();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- } catch (Exception e){
- unexpectedException();
- }
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(0, q.take());
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* timed offer times out if elements not taken
*/
- public void testTimedOffer() {
+ public void testTimedOffer() throws InterruptedException {
final SynchronousQueue q = new SynchronousQueue();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
-
- threadAssertFalse(q.offer(new Object(), SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- q.offer(new Object(), LONG_DELAY_MS, TimeUnit.MILLISECONDS);
- threadShouldThrow();
- } catch (InterruptedException success){}
- }
- });
-
- try {
- t.start();
- Thread.sleep(SMALL_DELAY_MS);
- t.interrupt();
- t.join();
- } catch (Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertFalse(q.offer(new Object(), SHORT_DELAY_MS, MILLISECONDS));
+ q.offer(new Object(), LONG_DELAY_MS, MILLISECONDS);
+ }});
+
+ t.start();
+ Thread.sleep(SMALL_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* take blocks interruptibly when empty
*/
- public void testTakeFromEmpty() {
+ public void testTakeFromEmpty() throws InterruptedException {
final SynchronousQueue q = new SynchronousQueue();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- q.take();
- threadShouldThrow();
- } catch (InterruptedException success){ }
- }
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- } catch (Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ q.take();
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* put blocks interruptibly if no active taker
*/
- public void testFairBlockingPut() {
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- SynchronousQueue q = new SynchronousQueue(true);
- q.put(zero);
- threadShouldThrow();
- } catch (InterruptedException ie){
- }
- }});
+ public void testFairBlockingPut() throws InterruptedException {
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ SynchronousQueue q = new SynchronousQueue(true);
+ q.put(zero);
+ }});
+
t.start();
- try {
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- }
- catch (InterruptedException ie) {
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
- * put blocks waiting for take
+ * put blocks waiting for take
*/
- public void testFairPutWithTake() {
+ public void testFairPutWithTake() throws InterruptedException {
final SynchronousQueue q = new SynchronousQueue(true);
- Thread t = new Thread(new Runnable() {
- public void run() {
- int added = 0;
- try {
- q.put(new Object());
- ++added;
- q.put(new Object());
- ++added;
- q.put(new Object());
- ++added;
- q.put(new Object());
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ int added = 0;
+ try {
+ while (true) {
+ q.put(added);
++added;
- threadShouldThrow();
- } catch (InterruptedException e){
- assertTrue(added >= 1);
}
+ } catch (InterruptedException success) {
+ assertTrue(added == 1);
}
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- q.take();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- } catch (Exception e){
- unexpectedException();
- }
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(0, q.take());
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* timed offer times out if elements not taken
*/
- public void testFairTimedOffer() {
+ public void testFairTimedOffer() throws InterruptedException {
final SynchronousQueue q = new SynchronousQueue(true);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
-
- threadAssertFalse(q.offer(new Object(), SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- q.offer(new Object(), LONG_DELAY_MS, TimeUnit.MILLISECONDS);
- threadShouldThrow();
- } catch (InterruptedException success){}
- }
- });
-
- try {
- t.start();
- Thread.sleep(SMALL_DELAY_MS);
- t.interrupt();
- t.join();
- } catch (Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertFalse(q.offer(new Object(), SHORT_DELAY_MS, MILLISECONDS));
+ q.offer(new Object(), LONG_DELAY_MS, MILLISECONDS);
+ }});
+
+ t.start();
+ Thread.sleep(SMALL_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* take blocks interruptibly when empty
*/
- public void testFairTakeFromEmpty() {
+ public void testFairTakeFromEmpty() throws InterruptedException {
final SynchronousQueue q = new SynchronousQueue(true);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- q.take();
- threadShouldThrow();
- } catch (InterruptedException success){ }
- }
- });
- try {
- t.start();
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- } catch (Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ q.take();
+ }});
+
+ t.start();
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
@@ -380,128 +305,98 @@ public class SynchronousQueueTest extends JSR166TestCase {
/**
* timed pool with zero timeout times out if no active taker
*/
- public void testTimedPoll0() {
- try {
- SynchronousQueue q = new SynchronousQueue();
- assertNull(q.poll(0, TimeUnit.MILLISECONDS));
- } catch (InterruptedException e){
- unexpectedException();
- }
+ public void testTimedPoll0() throws InterruptedException {
+ SynchronousQueue q = new SynchronousQueue();
+ assertNull(q.poll(0, MILLISECONDS));
}
/**
* timed pool with nonzero timeout times out if no active taker
*/
- public void testTimedPoll() {
- try {
- SynchronousQueue q = new SynchronousQueue();
- assertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- } catch (InterruptedException e){
- unexpectedException();
- }
+ public void testTimedPoll() throws InterruptedException {
+ SynchronousQueue q = new SynchronousQueue();
+ assertNull(q.poll(SHORT_DELAY_MS, MILLISECONDS));
}
/**
* Interrupted timed poll throws InterruptedException instead of
* returning timeout status
*/
- public void testInterruptedTimedPoll() {
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- SynchronousQueue q = new SynchronousQueue();
- assertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- } catch (InterruptedException success){
- }
- }});
+ public void testInterruptedTimedPoll() throws InterruptedException {
+ final SynchronousQueue q = new SynchronousQueue();
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ q.poll(SMALL_DELAY_MS, MILLISECONDS);
+ }});
+
t.start();
- try {
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- }
- catch (InterruptedException ie) {
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* timed poll before a delayed offer fails; after offer succeeds;
* on interruption throws
*/
- public void testTimedPollWithOffer() {
+ public void testTimedPollWithOffer() throws InterruptedException {
final SynchronousQueue q = new SynchronousQueue();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- threadAssertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- q.poll(LONG_DELAY_MS, TimeUnit.MILLISECONDS);
- q.poll(LONG_DELAY_MS, TimeUnit.MILLISECONDS);
- threadShouldThrow();
- } catch (InterruptedException success) { }
- }
- });
- try {
- t.start();
- Thread.sleep(SMALL_DELAY_MS);
- assertTrue(q.offer(zero, SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- t.interrupt();
- t.join();
- } catch (Exception e){
- unexpectedException();
- }
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertNull(q.poll(SHORT_DELAY_MS, MILLISECONDS));
+ assertSame(zero, q.poll(LONG_DELAY_MS, MILLISECONDS));
+ try {
+ q.poll(LONG_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SMALL_DELAY_MS);
+ assertTrue(q.offer(zero, SHORT_DELAY_MS, MILLISECONDS));
+ t.interrupt();
+ t.join();
+ }
/**
* Interrupted timed poll throws InterruptedException instead of
* returning timeout status
*/
- public void testFairInterruptedTimedPoll() {
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- SynchronousQueue q = new SynchronousQueue(true);
- assertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- } catch (InterruptedException success){
- }
- }});
+ public void testFairInterruptedTimedPoll() throws InterruptedException {
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ SynchronousQueue q = new SynchronousQueue(true);
+ q.poll(SMALL_DELAY_MS, MILLISECONDS);
+ }});
+
t.start();
- try {
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- }
- catch (InterruptedException ie) {
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
* timed poll before a delayed offer fails; after offer succeeds;
* on interruption throws
*/
- public void testFairTimedPollWithOffer() {
+ public void testFairTimedPollWithOffer() throws InterruptedException {
final SynchronousQueue q = new SynchronousQueue(true);
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- threadAssertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- q.poll(LONG_DELAY_MS, TimeUnit.MILLISECONDS);
- q.poll(LONG_DELAY_MS, TimeUnit.MILLISECONDS);
- threadShouldThrow();
- } catch (InterruptedException success) { }
- }
- });
- try {
- t.start();
- Thread.sleep(SMALL_DELAY_MS);
- assertTrue(q.offer(zero, SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
- t.interrupt();
- t.join();
- } catch (Exception e){
- unexpectedException();
- }
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertNull(q.poll(SHORT_DELAY_MS, MILLISECONDS));
+ assertSame(zero, q.poll(LONG_DELAY_MS, MILLISECONDS));
+ try {
+ q.poll(LONG_DELAY_MS, MILLISECONDS);
+ threadShouldThrow();
+ } catch (InterruptedException success) {}
+ }});
+
+ t.start();
+ Thread.sleep(SMALL_DELAY_MS);
+ assertTrue(q.offer(zero, SHORT_DELAY_MS, MILLISECONDS));
+ t.interrupt();
+ t.join();
+ }
/**
@@ -520,8 +415,7 @@ public class SynchronousQueueTest extends JSR166TestCase {
try {
q.element();
shouldThrow();
- }
- catch (NoSuchElementException success) {}
+ } catch (NoSuchElementException success) {}
}
/**
@@ -532,8 +426,7 @@ public class SynchronousQueueTest extends JSR166TestCase {
try {
q.remove();
shouldThrow();
- } catch (NoSuchElementException success){
- }
+ } catch (NoSuchElementException success) {}
}
/**
@@ -544,7 +437,7 @@ public class SynchronousQueueTest extends JSR166TestCase {
assertFalse(q.remove(zero));
assertTrue(q.isEmpty());
}
-
+
/**
* contains returns false
*/
@@ -613,16 +506,16 @@ public class SynchronousQueueTest extends JSR166TestCase {
Integer[] ints = new Integer[1];
assertNull(ints[0]);
}
-
+
/**
* toArray(null) throws NPE
*/
public void testToArray_BadArg() {
+ SynchronousQueue q = new SynchronousQueue();
try {
- SynchronousQueue q = new SynchronousQueue();
Object o[] = q.toArray(null);
shouldThrow();
- } catch(NullPointerException success){}
+ } catch (NullPointerException success) {}
}
@@ -636,8 +529,7 @@ public class SynchronousQueueTest extends JSR166TestCase {
try {
Object x = it.next();
shouldThrow();
- }
- catch (NoSuchElementException success) {}
+ } catch (NoSuchElementException success) {}
}
/**
@@ -649,8 +541,9 @@ public class SynchronousQueueTest extends JSR166TestCase {
try {
it.remove();
shouldThrow();
+ } catch (IllegalStateException success) {
+ } catch (UnsupportedOperationException success) { // android-added
}
- catch (IllegalStateException success) {}
}
/**
@@ -660,7 +553,7 @@ public class SynchronousQueueTest extends JSR166TestCase {
SynchronousQueue q = new SynchronousQueue();
String s = q.toString();
assertNotNull(s);
- }
+ }
/**
@@ -669,35 +562,21 @@ public class SynchronousQueueTest extends JSR166TestCase {
public void testOfferInExecutor() {
final SynchronousQueue q = new SynchronousQueue();
ExecutorService executor = Executors.newFixedThreadPool(2);
- final Integer one = new Integer(1);
- executor.execute(new Runnable() {
- public void run() {
- threadAssertFalse(q.offer(one));
- try {
- threadAssertTrue(q.offer(one, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS));
- threadAssertEquals(0, q.remainingCapacity());
- }
- catch (InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
+ executor.execute(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertFalse(q.offer(one));
+ assertTrue(q.offer(one, MEDIUM_DELAY_MS, MILLISECONDS));
+ assertEquals(0, q.remainingCapacity());
+ }});
- executor.execute(new Runnable() {
- public void run() {
- try {
- Thread.sleep(SMALL_DELAY_MS);
- threadAssertEquals(one, q.take());
- }
- catch (InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
-
- joinPool(executor);
+ executor.execute(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ Thread.sleep(SMALL_DELAY_MS);
+ assertSame(one, q.take());
+ }});
+ joinPool(executor);
}
/**
@@ -706,84 +585,65 @@ public class SynchronousQueueTest extends JSR166TestCase {
public void testPollInExecutor() {
final SynchronousQueue q = new SynchronousQueue();
ExecutorService executor = Executors.newFixedThreadPool(2);
- executor.execute(new Runnable() {
- public void run() {
- threadAssertNull(q.poll());
- try {
- threadAssertTrue(null != q.poll(MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS));
- threadAssertTrue(q.isEmpty());
- }
- catch (InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
+ executor.execute(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ assertNull(q.poll());
+ assertSame(one, q.poll(MEDIUM_DELAY_MS, MILLISECONDS));
+ assertTrue(q.isEmpty());
+ }});
+
+ executor.execute(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ Thread.sleep(SHORT_DELAY_MS);
+ q.put(one);
+ }});
- executor.execute(new Runnable() {
- public void run() {
- try {
- Thread.sleep(SMALL_DELAY_MS);
- q.put(new Integer(1));
- }
- catch (InterruptedException e) {
- threadUnexpectedException();
- }
- }
- });
-
joinPool(executor);
}
/**
* a deserialized serialized queue is usable
*/
- public void testSerialization() {
+ public void testSerialization() throws Exception {
SynchronousQueue q = new SynchronousQueue();
- try {
- ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
- ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
- out.writeObject(q);
- out.close();
-
- ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
- ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
- SynchronousQueue r = (SynchronousQueue)in.readObject();
- assertEquals(q.size(), r.size());
- while (!q.isEmpty())
- assertEquals(q.remove(), r.remove());
- } catch(Exception e){
- e.printStackTrace();
- unexpectedException();
- }
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(q);
+ out.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ SynchronousQueue r = (SynchronousQueue)in.readObject();
+ assertEquals(q.size(), r.size());
+ while (!q.isEmpty())
+ assertEquals(q.remove(), r.remove());
}
/**
* drainTo(null) throws NPE
- */
+ */
public void testDrainToNull() {
SynchronousQueue q = new SynchronousQueue();
try {
q.drainTo(null);
shouldThrow();
- } catch(NullPointerException success) {
- }
+ } catch (NullPointerException success) {}
}
/**
* drainTo(this) throws IAE
- */
+ */
public void testDrainToSelf() {
SynchronousQueue q = new SynchronousQueue();
try {
q.drainTo(q);
shouldThrow();
- } catch(IllegalArgumentException success) {
- }
+ } catch (IllegalArgumentException success) {}
}
/**
* drainTo(c) of empty queue doesn't transfer elements
- */
+ */
public void testDrainTo() {
SynchronousQueue q = new SynchronousQueue();
ArrayList l = new ArrayList();
@@ -794,98 +654,74 @@ public class SynchronousQueueTest extends JSR166TestCase {
/**
* drainTo empties queue, unblocking a waiting put.
- */
- public void testDrainToWithActivePut() {
+ */
+ public void testDrainToWithActivePut() throws InterruptedException {
final SynchronousQueue q = new SynchronousQueue();
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- q.put(new Integer(1));
- } catch (InterruptedException ie){
- threadUnexpectedException();
- }
- }
- });
- try {
- t.start();
- ArrayList l = new ArrayList();
- Thread.sleep(SHORT_DELAY_MS);
- q.drainTo(l);
- assertTrue(l.size() <= 1);
- if (l.size() > 0)
- assertEquals(l.get(0), new Integer(1));
- t.join();
- assertTrue(l.size() <= 1);
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ q.put(new Integer(1));
+ }});
+
+ t.start();
+ ArrayList l = new ArrayList();
+ Thread.sleep(SHORT_DELAY_MS);
+ q.drainTo(l);
+ assertTrue(l.size() <= 1);
+ if (l.size() > 0)
+ assertEquals(l.get(0), new Integer(1));
+ t.join();
+ assertTrue(l.size() <= 1);
}
/**
* drainTo(null, n) throws NPE
- */
+ */
public void testDrainToNullN() {
SynchronousQueue q = new SynchronousQueue();
try {
q.drainTo(null, 0);
shouldThrow();
- } catch(NullPointerException success) {
- }
+ } catch (NullPointerException success) {}
}
/**
* drainTo(this, n) throws IAE
- */
+ */
public void testDrainToSelfN() {
SynchronousQueue q = new SynchronousQueue();
try {
q.drainTo(q, 0);
shouldThrow();
- } catch(IllegalArgumentException success) {
- }
+ } catch (IllegalArgumentException success) {}
}
/**
* drainTo(c, n) empties up to n elements of queue into c
- */
- public void testDrainToN() {
+ */
+ public void testDrainToN() throws InterruptedException {
final SynchronousQueue q = new SynchronousQueue();
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- try {
- q.put(one);
- } catch (InterruptedException ie){
- threadUnexpectedException();
- }
- }
- });
- Thread t2 = new Thread(new Runnable() {
- public void run() {
- try {
- q.put(two);
- } catch (InterruptedException ie){
- threadUnexpectedException();
- }
- }
- });
-
- try {
- t1.start();
- t2.start();
- ArrayList l = new ArrayList();
- Thread.sleep(SHORT_DELAY_MS);
- q.drainTo(l, 1);
- assertTrue(l.size() == 1);
- q.drainTo(l, 1);
- assertTrue(l.size() == 2);
- assertTrue(l.contains(one));
- assertTrue(l.contains(two));
- t1.join();
- t2.join();
- } catch(Exception e){
- unexpectedException();
- }
+ Thread t1 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ q.put(one);
+ }});
+
+ Thread t2 = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ q.put(two);
+ }});
+
+ t1.start();
+ t2.start();
+ ArrayList l = new ArrayList();
+ Thread.sleep(SHORT_DELAY_MS);
+ q.drainTo(l, 1);
+ assertTrue(l.size() == 1);
+ q.drainTo(l, 1);
+ assertTrue(l.size() == 2);
+ assertTrue(l.contains(one));
+ assertTrue(l.contains(two));
+ t1.join();
+ t2.join();
}
-
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/SystemTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/SystemTest.java
index 439039a..e906186 100644
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/SystemTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/SystemTest.java
@@ -2,11 +2,11 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
@@ -15,9 +15,9 @@ public class SystemTest extends JSR166TestCase {
return new TestSuite(SystemTest.class);
}
- /**
+ /**
* Worst case rounding for millisecs; set for 60 cycle millis clock.
- * This value might need to be changed os JVMs with coarser
+ * This value might need to be changed on JVMs with coarser
* System.currentTimeMillis clocks.
*/
static final long MILLIS_ROUND = 17;
@@ -27,24 +27,19 @@ public class SystemTest extends JSR166TestCase {
* possible rounding).
* This shows only that nano timing not (much) worse than milli.
*/
- public void testNanoTime1() {
- try {
- long m1 = System.currentTimeMillis();
- Thread.sleep(1);
- long n1 = System.nanoTime();
- Thread.sleep(SHORT_DELAY_MS);
- long n2 = System.nanoTime();
- Thread.sleep(1);
- long m2 = System.currentTimeMillis();
- long millis = m2 - m1;
- long nanos = n2 - n1;
- assertTrue(nanos >= 0);
- long nanosAsMillis = nanos / 1000000;
- assertTrue(nanosAsMillis <= millis + MILLIS_ROUND);
- }
- catch(InterruptedException ie) {
- unexpectedException();
- }
+ public void testNanoTime1() throws InterruptedException {
+ long m1 = System.currentTimeMillis();
+ Thread.sleep(1);
+ long n1 = System.nanoTime();
+ Thread.sleep(SHORT_DELAY_MS);
+ long n2 = System.nanoTime();
+ Thread.sleep(1);
+ long m2 = System.currentTimeMillis();
+ long millis = m2 - m1;
+ long nanos = n2 - n1;
+ assertTrue(nanos >= 0);
+ long nanosAsMillis = nanos / 1000000;
+ assertTrue(nanosAsMillis <= millis + MILLIS_ROUND);
}
/**
@@ -52,26 +47,20 @@ public class SystemTest extends JSR166TestCase {
* for rounding.
* This shows only that nano timing not (much) worse than milli.
*/
- public void testNanoTime2() {
- try {
- long n1 = System.nanoTime();
- Thread.sleep(1);
- long m1 = System.currentTimeMillis();
- Thread.sleep(SHORT_DELAY_MS);
- long m2 = System.currentTimeMillis();
- Thread.sleep(1);
- long n2 = System.nanoTime();
- long millis = m2 - m1;
- long nanos = n2 - n1;
-
- assertTrue(nanos >= 0);
- long nanosAsMillis = nanos / 1000000;
- assertTrue(millis <= nanosAsMillis + MILLIS_ROUND);
- }
- catch(InterruptedException ie) {
- unexpectedException();
- }
+ public void testNanoTime2() throws InterruptedException {
+ long n1 = System.nanoTime();
+ Thread.sleep(1);
+ long m1 = System.currentTimeMillis();
+ Thread.sleep(SHORT_DELAY_MS);
+ long m2 = System.currentTimeMillis();
+ Thread.sleep(1);
+ long n2 = System.nanoTime();
+ long millis = m2 - m1;
+ long nanos = n2 - n1;
+
+ assertTrue(nanos >= 0);
+ long nanosAsMillis = nanos / 1000000;
+ assertTrue(millis <= nanosAsMillis + MILLIS_ROUND);
}
}
-
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/ThreadLocalTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/ThreadLocalTest.java
index b9b7ba5..d54bce0 100644
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/ThreadLocalTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/ThreadLocalTest.java
@@ -2,11 +2,11 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.concurrent.Semaphore;
@@ -27,7 +27,7 @@ public class ThreadLocalTest extends JSR166TestCase {
protected Integer initialValue() {
return zero;
}
-
+
protected Integer childValue(Integer parentValue) {
return new Integer(parentValue.intValue() + 1);
}
@@ -37,11 +37,11 @@ public class ThreadLocalTest extends JSR166TestCase {
* remove causes next access to return initial value
*/
public void testRemove() {
- assertEquals(tl.get(), one);
+ assertSame(tl.get(), one);
tl.set(two);
- assertEquals(tl.get(), two);
+ assertSame(tl.get(), two);
tl.remove();
- assertEquals(tl.get(), one);
+ assertSame(tl.get(), one);
}
/**
@@ -49,11 +49,11 @@ public class ThreadLocalTest extends JSR166TestCase {
* initial value
*/
public void testRemoveITL() {
- assertEquals(itl.get(), zero);
+ assertSame(itl.get(), zero);
itl.set(two);
- assertEquals(itl.get(), two);
+ assertSame(itl.get(), two);
itl.remove();
- assertEquals(itl.get(), zero);
+ assertSame(itl.get(), zero);
}
private class ITLThread extends Thread {
@@ -66,18 +66,18 @@ public class ThreadLocalTest extends JSR166TestCase {
child.start();
}
Thread.currentThread().yield();
-
+
int threadId = itl.get().intValue();
for (int j = 0; j < threadId; j++) {
x[threadId]++;
Thread.currentThread().yield();
}
-
+
if (child != null) { // Wait for child (if any)
try {
child.join();
- } catch(InterruptedException e) {
- threadUnexpectedException();
+ } catch (InterruptedException e) {
+ threadUnexpectedException(e);
}
}
}
@@ -86,19 +86,14 @@ public class ThreadLocalTest extends JSR166TestCase {
/**
* InheritableThreadLocal propagates generic values.
*/
- public void testGenericITL() {
+ public void testGenericITL() throws InterruptedException {
final int threadCount = 10;
final int x[] = new int[threadCount];
Thread progenitor = new ITLThread(x);
- try {
- progenitor.start();
- progenitor.join();
- for(int i = 0; i < threadCount; i++) {
- assertEquals(i, x[i]);
- }
- } catch(InterruptedException e) {
- unexpectedException();
+ progenitor.start();
+ progenitor.join();
+ for (int i = 0; i < threadCount; i++) {
+ assertEquals(i, x[i]);
}
}
}
-
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/ThreadPoolExecutorSubclassTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/ThreadPoolExecutorSubclassTest.java
new file mode 100644
index 0000000..911a35f
--- /dev/null
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/ThreadPoolExecutorSubclassTest.java
@@ -0,0 +1,1578 @@
+/*
+ * 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.
+ */
+
+package tests.api.java.util.concurrent; // android-added
+
+import java.util.concurrent.*;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import java.util.concurrent.locks.*;
+
+import junit.framework.*;
+import java.util.*;
+
+public class ThreadPoolExecutorSubclassTest extends JSR166TestCase {
+ public static Test suite() {
+ return new TestSuite(ThreadPoolExecutorSubclassTest.class);
+ }
+
+ static class CustomTask<V> implements RunnableFuture<V> {
+ final Callable<V> callable;
+ final ReentrantLock lock = new ReentrantLock();
+ final Condition cond = lock.newCondition();
+ boolean done;
+ boolean cancelled;
+ V result;
+ Thread thread;
+ Exception exception;
+ CustomTask(Callable<V> c) {
+ if (c == null) throw new NullPointerException();
+ callable = c;
+ }
+ CustomTask(final Runnable r, final V res) {
+ if (r == null) throw new NullPointerException();
+ callable = new Callable<V>() {
+ public V call() throws Exception { r.run(); return res; }};
+ }
+ public boolean isDone() {
+ lock.lock(); try { return done; } finally { lock.unlock() ; }
+ }
+ public boolean isCancelled() {
+ lock.lock(); try { return cancelled; } finally { lock.unlock() ; }
+ }
+ public boolean cancel(boolean mayInterrupt) {
+ lock.lock();
+ try {
+ if (!done) {
+ cancelled = true;
+ done = true;
+ if (mayInterrupt && thread != null)
+ thread.interrupt();
+ return true;
+ }
+ return false;
+ }
+ finally { lock.unlock() ; }
+ }
+ public void run() {
+ boolean runme;
+ lock.lock();
+ try {
+ runme = !done;
+ if (!runme)
+ thread = Thread.currentThread();
+ }
+ finally { lock.unlock() ; }
+ if (!runme) return;
+ V v = null;
+ Exception e = null;
+ try {
+ v = callable.call();
+ }
+ catch (Exception ex) {
+ e = ex;
+ }
+ lock.lock();
+ try {
+ result = v;
+ exception = e;
+ done = true;
+ thread = null;
+ cond.signalAll();
+ }
+ finally { lock.unlock(); }
+ }
+ public V get() throws InterruptedException, ExecutionException {
+ lock.lock();
+ try {
+ while (!done)
+ cond.await();
+ if (exception != null)
+ throw new ExecutionException(exception);
+ return result;
+ }
+ finally { lock.unlock(); }
+ }
+ public V get(long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ long nanos = unit.toNanos(timeout);
+ lock.lock();
+ try {
+ for (;;) {
+ if (done) break;
+ if (nanos < 0)
+ throw new TimeoutException();
+ nanos = cond.awaitNanos(nanos);
+ }
+ if (exception != null)
+ throw new ExecutionException(exception);
+ return result;
+ }
+ finally { lock.unlock(); }
+ }
+ }
+
+
+ static class CustomTPE extends ThreadPoolExecutor {
+ protected <V> RunnableFuture<V> newTaskFor(Callable<V> c) {
+ return new CustomTask<V>(c);
+ }
+ protected <V> RunnableFuture<V> newTaskFor(Runnable r, V v) {
+ return new CustomTask<V>(r, v);
+ }
+
+ CustomTPE(int corePoolSize,
+ int maximumPoolSize,
+ long keepAliveTime,
+ TimeUnit unit,
+ BlockingQueue<Runnable> workQueue) {
+ super(corePoolSize, maximumPoolSize, keepAliveTime, unit,
+ workQueue);
+ }
+ CustomTPE(int corePoolSize,
+ int maximumPoolSize,
+ long keepAliveTime,
+ TimeUnit unit,
+ BlockingQueue<Runnable> workQueue,
+ ThreadFactory threadFactory) {
+ super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
+ threadFactory);
+ }
+
+ CustomTPE(int corePoolSize,
+ int maximumPoolSize,
+ long keepAliveTime,
+ TimeUnit unit,
+ BlockingQueue<Runnable> workQueue,
+ RejectedExecutionHandler handler) {
+ super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
+ handler);
+ }
+ CustomTPE(int corePoolSize,
+ int maximumPoolSize,
+ long keepAliveTime,
+ TimeUnit unit,
+ BlockingQueue<Runnable> workQueue,
+ ThreadFactory threadFactory,
+ RejectedExecutionHandler handler) {
+ super(corePoolSize, maximumPoolSize, keepAliveTime, unit,
+ workQueue, threadFactory, handler);
+ }
+
+ volatile boolean beforeCalled = false;
+ volatile boolean afterCalled = false;
+ volatile boolean terminatedCalled = false;
+ public CustomTPE() {
+ super(1, 1, LONG_DELAY_MS, MILLISECONDS, new SynchronousQueue<Runnable>());
+ }
+ protected void beforeExecute(Thread t, Runnable r) {
+ beforeCalled = true;
+ }
+ protected void afterExecute(Runnable r, Throwable t) {
+ afterCalled = true;
+ }
+ protected void terminated() {
+ terminatedCalled = true;
+ }
+
+ }
+
+ static class FailingThreadFactory implements ThreadFactory {
+ int calls = 0;
+ public Thread newThread(Runnable r) {
+ if (++calls > 1) return null;
+ return new Thread(r);
+ }
+ }
+
+
+ /**
+ * execute successfully executes a runnable
+ */
+ public void testExecute() throws InterruptedException {
+ ThreadPoolExecutor p1 = new CustomTPE(1, 1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ try {
+ p1.execute(new ShortRunnable());
+ Thread.sleep(SMALL_DELAY_MS);
+ } finally {
+ joinPool(p1);
+ }
+ }
+
+ /**
+ * getActiveCount increases but doesn't overestimate, when a
+ * thread becomes active
+ */
+ public void testGetActiveCount() throws InterruptedException {
+ ThreadPoolExecutor p2 = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ assertEquals(0, p2.getActiveCount());
+ p2.execute(new MediumRunnable());
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(1, p2.getActiveCount());
+ joinPool(p2);
+ }
+
+ /**
+ * prestartCoreThread starts a thread if under corePoolSize, else doesn't
+ */
+ public void testPrestartCoreThread() {
+ ThreadPoolExecutor p2 = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ assertEquals(0, p2.getPoolSize());
+ assertTrue(p2.prestartCoreThread());
+ assertEquals(1, p2.getPoolSize());
+ assertTrue(p2.prestartCoreThread());
+ assertEquals(2, p2.getPoolSize());
+ assertFalse(p2.prestartCoreThread());
+ assertEquals(2, p2.getPoolSize());
+ joinPool(p2);
+ }
+
+ /**
+ * prestartAllCoreThreads starts all corePoolSize threads
+ */
+ public void testPrestartAllCoreThreads() {
+ ThreadPoolExecutor p2 = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ assertEquals(0, p2.getPoolSize());
+ p2.prestartAllCoreThreads();
+ assertEquals(2, p2.getPoolSize());
+ p2.prestartAllCoreThreads();
+ assertEquals(2, p2.getPoolSize());
+ joinPool(p2);
+ }
+
+ /**
+ * getCompletedTaskCount increases, but doesn't overestimate,
+ * when tasks complete
+ */
+ public void testGetCompletedTaskCount() throws InterruptedException {
+ ThreadPoolExecutor p2 = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ assertEquals(0, p2.getCompletedTaskCount());
+ p2.execute(new ShortRunnable());
+ Thread.sleep(SMALL_DELAY_MS);
+ assertEquals(1, p2.getCompletedTaskCount());
+ try { p2.shutdown(); } catch (SecurityException ok) { return; }
+ joinPool(p2);
+ }
+
+ /**
+ * getCorePoolSize returns size given in constructor if not otherwise set
+ */
+ public void testGetCorePoolSize() {
+ ThreadPoolExecutor p1 = new CustomTPE(1, 1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ assertEquals(1, p1.getCorePoolSize());
+ joinPool(p1);
+ }
+
+ /**
+ * getKeepAliveTime returns value given in constructor if not otherwise set
+ */
+ public void testGetKeepAliveTime() {
+ ThreadPoolExecutor p2 = new CustomTPE(2, 2, 1000, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ assertEquals(1, p2.getKeepAliveTime(TimeUnit.SECONDS));
+ joinPool(p2);
+ }
+
+
+ /**
+ * getThreadFactory returns factory in constructor if not set
+ */
+ public void testGetThreadFactory() {
+ ThreadFactory tf = new SimpleThreadFactory();
+ ThreadPoolExecutor p = new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10), tf, new NoOpREHandler());
+ assertSame(tf, p.getThreadFactory());
+ joinPool(p);
+ }
+
+ /**
+ * setThreadFactory sets the thread factory returned by getThreadFactory
+ */
+ public void testSetThreadFactory() {
+ ThreadPoolExecutor p = new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ ThreadFactory tf = new SimpleThreadFactory();
+ p.setThreadFactory(tf);
+ assertSame(tf, p.getThreadFactory());
+ joinPool(p);
+ }
+
+
+ /**
+ * setThreadFactory(null) throws NPE
+ */
+ public void testSetThreadFactoryNull() {
+ ThreadPoolExecutor p = new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ try {
+ p.setThreadFactory(null);
+ shouldThrow();
+ } catch (NullPointerException success) {
+ } finally {
+ joinPool(p);
+ }
+ }
+
+ /**
+ * getRejectedExecutionHandler returns handler in constructor if not set
+ */
+ public void testGetRejectedExecutionHandler() {
+ RejectedExecutionHandler h = new NoOpREHandler();
+ ThreadPoolExecutor p = new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10), h);
+ assertSame(h, p.getRejectedExecutionHandler());
+ joinPool(p);
+ }
+
+ /**
+ * setRejectedExecutionHandler sets the handler returned by
+ * getRejectedExecutionHandler
+ */
+ public void testSetRejectedExecutionHandler() {
+ ThreadPoolExecutor p = new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ RejectedExecutionHandler h = new NoOpREHandler();
+ p.setRejectedExecutionHandler(h);
+ assertSame(h, p.getRejectedExecutionHandler());
+ joinPool(p);
+ }
+
+
+ /**
+ * setRejectedExecutionHandler(null) throws NPE
+ */
+ public void testSetRejectedExecutionHandlerNull() {
+ ThreadPoolExecutor p = new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ try {
+ p.setRejectedExecutionHandler(null);
+ shouldThrow();
+ } catch (NullPointerException success) {
+ } finally {
+ joinPool(p);
+ }
+ }
+
+
+ /**
+ * getLargestPoolSize increases, but doesn't overestimate, when
+ * multiple threads active
+ */
+ public void testGetLargestPoolSize() throws InterruptedException {
+ ThreadPoolExecutor p2 = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ assertEquals(0, p2.getLargestPoolSize());
+ p2.execute(new MediumRunnable());
+ p2.execute(new MediumRunnable());
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(2, p2.getLargestPoolSize());
+ joinPool(p2);
+ }
+
+ /**
+ * getMaximumPoolSize returns value given in constructor if not
+ * otherwise set
+ */
+ public void testGetMaximumPoolSize() {
+ ThreadPoolExecutor p2 = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ assertEquals(2, p2.getMaximumPoolSize());
+ joinPool(p2);
+ }
+
+ /**
+ * getPoolSize increases, but doesn't overestimate, when threads
+ * become active
+ */
+ public void testGetPoolSize() {
+ ThreadPoolExecutor p1 = new CustomTPE(1, 1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ assertEquals(0, p1.getPoolSize());
+ p1.execute(new MediumRunnable());
+ assertEquals(1, p1.getPoolSize());
+ joinPool(p1);
+ }
+
+ /**
+ * getTaskCount increases, but doesn't overestimate, when tasks submitted
+ */
+ public void testGetTaskCount() throws InterruptedException {
+ ThreadPoolExecutor p1 = new CustomTPE(1, 1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ assertEquals(0, p1.getTaskCount());
+ p1.execute(new MediumRunnable());
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(1, p1.getTaskCount());
+ joinPool(p1);
+ }
+
+ /**
+ * isShutDown is false before shutdown, true after
+ */
+ public void testIsShutdown() {
+
+ ThreadPoolExecutor p1 = new CustomTPE(1, 1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ assertFalse(p1.isShutdown());
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
+ assertTrue(p1.isShutdown());
+ joinPool(p1);
+ }
+
+
+ /**
+ * isTerminated is false before termination, true after
+ */
+ public void testIsTerminated() throws InterruptedException {
+ ThreadPoolExecutor p1 = new CustomTPE(1, 1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ assertFalse(p1.isTerminated());
+ try {
+ p1.execute(new MediumRunnable());
+ } finally {
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
+ }
+ assertTrue(p1.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
+ assertTrue(p1.isTerminated());
+ }
+
+ /**
+ * isTerminating is not true when running or when terminated
+ */
+ public void testIsTerminating() throws InterruptedException {
+ ThreadPoolExecutor p1 = new CustomTPE(1, 1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ assertFalse(p1.isTerminating());
+ try {
+ p1.execute(new SmallRunnable());
+ assertFalse(p1.isTerminating());
+ } finally {
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
+ }
+ assertTrue(p1.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
+ assertTrue(p1.isTerminated());
+ assertFalse(p1.isTerminating());
+ }
+
+ /**
+ * getQueue returns the work queue, which contains queued tasks
+ */
+ public void testGetQueue() throws InterruptedException {
+ BlockingQueue<Runnable> q = new ArrayBlockingQueue<Runnable>(10);
+ ThreadPoolExecutor p1 = new CustomTPE(1, 1, LONG_DELAY_MS, MILLISECONDS, q);
+ FutureTask[] tasks = new FutureTask[5];
+ for (int i = 0; i < 5; i++) {
+ tasks[i] = new FutureTask(new MediumPossiblyInterruptedRunnable(), Boolean.TRUE);
+ p1.execute(tasks[i]);
+ }
+ try {
+ Thread.sleep(SHORT_DELAY_MS);
+ BlockingQueue<Runnable> wq = p1.getQueue();
+ assertSame(q, wq);
+ assertFalse(wq.contains(tasks[0]));
+ assertTrue(wq.contains(tasks[4]));
+ for (int i = 1; i < 5; ++i)
+ tasks[i].cancel(true);
+ p1.shutdownNow();
+ } finally {
+ joinPool(p1);
+ }
+ }
+
+ /**
+ * remove(task) removes queued task, and fails to remove active task
+ */
+ public void testRemove() throws InterruptedException {
+ BlockingQueue<Runnable> q = new ArrayBlockingQueue<Runnable>(10);
+ ThreadPoolExecutor p1 = new CustomTPE(1, 1, LONG_DELAY_MS, MILLISECONDS, q);
+ FutureTask[] tasks = new FutureTask[5];
+ for (int i = 0; i < 5; i++) {
+ tasks[i] = new FutureTask(new MediumPossiblyInterruptedRunnable(), Boolean.TRUE);
+ p1.execute(tasks[i]);
+ }
+ try {
+ Thread.sleep(SHORT_DELAY_MS);
+ assertFalse(p1.remove(tasks[0]));
+ assertTrue(q.contains(tasks[4]));
+ assertTrue(q.contains(tasks[3]));
+ assertTrue(p1.remove(tasks[4]));
+ assertFalse(p1.remove(tasks[4]));
+ assertFalse(q.contains(tasks[4]));
+ assertTrue(q.contains(tasks[3]));
+ assertTrue(p1.remove(tasks[3]));
+ assertFalse(q.contains(tasks[3]));
+ } finally {
+ joinPool(p1);
+ }
+ }
+
+ /**
+ * purge removes cancelled tasks from the queue
+ */
+ public void testPurge() {
+ ThreadPoolExecutor p1 = new CustomTPE(1, 1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ FutureTask[] tasks = new FutureTask[5];
+ for (int i = 0; i < 5; i++) {
+ tasks[i] = new FutureTask(new MediumPossiblyInterruptedRunnable(), Boolean.TRUE);
+ p1.execute(tasks[i]);
+ }
+ tasks[4].cancel(true);
+ tasks[3].cancel(true);
+ p1.purge();
+ long count = p1.getTaskCount();
+ assertTrue(count >= 2 && count < 5);
+ joinPool(p1);
+ }
+
+ /**
+ * shutDownNow returns a list containing tasks that were not run
+ */
+ public void testShutDownNow() {
+ ThreadPoolExecutor p1 = new CustomTPE(1, 1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ List l;
+ try {
+ for (int i = 0; i < 5; i++)
+ p1.execute(new MediumPossiblyInterruptedRunnable());
+ }
+ finally {
+ try {
+ l = p1.shutdownNow();
+ } catch (SecurityException ok) { return; }
+ }
+ assertTrue(p1.isShutdown());
+ assertTrue(l.size() <= 4);
+ }
+
+ // Exception Tests
+
+
+ /**
+ * Constructor throws if corePoolSize argument is less than zero
+ */
+ public void testConstructor1() {
+ try {
+ new CustomTPE(-1,1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * Constructor throws if maximumPoolSize is less than zero
+ */
+ public void testConstructor2() {
+ try {
+ new CustomTPE(1,-1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * Constructor throws if maximumPoolSize is equal to zero
+ */
+ public void testConstructor3() {
+ try {
+ new CustomTPE(1,0,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * Constructor throws if keepAliveTime is less than zero
+ */
+ public void testConstructor4() {
+ try {
+ new CustomTPE(1,2,-1L,MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * Constructor throws if corePoolSize is greater than the maximumPoolSize
+ */
+ public void testConstructor5() {
+ try {
+ new CustomTPE(2,1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * Constructor throws if workQueue is set to null
+ */
+ public void testConstructorNullPointerException() {
+ try {
+ new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS,null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+
+
+ /**
+ * Constructor throws if corePoolSize argument is less than zero
+ */
+ public void testConstructor6() {
+ try {
+ new CustomTPE(-1,1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory());
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * Constructor throws if maximumPoolSize is less than zero
+ */
+ public void testConstructor7() {
+ try {
+ new CustomTPE(1,-1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory());
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * Constructor throws if maximumPoolSize is equal to zero
+ */
+ public void testConstructor8() {
+ try {
+ new CustomTPE(1,0,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory());
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * Constructor throws if keepAliveTime is less than zero
+ */
+ public void testConstructor9() {
+ try {
+ new CustomTPE(1,2,-1L,MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory());
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * Constructor throws if corePoolSize is greater than the maximumPoolSize
+ */
+ public void testConstructor10() {
+ try {
+ new CustomTPE(2,1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory());
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * Constructor throws if workQueue is set to null
+ */
+ public void testConstructorNullPointerException2() {
+ try {
+ new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS,null,new SimpleThreadFactory());
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * Constructor throws if threadFactory is set to null
+ */
+ public void testConstructorNullPointerException3() {
+ try {
+ ThreadFactory f = null;
+ new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS,new ArrayBlockingQueue<Runnable>(10),f);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+
+ /**
+ * Constructor throws if corePoolSize argument is less than zero
+ */
+ public void testConstructor11() {
+ try {
+ new CustomTPE(-1,1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new NoOpREHandler());
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * Constructor throws if maximumPoolSize is less than zero
+ */
+ public void testConstructor12() {
+ try {
+ new CustomTPE(1,-1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new NoOpREHandler());
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * Constructor throws if maximumPoolSize is equal to zero
+ */
+ public void testConstructor13() {
+ try {
+ new CustomTPE(1,0,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new NoOpREHandler());
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * Constructor throws if keepAliveTime is less than zero
+ */
+ public void testConstructor14() {
+ try {
+ new CustomTPE(1,2,-1L,MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new NoOpREHandler());
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * Constructor throws if corePoolSize is greater than the maximumPoolSize
+ */
+ public void testConstructor15() {
+ try {
+ new CustomTPE(2,1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new NoOpREHandler());
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * Constructor throws if workQueue is set to null
+ */
+ public void testConstructorNullPointerException4() {
+ try {
+ new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS,null,new NoOpREHandler());
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * Constructor throws if handler is set to null
+ */
+ public void testConstructorNullPointerException5() {
+ try {
+ RejectedExecutionHandler r = null;
+ new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS,new ArrayBlockingQueue<Runnable>(10),r);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+
+ /**
+ * Constructor throws if corePoolSize argument is less than zero
+ */
+ public void testConstructor16() {
+ try {
+ new CustomTPE(-1,1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory(),new NoOpREHandler());
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * Constructor throws if maximumPoolSize is less than zero
+ */
+ public void testConstructor17() {
+ try {
+ new CustomTPE(1,-1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory(),new NoOpREHandler());
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * Constructor throws if maximumPoolSize is equal to zero
+ */
+ public void testConstructor18() {
+ try {
+ new CustomTPE(1,0,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory(),new NoOpREHandler());
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * Constructor throws if keepAliveTime is less than zero
+ */
+ public void testConstructor19() {
+ try {
+ new CustomTPE(1,2,-1L,MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory(),new NoOpREHandler());
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * Constructor throws if corePoolSize is greater than the maximumPoolSize
+ */
+ public void testConstructor20() {
+ try {
+ new CustomTPE(2,1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory(),new NoOpREHandler());
+ shouldThrow();
+ } catch (IllegalArgumentException success) {}
+ }
+
+ /**
+ * Constructor throws if workQueue is set to null
+ */
+ public void testConstructorNullPointerException6() {
+ try {
+ new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS,null,new SimpleThreadFactory(),new NoOpREHandler());
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * Constructor throws if handler is set to null
+ */
+ public void testConstructorNullPointerException7() {
+ try {
+ RejectedExecutionHandler r = null;
+ new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS,new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory(),r);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+ /**
+ * Constructor throws if ThreadFactory is set top null
+ */
+ public void testConstructorNullPointerException8() {
+ try {
+ ThreadFactory f = null;
+ new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS,new ArrayBlockingQueue<Runnable>(10),f,new NoOpREHandler());
+ shouldThrow();
+ } catch (NullPointerException success) {}
+ }
+
+
+ /**
+ * execute throws RejectedExecutionException
+ * if saturated.
+ */
+ public void testSaturatedExecute() {
+ ThreadPoolExecutor p = new CustomTPE(1,1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(1));
+ try {
+
+ for (int i = 0; i < 5; ++i) {
+ p.execute(new MediumRunnable());
+ }
+ shouldThrow();
+ } catch (RejectedExecutionException success) {}
+ joinPool(p);
+ }
+
+ /**
+ * executor using CallerRunsPolicy runs task if saturated.
+ */
+ public void testSaturatedExecute2() {
+ RejectedExecutionHandler h = new CustomTPE.CallerRunsPolicy();
+ ThreadPoolExecutor p = new CustomTPE(1,1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), h);
+ try {
+
+ TrackedNoOpRunnable[] tasks = new TrackedNoOpRunnable[5];
+ for (int i = 0; i < 5; ++i) {
+ tasks[i] = new TrackedNoOpRunnable();
+ }
+ TrackedLongRunnable mr = new TrackedLongRunnable();
+ p.execute(mr);
+ for (int i = 0; i < 5; ++i) {
+ p.execute(tasks[i]);
+ }
+ for (int i = 1; i < 5; ++i) {
+ assertTrue(tasks[i].done);
+ }
+ try { p.shutdownNow(); } catch (SecurityException ok) { return; }
+ } finally {
+ joinPool(p);
+ }
+ }
+
+ /**
+ * executor using DiscardPolicy drops task if saturated.
+ */
+ public void testSaturatedExecute3() {
+ RejectedExecutionHandler h = new CustomTPE.DiscardPolicy();
+ ThreadPoolExecutor p = new CustomTPE(1,1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), h);
+ try {
+
+ TrackedNoOpRunnable[] tasks = new TrackedNoOpRunnable[5];
+ for (int i = 0; i < 5; ++i) {
+ tasks[i] = new TrackedNoOpRunnable();
+ }
+ p.execute(new TrackedLongRunnable());
+ for (int i = 0; i < 5; ++i) {
+ p.execute(tasks[i]);
+ }
+ for (int i = 0; i < 5; ++i) {
+ assertFalse(tasks[i].done);
+ }
+ try { p.shutdownNow(); } catch (SecurityException ok) { return; }
+ } finally {
+ joinPool(p);
+ }
+ }
+
+ /**
+ * executor using DiscardOldestPolicy drops oldest task if saturated.
+ */
+ public void testSaturatedExecute4() {
+ RejectedExecutionHandler h = new CustomTPE.DiscardOldestPolicy();
+ ThreadPoolExecutor p = new CustomTPE(1,1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), h);
+ try {
+ p.execute(new TrackedLongRunnable());
+ TrackedLongRunnable r2 = new TrackedLongRunnable();
+ p.execute(r2);
+ assertTrue(p.getQueue().contains(r2));
+ TrackedNoOpRunnable r3 = new TrackedNoOpRunnable();
+ p.execute(r3);
+ assertFalse(p.getQueue().contains(r2));
+ assertTrue(p.getQueue().contains(r3));
+ try { p.shutdownNow(); } catch (SecurityException ok) { return; }
+ } finally {
+ joinPool(p);
+ }
+ }
+
+ /**
+ * execute throws RejectedExecutionException if shutdown
+ */
+ public void testRejectedExecutionExceptionOnShutdown() {
+ ThreadPoolExecutor tpe =
+ new CustomTPE(1,1,LONG_DELAY_MS, MILLISECONDS,new ArrayBlockingQueue<Runnable>(1));
+ try { tpe.shutdown(); } catch (SecurityException ok) { return; }
+ try {
+ tpe.execute(new NoOpRunnable());
+ shouldThrow();
+ } catch (RejectedExecutionException success) {}
+
+ joinPool(tpe);
+ }
+
+ /**
+ * execute using CallerRunsPolicy drops task on shutdown
+ */
+ public void testCallerRunsOnShutdown() {
+ RejectedExecutionHandler h = new CustomTPE.CallerRunsPolicy();
+ ThreadPoolExecutor p = new CustomTPE(1,1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), h);
+
+ try { p.shutdown(); } catch (SecurityException ok) { return; }
+ try {
+ TrackedNoOpRunnable r = new TrackedNoOpRunnable();
+ p.execute(r);
+ assertFalse(r.done);
+ } finally {
+ joinPool(p);
+ }
+ }
+
+ /**
+ * execute using DiscardPolicy drops task on shutdown
+ */
+ public void testDiscardOnShutdown() {
+ RejectedExecutionHandler h = new CustomTPE.DiscardPolicy();
+ ThreadPoolExecutor p = new CustomTPE(1,1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), h);
+
+ try { p.shutdown(); } catch (SecurityException ok) { return; }
+ try {
+ TrackedNoOpRunnable r = new TrackedNoOpRunnable();
+ p.execute(r);
+ assertFalse(r.done);
+ } finally {
+ joinPool(p);
+ }
+ }
+
+
+ /**
+ * execute using DiscardOldestPolicy drops task on shutdown
+ */
+ public void testDiscardOldestOnShutdown() {
+ RejectedExecutionHandler h = new CustomTPE.DiscardOldestPolicy();
+ ThreadPoolExecutor p = new CustomTPE(1,1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), h);
+
+ try { p.shutdown(); } catch (SecurityException ok) { return; }
+ try {
+ TrackedNoOpRunnable r = new TrackedNoOpRunnable();
+ p.execute(r);
+ assertFalse(r.done);
+ } finally {
+ joinPool(p);
+ }
+ }
+
+
+ /**
+ * execute (null) throws NPE
+ */
+ public void testExecuteNull() {
+ ThreadPoolExecutor tpe = null;
+ try {
+ tpe = new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS,new ArrayBlockingQueue<Runnable>(10));
+ tpe.execute(null);
+ shouldThrow();
+ } catch (NullPointerException success) {}
+
+ joinPool(tpe);
+ }
+
+ /**
+ * setCorePoolSize of negative value throws IllegalArgumentException
+ */
+ public void testCorePoolSizeIllegalArgumentException() {
+ ThreadPoolExecutor tpe =
+ new CustomTPE(1,2,LONG_DELAY_MS, MILLISECONDS,new ArrayBlockingQueue<Runnable>(10));
+ try {
+ tpe.setCorePoolSize(-1);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {
+ } finally {
+ try { tpe.shutdown(); } catch (SecurityException ok) { return; }
+ }
+ joinPool(tpe);
+ }
+
+ /**
+ * setMaximumPoolSize(int) throws IllegalArgumentException if
+ * given a value less the core pool size
+ */
+ public void testMaximumPoolSizeIllegalArgumentException() {
+ ThreadPoolExecutor tpe =
+ new CustomTPE(2,3,LONG_DELAY_MS, MILLISECONDS,new ArrayBlockingQueue<Runnable>(10));
+ try {
+ tpe.setMaximumPoolSize(1);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {
+ } finally {
+ try { tpe.shutdown(); } catch (SecurityException ok) { return; }
+ }
+ joinPool(tpe);
+ }
+
+ /**
+ * setMaximumPoolSize throws IllegalArgumentException
+ * if given a negative value
+ */
+ public void testMaximumPoolSizeIllegalArgumentException2() {
+ ThreadPoolExecutor tpe =
+ new CustomTPE(2,3,LONG_DELAY_MS, MILLISECONDS,new ArrayBlockingQueue<Runnable>(10));
+ try {
+ tpe.setMaximumPoolSize(-1);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {
+ } finally {
+ try { tpe.shutdown(); } catch (SecurityException ok) { return; }
+ }
+ joinPool(tpe);
+ }
+
+
+ /**
+ * setKeepAliveTime throws IllegalArgumentException
+ * when given a negative value
+ */
+ public void testKeepAliveTimeIllegalArgumentException() {
+ ThreadPoolExecutor tpe =
+ new CustomTPE(2,3,LONG_DELAY_MS, MILLISECONDS,new ArrayBlockingQueue<Runnable>(10));
+
+ try {
+ tpe.setKeepAliveTime(-1,MILLISECONDS);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {
+ } finally {
+ try { tpe.shutdown(); } catch (SecurityException ok) { return; }
+ }
+ joinPool(tpe);
+ }
+
+ /**
+ * terminated() is called on termination
+ */
+ public void testTerminated() {
+ CustomTPE tpe = new CustomTPE();
+ try { tpe.shutdown(); } catch (SecurityException ok) { return; }
+ assertTrue(tpe.terminatedCalled);
+ joinPool(tpe);
+ }
+
+ /**
+ * beforeExecute and afterExecute are called when executing task
+ */
+ public void testBeforeAfter() throws InterruptedException {
+ CustomTPE tpe = new CustomTPE();
+ try {
+ TrackedNoOpRunnable r = new TrackedNoOpRunnable();
+ tpe.execute(r);
+ Thread.sleep(SHORT_DELAY_MS);
+ assertTrue(r.done);
+ assertTrue(tpe.beforeCalled);
+ assertTrue(tpe.afterCalled);
+ try { tpe.shutdown(); } catch (SecurityException ok) { return; }
+ } finally {
+ joinPool(tpe);
+ }
+ }
+
+ /**
+ * completed submit of callable returns result
+ */
+ public void testSubmitCallable() throws Exception {
+ ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ try {
+ Future<String> future = e.submit(new StringTask());
+ String result = future.get();
+ assertSame(TEST_STRING, result);
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * completed submit of runnable returns successfully
+ */
+ public void testSubmitRunnable() throws Exception {
+ ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ try {
+ Future<?> future = e.submit(new NoOpRunnable());
+ future.get();
+ assertTrue(future.isDone());
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * completed submit of (runnable, result) returns result
+ */
+ public void testSubmitRunnable2() throws Exception {
+ ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ try {
+ Future<String> future = e.submit(new NoOpRunnable(), TEST_STRING);
+ String result = future.get();
+ assertSame(TEST_STRING, result);
+ } finally {
+ joinPool(e);
+ }
+ }
+
+
+ /**
+ * invokeAny(null) throws NPE
+ */
+ public void testInvokeAny1() throws Exception {
+ ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ try {
+ e.invokeAny(null);
+ shouldThrow();
+ } catch (NullPointerException success) {
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * invokeAny(empty collection) throws IAE
+ */
+ public void testInvokeAny2() throws Exception {
+ ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ try {
+ e.invokeAny(new ArrayList<Callable<String>>());
+ shouldThrow();
+ } catch (IllegalArgumentException success) {
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * invokeAny(c) throws NPE if c has null elements
+ */
+ public void testInvokeAny3() throws Exception {
+ CountDownLatch latch = new CountDownLatch(1);
+ ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(latchAwaitingStringTask(latch));
+ l.add(null);
+ try {
+ e.invokeAny(l);
+ shouldThrow();
+ } catch (NullPointerException success) {
+ } finally {
+ latch.countDown();
+ joinPool(e);
+ }
+ }
+
+ /**
+ * invokeAny(c) throws ExecutionException if no task completes
+ */
+ public void testInvokeAny4() throws Exception {
+ ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new NPETask());
+ try {
+ e.invokeAny(l);
+ shouldThrow();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof NullPointerException);
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * invokeAny(c) returns result of some task
+ */
+ public void testInvokeAny5() throws Exception {
+ ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ try {
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(new StringTask());
+ String result = e.invokeAny(l);
+ assertSame(TEST_STRING, result);
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * invokeAll(null) throws NPE
+ */
+ public void testInvokeAll1() throws Exception {
+ ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ try {
+ e.invokeAll(null);
+ shouldThrow();
+ } catch (NullPointerException success) {
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * invokeAll(empty collection) returns empty collection
+ */
+ public void testInvokeAll2() throws Exception {
+ ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ try {
+ List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>());
+ assertTrue(r.isEmpty());
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * invokeAll(c) throws NPE if c has null elements
+ */
+ public void testInvokeAll3() throws Exception {
+ ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(null);
+ try {
+ e.invokeAll(l);
+ shouldThrow();
+ } catch (NullPointerException success) {
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * get of element of invokeAll(c) throws exception on failed task
+ */
+ public void testInvokeAll4() throws Exception {
+ ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new NPETask());
+ List<Future<String>> futures = e.invokeAll(l);
+ assertEquals(1, futures.size());
+ try {
+ futures.get(0).get();
+ shouldThrow();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof NullPointerException);
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * invokeAll(c) returns results of all completed tasks
+ */
+ public void testInvokeAll5() throws Exception {
+ ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ try {
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(new StringTask());
+ List<Future<String>> futures = e.invokeAll(l);
+ assertEquals(2, futures.size());
+ for (Future<String> future : futures)
+ assertSame(TEST_STRING, future.get());
+ } finally {
+ joinPool(e);
+ }
+ }
+
+
+
+ /**
+ * timed invokeAny(null) throws NPE
+ */
+ public void testTimedInvokeAny1() throws Exception {
+ ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ try {
+ e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (NullPointerException success) {
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAny(,,null) throws NPE
+ */
+ public void testTimedInvokeAnyNullTimeUnit() throws Exception {
+ ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ try {
+ e.invokeAny(l, MEDIUM_DELAY_MS, null);
+ shouldThrow();
+ } catch (NullPointerException success) {
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAny(empty collection) throws IAE
+ */
+ public void testTimedInvokeAny2() throws Exception {
+ ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ try {
+ e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (IllegalArgumentException success) {
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAny(c) throws NPE if c has null elements
+ */
+ public void testTimedInvokeAny3() throws Exception {
+ CountDownLatch latch = new CountDownLatch(1);
+ ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(latchAwaitingStringTask(latch));
+ l.add(null);
+ try {
+ e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (NullPointerException success) {
+ } finally {
+ latch.countDown();
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAny(c) throws ExecutionException if no task completes
+ */
+ public void testTimedInvokeAny4() throws Exception {
+ ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new NPETask());
+ try {
+ e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof NullPointerException);
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAny(c) returns result of some task
+ */
+ public void testTimedInvokeAny5() throws Exception {
+ ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ try {
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(new StringTask());
+ String result = e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ assertSame(TEST_STRING, result);
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAll(null) throws NPE
+ */
+ public void testTimedInvokeAll1() throws Exception {
+ ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ try {
+ e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (NullPointerException success) {
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAll(,,null) throws NPE
+ */
+ public void testTimedInvokeAllNullTimeUnit() throws Exception {
+ ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ try {
+ e.invokeAll(l, MEDIUM_DELAY_MS, null);
+ shouldThrow();
+ } catch (NullPointerException success) {
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAll(empty collection) returns empty collection
+ */
+ public void testTimedInvokeAll2() throws Exception {
+ ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ try {
+ List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
+ assertTrue(r.isEmpty());
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAll(c) throws NPE if c has null elements
+ */
+ public void testTimedInvokeAll3() throws Exception {
+ ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(null);
+ try {
+ e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (NullPointerException success) {
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * get of element of invokeAll(c) throws exception on failed task
+ */
+ public void testTimedInvokeAll4() throws Exception {
+ ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new NPETask());
+ List<Future<String>> futures =
+ e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ assertEquals(1, futures.size());
+ try {
+ futures.get(0).get();
+ shouldThrow();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof NullPointerException);
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAll(c) returns results of all completed tasks
+ */
+ public void testTimedInvokeAll5() throws Exception {
+ ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ try {
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(new StringTask());
+ List<Future<String>> futures =
+ e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ assertEquals(2, futures.size());
+ for (Future<String> future : futures)
+ assertSame(TEST_STRING, future.get());
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * timed invokeAll(c) cancels tasks not completed by timeout
+ */
+ public void testTimedInvokeAll6() throws Exception {
+ ExecutorService e = new CustomTPE(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ try {
+ List<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>> futures =
+ e.invokeAll(l, SHORT_DELAY_MS, MILLISECONDS);
+ assertEquals(3, futures.size());
+ Iterator<Future<String>> it = futures.iterator();
+ Future<String> f1 = it.next();
+ Future<String> f2 = it.next();
+ Future<String> f3 = it.next();
+ assertTrue(f1.isDone());
+ assertTrue(f2.isDone());
+ assertTrue(f3.isDone());
+ assertFalse(f1.isCancelled());
+ assertTrue(f2.isCancelled());
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * Execution continues if there is at least one thread even if
+ * thread factory fails to create more
+ */
+ public void testFailingThreadFactory() throws InterruptedException {
+ ExecutorService e = new CustomTPE(100, 100, LONG_DELAY_MS, MILLISECONDS, new LinkedBlockingQueue<Runnable>(), new FailingThreadFactory());
+ try {
+ for (int k = 0; k < 100; ++k) {
+ e.execute(new NoOpRunnable());
+ }
+ Thread.sleep(LONG_DELAY_MS);
+ } finally {
+ joinPool(e);
+ }
+ }
+
+ /**
+ * allowsCoreThreadTimeOut is by default false.
+ */
+ public void testAllowsCoreThreadTimeOut() {
+ ThreadPoolExecutor tpe = new CustomTPE(2, 2, 1000, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ assertFalse(tpe.allowsCoreThreadTimeOut());
+ joinPool(tpe);
+ }
+
+ /**
+ * allowCoreThreadTimeOut(true) causes idle threads to time out
+ */
+ public void testAllowCoreThreadTimeOut_true() throws InterruptedException {
+ ThreadPoolExecutor tpe = new CustomTPE(2, 10, 10, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ tpe.allowCoreThreadTimeOut(true);
+ tpe.execute(new NoOpRunnable());
+ try {
+ Thread.sleep(MEDIUM_DELAY_MS);
+ assertEquals(0, tpe.getPoolSize());
+ } finally {
+ joinPool(tpe);
+ }
+ }
+
+ /**
+ * allowCoreThreadTimeOut(false) causes idle threads not to time out
+ */
+ public void testAllowCoreThreadTimeOut_false() throws InterruptedException {
+ ThreadPoolExecutor tpe = new CustomTPE(2, 10, 10, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ tpe.allowCoreThreadTimeOut(false);
+ tpe.execute(new NoOpRunnable());
+ try {
+ Thread.sleep(MEDIUM_DELAY_MS);
+ assertTrue(tpe.getPoolSize() >= 1);
+ } finally {
+ joinPool(tpe);
+ }
+ }
+
+}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/ThreadPoolExecutorTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/ThreadPoolExecutorTest.java
index ee27e51..9b7fcac 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/ThreadPoolExecutorTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/ThreadPoolExecutorTest.java
@@ -2,13 +2,14 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import java.util.concurrent.*;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.concurrent.atomic.*;
import junit.framework.*;
import java.util.*;
@@ -17,13 +18,13 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
public static Test suite() {
return new TestSuite(ThreadPoolExecutorTest.class);
}
-
+
static class ExtendedTPE extends ThreadPoolExecutor {
volatile boolean beforeCalled = false;
volatile boolean afterCalled = false;
volatile boolean terminatedCalled = false;
public ExtendedTPE() {
- super(1, 1, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new SynchronousQueue<Runnable>());
+ super(1, 1, LONG_DELAY_MS, MILLISECONDS, new SynchronousQueue<Runnable>());
}
protected void beforeExecute(Thread t, Runnable r) {
beforeCalled = true;
@@ -36,50 +37,37 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
}
}
- static class FailingThreadFactory implements ThreadFactory{
+ static class FailingThreadFactory implements ThreadFactory {
int calls = 0;
- public Thread newThread(Runnable r){
+ public Thread newThread(Runnable r) {
if (++calls > 1) return null;
return new Thread(r);
- }
+ }
}
-
+
/**
* execute successfully executes a runnable
*/
- public void testExecute() {
- ThreadPoolExecutor p1 = new ThreadPoolExecutor(1, 1, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testExecute() throws InterruptedException {
+ ThreadPoolExecutor p1 = new ThreadPoolExecutor(1, 1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
try {
- p1.execute(new Runnable() {
- public void run() {
- try {
- Thread.sleep(SHORT_DELAY_MS);
- } catch(InterruptedException e){
- threadUnexpectedException();
- }
- }
- });
+ p1.execute(new ShortRunnable());
Thread.sleep(SMALL_DELAY_MS);
- } catch(InterruptedException e){
- unexpectedException();
- }
- joinPool(p1);
+ } finally {
+ joinPool(p1);
+ }
}
/**
* getActiveCount increases but doesn't overestimate, when a
* thread becomes active
*/
- public void testGetActiveCount() {
- ThreadPoolExecutor p2 = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testGetActiveCount() throws InterruptedException {
+ ThreadPoolExecutor p2 = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
assertEquals(0, p2.getActiveCount());
p2.execute(new MediumRunnable());
- try {
- Thread.sleep(SHORT_DELAY_MS);
- } catch(Exception e){
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
assertEquals(1, p2.getActiveCount());
joinPool(p2);
}
@@ -88,7 +76,7 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
* prestartCoreThread starts a thread if under corePoolSize, else doesn't
*/
public void testPrestartCoreThread() {
- ThreadPoolExecutor p2 = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ ThreadPoolExecutor p2 = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
assertEquals(0, p2.getPoolSize());
assertTrue(p2.prestartCoreThread());
assertEquals(1, p2.getPoolSize());
@@ -103,7 +91,7 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
* prestartAllCoreThreads starts all corePoolSize threads
*/
public void testPrestartAllCoreThreads() {
- ThreadPoolExecutor p2 = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ ThreadPoolExecutor p2 = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
assertEquals(0, p2.getPoolSize());
p2.prestartAllCoreThreads();
assertEquals(2, p2.getPoolSize());
@@ -111,59 +99,55 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
assertEquals(2, p2.getPoolSize());
joinPool(p2);
}
-
+
/**
* getCompletedTaskCount increases, but doesn't overestimate,
* when tasks complete
*/
- public void testGetCompletedTaskCount() {
- ThreadPoolExecutor p2 = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testGetCompletedTaskCount() throws InterruptedException {
+ ThreadPoolExecutor p2 = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
assertEquals(0, p2.getCompletedTaskCount());
p2.execute(new ShortRunnable());
- try {
- Thread.sleep(SMALL_DELAY_MS);
- } catch(Exception e){
- unexpectedException();
- }
+ Thread.sleep(SMALL_DELAY_MS);
assertEquals(1, p2.getCompletedTaskCount());
- try { p2.shutdown(); } catch(SecurityException ok) { return; }
+ try { p2.shutdown(); } catch (SecurityException ok) { return; }
joinPool(p2);
}
-
+
/**
* getCorePoolSize returns size given in constructor if not otherwise set
*/
public void testGetCorePoolSize() {
- ThreadPoolExecutor p1 = new ThreadPoolExecutor(1, 1, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ ThreadPoolExecutor p1 = new ThreadPoolExecutor(1, 1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
assertEquals(1, p1.getCorePoolSize());
joinPool(p1);
}
-
+
/**
* getKeepAliveTime returns value given in constructor if not otherwise set
*/
public void testGetKeepAliveTime() {
- ThreadPoolExecutor p2 = new ThreadPoolExecutor(2, 2, 1000, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ ThreadPoolExecutor p2 = new ThreadPoolExecutor(2, 2, 1000, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
assertEquals(1, p2.getKeepAliveTime(TimeUnit.SECONDS));
joinPool(p2);
}
- /**
+ /**
* getThreadFactory returns factory in constructor if not set
*/
public void testGetThreadFactory() {
ThreadFactory tf = new SimpleThreadFactory();
- ThreadPoolExecutor p = new ThreadPoolExecutor(1,2,LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10), tf, new NoOpREHandler());
+ ThreadPoolExecutor p = new ThreadPoolExecutor(1,2,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10), tf, new NoOpREHandler());
assertSame(tf, p.getThreadFactory());
joinPool(p);
}
- /**
+ /**
* setThreadFactory sets the thread factory returned by getThreadFactory
*/
public void testSetThreadFactory() {
- ThreadPoolExecutor p = new ThreadPoolExecutor(1,2,LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ ThreadPoolExecutor p = new ThreadPoolExecutor(1,2,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
ThreadFactory tf = new SimpleThreadFactory();
p.setThreadFactory(tf);
assertSame(tf, p.getThreadFactory());
@@ -171,11 +155,11 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
}
- /**
+ /**
* setThreadFactory(null) throws NPE
*/
public void testSetThreadFactoryNull() {
- ThreadPoolExecutor p = new ThreadPoolExecutor(1,2,LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ ThreadPoolExecutor p = new ThreadPoolExecutor(1,2,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
try {
p.setThreadFactory(null);
shouldThrow();
@@ -185,22 +169,22 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
}
}
- /**
+ /**
* getRejectedExecutionHandler returns handler in constructor if not set
*/
public void testGetRejectedExecutionHandler() {
RejectedExecutionHandler h = new NoOpREHandler();
- ThreadPoolExecutor p = new ThreadPoolExecutor(1,2,LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10), h);
+ ThreadPoolExecutor p = new ThreadPoolExecutor(1,2,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10), h);
assertSame(h, p.getRejectedExecutionHandler());
joinPool(p);
}
- /**
+ /**
* setRejectedExecutionHandler sets the handler returned by
* getRejectedExecutionHandler
*/
public void testSetRejectedExecutionHandler() {
- ThreadPoolExecutor p = new ThreadPoolExecutor(1,2,LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ ThreadPoolExecutor p = new ThreadPoolExecutor(1,2,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
RejectedExecutionHandler h = new NoOpREHandler();
p.setRejectedExecutionHandler(h);
assertSame(h, p.getRejectedExecutionHandler());
@@ -208,11 +192,11 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
}
- /**
+ /**
* setRejectedExecutionHandler(null) throws NPE
*/
public void testSetRejectedExecutionHandlerNull() {
- ThreadPoolExecutor p = new ThreadPoolExecutor(1,2,LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ ThreadPoolExecutor p = new ThreadPoolExecutor(1,2,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
try {
p.setRejectedExecutionHandler(null);
shouldThrow();
@@ -222,124 +206,108 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
}
}
-
+
/**
* getLargestPoolSize increases, but doesn't overestimate, when
* multiple threads active
*/
- public void testGetLargestPoolSize() {
- ThreadPoolExecutor p2 = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
- try {
- assertEquals(0, p2.getLargestPoolSize());
- p2.execute(new MediumRunnable());
- p2.execute(new MediumRunnable());
- Thread.sleep(SHORT_DELAY_MS);
- assertEquals(2, p2.getLargestPoolSize());
- } catch(Exception e){
- unexpectedException();
- }
+ public void testGetLargestPoolSize() throws InterruptedException {
+ ThreadPoolExecutor p2 = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ assertEquals(0, p2.getLargestPoolSize());
+ p2.execute(new MediumRunnable());
+ p2.execute(new MediumRunnable());
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(2, p2.getLargestPoolSize());
joinPool(p2);
}
-
+
/**
* getMaximumPoolSize returns value given in constructor if not
* otherwise set
*/
public void testGetMaximumPoolSize() {
- ThreadPoolExecutor p2 = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ ThreadPoolExecutor p2 = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
assertEquals(2, p2.getMaximumPoolSize());
joinPool(p2);
}
-
+
/**
* getPoolSize increases, but doesn't overestimate, when threads
* become active
*/
public void testGetPoolSize() {
- ThreadPoolExecutor p1 = new ThreadPoolExecutor(1, 1, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ ThreadPoolExecutor p1 = new ThreadPoolExecutor(1, 1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
assertEquals(0, p1.getPoolSize());
p1.execute(new MediumRunnable());
assertEquals(1, p1.getPoolSize());
joinPool(p1);
}
-
+
/**
* getTaskCount increases, but doesn't overestimate, when tasks submitted
*/
- public void testGetTaskCount() {
- ThreadPoolExecutor p1 = new ThreadPoolExecutor(1, 1, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
- try {
- assertEquals(0, p1.getTaskCount());
- p1.execute(new MediumRunnable());
- Thread.sleep(SHORT_DELAY_MS);
- assertEquals(1, p1.getTaskCount());
- } catch(Exception e){
- unexpectedException();
- }
+ public void testGetTaskCount() throws InterruptedException {
+ ThreadPoolExecutor p1 = new ThreadPoolExecutor(1, 1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ assertEquals(0, p1.getTaskCount());
+ p1.execute(new MediumRunnable());
+ Thread.sleep(SHORT_DELAY_MS);
+ assertEquals(1, p1.getTaskCount());
joinPool(p1);
}
-
+
/**
* isShutDown is false before shutdown, true after
*/
public void testIsShutdown() {
-
- ThreadPoolExecutor p1 = new ThreadPoolExecutor(1, 1, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+
+ ThreadPoolExecutor p1 = new ThreadPoolExecutor(1, 1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
assertFalse(p1.isShutdown());
- try { p1.shutdown(); } catch(SecurityException ok) { return; }
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
assertTrue(p1.isShutdown());
joinPool(p1);
}
-
+
/**
* isTerminated is false before termination, true after
*/
- public void testIsTerminated() {
- ThreadPoolExecutor p1 = new ThreadPoolExecutor(1, 1, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testIsTerminated() throws InterruptedException {
+ ThreadPoolExecutor p1 = new ThreadPoolExecutor(1, 1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
assertFalse(p1.isTerminated());
try {
p1.execute(new MediumRunnable());
} finally {
- try { p1.shutdown(); } catch(SecurityException ok) { return; }
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
}
- try {
- assertTrue(p1.awaitTermination(LONG_DELAY_MS, TimeUnit.MILLISECONDS));
- assertTrue(p1.isTerminated());
- } catch(Exception e){
- unexpectedException();
- }
+ assertTrue(p1.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
+ assertTrue(p1.isTerminated());
}
/**
* isTerminating is not true when running or when terminated
*/
- public void testIsTerminating() {
- ThreadPoolExecutor p1 = new ThreadPoolExecutor(1, 1, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testIsTerminating() throws InterruptedException {
+ ThreadPoolExecutor p1 = new ThreadPoolExecutor(1, 1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
assertFalse(p1.isTerminating());
try {
p1.execute(new SmallRunnable());
assertFalse(p1.isTerminating());
} finally {
- try { p1.shutdown(); } catch(SecurityException ok) { return; }
+ try { p1.shutdown(); } catch (SecurityException ok) { return; }
}
- try {
- assertTrue(p1.awaitTermination(LONG_DELAY_MS, TimeUnit.MILLISECONDS));
- assertTrue(p1.isTerminated());
- assertFalse(p1.isTerminating());
- } catch(Exception e){
- unexpectedException();
- }
+ assertTrue(p1.awaitTermination(LONG_DELAY_MS, MILLISECONDS));
+ assertTrue(p1.isTerminated());
+ assertFalse(p1.isTerminating());
}
/**
* getQueue returns the work queue, which contains queued tasks
*/
- public void testGetQueue() {
+ public void testGetQueue() throws InterruptedException {
BlockingQueue<Runnable> q = new ArrayBlockingQueue<Runnable>(10);
- ThreadPoolExecutor p1 = new ThreadPoolExecutor(1, 1, LONG_DELAY_MS, TimeUnit.MILLISECONDS, q);
+ ThreadPoolExecutor p1 = new ThreadPoolExecutor(1, 1, LONG_DELAY_MS, MILLISECONDS, q);
FutureTask[] tasks = new FutureTask[5];
- for(int i = 0; i < 5; i++){
+ for (int i = 0; i < 5; i++) {
tasks[i] = new FutureTask(new MediumPossiblyInterruptedRunnable(), Boolean.TRUE);
p1.execute(tasks[i]);
}
@@ -352,8 +320,6 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
for (int i = 1; i < 5; ++i)
tasks[i].cancel(true);
p1.shutdownNow();
- } catch(Exception e) {
- unexpectedException();
} finally {
joinPool(p1);
}
@@ -362,11 +328,11 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* remove(task) removes queued task, and fails to remove active task
*/
- public void testRemove() {
+ public void testRemove() throws InterruptedException {
BlockingQueue<Runnable> q = new ArrayBlockingQueue<Runnable>(10);
- ThreadPoolExecutor p1 = new ThreadPoolExecutor(1, 1, LONG_DELAY_MS, TimeUnit.MILLISECONDS, q);
+ ThreadPoolExecutor p1 = new ThreadPoolExecutor(1, 1, LONG_DELAY_MS, MILLISECONDS, q);
FutureTask[] tasks = new FutureTask[5];
- for(int i = 0; i < 5; i++){
+ for (int i = 0; i < 5; i++) {
tasks[i] = new FutureTask(new MediumPossiblyInterruptedRunnable(), Boolean.TRUE);
p1.execute(tasks[i]);
}
@@ -381,8 +347,6 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
assertTrue(q.contains(tasks[3]));
assertTrue(p1.remove(tasks[3]));
assertFalse(q.contains(tasks[3]));
- } catch(Exception e) {
- unexpectedException();
} finally {
joinPool(p1);
}
@@ -392,9 +356,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
* purge removes cancelled tasks from the queue
*/
public void testPurge() {
- ThreadPoolExecutor p1 = new ThreadPoolExecutor(1, 1, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ ThreadPoolExecutor p1 = new ThreadPoolExecutor(1, 1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
FutureTask[] tasks = new FutureTask[5];
- for(int i = 0; i < 5; i++){
+ for (int i = 0; i < 5; i++) {
tasks[i] = new FutureTask(new MediumPossiblyInterruptedRunnable(), Boolean.TRUE);
p1.execute(tasks[i]);
}
@@ -410,355 +374,334 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
* shutDownNow returns a list containing tasks that were not run
*/
public void testShutDownNow() {
- ThreadPoolExecutor p1 = new ThreadPoolExecutor(1, 1, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ ThreadPoolExecutor p1 = new ThreadPoolExecutor(1, 1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
List l;
try {
- for(int i = 0; i < 5; i++)
+ for (int i = 0; i < 5; i++)
p1.execute(new MediumPossiblyInterruptedRunnable());
}
finally {
try {
l = p1.shutdownNow();
} catch (SecurityException ok) { return; }
-
}
assertTrue(p1.isShutdown());
assertTrue(l.size() <= 4);
}
// Exception Tests
-
- /**
- * Constructor throws if corePoolSize argument is less than zero
+
+ /**
+ * Constructor throws if corePoolSize argument is less than zero
*/
public void testConstructor1() {
try {
- new ThreadPoolExecutor(-1,1,LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ new ThreadPoolExecutor(-1,1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
shouldThrow();
- }
- catch (IllegalArgumentException success){}
+ } catch (IllegalArgumentException success) {}
}
-
- /**
- * Constructor throws if maximumPoolSize is less than zero
+
+ /**
+ * Constructor throws if maximumPoolSize is less than zero
*/
public void testConstructor2() {
try {
- new ThreadPoolExecutor(1,-1,LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ new ThreadPoolExecutor(1,-1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
shouldThrow();
- }
- catch (IllegalArgumentException success){}
+ } catch (IllegalArgumentException success) {}
}
-
- /**
- * Constructor throws if maximumPoolSize is equal to zero
+
+ /**
+ * Constructor throws if maximumPoolSize is equal to zero
*/
public void testConstructor3() {
try {
- new ThreadPoolExecutor(1,0,LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ new ThreadPoolExecutor(1,0,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
shouldThrow();
- }
- catch (IllegalArgumentException success){}
+ } catch (IllegalArgumentException success) {}
}
- /**
- * Constructor throws if keepAliveTime is less than zero
+ /**
+ * Constructor throws if keepAliveTime is less than zero
*/
public void testConstructor4() {
try {
- new ThreadPoolExecutor(1,2,-1L,TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ new ThreadPoolExecutor(1,2,-1L,MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
shouldThrow();
- }
- catch (IllegalArgumentException success){}
+ } catch (IllegalArgumentException success) {}
}
- /**
- * Constructor throws if corePoolSize is greater than the maximumPoolSize
+ /**
+ * Constructor throws if corePoolSize is greater than the maximumPoolSize
*/
public void testConstructor5() {
try {
- new ThreadPoolExecutor(2,1,LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ new ThreadPoolExecutor(2,1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
shouldThrow();
- }
- catch (IllegalArgumentException success){}
+ } catch (IllegalArgumentException success) {}
}
-
- /**
- * Constructor throws if workQueue is set to null
+
+ /**
+ * Constructor throws if workQueue is set to null
*/
public void testConstructorNullPointerException() {
try {
- new ThreadPoolExecutor(1,2,LONG_DELAY_MS, TimeUnit.MILLISECONDS,null);
+ new ThreadPoolExecutor(1,2,LONG_DELAY_MS, MILLISECONDS,null);
shouldThrow();
- }
- catch (NullPointerException success){}
+ } catch (NullPointerException success) {}
}
-
-
- /**
- * Constructor throws if corePoolSize argument is less than zero
+
+
+ /**
+ * Constructor throws if corePoolSize argument is less than zero
*/
public void testConstructor6() {
try {
- new ThreadPoolExecutor(-1,1,LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory());
+ new ThreadPoolExecutor(-1,1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory());
shouldThrow();
- } catch (IllegalArgumentException success){}
+ } catch (IllegalArgumentException success) {}
}
-
- /**
- * Constructor throws if maximumPoolSize is less than zero
+
+ /**
+ * Constructor throws if maximumPoolSize is less than zero
*/
public void testConstructor7() {
try {
- new ThreadPoolExecutor(1,-1,LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory());
+ new ThreadPoolExecutor(1,-1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory());
shouldThrow();
- }
- catch (IllegalArgumentException success){}
+ } catch (IllegalArgumentException success) {}
}
- /**
- * Constructor throws if maximumPoolSize is equal to zero
+ /**
+ * Constructor throws if maximumPoolSize is equal to zero
*/
public void testConstructor8() {
try {
- new ThreadPoolExecutor(1,0,LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory());
+ new ThreadPoolExecutor(1,0,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory());
shouldThrow();
- }
- catch (IllegalArgumentException success){}
+ } catch (IllegalArgumentException success) {}
}
- /**
- * Constructor throws if keepAliveTime is less than zero
+ /**
+ * Constructor throws if keepAliveTime is less than zero
*/
public void testConstructor9() {
try {
- new ThreadPoolExecutor(1,2,-1L,TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory());
+ new ThreadPoolExecutor(1,2,-1L,MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory());
shouldThrow();
- }
- catch (IllegalArgumentException success){}
+ } catch (IllegalArgumentException success) {}
}
- /**
- * Constructor throws if corePoolSize is greater than the maximumPoolSize
+ /**
+ * Constructor throws if corePoolSize is greater than the maximumPoolSize
*/
public void testConstructor10() {
try {
- new ThreadPoolExecutor(2,1,LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory());
+ new ThreadPoolExecutor(2,1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory());
shouldThrow();
- }
- catch (IllegalArgumentException success){}
+ } catch (IllegalArgumentException success) {}
}
- /**
- * Constructor throws if workQueue is set to null
+ /**
+ * Constructor throws if workQueue is set to null
*/
public void testConstructorNullPointerException2() {
try {
- new ThreadPoolExecutor(1,2,LONG_DELAY_MS, TimeUnit.MILLISECONDS,null,new SimpleThreadFactory());
+ new ThreadPoolExecutor(1,2,LONG_DELAY_MS, MILLISECONDS,null,new SimpleThreadFactory());
shouldThrow();
- }
- catch (NullPointerException success){}
+ } catch (NullPointerException success) {}
}
- /**
- * Constructor throws if threadFactory is set to null
+ /**
+ * Constructor throws if threadFactory is set to null
*/
public void testConstructorNullPointerException3() {
try {
ThreadFactory f = null;
- new ThreadPoolExecutor(1,2,LONG_DELAY_MS, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<Runnable>(10),f);
+ new ThreadPoolExecutor(1,2,LONG_DELAY_MS, MILLISECONDS,new ArrayBlockingQueue<Runnable>(10),f);
shouldThrow();
- }
- catch (NullPointerException success){}
+ } catch (NullPointerException success) {}
}
-
-
- /**
- * Constructor throws if corePoolSize argument is less than zero
+
+
+ /**
+ * Constructor throws if corePoolSize argument is less than zero
*/
public void testConstructor11() {
try {
- new ThreadPoolExecutor(-1,1,LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new NoOpREHandler());
+ new ThreadPoolExecutor(-1,1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new NoOpREHandler());
shouldThrow();
- }
- catch (IllegalArgumentException success){}
+ } catch (IllegalArgumentException success) {}
}
- /**
- * Constructor throws if maximumPoolSize is less than zero
+ /**
+ * Constructor throws if maximumPoolSize is less than zero
*/
public void testConstructor12() {
try {
- new ThreadPoolExecutor(1,-1,LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new NoOpREHandler());
+ new ThreadPoolExecutor(1,-1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new NoOpREHandler());
shouldThrow();
- }
- catch (IllegalArgumentException success){}
+ } catch (IllegalArgumentException success) {}
}
- /**
- * Constructor throws if maximumPoolSize is equal to zero
+ /**
+ * Constructor throws if maximumPoolSize is equal to zero
*/
public void testConstructor13() {
try {
- new ThreadPoolExecutor(1,0,LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new NoOpREHandler());
+ new ThreadPoolExecutor(1,0,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new NoOpREHandler());
shouldThrow();
- }
- catch (IllegalArgumentException success){}
+ } catch (IllegalArgumentException success) {}
}
- /**
- * Constructor throws if keepAliveTime is less than zero
+ /**
+ * Constructor throws if keepAliveTime is less than zero
*/
public void testConstructor14() {
try {
- new ThreadPoolExecutor(1,2,-1L,TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new NoOpREHandler());
+ new ThreadPoolExecutor(1,2,-1L,MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new NoOpREHandler());
shouldThrow();
- }
- catch (IllegalArgumentException success){}
+ } catch (IllegalArgumentException success) {}
}
- /**
- * Constructor throws if corePoolSize is greater than the maximumPoolSize
+ /**
+ * Constructor throws if corePoolSize is greater than the maximumPoolSize
*/
public void testConstructor15() {
try {
- new ThreadPoolExecutor(2,1,LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new NoOpREHandler());
+ new ThreadPoolExecutor(2,1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new NoOpREHandler());
shouldThrow();
- }
- catch (IllegalArgumentException success){}
+ } catch (IllegalArgumentException success) {}
}
- /**
- * Constructor throws if workQueue is set to null
+ /**
+ * Constructor throws if workQueue is set to null
*/
public void testConstructorNullPointerException4() {
try {
- new ThreadPoolExecutor(1,2,LONG_DELAY_MS, TimeUnit.MILLISECONDS,null,new NoOpREHandler());
+ new ThreadPoolExecutor(1,2,LONG_DELAY_MS, MILLISECONDS,null,new NoOpREHandler());
shouldThrow();
- }
- catch (NullPointerException success){}
+ } catch (NullPointerException success) {}
}
- /**
- * Constructor throws if handler is set to null
+ /**
+ * Constructor throws if handler is set to null
*/
public void testConstructorNullPointerException5() {
try {
RejectedExecutionHandler r = null;
- new ThreadPoolExecutor(1,2,LONG_DELAY_MS, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<Runnable>(10),r);
+ new ThreadPoolExecutor(1,2,LONG_DELAY_MS, MILLISECONDS,new ArrayBlockingQueue<Runnable>(10),r);
shouldThrow();
- }
- catch (NullPointerException success){}
+ } catch (NullPointerException success) {}
}
-
- /**
- * Constructor throws if corePoolSize argument is less than zero
+
+ /**
+ * Constructor throws if corePoolSize argument is less than zero
*/
public void testConstructor16() {
try {
- new ThreadPoolExecutor(-1,1,LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory(),new NoOpREHandler());
+ new ThreadPoolExecutor(-1,1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory(),new NoOpREHandler());
shouldThrow();
- }
- catch (IllegalArgumentException success){}
+ } catch (IllegalArgumentException success) {}
}
- /**
- * Constructor throws if maximumPoolSize is less than zero
+ /**
+ * Constructor throws if maximumPoolSize is less than zero
*/
public void testConstructor17() {
try {
- new ThreadPoolExecutor(1,-1,LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory(),new NoOpREHandler());
+ new ThreadPoolExecutor(1,-1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory(),new NoOpREHandler());
shouldThrow();
- }
- catch (IllegalArgumentException success){}
+ } catch (IllegalArgumentException success) {}
}
- /**
- * Constructor throws if maximumPoolSize is equal to zero
+ /**
+ * Constructor throws if maximumPoolSize is equal to zero
*/
public void testConstructor18() {
try {
- new ThreadPoolExecutor(1,0,LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory(),new NoOpREHandler());
+ new ThreadPoolExecutor(1,0,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory(),new NoOpREHandler());
shouldThrow();
- }
- catch (IllegalArgumentException success){}
+ } catch (IllegalArgumentException success) {}
}
- /**
- * Constructor throws if keepAliveTime is less than zero
+ /**
+ * Constructor throws if keepAliveTime is less than zero
*/
public void testConstructor19() {
try {
- new ThreadPoolExecutor(1,2,-1L,TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory(),new NoOpREHandler());
+ new ThreadPoolExecutor(1,2,-1L,MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory(),new NoOpREHandler());
shouldThrow();
- }
- catch (IllegalArgumentException success){}
+ } catch (IllegalArgumentException success) {}
}
- /**
- * Constructor throws if corePoolSize is greater than the maximumPoolSize
+ /**
+ * Constructor throws if corePoolSize is greater than the maximumPoolSize
*/
public void testConstructor20() {
try {
- new ThreadPoolExecutor(2,1,LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory(),new NoOpREHandler());
+ new ThreadPoolExecutor(2,1,LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory(),new NoOpREHandler());
shouldThrow();
- }
- catch (IllegalArgumentException success){}
+ } catch (IllegalArgumentException success) {}
}
- /**
- * Constructor throws if workQueue is set to null
+ /**
+ * Constructor throws if workQueue is set to null
*/
public void testConstructorNullPointerException6() {
try {
- new ThreadPoolExecutor(1,2,LONG_DELAY_MS, TimeUnit.MILLISECONDS,null,new SimpleThreadFactory(),new NoOpREHandler());
+ new ThreadPoolExecutor(1,2,LONG_DELAY_MS, MILLISECONDS,null,new SimpleThreadFactory(),new NoOpREHandler());
shouldThrow();
- }
- catch (NullPointerException success){}
+ } catch (NullPointerException success) {}
}
- /**
- * Constructor throws if handler is set to null
+ /**
+ * Constructor throws if handler is set to null
*/
public void testConstructorNullPointerException7() {
try {
RejectedExecutionHandler r = null;
- new ThreadPoolExecutor(1,2,LONG_DELAY_MS, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory(),r);
+ new ThreadPoolExecutor(1,2,LONG_DELAY_MS, MILLISECONDS,new ArrayBlockingQueue<Runnable>(10),new SimpleThreadFactory(),r);
shouldThrow();
- }
- catch (NullPointerException success){}
+ } catch (NullPointerException success) {}
}
- /**
- * Constructor throws if ThreadFactory is set top null
+ /**
+ * Constructor throws if ThreadFactory is set top null
*/
public void testConstructorNullPointerException8() {
try {
ThreadFactory f = null;
- new ThreadPoolExecutor(1,2,LONG_DELAY_MS, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<Runnable>(10),f,new NoOpREHandler());
+ new ThreadPoolExecutor(1,2,LONG_DELAY_MS, MILLISECONDS,new ArrayBlockingQueue<Runnable>(10),f,new NoOpREHandler());
shouldThrow();
- }
- catch (NullPointerException successdn8){}
+ } catch (NullPointerException success) {}
}
-
+
/**
* execute throws RejectedExecutionException
* if saturated.
*/
public void testSaturatedExecute() {
- ThreadPoolExecutor p = new ThreadPoolExecutor(1,1, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1));
+ ThreadPoolExecutor p =
+ new ThreadPoolExecutor(1, 1,
+ LONG_DELAY_MS, MILLISECONDS,
+ new ArrayBlockingQueue<Runnable>(1));
try {
-
- for(int i = 0; i < 5; ++i){
+ for (int i = 0; i < 2; ++i)
p.execute(new MediumRunnable());
+ for (int i = 0; i < 2; ++i) {
+ try {
+ p.execute(new MediumRunnable());
+ shouldThrow();
+ } catch (RejectedExecutionException success) {}
}
- shouldThrow();
- } catch(RejectedExecutionException success){}
- joinPool(p);
+ } finally {
+ joinPool(p);
+ }
}
/**
@@ -766,24 +709,22 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
*/
public void testSaturatedExecute2() {
RejectedExecutionHandler h = new ThreadPoolExecutor.CallerRunsPolicy();
- ThreadPoolExecutor p = new ThreadPoolExecutor(1,1, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), h);
+ ThreadPoolExecutor p = new ThreadPoolExecutor(1,1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), h);
try {
-
+
TrackedNoOpRunnable[] tasks = new TrackedNoOpRunnable[5];
- for(int i = 0; i < 5; ++i){
+ for (int i = 0; i < 5; ++i) {
tasks[i] = new TrackedNoOpRunnable();
}
TrackedLongRunnable mr = new TrackedLongRunnable();
p.execute(mr);
- for(int i = 0; i < 5; ++i){
+ for (int i = 0; i < 5; ++i) {
p.execute(tasks[i]);
}
- for(int i = 1; i < 5; ++i) {
+ for (int i = 1; i < 5; ++i) {
assertTrue(tasks[i].done);
}
- try { p.shutdownNow(); } catch(SecurityException ok) { return; }
- } catch(RejectedExecutionException ex){
- unexpectedException();
+ try { p.shutdownNow(); } catch (SecurityException ok) { return; }
} finally {
joinPool(p);
}
@@ -794,23 +735,21 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
*/
public void testSaturatedExecute3() {
RejectedExecutionHandler h = new ThreadPoolExecutor.DiscardPolicy();
- ThreadPoolExecutor p = new ThreadPoolExecutor(1,1, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), h);
+ ThreadPoolExecutor p = new ThreadPoolExecutor(1,1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), h);
try {
-
+
TrackedNoOpRunnable[] tasks = new TrackedNoOpRunnable[5];
- for(int i = 0; i < 5; ++i){
+ for (int i = 0; i < 5; ++i) {
tasks[i] = new TrackedNoOpRunnable();
}
p.execute(new TrackedLongRunnable());
- for(int i = 0; i < 5; ++i){
+ for (int i = 0; i < 5; ++i) {
p.execute(tasks[i]);
}
- for(int i = 0; i < 5; ++i){
+ for (int i = 0; i < 5; ++i) {
assertFalse(tasks[i].done);
}
- try { p.shutdownNow(); } catch(SecurityException ok) { return; }
- } catch(RejectedExecutionException ex){
- unexpectedException();
+ try { p.shutdownNow(); } catch (SecurityException ok) { return; }
} finally {
joinPool(p);
}
@@ -821,7 +760,7 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
*/
public void testSaturatedExecute4() {
RejectedExecutionHandler h = new ThreadPoolExecutor.DiscardOldestPolicy();
- ThreadPoolExecutor p = new ThreadPoolExecutor(1,1, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), h);
+ ThreadPoolExecutor p = new ThreadPoolExecutor(1,1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), h);
try {
p.execute(new TrackedLongRunnable());
TrackedLongRunnable r2 = new TrackedLongRunnable();
@@ -831,9 +770,7 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
p.execute(r3);
assertFalse(p.getQueue().contains(r2));
assertTrue(p.getQueue().contains(r3));
- try { p.shutdownNow(); } catch(SecurityException ok) { return; }
- } catch(RejectedExecutionException ex){
- unexpectedException();
+ try { p.shutdownNow(); } catch (SecurityException ok) { return; }
} finally {
joinPool(p);
}
@@ -843,14 +780,14 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
* execute throws RejectedExecutionException if shutdown
*/
public void testRejectedExecutionExceptionOnShutdown() {
- ThreadPoolExecutor tpe =
- new ThreadPoolExecutor(1,1,LONG_DELAY_MS, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<Runnable>(1));
- try { tpe.shutdown(); } catch(SecurityException ok) { return; }
+ ThreadPoolExecutor tpe =
+ new ThreadPoolExecutor(1,1,LONG_DELAY_MS, MILLISECONDS,new ArrayBlockingQueue<Runnable>(1));
+ try { tpe.shutdown(); } catch (SecurityException ok) { return; }
try {
tpe.execute(new NoOpRunnable());
shouldThrow();
- } catch(RejectedExecutionException success){}
-
+ } catch (RejectedExecutionException success) {}
+
joinPool(tpe);
}
@@ -859,15 +796,13 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
*/
public void testCallerRunsOnShutdown() {
RejectedExecutionHandler h = new ThreadPoolExecutor.CallerRunsPolicy();
- ThreadPoolExecutor p = new ThreadPoolExecutor(1,1, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), h);
+ ThreadPoolExecutor p = new ThreadPoolExecutor(1,1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), h);
- try { p.shutdown(); } catch(SecurityException ok) { return; }
+ try { p.shutdown(); } catch (SecurityException ok) { return; }
try {
TrackedNoOpRunnable r = new TrackedNoOpRunnable();
p.execute(r);
assertFalse(r.done);
- } catch(RejectedExecutionException success){
- unexpectedException();
} finally {
joinPool(p);
}
@@ -878,15 +813,13 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
*/
public void testDiscardOnShutdown() {
RejectedExecutionHandler h = new ThreadPoolExecutor.DiscardPolicy();
- ThreadPoolExecutor p = new ThreadPoolExecutor(1,1, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), h);
+ ThreadPoolExecutor p = new ThreadPoolExecutor(1,1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), h);
- try { p.shutdown(); } catch(SecurityException ok) { return; }
+ try { p.shutdown(); } catch (SecurityException ok) { return; }
try {
TrackedNoOpRunnable r = new TrackedNoOpRunnable();
p.execute(r);
assertFalse(r.done);
- } catch(RejectedExecutionException success){
- unexpectedException();
} finally {
joinPool(p);
}
@@ -898,15 +831,13 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
*/
public void testDiscardOldestOnShutdown() {
RejectedExecutionHandler h = new ThreadPoolExecutor.DiscardOldestPolicy();
- ThreadPoolExecutor p = new ThreadPoolExecutor(1,1, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), h);
+ ThreadPoolExecutor p = new ThreadPoolExecutor(1,1, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), h);
- try { p.shutdown(); } catch(SecurityException ok) { return; }
+ try { p.shutdown(); } catch (SecurityException ok) { return; }
try {
TrackedNoOpRunnable r = new TrackedNoOpRunnable();
p.execute(r);
assertFalse(r.done);
- } catch(RejectedExecutionException success){
- unexpectedException();
} finally {
joinPool(p);
}
@@ -917,89 +848,87 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
* execute (null) throws NPE
*/
public void testExecuteNull() {
- ThreadPoolExecutor tpe = null;
+ ThreadPoolExecutor tpe = new ThreadPoolExecutor(1,2,LONG_DELAY_MS, MILLISECONDS,new ArrayBlockingQueue<Runnable>(10));
try {
- tpe = new ThreadPoolExecutor(1,2,LONG_DELAY_MS, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<Runnable>(10));
tpe.execute(null);
shouldThrow();
- } catch(NullPointerException success){}
-
+ } catch (NullPointerException success) {}
+
joinPool(tpe);
}
-
+
/**
* setCorePoolSize of negative value throws IllegalArgumentException
*/
public void testCorePoolSizeIllegalArgumentException() {
- ThreadPoolExecutor tpe = null;
- try {
- tpe = new ThreadPoolExecutor(1,2,LONG_DELAY_MS, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<Runnable>(10));
- } catch(Exception e){}
+ ThreadPoolExecutor tpe =
+ new ThreadPoolExecutor(1, 2,
+ LONG_DELAY_MS, MILLISECONDS,
+ new ArrayBlockingQueue<Runnable>(10));
try {
tpe.setCorePoolSize(-1);
shouldThrow();
- } catch(IllegalArgumentException success){
+ } catch (IllegalArgumentException success) {
} finally {
- try { tpe.shutdown(); } catch(SecurityException ok) { return; }
+ try { tpe.shutdown(); } catch (SecurityException ok) { return; }
}
joinPool(tpe);
- }
+ }
/**
* setMaximumPoolSize(int) throws IllegalArgumentException if
* given a value less the core pool size
- */
+ */
public void testMaximumPoolSizeIllegalArgumentException() {
- ThreadPoolExecutor tpe = null;
- try {
- tpe = new ThreadPoolExecutor(2,3,LONG_DELAY_MS, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<Runnable>(10));
- } catch(Exception e){}
+ ThreadPoolExecutor tpe =
+ new ThreadPoolExecutor(2, 3,
+ LONG_DELAY_MS, MILLISECONDS,
+ new ArrayBlockingQueue<Runnable>(10));
try {
tpe.setMaximumPoolSize(1);
shouldThrow();
- } catch(IllegalArgumentException success){
+ } catch (IllegalArgumentException success) {
} finally {
- try { tpe.shutdown(); } catch(SecurityException ok) { return; }
+ try { tpe.shutdown(); } catch (SecurityException ok) { return; }
}
joinPool(tpe);
}
-
+
/**
* setMaximumPoolSize throws IllegalArgumentException
* if given a negative value
*/
public void testMaximumPoolSizeIllegalArgumentException2() {
- ThreadPoolExecutor tpe = null;
- try {
- tpe = new ThreadPoolExecutor(2,3,LONG_DELAY_MS, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<Runnable>(10));
- } catch(Exception e){}
+ ThreadPoolExecutor tpe =
+ new ThreadPoolExecutor(2, 3,
+ LONG_DELAY_MS, MILLISECONDS,
+ new ArrayBlockingQueue<Runnable>(10));
try {
tpe.setMaximumPoolSize(-1);
shouldThrow();
- } catch(IllegalArgumentException success){
+ } catch (IllegalArgumentException success) {
} finally {
- try { tpe.shutdown(); } catch(SecurityException ok) { return; }
+ try { tpe.shutdown(); } catch (SecurityException ok) { return; }
}
joinPool(tpe);
}
-
+
/**
* setKeepAliveTime throws IllegalArgumentException
* when given a negative value
*/
public void testKeepAliveTimeIllegalArgumentException() {
- ThreadPoolExecutor tpe = null;
+ ThreadPoolExecutor tpe =
+ new ThreadPoolExecutor(2, 3,
+ LONG_DELAY_MS, MILLISECONDS,
+ new ArrayBlockingQueue<Runnable>(10));
try {
- tpe = new ThreadPoolExecutor(2,3,LONG_DELAY_MS, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<Runnable>(10));
- } catch(Exception e){}
-
- try {
- tpe.setKeepAliveTime(-1,TimeUnit.MILLISECONDS);
+ tpe.setKeepAliveTime(-1,MILLISECONDS);
shouldThrow();
- } catch(IllegalArgumentException success){
+ } catch (IllegalArgumentException success) {
} finally {
- try { tpe.shutdown(); } catch(SecurityException ok) { return; }
+ try { tpe.shutdown(); } catch (SecurityException ok) { return; }
}
joinPool(tpe);
}
@@ -1009,7 +938,7 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
*/
public void testTerminated() {
ExtendedTPE tpe = new ExtendedTPE();
- try { tpe.shutdown(); } catch(SecurityException ok) { return; }
+ try { tpe.shutdown(); } catch (SecurityException ok) { return; }
assertTrue(tpe.terminatedCalled);
joinPool(tpe);
}
@@ -1017,7 +946,7 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* beforeExecute and afterExecute are called when executing task
*/
- public void testBeforeAfter() {
+ public void testBeforeAfter() throws InterruptedException {
ExtendedTPE tpe = new ExtendedTPE();
try {
TrackedNoOpRunnable r = new TrackedNoOpRunnable();
@@ -1026,10 +955,7 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
assertTrue(r.done);
assertTrue(tpe.beforeCalled);
assertTrue(tpe.afterCalled);
- try { tpe.shutdown(); } catch(SecurityException ok) { return; }
- }
- catch(Exception ex) {
- unexpectedException();
+ try { tpe.shutdown(); } catch (SecurityException ok) { return; }
} finally {
joinPool(tpe);
}
@@ -1038,18 +964,12 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* completed submit of callable returns result
*/
- public void testSubmitCallable() {
- ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testSubmitCallable() throws Exception {
+ ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
try {
Future<String> future = e.submit(new StringTask());
String result = future.get();
assertSame(TEST_STRING, result);
- }
- catch (ExecutionException ex) {
- unexpectedException();
- }
- catch (InterruptedException ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -1058,18 +978,12 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* completed submit of runnable returns successfully
*/
- public void testSubmitRunnable() {
- ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testSubmitRunnable() throws Exception {
+ ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
try {
Future<?> future = e.submit(new NoOpRunnable());
future.get();
assertTrue(future.isDone());
- }
- catch (ExecutionException ex) {
- unexpectedException();
- }
- catch (InterruptedException ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -1078,37 +992,27 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* completed submit of (runnable, result) returns result
*/
- public void testSubmitRunnable2() {
- ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testSubmitRunnable2() throws Exception {
+ ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
try {
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();
} finally {
joinPool(e);
}
}
-
-
-
/**
* invokeAny(null) throws NPE
*/
- public void testInvokeAny1() {
- ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testInvokeAny1() throws Exception {
+ ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
try {
e.invokeAny(null);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -1117,13 +1021,12 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* invokeAny(empty collection) throws IAE
*/
- public void testInvokeAny2() {
- ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testInvokeAny2() throws Exception {
+ ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
try {
e.invokeAny(new ArrayList<Callable<String>>());
+ shouldThrow();
} catch (IllegalArgumentException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -1132,17 +1035,18 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* invokeAny(c) throws NPE if c has null elements
*/
- public void testInvokeAny3() {
- ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testInvokeAny3() throws Exception {
+ CountDownLatch latch = new CountDownLatch(1);
+ ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(latchAwaitingStringTask(latch));
+ l.add(null);
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
- l.add(new StringTask());
- l.add(null);
e.invokeAny(l);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
+ latch.countDown();
joinPool(e);
}
}
@@ -1150,15 +1054,15 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* invokeAny(c) throws ExecutionException if no task completes
*/
- public void testInvokeAny4() {
- ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testInvokeAny4() throws Exception {
+ ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new NPETask());
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
- l.add(new NPETask());
e.invokeAny(l);
+ shouldThrow();
} catch (ExecutionException success) {
- } catch(Exception ex) {
- unexpectedException();
+ assertTrue(success.getCause() instanceof NullPointerException);
} finally {
joinPool(e);
}
@@ -1167,17 +1071,14 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* invokeAny(c) returns result of some task
*/
- public void testInvokeAny5() {
- ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testInvokeAny5() throws Exception {
+ ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<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);
}
@@ -1186,13 +1087,12 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* invokeAll(null) throws NPE
*/
- public void testInvokeAll1() {
- ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testInvokeAll1() throws Exception {
+ ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
try {
e.invokeAll(null);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -1201,13 +1101,11 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* invokeAll(empty collection) returns empty collection
*/
- public void testInvokeAll2() {
- ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testInvokeAll2() throws InterruptedException {
+ ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
try {
List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>());
assertTrue(r.isEmpty());
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -1216,16 +1114,15 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* invokeAll(c) throws NPE if c has null elements
*/
- public void testInvokeAll3() {
- ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testInvokeAll3() throws Exception {
+ ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(null);
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
- l.add(new StringTask());
- l.add(null);
e.invokeAll(l);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -1234,18 +1131,19 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* get of element of invokeAll(c) throws exception on failed task
*/
- public void testInvokeAll4() {
- ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testInvokeAll4() throws Exception {
+ ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<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();
+ List<Future<String>> futures = e.invokeAll(l);
+ assertEquals(1, futures.size());
+ try {
+ futures.get(0).get();
+ shouldThrow();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof NullPointerException);
+ }
} finally {
joinPool(e);
}
@@ -1254,19 +1152,16 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* invokeAll(c) returns results of all completed tasks
*/
- public void testInvokeAll5() {
- ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testInvokeAll5() throws Exception {
+ ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<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();
+ List<Future<String>> futures = e.invokeAll(l);
+ assertEquals(2, futures.size());
+ for (Future<String> future : futures)
+ assertSame(TEST_STRING, future.get());
} finally {
joinPool(e);
}
@@ -1277,13 +1172,12 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* timed invokeAny(null) throws NPE
*/
- public void testTimedInvokeAny1() {
- ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testTimedInvokeAny1() throws Exception {
+ ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
try {
- e.invokeAny(null, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ e.invokeAny(null, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -1292,15 +1186,14 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* timed invokeAny(,,null) throws NPE
*/
- public void testTimedInvokeAnyNullTimeUnit() {
- ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testTimedInvokeAnyNullTimeUnit() throws Exception {
+ ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
- l.add(new StringTask());
e.invokeAny(l, MEDIUM_DELAY_MS, null);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -1309,13 +1202,12 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* timed invokeAny(empty collection) throws IAE
*/
- public void testTimedInvokeAny2() {
- ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testTimedInvokeAny2() throws Exception {
+ ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
try {
- e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ e.invokeAny(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
} catch (IllegalArgumentException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -1324,18 +1216,18 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* timed invokeAny(c) throws NPE if c has null elements
*/
- public void testTimedInvokeAny3() {
- ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testTimedInvokeAny3() throws Exception {
+ CountDownLatch latch = new CountDownLatch(1);
+ ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(latchAwaitingStringTask(latch));
+ l.add(null);
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
- l.add(new StringTask());
- l.add(null);
- e.invokeAny(l, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- ex.printStackTrace();
- unexpectedException();
} finally {
+ latch.countDown();
joinPool(e);
}
}
@@ -1343,15 +1235,15 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* timed invokeAny(c) throws ExecutionException if no task completes
*/
- public void testTimedInvokeAny4() {
- ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testTimedInvokeAny4() throws Exception {
+ ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new NPETask());
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();
+ e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof NullPointerException);
} finally {
joinPool(e);
}
@@ -1360,17 +1252,14 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* timed invokeAny(c) returns result of some task
*/
- public void testTimedInvokeAny5() {
- ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testTimedInvokeAny5() throws Exception {
+ ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<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);
+ String result = e.invokeAny(l, MEDIUM_DELAY_MS, MILLISECONDS);
assertSame(TEST_STRING, result);
- } catch (ExecutionException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -1379,13 +1268,12 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* timed invokeAll(null) throws NPE
*/
- public void testTimedInvokeAll1() {
- ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testTimedInvokeAll1() throws Exception {
+ ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
try {
- e.invokeAll(null, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ e.invokeAll(null, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -1394,15 +1282,14 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* timed invokeAll(,,null) throws NPE
*/
- public void testTimedInvokeAllNullTimeUnit() {
- ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testTimedInvokeAllNullTimeUnit() throws Exception {
+ ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
- l.add(new StringTask());
e.invokeAll(l, MEDIUM_DELAY_MS, null);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -1411,13 +1298,11 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* timed invokeAll(empty collection) returns empty collection
*/
- public void testTimedInvokeAll2() {
- ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testTimedInvokeAll2() throws InterruptedException {
+ ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
try {
- List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ List<Future<String>> r = e.invokeAll(new ArrayList<Callable<String>>(), MEDIUM_DELAY_MS, MILLISECONDS);
assertTrue(r.isEmpty());
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -1426,16 +1311,15 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* timed invokeAll(c) throws NPE if c has null elements
*/
- public void testTimedInvokeAll3() {
- ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testTimedInvokeAll3() throws Exception {
+ ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new StringTask());
+ l.add(null);
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
- l.add(new StringTask());
- l.add(null);
- e.invokeAll(l, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
+ e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ shouldThrow();
} catch (NullPointerException success) {
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -1444,18 +1328,18 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* get of element of invokeAll(c) throws exception on failed task
*/
- public void testTimedInvokeAll4() {
- ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testTimedInvokeAll4() throws Exception {
+ ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
+ l.add(new NPETask());
+ List<Future<String>> futures =
+ e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ assertEquals(1, futures.size());
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();
+ futures.get(0).get();
+ shouldThrow();
+ } catch (ExecutionException success) {
+ assertTrue(success.getCause() instanceof NullPointerException);
} finally {
joinPool(e);
}
@@ -1464,19 +1348,17 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* timed invokeAll(c) returns results of all completed tasks
*/
- public void testTimedInvokeAll5() {
- ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testTimedInvokeAll5() throws Exception {
+ ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<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();
+ List<Future<String>> futures =
+ e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
+ assertEquals(2, futures.size());
+ for (Future<String> future : futures)
+ assertSame(TEST_STRING, future.get());
} finally {
joinPool(e);
}
@@ -1485,16 +1367,17 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
/**
* timed invokeAll(c) cancels tasks not completed by timeout
*/
- public void testTimedInvokeAll6() {
- ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ public void testTimedInvokeAll6() throws Exception {
+ ExecutorService e = new ThreadPoolExecutor(2, 2, LONG_DELAY_MS, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<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, SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
- assertEquals(3, result.size());
- Iterator<Future<String>> it = result.iterator();
+ List<Future<String>> futures =
+ e.invokeAll(l, SHORT_DELAY_MS, MILLISECONDS);
+ assertEquals(3, futures.size());
+ Iterator<Future<String>> it = futures.iterator();
Future<String> f1 = it.next();
Future<String> f2 = it.next();
Future<String> f3 = it.next();
@@ -1503,8 +1386,6 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
assertTrue(f3.isDone());
assertFalse(f1.isCancelled());
assertTrue(f2.isCancelled());
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
@@ -1514,34 +1395,71 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
* Execution continues if there is at least one thread even if
* thread factory fails to create more
*/
- public void testFailingThreadFactory() {
- ExecutorService e = new ThreadPoolExecutor(100, 100, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), new FailingThreadFactory());
+ public void testFailingThreadFactory() throws InterruptedException {
+ ExecutorService e = new ThreadPoolExecutor(100, 100, LONG_DELAY_MS, MILLISECONDS, new LinkedBlockingQueue<Runnable>(), new FailingThreadFactory());
try {
- ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<Callable<String>>();
for (int k = 0; k < 100; ++k) {
e.execute(new NoOpRunnable());
}
Thread.sleep(LONG_DELAY_MS);
- } catch(Exception ex) {
- unexpectedException();
} finally {
joinPool(e);
}
}
/**
+ * allowsCoreThreadTimeOut is by default false.
+ */
+ public void testAllowsCoreThreadTimeOut() {
+ ThreadPoolExecutor tpe = new ThreadPoolExecutor(2, 2, 1000, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ assertFalse(tpe.allowsCoreThreadTimeOut());
+ joinPool(tpe);
+ }
+
+ /**
+ * allowCoreThreadTimeOut(true) causes idle threads to time out
+ */
+ public void testAllowCoreThreadTimeOut_true() throws InterruptedException {
+ ThreadPoolExecutor tpe = new ThreadPoolExecutor(2, 10, 10, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ tpe.allowCoreThreadTimeOut(true);
+ tpe.execute(new NoOpRunnable());
+ try {
+ Thread.sleep(MEDIUM_DELAY_MS);
+ assertEquals(0, tpe.getPoolSize());
+ } finally {
+ joinPool(tpe);
+ }
+ }
+
+ /**
+ * allowCoreThreadTimeOut(false) causes idle threads not to time out
+ */
+ public void testAllowCoreThreadTimeOut_false() throws InterruptedException {
+ ThreadPoolExecutor tpe = new ThreadPoolExecutor(2, 10, 10, MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ tpe.allowCoreThreadTimeOut(false);
+ tpe.execute(new NoOpRunnable());
+ try {
+ Thread.sleep(MEDIUM_DELAY_MS);
+ assertTrue(tpe.getPoolSize() >= 1);
+ } finally {
+ joinPool(tpe);
+ }
+ }
+
+ /**
* execute allows the same task to be submitted multiple times, even
* if rejected
*/
- public void testRejectedRecycledTask() {
+ public void testRejectedRecycledTask() throws InterruptedException {
final int nTasks = 1000;
final AtomicInteger nRun = new AtomicInteger(0);
final Runnable recycledTask = new Runnable() {
public void run() {
nRun.getAndIncrement();
} };
- final ThreadPoolExecutor p =
- new ThreadPoolExecutor(1, 30, 60, TimeUnit.SECONDS,
+ final ThreadPoolExecutor p =
+ new ThreadPoolExecutor(1, 30, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue(30));
try {
for (int i = 0; i < nTasks; ++i) {
@@ -1556,12 +1474,9 @@ public class ThreadPoolExecutorTest extends JSR166TestCase {
}
Thread.sleep(5000); // enough time to run all tasks
assertEquals(nRun.get(), nTasks);
- } catch(Exception ex) {
- ex.printStackTrace();
- unexpectedException();
} finally {
p.shutdown();
}
}
-
+
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/ThreadTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/ThreadTest.java
index 3885c48..e9f28ac 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/ThreadTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/ThreadTest.java
@@ -2,11 +2,11 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
@@ -20,7 +20,7 @@ public class ThreadTest extends JSR166TestCase {
e.printStackTrace();
}
}
-
+
/**
* getUncaughtExceptionHandler returns ThreadGroup unless set,
* otherwise returning value of last setUncaughtExceptionHandler.
@@ -40,7 +40,7 @@ public class ThreadTest extends JSR166TestCase {
/**
* getDefaultUncaughtExceptionHandler returns value of last
- * setDefaultUncaughtExceptionHandler.
+ * setDefaultUncaughtExceptionHandler.
*/
public void testGetAndSetDefaultUncaughtExceptionHandler() {
assertEquals(null, Thread.getDefaultUncaughtExceptionHandler());
@@ -54,12 +54,12 @@ public class ThreadTest extends JSR166TestCase {
assertEquals(eh, Thread.getDefaultUncaughtExceptionHandler());
Thread.setDefaultUncaughtExceptionHandler(null);
}
- catch(SecurityException ok) {
+ catch (SecurityException ok) {
}
assertEquals(null, Thread.getDefaultUncaughtExceptionHandler());
}
-
+
// How to test actually using UEH within junit?
}
diff --git a/concurrent/src/test/java/tests/api/java/util/concurrent/TimeUnitTest.java b/concurrent/src/test/java/tests/api/java/util/concurrent/TimeUnitTest.java
index f6504d8..84be0c4 100755
--- a/concurrent/src/test/java/tests/api/java/util/concurrent/TimeUnitTest.java
+++ b/concurrent/src/test/java/tests/api/java/util/concurrent/TimeUnitTest.java
@@ -2,11 +2,11 @@
* 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.
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
*/
-package tests.api.java.util.concurrent;
+package tests.api.java.util.concurrent; // android-added
import junit.framework.*;
import java.util.concurrent.*;
@@ -24,57 +24,93 @@ public class TimeUnitTest extends JSR166TestCase {
*/
public void testConvert() {
for (long t = 0; t < 88888; ++t) {
+ assertEquals(t*60*60*24,
+ TimeUnit.SECONDS.convert(t,
+ TimeUnit.DAYS));
+ assertEquals(t*60*60,
+ TimeUnit.SECONDS.convert(t,
+ TimeUnit.HOURS));
+ assertEquals(t*60,
+ TimeUnit.SECONDS.convert(t,
+ TimeUnit.MINUTES));
assertEquals(t,
- TimeUnit.SECONDS.convert(t,
+ TimeUnit.SECONDS.convert(t,
TimeUnit.SECONDS));
- assertEquals(t,
- TimeUnit.SECONDS.convert(1000L*t,
+ assertEquals(t,
+ TimeUnit.SECONDS.convert(1000L*t,
TimeUnit.MILLISECONDS));
- assertEquals(t,
- TimeUnit.SECONDS.convert(1000000L*t,
+ assertEquals(t,
+ TimeUnit.SECONDS.convert(1000000L*t,
TimeUnit.MICROSECONDS));
- assertEquals(t,
- TimeUnit.SECONDS.convert(1000000000L*t,
+ assertEquals(t,
+ TimeUnit.SECONDS.convert(1000000000L*t,
TimeUnit.NANOSECONDS));
+ assertEquals(1000L*t*60*60*24,
+ TimeUnit.MILLISECONDS.convert(t,
+ TimeUnit.DAYS));
+ assertEquals(1000L*t*60*60,
+ TimeUnit.MILLISECONDS.convert(t,
+ TimeUnit.HOURS));
+ assertEquals(1000L*t*60,
+ TimeUnit.MILLISECONDS.convert(t,
+ TimeUnit.MINUTES));
assertEquals(1000L*t,
- TimeUnit.MILLISECONDS.convert(t,
+ TimeUnit.MILLISECONDS.convert(t,
TimeUnit.SECONDS));
- assertEquals(t,
- TimeUnit.MILLISECONDS.convert(t,
+ assertEquals(t,
+ TimeUnit.MILLISECONDS.convert(t,
TimeUnit.MILLISECONDS));
- assertEquals(t,
- TimeUnit.MILLISECONDS.convert(1000L*t,
+ assertEquals(t,
+ TimeUnit.MILLISECONDS.convert(1000L*t,
TimeUnit.MICROSECONDS));
- assertEquals(t,
- TimeUnit.MILLISECONDS.convert(1000000L*t,
+ assertEquals(t,
+ TimeUnit.MILLISECONDS.convert(1000000L*t,
TimeUnit.NANOSECONDS));
+ assertEquals(1000000L*t*60*60*24,
+ TimeUnit.MICROSECONDS.convert(t,
+ TimeUnit.DAYS));
+ assertEquals(1000000L*t*60*60,
+ TimeUnit.MICROSECONDS.convert(t,
+ TimeUnit.HOURS));
+ assertEquals(1000000L*t*60,
+ TimeUnit.MICROSECONDS.convert(t,
+ TimeUnit.MINUTES));
assertEquals(1000000L*t,
- TimeUnit.MICROSECONDS.convert(t,
+ TimeUnit.MICROSECONDS.convert(t,
TimeUnit.SECONDS));
- assertEquals(1000L*t,
- TimeUnit.MICROSECONDS.convert(t,
+ assertEquals(1000L*t,
+ TimeUnit.MICROSECONDS.convert(t,
TimeUnit.MILLISECONDS));
- assertEquals(t,
- TimeUnit.MICROSECONDS.convert(t,
+ assertEquals(t,
+ TimeUnit.MICROSECONDS.convert(t,
TimeUnit.MICROSECONDS));
- assertEquals(t,
- TimeUnit.MICROSECONDS.convert(1000L*t,
+ assertEquals(t,
+ TimeUnit.MICROSECONDS.convert(1000L*t,
TimeUnit.NANOSECONDS));
+ assertEquals(1000000000L*t*60*60*24,
+ TimeUnit.NANOSECONDS.convert(t,
+ TimeUnit.DAYS));
+ assertEquals(1000000000L*t*60*60,
+ TimeUnit.NANOSECONDS.convert(t,
+ TimeUnit.HOURS));
+ assertEquals(1000000000L*t*60,
+ TimeUnit.NANOSECONDS.convert(t,
+ TimeUnit.MINUTES));
assertEquals(1000000000L*t,
- TimeUnit.NANOSECONDS.convert(t,
+ TimeUnit.NANOSECONDS.convert(t,
TimeUnit.SECONDS));
- assertEquals(1000000L*t,
- TimeUnit.NANOSECONDS.convert(t,
+ assertEquals(1000000L*t,
+ TimeUnit.NANOSECONDS.convert(t,
TimeUnit.MILLISECONDS));
- assertEquals(1000L*t,
- TimeUnit.NANOSECONDS.convert(t,
+ assertEquals(1000L*t,
+ TimeUnit.NANOSECONDS.convert(t,
TimeUnit.MICROSECONDS));
- assertEquals(t,
- TimeUnit.NANOSECONDS.convert(t,
+ assertEquals(t,
+ TimeUnit.NANOSECONDS.convert(t,
TimeUnit.NANOSECONDS));
}
}
@@ -85,13 +121,19 @@ public class TimeUnitTest extends JSR166TestCase {
*/
public void testToNanos() {
for (long t = 0; t < 88888; ++t) {
+ assertEquals(t*1000000000L*60*60*24,
+ TimeUnit.DAYS.toNanos(t));
+ assertEquals(t*1000000000L*60*60,
+ TimeUnit.HOURS.toNanos(t));
+ assertEquals(t*1000000000L*60,
+ TimeUnit.MINUTES.toNanos(t));
assertEquals(1000000000L*t,
TimeUnit.SECONDS.toNanos(t));
- assertEquals(1000000L*t,
+ assertEquals(1000000L*t,
TimeUnit.MILLISECONDS.toNanos(t));
- assertEquals(1000L*t,
+ assertEquals(1000L*t,
TimeUnit.MICROSECONDS.toNanos(t));
- assertEquals(t,
+ assertEquals(t,
TimeUnit.NANOSECONDS.toNanos(t));
}
}
@@ -102,13 +144,19 @@ public class TimeUnitTest extends JSR166TestCase {
*/
public void testToMicros() {
for (long t = 0; t < 88888; ++t) {
+ assertEquals(t*1000000L*60*60*24,
+ TimeUnit.DAYS.toMicros(t));
+ assertEquals(t*1000000L*60*60,
+ TimeUnit.HOURS.toMicros(t));
+ assertEquals(t*1000000L*60,
+ TimeUnit.MINUTES.toMicros(t));
assertEquals(1000000L*t,
TimeUnit.SECONDS.toMicros(t));
- assertEquals(1000L*t,
+ assertEquals(1000L*t,
TimeUnit.MILLISECONDS.toMicros(t));
- assertEquals(t,
+ assertEquals(t,
TimeUnit.MICROSECONDS.toMicros(t));
- assertEquals(t,
+ assertEquals(t,
TimeUnit.NANOSECONDS.toMicros(t*1000L));
}
}
@@ -119,13 +167,19 @@ public class TimeUnitTest extends JSR166TestCase {
*/
public void testToMillis() {
for (long t = 0; t < 88888; ++t) {
+ assertEquals(t*1000L*60*60*24,
+ TimeUnit.DAYS.toMillis(t));
+ assertEquals(t*1000L*60*60,
+ TimeUnit.HOURS.toMillis(t));
+ assertEquals(t*1000L*60,
+ TimeUnit.MINUTES.toMillis(t));
assertEquals(1000L*t,
TimeUnit.SECONDS.toMillis(t));
- assertEquals(t,
+ assertEquals(t,
TimeUnit.MILLISECONDS.toMillis(t));
- assertEquals(t,
+ assertEquals(t,
TimeUnit.MICROSECONDS.toMillis(t*1000L));
- assertEquals(t,
+ assertEquals(t,
TimeUnit.NANOSECONDS.toMillis(t*1000000L));
}
}
@@ -136,19 +190,95 @@ public class TimeUnitTest extends JSR166TestCase {
*/
public void testToSeconds() {
for (long t = 0; t < 88888; ++t) {
+ assertEquals(t*60*60*24,
+ TimeUnit.DAYS.toSeconds(t));
+ assertEquals(t*60*60,
+ TimeUnit.HOURS.toSeconds(t));
+ assertEquals(t*60,
+ TimeUnit.MINUTES.toSeconds(t));
assertEquals(t,
TimeUnit.SECONDS.toSeconds(t));
- assertEquals(t,
+ assertEquals(t,
TimeUnit.MILLISECONDS.toSeconds(t*1000L));
- assertEquals(t,
+ assertEquals(t,
TimeUnit.MICROSECONDS.toSeconds(t*1000000L));
- assertEquals(t,
+ assertEquals(t,
TimeUnit.NANOSECONDS.toSeconds(t*1000000000L));
}
}
/**
- * convert saturates positive too-large values to Long.MAX_VALUE
+ * toMinutes correctly converts sample values in different units to
+ * minutes
+ */
+ public void testToMinutes() {
+ for (long t = 0; t < 88888; ++t) {
+ assertEquals(t*60*24,
+ TimeUnit.DAYS.toMinutes(t));
+ assertEquals(t*60,
+ TimeUnit.HOURS.toMinutes(t));
+ assertEquals(t,
+ TimeUnit.MINUTES.toMinutes(t));
+ assertEquals(t,
+ TimeUnit.SECONDS.toMinutes(t*60));
+ assertEquals(t,
+ TimeUnit.MILLISECONDS.toMinutes(t*1000L*60));
+ assertEquals(t,
+ TimeUnit.MICROSECONDS.toMinutes(t*1000000L*60));
+ assertEquals(t,
+ TimeUnit.NANOSECONDS.toMinutes(t*1000000000L*60));
+ }
+ }
+
+ /**
+ * toHours correctly converts sample values in different units to
+ * hours
+ */
+ public void testToHours() {
+ for (long t = 0; t < 88888; ++t) {
+ assertEquals(t*24,
+ TimeUnit.DAYS.toHours(t));
+ assertEquals(t,
+ TimeUnit.HOURS.toHours(t));
+ assertEquals(t,
+ TimeUnit.MINUTES.toHours(t*60));
+ assertEquals(t,
+ TimeUnit.SECONDS.toHours(t*60*60));
+ assertEquals(t,
+ TimeUnit.MILLISECONDS.toHours(t*1000L*60*60));
+ assertEquals(t,
+ TimeUnit.MICROSECONDS.toHours(t*1000000L*60*60));
+ assertEquals(t,
+ TimeUnit.NANOSECONDS.toHours(t*1000000000L*60*60));
+ }
+ }
+
+ /**
+ * toDays correctly converts sample values in different units to
+ * days
+ */
+ public void testToDays() {
+ for (long t = 0; t < 88888; ++t) {
+ assertEquals(t,
+ TimeUnit.DAYS.toDays(t));
+ assertEquals(t,
+ TimeUnit.HOURS.toDays(t*24));
+ assertEquals(t,
+ TimeUnit.MINUTES.toDays(t*60*24));
+ assertEquals(t,
+ TimeUnit.SECONDS.toDays(t*60*60*24));
+ assertEquals(t,
+ TimeUnit.MILLISECONDS.toDays(t*1000L*60*60*24));
+ assertEquals(t,
+ TimeUnit.MICROSECONDS.toDays(t*1000000L*60*60*24));
+ assertEquals(t,
+ TimeUnit.NANOSECONDS.toDays(t*1000000000L*60*60*24));
+ }
+ }
+
+
+ /**
+ * convert saturates positive too-large values to Long.MAX_VALUE
* and negative to LONG.MIN_VALUE
*/
public void testConvertSaturate() {
@@ -158,18 +288,35 @@ public class TimeUnitTest extends JSR166TestCase {
assertEquals(Long.MIN_VALUE,
TimeUnit.NANOSECONDS.convert(-Long.MAX_VALUE / 4,
TimeUnit.SECONDS));
-
+ assertEquals(Long.MAX_VALUE,
+ TimeUnit.NANOSECONDS.convert(Long.MAX_VALUE / 2,
+ TimeUnit.MINUTES));
+ assertEquals(Long.MIN_VALUE,
+ TimeUnit.NANOSECONDS.convert(-Long.MAX_VALUE / 4,
+ TimeUnit.MINUTES));
+ assertEquals(Long.MAX_VALUE,
+ TimeUnit.NANOSECONDS.convert(Long.MAX_VALUE / 2,
+ TimeUnit.HOURS));
+ assertEquals(Long.MIN_VALUE,
+ TimeUnit.NANOSECONDS.convert(-Long.MAX_VALUE / 4,
+ TimeUnit.HOURS));
+ assertEquals(Long.MAX_VALUE,
+ TimeUnit.NANOSECONDS.convert(Long.MAX_VALUE / 2,
+ TimeUnit.DAYS));
+ assertEquals(Long.MIN_VALUE,
+ TimeUnit.NANOSECONDS.convert(-Long.MAX_VALUE / 4,
+ TimeUnit.DAYS));
}
/**
- * toNanos saturates positive too-large values to Long.MAX_VALUE
+ * toNanos saturates positive too-large values to Long.MAX_VALUE
* and negative to LONG.MIN_VALUE
*/
public void testToNanosSaturate() {
- assertEquals(Long.MAX_VALUE,
- TimeUnit.MILLISECONDS.toNanos(Long.MAX_VALUE / 2));
- assertEquals(Long.MIN_VALUE,
- TimeUnit.MILLISECONDS.toNanos(-Long.MAX_VALUE / 3));
+ assertEquals(Long.MAX_VALUE,
+ TimeUnit.MILLISECONDS.toNanos(Long.MAX_VALUE / 2));
+ assertEquals(Long.MIN_VALUE,
+ TimeUnit.MILLISECONDS.toNanos(-Long.MAX_VALUE / 3));
}
@@ -181,151 +328,100 @@ public class TimeUnitTest extends JSR166TestCase {
assertTrue(s.indexOf("ECOND") >= 0);
}
-
+
/**
* Timed wait without holding lock throws
* IllegalMonitorStateException
*/
- public void testTimedWait_IllegalMonitorException() {
- //created a new thread with anonymous runnable
-
- Thread t = new Thread(new Runnable() {
- public void run() {
- Object o = new Object();
- TimeUnit tu = TimeUnit.MILLISECONDS;
- try {
- tu.timedWait(o,LONG_DELAY_MS);
- threadShouldThrow();
- }
- catch (InterruptedException ie) {
- threadUnexpectedException();
- }
- catch(IllegalMonitorStateException success) {
- }
-
- }
- });
+ public void testTimedWait_IllegalMonitorException() throws Exception {
+ Thread t = new Thread(new CheckedRunnable() {
+ public void realRun() throws InterruptedException {
+ Object o = new Object();
+ TimeUnit tu = TimeUnit.MILLISECONDS;
+ try {
+ tu.timedWait(o,LONG_DELAY_MS);
+ threadShouldThrow();
+ } catch (IllegalMonitorStateException success) {}}});
+
t.start();
- try {
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- } catch(Exception e) {
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
-
+
/**
* timedWait throws InterruptedException when interrupted
*/
- public void testTimedWait() {
- Thread t = new Thread(new Runnable() {
- public void run() {
- Object o = new Object();
-
- TimeUnit tu = TimeUnit.MILLISECONDS;
- try {
- synchronized(o) {
- tu.timedWait(o,MEDIUM_DELAY_MS);
- }
- threadShouldThrow();
- }
- catch(InterruptedException success) {}
- catch(IllegalMonitorStateException failure) {
- threadUnexpectedException();
- }
+ public void testTimedWait() throws InterruptedException {
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ Object o = new Object();
+
+ TimeUnit tu = TimeUnit.MILLISECONDS;
+ synchronized(o) {
+ tu.timedWait(o,MEDIUM_DELAY_MS);
}
- });
+ }});
t.start();
- try {
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- } catch(Exception e) {
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
-
-
+
+
/**
* timedJoin throws InterruptedException when interrupted
*/
- public void testTimedJoin() {
- Thread t = new Thread(new Runnable() {
- public void run() {
- TimeUnit tu = TimeUnit.MILLISECONDS;
- try {
- Thread s = new Thread(new Runnable() {
- public void run() {
- try {
- Thread.sleep(MEDIUM_DELAY_MS);
- } catch(InterruptedException success){}
- }
- });
- s.start();
- tu.timedJoin(s,MEDIUM_DELAY_MS);
- threadShouldThrow();
- }
- catch(Exception e) {}
- }
- });
+ public void testTimedJoin() throws InterruptedException {
+ final Thread s = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ Thread.sleep(MEDIUM_DELAY_MS);
+ }});
+ final Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ TimeUnit tu = TimeUnit.MILLISECONDS;
+ tu.timedJoin(s, MEDIUM_DELAY_MS);
+ }});;
+ s.start();
t.start();
- try {
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- } catch(Exception e) {
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
+ s.interrupt();
+ s.join();
}
-
+
/**
* timedSleep throws InterruptedException when interrupted
*/
- public void testTimedSleep() {
- //created a new thread with anonymous runnable
-
- Thread t = new Thread(new Runnable() {
- public void run() {
- TimeUnit tu = TimeUnit.MILLISECONDS;
- try {
- tu.sleep(MEDIUM_DELAY_MS);
- threadShouldThrow();
- }
- catch(InterruptedException success) {}
- }
- });
+ public void testTimedSleep() throws InterruptedException {
+ Thread t = new Thread(new CheckedInterruptedRunnable() {
+ public void realRun() throws InterruptedException {
+ TimeUnit tu = TimeUnit.MILLISECONDS;
+ tu.sleep(MEDIUM_DELAY_MS);
+ }});
+
t.start();
- try {
- Thread.sleep(SHORT_DELAY_MS);
- t.interrupt();
- t.join();
- } catch(Exception e) {
- unexpectedException();
- }
+ Thread.sleep(SHORT_DELAY_MS);
+ t.interrupt();
+ t.join();
}
/**
- * a deserialized serialized unit is equal
+ * a deserialized serialized unit is the same instance
*/
- public void testSerialization() {
+ public void testSerialization() throws Exception {
TimeUnit q = TimeUnit.MILLISECONDS;
- try {
- ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
- ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
- out.writeObject(q);
- out.close();
-
- ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
- ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
- TimeUnit r = (TimeUnit)in.readObject();
-
- assertEquals(q.toString(), r.toString());
- } catch(Exception e){
- e.printStackTrace();
- unexpectedException();
- }
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(10000);
+ ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout));
+ out.writeObject(q);
+ out.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
+ TimeUnit r = (TimeUnit)in.readObject();
+ assertSame(q, r);
}
}
diff --git a/luni-kernel/src/main/java/java/lang/Thread.java b/luni-kernel/src/main/java/java/lang/Thread.java
index 2dbba37..625d718 100644
--- a/luni-kernel/src/main/java/java/lang/Thread.java
+++ b/luni-kernel/src/main/java/java/lang/Thread.java
@@ -192,6 +192,9 @@ public class Thread implements Runnable {
/** the park state of the thread */
private int parkState = ParkState.UNPARKED;
+ /** The synchronization object responsible for this thread parking. */
+ private Object parkBlocker;
+
/**
* Constructs a new {@code Thread} with no {@code Runnable} object and a
* newly generated name. The new {@code Thread} will belong to the same
diff --git a/luni/src/main/java/java/util/AbstractMap.java b/luni/src/main/java/java/util/AbstractMap.java
index c98a25f..86b4740 100644
--- a/luni/src/main/java/java/util/AbstractMap.java
+++ b/luni/src/main/java/java/util/AbstractMap.java
@@ -17,6 +17,8 @@
package java.util;
+import java.io.Serializable;
+
/**
* This class is an abstract implementation of the {@code Map} interface. This
* implementation does not support adding. A subclass must implement the
@@ -32,6 +34,240 @@ public abstract class AbstractMap<K, V> implements Map<K, V> {
Collection<V> valuesCollection;
/**
+ * An immutable key-value mapping.
+ *
+ * @param <K>
+ * the type of key
+ * @param <V>
+ * the type of value
+ *
+ * @since 1.6
+ */
+ public static class SimpleImmutableEntry<K, V> implements Map.Entry<K, V>,
+ Serializable {
+
+ private static final long serialVersionUID = 7138329143949025153L;
+
+ private K key;
+
+ private V value;
+
+ /**
+ * Constructs a new instance by key and value.
+ *
+ * @param theKey
+ * the key
+ * @param theValue
+ * the value
+ */
+ public SimpleImmutableEntry(K theKey, V theValue) {
+ key = theKey;
+ value = theValue;
+ }
+
+ /**
+ * Constructs a new instance by an entry
+ *
+ * @param entry
+ * the entry
+ */
+ public SimpleImmutableEntry(Map.Entry<? extends K, ? extends V> entry) {
+ key = entry.getKey();
+ value = entry.getValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.Map.Entry#getKey()
+ */
+ public K getKey() {
+ return key;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.Map.Entry#getValue()
+ */
+ public V getValue() {
+ return value;
+ }
+
+ /**
+ * Throws an UnsupportedOperationException.
+ *
+ * @param object
+ * new value
+ * @return (Does not)
+ * @throws UnsupportedOperationException
+ * always
+ *
+ * @see java.util.Map.Entry#setValue(java.lang.Object)
+ */
+ public V setValue(V object) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns whether the object is equal to this entry. This works across
+ * all kinds of the Map.Entry interface.
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object object) {
+ if (this == object) {
+ return true;
+ }
+ if (object instanceof Map.Entry) {
+ Map.Entry<?, ?> entry = (Map.Entry<?, ?>) object;
+ return (key == null ? entry.getKey() == null : key.equals(entry
+ .getKey()))
+ && (value == null ? entry.getValue() == null : value
+ .equals(entry.getValue()));
+ }
+ return false;
+ }
+
+ /**
+ * Returns the hash code of this entry.
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return (key == null ? 0 : key.hashCode())
+ ^ (value == null ? 0 : value.hashCode());
+ }
+
+ /**
+ * Returns a String representation of this entry.
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return key + "=" + value; //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * A key-value mapping.
+ *
+ * @param <K>
+ * the type of key
+ * @param <V>
+ * the type of value
+ *
+ * @since 1.6
+ */
+ public static class SimpleEntry<K, V> implements Map.Entry<K, V>,
+ Serializable {
+
+ private static final long serialVersionUID = -8499721149061103585L;
+
+ private K key;
+
+ private V value;
+
+ /**
+ * Constructs a new instance by key and value.
+ *
+ * @param theKey
+ * the key
+ * @param theValue
+ * the value
+ */
+ public SimpleEntry(K theKey, V theValue) {
+ key = theKey;
+ value = theValue;
+ }
+
+ /**
+ * Constructs a new instance by an entry
+ *
+ * @param entry
+ * the entry
+ */
+ public SimpleEntry(Map.Entry<? extends K, ? extends V> entry) {
+ key = entry.getKey();
+ value = entry.getValue();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.Map.Entry#getKey()
+ */
+ public K getKey() {
+ return key;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.Map.Entry#getValue()
+ */
+ public V getValue() {
+ return value;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.Map.Entry#setValue(java.lang.Object)
+ */
+ public V setValue(V object) {
+ V result = value;
+ value = object;
+ return result;
+ }
+
+ /**
+ * Returns whether the object is equal to this entry. This works across
+ * all kinds of the Map.Entry interface.
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object object) {
+ if (this == object) {
+ return true;
+ }
+ if (object instanceof Map.Entry) {
+ Map.Entry<?, ?> entry = (Map.Entry<?, ?>) object;
+ return (key == null ? entry.getKey() == null : key.equals(entry
+ .getKey()))
+ && (value == null ? entry.getValue() == null : value
+ .equals(entry.getValue()));
+ }
+ return false;
+ }
+
+ /**
+ * Returns the hash code of this entry.
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return (key == null ? 0 : key.hashCode())
+ ^ (value == null ? 0 : value.hashCode());
+ }
+
+ /**
+ * Returns a String representation of this entry.
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return key + "=" + value; //$NON-NLS-1$
+ }
+ }
+
+ /**
* Constructs a new instance of this {@code AbstractMap}.
*/
protected AbstractMap() {
@@ -453,4 +689,4 @@ public abstract class AbstractMap<K, V> implements Map<K, V> {
result.valuesCollection = null;
return result;
}
-}
+} \ No newline at end of file
diff --git a/luni/src/main/java/java/util/ArrayDeque.java b/luni/src/main/java/java/util/ArrayDeque.java
new file mode 100644
index 0000000..2e2fe3a
--- /dev/null
+++ b/luni/src/main/java/java/util/ArrayDeque.java
@@ -0,0 +1,885 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.lang.reflect.Array;
+
+/**
+ * An implementation of Deque, backed by an array.
+ *
+ * ArrayDeques have no size limit, can not contain null element, and they are
+ * not thread-safe.
+ *
+ * All optional operations are supported, and the elements can be any objects.
+ *
+ * @param <E>
+ * the type of elements in this collection
+ *
+ * @since 1.6
+ */
+public class ArrayDeque<E> extends AbstractCollection<E> implements Deque<E>,
+ Cloneable, Serializable {
+
+ private static final long serialVersionUID = 2340985798034038923L;
+
+ private static final int DEFAULT_SIZE = 16;
+
+ private enum DequeStatus {
+ Empty, Normal, Full;
+ }
+
+ private transient DequeStatus status;
+
+ private transient int modCount;
+
+ // the pointer of the head element
+ private transient int front;
+
+ // the pointer of the "next" position of the tail element
+ private transient int rear;
+
+ private transient E[] elements;
+
+ @SuppressWarnings("hiding")
+ private class ArrayDequeIterator<E> implements Iterator<E> {
+ private int pos;
+
+ private final int expectedModCount;
+
+ private boolean canRemove;
+
+ @SuppressWarnings("synthetic-access")
+ ArrayDequeIterator() {
+ super();
+ pos = front;
+ expectedModCount = modCount;
+ canRemove = false;
+ }
+
+ @SuppressWarnings("synthetic-access")
+ public boolean hasNext() {
+ if (expectedModCount != modCount) {
+ return false;
+ }
+ return hasNextInternal();
+ }
+
+ private boolean hasNextInternal() {
+ // canRemove means "next" method is called, and the Full
+ // status can ensure that this method is not called just
+ // after "remove" method is call.(so, canRemove can keep
+ // true after "next" method called)
+ return (pos != rear)
+ || ((status == DequeStatus.Full) && !canRemove);
+ }
+
+ @SuppressWarnings( { "synthetic-access", "unchecked" })
+ public E next() {
+ if (hasNextInternal()) {
+ E result = (E) elements[pos];
+ if (expectedModCount == modCount && null != result) {
+ canRemove = true;
+ pos = circularBiggerPos(pos);
+ return result;
+ }
+ throw new ConcurrentModificationException();
+ }
+ throw new NoSuchElementException();
+ }
+
+ @SuppressWarnings("synthetic-access")
+ public void remove() {
+ if (canRemove) {
+ int removedPos = circularSmallerPos(pos);
+ if (expectedModCount == modCount
+ && null != elements[removedPos]) {
+ removeInternal(removedPos, true);
+ canRemove = false;
+ return;
+ }
+ throw new ConcurrentModificationException();
+ }
+ throw new IllegalStateException();
+ }
+ }
+
+ /*
+ * NOTES:descendingIterator is not fail-fast, according to the documentation
+ * and test case.
+ */
+ @SuppressWarnings("hiding")
+ private class ReverseArrayDequeIterator<E> implements Iterator<E> {
+ private int pos;
+
+ private final int expectedModCount;
+
+ private boolean canRemove;
+
+ @SuppressWarnings("synthetic-access")
+ ReverseArrayDequeIterator() {
+ super();
+ expectedModCount = modCount;
+ pos = circularSmallerPos(rear);
+ canRemove = false;
+ }
+
+ @SuppressWarnings("synthetic-access")
+ public boolean hasNext() {
+ if (expectedModCount != modCount) {
+ return false;
+ }
+ return hasNextInternal();
+ }
+
+ private boolean hasNextInternal() {
+ // canRemove means "next" method is called, and the Full
+ // status can ensure that this method is not called just
+ // after "remove" method is call.(so, canRemove can keep
+ // true after "next" method called)
+ return (circularBiggerPos(pos) != front)
+ || ((status == DequeStatus.Full) && !canRemove);
+ }
+
+ @SuppressWarnings( { "synthetic-access", "unchecked" })
+ public E next() {
+ if (hasNextInternal()) {
+ E result = (E) elements[pos];
+ canRemove = true;
+ pos = circularSmallerPos(pos);
+ return result;
+ }
+ throw new NoSuchElementException();
+ }
+
+ @SuppressWarnings("synthetic-access")
+ public void remove() {
+ if (canRemove) {
+ removeInternal(circularBiggerPos(pos), false);
+ canRemove = false;
+ return;
+ }
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Constructs a new empty instance of ArrayDeque big enough for 16 elements.
+ */
+ public ArrayDeque() {
+ this(DEFAULT_SIZE);
+ }
+
+ /**
+ * Constructs a new empty instance of ArrayDeque big enough for specified
+ * number of elements.
+ *
+ * @param minSize
+ * the smallest size of the ArrayDeque
+ */
+ @SuppressWarnings("unchecked")
+ public ArrayDeque(final int minSize) {
+ int size = countInitSize(minSize);
+ elements = (E[]) new Object[size];
+ front = rear = 0;
+ status = DequeStatus.Empty;
+ modCount = 0;
+ }
+
+ /*
+ * count out the size for a new deque, and ensure that size >= minSize
+ */
+ private int countInitSize(final int minSize) {
+ int size = Math.max(minSize, DEFAULT_SIZE);
+ // get the smallest number that not smaller than size,
+ // and is a power of 2.
+ size = Integer.highestOneBit(size - 1) << 1;
+ if (0 >= size) {
+ size = minSize;
+ }
+ return size;
+ }
+
+ /**
+ * Constructs a new instance of ArrayDeque containing the elements of the
+ * specified collection, with the order returned by the collection's
+ * iterator.
+ *
+ * @param c
+ * the source of the elements
+ * @throws NullPointerException
+ * if the collection is null
+ */
+ @SuppressWarnings("unchecked")
+ public ArrayDeque(Collection<? extends E> c) {
+ elements = (E[]) new Object[countInitSize(c.size())];
+ front = rear = 0;
+ status = DequeStatus.Empty;
+ modCount = 0;
+ Iterator<? extends E> it = c.iterator();
+ while (it.hasNext()) {
+ addLastImpl(it.next());
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @param e
+ * the element
+ * @throws NullPointerException
+ * if the element is null
+ * @see java.util.Deque#addFirst(java.lang.Object)
+ */
+ public void addFirst(E e) {
+ offerFirst(e);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @param e
+ * the element
+ * @throws NullPointerException
+ * if the element is null
+ * @see java.util.Deque#addLast(java.lang.Object)
+ */
+ public void addLast(E e) {
+ addLastImpl(e);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @param e
+ * the element
+ * @return true
+ * @throws NullPointerException
+ * if the element is null
+ * @see java.util.Deque#offerFirst(java.lang.Object)
+ */
+ public boolean offerFirst(E e) {
+ checkNull(e);
+ checkAndExpand();
+ front = circularSmallerPos(front);
+ elements[front] = e;
+ resetStatus(true);
+ modCount++;
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @param e
+ * the element
+ * @return true if the operation succeeds or false if it fails
+ * @throws NullPointerException
+ * if the element is null
+ * @see java.util.Deque#offerLast(java.lang.Object)
+ */
+ public boolean offerLast(E e) {
+ return addLastImpl(e);
+ }
+
+ /**
+ * Inserts the element at the tail of the deque.
+ *
+ * @param e
+ * the element
+ * @return true if the operation succeeds or false if it fails.
+ * @throws NullPointerException
+ * if the element is null
+ * @see java.util.Queue#offer(java.lang.Object)
+ */
+ public boolean offer(E e) {
+ return addLastImpl(e);
+ }
+
+ /**
+ * Inserts the element to the tail of the deque.
+ *
+ * @param e
+ * the element
+ * @return true
+ * @see java.util.AbstractCollection#add(java.lang.Object)
+ */
+ @Override
+ public boolean add(E e) {
+ return addLastImpl(e);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @param e
+ * the element to push
+ * @throws NullPointerException
+ * if the element is null
+ * @see java.util.Deque#push(java.lang.Object)
+ */
+ public void push(E e) {
+ offerFirst(e);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return the head element
+ * @throws NoSuchElementException
+ * if the deque is empty
+ * @see java.util.Deque#removeFirst()
+ */
+ public E removeFirst() {
+ checkEmpty();
+ return removePollFirstImpl();
+ }
+
+ /**
+ * Gets and removes the head element of this deque. This method throws an
+ * exception if the deque is empty.
+ *
+ * @return the head element
+ * @throws NoSuchElementException
+ * if the deque is empty
+ * @see java.util.Queue#remove()
+ */
+ public E remove() {
+ return removeFirst();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return the head element
+ * @throws NoSuchElementException
+ * if the deque is empty
+ * @see java.util.Deque#pop()
+ */
+ public E pop() {
+ return removeFirst();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return the tail element
+ * @throws NoSuchElementException
+ * if the deque is empty
+ * @see java.util.Deque#removeLast()
+ */
+ public E removeLast() {
+ checkEmpty();
+ return removeLastImpl();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return the head element or null if the deque is empty
+ * @see java.util.Deque#pollFirst()
+ */
+ public E pollFirst() {
+ return (status == DequeStatus.Empty) ? null : removePollFirstImpl();
+ }
+
+ /**
+ * Gets and removes the head element of this deque. This method returns null
+ * if the deque is empty.
+ *
+ * @return the head element or null if the deque is empty
+ * @see java.util.Queue#poll()
+ */
+ public E poll() {
+ return pollFirst();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return the tail element or null if the deque is empty
+ * @see java.util.Deque#pollLast()
+ */
+ public E pollLast() {
+ return (status == DequeStatus.Empty) ? null : removeLastImpl();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return the head element
+ * @throws NoSuchElementException
+ * if the deque is empty
+ * @see java.util.Deque#getFirst()
+ */
+ public E getFirst() {
+ checkEmpty();
+ return elements[front];
+ }
+
+ /**
+ * Gets but does not remove the head element of this deque. It throws an
+ * exception if the deque is empty.
+ *
+ * @return the head element
+ * @throws NoSuchElementException
+ * if the deque is empty
+ * @see java.util.Queue#element()
+ */
+ public E element() {
+ return getFirst();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return the tail element
+ * @throws NoSuchElementException
+ * if the deque is empty
+ * @see java.util.Deque#getLast()
+ */
+ public E getLast() {
+ checkEmpty();
+ return elements[circularSmallerPos(rear)];
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return the head element or null if the deque is empty
+ * @see java.util.Deque#peekFirst()
+ */
+ public E peekFirst() {
+ return (status == DequeStatus.Empty) ? null : elements[front];
+ }
+
+ /**
+ * Gets but not removes the head element of this deque. This method returns
+ * null if the deque is empty.
+ *
+ * @return the head element or null if the deque is empty
+ * @see java.util.Queue#peek()
+ */
+ public E peek() {
+ return (status == DequeStatus.Empty) ? null : elements[front];
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return the tail element or null if the deque is empty
+ * @see java.util.Deque#peekLast()
+ */
+ public E peekLast() {
+ return (status == DequeStatus.Empty) ? null
+ : elements[circularSmallerPos(rear)];
+ }
+
+ private void checkNull(E e) {
+ if (null == e) {
+ throw new NullPointerException();
+ }
+ }
+
+ private void checkEmpty() {
+ if (status == DequeStatus.Empty) {
+ throw new NoSuchElementException();
+ }
+ }
+
+ private int circularSmallerPos(int current) {
+ return (current - 1 < 0) ? (elements.length - 1) : current - 1;
+ }
+
+ private int circularBiggerPos(int current) {
+ return (current + 1 >= elements.length) ? 0 : current + 1;
+ }
+
+ @SuppressWarnings("unchecked")
+ /*
+ * If array of elements is full, there will be a new bigger array to store
+ * the elements.
+ */
+ private void checkAndExpand() {
+ if (status != DequeStatus.Full) {
+ return;
+ }
+ if (Integer.MAX_VALUE == elements.length) {
+ throw new IllegalStateException();
+ }
+ int length = elements.length;
+ int newLength = length << 1;
+ // bigger than Integer.MAX_VALUE
+ if (newLength < 0) {
+ newLength = Integer.MAX_VALUE;
+ }
+ E[] newElements = (E[]) new Object[newLength];
+ System.arraycopy(elements, front, newElements, 0, length - front);
+ System.arraycopy(elements, 0, newElements, length - front, front);
+ front = 0;
+ rear = length;
+ status = DequeStatus.Normal;
+ elements = newElements;
+ }
+
+ /**
+ * Resets the status after adding or removing operation.
+ *
+ * @param adding
+ * if the method is called after an "adding" operation
+ */
+ private void resetStatus(boolean adding) {
+ if (front == rear) {
+ status = adding ? DequeStatus.Full : DequeStatus.Empty;
+ } else {
+ status = DequeStatus.Normal;
+ }
+ }
+
+ private boolean addLastImpl(E e) {
+ checkNull(e);
+ checkAndExpand();
+ elements[rear] = e;
+ rear = circularBiggerPos(rear);
+ resetStatus(true);
+ modCount++;
+ return true;
+ }
+
+ private E removePollFirstImpl() {
+ E element = elements[front];
+ elements[front] = null;
+ front = circularBiggerPos(front);
+ resetStatus(false);
+ modCount++;
+ return element;
+ }
+
+ private E removeLastImpl() {
+ int last = circularSmallerPos(rear);
+ E element = elements[last];
+ elements[last] = null;
+ rear = last;
+ resetStatus(false);
+ modCount++;
+ return element;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @param obj
+ * the element to be removed
+ * @return true if the operation succeeds or false if the deque does not
+ * contain the element
+ * @see java.util.Deque#removeFirstOccurrence(java.lang.Object)
+ */
+ public boolean removeFirstOccurrence(Object obj) {
+ return removeFirstOccurrenceImpl(obj);
+ }
+
+ /**
+ * Removes the first equivalent element of the specified object. If the
+ * deque does not contain the element, it is unchanged and returns false.
+ *
+ * @param obj
+ * the element to be removed
+ * @return true if the operation succeeds or false if the deque does not
+ * contain the element
+ * @see java.util.AbstractCollection#remove(java.lang.Object)
+ */
+ @Override
+ public boolean remove(Object obj) {
+ return removeFirstOccurrenceImpl(obj);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @param obj
+ * the element to be removed
+ * @return true if the operation succeeds or false if the deque does not
+ * contain the element.
+ * @see java.util.Deque#removeLastOccurrence(java.lang.Object)
+ */
+ public boolean removeLastOccurrence(final Object obj) {
+ if (null != obj) {
+ Iterator<E> iter = descendingIterator();
+ while (iter.hasNext()) {
+ if (iter.next().equals(obj)) {
+ iter.remove();
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean removeFirstOccurrenceImpl(final Object obj) {
+ if (null != obj) {
+ Iterator<E> iter = iterator();
+ while (iter.hasNext()) {
+ if (iter.next().equals(obj)) {
+ iter.remove();
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /*
+ * Removes the element in the cursor position and shifts front elements to
+ * fill the gap if frontShift is true, shifts rear elements otherwise.
+ *
+ */
+ private void removeInternal(final int current, final boolean frontShift) {
+ int cursor = current;
+ if (frontShift) {
+ while (cursor != front) {
+ int next = circularSmallerPos(cursor);
+ elements[cursor] = elements[next];
+ cursor = next;
+ }
+ front = circularBiggerPos(front);
+ } else {
+ while (cursor != rear) {
+ int next = circularBiggerPos(cursor);
+ elements[cursor] = elements[next];
+ cursor = next;
+ }
+ rear = circularSmallerPos(rear);
+ }
+ elements[cursor] = null;
+ resetStatus(false);
+ }
+
+ /**
+ * Returns the size of the deque.
+ *
+ * @return the size of the deque
+ * @see java.util.AbstractCollection#size()
+ */
+ @Override
+ public int size() {
+ if (status == DequeStatus.Full) {
+ return elements.length;
+ }
+ return (front <= rear) ? (rear - front)
+ : (rear + elements.length - front);
+ }
+
+ /**
+ * Returns true if the deque has no elements.
+ *
+ * @return true if the deque has no elements, false otherwise
+ * @see java.util.AbstractCollection#isEmpty()
+ */
+ @Override
+ public boolean isEmpty() {
+ return 0 == size();
+ }
+
+ /**
+ * Returns true if the specified element is in the deque.
+ *
+ * @param obj
+ * the element
+ * @return true if the element is in the deque, false otherwise
+ * @see java.util.AbstractCollection#contains(java.lang.Object)
+ */
+ @SuppressWarnings("cast")
+ @Override
+ public boolean contains(final Object obj) {
+ if (null != obj) {
+ Iterator<E> it = new ArrayDequeIterator<E>();
+ while (it.hasNext()) {
+ if (obj.equals((E) it.next())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Empty the deque.
+ *
+ * @see java.util.AbstractCollection#clear()
+ */
+ @SuppressWarnings("cast")
+ @Override
+ public void clear() {
+ if (status != DequeStatus.Empty) {
+ int cursor = front;
+ do {
+ elements[cursor] = null;
+ cursor = circularBiggerPos(cursor);
+ } while (cursor != rear);
+ status = DequeStatus.Empty;
+ }
+ front = rear = 0;
+ modCount = 0;
+ }
+
+ /**
+ * Returns a clone of the deque.
+ *
+ * @return the clone of the deque
+ * @see java.lang.Object#clone()
+ * @see java.lang.Cloneable
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public ArrayDeque<E> clone() {
+ try {
+ ArrayDeque<E> newDeque = (ArrayDeque<E>) super.clone();
+ newDeque.elements = elements.clone();
+ return newDeque;
+ } catch (CloneNotSupportedException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Returns all the elements in an array from head to tail. The result is a
+ * copy of all the elements.
+ *
+ * @return the Array of all the elements
+ * @see java.util.AbstractCollection#toArray()
+ */
+ @Override
+ public Object[] toArray() {
+ return newArray(new Object[size()]);
+ }
+
+ /**
+ * Returns all the elements in an array from head to tail, and the type of
+ * the result array is the type of the argument array. If the argument array
+ * is big enough, the elements from the deque will be stored in it(elements
+ * following the tail of the deque is set to null, if any); otherwise, it
+ * will return a new array with the size of the argument array and size of
+ * the deque.
+ *
+ * @param <T>
+ * the type of elements in the array
+ * @param array
+ * the array stores all the elements from the deque, if it has
+ * enough space; otherwise, a new array of the same type and the
+ * size of the deque will be used
+ * @return the Array of all the elements
+ * @throws ArrayStoreException
+ * if the type of the argument array is not compatible with
+ * every element in the deque
+ * @throws NullPointerException
+ * if the argument array is null
+ * @see java.util.AbstractCollection#toArray
+ */
+ @Override
+ public <T> T[] toArray(T[] array) {
+ return newArray(array);
+ }
+
+ @SuppressWarnings("unchecked")
+ private <T> T[] newArray(T[] array) {
+ int size = size();
+ if (size > array.length) {
+ Class<?> clazz = array.getClass().getComponentType();
+ array = (T[]) Array.newInstance(clazz, size);
+ }
+ if (front < rear) {
+ System.arraycopy(elements, front, array, 0, size);
+ } else if (size != 0) {
+ int length = elements.length;
+ System.arraycopy(elements, front, array, 0, length - front);
+ System.arraycopy(elements, 0, array, length - front, rear);
+ }
+ if (size < array.length) {
+ array[size] = null;
+ }
+ return array;
+ }
+
+ /**
+ * Returns the iterator of the deque. The elements will be ordered from head
+ * to tail.
+ *
+ * @return the iterator
+ * @see java.util.AbstractCollection#iterator()
+ */
+ @SuppressWarnings("synthetic-access")
+ @Override
+ public Iterator<E> iterator() {
+ return new ArrayDequeIterator<E>();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return the reverse order Iterator
+ * @see java.util.Deque#descendingIterator()
+ */
+ public Iterator<E> descendingIterator() {
+ return new ReverseArrayDequeIterator<E>();
+ }
+
+ /**
+ * Deserialization method.
+ *
+ * @param stream
+ * the ObjectInputStream
+ * @throws IOException
+ * @throws ClassNotFoundException
+ */
+ @SuppressWarnings("unchecked")
+ private void readObject(ObjectInputStream stream) throws IOException,
+ ClassNotFoundException {
+ stream.defaultReadObject();
+ int size = stream.readInt();
+ elements = (E[]) new Object[countInitSize(size)];
+ front = rear = 0;
+ status = DequeStatus.Empty;
+ modCount = 0;
+ for (int i = 0; i < size; i++) {
+ addLastImpl((E) stream.readObject());
+ }
+ }
+
+ /**
+ * Serialization method.
+ *
+ * @param stream
+ * the ObjectOutputStream
+ * @serialData The current size of the deque, followed by all the elements
+ * from head to tail.
+ * @throws IOException
+ *
+ */
+ private void writeObject(ObjectOutputStream stream) throws IOException {
+ stream.defaultWriteObject();
+ stream.writeInt(size());
+ Iterator<?> it = new ArrayDequeIterator<E>();
+ while (it.hasNext()) {
+ stream.writeObject(it.next());
+ }
+ }
+
+} \ No newline at end of file
diff --git a/luni/src/main/java/java/util/Deque.java b/luni/src/main/java/java/util/Deque.java
new file mode 100644
index 0000000..b13cdb0
--- /dev/null
+++ b/luni/src/main/java/java/util/Deque.java
@@ -0,0 +1,255 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util;
+
+/**
+ * A kind of collection that can insert or remove element at both ends("double
+ * ended queue"). Mostly a deque has no limit of its size.
+ *
+ * Extending from Queue, a deque can be used as a Queue which behavior is
+ * first-in-first-out. Furthermore, a deque can also be used as a Stack(legacy
+ * class) which behavior is last-in-first-out.
+ *
+ * A typical deque does not allow null to be inserted as its element, while some
+ * implementations allow it. But null should not be inserted even in these
+ * implementations, since method poll return null to indicate that there is no
+ * element left in the deque.
+ *
+ * A deque can also remove interior elements by removeFirstOccurrence and
+ * removeLastOccurrence methods. A deque can not access elements by index.
+ *
+ * @param <E>
+ * the type of elements in this collection
+ * @since 1.6
+ */
+public interface Deque<E> extends Queue<E> {
+
+ /**
+ * Inserts an element at the head of this deque if it dose not violate size
+ * limit immediately. It is better to use offerFirst(E) if a deque is
+ * size-limited.
+ *
+ * @param e
+ * the element
+ * @throws IllegalStateException
+ * if it can not add now due to size limit
+ * @throws ClassCastException
+ * if the class of element can not be added into this deque
+ * @throws NullPointerException
+ * if the element is null and the deque can not contain null
+ * element
+ * @throws IllegalArgumentException
+ * if the element can not be added due to some property.
+ */
+ void addFirst(E e);
+
+ /**
+ * Inserts an element at the tail of this deque if it dose not violate size
+ * limit immediately. It is better to use offerLast(E) if a deque is
+ * size-limited.
+ *
+ * @param e
+ * the element
+ * @throws IllegalStateException
+ * if it can not add now due to size limit
+ * @throws ClassCastException
+ * if the class of element can not be added into this deque
+ * @throws NullPointerException
+ * if the element is null and the deque can not contain null
+ * element
+ * @throws IllegalArgumentException
+ * if the element can not be added due to some property.
+ */
+ void addLast(E e);
+
+ /**
+ * Inserts an element at the head of this deque unless it would violate size
+ * limit. It is better than the addFirst(E) method in a size-limited deque,
+ * because the latter one may fail to add the element only by throwing an
+ * exception.
+ *
+ * @param e
+ * the element
+ * @return true if the operation succeeds or false if it fails.
+ * @throws ClassCastException
+ * if the class of element can not be added into this deque
+ * @throws NullPointerException
+ * if the element is null and the deque can not contain null
+ * element
+ * @throws IllegalArgumentException
+ * if the element can not be added due to some property.
+ */
+ boolean offerFirst(E e);
+
+ /**
+ * Inserts an element at the tail of this deque unless it would violate size
+ * limit. It is better than the addLast(E) method in a size-limited deque,
+ * because the latter one may fail to add the element only by throwing an
+ * exception.
+ *
+ * @param e
+ * the element
+ * @return true if the operation succeeds or false if it fails
+ * @throws ClassCastException
+ * if the class of element can not be added into this deque
+ * @throws NullPointerException
+ * if the element is null and the deque can not contain null
+ * element
+ * @throws IllegalArgumentException
+ * if the element can not be added due to some property
+ */
+ boolean offerLast(E e);
+
+ /**
+ * Gets and removes the head element of this deque. This method throws an
+ * exception if the deque is empty.
+ *
+ * @return the head element
+ * @throws NoSuchElementException
+ * if the deque is empty
+ */
+ E removeFirst();
+
+ /**
+ * Gets and removes the tail element of this deque. This method throws an
+ * exception if the deque is empty.
+ *
+ * @return the tail element
+ * @throws NoSuchElementException
+ * if the deque is empty
+ */
+ E removeLast();
+
+ /**
+ * Gets and removes the head element of this deque. This method returns null
+ * if the deque is empty.
+ *
+ * @return the head element or null if the deque is empty
+ */
+ E pollFirst();
+
+ /**
+ * Gets and removes the tail element of this deque. This method returns null
+ * if the deque is empty.
+ *
+ * @return the tail element or null if the deque is empty
+ */
+ E pollLast();
+
+ /**
+ * Gets but not removes the head element of this deque. This method throws
+ * an exception if the deque is empty.
+ *
+ * @return the head element
+ * @throws NoSuchElementException
+ * if the deque is empty
+ */
+ E getFirst();
+
+ /**
+ * Gets but not removes the tail element of this deque. This method throws
+ * an exception if the deque is empty.
+ *
+ * @return the tail element
+ * @throws NoSuchElementException
+ * if the deque is empty
+ */
+ E getLast();
+
+ /**
+ * Gets but not removes the head element of this deque. This method returns
+ * null if the deque is empty.
+ *
+ * @return the head element or null if the deque is empty
+ */
+ E peekFirst();
+
+ /**
+ * Gets but not removes the tail element of this deque. This method returns
+ * null if the deque is empty.
+ *
+ * @return the tail element or null if the deque is empty
+ */
+ E peekLast();
+
+ /**
+ * Removes the first equivalent element of the specified object. If the
+ * deque does not contain the element, it is unchanged and returns false.
+ *
+ * @param o
+ * the element to be removed
+ * @return true if the operation succeeds or false if the deque does not
+ * contain the element.
+ * @throws ClassCastException
+ * if the class of the element is incompatible with the deque
+ * @throws NullPointerException
+ * if the element is null and the deque can not contain null
+ * element
+ */
+ boolean removeFirstOccurrence(Object o);
+
+ /**
+ * Removes the last equivalent element of the specified object. If the deque
+ * does not contain the element, it is unchanged and returns false.
+ *
+ * @param o
+ * the element to be removed
+ * @return true if the operation succeeds or false if the deque does not
+ * contain the element.
+ * @throws ClassCastException
+ * if the class of the element is incompatible with the deque
+ * @throws NullPointerException
+ * if the element is null and the deque can not contain null
+ * element
+ */
+ boolean removeLastOccurrence(Object o);
+
+ /**
+ * Pushes the element to the deque(at the head of the deque), just same as
+ * addFirst(E).
+ *
+ * @param e
+ * the element
+ * @throws IllegalStateException
+ * if it can not add now due to size limit
+ * @throws ClassCastException
+ * if the class of element can not be added into this deque
+ * @throws NullPointerException
+ * if the element is null and the deque can not contain null
+ * element
+ * @throws IllegalArgumentException
+ * if the element can not be added due to some property.
+ */
+ void push(E e);
+
+ /**
+ * Pops the head element of the deque, just same as removeFirst().
+ *
+ * @return the head element
+ * @throws NoSuchElementException
+ * if the deque is empty
+ */
+ E pop();
+
+ /**
+ * Returns the iterator in reverse order, from tail to head.
+ *
+ * @return the iterator in reverse order
+ */
+ Iterator<E> descendingIterator();
+} \ No newline at end of file
diff --git a/luni/src/main/java/java/util/NavigableMap.java b/luni/src/main/java/java/util/NavigableMap.java
new file mode 100644
index 0000000..a87a8c0
--- /dev/null
+++ b/luni/src/main/java/java/util/NavigableMap.java
@@ -0,0 +1,262 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util;
+
+/**
+ * NavigableMap is a SortedMap with navigation methods answering the closest
+ * matches for specified item.
+ *
+ * @param <K>
+ * the type of key
+ * @param <V>
+ * the type of value
+ * @since 1.6
+ */
+public interface NavigableMap<K, V> extends SortedMap<K, V> {
+ /**
+ * Returns the entry with the smallest key, or null if the map is empty.
+ *
+ * @return the entry with the smallest key, or null if the map is empty
+ */
+ Map.Entry<K, V> firstEntry();
+
+ /**
+ * Returns the entry with the biggest key, or null if the map is empty.
+ *
+ * @return the entry with the biggest key, or null if the map is empty
+ */
+ Map.Entry<K, V> lastEntry();
+
+ /**
+ * Deletes and returns the entry with the smallest key, or null if the map
+ * is empty.
+ *
+ * @return the entry with the smallest key, or null if the map is empty
+ */
+ Map.Entry<K, V> pollFirstEntry();
+
+ /**
+ * Deletes and returns the entry with the biggest key, or null if the map is
+ * empty.
+ *
+ * @return the entry with the biggest key, or null if the map is empty
+ */
+ Map.Entry<K, V> pollLastEntry();
+
+ /**
+ * Returns an entry related with the smallest key greater than or equal to
+ * the specified key, or null if no such key.
+ *
+ * @param key
+ * the key
+ * @return the entry, or null if no such key
+ * @throws ClassCastException
+ * if the key cannot be compared with the keys in the map
+ * @throws NullPointerException
+ * if the key is null and the map can not contain null key
+ */
+ Map.Entry<K, V> ceilingEntry(K key);
+
+ /**
+ * Returns the smallest key greater than or equal to the specified key, or
+ * null if no such key.
+ *
+ * @param key
+ * the key
+ * @return the smallest key greater than or equal to key, or null if no such
+ * key
+ * @throws ClassCastException
+ * if the key cannot be compared with the keys in the map
+ * @throws NullPointerException
+ * if the key is null and the map can not contain null key
+ */
+ K ceilingKey(K key);
+
+ /**
+ * Returns an entry related with the smallest key greater than the specified
+ * key, or null if no such key.
+ *
+ * @param key
+ * the key
+ * @return the entry, or null if no such key
+ * @throws ClassCastException
+ * if the key cannot be compared with the keys in the map
+ * @throws NullPointerException
+ * if the key is null and the map can not contain null key
+ */
+ Map.Entry<K, V> higherEntry(K key);
+
+ /**
+ * Returns the smallest key greater than the specified key, or null if no
+ * such key.
+ *
+ * @param key
+ * the key
+ * @return the smallest key greater than key, or null if no such key
+ * @throws ClassCastException
+ * if the key cannot be compared with the keys in the map
+ * @throws NullPointerException
+ * if the key is null and the map can not contain null key
+ */
+ K higherKey(K key);
+
+ /**
+ * Returns an entry related with the biggest key less than or equal to the
+ * specified key, or null if no such key.
+ *
+ * @param key
+ * the key
+ * @return the entry, or null if no such key
+ * @throws ClassCastException
+ * if the key cannot be compared with the keys in the map
+ * @throws NullPointerException
+ * if the key is null and the map can not contain null key
+ */
+ Map.Entry<K, V> floorEntry(K key);
+
+ /**
+ * Returns the biggest key less than or equal to the specified key, or null
+ * if no such key.
+ *
+ * @param key
+ * the key
+ * @return the biggest key less than or equal to key, or null if no such key
+ * @throws ClassCastException
+ * if the key cannot be compared with the keys in the map
+ * @throws NullPointerException
+ * if the key is null and the map can not contain null key
+ */
+ K floorKey(K key);
+
+ /**
+ * Returns an entry related with the biggest key less than the specified
+ * key, or null if no such key.
+ *
+ * @param key
+ * the key
+ * @return the entry, or null if no such key
+ * @throws ClassCastException
+ * if the key cannot be compared with the keys in the map
+ * @throws NullPointerException
+ * if the key is null and the map can not contain null key
+ */
+ Map.Entry<K, V> lowerEntry(K key);
+
+ /**
+ * Returns the biggest key less than the specified key, or null if no such
+ * key.
+ *
+ * @param key
+ * the key
+ * @return the biggest key less than key, or null if no such key
+ * @throws ClassCastException
+ * if the key cannot be compared with the keys in the map
+ * @throws NullPointerException
+ * if the key is null and the map can not contain null key
+ */
+ K lowerKey(K key);
+
+ /**
+ * Returns a NavigableSet view of the keys in ascending order.
+ *
+ * @return the navigable set view
+ */
+ NavigableSet<K> navigableKeySet();
+
+ /**
+ * Returns a reverse order view of the map.
+ *
+ * @return the reverse order view of the map
+ */
+ NavigableMap<K, V> descendingMap();
+
+ /**
+ * Returns a NavigableSet view of the keys in descending order.
+ *
+ * @return the navigable set view
+ */
+ NavigableSet<K> descendingKeySet();
+
+ /**
+ * Returns a view of part of the map whose keys is from startKey to endKey.
+ *
+ * @param startKey
+ * the start key
+ * @param startInclusive
+ * true if the start key is in the returned map
+ * @param endKey
+ * the end key
+ * @param endInclusive
+ * true if the end key is in the returned map
+ * @return the sub-map view
+ *
+ * @exception ClassCastException
+ * when the class of the start or end key is inappropriate
+ * for this SubMap
+ * @exception NullPointerException
+ * when the start or end key is null and this SortedMap does
+ * not support null keys
+ * @exception IllegalArgumentException
+ * when the start key is greater than the end key
+ */
+ NavigableMap<K, V> subMap(K startKey, boolean startInclusive, K endKey,
+ boolean endInclusive);
+
+ /**
+ * Returns a view of the head of the map whose keys are smaller than (or
+ * equal to, depends on inclusive argument) endKey.
+ *
+ * @param endKey
+ * the end key
+ * @param inclusive
+ * true if the end key is in the returned map
+ * @return the head-map view
+ *
+ * @exception ClassCastException
+ * when the class of the end key is inappropriate for this
+ * SubMap
+ * @exception NullPointerException
+ * when the end key is null and this SortedMap does not
+ * support null keys
+ * @exception IllegalArgumentException
+ * when the map is range-limited and end key is out of the
+ * range of the map
+ */
+ NavigableMap<K, V> headMap(K endKey, boolean inclusive);
+
+ /**
+ * Returns a view of the tail of the map whose keys are bigger than (or
+ * equal to, depends on inclusive argument) startKey.
+ *
+ * @param startKey
+ * the start key
+ * @param inclusive
+ * true if the start key is in the returned map
+ * @return the tail-map view
+ *
+ * @exception ClassCastException
+ * when the class of the start key is inappropriate for this
+ * SubMap
+ * @exception NullPointerException
+ * when the start key is null and this SortedMap does not
+ * support null keys
+ * @exception IllegalArgumentException
+ * when the map is range-limited and start key is out of the
+ * range of the map
+ */
+ NavigableMap<K, V> tailMap(K startKey, boolean inclusive);
+} \ No newline at end of file
diff --git a/luni/src/main/java/java/util/NavigableSet.java b/luni/src/main/java/java/util/NavigableSet.java
new file mode 100644
index 0000000..ae94b77
--- /dev/null
+++ b/luni/src/main/java/java/util/NavigableSet.java
@@ -0,0 +1,192 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util;
+
+/**
+ * NavigableSet is a SortedSet with navigation methods answering the closest
+ * matches for specified item.
+ *
+ * @param <E>
+ * the type of element
+ * @since 1.6
+ */
+public interface NavigableSet<E> extends SortedSet<E> {
+
+ /**
+ * Deletes and returns the smallest element, or null if the set is empty.
+ *
+ * @return the smallest element, or null if the set is empty
+ */
+ E pollFirst();
+
+ /**
+ * Deletes and returns the biggest element, or null if the set is empty.
+ *
+ * @return the biggest element, or null if the set is empty
+ */
+ E pollLast();
+
+ /**
+ * Returns the smallest element bigger than the specified one, or null if no
+ * such element.
+ *
+ * @param e
+ * the specified element
+ * @return the smallest element bigger than the specified one, or null if no
+ * such element
+ * @throws ClassCastException
+ * if the element cannot be compared with the ones in the set
+ * @throws NullPointerException
+ * if the element is null and the set can not contain null
+ */
+ E higher(E e);
+
+ /**
+ * Returns the smallest element bigger than or equal to the specified one,
+ * or null if no such element.
+ *
+ * @param e
+ * the specified element
+ * @return the smallest element bigger than or equal to the specified one,
+ * or null if no such element
+ * @throws ClassCastException
+ * if the element cannot be compared with the ones in the set
+ * @throws NullPointerException
+ * if the element is null and the set can not contain null
+ */
+ E ceiling(E e);
+
+ /**
+ * Returns the biggest element less than the specified one, or null if no
+ * such element.
+ *
+ * @param e
+ * the specified element
+ * @return the biggest element less than the specified one, or null if no
+ * such element
+ * @throws ClassCastException
+ * if the element cannot be compared with the ones in the set
+ * @throws NullPointerException
+ * if the element is null and the set can not contain null
+ */
+ E lower(E e);
+
+ /**
+ * Returns the biggest element less than or equal to the specified one, or
+ * null if no such element.
+ *
+ * @param e
+ * the specified element
+ * @return the biggest element less than or equal to the specified one, or
+ * null if no such element
+ * @throws ClassCastException
+ * if the element cannot be compared with the ones in the set
+ * @throws NullPointerException
+ * if the element is null and the set can not contain null
+ */
+ E floor(E e);
+
+ /**
+ * Returns a descending iterator of this set.
+ *
+ * @return the descending iterator
+ */
+ Iterator<E> descendingIterator();
+
+ /**
+ * Returns a reverse order view of this set.
+ *
+ * @return the reverse order view
+ */
+ NavigableSet<E> descendingSet();
+
+ /**
+ * Returns a NavigableSet of the specified portion of this set which
+ * contains elements greater (or equal to, depends on startInclusive) the
+ * start element but less than (or equal to, depends on endInclusive) the
+ * end element. The returned NavigableSet is backed by this set so changes
+ * to one are reflected by the other.
+ *
+ * @param start
+ * the start element
+ * @param startInclusive
+ * true if the start element is in the returned set
+ * @param end
+ * the end element
+ * @param endInclusive
+ * true if the end element is in the returned set
+ * @return the subset
+ *
+ * @throws ClassCastException
+ * when the start or end object cannot be compared with the
+ * elements in this set
+ * @throws NullPointerException
+ * when the start or end object is null and the set cannot
+ * contain null
+ * @throws IllegalArgumentException
+ * when the start is bigger than end; or start or end is out of
+ * range and the set has a range
+ */
+ NavigableSet<E> subSet(E start, boolean startInclusive, E end,
+ boolean endInclusive);
+
+ /**
+ * Returns a NavigableSet of the specified portion of this set which
+ * contains elements less than (or equal to, depends on endInclusive) the
+ * end element. The returned NavigableSet is backed by this set so changes
+ * to one are reflected by the other.
+ *
+ * @param end
+ * the end element
+ * @param endInclusive
+ * true if the end element is in the returned set
+ * @return the subset
+ *
+ * @throws ClassCastException
+ * when the end object cannot be compared with the elements in
+ * this set
+ * @throws NullPointerException
+ * when the end object is null and the set cannot contain handle
+ * null
+ * @throws IllegalArgumentException
+ * when end is out of range and the set has a range
+ */
+ NavigableSet<E> headSet(E end, boolean endInclusive);
+
+ /**
+ * Returns a NavigableSet of the specified portion of this set which
+ * contains elements greater (or equal to, depends on startInclusive) the
+ * start element. The returned NavigableSet is backed by this set so changes
+ * to one are reflected by the other.
+ *
+ * @param start
+ * the start element
+ * @param startInclusive
+ * true if the start element is in the returned set
+ * @return the subset
+ *
+ * @throws ClassCastException
+ * when the start object cannot be compared with the elements in
+ * this set
+ * @throws NullPointerException
+ * when the start object is null and the set cannot contain null
+ * @throws IllegalArgumentException
+ * when start is out of range and the set has a range
+ */
+ NavigableSet<E> tailSet(E start, boolean startInclusive);
+} \ No newline at end of file
diff --git a/suncompat/src/main/java/sun/misc/Unsafe.java b/suncompat/src/main/java/sun/misc/Unsafe.java
index 6ae572f..5c6aa01 100644
--- a/suncompat/src/main/java/sun/misc/Unsafe.java
+++ b/suncompat/src/main/java/sun/misc/Unsafe.java
@@ -17,11 +17,9 @@
package sun.misc;
import dalvik.system.VMStack;
-
-import org.apache.harmony.kernel.vm.LangAccess;
-
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
+import org.apache.harmony.kernel.vm.LangAccess;
/**
* The package name notwithstanding, this class is the quasi-standard
@@ -106,7 +104,6 @@ public final class Unsafe {
* Helper for {@link #arrayBaseOffset}, which does all the work,
* assuming the parameter is deemed valid.
*
- * @param field non-null; the instance field
* @return the offset to the field
*/
private static native int arrayBaseOffset0(Class clazz);
@@ -130,7 +127,6 @@ public final class Unsafe {
* Helper for {@link #arrayIndexScale}, which does all the work,
* assuming the parameter is deemed valid.
*
- * @param field non-null; the instance field
* @return the offset to the field
*/
private static native int arrayIndexScale0(Class clazz);
@@ -258,7 +254,15 @@ public final class Unsafe {
* @param newValue the value to store
*/
public native void putInt(Object obj, long offset, int newValue);
-
+
+ /**
+ * Lazy set an int field.
+ */
+ public void putOrderedInt(Object obj, long offset, int newValue) {
+ // TODO: this should be an intrinsic that executes a store fence followed by a write
+ putIntVolatile(obj, offset, newValue);
+ }
+
/**
* Gets a <code>long</code> field from the given object.
*
@@ -278,6 +282,14 @@ public final class Unsafe {
public native void putLong(Object obj, long offset, long newValue);
/**
+ * Lazy set a long field.
+ */
+ public void putOrderedLong(Object obj, long offset, long newValue) {
+ // TODO: this should be an intrinsic that executes a store fence followed by a write
+ putLongVolatile(obj, offset, newValue);
+ }
+
+ /**
* Gets an <code>Object</code> field from the given object.
*
* @param obj non-null; object containing the field
@@ -296,6 +308,14 @@ public final class Unsafe {
public native void putObject(Object obj, long offset, Object newValue);
/**
+ * Lazy set an object field.
+ */
+ public void putOrderedObject(Object obj, long offset, Object newValue) {
+ // TODO: this should be an intrinsic that executes a store fence followed by a write
+ putObjectVolatile(obj, offset, newValue);
+ }
+
+ /**
* Parks the calling thread for the specified amount of time,
* unless the "permit" for the thread is already available (due to
* a previous call to {@link #unpark}. This method may also return
@@ -333,6 +353,4 @@ public final class Unsafe {
throw new IllegalArgumentException("valid for Threads only");
}
}
-
- // TODO(danfuzz): Stuff goes here.
}