summaryrefslogtreecommitdiff
path: root/libjava/classpath/external/jsr166/java/util/concurrent
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/external/jsr166/java/util/concurrent')
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/AbstractExecutorService.java270
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/ArrayBlockingQueue.java778
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/BlockingDeque.java613
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/BlockingQueue.java344
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/BrokenBarrierException.java38
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/Callable.java36
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/CancellationException.java34
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/CompletionService.java97
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/ConcurrentHashMap.java1277
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/ConcurrentLinkedQueue.java480
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/ConcurrentMap.java134
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/ConcurrentNavigableMap.java148
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/ConcurrentSkipListMap.java3114
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/ConcurrentSkipListSet.java456
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/CopyOnWriteArraySet.java364
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/CountDownLatch.java290
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/CyclicBarrier.java454
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/DelayQueue.java487
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/Delayed.java33
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/Exchanger.java656
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/ExecutionException.java65
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/Executor.java112
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/ExecutorCompletionService.java174
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/ExecutorService.java306
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/Executors.java666
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/Future.java142
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/FutureTask.java325
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/LinkedBlockingDeque.java1021
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/LinkedBlockingQueue.java807
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/PriorityBlockingQueue.java563
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/RejectedExecutionException.java62
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/RejectedExecutionHandler.java33
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/RunnableFuture.java25
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/RunnableScheduledFuture.java29
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/ScheduledExecutorService.java159
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/ScheduledFuture.java19
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/ScheduledThreadPoolExecutor.java626
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/Semaphore.java681
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/SynchronousQueue.java1127
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/ThreadFactory.java40
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/ThreadPoolExecutor.java1605
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/TimeUnit.java331
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/TimeoutException.java38
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicBoolean.java133
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicInteger.java234
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicIntegerArray.java255
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java316
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicLong.java248
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicLongArray.java255
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicLongFieldUpdater.java406
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicMarkableReference.java161
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicReference.java124
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicReferenceArray.java163
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java275
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicStampedReference.java165
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/locks/AbstractOwnableSynchronizer.java57
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java1934
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/locks/AbstractQueuedSynchronizer.java2159
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/locks/Condition.java435
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/locks/Lock.java327
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/locks/LockSupport.java352
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/locks/ReadWriteLock.java104
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/locks/ReentrantLock.java740
-rw-r--r--libjava/classpath/external/jsr166/java/util/concurrent/locks/ReentrantReadWriteLock.java1346
64 files changed, 29248 insertions, 0 deletions
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/AbstractExecutorService.java b/libjava/classpath/external/jsr166/java/util/concurrent/AbstractExecutorService.java
new file mode 100644
index 000000000..ac15c5010
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/AbstractExecutorService.java
@@ -0,0 +1,270 @@
+/*
+ * 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.*;
+
+/**
+ * Provides default implementations of {@link ExecutorService}
+ * execution methods. This class implements the <tt>submit</tt>,
+ * <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>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);
+ }
+
+ public Future<?> submit(Runnable task) {
+ if (task == null) throw new NullPointerException();
+ RunnableFuture<Object> ftask = newTaskFor(task, null);
+ execute(ftask);
+ return ftask;
+ }
+
+ public <T> Future<T> submit(Runnable task, T result) {
+ if (task == null) throw new NullPointerException();
+ RunnableFuture<T> ftask = newTaskFor(task, result);
+ execute(ftask);
+ return ftask;
+ }
+
+ public <T> Future<T> submit(Callable<T> task) {
+ if (task == null) throw new NullPointerException();
+ RunnableFuture<T> ftask = newTaskFor(task);
+ execute(ftask);
+ return ftask;
+ }
+
+ /**
+ * the main mechanics of invokeAny.
+ */
+ private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,
+ boolean timed, long nanos)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ if (tasks == null)
+ throw new NullPointerException();
+ int ntasks = tasks.size();
+ if (ntasks == 0)
+ throw new IllegalArgumentException();
+ List<Future<T>> futures= new ArrayList<Future<T>>(ntasks);
+ ExecutorCompletionService<T> ecs =
+ new ExecutorCompletionService<T>(this);
+
+ // For efficiency, especially in executors with limited
+ // parallelism, check to see if previously submitted tasks are
+ // done before submitting more of them. This interleaving
+ // plus the exception mechanics account for messiness of main
+ // loop.
+
+ try {
+ // Record exceptions so that if we fail to obtain any
+ // result, we can throw the last exception we got.
+ ExecutionException ee = null;
+ long lastTime = (timed)? System.nanoTime() : 0;
+ Iterator<? extends Callable<T>> it = tasks.iterator();
+
+ // Start one task for sure; the rest incrementally
+ futures.add(ecs.submit(it.next()));
+ --ntasks;
+ int active = 1;
+
+ for (;;) {
+ Future<T> f = ecs.poll();
+ if (f == null) {
+ if (ntasks > 0) {
+ --ntasks;
+ futures.add(ecs.submit(it.next()));
+ ++active;
+ }
+ else if (active == 0)
+ break;
+ else if (timed) {
+ f = ecs.poll(nanos, TimeUnit.NANOSECONDS);
+ if (f == null)
+ throw new TimeoutException();
+ long now = System.nanoTime();
+ nanos -= now - lastTime;
+ lastTime = now;
+ }
+ else
+ f = ecs.take();
+ }
+ if (f != null) {
+ --active;
+ try {
+ return f.get();
+ } catch (InterruptedException ie) {
+ throw ie;
+ } catch (ExecutionException eex) {
+ ee = eex;
+ } catch (RuntimeException rex) {
+ ee = new ExecutionException(rex);
+ }
+ }
+ }
+
+ if (ee == null)
+ ee = new ExecutionException();
+ throw ee;
+
+ } finally {
+ for (Future<T> f : futures)
+ f.cancel(true);
+ }
+ }
+
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException, ExecutionException {
+ try {
+ return doInvokeAny(tasks, false, 0);
+ } catch (TimeoutException cannotHappen) {
+ assert false;
+ return null;
+ }
+ }
+
+ 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<? extends Callable<T>> tasks)
+ throws InterruptedException {
+ if (tasks == null)
+ throw new NullPointerException();
+ List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
+ boolean done = false;
+ try {
+ for (Callable<T> t : tasks) {
+ RunnableFuture<T> f = newTaskFor(t);
+ futures.add(f);
+ execute(f);
+ }
+ for (Future<T> f : futures) {
+ if (!f.isDone()) {
+ try {
+ f.get();
+ } catch (CancellationException ignore) {
+ } catch (ExecutionException ignore) {
+ }
+ }
+ }
+ done = true;
+ return futures;
+ } finally {
+ if (!done)
+ for (Future<T> f : futures)
+ f.cancel(true);
+ }
+ }
+
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
+ long timeout, TimeUnit unit)
+ throws InterruptedException {
+ if (tasks == null || unit == null)
+ throw new NullPointerException();
+ long nanos = unit.toNanos(timeout);
+ List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
+ boolean done = false;
+ try {
+ for (Callable<T> t : tasks)
+ futures.add(newTaskFor(t));
+
+ long lastTime = System.nanoTime();
+
+ // Interleave time checks and calls to execute in case
+ // executor doesn't have any/much parallelism.
+ Iterator<Future<T>> it = futures.iterator();
+ while (it.hasNext()) {
+ execute((Runnable)(it.next()));
+ long now = System.nanoTime();
+ nanos -= now - lastTime;
+ lastTime = now;
+ if (nanos <= 0)
+ return futures;
+ }
+
+ for (Future<T> f : futures) {
+ if (!f.isDone()) {
+ if (nanos <= 0)
+ return futures;
+ try {
+ f.get(nanos, TimeUnit.NANOSECONDS);
+ } catch (CancellationException ignore) {
+ } catch (ExecutionException ignore) {
+ } catch (TimeoutException toe) {
+ return futures;
+ }
+ long now = System.nanoTime();
+ nanos -= now - lastTime;
+ lastTime = now;
+ }
+ }
+ done = true;
+ return futures;
+ } finally {
+ if (!done)
+ for (Future<T> f : futures)
+ f.cancel(true);
+ }
+ }
+
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/ArrayBlockingQueue.java b/libjava/classpath/external/jsr166/java/util/concurrent/ArrayBlockingQueue.java
new file mode 100644
index 000000000..3ce9ed859
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/ArrayBlockingQueue.java
@@ -0,0 +1,778 @@
+/*
+ * 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.concurrent.locks.*;
+import java.util.*;
+
+/**
+ * A bounded {@linkplain BlockingQueue blocking queue} backed by an
+ * array. This queue orders elements FIFO (first-in-first-out). The
+ * <em>head</em> of the queue is that element that has been on the
+ * queue the longest time. The <em>tail</em> of the queue is that
+ * element that has been on the queue the shortest time. New elements
+ * are inserted at the tail of the queue, and the queue retrieval
+ * operations obtain elements at the head of the queue.
+ *
+ * <p>This is a classic &quot;bounded buffer&quot;, in which a
+ * fixed-sized array holds elements inserted by producers and
+ * extracted by consumers. Once created, the capacity cannot be
+ * increased. Attempts to <tt>put</tt> an element into a full queue
+ * will result in the operation blocking; attempts to <tt>take</tt> an
+ * element from an empty queue will similarly block.
+ *
+ * <p> This class supports an optional fairness policy for ordering
+ * waiting producer and consumer threads. By default, this ordering
+ * is not guaranteed. However, a queue constructed with fairness set
+ * to <tt>true</tt> grants threads access in FIFO order. Fairness
+ * generally decreases throughput but reduces variability and avoids
+ * starvation.
+ *
+ * <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.5
+ * @author Doug Lea
+ * @param <E> the type of elements held in this collection
+ */
+public class ArrayBlockingQueue<E> extends AbstractQueue<E>
+ implements BlockingQueue<E>, java.io.Serializable {
+
+ /**
+ * Serialization ID. This class relies on default serialization
+ * even for the items array, which is default-serialized, even if
+ * it is empty. Otherwise it could not be declared final, which is
+ * necessary here.
+ */
+ private static final long serialVersionUID = -817911632652898426L;
+
+ /** The queued items */
+ private final E[] items;
+ /** items index for next take, poll or remove */
+ private int takeIndex;
+ /** items index for next put, offer, or add. */
+ private int putIndex;
+ /** Number of items in the queue */
+ private int count;
+
+ /*
+ * Concurrency control uses the classic two-condition algorithm
+ * found in any textbook.
+ */
+
+ /** Main lock guarding all access */
+ private final ReentrantLock lock;
+ /** Condition for waiting takes */
+ private final Condition notEmpty;
+ /** Condition for waiting puts */
+ private final Condition notFull;
+
+ // Internal helper methods
+
+ /**
+ * Circularly increment i.
+ */
+ final int inc(int i) {
+ return (++i == items.length)? 0 : i;
+ }
+
+ /**
+ * Inserts element at current put position, advances, and signals.
+ * Call only when holding lock.
+ */
+ private void insert(E x) {
+ items[putIndex] = x;
+ putIndex = inc(putIndex);
+ ++count;
+ notEmpty.signal();
+ }
+
+ /**
+ * Extracts element at current take position, advances, and signals.
+ * Call only when holding lock.
+ */
+ private E extract() {
+ final E[] items = this.items;
+ E x = items[takeIndex];
+ items[takeIndex] = null;
+ takeIndex = inc(takeIndex);
+ --count;
+ notFull.signal();
+ return x;
+ }
+
+ /**
+ * Utility for remove and iterator.remove: Delete item at position i.
+ * Call only when holding lock.
+ */
+ void removeAt(int i) {
+ final E[] items = this.items;
+ // if removing front item, just advance
+ if (i == takeIndex) {
+ items[takeIndex] = null;
+ takeIndex = inc(takeIndex);
+ } else {
+ // slide over all others up through putIndex.
+ for (;;) {
+ int nexti = inc(i);
+ if (nexti != putIndex) {
+ items[i] = items[nexti];
+ i = nexti;
+ } else {
+ items[i] = null;
+ putIndex = i;
+ break;
+ }
+ }
+ }
+ --count;
+ notFull.signal();
+ }
+
+ /**
+ * Creates an <tt>ArrayBlockingQueue</tt> with the given (fixed)
+ * capacity and default access policy.
+ *
+ * @param capacity the capacity of this queue
+ * @throws IllegalArgumentException if <tt>capacity</tt> is less than 1
+ */
+ public ArrayBlockingQueue(int capacity) {
+ this(capacity, false);
+ }
+
+ /**
+ * Creates an <tt>ArrayBlockingQueue</tt> with the given (fixed)
+ * capacity and the specified access policy.
+ *
+ * @param capacity the capacity of this queue
+ * @param fair if <tt>true</tt> then queue accesses for threads blocked
+ * on insertion or removal, are processed in FIFO order;
+ * if <tt>false</tt> the access order is unspecified.
+ * @throws IllegalArgumentException if <tt>capacity</tt> is less than 1
+ */
+ public ArrayBlockingQueue(int capacity, boolean fair) {
+ if (capacity <= 0)
+ throw new IllegalArgumentException();
+ this.items = (E[]) new Object[capacity];
+ lock = new ReentrantLock(fair);
+ notEmpty = lock.newCondition();
+ notFull = lock.newCondition();
+ }
+
+ /**
+ * Creates an <tt>ArrayBlockingQueue</tt> with the given (fixed)
+ * capacity, the specified access policy and initially containing the
+ * elements of the given collection,
+ * added in traversal order of the collection's iterator.
+ *
+ * @param capacity the capacity of this queue
+ * @param fair if <tt>true</tt> then queue accesses for threads blocked
+ * on insertion or removal, are processed in FIFO order;
+ * if <tt>false</tt> the access order is unspecified.
+ * @param c the collection of elements to initially contain
+ * @throws IllegalArgumentException if <tt>capacity</tt> is less than
+ * <tt>c.size()</tt>, or less than 1.
+ * @throws NullPointerException if the specified collection or any
+ * of its elements are null
+ */
+ public ArrayBlockingQueue(int capacity, boolean fair,
+ Collection<? extends E> c) {
+ this(capacity, fair);
+ if (capacity < c.size())
+ throw new IllegalArgumentException();
+
+ for (Iterator<? extends E> it = c.iterator(); it.hasNext();)
+ add(it.next());
+ }
+
+ /**
+ * 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 throwing an
+ * <tt>IllegalStateException</tt> if this queue is full.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> (as specified by {@link Collection#add})
+ * @throws IllegalStateException if this queue is full
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean add(E e) {
+ return super.add(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
+ * is full. This method is generally preferable to method {@link #add},
+ * which can fail to insert an element only by throwing an exception.
+ *
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean offer(E e) {
+ if (e == null) throw new NullPointerException();
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ if (count == items.length)
+ return false;
+ else {
+ insert(e);
+ return true;
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Inserts the specified element at the tail of this queue, waiting
+ * for space to become available if the queue is full.
+ *
+ * @throws InterruptedException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public void put(E e) throws InterruptedException {
+ if (e == null) throw new NullPointerException();
+ final E[] items = this.items;
+ final ReentrantLock lock = this.lock;
+ lock.lockInterruptibly();
+ try {
+ try {
+ while (count == items.length)
+ notFull.await();
+ } catch (InterruptedException ie) {
+ notFull.signal(); // propagate to non-interrupted thread
+ throw ie;
+ }
+ insert(e);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Inserts the specified element at the tail of this queue, waiting
+ * up to the specified wait time for space to become available if
+ * the queue is full.
+ *
+ * @throws InterruptedException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean offer(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 {
+ for (;;) {
+ if (count != items.length) {
+ insert(e);
+ return true;
+ }
+ if (nanos <= 0)
+ return false;
+ try {
+ nanos = notFull.awaitNanos(nanos);
+ } catch (InterruptedException ie) {
+ notFull.signal(); // propagate to non-interrupted thread
+ throw ie;
+ }
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E poll() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ if (count == 0)
+ return null;
+ E x = extract();
+ return x;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E take() throws InterruptedException {
+ final ReentrantLock lock = this.lock;
+ lock.lockInterruptibly();
+ try {
+ try {
+ while (count == 0)
+ notEmpty.await();
+ } catch (InterruptedException ie) {
+ notEmpty.signal(); // propagate to non-interrupted thread
+ throw ie;
+ }
+ E x = extract();
+ return x;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E poll(long timeout, TimeUnit unit) throws InterruptedException {
+ long nanos = unit.toNanos(timeout);
+ final ReentrantLock lock = this.lock;
+ lock.lockInterruptibly();
+ try {
+ for (;;) {
+ if (count != 0) {
+ E x = extract();
+ return x;
+ }
+ if (nanos <= 0)
+ return null;
+ try {
+ nanos = notEmpty.awaitNanos(nanos);
+ } catch (InterruptedException ie) {
+ notEmpty.signal(); // propagate to non-interrupted thread
+ throw ie;
+ }
+
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E peek() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return (count == 0) ? null : items[takeIndex];
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ // this doc comment is overridden to remove the reference to collections
+ // greater in size than Integer.MAX_VALUE
+ /**
+ * Returns the number of elements in this queue.
+ *
+ * @return the number of elements in this queue
+ */
+ public int size() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return count;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ // this doc comment is a modified copy of the inherited doc comment,
+ // without the reference to unlimited queues.
+ /**
+ * 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.
+ *
+ * <p>Note that you <em>cannot</em> always tell if an attempt to insert
+ * an element will succeed by inspecting <tt>remainingCapacity</tt>
+ * 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 items.length - count;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * 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
+ * elements.
+ * Returns <tt>true</tt> 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
+ */
+ public boolean remove(Object o) {
+ if (o == null) return false;
+ final E[] items = this.items;
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ int i = takeIndex;
+ int k = 0;
+ for (;;) {
+ if (k++ >= count)
+ return false;
+ if (o.equals(items[i])) {
+ removeAt(i);
+ return true;
+ }
+ i = inc(i);
+ }
+
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns <tt>true</tt> if this queue contains the specified element.
+ * More formally, returns <tt>true</tt> if and only if this queue 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 queue
+ * @return <tt>true</tt> if this queue contains the specified element
+ */
+ public boolean contains(Object o) {
+ if (o == null) return false;
+ final E[] items = this.items;
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ int i = takeIndex;
+ int k = 0;
+ while (k++ < count) {
+ if (o.equals(items[i]))
+ return true;
+ i = inc(i);
+ }
+ return false;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns an array containing all of the elements in this queue, in
+ * proper sequence.
+ *
+ * <p>The returned array will be "safe" in that no references to it are
+ * maintained by this queue. (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 queue
+ */
+ public Object[] toArray() {
+ final E[] items = this.items;
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ Object[] a = new Object[count];
+ int k = 0;
+ int i = takeIndex;
+ while (k < count) {
+ a[k++] = items[i];
+ i = inc(i);
+ }
+ return a;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns an array containing all of the elements in this queue, in
+ * proper sequence; the runtime type of the returned array is that of
+ * the specified array. If the queue 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 queue.
+ *
+ * <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>.
+ *
+ * <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.
+ * The following code can be used to dump the queue into a newly
+ * allocated array of <tt>String</tt>:
+ *
+ * <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>.
+ *
+ * @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
+ * same runtime type is allocated for this purpose
+ * @return an array containing all of the elements in this queue
+ * @throws ArrayStoreException if the runtime type of the specified array
+ * is not a supertype of the runtime type of every element in
+ * this queue
+ * @throws NullPointerException if the specified array is null
+ */
+ public <T> T[] toArray(T[] a) {
+ final E[] items = this.items;
+ 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;
+ int i = takeIndex;
+ while (k < count) {
+ a[k++] = (T)items[i];
+ i = inc(i);
+ }
+ if (a.length > count)
+ a[count] = 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 queue.
+ * The queue will be empty after this call returns.
+ */
+ public void clear() {
+ final E[] items = this.items;
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ int i = takeIndex;
+ int k = count;
+ while (k-- > 0) {
+ items[i] = null;
+ i = inc(i);
+ }
+ count = 0;
+ putIndex = 0;
+ takeIndex = 0;
+ notFull.signalAll();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws UnsupportedOperationException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public int drainTo(Collection<? super E> c) {
+ if (c == null)
+ throw new NullPointerException();
+ if (c == this)
+ throw new IllegalArgumentException();
+ final E[] items = this.items;
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ int i = takeIndex;
+ int n = 0;
+ int max = count;
+ while (n < max) {
+ c.add(items[i]);
+ items[i] = null;
+ i = inc(i);
+ ++n;
+ }
+ if (n > 0) {
+ count = 0;
+ putIndex = 0;
+ takeIndex = 0;
+ notFull.signalAll();
+ }
+ return n;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @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();
+ if (maxElements <= 0)
+ return 0;
+ final E[] items = this.items;
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ int i = takeIndex;
+ int n = 0;
+ int sz = count;
+ int max = (maxElements < count)? maxElements : count;
+ while (n < max) {
+ c.add(items[i]);
+ items[i] = null;
+ i = inc(i);
+ ++n;
+ }
+ if (n > 0) {
+ count -= n;
+ takeIndex = i;
+ notFull.signalAll();
+ }
+ return n;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+
+ /**
+ * 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},
+ * 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 queue in proper sequence
+ */
+ public Iterator<E> iterator() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return new Itr();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Iterator for ArrayBlockingQueue
+ */
+ private class Itr implements Iterator<E> {
+ /**
+ * Index of element to be returned by next,
+ * or a negative number if no such.
+ */
+ private int nextIndex;
+
+ /**
+ * 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;
+
+ /**
+ * Index of element returned by most recent call to next.
+ * Reset to -1 if this element is deleted by a call to remove.
+ */
+ private int lastRet;
+
+ Itr() {
+ lastRet = -1;
+ if (count == 0)
+ nextIndex = -1;
+ else {
+ nextIndex = takeIndex;
+ nextItem = items[takeIndex];
+ }
+ }
+
+ public boolean hasNext() {
+ /*
+ * No sync. We can return true by mistake here
+ * only if this iterator passed across threads,
+ * which we don't support anyway.
+ */
+ return nextIndex >= 0;
+ }
+
+ /**
+ * Checks whether nextIndex is valid; if so setting nextItem.
+ * Stops iterator when either hits putIndex or sees null item.
+ */
+ private void checkNext() {
+ if (nextIndex == putIndex) {
+ nextIndex = -1;
+ nextItem = null;
+ } else {
+ nextItem = items[nextIndex];
+ if (nextItem == null)
+ nextIndex = -1;
+ }
+ }
+
+ public E next() {
+ final ReentrantLock lock = ArrayBlockingQueue.this.lock;
+ lock.lock();
+ try {
+ if (nextIndex < 0)
+ throw new NoSuchElementException();
+ lastRet = nextIndex;
+ E x = nextItem;
+ nextIndex = inc(nextIndex);
+ checkNext();
+ return x;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public void remove() {
+ final ReentrantLock lock = ArrayBlockingQueue.this.lock;
+ lock.lock();
+ try {
+ int i = lastRet;
+ if (i == -1)
+ throw new IllegalStateException();
+ lastRet = -1;
+
+ int ti = takeIndex;
+ removeAt(i);
+ // back up cursor (reset to front if was first element)
+ nextIndex = (i == ti) ? takeIndex : i;
+ checkNext();
+ } finally {
+ lock.unlock();
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/BlockingDeque.java b/libjava/classpath/external/jsr166/java/util/concurrent/BlockingDeque.java
new file mode 100644
index 000000000..d77a96555
--- /dev/null
+++ b/libjava/classpath/external/jsr166/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/libjava/classpath/external/jsr166/java/util/concurrent/BlockingQueue.java b/libjava/classpath/external/jsr166/java/util/concurrent/BlockingQueue.java
new file mode 100644
index 000000000..b47cc9842
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/BlockingQueue.java
@@ -0,0 +1,344 @@
+/*
+ * 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.Collection;
+import java.util.Queue;
+
+/**
+ * A {@link java.util.Queue} that additionally supports operations
+ * that wait for the queue to become non-empty when retrieving an
+ * element, and wait for space to become available in the queue when
+ * storing an element.
+ *
+ * <p><tt>BlockingQueue</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></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 #add add(e)}</td>
+ * <td>{@link #offer offer(e)}</td>
+ * <td>{@link #put put(e)}</td>
+ * <td>{@link #offer(Object, long, TimeUnit) offer(e, time, unit)}</td>
+ * </tr>
+ * <tr>
+ * <td><b>Remove</b></td>
+ * <td>{@link #remove remove()}</td>
+ * <td>{@link #poll poll()}</td>
+ * <td>{@link #take take()}</td>
+ * <td>{@link #poll(long, TimeUnit) poll(time, unit)}</td>
+ * </tr>
+ * <tr>
+ * <td><b>Examine</b></td>
+ * <td>{@link #element element()}</td>
+ * <td>{@link #peek peek()}</td>
+ * <td><em>not applicable</em></td>
+ * <td><em>not applicable</em></td>
+ * </tr>
+ * </table>
+ *
+ * <p>A <tt>BlockingQueue</tt> does not accept <tt>null</tt> elements.
+ * Implementations throw <tt>NullPointerException</tt> on attempts
+ * to <tt>add</tt>, <tt>put</tt> or <tt>offer</tt> a <tt>null</tt>. A
+ * <tt>null</tt> is used as a sentinel value to indicate failure of
+ * <tt>poll</tt> operations.
+ *
+ * <p>A <tt>BlockingQueue</tt> may be capacity bounded. At any given
+ * time it may have a <tt>remainingCapacity</tt> beyond which no
+ * additional elements can be <tt>put</tt> without blocking.
+ * A <tt>BlockingQueue</tt> without any intrinsic capacity constraints always
+ * reports a remaining capacity of <tt>Integer.MAX_VALUE</tt>.
+ *
+ * <p> <tt>BlockingQueue</tt> implementations are designed to be used
+ * primarily for producer-consumer queues, but additionally support
+ * the {@link java.util.Collection} interface. So, for example, it is
+ * possible to remove an arbitrary element from a queue using
+ * <tt>remove(x)</tt>. However, such operations are in general
+ * <em>not</em> performed very efficiently, and are intended for only
+ * occasional use, such as when a queued message is cancelled.
+ *
+ * <p> <tt>BlockingQueue</tt> implementations are thread-safe. All
+ * queuing methods achieve their effects atomically using internal
+ * locks or other forms of concurrency control. However, the
+ * <em>bulk</em> Collection operations <tt>addAll</tt>,
+ * <tt>containsAll</tt>, <tt>retainAll</tt> and <tt>removeAll</tt> are
+ * <em>not</em> necessarily performed atomically unless specified
+ * otherwise in an implementation. So it is possible, for example, for
+ * <tt>addAll(c)</tt> to fail (throwing an exception) after adding
+ * only some of the elements in <tt>c</tt>.
+ *
+ * <p>A <tt>BlockingQueue</tt> does <em>not</em> intrinsically support
+ * any kind of &quot;close&quot; or &quot;shutdown&quot; operation to
+ * indicate that no more items will be added. The needs and usage of
+ * such features tend to be implementation-dependent. For example, a
+ * common tactic is for producers to insert special
+ * <em>end-of-stream</em> or <em>poison</em> objects, that are
+ * interpreted accordingly when taken by consumers.
+ *
+ * <p>
+ * Usage example, based on a typical producer-consumer scenario.
+ * Note that a <tt>BlockingQueue</tt> can safely be used with multiple
+ * producers and multiple consumers.
+ * <pre>
+ * class Producer implements Runnable {
+ * private final BlockingQueue queue;
+ * Producer(BlockingQueue q) { queue = q; }
+ * public void run() {
+ * try {
+ * while (true) { queue.put(produce()); }
+ * } catch (InterruptedException ex) { ... handle ...}
+ * }
+ * Object produce() { ... }
+ * }
+ *
+ * class Consumer implements Runnable {
+ * private final BlockingQueue queue;
+ * Consumer(BlockingQueue q) { queue = q; }
+ * public void run() {
+ * try {
+ * while (true) { consume(queue.take()); }
+ * } catch (InterruptedException ex) { ... handle ...}
+ * }
+ * void consume(Object x) { ... }
+ * }
+ *
+ * class Setup {
+ * void main() {
+ * BlockingQueue q = new SomeQueueImplementation();
+ * Producer p = new Producer(q);
+ * Consumer c1 = new Consumer(q);
+ * Consumer c2 = new Consumer(q);
+ * new Thread(p).start();
+ * new Thread(c1).start();
+ * new Thread(c2).start();
+ * }
+ * }
+ * </pre>
+ *
+ * <p>Memory consistency effects: As with other concurrent
+ * collections, actions in a thread prior to placing an object into a
+ * {@code BlockingQueue}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions subsequent to the access or removal of that element from
+ * the {@code BlockingQueue} 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.5
+ * @author Doug Lea
+ * @param <E> the type of elements held in this collection
+ */
+public interface BlockingQueue<E> extends Queue<E> {
+ /**
+ * Inserts the specified element into this queue 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 queue, it is generally preferable to
+ * use {@link #offer(Object) offer}.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> (as specified by {@link Collection#add})
+ * @throws IllegalStateException if the element cannot be added at this
+ * time due to capacity restrictions
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this queue
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this queue
+ */
+ boolean add(E e);
+
+ /**
+ * Inserts the specified element into this queue 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 queue, this method is
+ * generally preferable to {@link #add}, which can fail to insert an
+ * element only by throwing an exception.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> if the element was added to this queue, else
+ * <tt>false</tt>
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this queue
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this queue
+ */
+ boolean offer(E e);
+
+ /**
+ * Inserts the specified element into this queue, 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 queue
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this queue
+ */
+ void put(E e) throws InterruptedException;
+
+ /**
+ * Inserts the specified element into this queue, 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 queue
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this queue
+ */
+ boolean offer(E e, long timeout, TimeUnit unit)
+ throws InterruptedException;
+
+ /**
+ * Retrieves and removes the head of this queue, waiting if necessary
+ * until an element becomes available.
+ *
+ * @return the head of this queue
+ * @throws InterruptedException if interrupted while waiting
+ */
+ E take() throws InterruptedException;
+
+ /**
+ * Retrieves and removes the head of this queue, 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 queue, 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;
+
+ /**
+ * Returns the number of additional elements that this queue can ideally
+ * (in the absence of memory or resource constraints) accept without
+ * blocking, or <tt>Integer.MAX_VALUE</tt> if there is no intrinsic
+ * limit.
+ *
+ * <p>Note that you <em>cannot</em> always tell if an attempt to insert
+ * an element will succeed by inspecting <tt>remainingCapacity</tt>
+ * because it may be the case that another thread is about to
+ * insert or remove an element.
+ *
+ * @return the remaining capacity
+ */
+ int remainingCapacity();
+
+ /**
+ * 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
+ * elements.
+ * Returns <tt>true</tt> 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
+ * @throws ClassCastException if the class of the specified element
+ * is incompatible with this queue (optional)
+ * @throws NullPointerException if the specified element is null (optional)
+ */
+ boolean remove(Object o);
+
+ /**
+ * Returns <tt>true</tt> if this queue contains the specified element.
+ * More formally, returns <tt>true</tt> if and only if this queue 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 queue
+ * @return <tt>true</tt> if this queue contains the specified element
+ * @throws ClassCastException if the class of the specified element
+ * is incompatible with this queue (optional)
+ * @throws NullPointerException if the specified element is null (optional)
+ */
+ public boolean contains(Object o);
+
+ /**
+ * Removes all available elements from this queue and adds them
+ * to the given collection. This operation may be more
+ * efficient than repeatedly polling this queue. A failure
+ * encountered while attempting to add elements to
+ * collection <tt>c</tt> may result in elements being in neither,
+ * either or both collections when the associated exception is
+ * thrown. Attempts to drain a queue to itself result in
+ * <tt>IllegalArgumentException</tt>. Further, the behavior of
+ * this operation is undefined if the specified collection is
+ * modified while the operation is in progress.
+ *
+ * @param c the collection to transfer elements into
+ * @return the number of elements transferred
+ * @throws UnsupportedOperationException if addition of elements
+ * is not supported by the specified collection
+ * @throws ClassCastException if the class of an element of this queue
+ * prevents it from being added to the specified collection
+ * @throws NullPointerException if the specified collection is null
+ * @throws IllegalArgumentException if the specified collection is this
+ * queue, or some property of an element of this queue prevents
+ * it from being added to the specified collection
+ */
+ int drainTo(Collection<? super E> c);
+
+ /**
+ * Removes at most the given number of available elements from
+ * this queue and adds them to the given collection. A failure
+ * encountered while attempting to add elements to
+ * collection <tt>c</tt> may result in elements being in neither,
+ * either or both collections when the associated exception is
+ * thrown. Attempts to drain a queue to itself result in
+ * <tt>IllegalArgumentException</tt>. Further, the behavior of
+ * this operation is undefined if the specified collection is
+ * modified while the operation is in progress.
+ *
+ * @param c the collection to transfer elements into
+ * @param maxElements the maximum number of elements to transfer
+ * @return the number of elements transferred
+ * @throws UnsupportedOperationException if addition of elements
+ * is not supported by the specified collection
+ * @throws ClassCastException if the class of an element of this queue
+ * prevents it from being added to the specified collection
+ * @throws NullPointerException if the specified collection is null
+ * @throws IllegalArgumentException if the specified collection is this
+ * queue, or some property of an element of this queue prevents
+ * it from being added to the specified collection
+ */
+ int drainTo(Collection<? super E> c, int maxElements);
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/BrokenBarrierException.java b/libjava/classpath/external/jsr166/java/util/concurrent/BrokenBarrierException.java
new file mode 100644
index 000000000..3f93fbb9d
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/BrokenBarrierException.java
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+/**
+ * Exception thrown when a thread tries to wait upon a barrier that is
+ * in a broken state, or which enters the broken state while the thread
+ * is waiting.
+ *
+ * @see CyclicBarrier
+ *
+ * @since 1.5
+ * @author Doug Lea
+ *
+ */
+public class BrokenBarrierException extends Exception {
+ private static final long serialVersionUID = 7117394618823254244L;
+
+ /**
+ * Constructs a <tt>BrokenBarrierException</tt> with no specified detail
+ * message.
+ */
+ public BrokenBarrierException() {}
+
+ /**
+ * Constructs a <tt>BrokenBarrierException</tt> with the specified
+ * detail message.
+ *
+ * @param message the detail message
+ */
+ public BrokenBarrierException(String message) {
+ super(message);
+ }
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/Callable.java b/libjava/classpath/external/jsr166/java/util/concurrent/Callable.java
new file mode 100644
index 000000000..abc4d0407
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/Callable.java
@@ -0,0 +1,36 @@
+/*
+ * 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 task that returns a result and may throw an exception.
+ * Implementors define a single method with no arguments called
+ * <tt>call</tt>.
+ *
+ * <p>The <tt>Callable</tt> interface is similar to {@link
+ * java.lang.Runnable}, in that both are designed for classes whose
+ * instances are potentially executed by another thread. A
+ * <tt>Runnable</tt>, however, does not return a result and cannot
+ * throw a checked exception.
+ *
+ * <p> The {@link Executors} class contains utility methods to
+ * convert from other common forms to <tt>Callable</tt> classes.
+ *
+ * @see Executor
+ * @since 1.5
+ * @author Doug Lea
+ * @param <V> the result type of method <tt>call</tt>
+ */
+public interface Callable<V> {
+ /**
+ * Computes a result, or throws an exception if unable to do so.
+ *
+ * @return computed result
+ * @throws Exception if unable to compute a result
+ */
+ V call() throws Exception;
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/CancellationException.java b/libjava/classpath/external/jsr166/java/util/concurrent/CancellationException.java
new file mode 100644
index 000000000..2c29544a0
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/CancellationException.java
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+/**
+ * Exception indicating that the result of a value-producing task,
+ * such as a {@link FutureTask}, cannot be retrieved because the task
+ * was cancelled.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class CancellationException extends IllegalStateException {
+ private static final long serialVersionUID = -9202173006928992231L;
+
+ /**
+ * Constructs a <tt>CancellationException</tt> with no detail message.
+ */
+ public CancellationException() {}
+
+ /**
+ * Constructs a <tt>CancellationException</tt> with the specified detail
+ * message.
+ *
+ * @param message the detail message
+ */
+ public CancellationException(String message) {
+ super(message);
+ }
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/CompletionService.java b/libjava/classpath/external/jsr166/java/util/concurrent/CompletionService.java
new file mode 100644
index 000000000..df9f719c4
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/CompletionService.java
@@ -0,0 +1,97 @@
+/*
+ * 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 service that decouples the production of new asynchronous tasks
+ * from the consumption of the results of completed tasks. Producers
+ * <tt>submit</tt> tasks for execution. Consumers <tt>take</tt>
+ * completed tasks and process their results in the order they
+ * complete. A <tt>CompletionService</tt> can for example be used to
+ * manage asynchronous IO, in which tasks that perform reads are
+ * submitted in one part of a program or system, and then acted upon
+ * in a different part of the program when the reads complete,
+ * possibly in a different order than they were requested.
+ *
+ * <p>Typically, a <tt>CompletionService</tt> relies on a separate
+ * {@link Executor} to actually execute the tasks, in which case the
+ * <tt>CompletionService</tt> only manages an internal completion
+ * queue. The {@link ExecutorCompletionService} class provides an
+ * implementation of this approach.
+ *
+ * <p>Memory consistency effects: Actions in a thread prior to
+ * submitting a task to a {@code CompletionService}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions taken by that task, which in turn <i>happen-before</i>
+ * actions following a successful return from the corresponding {@code take()}.
+ *
+ */
+public interface CompletionService<V> {
+ /**
+ * Submits a value-returning task for execution and returns a Future
+ * representing the pending results of the task. Upon completion,
+ * this task may be taken or polled.
+ *
+ * @param task the task to submit
+ * @return a Future representing pending completion of the task
+ * @throws RejectedExecutionException if the task cannot be
+ * scheduled for execution
+ * @throws NullPointerException if the task is null
+ */
+ Future<V> submit(Callable<V> task);
+
+ /**
+ * Submits a Runnable task for execution and returns a Future
+ * representing that task. Upon completion, this task may be
+ * taken or polled.
+ *
+ * @param task the task to submit
+ * @param result the result to return upon successful completion
+ * @return a Future representing pending completion of the task,
+ * and whose <tt>get()</tt> method will return the given
+ * result value upon completion
+ * @throws RejectedExecutionException if the task cannot be
+ * scheduled for execution
+ * @throws NullPointerException if the task is null
+ */
+ Future<V> submit(Runnable task, V result);
+
+ /**
+ * Retrieves and removes the Future representing the next
+ * completed task, waiting if none are yet present.
+ *
+ * @return the Future representing the next completed task
+ * @throws InterruptedException if interrupted while waiting
+ */
+ Future<V> take() throws InterruptedException;
+
+
+ /**
+ * Retrieves and removes the Future representing the next
+ * completed task or <tt>null</tt> if none are present.
+ *
+ * @return the Future representing the next completed task, or
+ * <tt>null</tt> if none are present
+ */
+ Future<V> poll();
+
+ /**
+ * Retrieves and removes the Future representing the next
+ * completed task, waiting if necessary up to the specified wait
+ * time if none are yet present.
+ *
+ * @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 Future representing the next completed task or
+ * <tt>null</tt> if the specified waiting time elapses
+ * before one is present
+ * @throws InterruptedException if interrupted while waiting
+ */
+ Future<V> poll(long timeout, TimeUnit unit) throws InterruptedException;
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/ConcurrentHashMap.java b/libjava/classpath/external/jsr166/java/util/concurrent/ConcurrentHashMap.java
new file mode 100644
index 000000000..9ad9ab25b
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/ConcurrentHashMap.java
@@ -0,0 +1,1277 @@
+/*
+ * 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.concurrent.locks.*;
+import java.util.*;
+import java.io.Serializable;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+/**
+ * A hash table supporting full concurrency of retrievals and
+ * adjustable expected concurrency for updates. This class obeys the
+ * same functional specification as {@link java.util.Hashtable}, and
+ * includes versions of methods corresponding to each method of
+ * <tt>Hashtable</tt>. However, even though all operations are
+ * thread-safe, retrieval operations do <em>not</em> entail locking,
+ * and there is <em>not</em> any support for locking the entire table
+ * in a way that prevents all access. This class is fully
+ * interoperable with <tt>Hashtable</tt> in programs that rely on its
+ * thread safety but not on its synchronization details.
+ *
+ * <p> Retrieval operations (including <tt>get</tt>) generally do not
+ * block, so may overlap with update operations (including
+ * <tt>put</tt> and <tt>remove</tt>). Retrievals reflect the results
+ * of the most recently <em>completed</em> update operations holding
+ * upon their onset. For aggregate operations such as <tt>putAll</tt>
+ * and <tt>clear</tt>, concurrent retrievals may reflect insertion or
+ * removal of only some entries. Similarly, Iterators and
+ * Enumerations return elements reflecting the state of the hash table
+ * at some point at or since the creation of the iterator/enumeration.
+ * They do <em>not</em> throw {@link ConcurrentModificationException}.
+ * However, iterators are designed to be used by only one thread at a time.
+ *
+ * <p> The allowed concurrency among update operations is guided by
+ * the optional <tt>concurrencyLevel</tt> constructor argument
+ * (default <tt>16</tt>), which is used as a hint for internal sizing. The
+ * table is internally partitioned to try to permit the indicated
+ * number of concurrent updates without contention. Because placement
+ * in hash tables is essentially random, the actual concurrency will
+ * vary. Ideally, you should choose a value to accommodate as many
+ * threads as will ever concurrently modify the table. Using a
+ * significantly higher value than you need can waste space and time,
+ * and a significantly lower value can lead to thread contention. But
+ * overestimates and underestimates within an order of magnitude do
+ * not usually have much noticeable impact. A value of one is
+ * appropriate when it is known that only one thread will modify and
+ * all others will only read. Also, resizing this or any other kind of
+ * hash table is a relatively slow operation, so, when possible, it is
+ * a good idea to provide estimates of expected table sizes in
+ * constructors.
+ *
+ * <p>This class and its views and iterators implement all of the
+ * <em>optional</em> methods of the {@link Map} and {@link Iterator}
+ * interfaces.
+ *
+ * <p> Like {@link Hashtable} but unlike {@link HashMap}, this class
+ * does <em>not</em> allow <tt>null</tt> to be used as a key or value.
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <K> the type of keys maintained by this map
+ * @param <V> the type of mapped values
+ */
+public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
+ implements ConcurrentMap<K, V>, Serializable {
+ private static final long serialVersionUID = 7249069246763182397L;
+
+ /*
+ * The basic strategy is to subdivide the table among Segments,
+ * each of which itself is a concurrently readable hash table.
+ */
+
+ /* ---------------- Constants -------------- */
+
+ /**
+ * The default initial capacity for this table,
+ * used when not otherwise specified in a constructor.
+ */
+ static final int DEFAULT_INITIAL_CAPACITY = 16;
+
+ /**
+ * The default load factor for this table, used when not
+ * otherwise specified in a constructor.
+ */
+ static final float DEFAULT_LOAD_FACTOR = 0.75f;
+
+ /**
+ * The default concurrency level for this table, used when not
+ * otherwise specified in a constructor.
+ */
+ static final int DEFAULT_CONCURRENCY_LEVEL = 16;
+
+ /**
+ * The maximum capacity, used if a higher value is implicitly
+ * specified by either of the constructors with arguments. MUST
+ * be a power of two <= 1<<30 to ensure that entries are indexable
+ * using ints.
+ */
+ static final int MAXIMUM_CAPACITY = 1 << 30;
+
+ /**
+ * The maximum number of segments to allow; used to bound
+ * constructor arguments.
+ */
+ static final int MAX_SEGMENTS = 1 << 16; // slightly conservative
+
+ /**
+ * Number of unsynchronized retries in size and containsValue
+ * methods before resorting to locking. This is used to avoid
+ * unbounded retries if tables undergo continuous modification
+ * which would make it impossible to obtain an accurate result.
+ */
+ static final int RETRIES_BEFORE_LOCK = 2;
+
+ /* ---------------- Fields -------------- */
+
+ /**
+ * Mask value for indexing into segments. The upper bits of a
+ * key's hash code are used to choose the segment.
+ */
+ final int segmentMask;
+
+ /**
+ * Shift value for indexing within segments.
+ */
+ final int segmentShift;
+
+ /**
+ * The segments, each of which is a specialized hash table
+ */
+ final Segment<K,V>[] segments;
+
+ transient Set<K> keySet;
+ transient Set<Map.Entry<K,V>> entrySet;
+ transient Collection<V> values;
+
+ /* ---------------- Small Utilities -------------- */
+
+ /**
+ * Applies a supplemental hash function to a given hashCode, which
+ * defends against poor quality hash functions. This is critical
+ * because ConcurrentHashMap uses power-of-two length hash tables,
+ * that otherwise encounter collisions for hashCodes that do not
+ * differ in lower bits.
+ */
+ private static int hash(int h) {
+ // This function ensures that hashCodes that differ only by
+ // constant multiples at each bit position have a bounded
+ // number of collisions (approximately 8 at default load factor).
+ h ^= (h >>> 20) ^ (h >>> 12);
+ return h ^ (h >>> 7) ^ (h >>> 4);
+ }
+
+ /**
+ * Returns the segment that should be used for key with given hash
+ * @param hash the hash code for the key
+ * @return the segment
+ */
+ final Segment<K,V> segmentFor(int hash) {
+ return segments[(hash >>> segmentShift) & segmentMask];
+ }
+
+ /* ---------------- Inner Classes -------------- */
+
+ /**
+ * ConcurrentHashMap list entry. Note that this is never exported
+ * out as a user-visible Map.Entry.
+ *
+ * Because the value field is volatile, not final, it is legal wrt
+ * the Java Memory Model for an unsynchronized reader to see null
+ * instead of initial value when read via a data race. Although a
+ * reordering leading to this is not likely to ever actually
+ * occur, the Segment.readValueUnderLock method is used as a
+ * backup in case a null (pre-initialized) value is ever seen in
+ * an unsynchronized access method.
+ */
+ static final class HashEntry<K,V> {
+ final K key;
+ final int hash;
+ volatile V value;
+ final HashEntry<K,V> next;
+
+ HashEntry(K key, int hash, HashEntry<K,V> next, V value) {
+ this.key = key;
+ this.hash = hash;
+ this.next = next;
+ this.value = value;
+ }
+
+ @SuppressWarnings("unchecked")
+ static final <K,V> HashEntry<K,V>[] newArray(int i) {
+ return new HashEntry[i];
+ }
+ }
+
+ /**
+ * Segments are specialized versions of hash tables. This
+ * subclasses from ReentrantLock opportunistically, just to
+ * simplify some locking and avoid separate construction.
+ */
+ static final class Segment<K,V> extends ReentrantLock implements Serializable {
+ /*
+ * Segments maintain a table of entry lists that are ALWAYS
+ * kept in a consistent state, so can be read without locking.
+ * Next fields of nodes are immutable (final). All list
+ * additions are performed at the front of each bin. This
+ * makes it easy to check changes, and also fast to traverse.
+ * When nodes would otherwise be changed, new nodes are
+ * created to replace them. This works well for hash tables
+ * since the bin lists tend to be short. (The average length
+ * is less than two for the default load factor threshold.)
+ *
+ * Read operations can thus proceed without locking, but rely
+ * on selected uses of volatiles to ensure that completed
+ * write operations performed by other threads are
+ * noticed. For most purposes, the "count" field, tracking the
+ * number of elements, serves as that volatile variable
+ * ensuring visibility. This is convenient because this field
+ * needs to be read in many read operations anyway:
+ *
+ * - All (unsynchronized) read operations must first read the
+ * "count" field, and should not look at table entries if
+ * it is 0.
+ *
+ * - All (synchronized) write operations should write to
+ * the "count" field after structurally changing any bin.
+ * The operations must not take any action that could even
+ * momentarily cause a concurrent read operation to see
+ * inconsistent data. This is made easier by the nature of
+ * the read operations in Map. For example, no operation
+ * can reveal that the table has grown but the threshold
+ * has not yet been updated, so there are no atomicity
+ * requirements for this with respect to reads.
+ *
+ * As a guide, all critical volatile reads and writes to the
+ * count field are marked in code comments.
+ */
+
+ private static final long serialVersionUID = 2249069246763182397L;
+
+ /**
+ * The number of elements in this segment's region.
+ */
+ transient volatile int count;
+
+ /**
+ * Number of updates that alter the size of the table. This is
+ * used during bulk-read methods to make sure they see a
+ * consistent snapshot: If modCounts change during a traversal
+ * of segments computing size or checking containsValue, then
+ * we might have an inconsistent view of state so (usually)
+ * must retry.
+ */
+ transient int modCount;
+
+ /**
+ * The table is rehashed when its size exceeds this threshold.
+ * (The value of this field is always <tt>(int)(capacity *
+ * loadFactor)</tt>.)
+ */
+ transient int threshold;
+
+ /**
+ * The per-segment table.
+ */
+ transient volatile HashEntry<K,V>[] table;
+
+ /**
+ * The load factor for the hash table. Even though this value
+ * is same for all segments, it is replicated to avoid needing
+ * links to outer object.
+ * @serial
+ */
+ final float loadFactor;
+
+ Segment(int initialCapacity, float lf) {
+ loadFactor = lf;
+ setTable(HashEntry.<K,V>newArray(initialCapacity));
+ }
+
+ @SuppressWarnings("unchecked")
+ static final <K,V> Segment<K,V>[] newArray(int i) {
+ return new Segment[i];
+ }
+
+ /**
+ * Sets table to new HashEntry array.
+ * Call only while holding lock or in constructor.
+ */
+ void setTable(HashEntry<K,V>[] newTable) {
+ threshold = (int)(newTable.length * loadFactor);
+ table = newTable;
+ }
+
+ /**
+ * Returns properly casted first entry of bin for given hash.
+ */
+ HashEntry<K,V> getFirst(int hash) {
+ HashEntry<K,V>[] tab = table;
+ return tab[hash & (tab.length - 1)];
+ }
+
+ /**
+ * Reads value field of an entry under lock. Called if value
+ * field ever appears to be null. This is possible only if a
+ * compiler happens to reorder a HashEntry initialization with
+ * its table assignment, which is legal under memory model
+ * but is not known to ever occur.
+ */
+ V readValueUnderLock(HashEntry<K,V> e) {
+ lock();
+ try {
+ return e.value;
+ } finally {
+ unlock();
+ }
+ }
+
+ /* Specialized implementations of map methods */
+
+ V get(Object key, int hash) {
+ if (count != 0) { // read-volatile
+ HashEntry<K,V> e = getFirst(hash);
+ while (e != null) {
+ if (e.hash == hash && key.equals(e.key)) {
+ V v = e.value;
+ if (v != null)
+ return v;
+ return readValueUnderLock(e); // recheck
+ }
+ e = e.next;
+ }
+ }
+ return null;
+ }
+
+ boolean containsKey(Object key, int hash) {
+ if (count != 0) { // read-volatile
+ HashEntry<K,V> e = getFirst(hash);
+ while (e != null) {
+ if (e.hash == hash && key.equals(e.key))
+ return true;
+ e = e.next;
+ }
+ }
+ return false;
+ }
+
+ boolean containsValue(Object value) {
+ if (count != 0) { // read-volatile
+ HashEntry<K,V>[] tab = table;
+ int len = tab.length;
+ for (int i = 0 ; i < len; i++) {
+ for (HashEntry<K,V> e = tab[i]; e != null; e = e.next) {
+ V v = e.value;
+ if (v == null) // recheck
+ v = readValueUnderLock(e);
+ if (value.equals(v))
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ boolean replace(K key, int hash, V oldValue, V newValue) {
+ lock();
+ try {
+ HashEntry<K,V> e = getFirst(hash);
+ while (e != null && (e.hash != hash || !key.equals(e.key)))
+ e = e.next;
+
+ boolean replaced = false;
+ if (e != null && oldValue.equals(e.value)) {
+ replaced = true;
+ e.value = newValue;
+ }
+ return replaced;
+ } finally {
+ unlock();
+ }
+ }
+
+ V replace(K key, int hash, V newValue) {
+ lock();
+ try {
+ HashEntry<K,V> e = getFirst(hash);
+ while (e != null && (e.hash != hash || !key.equals(e.key)))
+ e = e.next;
+
+ V oldValue = null;
+ if (e != null) {
+ oldValue = e.value;
+ e.value = newValue;
+ }
+ return oldValue;
+ } finally {
+ unlock();
+ }
+ }
+
+
+ V put(K key, int hash, V value, boolean onlyIfAbsent) {
+ lock();
+ try {
+ int c = count;
+ if (c++ > threshold) // ensure capacity
+ rehash();
+ HashEntry<K,V>[] tab = table;
+ int index = hash & (tab.length - 1);
+ HashEntry<K,V> first = tab[index];
+ HashEntry<K,V> e = first;
+ while (e != null && (e.hash != hash || !key.equals(e.key)))
+ e = e.next;
+
+ V oldValue;
+ if (e != null) {
+ oldValue = e.value;
+ if (!onlyIfAbsent)
+ e.value = value;
+ }
+ else {
+ oldValue = null;
+ ++modCount;
+ tab[index] = new HashEntry<K,V>(key, hash, first, value);
+ count = c; // write-volatile
+ }
+ return oldValue;
+ } finally {
+ unlock();
+ }
+ }
+
+ void rehash() {
+ HashEntry<K,V>[] oldTable = table;
+ int oldCapacity = oldTable.length;
+ if (oldCapacity >= MAXIMUM_CAPACITY)
+ return;
+
+ /*
+ * Reclassify nodes in each list to new Map. Because we are
+ * using power-of-two expansion, the elements from each bin
+ * must either stay at same index, or move with a power of two
+ * offset. We eliminate unnecessary node creation by catching
+ * cases where old nodes can be reused because their next
+ * fields won't change. Statistically, at the default
+ * threshold, only about one-sixth of them need cloning when
+ * a table doubles. The nodes they replace will be garbage
+ * collectable as soon as they are no longer referenced by any
+ * reader thread that may be in the midst of traversing table
+ * right now.
+ */
+
+ HashEntry<K,V>[] newTable = HashEntry.newArray(oldCapacity<<1);
+ threshold = (int)(newTable.length * loadFactor);
+ int sizeMask = newTable.length - 1;
+ for (int i = 0; i < oldCapacity ; i++) {
+ // We need to guarantee that any existing reads of old Map can
+ // proceed. So we cannot yet null out each bin.
+ HashEntry<K,V> e = oldTable[i];
+
+ if (e != null) {
+ HashEntry<K,V> next = e.next;
+ int idx = e.hash & sizeMask;
+
+ // Single node on list
+ if (next == null)
+ newTable[idx] = e;
+
+ else {
+ // Reuse trailing consecutive sequence at same slot
+ HashEntry<K,V> lastRun = e;
+ int lastIdx = idx;
+ for (HashEntry<K,V> last = next;
+ last != null;
+ last = last.next) {
+ int k = last.hash & sizeMask;
+ if (k != lastIdx) {
+ lastIdx = k;
+ lastRun = last;
+ }
+ }
+ newTable[lastIdx] = lastRun;
+
+ // Clone all remaining nodes
+ for (HashEntry<K,V> p = e; p != lastRun; p = p.next) {
+ int k = p.hash & sizeMask;
+ HashEntry<K,V> n = newTable[k];
+ newTable[k] = new HashEntry<K,V>(p.key, p.hash,
+ n, p.value);
+ }
+ }
+ }
+ }
+ table = newTable;
+ }
+
+ /**
+ * Remove; match on key only if value null, else match both.
+ */
+ V remove(Object key, int hash, Object value) {
+ lock();
+ try {
+ int c = count - 1;
+ HashEntry<K,V>[] tab = table;
+ int index = hash & (tab.length - 1);
+ HashEntry<K,V> first = tab[index];
+ HashEntry<K,V> e = first;
+ while (e != null && (e.hash != hash || !key.equals(e.key)))
+ e = e.next;
+
+ V oldValue = null;
+ if (e != null) {
+ V v = e.value;
+ if (value == null || value.equals(v)) {
+ oldValue = v;
+ // All entries following removed node can stay
+ // in list, but all preceding ones need to be
+ // cloned.
+ ++modCount;
+ HashEntry<K,V> newFirst = e.next;
+ for (HashEntry<K,V> p = first; p != e; p = p.next)
+ newFirst = new HashEntry<K,V>(p.key, p.hash,
+ newFirst, p.value);
+ tab[index] = newFirst;
+ count = c; // write-volatile
+ }
+ }
+ return oldValue;
+ } finally {
+ unlock();
+ }
+ }
+
+ void clear() {
+ if (count != 0) {
+ lock();
+ try {
+ HashEntry<K,V>[] tab = table;
+ for (int i = 0; i < tab.length ; i++)
+ tab[i] = null;
+ ++modCount;
+ count = 0; // write-volatile
+ } finally {
+ unlock();
+ }
+ }
+ }
+ }
+
+
+
+ /* ---------------- Public operations -------------- */
+
+ /**
+ * Creates a new, empty map with the specified initial
+ * capacity, load factor and concurrency level.
+ *
+ * @param initialCapacity the initial capacity. 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.
+ * @param concurrencyLevel the estimated number of concurrently
+ * updating threads. The implementation performs internal sizing
+ * to try to accommodate this many threads.
+ * @throws IllegalArgumentException if the initial capacity is
+ * negative or the load factor or concurrencyLevel are
+ * nonpositive.
+ */
+ public ConcurrentHashMap(int initialCapacity,
+ float loadFactor, int concurrencyLevel) {
+ if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0)
+ throw new IllegalArgumentException();
+
+ if (concurrencyLevel > MAX_SEGMENTS)
+ concurrencyLevel = MAX_SEGMENTS;
+
+ // Find power-of-two sizes best matching arguments
+ int sshift = 0;
+ int ssize = 1;
+ while (ssize < concurrencyLevel) {
+ ++sshift;
+ ssize <<= 1;
+ }
+ segmentShift = 32 - sshift;
+ segmentMask = ssize - 1;
+ this.segments = Segment.newArray(ssize);
+
+ if (initialCapacity > MAXIMUM_CAPACITY)
+ initialCapacity = MAXIMUM_CAPACITY;
+ int c = initialCapacity / ssize;
+ if (c * ssize < initialCapacity)
+ ++c;
+ int cap = 1;
+ while (cap < c)
+ cap <<= 1;
+
+ for (int i = 0; i < this.segments.length; ++i)
+ this.segments[i] = new Segment<K,V>(cap, loadFactor);
+ }
+
+ /**
+ * 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).
+ *
+ * @param initialCapacity the initial capacity. The implementation
+ * performs internal sizing to accommodate this many elements.
+ * @throws IllegalArgumentException if the initial capacity of
+ * elements is negative.
+ */
+ public ConcurrentHashMap(int initialCapacity) {
+ this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
+ }
+
+ /**
+ * Creates a new, empty map with a default initial capacity (16),
+ * load factor (0.75) and concurrencyLevel (16).
+ */
+ public ConcurrentHashMap() {
+ this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
+ }
+
+ /**
+ * Creates a new map with the same mappings as the given map.
+ * The map is created with a capacity of 1.5 times the number
+ * of mappings in the given map or 16 (whichever is greater),
+ * and a default load factor (0.75) and concurrencyLevel (16).
+ *
+ * @param m the map
+ */
+ public ConcurrentHashMap(Map<? extends K, ? extends V> m) {
+ this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
+ DEFAULT_INITIAL_CAPACITY),
+ DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
+ putAll(m);
+ }
+
+ /**
+ * 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() {
+ final Segment<K,V>[] segments = this.segments;
+ /*
+ * We keep track of per-segment modCounts to avoid ABA
+ * problems in which an element in one segment was added and
+ * in another removed during traversal, in which case the
+ * table was never actually empty at any point. Note the
+ * similar use of modCounts in the size() and containsValue()
+ * methods, which are the only other methods also susceptible
+ * to ABA problems.
+ */
+ int[] mc = new int[segments.length];
+ int mcsum = 0;
+ for (int i = 0; i < segments.length; ++i) {
+ if (segments[i].count != 0)
+ return false;
+ else
+ mcsum += mc[i] = segments[i].modCount;
+ }
+ // If mcsum happens to be zero, then we know we got a snapshot
+ // before any modifications at all were made. This is
+ // probably common enough to bother tracking.
+ if (mcsum != 0) {
+ for (int i = 0; i < segments.length; ++i) {
+ if (segments[i].count != 0 ||
+ mc[i] != segments[i].modCount)
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns the number of key-value mappings in this map. If the
+ * map contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
+ * <tt>Integer.MAX_VALUE</tt>.
+ *
+ * @return the number of key-value mappings in this map
+ */
+ public int size() {
+ final Segment<K,V>[] segments = this.segments;
+ long sum = 0;
+ long check = 0;
+ int[] mc = new int[segments.length];
+ // Try a few times to get accurate count. On failure due to
+ // continuous async changes in table, resort to locking.
+ for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) {
+ check = 0;
+ sum = 0;
+ int mcsum = 0;
+ for (int i = 0; i < segments.length; ++i) {
+ sum += segments[i].count;
+ mcsum += mc[i] = segments[i].modCount;
+ }
+ if (mcsum != 0) {
+ for (int i = 0; i < segments.length; ++i) {
+ check += segments[i].count;
+ if (mc[i] != segments[i].modCount) {
+ check = -1; // force retry
+ break;
+ }
+ }
+ }
+ if (check == sum)
+ break;
+ }
+ if (check != sum) { // Resort to locking all segments
+ sum = 0;
+ for (int i = 0; i < segments.length; ++i)
+ segments[i].lock();
+ for (int i = 0; i < segments.length; ++i)
+ sum += segments[i].count;
+ for (int i = 0; i < segments.length; ++i)
+ segments[i].unlock();
+ }
+ if (sum > Integer.MAX_VALUE)
+ return Integer.MAX_VALUE;
+ else
+ return (int)sum;
+ }
+
+ /**
+ * 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.equals(k)},
+ * then this method returns {@code v}; otherwise it returns
+ * {@code null}. (There can be at most one such mapping.)
+ *
+ * @throws NullPointerException if the specified key is null
+ */
+ public V get(Object key) {
+ int hash = hash(key.hashCode());
+ return segmentFor(hash).get(key, hash);
+ }
+
+ /**
+ * Tests if the specified object is a key in this table.
+ *
+ * @param key possible key
+ * @return <tt>true</tt> if and only if the specified object
+ * is a key in this table, as determined by the
+ * <tt>equals</tt> method; <tt>false</tt> otherwise.
+ * @throws NullPointerException if the specified key is null
+ */
+ public boolean containsKey(Object key) {
+ int hash = hash(key.hashCode());
+ return segmentFor(hash).containsKey(key, hash);
+ }
+
+ /**
+ * Returns <tt>true</tt> if this map maps one or more keys to the
+ * specified value. Note: This method requires a full internal
+ * traversal of the hash table, and so is much slower than
+ * method <tt>containsKey</tt>.
+ *
+ * @param value value whose presence in this map is to be tested
+ * @return <tt>true</tt> if this map maps one or more keys to the
+ * specified value
+ * @throws NullPointerException if the specified value is null
+ */
+ public boolean containsValue(Object value) {
+ if (value == null)
+ throw new NullPointerException();
+
+ // See explanation of modCount use above
+
+ final Segment<K,V>[] segments = this.segments;
+ int[] mc = new int[segments.length];
+
+ // Try a few times without locking
+ for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) {
+ int sum = 0;
+ int mcsum = 0;
+ for (int i = 0; i < segments.length; ++i) {
+ int c = segments[i].count;
+ mcsum += mc[i] = segments[i].modCount;
+ if (segments[i].containsValue(value))
+ return true;
+ }
+ boolean cleanSweep = true;
+ if (mcsum != 0) {
+ for (int i = 0; i < segments.length; ++i) {
+ int c = segments[i].count;
+ if (mc[i] != segments[i].modCount) {
+ cleanSweep = false;
+ break;
+ }
+ }
+ }
+ if (cleanSweep)
+ return false;
+ }
+ // Resort to locking all segments
+ for (int i = 0; i < segments.length; ++i)
+ segments[i].lock();
+ boolean found = false;
+ try {
+ for (int i = 0; i < segments.length; ++i) {
+ if (segments[i].containsValue(value)) {
+ found = true;
+ break;
+ }
+ }
+ } finally {
+ for (int i = 0; i < segments.length; ++i)
+ segments[i].unlock();
+ }
+ return found;
+ }
+
+ /**
+ * Legacy method testing if some key maps into the specified value
+ * in this table. This method is identical in functionality to
+ * {@link #containsValue}, and exists solely to ensure
+ * full compatibility with class {@link java.util.Hashtable},
+ * which supported this method prior to introduction of the
+ * Java Collections framework.
+
+ * @param value a value to search for
+ * @return <tt>true</tt> if and only if some key maps to the
+ * <tt>value</tt> argument in this table as
+ * determined by the <tt>equals</tt> method;
+ * <tt>false</tt> otherwise
+ * @throws NullPointerException if the specified value is null
+ */
+ public boolean contains(Object value) {
+ return containsValue(value);
+ }
+
+ /**
+ * Maps the specified key to the specified value in this table.
+ * Neither the key nor the value can be null.
+ *
+ * <p> The value can be retrieved by calling the <tt>get</tt> method
+ * with a key that is equal to the original key.
+ *
+ * @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 <tt>key</tt>, or
+ * <tt>null</tt> if there was no mapping for <tt>key</tt>
+ * @throws NullPointerException if the specified key or value is null
+ */
+ public V put(K key, V value) {
+ if (value == null)
+ throw new NullPointerException();
+ int hash = hash(key.hashCode());
+ return segmentFor(hash).put(key, hash, value, false);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return the previous value associated with the specified key,
+ * or <tt>null</tt> if there was no mapping for the key
+ * @throws NullPointerException if the specified key or value is null
+ */
+ public V putIfAbsent(K key, V value) {
+ if (value == null)
+ throw new NullPointerException();
+ int hash = hash(key.hashCode());
+ return segmentFor(hash).put(key, hash, value, true);
+ }
+
+ /**
+ * Copies all of the mappings from the specified map to this one.
+ * These mappings replace any mappings that this map had for any of the
+ * keys currently in the specified map.
+ *
+ * @param m mappings to be stored in this map
+ */
+ public void putAll(Map<? extends K, ? extends V> m) {
+ for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
+ put(e.getKey(), e.getValue());
+ }
+
+ /**
+ * Removes the key (and its corresponding value) from this map.
+ * This method does nothing if the key is not in the map.
+ *
+ * @param key the key that needs to be removed
+ * @return the previous value associated with <tt>key</tt>, or
+ * <tt>null</tt> if there was no mapping for <tt>key</tt>
+ * @throws NullPointerException if the specified key is null
+ */
+ public V remove(Object key) {
+ int hash = hash(key.hashCode());
+ return segmentFor(hash).remove(key, hash, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws NullPointerException if the specified key is null
+ */
+ public boolean remove(Object key, Object value) {
+ int hash = hash(key.hashCode());
+ if (value == null)
+ return false;
+ return segmentFor(hash).remove(key, hash, value) != null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @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();
+ int hash = hash(key.hashCode());
+ return segmentFor(hash).replace(key, hash, oldValue, newValue);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return the previous value associated with the specified key,
+ * or <tt>null</tt> if there was no mapping for the key
+ * @throws NullPointerException if the specified key or value is null
+ */
+ public V replace(K key, V value) {
+ if (value == null)
+ throw new NullPointerException();
+ int hash = hash(key.hashCode());
+ return segmentFor(hash).replace(key, hash, value);
+ }
+
+ /**
+ * Removes all of the mappings from this map.
+ */
+ public void clear() {
+ for (int i = 0; i < segments.length; ++i)
+ segments[i].clear();
+ }
+
+ /**
+ * Returns a {@link Set} view of the keys contained in this map.
+ * 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 this 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.
+ */
+ public Set<K> keySet() {
+ Set<K> ks = keySet;
+ return (ks != null) ? ks : (keySet = new KeySet());
+ }
+
+ /**
+ * Returns a {@link Collection} view of the values contained in this map.
+ * 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 this 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() {
+ Collection<V> vs = values;
+ return (vs != null) ? vs : (values = new Values());
+ }
+
+ /**
+ * Returns a {@link Set} view of the mappings contained in this map.
+ * 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.
+ */
+ public Set<Map.Entry<K,V>> entrySet() {
+ Set<Map.Entry<K,V>> es = entrySet;
+ return (es != null) ? es : (entrySet = new EntrySet());
+ }
+
+ /**
+ * Returns an enumeration of the keys in this table.
+ *
+ * @return an enumeration of the keys in this table
+ * @see #keySet
+ */
+ public Enumeration<K> keys() {
+ return new KeyIterator();
+ }
+
+ /**
+ * Returns an enumeration of the values in this table.
+ *
+ * @return an enumeration of the values in this table
+ * @see #values
+ */
+ public Enumeration<V> elements() {
+ return new ValueIterator();
+ }
+
+ /* ---------------- Iterator Support -------------- */
+
+ abstract class HashIterator {
+ int nextSegmentIndex;
+ int nextTableIndex;
+ HashEntry<K,V>[] currentTable;
+ HashEntry<K, V> nextEntry;
+ HashEntry<K, V> lastReturned;
+
+ HashIterator() {
+ nextSegmentIndex = segments.length - 1;
+ nextTableIndex = -1;
+ advance();
+ }
+
+ public boolean hasMoreElements() { return hasNext(); }
+
+ final void advance() {
+ if (nextEntry != null && (nextEntry = nextEntry.next) != null)
+ return;
+
+ while (nextTableIndex >= 0) {
+ if ( (nextEntry = currentTable[nextTableIndex--]) != null)
+ return;
+ }
+
+ while (nextSegmentIndex >= 0) {
+ Segment<K,V> seg = segments[nextSegmentIndex--];
+ if (seg.count != 0) {
+ currentTable = seg.table;
+ for (int j = currentTable.length - 1; j >= 0; --j) {
+ if ( (nextEntry = currentTable[j]) != null) {
+ nextTableIndex = j - 1;
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ public boolean hasNext() { return nextEntry != null; }
+
+ HashEntry<K,V> nextEntry() {
+ if (nextEntry == null)
+ throw new NoSuchElementException();
+ lastReturned = nextEntry;
+ advance();
+ return lastReturned;
+ }
+
+ public void remove() {
+ if (lastReturned == null)
+ throw new IllegalStateException();
+ ConcurrentHashMap.this.remove(lastReturned.key);
+ lastReturned = null;
+ }
+ }
+
+ final class KeyIterator
+ extends HashIterator
+ implements Iterator<K>, Enumeration<K>
+ {
+ public K next() { return super.nextEntry().key; }
+ public K nextElement() { return super.nextEntry().key; }
+ }
+
+ final class ValueIterator
+ extends HashIterator
+ implements Iterator<V>, Enumeration<V>
+ {
+ public V next() { return super.nextEntry().value; }
+ public V nextElement() { return super.nextEntry().value; }
+ }
+
+ /**
+ * Custom Entry class used by EntryIterator.next(), that relays
+ * setValue changes to the underlying map.
+ */
+ final class WriteThroughEntry
+ extends AbstractMap.SimpleEntry<K,V>
+ {
+ WriteThroughEntry(K k, V v) {
+ super(k,v);
+ }
+
+ /**
+ * Set our entry's value and write through to the map. The
+ * value to return is somewhat arbitrary here. Since a
+ * WriteThroughEntry does not necessarily track asynchronous
+ * changes, the most recent "previous" value could be
+ * different from what we return (or could even have been
+ * removed in which case the put will re-establish). We do not
+ * and cannot guarantee more.
+ */
+ public V setValue(V value) {
+ if (value == null) throw new NullPointerException();
+ V v = super.setValue(value);
+ ConcurrentHashMap.this.put(getKey(), value);
+ return v;
+ }
+ }
+
+ final class EntryIterator
+ extends HashIterator
+ implements Iterator<Entry<K,V>>
+ {
+ public Map.Entry<K,V> next() {
+ HashEntry<K,V> e = super.nextEntry();
+ return new WriteThroughEntry(e.key, e.value);
+ }
+ }
+
+ final class KeySet extends AbstractSet<K> {
+ public Iterator<K> iterator() {
+ return new KeyIterator();
+ }
+ public int size() {
+ return ConcurrentHashMap.this.size();
+ }
+ public boolean contains(Object o) {
+ return ConcurrentHashMap.this.containsKey(o);
+ }
+ public boolean remove(Object o) {
+ return ConcurrentHashMap.this.remove(o) != null;
+ }
+ public void clear() {
+ ConcurrentHashMap.this.clear();
+ }
+ }
+
+ final class Values extends AbstractCollection<V> {
+ public Iterator<V> iterator() {
+ return new ValueIterator();
+ }
+ public int size() {
+ return ConcurrentHashMap.this.size();
+ }
+ public boolean contains(Object o) {
+ return ConcurrentHashMap.this.containsValue(o);
+ }
+ public void clear() {
+ ConcurrentHashMap.this.clear();
+ }
+ }
+
+ final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
+ public Iterator<Map.Entry<K,V>> iterator() {
+ return new EntryIterator();
+ }
+ public boolean contains(Object o) {
+ if (!(o instanceof Map.Entry))
+ return false;
+ Map.Entry<?,?> e = (Map.Entry<?,?>)o;
+ V v = ConcurrentHashMap.this.get(e.getKey());
+ return v != null && v.equals(e.getValue());
+ }
+ public boolean remove(Object o) {
+ if (!(o instanceof Map.Entry))
+ return false;
+ Map.Entry<?,?> e = (Map.Entry<?,?>)o;
+ return ConcurrentHashMap.this.remove(e.getKey(), e.getValue());
+ }
+ public int size() {
+ return ConcurrentHashMap.this.size();
+ }
+ public void clear() {
+ ConcurrentHashMap.this.clear();
+ }
+ }
+
+ /* ---------------- Serialization Support -------------- */
+
+ /**
+ * Save the state of the <tt>ConcurrentHashMap</tt> instance to a
+ * stream (i.e., serialize it).
+ * @param s the stream
+ * @serialData
+ * the key (Object) and value (Object)
+ * for each key-value mapping, followed by a null pair.
+ * The key-value mappings are emitted in no particular order.
+ */
+ private void writeObject(java.io.ObjectOutputStream s) throws IOException {
+ s.defaultWriteObject();
+
+ for (int k = 0; k < segments.length; ++k) {
+ Segment<K,V> seg = segments[k];
+ seg.lock();
+ try {
+ HashEntry<K,V>[] tab = seg.table;
+ for (int i = 0; i < tab.length; ++i) {
+ for (HashEntry<K,V> e = tab[i]; e != null; e = e.next) {
+ s.writeObject(e.key);
+ s.writeObject(e.value);
+ }
+ }
+ } finally {
+ seg.unlock();
+ }
+ }
+ s.writeObject(null);
+ s.writeObject(null);
+ }
+
+ /**
+ * Reconstitute the <tt>ConcurrentHashMap</tt> instance from a
+ * stream (i.e., deserialize it).
+ * @param s the stream
+ */
+ private void readObject(java.io.ObjectInputStream s)
+ throws IOException, ClassNotFoundException {
+ s.defaultReadObject();
+
+ // Initialize each segment to be minimally sized, and let grow.
+ for (int i = 0; i < segments.length; ++i) {
+ segments[i].setTable(new HashEntry[1]);
+ }
+
+ // Read the keys and values, and put the mappings in the table
+ for (;;) {
+ K key = (K) s.readObject();
+ V value = (V) s.readObject();
+ if (key == null)
+ break;
+ put(key, value);
+ }
+ }
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/ConcurrentLinkedQueue.java b/libjava/classpath/external/jsr166/java/util/concurrent/ConcurrentLinkedQueue.java
new file mode 100644
index 000000000..000f4a4c9
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/ConcurrentLinkedQueue.java
@@ -0,0 +1,480 @@
+/*
+ * 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.*;
+
+
+/**
+ * An unbounded thread-safe {@linkplain Queue queue} based on linked nodes.
+ * This queue orders elements FIFO (first-in-first-out).
+ * The <em>head</em> of the queue is that element that has been on the
+ * queue the longest time.
+ * The <em>tail</em> of the queue is that element that has been on the
+ * queue the shortest time. New elements
+ * are inserted at the tail of the queue, and the queue retrieval
+ * operations obtain elements at the head of the queue.
+ * A <tt>ConcurrentLinkedQueue</tt> is an appropriate choice when
+ * many threads will share access to a common collection.
+ * This queue does not permit <tt>null</tt> elements.
+ *
+ * <p>This implementation employs an efficient &quot;wait-free&quot;
+ * algorithm based on one described in <a
+ * href="http://www.cs.rochester.edu/u/michael/PODC96.html"> Simple,
+ * Fast, and Practical Non-Blocking and Blocking Concurrent Queue
+ * Algorithms</a> by Maged M. Michael and Michael L. Scott.
+ *
+ * <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 queues, determining the current number
+ * of elements requires a traversal of the elements.
+ *
+ * <p>This class and its iterator implement all of the
+ * <em>optional</em> methods of the {@link Collection} and {@link
+ * Iterator} interfaces.
+ *
+ * <p>Memory consistency effects: As with other concurrent
+ * collections, actions in a thread prior to placing an object into a
+ * {@code ConcurrentLinkedQueue}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions subsequent to the access or removal of that element from
+ * the {@code ConcurrentLinkedQueue} in another thread.
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <E> the type of elements held in this collection
+ *
+ */
+public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
+ implements Queue<E>, java.io.Serializable {
+ private static final long serialVersionUID = 196745693267521676L;
+
+ /*
+ * This is a straight adaptation of Michael & Scott algorithm.
+ * For explanation, read the paper. The only (minor) algorithmic
+ * difference is that this version supports lazy deletion of
+ * internal nodes (method remove(Object)) -- remove CAS'es item
+ * fields to null. The normal queue operations unlink but then
+ * pass over nodes with null item fields. Similarly, iteration
+ * methods ignore those with nulls.
+ *
+ * Also note that like most non-blocking algorithms in this
+ * package, this implementation relies on the fact that in garbage
+ * collected systems, there is no possibility of ABA problems due
+ * to recycled nodes, so there is no need to use "counted
+ * pointers" or related techniques seen in versions used in
+ * non-GC'ed settings.
+ */
+
+ 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 x) { item = x; }
+
+ Node(E x, Node<E> n) { item = x; next = n; }
+
+ E getItem() {
+ return item;
+ }
+
+ boolean casItem(E cmp, E val) {
+ return itemUpdater.compareAndSet(this, cmp, val);
+ }
+
+ void setItem(E val) {
+ itemUpdater.set(this, val);
+ }
+
+ Node<E> getNext() {
+ return next;
+ }
+
+ boolean casNext(Node<E> cmp, Node<E> val) {
+ return nextUpdater.compareAndSet(this, cmp, val);
+ }
+
+ void setNext(Node<E> val) {
+ nextUpdater.set(this, val);
+ }
+
+ }
+
+ 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 header node, initialized to a dummy node. The first
+ * actual node is at head.getNext().
+ */
+ private transient volatile Node<E> head = new Node<E>(null, null);
+
+ /** Pointer to last node on list **/
+ private transient volatile Node<E> tail = head;
+
+
+ /**
+ * Creates a <tt>ConcurrentLinkedQueue</tt> that is initially empty.
+ */
+ public ConcurrentLinkedQueue() {}
+
+ /**
+ * Creates a <tt>ConcurrentLinkedQueue</tt>
+ * 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 ConcurrentLinkedQueue(Collection<? extends E> c) {
+ for (Iterator<? extends E> it = c.iterator(); it.hasNext();)
+ add(it.next());
+ }
+
+ // Have to override just to update the javadoc
+
+ /**
+ * Inserts the specified element at the tail of this queue.
+ *
+ * @return <tt>true</tt> (as specified by {@link Collection#add})
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean add(E e) {
+ return offer(e);
+ }
+
+ /**
+ * Inserts the specified element at the tail of this queue.
+ *
+ * @return <tt>true</tt> (as specified by {@link Queue#offer})
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean offer(E e) {
+ if (e == null) throw new NullPointerException();
+ Node<E> n = new Node<E>(e, null);
+ for (;;) {
+ Node<E> t = tail;
+ Node<E> s = t.getNext();
+ if (t == tail) {
+ if (s == null) {
+ if (t.casNext(s, n)) {
+ casTail(t, n);
+ return true;
+ }
+ } else {
+ casTail(t, s);
+ }
+ }
+ }
+ }
+
+ public E poll() {
+ for (;;) {
+ Node<E> h = head;
+ Node<E> t = tail;
+ Node<E> first = h.getNext();
+ if (h == head) {
+ if (h == t) {
+ if (first == null)
+ return null;
+ else
+ casTail(t, first);
+ } else if (casHead(h, first)) {
+ E item = first.getItem();
+ if (item != null) {
+ first.setItem(null);
+ return item;
+ }
+ // else skip over deleted item, continue loop,
+ }
+ }
+ }
+ }
+
+ public E peek() { // same as poll except don't remove item
+ for (;;) {
+ Node<E> h = head;
+ Node<E> t = tail;
+ Node<E> first = h.getNext();
+ if (h == head) {
+ if (h == t) {
+ if (first == null)
+ return null;
+ else
+ casTail(t, first);
+ } else {
+ E item = first.getItem();
+ if (item != null)
+ return item;
+ else // remove deleted node and continue
+ casHead(h, first);
+ }
+ }
+ }
+ }
+
+ /**
+ * 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.)
+ */
+ Node<E> first() {
+ for (;;) {
+ Node<E> h = head;
+ Node<E> t = tail;
+ Node<E> first = h.getNext();
+ if (h == head) {
+ if (h == t) {
+ if (first == null)
+ return null;
+ else
+ casTail(t, first);
+ } else {
+ if (first.getItem() != null)
+ return first;
+ else // remove deleted node and continue
+ casHead(h, first);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Returns <tt>true</tt> if this queue contains no elements.
+ *
+ * @return <tt>true</tt> if this queue contains no elements
+ */
+ public boolean isEmpty() {
+ return first() == null;
+ }
+
+ /**
+ * Returns the number of elements in this queue. If this queue
+ * contains more than <tt>Integer.MAX_VALUE</tt> elements, 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 queues, determining the current
+ * number of elements requires an O(n) traversal.
+ *
+ * @return the number of elements in this queue
+ */
+ public int size() {
+ int count = 0;
+ for (Node<E> p = first(); p != null; p = p.getNext()) {
+ if (p.getItem() != null) {
+ // Collections.size() spec says to max out
+ if (++count == Integer.MAX_VALUE)
+ break;
+ }
+ }
+ return count;
+ }
+
+ /**
+ * Returns <tt>true</tt> if this queue contains the specified element.
+ * More formally, returns <tt>true</tt> if and only if this queue 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 queue
+ * @return <tt>true</tt> if this queue contains the specified element
+ */
+ public boolean contains(Object o) {
+ if (o == null) return false;
+ for (Node<E> p = first(); p != null; p = p.getNext()) {
+ E item = p.getItem();
+ if (item != null &&
+ o.equals(item))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 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
+ * elements.
+ * Returns <tt>true</tt> 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
+ */
+ public boolean remove(Object o) {
+ if (o == null) return false;
+ for (Node<E> p = first(); p != null; p = p.getNext()) {
+ E item = p.getItem();
+ if (item != null &&
+ o.equals(item) &&
+ p.casItem(item, null))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 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},
+ * 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 queue in proper sequence
+ */
+ public Iterator<E> iterator() {
+ return new Itr();
+ }
+
+ private class Itr 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 of the last returned item, to support remove.
+ */
+ private Node<E> lastRet;
+
+ Itr() {
+ advance();
+ }
+
+ /**
+ * Moves to next valid node and returns item to return for
+ * next(), or null if no such.
+ */
+ private E advance() {
+ lastRet = nextNode;
+ E x = nextItem;
+
+ Node<E> p = (nextNode == null)? first() : nextNode.getNext();
+ for (;;) {
+ if (p == null) {
+ nextNode = null;
+ nextItem = null;
+ return x;
+ }
+ E item = p.getItem();
+ if (item != null) {
+ nextNode = p;
+ nextItem = item;
+ return x;
+ } else // skip over nulls
+ p = p.getNext();
+ }
+ }
+
+ public boolean hasNext() {
+ return nextNode != null;
+ }
+
+ public E next() {
+ if (nextNode == null) throw new NoSuchElementException();
+ return advance();
+ }
+
+ public void remove() {
+ Node<E> l = lastRet;
+ if (l == null) throw new IllegalStateException();
+ // rely on a future traversal to relink.
+ l.setItem(null);
+ lastRet = null;
+ }
+ }
+
+ /**
+ * Save the state to a stream (that is, serialize it).
+ *
+ * @serialData All of the elements (each an <tt>E</tt>) 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 = p.getNext()) {
+ Object item = p.getItem();
+ 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();
+ head = new Node<E>(null, null);
+ tail = head;
+ // Read in all elements and place in queue
+ for (;;) {
+ E item = (E)s.readObject();
+ if (item == null)
+ break;
+ else
+ offer(item);
+ }
+ }
+
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/ConcurrentMap.java b/libjava/classpath/external/jsr166/java/util/concurrent/ConcurrentMap.java
new file mode 100644
index 000000000..6e5bd0738
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/ConcurrentMap.java
@@ -0,0 +1,134 @@
+/*
+ * 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.Map;
+
+/**
+ * A {@link java.util.Map} providing additional atomic
+ * <tt>putIfAbsent</tt>, <tt>remove</tt>, and <tt>replace</tt> methods.
+ *
+ * <p>Memory consistency effects: As with other concurrent
+ * collections, actions in a thread prior to placing an object into a
+ * {@code ConcurrentMap} as a key or value
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions subsequent to the access or removal of that object from
+ * the {@code ConcurrentMap} 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.5
+ * @author Doug Lea
+ * @param <K> the type of keys maintained by this map
+ * @param <V> the type of mapped values
+ */
+public interface ConcurrentMap<K, V> extends Map<K, V> {
+ /**
+ * If the specified key is not already associated
+ * with a value, associate it with the given value.
+ * This is equivalent to
+ * <pre>
+ * if (!map.containsKey(key))
+ * return map.put(key, value);
+ * else
+ * return map.get(key);</pre>
+ * except that the action is performed atomically.
+ *
+ * @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.
+ * (A <tt>null</tt> return can also indicate that the map
+ * previously associated <tt>null</tt> with the key,
+ * if the implementation supports null values.)
+ * @throws UnsupportedOperationException if the <tt>put</tt> operation
+ * is not supported by this map
+ * @throws ClassCastException if the class of the specified key or value
+ * prevents it from being stored in this map
+ * @throws NullPointerException if the specified key or value is null,
+ * and this map does not permit null keys or values
+ * @throws IllegalArgumentException if some property of the specified key
+ * or value prevents it from being stored in this map
+ *
+ */
+ V putIfAbsent(K key, V value);
+
+ /**
+ * Removes the entry for a key only if currently mapped to a given value.
+ * This is equivalent to
+ * <pre>
+ * if (map.containsKey(key) &amp;&amp; map.get(key).equals(value)) {
+ * map.remove(key);
+ * return true;
+ * } else return false;</pre>
+ * except that the action is performed atomically.
+ *
+ * @param key key with which the specified value is associated
+ * @param value value expected to be associated with the specified key
+ * @return <tt>true</tt> if the value was removed
+ * @throws UnsupportedOperationException if the <tt>remove</tt> operation
+ * is not supported by this map
+ * @throws ClassCastException if the key or value is of an inappropriate
+ * type for this map (optional)
+ * @throws NullPointerException if the specified key or value is null,
+ * and this map does not permit null keys or values (optional)
+ */
+ boolean remove(Object key, Object value);
+
+ /**
+ * Replaces the entry for a key only if currently mapped to a given value.
+ * This is equivalent to
+ * <pre>
+ * if (map.containsKey(key) &amp;&amp; map.get(key).equals(oldValue)) {
+ * map.put(key, newValue);
+ * return true;
+ * } else return false;</pre>
+ * except that the action is performed atomically.
+ *
+ * @param key key with which the specified value is associated
+ * @param oldValue value expected to be associated with the specified key
+ * @param newValue value to be associated with the specified key
+ * @return <tt>true</tt> if the value was replaced
+ * @throws UnsupportedOperationException if the <tt>put</tt> operation
+ * is not supported by this map
+ * @throws ClassCastException if the class of a specified key or value
+ * prevents it from being stored in this map
+ * @throws NullPointerException if a specified key or value is null,
+ * and this map does not permit null keys or values
+ * @throws IllegalArgumentException if some property of a specified key
+ * or value prevents it from being stored in this map
+ */
+ boolean replace(K key, V oldValue, V newValue);
+
+ /**
+ * Replaces the entry for a key only if currently mapped to some value.
+ * This is equivalent to
+ * <pre>
+ * if (map.containsKey(key)) {
+ * return map.put(key, value);
+ * } else return null;</pre>
+ * except that the action is performed atomically.
+ *
+ * @param key key with which the specified value is 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.
+ * (A <tt>null</tt> return can also indicate that the map
+ * previously associated <tt>null</tt> with the key,
+ * if the implementation supports null values.)
+ * @throws UnsupportedOperationException if the <tt>put</tt> operation
+ * is not supported by this map
+ * @throws ClassCastException if the class of the specified key or value
+ * prevents it from being stored in this map
+ * @throws NullPointerException if the specified key or value is null,
+ * and this map does not permit null keys or values
+ * @throws IllegalArgumentException if some property of the specified key
+ * or value prevents it from being stored in this map
+ */
+ V replace(K key, V value);
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/ConcurrentNavigableMap.java b/libjava/classpath/external/jsr166/java/util/concurrent/ConcurrentNavigableMap.java
new file mode 100644
index 000000000..7d86afb70
--- /dev/null
+++ b/libjava/classpath/external/jsr166/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/libjava/classpath/external/jsr166/java/util/concurrent/ConcurrentSkipListMap.java b/libjava/classpath/external/jsr166/java/util/concurrent/ConcurrentSkipListMap.java
new file mode 100644
index 000000000..1ad924454
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/ConcurrentSkipListMap.java
@@ -0,0 +1,3114 @@
+/*
+ * 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 ((lastReturned = next) == null)
+ throw new NoSuchElementException();
+ 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 ConcurrentSkipListSet<E>
+ (m.subMap(fromElement, fromInclusive,
+ toElement, toInclusive));
+ }
+ public NavigableSet<E> headSet(E toElement, boolean inclusive) {
+ return new ConcurrentSkipListSet<E>(m.headMap(toElement, inclusive));
+ }
+ public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
+ return new ConcurrentSkipListSet<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 ConcurrentSkipListSet(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 ((lastReturned = next) == null)
+ throw new NoSuchElementException();
+ 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/libjava/classpath/external/jsr166/java/util/concurrent/ConcurrentSkipListSet.java b/libjava/classpath/external/jsr166/java/util/concurrent/ConcurrentSkipListSet.java
new file mode 100644
index 000000000..7fd1c7608
--- /dev/null
+++ b/libjava/classpath/external/jsr166/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/libjava/classpath/external/jsr166/java/util/concurrent/CopyOnWriteArraySet.java b/libjava/classpath/external/jsr166/java/util/concurrent/CopyOnWriteArraySet.java
new file mode 100644
index 000000000..063636bd8
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/CopyOnWriteArraySet.java
@@ -0,0 +1,364 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain. Use, modify, and
+ * redistribute this code in any way without acknowledgement.
+ */
+
+package java.util.concurrent;
+import java.util.*;
+
+/**
+ * A {@link java.util.Set} that uses an internal {@link CopyOnWriteArrayList}
+ * for all of its operations. Thus, it shares the same basic properties:
+ * <ul>
+ * <li>It is best suited for applications in which set sizes generally
+ * stay small, read-only operations
+ * vastly outnumber mutative operations, and you need
+ * to prevent interference among threads during traversal.
+ * <li>It is thread-safe.
+ * <li>Mutative operations (<tt>add</tt>, <tt>set</tt>, <tt>remove</tt>, etc.)
+ * are expensive since they usually entail copying the entire underlying
+ * array.
+ * <li>Iterators do not support the mutative <tt>remove</tt> operation.
+ * <li>Traversal via iterators is fast and cannot encounter
+ * interference from other threads. Iterators rely on
+ * unchanging snapshots of the array at the time the iterators were
+ * constructed.
+ * </ul>
+ *
+ * <p> <b>Sample Usage.</b> The following code sketch uses a
+ * copy-on-write set to maintain a set of Handler objects that
+ * perform some action upon state updates.
+ *
+ * <pre>
+ * class Handler { void handle(); ... }
+ *
+ * class X {
+ * private final CopyOnWriteArraySet&lt;Handler&gt; handlers
+ * = new CopyOnWriteArraySet&lt;Handler&gt;();
+ * public void addHandler(Handler h) { handlers.add(h); }
+ *
+ * private long internalState;
+ * private synchronized void changeState() { internalState = ...; }
+ *
+ * public void update() {
+ * changeState();
+ * for (Handler handler : handlers)
+ * handler.handle();
+ * }
+ * }
+ * </pre>
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @see CopyOnWriteArrayList
+ * @since 1.5
+ * @author Doug Lea
+ * @param <E> the type of elements held in this collection
+ */
+public class CopyOnWriteArraySet<E> extends AbstractSet<E>
+ implements java.io.Serializable {
+ private static final long serialVersionUID = 5457747651344034263L;
+
+ private final CopyOnWriteArrayList<E> al;
+
+ /**
+ * Creates an empty set.
+ */
+ public CopyOnWriteArraySet() {
+ al = new CopyOnWriteArrayList<E>();
+ }
+
+ /**
+ * Creates a set containing all of the elements of the specified
+ * collection.
+ *
+ * @param c the collection of elements to initially contain
+ * @throws NullPointerException if the specified collection is null
+ */
+ public CopyOnWriteArraySet(Collection<? extends E> c) {
+ al = new CopyOnWriteArrayList<E>();
+ al.addAllAbsent(c);
+ }
+
+ /**
+ * Returns the number of elements in this set.
+ *
+ * @return the number of elements in this set
+ */
+ public int size() {
+ return al.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 al.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==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
+ *
+ * @param o element whose presence in this set is to be tested
+ * @return <tt>true</tt> if this set contains the specified element
+ */
+ public boolean contains(Object o) {
+ return al.contains(o);
+ }
+
+ /**
+ * Returns an array containing all of the elements in this set.
+ * If this set makes any guarantees as to what order its elements
+ * are returned by its iterator, this method must return the
+ * elements in the same order.
+ *
+ * <p>The returned array will be "safe" in that no references to it
+ * are maintained by this set. (In other words, this method must
+ * allocate a new array even if this set is backed by an 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 the elements in this set
+ */
+ public Object[] toArray() {
+ return al.toArray();
+ }
+
+ /**
+ * Returns an array containing all of the elements in this set; the
+ * runtime type of the returned array is that of the specified array.
+ * If the set 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 set.
+ *
+ * <p>If this set fits in the specified array with room to spare
+ * (i.e., the array has more elements than this set), the element in
+ * the array immediately following the end of the set is set to
+ * <tt>null</tt>. (This is useful in determining the length of this
+ * set <i>only</i> if the caller knows that this set does not contain
+ * any null elements.)
+ *
+ * <p>If this set makes any guarantees as to what order its elements
+ * are returned by its iterator, this method must return the elements
+ * in the same order.
+ *
+ * <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 set known to contain only strings.
+ * The following code can be used to dump the set into a newly allocated
+ * array of <tt>String</tt>:
+ *
+ * <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>.
+ *
+ * @param a the array into which the elements of this set 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 the elements in this set
+ * @throws ArrayStoreException if the runtime type of the specified array
+ * is not a supertype of the runtime type of every element in this
+ * set
+ * @throws NullPointerException if the specified array is null
+ */
+ public <T> T[] toArray(T[] a) {
+ return al.toArray(a);
+ }
+
+ /**
+ * Removes all of the elements from this set.
+ * The set will be empty after this call returns.
+ */
+ public void clear() {
+ al.clear();
+ }
+
+ /**
+ * Removes the specified element from this set if it is present.
+ * More formally, removes an element <tt>e</tt> such that
+ * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;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
+ */
+ public boolean remove(Object o) {
+ return al.remove(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==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;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
+ */
+ public boolean add(E e) {
+ return al.addIfAbsent(e);
+ }
+
+ /**
+ * Returns <tt>true</tt> if this set contains all of the elements of the
+ * specified collection. If the specified collection is also a set, this
+ * method returns <tt>true</tt> if it is a <i>subset</i> of this set.
+ *
+ * @param c collection to be checked for containment in this set
+ * @return <tt>true</tt> if this set contains all of the elements of the
+ * specified collection
+ * @throws NullPointerException if the specified collection is null
+ * @see #contains(Object)
+ */
+ public boolean containsAll(Collection<?> c) {
+ return al.containsAll(c);
+ }
+
+ /**
+ * Adds all of the elements in the specified collection to this set if
+ * they're not already present. If the specified collection is also a
+ * set, the <tt>addAll</tt> operation effectively modifies this set so
+ * that its value is the <i>union</i> of the two sets. 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 set
+ * @return <tt>true</tt> if this set changed as a result of the call
+ * @throws NullPointerException if the specified collection is null
+ * @see #add(Object)
+ */
+ public boolean addAll(Collection<? extends E> c) {
+ return al.addAllAbsent(c) > 0;
+ }
+
+ /**
+ * 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 class of an element of this set
+ * is incompatible with the specified collection (optional)
+ * @throws NullPointerException if this set contains a null element and the
+ * specified collection does not permit null elements (optional),
+ * or if the specified collection is null
+ * @see #remove(Object)
+ */
+ public boolean removeAll(Collection<?> c) {
+ return al.removeAll(c);
+ }
+
+ /**
+ * Retains only the elements in this set that are contained in the
+ * specified collection. In other words, removes from this set all of
+ * its elements that are not 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>intersection</i> of the
+ * two sets.
+ *
+ * @param c collection containing elements to be retained in this set
+ * @return <tt>true</tt> if this set changed as a result of the call
+ * @throws ClassCastException if the class of an element of this set
+ * is incompatible with the specified collection (optional)
+ * @throws NullPointerException if this set contains a null element and the
+ * specified collection does not permit null elements (optional),
+ * or if the specified collection is null
+ * @see #remove(Object)
+ */
+ public boolean retainAll(Collection<?> c) {
+ return al.retainAll(c);
+ }
+
+ /**
+ * Returns an iterator over the elements contained in this set
+ * in the order in which these elements were added.
+ *
+ * <p>The returned iterator provides a snapshot of the state of the set
+ * when the iterator was constructed. No synchronization is needed while
+ * traversing the iterator. The iterator does <em>NOT</em> support the
+ * <tt>remove</tt> method.
+ *
+ * @return an iterator over the elements in this set
+ */
+ public Iterator<E> iterator() {
+ return al.iterator();
+ }
+
+ /**
+ * Compares the specified object with this set for equality.
+ * Returns {@code true} if the specified object is the same object
+ * as this object, or if it is also a {@link Set} and the elements
+ * returned by an {@linkplain List#iterator() iterator} over the
+ * specified set are the same as the elements returned by an
+ * iterator over this set. More formally, the two iterators are
+ * considered to return the same elements if they return the same
+ * number of elements and for every element {@code e1} returned by
+ * the iterator over the specified set, there is an element
+ * {@code e2} returned by the iterator over this set such that
+ * {@code (e1==null ? e2==null : e1.equals(e2))}.
+ *
+ * @param o object to be compared for equality with this set
+ * @return {@code true} if the specified object is equal to this set
+ */
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+ if (!(o instanceof Set))
+ return false;
+ Set<?> set = (Set<?>)(o);
+ Iterator<?> it = set.iterator();
+
+ // Uses O(n^2) algorithm that is only appropriate
+ // for small sets, which CopyOnWriteArraySets should be.
+
+ // Use a single snapshot of underlying array
+ Object[] elements = al.getArray();
+ int len = elements.length;
+ // Mark matched elements to avoid re-checking
+ boolean[] matched = new boolean[len];
+ int k = 0;
+ outer: while (it.hasNext()) {
+ if (++k > len)
+ return false;
+ Object x = it.next();
+ for (int i = 0; i < len; ++i) {
+ if (!matched[i] && eq(x, elements[i])) {
+ matched[i] = true;
+ continue outer;
+ }
+ }
+ return false;
+ }
+ return k == len;
+ }
+
+ /**
+ * Test for equality, coping with nulls.
+ */
+ private static boolean eq(Object o1, Object o2) {
+ return (o1 == null ? o2 == null : o1.equals(o2));
+ }
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/CountDownLatch.java b/libjava/classpath/external/jsr166/java/util/concurrent/CountDownLatch.java
new file mode 100644
index 000000000..016c1a7a5
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/CountDownLatch.java
@@ -0,0 +1,290 @@
+/*
+ * 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.concurrent.locks.*;
+import java.util.concurrent.atomic.*;
+
+/**
+ * A synchronization aid that allows one or more threads to wait until
+ * a set of operations being performed in other threads completes.
+ *
+ * <p>A {@code CountDownLatch} is initialized with a given <em>count</em>.
+ * The {@link #await await} methods block until the current count reaches
+ * zero due to invocations of the {@link #countDown} method, after which
+ * all waiting threads are released and any subsequent invocations of
+ * {@link #await await} return immediately. This is a one-shot phenomenon
+ * -- the count cannot be reset. If you need a version that resets the
+ * count, consider using a {@link CyclicBarrier}.
+ *
+ * <p>A {@code CountDownLatch} is a versatile synchronization tool
+ * and can be used for a number of purposes. A
+ * {@code CountDownLatch} initialized with a count of one serves as a
+ * simple on/off latch, or gate: all threads invoking {@link #await await}
+ * wait at the gate until it is opened by a thread invoking {@link
+ * #countDown}. A {@code CountDownLatch} initialized to <em>N</em>
+ * can be used to make one thread wait until <em>N</em> threads have
+ * completed some action, or some action has been completed N times.
+ *
+ * <p>A useful property of a {@code CountDownLatch} is that it
+ * doesn't require that threads calling {@code countDown} wait for
+ * the count to reach zero before proceeding, it simply prevents any
+ * thread from proceeding past an {@link #await await} until all
+ * threads could pass.
+ *
+ * <p><b>Sample usage:</b> Here is a pair of classes in which a group
+ * of worker threads use two countdown latches:
+ * <ul>
+ * <li>The first is a start signal that prevents any worker from proceeding
+ * until the driver is ready for them to proceed;
+ * <li>The second is a completion signal that allows the driver to wait
+ * until all workers have completed.
+ * </ul>
+ *
+ * <pre>
+ * class Driver { // ...
+ * void main() throws InterruptedException {
+ * CountDownLatch startSignal = new CountDownLatch(1);
+ * CountDownLatch doneSignal = new CountDownLatch(N);
+ *
+ * for (int i = 0; i < N; ++i) // create and start threads
+ * new Thread(new Worker(startSignal, doneSignal)).start();
+ *
+ * doSomethingElse(); // don't let run yet
+ * startSignal.countDown(); // let all threads proceed
+ * doSomethingElse();
+ * doneSignal.await(); // wait for all to finish
+ * }
+ * }
+ *
+ * class Worker implements Runnable {
+ * private final CountDownLatch startSignal;
+ * private final CountDownLatch doneSignal;
+ * Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
+ * this.startSignal = startSignal;
+ * this.doneSignal = doneSignal;
+ * }
+ * public void run() {
+ * try {
+ * startSignal.await();
+ * doWork();
+ * doneSignal.countDown();
+ * } catch (InterruptedException ex) {} // return;
+ * }
+ *
+ * void doWork() { ... }
+ * }
+ *
+ * </pre>
+ *
+ * <p>Another typical usage would be to divide a problem into N parts,
+ * describe each part with a Runnable that executes that portion and
+ * counts down on the latch, and queue all the Runnables to an
+ * Executor. When all sub-parts are complete, the coordinating thread
+ * will be able to pass through await. (When threads must repeatedly
+ * count down in this way, instead use a {@link CyclicBarrier}.)
+ *
+ * <pre>
+ * class Driver2 { // ...
+ * void main() throws InterruptedException {
+ * CountDownLatch doneSignal = new CountDownLatch(N);
+ * Executor e = ...
+ *
+ * for (int i = 0; i < N; ++i) // create and start threads
+ * e.execute(new WorkerRunnable(doneSignal, i));
+ *
+ * doneSignal.await(); // wait for all to finish
+ * }
+ * }
+ *
+ * class WorkerRunnable implements Runnable {
+ * private final CountDownLatch doneSignal;
+ * private final int i;
+ * WorkerRunnable(CountDownLatch doneSignal, int i) {
+ * this.doneSignal = doneSignal;
+ * this.i = i;
+ * }
+ * public void run() {
+ * try {
+ * doWork(i);
+ * doneSignal.countDown();
+ * } catch (InterruptedException ex) {} // return;
+ * }
+ *
+ * void doWork() { ... }
+ * }
+ *
+ * </pre>
+ *
+ * <p>Memory consistency effects: Actions in a thread prior to calling
+ * {@code countDown()}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions following a successful return from a corresponding
+ * {@code await()} in another thread.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class CountDownLatch {
+ /**
+ * Synchronization control For CountDownLatch.
+ * Uses AQS state to represent count.
+ */
+ private static final class Sync extends AbstractQueuedSynchronizer {
+ private static final long serialVersionUID = 4982264981922014374L;
+
+ Sync(int count) {
+ setState(count);
+ }
+
+ int getCount() {
+ return getState();
+ }
+
+ public int tryAcquireShared(int acquires) {
+ return getState() == 0? 1 : -1;
+ }
+
+ public boolean tryReleaseShared(int releases) {
+ // Decrement count; signal when transition to zero
+ for (;;) {
+ int c = getState();
+ if (c == 0)
+ return false;
+ int nextc = c-1;
+ if (compareAndSetState(c, nextc))
+ return nextc == 0;
+ }
+ }
+ }
+
+ private final Sync sync;
+
+ /**
+ * Constructs a {@code CountDownLatch} initialized with the given count.
+ *
+ * @param count the number of times {@link #countDown} must be invoked
+ * before threads can pass through {@link #await}
+ * @throws IllegalArgumentException if {@code count} is negative
+ */
+ public CountDownLatch(int count) {
+ if (count < 0) throw new IllegalArgumentException("count < 0");
+ this.sync = new Sync(count);
+ }
+
+ /**
+ * Causes the current thread to wait until the latch has counted down to
+ * zero, unless the thread is {@linkplain Thread#interrupt interrupted}.
+ *
+ * <p>If the current count is zero then this method returns immediately.
+ *
+ * <p>If the current count is greater than zero then the current
+ * thread becomes disabled for thread scheduling purposes and lies
+ * dormant until one of two things happen:
+ * <ul>
+ * <li>The count reaches zero due to invocations of the
+ * {@link #countDown} method; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread.
+ * </ul>
+ *
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while waiting,
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ *
+ * @throws InterruptedException if the current thread is interrupted
+ * while waiting
+ */
+ public void await() throws InterruptedException {
+ sync.acquireSharedInterruptibly(1);
+ }
+
+ /**
+ * Causes the current thread to wait until the latch has counted down to
+ * zero, unless the thread is {@linkplain Thread#interrupt interrupted},
+ * or the specified waiting time elapses.
+ *
+ * <p>If the current count is zero then this method returns immediately
+ * with the value {@code true}.
+ *
+ * <p>If the current count is greater than zero then the current
+ * thread becomes disabled for thread scheduling purposes and lies
+ * dormant until one of three things happen:
+ * <ul>
+ * <li>The count reaches zero due to invocations of the
+ * {@link #countDown} method; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread; or
+ * <li>The specified waiting time elapses.
+ * </ul>
+ *
+ * <p>If the count reaches zero then the method returns with the
+ * value {@code true}.
+ *
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while waiting,
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ *
+ * <p>If the specified waiting time elapses then the value {@code false}
+ * is returned. If the time is less than or equal to zero, the method
+ * will not wait at all.
+ *
+ * @param timeout the maximum time to wait
+ * @param unit the time unit of the {@code timeout} argument
+ * @return {@code true} if the count reached zero and {@code false}
+ * if the waiting time elapsed before the count reached zero
+ * @throws InterruptedException if the current thread is interrupted
+ * while waiting
+ */
+ public boolean await(long timeout, TimeUnit unit)
+ throws InterruptedException {
+ return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
+ }
+
+ /**
+ * Decrements the count of the latch, releasing all waiting threads if
+ * the count reaches zero.
+ *
+ * <p>If the current count is greater than zero then it is decremented.
+ * If the new count is zero then all waiting threads are re-enabled for
+ * thread scheduling purposes.
+ *
+ * <p>If the current count equals zero then nothing happens.
+ */
+ public void countDown() {
+ sync.releaseShared(1);
+ }
+
+ /**
+ * Returns the current count.
+ *
+ * <p>This method is typically used for debugging and testing purposes.
+ *
+ * @return the current count
+ */
+ public long getCount() {
+ return sync.getCount();
+ }
+
+ /**
+ * Returns a string identifying this latch, as well as its state.
+ * The state, in brackets, includes the String {@code "Count ="}
+ * followed by the current count.
+ *
+ * @return a string identifying this latch, as well as its state
+ */
+ public String toString() {
+ return super.toString() + "[Count = " + sync.getCount() + "]";
+ }
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/CyclicBarrier.java b/libjava/classpath/external/jsr166/java/util/concurrent/CyclicBarrier.java
new file mode 100644
index 000000000..d5738c5ae
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/CyclicBarrier.java
@@ -0,0 +1,454 @@
+/*
+ * 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.concurrent.locks.*;
+
+/**
+ * A synchronization aid that allows a set of threads to all wait for
+ * each other to reach a common barrier point. CyclicBarriers are
+ * useful in programs involving a fixed sized party of threads that
+ * must occasionally wait for each other. The barrier is called
+ * <em>cyclic</em> because it can be re-used after the waiting threads
+ * are released.
+ *
+ * <p>A <tt>CyclicBarrier</tt> supports an optional {@link Runnable} command
+ * that is run once per barrier point, after the last thread in the party
+ * arrives, but before any threads are released.
+ * This <em>barrier action</em> is useful
+ * for updating shared-state before any of the parties continue.
+ *
+ * <p><b>Sample usage:</b> Here is an example of
+ * using a barrier in a parallel decomposition design:
+ * <pre>
+ * class Solver {
+ * final int N;
+ * final float[][] data;
+ * final CyclicBarrier barrier;
+ *
+ * class Worker implements Runnable {
+ * int myRow;
+ * Worker(int row) { myRow = row; }
+ * public void run() {
+ * while (!done()) {
+ * processRow(myRow);
+ *
+ * try {
+ * barrier.await();
+ * } catch (InterruptedException ex) {
+ * return;
+ * } catch (BrokenBarrierException ex) {
+ * return;
+ * }
+ * }
+ * }
+ * }
+ *
+ * public Solver(float[][] matrix) {
+ * data = matrix;
+ * N = matrix.length;
+ * barrier = new CyclicBarrier(N,
+ * new Runnable() {
+ * public void run() {
+ * mergeRows(...);
+ * }
+ * });
+ * for (int i = 0; i < N; ++i)
+ * new Thread(new Worker(i)).start();
+ *
+ * waitUntilDone();
+ * }
+ * }
+ * </pre>
+ * Here, each worker thread processes a row of the matrix then waits at the
+ * barrier until all rows have been processed. When all rows are processed
+ * the supplied {@link Runnable} barrier action is executed and merges the
+ * rows. If the merger
+ * determines that a solution has been found then <tt>done()</tt> will return
+ * <tt>true</tt> and each worker will terminate.
+ *
+ * <p>If the barrier action does not rely on the parties being suspended when
+ * it is executed, then any of the threads in the party could execute that
+ * action when it is released. To facilitate this, each invocation of
+ * {@link #await} returns the arrival index of that thread at the barrier.
+ * You can then choose which thread should execute the barrier action, for
+ * example:
+ * <pre> if (barrier.await() == 0) {
+ * // log the completion of this iteration
+ * }</pre>
+ *
+ * <p>The <tt>CyclicBarrier</tt> uses an all-or-none breakage model
+ * for failed synchronization attempts: If a thread leaves a barrier
+ * point prematurely because of interruption, failure, or timeout, all
+ * other threads waiting at that barrier point will also leave
+ * abnormally via {@link BrokenBarrierException} (or
+ * {@link InterruptedException} if they too were interrupted at about
+ * the same time).
+ *
+ * <p>Memory consistency effects: Actions in a thread prior to calling
+ * {@code await()}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions that are part of the barrier action, which in turn
+ * <i>happen-before</i> actions following a successful return from the
+ * corresponding {@code await()} in other threads.
+ *
+ * @since 1.5
+ * @see CountDownLatch
+ *
+ * @author Doug Lea
+ */
+public class CyclicBarrier {
+ /**
+ * Each use of the barrier is represented as a generation instance.
+ * The generation changes whenever the barrier is tripped, or
+ * is reset. There can be many generations associated with threads
+ * using the barrier - due to the non-deterministic way the lock
+ * may be allocated to waiting threads - but only one of these
+ * can be active at a time (the one to which <tt>count</tt> applies)
+ * and all the rest are either broken or tripped.
+ * There need not be an active generation if there has been a break
+ * but no subsequent reset.
+ */
+ private static class Generation {
+ boolean broken = false;
+ }
+
+ /** The lock for guarding barrier entry */
+ private final ReentrantLock lock = new ReentrantLock();
+ /** Condition to wait on until tripped */
+ private final Condition trip = lock.newCondition();
+ /** The number of parties */
+ private final int parties;
+ /* The command to run when tripped */
+ private final Runnable barrierCommand;
+ /** The current generation */
+ private Generation generation = new Generation();
+
+ /**
+ * Number of parties still waiting. Counts down from parties to 0
+ * on each generation. It is reset to parties on each new
+ * generation or when broken.
+ */
+ private int count;
+
+ /**
+ * Updates state on barrier trip and wakes up everyone.
+ * Called only while holding lock.
+ */
+ private void nextGeneration() {
+ // signal completion of last generation
+ trip.signalAll();
+ // set up next generation
+ count = parties;
+ generation = new Generation();
+ }
+
+ /**
+ * Sets current barrier generation as broken and wakes up everyone.
+ * Called only while holding lock.
+ */
+ private void breakBarrier() {
+ generation.broken = true;
+ count = parties;
+ trip.signalAll();
+ }
+
+ /**
+ * Main barrier code, covering the various policies.
+ */
+ private int dowait(boolean timed, long nanos)
+ throws InterruptedException, BrokenBarrierException,
+ TimeoutException {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ final Generation g = generation;
+
+ if (g.broken)
+ throw new BrokenBarrierException();
+
+ if (Thread.interrupted()) {
+ breakBarrier();
+ throw new InterruptedException();
+ }
+
+ int index = --count;
+ if (index == 0) { // tripped
+ boolean ranAction = false;
+ try {
+ final Runnable command = barrierCommand;
+ if (command != null)
+ command.run();
+ ranAction = true;
+ nextGeneration();
+ return 0;
+ } finally {
+ if (!ranAction)
+ breakBarrier();
+ }
+ }
+
+ // loop until tripped, broken, interrupted, or timed out
+ for (;;) {
+ try {
+ if (!timed)
+ trip.await();
+ else if (nanos > 0L)
+ nanos = trip.awaitNanos(nanos);
+ } catch (InterruptedException ie) {
+ if (g == generation && ! g.broken) {
+ breakBarrier();
+ throw ie;
+ } else {
+ // We're about to finish waiting even if we had not
+ // been interrupted, so this interrupt is deemed to
+ // "belong" to subsequent execution.
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ if (g.broken)
+ throw new BrokenBarrierException();
+
+ if (g != generation)
+ return index;
+
+ if (timed && nanos <= 0L) {
+ breakBarrier();
+ throw new TimeoutException();
+ }
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Creates a new <tt>CyclicBarrier</tt> that will trip when the
+ * given number of parties (threads) are waiting upon it, and which
+ * will execute the given barrier action when the barrier is tripped,
+ * performed by the last thread entering the barrier.
+ *
+ * @param parties the number of threads that must invoke {@link #await}
+ * before the barrier is tripped
+ * @param barrierAction the command to execute when the barrier is
+ * tripped, or {@code null} if there is no action
+ * @throws IllegalArgumentException if {@code parties} is less than 1
+ */
+ public CyclicBarrier(int parties, Runnable barrierAction) {
+ if (parties <= 0) throw new IllegalArgumentException();
+ this.parties = parties;
+ this.count = parties;
+ this.barrierCommand = barrierAction;
+ }
+
+ /**
+ * Creates a new <tt>CyclicBarrier</tt> that will trip when the
+ * given number of parties (threads) are waiting upon it, and
+ * does not perform a predefined action when the barrier is tripped.
+ *
+ * @param parties the number of threads that must invoke {@link #await}
+ * before the barrier is tripped
+ * @throws IllegalArgumentException if {@code parties} is less than 1
+ */
+ public CyclicBarrier(int parties) {
+ this(parties, null);
+ }
+
+ /**
+ * Returns the number of parties required to trip this barrier.
+ *
+ * @return the number of parties required to trip this barrier
+ */
+ public int getParties() {
+ return parties;
+ }
+
+ /**
+ * Waits until all {@linkplain #getParties parties} have invoked
+ * <tt>await</tt> on this barrier.
+ *
+ * <p>If the current thread is not the last to arrive then it is
+ * disabled for thread scheduling purposes and lies dormant until
+ * one of the following things happens:
+ * <ul>
+ * <li>The last thread arrives; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * one of the other waiting threads; or
+ * <li>Some other thread times out while waiting for barrier; or
+ * <li>Some other thread invokes {@link #reset} on this barrier.
+ * </ul>
+ *
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ *
+ * <p>If the barrier is {@link #reset} while any thread is waiting,
+ * or if the barrier {@linkplain #isBroken is broken} when
+ * <tt>await</tt> is invoked, or while any thread is waiting, then
+ * {@link BrokenBarrierException} is thrown.
+ *
+ * <p>If any thread is {@linkplain Thread#interrupt interrupted} while waiting,
+ * then all other waiting threads will throw
+ * {@link BrokenBarrierException} and the barrier is placed in the broken
+ * state.
+ *
+ * <p>If the current thread is the last thread to arrive, and a
+ * non-null barrier action was supplied in the constructor, then the
+ * current thread runs the action before allowing the other threads to
+ * continue.
+ * If an exception occurs during the barrier action then that exception
+ * will be propagated in the current thread and the barrier is placed in
+ * the broken state.
+ *
+ * @return the arrival index of the current thread, where index
+ * <tt>{@link #getParties()} - 1</tt> indicates the first
+ * to arrive and zero indicates the last to arrive
+ * @throws InterruptedException if the current thread was interrupted
+ * while waiting
+ * @throws BrokenBarrierException if <em>another</em> thread was
+ * interrupted or timed out while the current thread was
+ * waiting, or the barrier was reset, or the barrier was
+ * broken when {@code await} was called, or the barrier
+ * action (if present) failed due an exception.
+ */
+ public int await() throws InterruptedException, BrokenBarrierException {
+ try {
+ return dowait(false, 0L);
+ } catch (TimeoutException toe) {
+ throw new Error(toe); // cannot happen;
+ }
+ }
+
+ /**
+ * Waits until all {@linkplain #getParties parties} have invoked
+ * <tt>await</tt> on this barrier, or the specified waiting time elapses.
+ *
+ * <p>If the current thread is not the last to arrive then it is
+ * disabled for thread scheduling purposes and lies dormant until
+ * one of the following things happens:
+ * <ul>
+ * <li>The last thread arrives; or
+ * <li>The specified timeout elapses; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * one of the other waiting threads; or
+ * <li>Some other thread times out while waiting for barrier; or
+ * <li>Some other thread invokes {@link #reset} on this barrier.
+ * </ul>
+ *
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ *
+ * <p>If the specified waiting time elapses then {@link TimeoutException}
+ * is thrown. If the time is less than or equal to zero, the
+ * method will not wait at all.
+ *
+ * <p>If the barrier is {@link #reset} while any thread is waiting,
+ * or if the barrier {@linkplain #isBroken is broken} when
+ * <tt>await</tt> is invoked, or while any thread is waiting, then
+ * {@link BrokenBarrierException} is thrown.
+ *
+ * <p>If any thread is {@linkplain Thread#interrupt interrupted} while
+ * waiting, then all other waiting threads will throw {@link
+ * BrokenBarrierException} and the barrier is placed in the broken
+ * state.
+ *
+ * <p>If the current thread is the last thread to arrive, and a
+ * non-null barrier action was supplied in the constructor, then the
+ * current thread runs the action before allowing the other threads to
+ * continue.
+ * If an exception occurs during the barrier action then that exception
+ * will be propagated in the current thread and the barrier is placed in
+ * the broken state.
+ *
+ * @param timeout the time to wait for the barrier
+ * @param unit the time unit of the timeout parameter
+ * @return the arrival index of the current thread, where index
+ * <tt>{@link #getParties()} - 1</tt> indicates the first
+ * to arrive and zero indicates the last to arrive
+ * @throws InterruptedException if the current thread was interrupted
+ * while waiting
+ * @throws TimeoutException if the specified timeout elapses
+ * @throws BrokenBarrierException if <em>another</em> thread was
+ * interrupted or timed out while the current thread was
+ * waiting, or the barrier was reset, or the barrier was broken
+ * when {@code await} was called, or the barrier action (if
+ * present) failed due an exception
+ */
+ public int await(long timeout, TimeUnit unit)
+ throws InterruptedException,
+ BrokenBarrierException,
+ TimeoutException {
+ return dowait(true, unit.toNanos(timeout));
+ }
+
+ /**
+ * Queries if this barrier is in a broken state.
+ *
+ * @return {@code true} if one or more parties broke out of this
+ * barrier due to interruption or timeout since
+ * construction or the last reset, or a barrier action
+ * failed due to an exception; {@code false} otherwise.
+ */
+ public boolean isBroken() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return generation.broken;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Resets the barrier to its initial state. If any parties are
+ * currently waiting at the barrier, they will return with a
+ * {@link BrokenBarrierException}. Note that resets <em>after</em>
+ * a breakage has occurred for other reasons can be complicated to
+ * carry out; threads need to re-synchronize in some other way,
+ * and choose one to perform the reset. It may be preferable to
+ * instead create a new barrier for subsequent use.
+ */
+ public void reset() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ breakBarrier(); // break the current generation
+ nextGeneration(); // start a new generation
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns the number of parties currently waiting at the barrier.
+ * This method is primarily useful for debugging and assertions.
+ *
+ * @return the number of parties currently blocked in {@link #await}
+ */
+ public int getNumberWaiting() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return parties - count;
+ } finally {
+ lock.unlock();
+ }
+ }
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/DelayQueue.java b/libjava/classpath/external/jsr166/java/util/concurrent/DelayQueue.java
new file mode 100644
index 000000000..4ce7bc652
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/DelayQueue.java
@@ -0,0 +1,487 @@
+/*
+ * 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.concurrent.locks.*;
+import java.util.*;
+
+/**
+ * An unbounded {@linkplain BlockingQueue blocking queue} of
+ * <tt>Delayed</tt> elements, in which an element can only be taken
+ * when its delay has expired. The <em>head</em> of the queue is that
+ * <tt>Delayed</tt> element whose delay expired furthest in the
+ * past. If no delay has expired there is no head and <tt>poll</tt>
+ * will return <tt>null</tt>. Expiration occurs when an element's
+ * <tt>getDelay(TimeUnit.NANOSECONDS)</tt> method returns a value less
+ * than or equal to zero. Even though unexpired elements cannot be
+ * removed using <tt>take</tt> or <tt>poll</tt>, they are otherwise
+ * treated as normal elements. For example, the <tt>size</tt> method
+ * returns the count of both expired and unexpired elements.
+ * This queue does not permit null elements.
+ *
+ * <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.5
+ * @author Doug Lea
+ * @param <E> the type of elements held in this collection
+ */
+
+public class DelayQueue<E extends Delayed> extends AbstractQueue<E>
+ implements BlockingQueue<E> {
+
+ private transient final ReentrantLock lock = new ReentrantLock();
+ private transient final Condition available = lock.newCondition();
+ private final PriorityQueue<E> q = new PriorityQueue<E>();
+
+ /**
+ * Creates a new <tt>DelayQueue</tt> that is initially empty.
+ */
+ public DelayQueue() {}
+
+ /**
+ * Creates a <tt>DelayQueue</tt> initially containing the elements of the
+ * given collection of {@link Delayed} instances.
+ *
+ * @param c the collection of elements to initially contain
+ * @throws NullPointerException if the specified collection or any
+ * of its elements are null
+ */
+ public DelayQueue(Collection<? extends E> c) {
+ this.addAll(c);
+ }
+
+ /**
+ * Inserts the specified element into this delay queue.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> (as specified by {@link Collection#add})
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean add(E e) {
+ return offer(e);
+ }
+
+ /**
+ * Inserts the specified element into this delay queue.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt>
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean offer(E e) {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ E first = q.peek();
+ q.offer(e);
+ if (first == null || e.compareTo(first) < 0)
+ available.signalAll();
+ return true;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Inserts the specified element into this delay queue. As the queue is
+ * unbounded this method will never block.
+ *
+ * @param e the element to add
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public void put(E e) {
+ offer(e);
+ }
+
+ /**
+ * Inserts the specified element into this delay queue. As the queue is
+ * unbounded this method will never block.
+ *
+ * @param e the element to add
+ * @param timeout This parameter is ignored as the method never blocks
+ * @param unit This parameter is ignored as the method never blocks
+ * @return <tt>true</tt>
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean offer(E e, long timeout, TimeUnit unit) {
+ return offer(e);
+ }
+
+ /**
+ * Retrieves and removes the head of this queue, or returns <tt>null</tt>
+ * if this queue has no elements with an expired delay.
+ *
+ * @return the head of this queue, or <tt>null</tt> if this
+ * queue has no elements with an expired delay
+ */
+ public E poll() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ E first = q.peek();
+ if (first == null || first.getDelay(TimeUnit.NANOSECONDS) > 0)
+ return null;
+ else {
+ E x = q.poll();
+ assert x != null;
+ if (q.size() != 0)
+ available.signalAll();
+ return x;
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Retrieves and removes the head of this queue, waiting if necessary
+ * until an element with an expired delay is available on this queue.
+ *
+ * @return the head of this queue
+ * @throws InterruptedException {@inheritDoc}
+ */
+ public E take() throws InterruptedException {
+ final ReentrantLock lock = this.lock;
+ lock.lockInterruptibly();
+ try {
+ for (;;) {
+ E first = q.peek();
+ if (first == null) {
+ available.await();
+ } else {
+ long delay = first.getDelay(TimeUnit.NANOSECONDS);
+ if (delay > 0) {
+ long tl = available.awaitNanos(delay);
+ } else {
+ E x = q.poll();
+ assert x != null;
+ if (q.size() != 0)
+ available.signalAll(); // wake up other takers
+ return x;
+
+ }
+ }
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Retrieves and removes the head of this queue, waiting if necessary
+ * until an element with an expired delay is available on this queue,
+ * or the specified wait time expires.
+ *
+ * @return the head of this queue, or <tt>null</tt> if the
+ * specified waiting time elapses before an element with
+ * an expired delay becomes available
+ * @throws InterruptedException {@inheritDoc}
+ */
+ public E poll(long timeout, TimeUnit unit) throws InterruptedException {
+ long nanos = unit.toNanos(timeout);
+ final ReentrantLock lock = this.lock;
+ lock.lockInterruptibly();
+ try {
+ for (;;) {
+ E first = q.peek();
+ if (first == null) {
+ if (nanos <= 0)
+ return null;
+ else
+ nanos = available.awaitNanos(nanos);
+ } else {
+ long delay = first.getDelay(TimeUnit.NANOSECONDS);
+ if (delay > 0) {
+ if (nanos <= 0)
+ return null;
+ if (delay > nanos)
+ delay = nanos;
+ long timeLeft = available.awaitNanos(delay);
+ nanos -= delay - timeLeft;
+ } else {
+ E x = q.poll();
+ assert x != null;
+ if (q.size() != 0)
+ available.signalAll();
+ return x;
+ }
+ }
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Retrieves, but does not remove, the head of this queue, or
+ * returns <tt>null</tt> if this queue is empty. Unlike
+ * <tt>poll</tt>, if no expired elements are available in the queue,
+ * this method returns the element that will expire next,
+ * if one exists.
+ *
+ * @return the head of this queue, or <tt>null</tt> if this
+ * queue is empty.
+ */
+ public E peek() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return q.peek();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public int size() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return q.size();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws UnsupportedOperationException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public int drainTo(Collection<? super E> c) {
+ if (c == null)
+ throw new NullPointerException();
+ if (c == this)
+ throw new IllegalArgumentException();
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ int n = 0;
+ for (;;) {
+ E first = q.peek();
+ if (first == null || first.getDelay(TimeUnit.NANOSECONDS) > 0)
+ break;
+ c.add(q.poll());
+ ++n;
+ }
+ if (n > 0)
+ available.signalAll();
+ return n;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @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();
+ if (maxElements <= 0)
+ return 0;
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ int n = 0;
+ while (n < maxElements) {
+ E first = q.peek();
+ if (first == null || first.getDelay(TimeUnit.NANOSECONDS) > 0)
+ break;
+ c.add(q.poll());
+ ++n;
+ }
+ if (n > 0)
+ available.signalAll();
+ return n;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Atomically removes all of the elements from this delay queue.
+ * The queue will be empty after this call returns.
+ * Elements with an unexpired delay are not waited for; they are
+ * simply discarded from the queue.
+ */
+ public void clear() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ q.clear();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Always returns <tt>Integer.MAX_VALUE</tt> because
+ * a <tt>DelayQueue</tt> is not capacity constrained.
+ *
+ * @return <tt>Integer.MAX_VALUE</tt>
+ */
+ public int remainingCapacity() {
+ return Integer.MAX_VALUE;
+ }
+
+ /**
+ * Returns an array containing all of the elements in this queue.
+ * The returned array elements are in no particular order.
+ *
+ * <p>The returned array will be "safe" in that no references to it are
+ * maintained by this queue. (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 queue
+ */
+ public Object[] toArray() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return q.toArray();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns an array containing all of the elements in this queue; the
+ * runtime type of the returned array is that of the specified array.
+ * The returned array elements are in no particular order.
+ * If the queue 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 queue.
+ *
+ * <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>.
+ *
+ * <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>The following code can be used to dump a delay queue into a newly
+ * allocated array of <tt>Delayed</tt>:
+ *
+ * <pre>
+ * Delayed[] a = q.toArray(new Delayed[0]);</pre>
+ *
+ * Note that <tt>toArray(new Object[0])</tt> is identical in function to
+ * <tt>toArray()</tt>.
+ *
+ * @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
+ * same runtime type is allocated for this purpose
+ * @return an array containing all of the elements in this queue
+ * @throws ArrayStoreException if the runtime type of the specified array
+ * is not a supertype of the runtime type of every element in
+ * this queue
+ * @throws NullPointerException if the specified array is null
+ */
+ public <T> T[] toArray(T[] a) {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return q.toArray(a);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Removes a single instance of the specified element from this
+ * queue, if it is present, whether or not it has expired.
+ */
+ public boolean remove(Object o) {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return q.remove(o);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns an iterator over all the elements (both expired and
+ * unexpired) in this queue. The iterator does not return the
+ * elements in any particular order. The returned
+ * <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.
+ *
+ * @return an iterator over the elements in this queue
+ */
+ public Iterator<E> iterator() {
+ return new Itr(toArray());
+ }
+
+ /**
+ * Snapshot iterator that works off copy of underlying q array.
+ */
+ private class Itr implements Iterator<E> {
+ final Object[] array; // Array of all elements
+ int cursor; // index of next element to return;
+ int lastRet; // index of last element, or -1 if no such
+
+ Itr(Object[] array) {
+ lastRet = -1;
+ this.array = array;
+ }
+
+ public boolean hasNext() {
+ return cursor < array.length;
+ }
+
+ public E next() {
+ if (cursor >= array.length)
+ throw new NoSuchElementException();
+ lastRet = cursor;
+ return (E)array[cursor++];
+ }
+
+ public void remove() {
+ if (lastRet < 0)
+ throw new IllegalStateException();
+ Object x = array[lastRet];
+ lastRet = -1;
+ // Traverse underlying queue to find == element,
+ // not just a .equals element.
+ lock.lock();
+ try {
+ for (Iterator it = q.iterator(); it.hasNext(); ) {
+ if (it.next() == x) {
+ it.remove();
+ return;
+ }
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+ }
+
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/Delayed.java b/libjava/classpath/external/jsr166/java/util/concurrent/Delayed.java
new file mode 100644
index 000000000..b1ff4eee5
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/Delayed.java
@@ -0,0 +1,33 @@
+/*
+ * 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 mix-in style interface for marking objects that should be
+ * acted upon after a given delay.
+ *
+ * <p>An implementation of this interface must define a
+ * <tt>compareTo</tt> method that provides an ordering consistent with
+ * its <tt>getDelay</tt> method.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public interface Delayed extends Comparable<Delayed> {
+
+ /**
+ * Returns the remaining delay associated with this object, in the
+ * given time unit.
+ *
+ * @param unit the time unit
+ * @return the remaining delay; zero or negative values indicate
+ * that the delay has already elapsed
+ */
+ long getDelay(TimeUnit unit);
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/Exchanger.java b/libjava/classpath/external/jsr166/java/util/concurrent/Exchanger.java
new file mode 100644
index 000000000..fb917f432
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/Exchanger.java
@@ -0,0 +1,656 @@
+/*
+ * Written by Doug Lea, Bill Scherer, and Michael Scott 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.concurrent.atomic.*;
+import java.util.concurrent.locks.LockSupport;
+
+/**
+ * A synchronization point at which threads can pair and swap elements
+ * within pairs. Each thread presents some object on entry to the
+ * {@link #exchange exchange} method, matches with a partner thread,
+ * and receives its partner's object on return. An Exchanger may be
+ * viewed as a bidirectional form of a {@link SynchronousQueue}.
+ * Exchangers may be useful in applications such as genetic algorithms
+ * and pipeline designs.
+ *
+ * <p><b>Sample Usage:</b>
+ * Here are the highlights of a class that uses an {@code Exchanger}
+ * to swap buffers between threads so that the thread filling the
+ * buffer gets a freshly emptied one when it needs it, handing off the
+ * filled one to the thread emptying the buffer.
+ * <pre>{@code
+ * class FillAndEmpty {
+ * Exchanger<DataBuffer> exchanger = new Exchanger<DataBuffer>();
+ * DataBuffer initialEmptyBuffer = ... a made-up type
+ * DataBuffer initialFullBuffer = ...
+ *
+ * class FillingLoop implements Runnable {
+ * public void run() {
+ * DataBuffer currentBuffer = initialEmptyBuffer;
+ * try {
+ * while (currentBuffer != null) {
+ * addToBuffer(currentBuffer);
+ * if (currentBuffer.isFull())
+ * currentBuffer = exchanger.exchange(currentBuffer);
+ * }
+ * } catch (InterruptedException ex) { ... handle ... }
+ * }
+ * }
+ *
+ * class EmptyingLoop implements Runnable {
+ * public void run() {
+ * DataBuffer currentBuffer = initialFullBuffer;
+ * try {
+ * while (currentBuffer != null) {
+ * takeFromBuffer(currentBuffer);
+ * if (currentBuffer.isEmpty())
+ * currentBuffer = exchanger.exchange(currentBuffer);
+ * }
+ * } catch (InterruptedException ex) { ... handle ...}
+ * }
+ * }
+ *
+ * void start() {
+ * new Thread(new FillingLoop()).start();
+ * new Thread(new EmptyingLoop()).start();
+ * }
+ * }
+ * }</pre>
+ *
+ * <p>Memory consistency effects: For each pair of threads that
+ * successfully exchange objects via an {@code Exchanger}, actions
+ * prior to the {@code exchange()} in each thread
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * those subsequent to a return from the corresponding {@code exchange()}
+ * in the other thread.
+ *
+ * @since 1.5
+ * @author Doug Lea and Bill Scherer and Michael Scott
+ * @param <V> The type of objects that may be exchanged
+ */
+public class Exchanger<V> {
+ /*
+ * Algorithm Description:
+ *
+ * The basic idea is to maintain a "slot", which is a reference to
+ * a Node containing both an Item to offer and a "hole" waiting to
+ * get filled in. If an incoming "occupying" thread sees that the
+ * slot is null, it CAS'es (compareAndSets) a Node there and waits
+ * for another to invoke exchange. That second "fulfilling" thread
+ * sees that the slot is non-null, and so CASes it back to null,
+ * also exchanging items by CASing the hole, plus waking up the
+ * occupying thread if it is blocked. In each case CAS'es may
+ * fail because a slot at first appears non-null but is null upon
+ * CAS, or vice-versa. So threads may need to retry these
+ * actions.
+ *
+ * This simple approach works great when there are only a few
+ * threads using an Exchanger, but performance rapidly
+ * deteriorates due to CAS contention on the single slot when
+ * there are lots of threads using an exchanger. So instead we use
+ * an "arena"; basically a kind of hash table with a dynamically
+ * varying number of slots, any one of which can be used by
+ * threads performing an exchange. Incoming threads pick slots
+ * based on a hash of their Thread ids. If an incoming thread
+ * fails to CAS in its chosen slot, it picks an alternative slot
+ * instead. And similarly from there. If a thread successfully
+ * CASes into a slot but no other thread arrives, it tries
+ * another, heading toward the zero slot, which always exists even
+ * if the table shrinks. The particular mechanics controlling this
+ * are as follows:
+ *
+ * Waiting: Slot zero is special in that it is the only slot that
+ * exists when there is no contention. A thread occupying slot
+ * zero will block if no thread fulfills it after a short spin.
+ * In other cases, occupying threads eventually give up and try
+ * another slot. Waiting threads spin for a while (a period that
+ * should be a little less than a typical context-switch time)
+ * before either blocking (if slot zero) or giving up (if other
+ * slots) and restarting. There is no reason for threads to block
+ * unless there are unlikely to be any other threads present.
+ * Occupants are mainly avoiding memory contention so sit there
+ * quietly polling for a shorter period than it would take to
+ * block and then unblock them. Non-slot-zero waits that elapse
+ * because of lack of other threads waste around one extra
+ * context-switch time per try, which is still on average much
+ * faster than alternative approaches.
+ *
+ * Sizing: Usually, using only a few slots suffices to reduce
+ * contention. Especially with small numbers of threads, using
+ * too many slots can lead to just as poor performance as using
+ * too few of them, and there's not much room for error. The
+ * variable "max" maintains the number of slots actually in
+ * use. It is increased when a thread sees too many CAS
+ * failures. (This is analogous to resizing a regular hash table
+ * based on a target load factor, except here, growth steps are
+ * just one-by-one rather than proportional.) Growth requires
+ * contention failures in each of three tried slots. Requiring
+ * multiple failures for expansion copes with the fact that some
+ * failed CASes are not due to contention but instead to simple
+ * races between two threads or thread pre-emptions occurring
+ * between reading and CASing. Also, very transient peak
+ * contention can be much higher than the average sustainable
+ * levels. The max limit is decreased on average 50% of the times
+ * that a non-slot-zero wait elapses without being fulfilled.
+ * Threads experiencing elapsed waits move closer to zero, so
+ * eventually find existing (or future) threads even if the table
+ * has been shrunk due to inactivity. The chosen mechanics and
+ * thresholds for growing and shrinking are intrinsically
+ * entangled with indexing and hashing inside the exchange code,
+ * and can't be nicely abstracted out.
+ *
+ * Hashing: Each thread picks its initial slot to use in accord
+ * with a simple hashcode. The sequence is the same on each
+ * encounter by any given thread, but effectively random across
+ * threads. Using arenas encounters the classic cost vs quality
+ * tradeoffs of all hash tables. Here, we use a one-step FNV-1a
+ * hash code based on the current thread's Thread.getId(), along
+ * with a cheap approximation to a mod operation to select an
+ * index. The downside of optimizing index selection in this way
+ * is that the code is hardwired to use a maximum table size of
+ * 32. But this value more than suffices for known platforms and
+ * applications.
+ *
+ * Probing: On sensed contention of a selected slot, we probe
+ * sequentially through the table, analogously to linear probing
+ * after collision in a hash table. (We move circularly, in
+ * reverse order, to mesh best with table growth and shrinkage
+ * rules.) Except that to minimize the effects of false-alarms
+ * and cache thrashing, we try the first selected slot twice
+ * before moving.
+ *
+ * Padding: Even with contention management, slots are heavily
+ * contended, so use cache-padding to avoid poor memory
+ * performance. Because of this, slots are lazily constructed
+ * only when used, to avoid wasting this space unnecessarily.
+ * While isolation of locations is not much of an issue at first
+ * in an application, as time goes on and garbage-collectors
+ * perform compaction, slots are very likely to be moved adjacent
+ * to each other, which can cause much thrashing of cache lines on
+ * MPs unless padding is employed.
+ *
+ * This is an improvement of the algorithm described in the paper
+ * "A Scalable Elimination-based Exchange Channel" by William
+ * Scherer, Doug Lea, and Michael Scott in Proceedings of SCOOL05
+ * workshop. Available at: http://hdl.handle.net/1802/2104
+ */
+
+ /** The number of CPUs, for sizing and spin control */
+ private static final int NCPU = Runtime.getRuntime().availableProcessors();
+
+ /**
+ * The capacity of the arena. Set to a value that provides more
+ * than enough space to handle contention. On small machines
+ * most slots won't be used, but it is still not wasted because
+ * the extra space provides some machine-level address padding
+ * to minimize interference with heavily CAS'ed Slot locations.
+ * And on very large machines, performance eventually becomes
+ * bounded by memory bandwidth, not numbers of threads/CPUs.
+ * This constant cannot be changed without also modifying
+ * indexing and hashing algorithms.
+ */
+ private static final int CAPACITY = 32;
+
+ /**
+ * The value of "max" that will hold all threads without
+ * contention. When this value is less than CAPACITY, some
+ * otherwise wasted expansion can be avoided.
+ */
+ private static final int FULL =
+ Math.max(0, Math.min(CAPACITY, NCPU / 2) - 1);
+
+ /**
+ * The number of times to spin (doing nothing except polling a
+ * memory location) before blocking or giving up while waiting to
+ * be fulfilled. Should be zero on uniprocessors. On
+ * multiprocessors, this value should be large enough so that two
+ * threads exchanging items as fast as possible block only when
+ * one of them is stalled (due to GC or preemption), but not much
+ * longer, to avoid wasting CPU resources. Seen differently, this
+ * value is a little over half the number of cycles of an average
+ * context switch time on most systems. The value here is
+ * approximately the average of those across a range of tested
+ * systems.
+ */
+ private static final int SPINS = (NCPU == 1) ? 0 : 2000;
+
+ /**
+ * The number of times to spin before blocking in timed waits.
+ * Timed waits spin more slowly because checking the time takes
+ * time. The best value relies mainly on the relative rate of
+ * System.nanoTime vs memory accesses. The value is empirically
+ * derived to work well across a variety of systems.
+ */
+ private static final int TIMED_SPINS = SPINS / 20;
+
+ /**
+ * Sentinel item representing cancellation of a wait due to
+ * interruption, timeout, or elapsed spin-waits. This value is
+ * placed in holes on cancellation, and used as a return value
+ * from waiting methods to indicate failure to set or get hole.
+ */
+ private static final Object CANCEL = new Object();
+
+ /**
+ * Value representing null arguments/returns from public
+ * methods. This disambiguates from internal requirement that
+ * holes start out as null to mean they are not yet set.
+ */
+ private static final Object NULL_ITEM = new Object();
+
+ /**
+ * Nodes hold partially exchanged data. This class
+ * opportunistically subclasses AtomicReference to represent the
+ * hole. So get() returns hole, and compareAndSet CAS'es value
+ * into hole. This class cannot be parameterized as "V" because
+ * of the use of non-V CANCEL sentinels.
+ */
+ private static final class Node extends AtomicReference<Object> {
+ /** The element offered by the Thread creating this node. */
+ public final Object item;
+
+ /** The Thread waiting to be signalled; null until waiting. */
+ public volatile Thread waiter;
+
+ /**
+ * Creates node with given item and empty hole.
+ * @param item the item
+ */
+ public Node(Object item) {
+ this.item = item;
+ }
+ }
+
+ /**
+ * A Slot is an AtomicReference with heuristic padding to lessen
+ * cache effects of this heavily CAS'ed location. While the
+ * padding adds noticeable space, all slots are created only on
+ * demand, and there will be more than one of them only when it
+ * would improve throughput more than enough to outweigh using
+ * extra space.
+ */
+ private static final class Slot extends AtomicReference<Object> {
+ // Improve likelihood of isolation on <= 64 byte cache lines
+ long q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, qa, qb, qc, qd, qe;
+ }
+
+ /**
+ * Slot array. Elements are lazily initialized when needed.
+ * Declared volatile to enable double-checked lazy construction.
+ */
+ private volatile Slot[] arena = new Slot[CAPACITY];
+
+ /**
+ * The maximum slot index being used. The value sometimes
+ * increases when a thread experiences too many CAS contentions,
+ * and sometimes decreases when a spin-wait elapses. Changes
+ * are performed only via compareAndSet, to avoid stale values
+ * when a thread happens to stall right before setting.
+ */
+ private final AtomicInteger max = new AtomicInteger();
+
+ /**
+ * Main exchange function, handling the different policy variants.
+ * Uses Object, not "V" as argument and return value to simplify
+ * handling of sentinel values. Callers from public methods decode
+ * and cast accordingly.
+ *
+ * @param item the (non-null) item to exchange
+ * @param timed true if the wait is timed
+ * @param nanos if timed, the maximum wait time
+ * @return the other thread's item, or CANCEL if interrupted or timed out
+ */
+ private Object doExchange(Object item, boolean timed, long nanos) {
+ Node me = new Node(item); // Create in case occupying
+ int index = hashIndex(); // Index of current slot
+ int fails = 0; // Number of CAS failures
+
+ for (;;) {
+ Object y; // Contents of current slot
+ Slot slot = arena[index];
+ if (slot == null) // Lazily initialize slots
+ createSlot(index); // Continue loop to reread
+ else if ((y = slot.get()) != null && // Try to fulfill
+ slot.compareAndSet(y, null)) {
+ Node you = (Node)y; // Transfer item
+ if (you.compareAndSet(null, item)) {
+ LockSupport.unpark(you.waiter);
+ return you.item;
+ } // Else cancelled; continue
+ }
+ else if (y == null && // Try to occupy
+ slot.compareAndSet(null, me)) {
+ if (index == 0) // Blocking wait for slot 0
+ return timed? awaitNanos(me, slot, nanos): await(me, slot);
+ Object v = spinWait(me, slot); // Spin wait for non-0
+ if (v != CANCEL)
+ return v;
+ me = new Node(item); // Throw away cancelled node
+ int m = max.get();
+ if (m > (index >>>= 1)) // Decrease index
+ max.compareAndSet(m, m - 1); // Maybe shrink table
+ }
+ else if (++fails > 1) { // Allow 2 fails on 1st slot
+ int m = max.get();
+ if (fails > 3 && m < FULL && max.compareAndSet(m, m + 1))
+ index = m + 1; // Grow on 3rd failed slot
+ else if (--index < 0)
+ index = m; // Circularly traverse
+ }
+ }
+ }
+
+ /**
+ * Returns a hash index for the current thread. Uses a one-step
+ * FNV-1a hash code (http://www.isthe.com/chongo/tech/comp/fnv/)
+ * based on the current thread's Thread.getId(). These hash codes
+ * have more uniform distribution properties with respect to small
+ * moduli (here 1-31) than do other simple hashing functions.
+ *
+ * <p>To return an index between 0 and max, we use a cheap
+ * approximation to a mod operation, that also corrects for bias
+ * due to non-power-of-2 remaindering (see {@link
+ * java.util.Random#nextInt}). Bits of the hashcode are masked
+ * with "nbits", the ceiling power of two of table size (looked up
+ * in a table packed into three ints). If too large, this is
+ * retried after rotating the hash by nbits bits, while forcing new
+ * top bit to 0, which guarantees eventual termination (although
+ * with a non-random-bias). This requires an average of less than
+ * 2 tries for all table sizes, and has a maximum 2% difference
+ * from perfectly uniform slot probabilities when applied to all
+ * possible hash codes for sizes less than 32.
+ *
+ * @return a per-thread-random index, 0 <= index < max
+ */
+ private final int hashIndex() {
+ long id = Thread.currentThread().getId();
+ int hash = (((int)(id ^ (id >>> 32))) ^ 0x811c9dc5) * 0x01000193;
+
+ int m = max.get();
+ int nbits = (((0xfffffc00 >> m) & 4) | // Compute ceil(log2(m+1))
+ ((0x000001f8 >>> m) & 2) | // The constants hold
+ ((0xffff00f2 >>> m) & 1)); // a lookup table
+ int index;
+ while ((index = hash & ((1 << nbits) - 1)) > m) // May retry on
+ hash = (hash >>> nbits) | (hash << (33 - nbits)); // non-power-2 m
+ return index;
+ }
+
+ /**
+ * Creates a new slot at given index. Called only when the slot
+ * appears to be null. Relies on double-check using builtin
+ * locks, since they rarely contend. This in turn relies on the
+ * arena array being declared volatile.
+ *
+ * @param index the index to add slot at
+ */
+ private void createSlot(int index) {
+ // Create slot outside of lock to narrow sync region
+ Slot newSlot = new Slot();
+ Slot[] a = arena;
+ synchronized (a) {
+ if (a[index] == null)
+ a[index] = newSlot;
+ }
+ }
+
+ /**
+ * Tries to cancel a wait for the given node waiting in the given
+ * slot, if so, helping clear the node from its slot to avoid
+ * garbage retention.
+ *
+ * @param node the waiting node
+ * @param the slot it is waiting in
+ * @return true if successfully cancelled
+ */
+ private static boolean tryCancel(Node node, Slot slot) {
+ if (!node.compareAndSet(null, CANCEL))
+ return false;
+ if (slot.get() == node) // pre-check to minimize contention
+ slot.compareAndSet(node, null);
+ return true;
+ }
+
+ // Three forms of waiting. Each just different enough not to merge
+ // code with others.
+
+ /**
+ * Spin-waits for hole for a non-0 slot. Fails if spin elapses
+ * before hole filled. Does not check interrupt, relying on check
+ * in public exchange method to abort if interrupted on entry.
+ *
+ * @param node the waiting node
+ * @return on success, the hole; on failure, CANCEL
+ */
+ private static Object spinWait(Node node, Slot slot) {
+ int spins = SPINS;
+ for (;;) {
+ Object v = node.get();
+ if (v != null)
+ return v;
+ else if (spins > 0)
+ --spins;
+ else
+ tryCancel(node, slot);
+ }
+ }
+
+ /**
+ * Waits for (by spinning and/or blocking) and gets the hole
+ * filled in by another thread. Fails if interrupted before
+ * hole filled.
+ *
+ * When a node/thread is about to block, it sets its waiter field
+ * and then rechecks state at least one more time before actually
+ * parking, thus covering race vs fulfiller noticing that waiter
+ * is non-null so should be woken.
+ *
+ * Thread interruption status is checked only surrounding calls to
+ * park. The caller is assumed to have checked interrupt status
+ * on entry.
+ *
+ * @param node the waiting node
+ * @return on success, the hole; on failure, CANCEL
+ */
+ private static Object await(Node node, Slot slot) {
+ Thread w = Thread.currentThread();
+ int spins = SPINS;
+ for (;;) {
+ Object v = node.get();
+ if (v != null)
+ return v;
+ else if (spins > 0) // Spin-wait phase
+ --spins;
+ else if (node.waiter == null) // Set up to block next
+ node.waiter = w;
+ else if (w.isInterrupted()) // Abort on interrupt
+ tryCancel(node, slot);
+ else // Block
+ LockSupport.park(node);
+ }
+ }
+
+ /**
+ * Waits for (at index 0) and gets the hole filled in by another
+ * thread. Fails if timed out or interrupted before hole filled.
+ * Same basic logic as untimed version, but a bit messier.
+ *
+ * @param node the waiting node
+ * @param nanos the wait time
+ * @return on success, the hole; on failure, CANCEL
+ */
+ private Object awaitNanos(Node node, Slot slot, long nanos) {
+ int spins = TIMED_SPINS;
+ long lastTime = 0;
+ Thread w = null;
+ for (;;) {
+ Object v = node.get();
+ if (v != null)
+ return v;
+ long now = System.nanoTime();
+ if (w == null)
+ w = Thread.currentThread();
+ else
+ nanos -= now - lastTime;
+ lastTime = now;
+ if (nanos > 0) {
+ if (spins > 0)
+ --spins;
+ else if (node.waiter == null)
+ node.waiter = w;
+ else if (w.isInterrupted())
+ tryCancel(node, slot);
+ else
+ LockSupport.parkNanos(node, nanos);
+ }
+ else if (tryCancel(node, slot) && !w.isInterrupted())
+ return scanOnTimeout(node);
+ }
+ }
+
+ /**
+ * Sweeps through arena checking for any waiting threads. Called
+ * only upon return from timeout while waiting in slot 0. When a
+ * thread gives up on a timed wait, it is possible that a
+ * previously-entered thread is still waiting in some other
+ * slot. So we scan to check for any. This is almost always
+ * overkill, but decreases the likelihood of timeouts when there
+ * are other threads present to far less than that in lock-based
+ * exchangers in which earlier-arriving threads may still be
+ * waiting on entry locks.
+ *
+ * @param node the waiting node
+ * @return another thread's item, or CANCEL
+ */
+ private Object scanOnTimeout(Node node) {
+ Object y;
+ for (int j = arena.length - 1; j >= 0; --j) {
+ Slot slot = arena[j];
+ if (slot != null) {
+ while ((y = slot.get()) != null) {
+ if (slot.compareAndSet(y, null)) {
+ Node you = (Node)y;
+ if (you.compareAndSet(null, node.item)) {
+ LockSupport.unpark(you.waiter);
+ return you.item;
+ }
+ }
+ }
+ }
+ }
+ return CANCEL;
+ }
+
+ /**
+ * Creates a new Exchanger.
+ */
+ public Exchanger() {
+ }
+
+ /**
+ * Waits for another thread to arrive at this exchange point (unless
+ * the current thread is {@linkplain Thread#interrupt interrupted}),
+ * and then transfers the given object to it, receiving its object
+ * in return.
+ *
+ * <p>If another thread is already waiting at the exchange point then
+ * it is resumed for thread scheduling purposes and receives the object
+ * passed in by the current thread. The current thread returns immediately,
+ * receiving the object passed to the exchange by that other thread.
+ *
+ * <p>If no other thread is already waiting at the exchange then the
+ * current thread is disabled for thread scheduling purposes and lies
+ * dormant until one of two things happens:
+ * <ul>
+ * <li>Some other thread enters the exchange; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts} the current
+ * thread.
+ * </ul>
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+ * for the exchange,
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ *
+ * @param x the object to exchange
+ * @return the object provided by the other thread
+ * @throws InterruptedException if the current thread was
+ * interrupted while waiting
+ */
+ public V exchange(V x) throws InterruptedException {
+ if (!Thread.interrupted()) {
+ Object v = doExchange(x == null? NULL_ITEM : x, false, 0);
+ if (v == NULL_ITEM)
+ return null;
+ if (v != CANCEL)
+ return (V)v;
+ Thread.interrupted(); // Clear interrupt status on IE throw
+ }
+ throw new InterruptedException();
+ }
+
+ /**
+ * Waits for another thread to arrive at this exchange point (unless
+ * the current thread is {@linkplain Thread#interrupt interrupted} or
+ * the specified waiting time elapses), and then transfers the given
+ * object to it, receiving its object in return.
+ *
+ * <p>If another thread is already waiting at the exchange point then
+ * it is resumed for thread scheduling purposes and receives the object
+ * passed in by the current thread. The current thread returns immediately,
+ * receiving the object passed to the exchange by that other thread.
+ *
+ * <p>If no other thread is already waiting at the exchange then the
+ * current thread is disabled for thread scheduling purposes and lies
+ * dormant until one of three things happens:
+ * <ul>
+ * <li>Some other thread enters the exchange; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread; or
+ * <li>The specified waiting time elapses.
+ * </ul>
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+ * for the exchange,
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ *
+ * <p>If the specified waiting time elapses then {@link
+ * TimeoutException} is thrown. If the time is less than or equal
+ * to zero, the method will not wait at all.
+ *
+ * @param x the object to exchange
+ * @param timeout the maximum time to wait
+ * @param unit the time unit of the <tt>timeout</tt> argument
+ * @return the object provided by the other thread
+ * @throws InterruptedException if the current thread was
+ * interrupted while waiting
+ * @throws TimeoutException if the specified waiting time elapses
+ * before another thread enters the exchange
+ */
+ public V exchange(V x, long timeout, TimeUnit unit)
+ throws InterruptedException, TimeoutException {
+ if (!Thread.interrupted()) {
+ Object v = doExchange(x == null? NULL_ITEM : x,
+ true, unit.toNanos(timeout));
+ if (v == NULL_ITEM)
+ return null;
+ if (v != CANCEL)
+ return (V)v;
+ if (!Thread.interrupted())
+ throw new TimeoutException();
+ }
+ throw new InterruptedException();
+ }
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/ExecutionException.java b/libjava/classpath/external/jsr166/java/util/concurrent/ExecutionException.java
new file mode 100644
index 000000000..bc561e58e
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/ExecutionException.java
@@ -0,0 +1,65 @@
+/*
+ * 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;
+
+/**
+ * Exception thrown when attempting to retrieve the result of a task
+ * that aborted by throwing an exception. This exception can be
+ * inspected using the {@link #getCause()} method.
+ *
+ * @see Future
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class ExecutionException extends Exception {
+ private static final long serialVersionUID = 7830266012832686185L;
+
+ /**
+ * Constructs an <tt>ExecutionException</tt> with no detail message.
+ * The cause is not initialized, and may subsequently be
+ * initialized by a call to {@link #initCause(Throwable) initCause}.
+ */
+ protected ExecutionException() { }
+
+ /**
+ * Constructs an <tt>ExecutionException</tt> with the specified detail
+ * message. The cause is not initialized, and may subsequently be
+ * initialized by a call to {@link #initCause(Throwable) initCause}.
+ *
+ * @param message the detail message
+ */
+ protected ExecutionException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs an <tt>ExecutionException</tt> with the specified detail
+ * message and cause.
+ *
+ * @param message the detail message
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method)
+ */
+ public ExecutionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Constructs an <tt>ExecutionException</tt> with the specified cause.
+ * The detail message is set to:
+ * <pre>
+ * (cause == null ? null : cause.toString())</pre>
+ * (which typically contains the class and detail message of
+ * <tt>cause</tt>).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method)
+ */
+ public ExecutionException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/Executor.java b/libjava/classpath/external/jsr166/java/util/concurrent/Executor.java
new file mode 100644
index 000000000..a61e92152
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/Executor.java
@@ -0,0 +1,112 @@
+/*
+ * 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;
+
+/**
+ * An object that executes submitted {@link Runnable} tasks. This
+ * interface provides a way of decoupling task submission from the
+ * mechanics of how each task will be run, including details of thread
+ * use, scheduling, etc. An <tt>Executor</tt> is normally used
+ * instead of explicitly creating threads. For example, rather than
+ * invoking <tt>new Thread(new(RunnableTask())).start()</tt> for each
+ * of a set of tasks, you might use:
+ *
+ * <pre>
+ * Executor executor = <em>anExecutor</em>;
+ * executor.execute(new RunnableTask1());
+ * executor.execute(new RunnableTask2());
+ * ...
+ * </pre>
+ *
+ * However, the <tt>Executor</tt> interface does not strictly
+ * require that execution be asynchronous. In the simplest case, an
+ * executor can run the submitted task immediately in the caller's
+ * thread:
+ *
+ * <pre>
+ * class DirectExecutor implements Executor {
+ * public void execute(Runnable r) {
+ * r.run();
+ * }
+ * }</pre>
+ *
+ * More typically, tasks are executed in some thread other
+ * than the caller's thread. The executor below spawns a new thread
+ * for each task.
+ *
+ * <pre>
+ * class ThreadPerTaskExecutor implements Executor {
+ * public void execute(Runnable r) {
+ * new Thread(r).start();
+ * }
+ * }</pre>
+ *
+ * Many <tt>Executor</tt> implementations impose some sort of
+ * limitation on how and when tasks are scheduled. The executor below
+ * serializes the submission of tasks to a second executor,
+ * illustrating a composite executor.
+ *
+ * <pre>
+ * class SerialExecutor implements Executor {
+ * final Queue&lt;Runnable&gt; tasks = new ArrayDeque&lt;Runnable&gt;();
+ * final Executor executor;
+ * Runnable active;
+ *
+ * SerialExecutor(Executor executor) {
+ * this.executor = executor;
+ * }
+ *
+ * public synchronized void execute(final Runnable r) {
+ * tasks.offer(new Runnable() {
+ * public void run() {
+ * try {
+ * r.run();
+ * } finally {
+ * scheduleNext();
+ * }
+ * }
+ * });
+ * if (active == null) {
+ * scheduleNext();
+ * }
+ * }
+ *
+ * protected synchronized void scheduleNext() {
+ * if ((active = tasks.poll()) != null) {
+ * executor.execute(active);
+ * }
+ * }
+ * }</pre>
+ *
+ * The <tt>Executor</tt> implementations provided in this package
+ * implement {@link ExecutorService}, which is a more extensive
+ * interface. The {@link ThreadPoolExecutor} class provides an
+ * extensible thread pool implementation. The {@link Executors} class
+ * provides convenient factory methods for these Executors.
+ *
+ * <p>Memory consistency effects: Actions in a thread prior to
+ * submitting a {@code Runnable} object to an {@code Executor}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * its execution begins, perhaps in another thread.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public interface Executor {
+
+ /**
+ * Executes the given command at some time in the future. The command
+ * may execute in a new thread, in a pooled thread, or in the calling
+ * thread, at the discretion of the <tt>Executor</tt> implementation.
+ *
+ * @param command the runnable task
+ * @throws RejectedExecutionException if this task cannot be
+ * accepted for execution.
+ * @throws NullPointerException if command is null
+ */
+ void execute(Runnable command);
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/ExecutorCompletionService.java b/libjava/classpath/external/jsr166/java/util/concurrent/ExecutorCompletionService.java
new file mode 100644
index 000000000..9b7a0e027
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/ExecutorCompletionService.java
@@ -0,0 +1,174 @@
+/*
+ * 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 CompletionService} that uses a supplied {@link Executor}
+ * to execute tasks. This class arranges that submitted tasks are,
+ * upon completion, placed on a queue accessible using <tt>take</tt>.
+ * The class is lightweight enough to be suitable for transient use
+ * when processing groups of tasks.
+ *
+ * <p>
+ *
+ * <b>Usage Examples.</b>
+ *
+ * Suppose you have a set of solvers for a certain problem, each
+ * returning a value of some type <tt>Result</tt>, and would like to
+ * run them concurrently, processing the results of each of them that
+ * return a non-null value, in some method <tt>use(Result r)</tt>. You
+ * could write this as:
+ *
+ * <pre>
+ * void solve(Executor e,
+ * Collection&lt;Callable&lt;Result&gt;&gt; solvers)
+ * throws InterruptedException, ExecutionException {
+ * CompletionService&lt;Result&gt; ecs
+ * = new ExecutorCompletionService&lt;Result&gt;(e);
+ * for (Callable&lt;Result&gt; s : solvers)
+ * ecs.submit(s);
+ * int n = solvers.size();
+ * for (int i = 0; i &lt; n; ++i) {
+ * Result r = ecs.take().get();
+ * if (r != null)
+ * use(r);
+ * }
+ * }
+ * </pre>
+ *
+ * Suppose instead that you would like to use the first non-null result
+ * of the set of tasks, ignoring any that encounter exceptions,
+ * and cancelling all other tasks when the first one is ready:
+ *
+ * <pre>
+ * void solve(Executor e,
+ * Collection&lt;Callable&lt;Result&gt;&gt; solvers)
+ * throws InterruptedException {
+ * CompletionService&lt;Result&gt; ecs
+ * = new ExecutorCompletionService&lt;Result&gt;(e);
+ * int n = solvers.size();
+ * List&lt;Future&lt;Result&gt;&gt; futures
+ * = new ArrayList&lt;Future&lt;Result&gt;&gt;(n);
+ * Result result = null;
+ * try {
+ * for (Callable&lt;Result&gt; s : solvers)
+ * futures.add(ecs.submit(s));
+ * for (int i = 0; i &lt; n; ++i) {
+ * try {
+ * Result r = ecs.take().get();
+ * if (r != null) {
+ * result = r;
+ * break;
+ * }
+ * } catch (ExecutionException ignore) {}
+ * }
+ * }
+ * finally {
+ * for (Future&lt;Result&gt; f : futures)
+ * f.cancel(true);
+ * }
+ *
+ * if (result != null)
+ * use(result);
+ * }
+ * </pre>
+ */
+public class ExecutorCompletionService<V> implements CompletionService<V> {
+ private final Executor executor;
+ private final AbstractExecutorService aes;
+ private final BlockingQueue<Future<V>> completionQueue;
+
+ /**
+ * FutureTask extension to enqueue upon completion
+ */
+ private class QueueingFuture extends FutureTask<Void> {
+ QueueingFuture(RunnableFuture<V> task) {
+ super(task, null);
+ this.task = task;
+ }
+ protected void done() { completionQueue.add(task); }
+ private final Future<V> task;
+ }
+
+ private RunnableFuture<V> newTaskFor(Callable<V> task) {
+ if (aes == null)
+ return new FutureTask<V>(task);
+ else
+ return aes.newTaskFor(task);
+ }
+
+ private RunnableFuture<V> newTaskFor(Runnable task, V result) {
+ if (aes == null)
+ return new FutureTask<V>(task, result);
+ else
+ return aes.newTaskFor(task, result);
+ }
+
+ /**
+ * Creates an ExecutorCompletionService using the supplied
+ * executor for base task execution and a
+ * {@link LinkedBlockingQueue} as a completion queue.
+ *
+ * @param executor the executor to use
+ * @throws NullPointerException if executor is <tt>null</tt>
+ */
+ public ExecutorCompletionService(Executor executor) {
+ if (executor == null)
+ throw new NullPointerException();
+ this.executor = executor;
+ this.aes = (executor instanceof AbstractExecutorService) ?
+ (AbstractExecutorService) executor : null;
+ this.completionQueue = new LinkedBlockingQueue<Future<V>>();
+ }
+
+ /**
+ * Creates an ExecutorCompletionService using the supplied
+ * executor for base task execution and the supplied queue as its
+ * completion queue.
+ *
+ * @param executor the executor to use
+ * @param completionQueue the queue to use as the completion queue
+ * normally one dedicated for use by this service
+ * @throws NullPointerException if executor or completionQueue are <tt>null</tt>
+ */
+ public ExecutorCompletionService(Executor executor,
+ BlockingQueue<Future<V>> completionQueue) {
+ if (executor == null || completionQueue == null)
+ throw new NullPointerException();
+ this.executor = executor;
+ this.aes = (executor instanceof AbstractExecutorService) ?
+ (AbstractExecutorService) executor : null;
+ this.completionQueue = completionQueue;
+ }
+
+ public Future<V> submit(Callable<V> task) {
+ if (task == null) throw new NullPointerException();
+ 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();
+ RunnableFuture<V> f = newTaskFor(task, result);
+ executor.execute(new QueueingFuture(f));
+ return f;
+ }
+
+ public Future<V> take() throws InterruptedException {
+ return completionQueue.take();
+ }
+
+ public Future<V> poll() {
+ return completionQueue.poll();
+ }
+
+ public Future<V> poll(long timeout, TimeUnit unit) throws InterruptedException {
+ return completionQueue.poll(timeout, unit);
+ }
+
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/ExecutorService.java b/libjava/classpath/external/jsr166/java/util/concurrent/ExecutorService.java
new file mode 100644
index 000000000..777319265
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/ExecutorService.java
@@ -0,0 +1,306 @@
+/*
+ * 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.List;
+import java.util.Collection;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
+
+/**
+ * An {@link Executor} that provides methods to manage termination and
+ * methods that can produce a {@link Future} for tracking progress of
+ * one or more asynchronous tasks.
+ *
+ * <p>
+ * An <tt>ExecutorService</tt> can be shut down, which will cause it
+ * to stop accepting new tasks. After being shut down, the executor
+ * will eventually terminate, at which point no tasks are actively
+ * executing, no tasks are awaiting execution, and no new tasks can be
+ * submitted. An unused <tt>ExecutorService</tt> should be shut down
+ * to allow reclamation of its resources.
+ *
+ * <p> Method <tt>submit</tt> extends base method {@link
+ * Executor#execute} by creating and returning a {@link Future} that
+ * can be used to cancel execution and/or wait for completion.
+ * Methods <tt>invokeAny</tt> and <tt>invokeAll</tt> perform the most
+ * commonly useful forms of bulk execution, executing a collection of
+ * tasks and then waiting for at least one, or all, to
+ * complete. (Class {@link ExecutorCompletionService} can be used to
+ * write customized variants of these methods.)
+ *
+ * <p>The {@link Executors} class provides factory methods for the
+ * executor services provided in this package.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * Here is a sketch of a network service in which threads in a thread
+ * pool service incoming requests. It uses the preconfigured {@link
+ * Executors#newFixedThreadPool} factory method:
+ *
+ * <pre>
+ * class NetworkService {
+ * private final ServerSocket serverSocket;
+ * private final ExecutorService pool;
+ *
+ * public NetworkService(int port, int poolSize)
+ * throws IOException {
+ * serverSocket = new ServerSocket(port);
+ * pool = Executors.newFixedThreadPool(poolSize);
+ * }
+ *
+ * public void serve() {
+ * try {
+ * for (;;) {
+ * pool.execute(new Handler(serverSocket.accept()));
+ * }
+ * } catch (IOException ex) {
+ * pool.shutdown();
+ * }
+ * }
+ * }
+ *
+ * class Handler implements Runnable {
+ * private final Socket socket;
+ * Handler(Socket socket) { this.socket = socket; }
+ * public void run() {
+ * // read and service request
+ * }
+ * }
+ * </pre>
+ *
+ * <p>Memory consistency effects: Actions in a thread prior to the
+ * submission of a {@code Runnable} or {@code Callable} task to an
+ * {@code ExecutorService}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * any actions taken by that task, which in turn <i>happen-before</i> the
+ * result is retrieved via {@code Future.get()}.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public interface ExecutorService extends Executor {
+
+ /**
+ * 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.
+ *
+ * @throws SecurityException if a security manager exists and
+ * shutting down this ExecutorService may manipulate
+ * threads that the caller is not permitted to modify
+ * because it does not hold {@link
+ * java.lang.RuntimePermission}<tt>("modifyThread")</tt>,
+ * or the security manager's <tt>checkAccess</tt> method
+ * denies access.
+ */
+ void shutdown();
+
+ /**
+ * Attempts to stop all actively executing tasks, halts the
+ * processing of waiting tasks, and returns a list of the tasks that were
+ * awaiting execution.
+ *
+ * <p>There are no guarantees beyond best-effort attempts to stop
+ * processing actively executing tasks. For example, typical
+ * implementations will cancel via {@link Thread#interrupt}, so any
+ * task that fails to respond to interrupts may never terminate.
+ *
+ * @return list of tasks that never commenced execution
+ * @throws SecurityException if a security manager exists and
+ * shutting down this ExecutorService may manipulate
+ * threads that the caller is not permitted to modify
+ * because it does not hold {@link
+ * java.lang.RuntimePermission}<tt>("modifyThread")</tt>,
+ * or the security manager's <tt>checkAccess</tt> method
+ * denies access.
+ */
+ List<Runnable> shutdownNow();
+
+ /**
+ * Returns <tt>true</tt> if this executor has been shut down.
+ *
+ * @return <tt>true</tt> if this executor has been shut down
+ */
+ boolean isShutdown();
+
+ /**
+ * Returns <tt>true</tt> if all tasks have completed following shut down.
+ * Note that <tt>isTerminated</tt> is never <tt>true</tt> unless
+ * either <tt>shutdown</tt> or <tt>shutdownNow</tt> was called first.
+ *
+ * @return <tt>true</tt> if all tasks have completed following shut down
+ */
+ boolean isTerminated();
+
+ /**
+ * Blocks until all tasks have completed execution after a shutdown
+ * request, or the timeout occurs, or the current thread is
+ * interrupted, whichever happens first.
+ *
+ * @param timeout the maximum time to wait
+ * @param unit the time unit of the timeout argument
+ * @return <tt>true</tt> if this executor terminated and
+ * <tt>false</tt> if the timeout elapsed before termination
+ * @throws InterruptedException if interrupted while waiting
+ */
+ boolean awaitTermination(long timeout, TimeUnit unit)
+ throws InterruptedException;
+
+
+ /**
+ * Submits a value-returning task for execution and returns a
+ * Future representing the pending results of the task. The
+ * Future's <tt>get</tt> method will return the task's result upon
+ * successful completion.
+ *
+ * <p>
+ * If you would like to immediately block waiting
+ * for a task, you can use constructions of the form
+ * <tt>result = exec.submit(aCallable).get();</tt>
+ *
+ * <p> Note: The {@link Executors} class includes a set of methods
+ * that can convert some other common closure-like objects,
+ * for example, {@link java.security.PrivilegedAction} to
+ * {@link Callable} form so they can be submitted.
+ *
+ * @param task the task to submit
+ * @return a Future representing pending completion of the task
+ * @throws RejectedExecutionException if the task cannot be
+ * scheduled for execution
+ * @throws NullPointerException if the task is null
+ */
+ <T> Future<T> submit(Callable<T> task);
+
+ /**
+ * Submits a Runnable task for execution and returns a Future
+ * representing that task. The Future's <tt>get</tt> method will
+ * return the given result upon successful completion.
+ *
+ * @param task the task to submit
+ * @param result the result to return
+ * @return a Future representing pending completion of the task
+ * @throws RejectedExecutionException if the task cannot be
+ * scheduled for execution
+ * @throws NullPointerException if the task is null
+ */
+ <T> Future<T> submit(Runnable task, T result);
+
+ /**
+ * Submits a Runnable task for execution and returns a Future
+ * representing that task. The Future's <tt>get</tt> method will
+ * return <tt>null</tt> upon <em>successful</em> completion.
+ *
+ * @param task the task to submit
+ * @return a Future representing pending completion of the task
+ * @throws RejectedExecutionException if the task cannot be
+ * scheduled for execution
+ * @throws NullPointerException if the task is null
+ */
+ Future<?> submit(Runnable task);
+
+ /**
+ * Executes the given tasks, returning a list of Futures holding
+ * their status and results when all complete.
+ * {@link Future#isDone} is <tt>true</tt> for each
+ * element of the returned list.
+ * Note that a <em>completed</em> task could have
+ * terminated either normally or by throwing an exception.
+ * The results of this method are undefined if the given
+ * collection is modified while this operation is in progress.
+ *
+ * @param tasks the collection of tasks
+ * @return A list of Futures representing the tasks, in the same
+ * sequential order as produced by the iterator for the
+ * given task list, each of which has completed.
+ * @throws InterruptedException if interrupted while waiting, in
+ * which case unfinished tasks are cancelled.
+ * @throws NullPointerException if tasks or any of its elements are <tt>null</tt>
+ * @throws RejectedExecutionException if any task cannot be
+ * scheduled for execution
+ */
+
+ <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException;
+
+ /**
+ * Executes the given tasks, returning a list of Futures holding
+ * their status and results
+ * when all complete or the timeout expires, whichever happens first.
+ * {@link Future#isDone} is <tt>true</tt> for each
+ * element of the returned list.
+ * Upon return, tasks that have not completed are cancelled.
+ * Note that a <em>completed</em> task could have
+ * terminated either normally or by throwing an exception.
+ * The results of this method are undefined if the given
+ * collection is modified while this operation is in progress.
+ *
+ * @param tasks the collection of tasks
+ * @param timeout the maximum time to wait
+ * @param unit the time unit of the timeout argument
+ * @return a list of Futures representing the tasks, in the same
+ * sequential order as produced by the iterator for the
+ * given task list. If the operation did not time out,
+ * each task will have completed. If it did time out, some
+ * of these tasks will not have completed.
+ * @throws InterruptedException if interrupted while waiting, in
+ * which case unfinished tasks are cancelled
+ * @throws NullPointerException if tasks, any of its elements, or
+ * unit are <tt>null</tt>
+ * @throws RejectedExecutionException if any task cannot be scheduled
+ * for execution
+ */
+ <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
+ long timeout, TimeUnit unit)
+ throws InterruptedException;
+
+ /**
+ * Executes the given tasks, returning the result
+ * of one that has completed successfully (i.e., without throwing
+ * an exception), if any do. Upon normal or exceptional return,
+ * tasks that have not completed are cancelled.
+ * The results of this method are undefined if the given
+ * collection is modified while this operation is in progress.
+ *
+ * @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 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<? extends Callable<T>> tasks)
+ throws InterruptedException, ExecutionException;
+
+ /**
+ * Executes the given tasks, returning the result
+ * of one that has completed successfully (i.e., without throwing
+ * an exception), if any do before the given timeout elapses.
+ * Upon normal or exceptional return, tasks that have not
+ * completed are cancelled.
+ * The results of this method are undefined if the given
+ * collection is modified while this operation is in progress.
+ *
+ * @param tasks the collection of tasks
+ * @param timeout the maximum time to wait
+ * @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 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<? extends Callable<T>> tasks,
+ long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException;
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/Executors.java b/libjava/classpath/external/jsr166/java/util/concurrent/Executors.java
new file mode 100644
index 000000000..18e6b33cc
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/Executors.java
@@ -0,0 +1,666 @@
+/*
+ * 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.AtomicInteger;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
+import java.security.AccessControlException;
+
+/**
+ * Factory and utility methods for {@link Executor}, {@link
+ * ExecutorService}, {@link ScheduledExecutorService}, {@link
+ * ThreadFactory}, and {@link Callable} classes defined in this
+ * package. This class supports the following kinds of methods:
+ *
+ * <ul>
+ * <li> Methods that create and return an {@link ExecutorService}
+ * set up with commonly useful configuration settings.
+ * <li> Methods that create and return a {@link ScheduledExecutorService}
+ * set up with commonly useful configuration settings.
+ * <li> Methods that create and return a "wrapped" ExecutorService, that
+ * disables reconfiguration by making implementation-specific methods
+ * inaccessible.
+ * <li> Methods that create and return a {@link ThreadFactory}
+ * that sets newly created threads to a known state.
+ * <li> Methods that create and return a {@link Callable}
+ * out of other closure-like forms, so they can be used
+ * in execution methods requiring <tt>Callable</tt>.
+ * </ul>
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class Executors {
+
+ /**
+ * Creates a thread pool that reuses a fixed number of threads
+ * operating off a shared unbounded queue. At any point, at most
+ * <tt>nThreads</tt> threads will be active processing tasks.
+ * If additional tasks are submitted when all threads are active,
+ * they will wait in the queue until a thread is available.
+ * If any thread terminates due to a failure during execution
+ * prior to shutdown, a new one will take its place if needed to
+ * execute subsequent tasks. The threads in the pool will exist
+ * until it is explicitly {@link ExecutorService#shutdown shutdown}.
+ *
+ * @param nThreads the number of threads in the pool
+ * @return the newly created thread pool
+ * @throws IllegalArgumentException if <tt>nThreads &lt;= 0</tt>
+ */
+ public static ExecutorService newFixedThreadPool(int nThreads) {
+ return new ThreadPoolExecutor(nThreads, nThreads,
+ 0L, TimeUnit.MILLISECONDS,
+ new LinkedBlockingQueue<Runnable>());
+ }
+
+ /**
+ * Creates a thread pool that reuses a fixed number of threads
+ * operating off a shared unbounded queue, using the provided
+ * ThreadFactory to create new threads when needed. At any point,
+ * at most <tt>nThreads</tt> threads will be active processing
+ * tasks. If additional tasks are submitted when all threads are
+ * active, they will wait in the queue until a thread is
+ * available. If any thread terminates due to a failure during
+ * execution prior to shutdown, a new one will take its place if
+ * needed to execute subsequent tasks. The threads in the pool will
+ * exist until it is explicitly {@link ExecutorService#shutdown
+ * shutdown}.
+ *
+ * @param nThreads the number of threads in the pool
+ * @param threadFactory the factory to use when creating new threads
+ * @return the newly created thread pool
+ * @throws NullPointerException if threadFactory is null
+ * @throws IllegalArgumentException if <tt>nThreads &lt;= 0</tt>
+ */
+ public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
+ return new ThreadPoolExecutor(nThreads, nThreads,
+ 0L, TimeUnit.MILLISECONDS,
+ new LinkedBlockingQueue<Runnable>(),
+ threadFactory);
+ }
+
+ /**
+ * Creates an Executor that uses a single worker thread operating
+ * off an unbounded queue. (Note however that if this single
+ * thread terminates due to a failure during execution prior to
+ * shutdown, a new one will take its place if needed to execute
+ * subsequent tasks.) Tasks are guaranteed to execute
+ * sequentially, and no more than one task will be active at any
+ * given time. Unlike the otherwise equivalent
+ * <tt>newFixedThreadPool(1)</tt> the returned executor is
+ * guaranteed not to be reconfigurable to use additional threads.
+ *
+ * @return the newly created single-threaded Executor
+ */
+ public static ExecutorService newSingleThreadExecutor() {
+ return new FinalizableDelegatedExecutorService
+ (new ThreadPoolExecutor(1, 1,
+ 0L, TimeUnit.MILLISECONDS,
+ new LinkedBlockingQueue<Runnable>()));
+ }
+
+ /**
+ * Creates an Executor that uses a single worker thread operating
+ * off an unbounded queue, and uses the provided ThreadFactory to
+ * create a new thread when needed. Unlike the otherwise
+ * equivalent <tt>newFixedThreadPool(1, threadFactory)</tt> the
+ * returned executor is guaranteed not to be reconfigurable to use
+ * additional threads.
+ *
+ * @param threadFactory the factory to use when creating new
+ * threads
+ *
+ * @return the newly created single-threaded Executor
+ * @throws NullPointerException if threadFactory is null
+ */
+ public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
+ return new FinalizableDelegatedExecutorService
+ (new ThreadPoolExecutor(1, 1,
+ 0L, TimeUnit.MILLISECONDS,
+ new LinkedBlockingQueue<Runnable>(),
+ threadFactory));
+ }
+
+ /**
+ * Creates a thread pool that creates new threads as needed, but
+ * will reuse previously constructed threads when they are
+ * available. These pools will typically improve the performance
+ * of programs that execute many short-lived asynchronous tasks.
+ * Calls to <tt>execute</tt> will reuse previously constructed
+ * threads if available. If no existing thread is available, a new
+ * thread will be created and added to the pool. Threads that have
+ * not been used for sixty seconds are terminated and removed from
+ * the cache. Thus, a pool that remains idle for long enough will
+ * not consume any resources. Note that pools with similar
+ * properties but different details (for example, timeout parameters)
+ * may be created using {@link ThreadPoolExecutor} constructors.
+ *
+ * @return the newly created thread pool
+ */
+ public static ExecutorService newCachedThreadPool() {
+ return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
+ 60L, TimeUnit.SECONDS,
+ new SynchronousQueue<Runnable>());
+ }
+
+ /**
+ * Creates a thread pool that creates new threads as needed, but
+ * will reuse previously constructed threads when they are
+ * available, and uses the provided
+ * ThreadFactory to create new threads when needed.
+ * @param threadFactory the factory to use when creating new threads
+ * @return the newly created thread pool
+ * @throws NullPointerException if threadFactory is null
+ */
+ public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
+ return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
+ 60L, TimeUnit.SECONDS,
+ new SynchronousQueue<Runnable>(),
+ threadFactory);
+ }
+
+ /**
+ * Creates a single-threaded executor that can schedule commands
+ * to run after a given delay, or to execute periodically.
+ * (Note however that if this single
+ * thread terminates due to a failure during execution prior to
+ * shutdown, a new one will take its place if needed to execute
+ * subsequent tasks.) Tasks are guaranteed to execute
+ * sequentially, and no more than one task will be active at any
+ * given time. Unlike the otherwise equivalent
+ * <tt>newScheduledThreadPool(1)</tt> the returned executor is
+ * guaranteed not to be reconfigurable to use additional threads.
+ * @return the newly created scheduled executor
+ */
+ public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
+ return new DelegatedScheduledExecutorService
+ (new ScheduledThreadPoolExecutor(1));
+ }
+
+ /**
+ * Creates a single-threaded executor that can schedule commands
+ * to run after a given delay, or to execute periodically. (Note
+ * however that if this single thread terminates due to a failure
+ * during execution prior to shutdown, a new one will take its
+ * place if needed to execute subsequent tasks.) Tasks are
+ * guaranteed to execute sequentially, and no more than one task
+ * will be active at any given time. Unlike the otherwise
+ * equivalent <tt>newScheduledThreadPool(1, threadFactory)</tt>
+ * the returned executor is guaranteed not to be reconfigurable to
+ * use additional threads.
+ * @param threadFactory the factory to use when creating new
+ * threads
+ * @return a newly created scheduled executor
+ * @throws NullPointerException if threadFactory is null
+ */
+ public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {
+ return new DelegatedScheduledExecutorService
+ (new ScheduledThreadPoolExecutor(1, threadFactory));
+ }
+
+ /**
+ * Creates a thread pool that can schedule commands to run after a
+ * given delay, or to execute periodically.
+ * @param corePoolSize the number of threads to keep in the pool,
+ * even if they are idle.
+ * @return a newly created scheduled thread pool
+ * @throws IllegalArgumentException if <tt>corePoolSize &lt; 0</tt>
+ */
+ public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
+ return new ScheduledThreadPoolExecutor(corePoolSize);
+ }
+
+ /**
+ * Creates a thread pool that can schedule commands to run after a
+ * given delay, or to execute periodically.
+ * @param corePoolSize the number of threads to keep in the pool,
+ * even if they are idle.
+ * @param threadFactory the factory to use when the executor
+ * creates a new thread.
+ * @return a newly created scheduled thread pool
+ * @throws IllegalArgumentException if <tt>corePoolSize &lt; 0</tt>
+ * @throws NullPointerException if threadFactory is null
+ */
+ public static ScheduledExecutorService newScheduledThreadPool(
+ int corePoolSize, ThreadFactory threadFactory) {
+ return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
+ }
+
+
+ /**
+ * Returns an object that delegates all defined {@link
+ * ExecutorService} methods to the given executor, but not any
+ * other methods that might otherwise be accessible using
+ * casts. This provides a way to safely "freeze" configuration and
+ * disallow tuning of a given concrete implementation.
+ * @param executor the underlying implementation
+ * @return an <tt>ExecutorService</tt> instance
+ * @throws NullPointerException if executor null
+ */
+ public static ExecutorService unconfigurableExecutorService(ExecutorService executor) {
+ if (executor == null)
+ throw new NullPointerException();
+ return new DelegatedExecutorService(executor);
+ }
+
+ /**
+ * Returns an object that delegates all defined {@link
+ * ScheduledExecutorService} methods to the given executor, but
+ * not any other methods that might otherwise be accessible using
+ * casts. This provides a way to safely "freeze" configuration and
+ * disallow tuning of a given concrete implementation.
+ * @param executor the underlying implementation
+ * @return a <tt>ScheduledExecutorService</tt> instance
+ * @throws NullPointerException if executor null
+ */
+ public static ScheduledExecutorService unconfigurableScheduledExecutorService(ScheduledExecutorService executor) {
+ if (executor == null)
+ throw new NullPointerException();
+ return new DelegatedScheduledExecutorService(executor);
+ }
+
+ /**
+ * Returns a default thread factory used to create new threads.
+ * This factory creates all new threads used by an Executor in the
+ * same {@link ThreadGroup}. If there is a {@link
+ * java.lang.SecurityManager}, it uses the group of {@link
+ * System#getSecurityManager}, else the group of the thread
+ * invoking this <tt>defaultThreadFactory</tt> method. Each new
+ * thread is created as a non-daemon thread with priority set to
+ * the smaller of <tt>Thread.NORM_PRIORITY</tt> and the maximum
+ * priority permitted in the thread group. New threads have names
+ * accessible via {@link Thread#getName} of
+ * <em>pool-N-thread-M</em>, where <em>N</em> is the sequence
+ * number of this factory, and <em>M</em> is the sequence number
+ * of the thread created by this factory.
+ * @return a thread factory
+ */
+ public static ThreadFactory defaultThreadFactory() {
+ return new DefaultThreadFactory();
+ }
+
+ /**
+ * Returns a thread factory used to create new threads that
+ * have the same permissions as the current thread.
+ * This factory creates threads with the same settings as {@link
+ * Executors#defaultThreadFactory}, additionally setting the
+ * AccessControlContext and contextClassLoader of new threads to
+ * be the same as the thread invoking this
+ * <tt>privilegedThreadFactory</tt> method. A new
+ * <tt>privilegedThreadFactory</tt> can be created within an
+ * {@link AccessController#doPrivileged} action setting the
+ * current thread's access control context to create threads with
+ * the selected permission settings holding within that action.
+ *
+ * <p> Note that while tasks running within such threads will have
+ * the same access control and class loader settings as the
+ * current thread, they need not have the same {@link
+ * java.lang.ThreadLocal} or {@link
+ * java.lang.InheritableThreadLocal} values. If necessary,
+ * particular values of thread locals can be set or reset before
+ * any task runs in {@link ThreadPoolExecutor} subclasses using
+ * {@link ThreadPoolExecutor#beforeExecute}. Also, if it is
+ * necessary to initialize worker threads to have the same
+ * InheritableThreadLocal settings as some other designated
+ * thread, you can create a custom ThreadFactory in which that
+ * thread waits for and services requests to create others that
+ * will inherit its values.
+ *
+ * @return a thread factory
+ * @throws AccessControlException if the current access control
+ * context does not have permission to both get and set context
+ * class loader.
+ */
+ public static ThreadFactory privilegedThreadFactory() {
+ return new PrivilegedThreadFactory();
+ }
+
+ /**
+ * Returns a {@link Callable} object that, when
+ * called, runs the given task and returns the given result. This
+ * can be useful when applying methods requiring a
+ * <tt>Callable</tt> to an otherwise resultless action.
+ * @param task the task to run
+ * @param result the result to return
+ * @return a callable object
+ * @throws NullPointerException if task null
+ */
+ public static <T> Callable<T> callable(Runnable task, T result) {
+ if (task == null)
+ throw new NullPointerException();
+ return new RunnableAdapter<T>(task, result);
+ }
+
+ /**
+ * Returns a {@link Callable} object that, when
+ * called, runs the given task and returns <tt>null</tt>.
+ * @param task the task to run
+ * @return a callable object
+ * @throws NullPointerException if task null
+ */
+ public static Callable<Object> callable(Runnable task) {
+ if (task == null)
+ throw new NullPointerException();
+ return new RunnableAdapter<Object>(task, null);
+ }
+
+ /**
+ * Returns a {@link Callable} object that, when
+ * called, runs the given privileged action and returns its result.
+ * @param action the privileged action to run
+ * @return a callable object
+ * @throws NullPointerException if action null
+ */
+ public static Callable<Object> callable(final PrivilegedAction<?> action) {
+ if (action == null)
+ throw new NullPointerException();
+ return new Callable<Object>() {
+ public Object call() { return action.run(); }};
+ }
+
+ /**
+ * Returns a {@link Callable} object that, when
+ * called, runs the given privileged exception action and returns
+ * its result.
+ * @param action the privileged exception action to run
+ * @return a callable object
+ * @throws NullPointerException if action null
+ */
+ public static Callable<Object> callable(final PrivilegedExceptionAction<?> action) {
+ if (action == null)
+ throw new NullPointerException();
+ return new Callable<Object>() {
+ public Object call() throws Exception { return action.run(); }};
+ }
+
+ /**
+ * Returns a {@link Callable} object that will, when
+ * called, execute the given <tt>callable</tt> under the current
+ * access control context. This method should normally be
+ * invoked within an {@link AccessController#doPrivileged} action
+ * to create callables that will, if possible, execute under the
+ * selected permission settings holding within that action; or if
+ * not possible, throw an associated {@link
+ * AccessControlException}.
+ * @param callable the underlying task
+ * @return a callable object
+ * @throws NullPointerException if callable null
+ *
+ */
+ public static <T> Callable<T> privilegedCallable(Callable<T> callable) {
+ if (callable == null)
+ throw new NullPointerException();
+ return new PrivilegedCallable<T>(callable);
+ }
+
+ /**
+ * Returns a {@link Callable} object that will, when
+ * called, execute the given <tt>callable</tt> under the current
+ * access control context, with the current context class loader
+ * as the context class loader. This method should normally be
+ * invoked within an {@link AccessController#doPrivileged} action
+ * to create callables that will, if possible, execute under the
+ * selected permission settings holding within that action; or if
+ * not possible, throw an associated {@link
+ * AccessControlException}.
+ * @param callable the underlying task
+ *
+ * @return a callable object
+ * @throws NullPointerException if callable null
+ * @throws AccessControlException if the current access control
+ * context does not have permission to both set and get context
+ * class loader.
+ */
+ public static <T> Callable<T> privilegedCallableUsingCurrentClassLoader(Callable<T> callable) {
+ if (callable == null)
+ throw new NullPointerException();
+ return new PrivilegedCallableUsingCurrentClassLoader<T>(callable);
+ }
+
+ // Non-public classes supporting the public methods
+
+ /**
+ * A callable that runs given task and returns given result
+ */
+ static final class RunnableAdapter<T> implements Callable<T> {
+ final Runnable task;
+ final T result;
+ RunnableAdapter(Runnable task, T result) {
+ this.task = task;
+ this.result = result;
+ }
+ public T call() {
+ task.run();
+ return result;
+ }
+ }
+
+ /**
+ * A callable that runs under established access control settings
+ */
+ static final class PrivilegedCallable<T> implements Callable<T> {
+ private final AccessControlContext acc;
+ private final Callable<T> task;
+ private T result;
+ private Exception exception;
+ PrivilegedCallable(Callable<T> task) {
+ this.task = task;
+ this.acc = AccessController.getContext();
+ }
+
+ public T call() throws Exception {
+ AccessController.doPrivileged(new PrivilegedAction<T>() {
+ public T run() {
+ try {
+ result = task.call();
+ } catch (Exception ex) {
+ exception = ex;
+ }
+ return null;
+ }
+ }, acc);
+ if (exception != null)
+ throw exception;
+ else
+ return result;
+ }
+ }
+
+ /**
+ * A callable that runs under established access control settings and
+ * current ClassLoader
+ */
+ static final class PrivilegedCallableUsingCurrentClassLoader<T> implements Callable<T> {
+ private final ClassLoader ccl;
+ private final AccessControlContext acc;
+ private final Callable<T> task;
+ private T result;
+ private Exception exception;
+ PrivilegedCallableUsingCurrentClassLoader(Callable<T> task) {
+ this.task = task;
+ this.ccl = Thread.currentThread().getContextClassLoader();
+ this.acc = AccessController.getContext();
+ acc.checkPermission(new RuntimePermission("getContextClassLoader"));
+ acc.checkPermission(new RuntimePermission("setContextClassLoader"));
+ }
+
+ public T call() throws Exception {
+ AccessController.doPrivileged(new PrivilegedAction<T>() {
+ public T run() {
+ ClassLoader savedcl = null;
+ Thread t = Thread.currentThread();
+ try {
+ ClassLoader cl = t.getContextClassLoader();
+ if (ccl != cl) {
+ t.setContextClassLoader(ccl);
+ savedcl = cl;
+ }
+ result = task.call();
+ } catch (Exception ex) {
+ exception = ex;
+ } finally {
+ if (savedcl != null)
+ t.setContextClassLoader(savedcl);
+ }
+ return null;
+ }
+ }, acc);
+ if (exception != null)
+ throw exception;
+ else
+ return result;
+ }
+ }
+
+ /**
+ * The default thread factory
+ */
+ static class DefaultThreadFactory implements ThreadFactory {
+ static final AtomicInteger poolNumber = new AtomicInteger(1);
+ final ThreadGroup group;
+ final AtomicInteger threadNumber = new AtomicInteger(1);
+ final String namePrefix;
+
+ DefaultThreadFactory() {
+ SecurityManager s = System.getSecurityManager();
+ group = (s != null)? s.getThreadGroup() :
+ Thread.currentThread().getThreadGroup();
+ namePrefix = "pool-" +
+ poolNumber.getAndIncrement() +
+ "-thread-";
+ }
+
+ public Thread newThread(Runnable r) {
+ Thread t = new Thread(group, r,
+ namePrefix + threadNumber.getAndIncrement(),
+ 0);
+ if (t.isDaemon())
+ t.setDaemon(false);
+ if (t.getPriority() != Thread.NORM_PRIORITY)
+ t.setPriority(Thread.NORM_PRIORITY);
+ return t;
+ }
+ }
+
+ /**
+ * Thread factory capturing access control and class loader
+ */
+ static class PrivilegedThreadFactory extends DefaultThreadFactory {
+ private final ClassLoader ccl;
+ private final AccessControlContext acc;
+
+ PrivilegedThreadFactory() {
+ super();
+ this.ccl = Thread.currentThread().getContextClassLoader();
+ this.acc = AccessController.getContext();
+ acc.checkPermission(new RuntimePermission("setContextClassLoader"));
+ }
+
+ public Thread newThread(final Runnable r) {
+ return super.newThread(new Runnable() {
+ public void run() {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ Thread.currentThread().setContextClassLoader(ccl);
+ r.run();
+ return null;
+ }
+ }, acc);
+ }
+ });
+ }
+
+ }
+
+ /**
+ * A wrapper class that exposes only the ExecutorService methods
+ * of an ExecutorService implementation.
+ */
+ static class DelegatedExecutorService extends AbstractExecutorService {
+ private final ExecutorService e;
+ DelegatedExecutorService(ExecutorService executor) { e = executor; }
+ public void execute(Runnable command) { e.execute(command); }
+ public void shutdown() { e.shutdown(); }
+ public List<Runnable> shutdownNow() { return e.shutdownNow(); }
+ public boolean isShutdown() { return e.isShutdown(); }
+ public boolean isTerminated() { return e.isTerminated(); }
+ public boolean awaitTermination(long timeout, TimeUnit unit)
+ throws InterruptedException {
+ return e.awaitTermination(timeout, unit);
+ }
+ public Future<?> submit(Runnable task) {
+ return e.submit(task);
+ }
+ public <T> Future<T> submit(Callable<T> task) {
+ return e.submit(task);
+ }
+ public <T> Future<T> submit(Runnable task, T result) {
+ return e.submit(task, result);
+ }
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException {
+ return e.invokeAll(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<? extends Callable<T>> tasks)
+ throws InterruptedException, ExecutionException {
+ return e.invokeAny(tasks);
+ }
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
+ long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ return e.invokeAny(tasks, timeout, unit);
+ }
+ }
+
+ static class FinalizableDelegatedExecutorService
+ extends DelegatedExecutorService {
+ FinalizableDelegatedExecutorService(ExecutorService executor) {
+ super(executor);
+ }
+ protected void finalize() {
+ super.shutdown();
+ }
+ }
+
+ /**
+ * A wrapper class that exposes only the ScheduledExecutorService
+ * methods of a ScheduledExecutorService implementation.
+ */
+ static class DelegatedScheduledExecutorService
+ extends DelegatedExecutorService
+ implements ScheduledExecutorService {
+ private final ScheduledExecutorService e;
+ DelegatedScheduledExecutorService(ScheduledExecutorService executor) {
+ super(executor);
+ e = executor;
+ }
+ public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
+ return e.schedule(command, delay, unit);
+ }
+ public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
+ return e.schedule(callable, delay, unit);
+ }
+ public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
+ return e.scheduleAtFixedRate(command, initialDelay, period, unit);
+ }
+ public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
+ return e.scheduleWithFixedDelay(command, initialDelay, delay, unit);
+ }
+ }
+
+
+ /** Cannot instantiate. */
+ private Executors() {}
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/Future.java b/libjava/classpath/external/jsr166/java/util/concurrent/Future.java
new file mode 100644
index 000000000..0459ee453
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/Future.java
@@ -0,0 +1,142 @@
+/*
+ * 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 <tt>Future</tt> represents the result of an asynchronous
+ * computation. Methods are provided to check if the computation is
+ * complete, to wait for its completion, and to retrieve the result of
+ * the computation. The result can only be retrieved using method
+ * <tt>get</tt> when the computation has completed, blocking if
+ * necessary until it is ready. Cancellation is performed by the
+ * <tt>cancel</tt> method. Additional methods are provided to
+ * determine if the task completed normally or was cancelled. Once a
+ * computation has completed, the computation cannot be cancelled.
+ * If you would like to use a <tt>Future</tt> for the sake
+ * of cancellability but not provide a usable result, you can
+ * declare types of the form <tt>Future&lt;?&gt;</tt> and
+ * return <tt>null</tt> as a result of the underlying task.
+ *
+ * <p>
+ * <b>Sample Usage</b> (Note that the following classes are all
+ * made-up.) <p>
+ * <pre>
+ * interface ArchiveSearcher { String search(String target); }
+ * class App {
+ * ExecutorService executor = ...
+ * ArchiveSearcher searcher = ...
+ * void showSearch(final String target)
+ * throws InterruptedException {
+ * Future&lt;String&gt; future
+ * = executor.submit(new Callable&lt;String&gt;() {
+ * public String call() {
+ * return searcher.search(target);
+ * }});
+ * displayOtherThings(); // do other things while searching
+ * try {
+ * displayText(future.get()); // use future
+ * } catch (ExecutionException ex) { cleanup(); return; }
+ * }
+ * }
+ * </pre>
+ *
+ * The {@link FutureTask} class is an implementation of <tt>Future</tt> that
+ * implements <tt>Runnable</tt>, and so may be executed by an <tt>Executor</tt>.
+ * For example, the above construction with <tt>submit</tt> could be replaced by:
+ * <pre>
+ * FutureTask&lt;String&gt; future =
+ * new FutureTask&lt;String&gt;(new Callable&lt;String&gt;() {
+ * public String call() {
+ * return searcher.search(target);
+ * }});
+ * executor.execute(future);
+ * </pre>
+ *
+ * <p>Memory consistency effects: Actions taken by the asynchronous computation
+ * <a href="package-summary.html#MemoryVisibility"> <i>happen-before</i></a>
+ * actions following the corresponding {@code Future.get()} in another thread.
+ *
+ * @see FutureTask
+ * @see Executor
+ * @since 1.5
+ * @author Doug Lea
+ * @param <V> The result type returned by this Future's <tt>get</tt> method
+ */
+public interface Future<V> {
+
+ /**
+ * Attempts to cancel execution of this task. This attempt will
+ * fail if the task has already completed, has already been cancelled,
+ * or could not be cancelled for some other reason. If successful,
+ * and this task has not started when <tt>cancel</tt> is called,
+ * this task should never run. If the task has already started,
+ * then the <tt>mayInterruptIfRunning</tt> parameter determines
+ * whether the thread executing this task should be interrupted in
+ * an attempt to stop the task.
+ *
+ * <p>After this method returns, subsequent calls to {@link #isDone} will
+ * always return <tt>true</tt>. Subsequent calls to {@link #isCancelled}
+ * will always return <tt>true</tt> if this method returned <tt>true</tt>.
+ *
+ * @param mayInterruptIfRunning <tt>true</tt> if the thread executing this
+ * task should be interrupted; otherwise, in-progress tasks are allowed
+ * to complete
+ * @return <tt>false</tt> if the task could not be cancelled,
+ * typically because it has already completed normally;
+ * <tt>true</tt> otherwise
+ */
+ boolean cancel(boolean mayInterruptIfRunning);
+
+ /**
+ * Returns <tt>true</tt> if this task was cancelled before it completed
+ * normally.
+ *
+ * @return <tt>true</tt> if this task was cancelled before it completed
+ */
+ boolean isCancelled();
+
+ /**
+ * Returns <tt>true</tt> if this task completed.
+ *
+ * Completion may be due to normal termination, an exception, or
+ * cancellation -- in all of these cases, this method will return
+ * <tt>true</tt>.
+ *
+ * @return <tt>true</tt> if this task completed
+ */
+ boolean isDone();
+
+ /**
+ * Waits if necessary for the computation to complete, and then
+ * retrieves its result.
+ *
+ * @return the computed result
+ * @throws CancellationException if the computation was cancelled
+ * @throws ExecutionException if the computation threw an
+ * exception
+ * @throws InterruptedException if the current thread was interrupted
+ * while waiting
+ */
+ V get() throws InterruptedException, ExecutionException;
+
+ /**
+ * Waits if necessary for at most the given time for the computation
+ * to complete, and then retrieves its result, if available.
+ *
+ * @param timeout the maximum time to wait
+ * @param unit the time unit of the timeout argument
+ * @return the computed result
+ * @throws CancellationException if the computation was cancelled
+ * @throws ExecutionException if the computation threw an
+ * exception
+ * @throws InterruptedException if the current thread was interrupted
+ * while waiting
+ * @throws TimeoutException if the wait timed out
+ */
+ V get(long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException;
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/FutureTask.java b/libjava/classpath/external/jsr166/java/util/concurrent/FutureTask.java
new file mode 100644
index 000000000..94742405d
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/FutureTask.java
@@ -0,0 +1,325 @@
+/*
+ * 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.concurrent.locks.*;
+
+/**
+ * A cancellable asynchronous computation. This class provides a base
+ * implementation of {@link Future}, with methods to start and cancel
+ * a computation, query to see if the computation is complete, and
+ * retrieve the result of the computation. The result can only be
+ * retrieved when the computation has completed; the <tt>get</tt>
+ * method will block if the computation has not yet completed. Once
+ * the computation has completed, the computation cannot be restarted
+ * or cancelled.
+ *
+ * <p>A <tt>FutureTask</tt> can be used to wrap a {@link Callable} or
+ * {@link java.lang.Runnable} object. Because <tt>FutureTask</tt>
+ * implements <tt>Runnable</tt>, a <tt>FutureTask</tt> can be
+ * submitted to an {@link Executor} for execution.
+ *
+ * <p>In addition to serving as a standalone class, this class provides
+ * <tt>protected</tt> functionality that may be useful when creating
+ * customized task classes.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <V> The result type returned by this FutureTask's <tt>get</tt> method
+ */
+public class FutureTask<V> implements RunnableFuture<V> {
+ /** Synchronization control for FutureTask */
+ private final Sync sync;
+
+ /**
+ * Creates a <tt>FutureTask</tt> that will upon running, execute the
+ * given <tt>Callable</tt>.
+ *
+ * @param callable the callable task
+ * @throws NullPointerException if callable is null
+ */
+ public FutureTask(Callable<V> callable) {
+ if (callable == null)
+ throw new NullPointerException();
+ sync = new Sync(callable);
+ }
+
+ /**
+ * Creates a <tt>FutureTask</tt> that will upon running, execute the
+ * given <tt>Runnable</tt>, and arrange that <tt>get</tt> will return the
+ * given result on successful completion.
+ *
+ * @param runnable the runnable task
+ * @param result the result to return on successful completion. If
+ * you don't need a particular result, consider using
+ * constructions of the form:
+ * <tt>Future&lt;?&gt; f = new FutureTask&lt;Object&gt;(runnable, null)</tt>
+ * @throws NullPointerException if runnable is null
+ */
+ public FutureTask(Runnable runnable, V result) {
+ sync = new Sync(Executors.callable(runnable, result));
+ }
+
+ public boolean isCancelled() {
+ return sync.innerIsCancelled();
+ }
+
+ public boolean isDone() {
+ return sync.innerIsDone();
+ }
+
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ return sync.innerCancel(mayInterruptIfRunning);
+ }
+
+ /**
+ * @throws CancellationException {@inheritDoc}
+ */
+ public V get() throws InterruptedException, ExecutionException {
+ return sync.innerGet();
+ }
+
+ /**
+ * @throws CancellationException {@inheritDoc}
+ */
+ public V get(long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ return sync.innerGet(unit.toNanos(timeout));
+ }
+
+ /**
+ * Protected method invoked when this task transitions to state
+ * <tt>isDone</tt> (whether normally or via cancellation). The
+ * default implementation does nothing. Subclasses may override
+ * this method to invoke completion callbacks or perform
+ * bookkeeping. Note that you can query status inside the
+ * implementation of this method to determine whether this task
+ * has been cancelled.
+ */
+ protected void done() { }
+
+ /**
+ * Sets the result of this Future to the given value unless
+ * this future has already been set or has been cancelled.
+ * This method is invoked internally by the <tt>run</tt> method
+ * upon successful completion of the computation.
+ * @param v the value
+ */
+ protected void set(V v) {
+ sync.innerSet(v);
+ }
+
+ /**
+ * Causes this future to report an <tt>ExecutionException</tt>
+ * with the given throwable as its cause, unless this Future has
+ * already been set or has been cancelled.
+ * This method is invoked internally by the <tt>run</tt> method
+ * upon failure of the computation.
+ * @param t the cause of failure
+ */
+ protected void setException(Throwable t) {
+ sync.innerSetException(t);
+ }
+
+ // The following (duplicated) doc comment can be removed once
+ //
+ // 6270645: Javadoc comments should be inherited from most derived
+ // superinterface or superclass
+ // is fixed.
+ /**
+ * Sets this Future to the result of its computation
+ * unless it has been cancelled.
+ */
+ public void run() {
+ sync.innerRun();
+ }
+
+ /**
+ * Executes the computation without setting its result, and then
+ * resets this Future to initial state, failing to do so if the
+ * computation encounters an exception or is cancelled. This is
+ * designed for use with tasks that intrinsically execute more
+ * than once.
+ * @return true if successfully run and reset
+ */
+ protected boolean runAndReset() {
+ return sync.innerRunAndReset();
+ }
+
+ /**
+ * Synchronization control for FutureTask. Note that this must be
+ * a non-static inner class in order to invoke the protected
+ * <tt>done</tt> method. For clarity, all inner class support
+ * methods are same as outer, prefixed with "inner".
+ *
+ * Uses AQS sync state to represent run status
+ */
+ private final class Sync extends AbstractQueuedSynchronizer {
+ private static final long serialVersionUID = -7828117401763700385L;
+
+ /** State value representing that task is running */
+ private static final int RUNNING = 1;
+ /** State value representing that task ran */
+ private static final int RAN = 2;
+ /** State value representing that task was cancelled */
+ private static final int CANCELLED = 4;
+
+ /** The underlying callable */
+ private final Callable<V> callable;
+ /** The result to return from get() */
+ private V result;
+ /** The exception to throw from get() */
+ private Throwable exception;
+
+ /**
+ * The thread running task. When nulled after set/cancel, this
+ * indicates that the results are accessible. Must be
+ * volatile, to ensure visibility upon completion.
+ */
+ private volatile Thread runner;
+
+ Sync(Callable<V> callable) {
+ this.callable = callable;
+ }
+
+ private boolean ranOrCancelled(int state) {
+ return (state & (RAN | CANCELLED)) != 0;
+ }
+
+ /**
+ * Implements AQS base acquire to succeed if ran or cancelled
+ */
+ protected int tryAcquireShared(int ignore) {
+ return innerIsDone()? 1 : -1;
+ }
+
+ /**
+ * Implements AQS base release to always signal after setting
+ * final done status by nulling runner thread.
+ */
+ protected boolean tryReleaseShared(int ignore) {
+ runner = null;
+ return true;
+ }
+
+ boolean innerIsCancelled() {
+ return getState() == CANCELLED;
+ }
+
+ boolean innerIsDone() {
+ return ranOrCancelled(getState()) && runner == null;
+ }
+
+ V innerGet() throws InterruptedException, ExecutionException {
+ acquireSharedInterruptibly(0);
+ if (getState() == CANCELLED)
+ throw new CancellationException();
+ if (exception != null)
+ throw new ExecutionException(exception);
+ return result;
+ }
+
+ V innerGet(long nanosTimeout) throws InterruptedException, ExecutionException, TimeoutException {
+ if (!tryAcquireSharedNanos(0, nanosTimeout))
+ throw new TimeoutException();
+ if (getState() == CANCELLED)
+ throw new CancellationException();
+ if (exception != null)
+ throw new ExecutionException(exception);
+ return result;
+ }
+
+ void innerSet(V v) {
+ for (;;) {
+ int s = getState();
+ if (s == RAN)
+ return;
+ if (s == CANCELLED) {
+ // aggressively release to set runner to null,
+ // in case we are racing with a cancel request
+ // that will try to interrupt runner
+ releaseShared(0);
+ return;
+ }
+ if (compareAndSetState(s, RAN)) {
+ result = v;
+ releaseShared(0);
+ done();
+ return;
+ }
+ }
+ }
+
+ void innerSetException(Throwable t) {
+ for (;;) {
+ int s = getState();
+ if (s == RAN)
+ return;
+ if (s == CANCELLED) {
+ // aggressively release to set runner to null,
+ // in case we are racing with a cancel request
+ // that will try to interrupt runner
+ releaseShared(0);
+ return;
+ }
+ if (compareAndSetState(s, RAN)) {
+ exception = t;
+ result = null;
+ releaseShared(0);
+ done();
+ return;
+ }
+ }
+ }
+
+ boolean innerCancel(boolean mayInterruptIfRunning) {
+ for (;;) {
+ int s = getState();
+ if (ranOrCancelled(s))
+ return false;
+ if (compareAndSetState(s, CANCELLED))
+ break;
+ }
+ if (mayInterruptIfRunning) {
+ Thread r = runner;
+ if (r != null)
+ r.interrupt();
+ }
+ releaseShared(0);
+ done();
+ return true;
+ }
+
+ void innerRun() {
+ if (!compareAndSetState(0, RUNNING))
+ return;
+ try {
+ runner = Thread.currentThread();
+ if (getState() == RUNNING) // recheck after setting thread
+ innerSet(callable.call());
+ else
+ releaseShared(0); // cancel
+ } catch (Throwable ex) {
+ innerSetException(ex);
+ }
+ }
+
+ boolean innerRunAndReset() {
+ if (!compareAndSetState(0, RUNNING))
+ return false;
+ try {
+ runner = Thread.currentThread();
+ if (getState() == RUNNING)
+ callable.call(); // don't set result
+ runner = null;
+ return compareAndSetState(RUNNING, 0);
+ } catch (Throwable ex) {
+ innerSetException(ex);
+ return false;
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/LinkedBlockingDeque.java b/libjava/classpath/external/jsr166/java/util/concurrent/LinkedBlockingDeque.java
new file mode 100644
index 000000000..2dc8fa877
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/LinkedBlockingDeque.java
@@ -0,0 +1,1021 @@
+/*
+ * 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.locks.*;
+
+/**
+ * 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.
+ */
+
+ /*
+ * 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> {
+ E item;
+ Node<E> prev;
+ Node<E> next;
+ Node(E x, Node<E> p, Node<E> n) {
+ item = x;
+ prev = p;
+ next = n;
+ }
+ }
+
+ /** Pointer to first node */
+ private transient Node<E> first;
+ /** Pointer to last node */
+ private 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 */
+ private 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 <tt>LinkedBlockingDeque</tt> with a capacity of
+ * {@link Integer#MAX_VALUE}.
+ */
+ public LinkedBlockingDeque() {
+ this(Integer.MAX_VALUE);
+ }
+
+ /**
+ * Creates a <tt>LinkedBlockingDeque</tt> with the given (fixed) capacity.
+ *
+ * @param capacity the capacity of this deque
+ * @throws IllegalArgumentException if <tt>capacity</tt> is less than 1
+ */
+ public LinkedBlockingDeque(int capacity) {
+ if (capacity <= 0) throw new IllegalArgumentException();
+ this.capacity = capacity;
+ }
+
+ /**
+ * Creates a <tt>LinkedBlockingDeque</tt> 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);
+ for (E e : c)
+ add(e);
+ }
+
+
+ // 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) {
+ if (count >= capacity)
+ return false;
+ ++count;
+ Node<E> f = first;
+ Node<E> x = new Node<E>(e, null, f);
+ first = x;
+ if (last == null)
+ last = x;
+ else
+ f.prev = x;
+ notEmpty.signal();
+ return true;
+ }
+
+ /**
+ * Links e as last element, or returns false if full.
+ */
+ private boolean linkLast(E e) {
+ if (count >= capacity)
+ return false;
+ ++count;
+ Node<E> l = last;
+ Node<E> x = new Node<E>(e, l, null);
+ last = x;
+ if (first == null)
+ first = x;
+ else
+ l.next = x;
+ notEmpty.signal();
+ return true;
+ }
+
+ /**
+ * Removes and returns first element, or null if empty.
+ */
+ private E unlinkFirst() {
+ Node<E> f = first;
+ if (f == null)
+ return null;
+ Node<E> n = f.next;
+ first = n;
+ if (n == null)
+ last = null;
+ else
+ n.prev = null;
+ --count;
+ notFull.signal();
+ return f.item;
+ }
+
+ /**
+ * Removes and returns last element, or null if empty.
+ */
+ private E unlinkLast() {
+ Node<E> l = last;
+ if (l == null)
+ return null;
+ Node<E> p = l.prev;
+ last = p;
+ if (p == null)
+ first = null;
+ else
+ p.next = null;
+ --count;
+ notFull.signal();
+ return l.item;
+ }
+
+ /**
+ * Unlink e
+ */
+ private void unlink(Node<E> x) {
+ Node<E> p = x.prev;
+ Node<E> n = x.next;
+ if (p == null) {
+ if (n == null)
+ first = last = null;
+ else {
+ n.prev = null;
+ first = n;
+ }
+ } else if (n == null) {
+ p.next = null;
+ last = p;
+ } else {
+ p.next = n;
+ n.prev = p;
+ }
+ --count;
+ notFull.signalAll();
+ }
+
+ // 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();
+ lock.lock();
+ try {
+ return linkFirst(e);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean offerLast(E e) {
+ if (e == null) throw new NullPointerException();
+ 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();
+ 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();
+ 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);
+ lock.lockInterruptibly();
+ try {
+ for (;;) {
+ if (linkFirst(e))
+ return true;
+ if (nanos <= 0)
+ return false;
+ nanos = notFull.awaitNanos(nanos);
+ }
+ } 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);
+ lock.lockInterruptibly();
+ try {
+ for (;;) {
+ if (linkLast(e))
+ return true;
+ if (nanos <= 0)
+ return false;
+ nanos = notFull.awaitNanos(nanos);
+ }
+ } 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() {
+ lock.lock();
+ try {
+ return unlinkFirst();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E pollLast() {
+ lock.lock();
+ try {
+ return unlinkLast();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E takeFirst() throws InterruptedException {
+ lock.lock();
+ try {
+ E x;
+ while ( (x = unlinkFirst()) == null)
+ notEmpty.await();
+ return x;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E takeLast() throws InterruptedException {
+ 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);
+ lock.lockInterruptibly();
+ try {
+ for (;;) {
+ E x = unlinkFirst();
+ if (x != null)
+ return x;
+ if (nanos <= 0)
+ return null;
+ nanos = notEmpty.awaitNanos(nanos);
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E pollLast(long timeout, TimeUnit unit)
+ throws InterruptedException {
+ long nanos = unit.toNanos(timeout);
+ lock.lockInterruptibly();
+ try {
+ for (;;) {
+ E x = unlinkLast();
+ if (x != null)
+ return x;
+ if (nanos <= 0)
+ return null;
+ nanos = notEmpty.awaitNanos(nanos);
+ }
+ } 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() {
+ lock.lock();
+ try {
+ return (first == null) ? null : first.item;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E peekLast() {
+ lock.lock();
+ try {
+ return (last == null) ? null : last.item;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public boolean removeFirstOccurrence(Object o) {
+ if (o == null) return false;
+ 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;
+ 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 <tt>size</tt> of this deque.
+ *
+ * <p>Note that you <em>cannot</em> always tell if an attempt to insert
+ * an element will succeed by inspecting <tt>remainingCapacity</tt>
+ * because it may be the case that another thread is about to
+ * insert or remove an element.
+ */
+ public int remainingCapacity() {
+ 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) {
+ if (c == null)
+ throw new NullPointerException();
+ if (c == this)
+ throw new IllegalArgumentException();
+ lock.lock();
+ try {
+ for (Node<E> p = first; p != null; p = p.next)
+ c.add(p.item);
+ int n = count;
+ count = 0;
+ first = last = null;
+ notFull.signalAll();
+ return n;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @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();
+ lock.lock();
+ try {
+ int n = 0;
+ while (n < maxElements && first != null) {
+ c.add(first.item);
+ first.prev = null;
+ first = first.next;
+ --count;
+ ++n;
+ }
+ if (first == null)
+ last = null;
+ notFull.signalAll();
+ 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 <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
+ */
+ 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() {
+ lock.lock();
+ try {
+ return count;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * 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
+ */
+ public boolean contains(Object o) {
+ if (o == null) return false;
+ 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();
+ }
+ }
+
+ /**
+ * Variant of removeFirstOccurrence needed by iterator.remove.
+ * Searches for the node, not its contents.
+ */
+ boolean removeNode(Node<E> e) {
+ lock.lock();
+ try {
+ for (Node<E> p = first; p != null; p = p.next) {
+ if (p == e) {
+ unlink(p);
+ return true;
+ }
+ }
+ return false;
+ } 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
+ */
+ public Object[] toArray() {
+ 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
+ * <tt>null</tt>.
+ *
+ * <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 deque known to contain only strings.
+ * The following code can be used to dump the deque into a newly
+ * allocated array of <tt>String</tt>:
+ *
+ * <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>.
+ *
+ * @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) {
+ 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() {
+ 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() {
+ lock.lock();
+ try {
+ 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 <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.
+ *
+ * @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 <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 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;
+
+ AbstractItr() {
+ advance(); // set to initial position
+ }
+
+ /**
+ * Advances next, or if not yet initialized, sets to first node.
+ * Implemented to move forward vs backward in the two subclasses.
+ */
+ abstract void advance();
+
+ 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;
+ // Note: removeNode rescans looking for this node to make
+ // sure it was not already removed. Otherwise, trying to
+ // re-remove could corrupt list.
+ removeNode(n);
+ }
+ }
+
+ /** Forward iterator */
+ private class Itr extends AbstractItr {
+ void advance() {
+ final ReentrantLock lock = LinkedBlockingDeque.this.lock;
+ lock.lock();
+ try {
+ next = (next == null)? first : next.next;
+ nextItem = (next == null)? null : next.item;
+ } finally {
+ lock.unlock();
+ }
+ }
+ }
+
+ /**
+ * Descending iterator for LinkedBlockingDeque
+ */
+ private class DescendingItr extends AbstractItr {
+ void advance() {
+ final ReentrantLock lock = LinkedBlockingDeque.this.lock;
+ lock.lock();
+ try {
+ next = (next == null)? last : next.prev;
+ nextItem = (next == null)? null : next.item;
+ } finally {
+ lock.unlock();
+ }
+ }
+ }
+
+ /**
+ * Save the state of this deque to a stream (that is, serialize it).
+ *
+ * @serialData The capacity (int), followed by elements (each an
+ * <tt>Object</tt>) in the proper order, followed by a null
+ * @param s the stream
+ */
+ private void writeObject(java.io.ObjectOutputStream s)
+ throws java.io.IOException {
+ 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 (;;) {
+ E item = (E)s.readObject();
+ if (item == null)
+ break;
+ add(item);
+ }
+ }
+
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/LinkedBlockingQueue.java b/libjava/classpath/external/jsr166/java/util/concurrent/LinkedBlockingQueue.java
new file mode 100644
index 000000000..62018096a
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/LinkedBlockingQueue.java
@@ -0,0 +1,807 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+import java.util.concurrent.atomic.*;
+import java.util.concurrent.locks.*;
+import java.util.*;
+
+/**
+ * An optionally-bounded {@linkplain BlockingQueue blocking queue} based on
+ * linked nodes.
+ * This queue orders elements FIFO (first-in-first-out).
+ * The <em>head</em> of the queue is that element that has been on the
+ * queue the longest time.
+ * The <em>tail</em> of the queue is that element that has been on the
+ * queue the shortest time. New elements
+ * are inserted at the tail of the queue, and the queue retrieval
+ * operations obtain elements at the head of the queue.
+ * Linked queues typically have higher throughput than array-based queues but
+ * less predictable performance in most concurrent applications.
+ *
+ * <p> The optional capacity bound constructor argument serves as a
+ * way to prevent excessive queue 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
+ * queue above capacity.
+ *
+ * <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.5
+ * @author Doug Lea
+ * @param <E> the type of elements held in this collection
+ *
+ */
+public class LinkedBlockingQueue<E> extends AbstractQueue<E>
+ implements BlockingQueue<E>, java.io.Serializable {
+ private static final long serialVersionUID = -6903933977591709194L;
+
+ /*
+ * A variant of the "two lock queue" algorithm. The putLock gates
+ * entry to put (and offer), and has an associated condition for
+ * waiting puts. Similarly for the takeLock. The "count" field
+ * that they both rely on is maintained as an atomic to avoid
+ * needing to get both locks in most cases. Also, to minimize need
+ * for puts to get takeLock and vice-versa, cascading notifies are
+ * used. When a put notices that it has enabled at least one take,
+ * it signals taker. That taker in turn signals others if more
+ * items have been entered since the signal. And symmetrically for
+ * takes signalling puts. Operations such as remove(Object) and
+ * iterators acquire both locks.
+ */
+
+ /**
+ * Linked list node class
+ */
+ static class Node<E> {
+ /** The item, volatile to ensure barrier separating write and read */
+ volatile E item;
+ Node<E> next;
+ Node(E x) { item = x; }
+ }
+
+ /** The capacity bound, or Integer.MAX_VALUE if none */
+ private final int capacity;
+
+ /** Current number of elements */
+ private final AtomicInteger count = new AtomicInteger(0);
+
+ /** Head of linked list */
+ private transient Node<E> head;
+
+ /** Tail of linked list */
+ private transient Node<E> last;
+
+ /** Lock held by take, poll, etc */
+ private final ReentrantLock takeLock = new ReentrantLock();
+
+ /** Wait queue for waiting takes */
+ private final Condition notEmpty = takeLock.newCondition();
+
+ /** Lock held by put, offer, etc */
+ private final ReentrantLock putLock = new ReentrantLock();
+
+ /** Wait queue for waiting puts */
+ private final Condition notFull = putLock.newCondition();
+
+ /**
+ * Signals a waiting take. Called only from put/offer (which do not
+ * otherwise ordinarily lock takeLock.)
+ */
+ private void signalNotEmpty() {
+ final ReentrantLock takeLock = this.takeLock;
+ takeLock.lock();
+ try {
+ notEmpty.signal();
+ } finally {
+ takeLock.unlock();
+ }
+ }
+
+ /**
+ * Signals a waiting put. Called only from take/poll.
+ */
+ private void signalNotFull() {
+ final ReentrantLock putLock = this.putLock;
+ putLock.lock();
+ try {
+ notFull.signal();
+ } finally {
+ putLock.unlock();
+ }
+ }
+
+ /**
+ * Creates a node and links it at end of queue.
+ * @param x the item
+ */
+ private void insert(E x) {
+ last = last.next = new Node<E>(x);
+ }
+
+ /**
+ * Removes a node from head of queue,
+ * @return the node
+ */
+ private E extract() {
+ Node<E> first = head.next;
+ head = first;
+ E x = first.item;
+ first.item = null;
+ return x;
+ }
+
+ /**
+ * Lock to prevent both puts and takes.
+ */
+ private void fullyLock() {
+ putLock.lock();
+ takeLock.lock();
+ }
+
+ /**
+ * Unlock to allow both puts and takes.
+ */
+ private void fullyUnlock() {
+ takeLock.unlock();
+ putLock.unlock();
+ }
+
+
+ /**
+ * Creates a <tt>LinkedBlockingQueue</tt> with a capacity of
+ * {@link Integer#MAX_VALUE}.
+ */
+ public LinkedBlockingQueue() {
+ this(Integer.MAX_VALUE);
+ }
+
+ /**
+ * Creates a <tt>LinkedBlockingQueue</tt> with the given (fixed) capacity.
+ *
+ * @param capacity the capacity of this queue
+ * @throws IllegalArgumentException if <tt>capacity</tt> is not greater
+ * than zero
+ */
+ public LinkedBlockingQueue(int capacity) {
+ if (capacity <= 0) throw new IllegalArgumentException();
+ this.capacity = capacity;
+ last = head = new Node<E>(null);
+ }
+
+ /**
+ * Creates a <tt>LinkedBlockingQueue</tt> 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 LinkedBlockingQueue(Collection<? extends E> c) {
+ this(Integer.MAX_VALUE);
+ for (E e : c)
+ add(e);
+ }
+
+
+ // this doc comment is overridden to remove the reference to collections
+ // greater in size than Integer.MAX_VALUE
+ /**
+ * Returns the number of elements in this queue.
+ *
+ * @return the number of elements in this queue
+ */
+ public int size() {
+ return count.get();
+ }
+
+ // this doc comment is a modified copy of the inherited doc comment,
+ // without the reference to unlimited queues.
+ /**
+ * 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.
+ *
+ * <p>Note that you <em>cannot</em> always tell if an attempt to insert
+ * an element will succeed by inspecting <tt>remainingCapacity</tt>
+ * because it may be the case that another thread is about to
+ * insert or remove an element.
+ */
+ public int remainingCapacity() {
+ return capacity - count.get();
+ }
+
+ /**
+ * Inserts the specified element at the tail of this queue, waiting if
+ * necessary for space to become available.
+ *
+ * @throws InterruptedException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ */
+ 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.
+ int c = -1;
+ final ReentrantLock putLock = this.putLock;
+ final AtomicInteger count = this.count;
+ putLock.lockInterruptibly();
+ try {
+ /*
+ * Note that count is used in wait guard even though it is
+ * 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.
+ */
+ try {
+ while (count.get() == capacity)
+ notFull.await();
+ } catch (InterruptedException ie) {
+ notFull.signal(); // propagate to a non-interrupted thread
+ throw ie;
+ }
+ insert(e);
+ c = count.getAndIncrement();
+ if (c + 1 < capacity)
+ notFull.signal();
+ } finally {
+ putLock.unlock();
+ }
+ if (c == 0)
+ signalNotEmpty();
+ }
+
+ /**
+ * 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
+ * the specified waiting time elapses before space is available.
+ * @throws InterruptedException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean offer(E e, long timeout, TimeUnit unit)
+ throws InterruptedException {
+
+ if (e == null) throw new NullPointerException();
+ long nanos = unit.toNanos(timeout);
+ int c = -1;
+ final ReentrantLock putLock = this.putLock;
+ 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;
+ }
+ if (nanos <= 0)
+ return false;
+ try {
+ nanos = notFull.awaitNanos(nanos);
+ } catch (InterruptedException ie) {
+ notFull.signal(); // propagate to a non-interrupted thread
+ throw ie;
+ }
+ }
+ } finally {
+ putLock.unlock();
+ }
+ if (c == 0)
+ signalNotEmpty();
+ return true;
+ }
+
+ /**
+ * 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
+ * is full.
+ * When using a capacity-restricted queue, this method is generally
+ * preferable to method {@link BlockingQueue#add add}, which can fail to
+ * insert an element only by throwing an exception.
+ *
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean offer(E e) {
+ if (e == null) throw new NullPointerException();
+ final AtomicInteger count = this.count;
+ if (count.get() == capacity)
+ return false;
+ int c = -1;
+ final ReentrantLock putLock = this.putLock;
+ putLock.lock();
+ try {
+ if (count.get() < capacity) {
+ insert(e);
+ c = count.getAndIncrement();
+ if (c + 1 < capacity)
+ notFull.signal();
+ }
+ } finally {
+ putLock.unlock();
+ }
+ if (c == 0)
+ signalNotEmpty();
+ return c >= 0;
+ }
+
+
+ public E take() throws InterruptedException {
+ E x;
+ int c = -1;
+ final AtomicInteger count = this.count;
+ 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;
+ }
+
+ x = extract();
+ c = count.getAndDecrement();
+ if (c > 1)
+ notEmpty.signal();
+ } finally {
+ takeLock.unlock();
+ }
+ if (c == capacity)
+ signalNotFull();
+ return x;
+ }
+
+ public E poll(long timeout, TimeUnit unit) throws InterruptedException {
+ E x = null;
+ int c = -1;
+ long nanos = unit.toNanos(timeout);
+ final AtomicInteger count = this.count;
+ final ReentrantLock takeLock = this.takeLock;
+ takeLock.lockInterruptibly();
+ try {
+ for (;;) {
+ if (count.get() > 0) {
+ x = extract();
+ c = count.getAndDecrement();
+ if (c > 1)
+ notEmpty.signal();
+ break;
+ }
+ if (nanos <= 0)
+ return null;
+ try {
+ nanos = notEmpty.awaitNanos(nanos);
+ } catch (InterruptedException ie) {
+ notEmpty.signal(); // propagate to a non-interrupted thread
+ throw ie;
+ }
+ }
+ } finally {
+ takeLock.unlock();
+ }
+ if (c == capacity)
+ signalNotFull();
+ return x;
+ }
+
+ public E poll() {
+ final AtomicInteger count = this.count;
+ if (count.get() == 0)
+ return null;
+ E x = null;
+ int c = -1;
+ final ReentrantLock takeLock = this.takeLock;
+ takeLock.lock();
+ try {
+ if (count.get() > 0) {
+ x = extract();
+ c = count.getAndDecrement();
+ if (c > 1)
+ notEmpty.signal();
+ }
+ } finally {
+ takeLock.unlock();
+ }
+ if (c == capacity)
+ signalNotFull();
+ return x;
+ }
+
+
+ public E peek() {
+ if (count.get() == 0)
+ return null;
+ final ReentrantLock takeLock = this.takeLock;
+ takeLock.lock();
+ try {
+ Node<E> first = head.next;
+ if (first == null)
+ return null;
+ else
+ return first.item;
+ } finally {
+ takeLock.unlock();
+ }
+ }
+
+ /**
+ * 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
+ * elements.
+ * Returns <tt>true</tt> 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
+ */
+ 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) {
+ if (o.equals(p.item)) {
+ removed = true;
+ break;
+ }
+ 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();
+ }
+ } finally {
+ fullyUnlock();
+ }
+ return removed;
+ }
+
+ /**
+ * Returns an array containing all of the elements in this queue, in
+ * proper sequence.
+ *
+ * <p>The returned array will be "safe" in that no references to it are
+ * maintained by this queue. (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 queue
+ */
+ public Object[] toArray() {
+ fullyLock();
+ try {
+ int size = count.get();
+ Object[] a = new Object[size];
+ int k = 0;
+ for (Node<E> p = head.next; p != null; p = p.next)
+ a[k++] = p.item;
+ return a;
+ } finally {
+ fullyUnlock();
+ }
+ }
+
+ /**
+ * Returns an array containing all of the elements in this queue, in
+ * proper sequence; the runtime type of the returned array is that of
+ * the specified array. If the queue 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 queue.
+ *
+ * <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>.
+ *
+ * <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.
+ * The following code can be used to dump the queue into a newly
+ * allocated array of <tt>String</tt>:
+ *
+ * <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>.
+ *
+ * @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
+ * same runtime type is allocated for this purpose
+ * @return an array containing all of the elements in this queue
+ * @throws ArrayStoreException if the runtime type of the specified array
+ * is not a supertype of the runtime type of every element in
+ * this queue
+ * @throws NullPointerException if the specified array is null
+ */
+ public <T> T[] toArray(T[] a) {
+ fullyLock();
+ try {
+ int size = count.get();
+ if (a.length < size)
+ a = (T[])java.lang.reflect.Array.newInstance
+ (a.getClass().getComponentType(), size);
+
+ int k = 0;
+ for (Node p = head.next; p != null; p = p.next)
+ a[k++] = (T)p.item;
+ if (a.length > k)
+ a[k] = null;
+ return a;
+ } finally {
+ fullyUnlock();
+ }
+ }
+
+ public String toString() {
+ fullyLock();
+ try {
+ return super.toString();
+ } finally {
+ fullyUnlock();
+ }
+ }
+
+ /**
+ * Atomically removes all of the elements from this queue.
+ * The queue will be empty after this call returns.
+ */
+ public void clear() {
+ fullyLock();
+ try {
+ head.next = null;
+ assert head.item == null;
+ last = head;
+ if (count.getAndSet(0) == capacity)
+ notFull.signalAll();
+ } finally {
+ fullyUnlock();
+ }
+ }
+
+ /**
+ * @throws UnsupportedOperationException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @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;
+ }
+
+ /**
+ * @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();
+ fullyLock();
+ 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();
+ }
+ return n;
+ } finally {
+ fullyUnlock();
+ }
+ }
+
+ /**
+ * 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},
+ * 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 queue in proper sequence
+ */
+ public Iterator<E> iterator() {
+ return new Itr();
+ }
+
+ private class Itr implements Iterator<E> {
+ /*
+ * Basic weak-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.
+ */
+ private Node<E> current;
+ private Node<E> lastRet;
+ private E currentElement;
+
+ Itr() {
+ final ReentrantLock putLock = LinkedBlockingQueue.this.putLock;
+ final ReentrantLock takeLock = LinkedBlockingQueue.this.takeLock;
+ putLock.lock();
+ takeLock.lock();
+ try {
+ current = head.next;
+ if (current != null)
+ currentElement = current.item;
+ } finally {
+ takeLock.unlock();
+ putLock.unlock();
+ }
+ }
+
+ public boolean hasNext() {
+ return current != null;
+ }
+
+ public E next() {
+ final ReentrantLock putLock = LinkedBlockingQueue.this.putLock;
+ final ReentrantLock takeLock = LinkedBlockingQueue.this.takeLock;
+ putLock.lock();
+ takeLock.lock();
+ try {
+ if (current == null)
+ throw new NoSuchElementException();
+ E x = currentElement;
+ lastRet = current;
+ current = current.next;
+ if (current != null)
+ currentElement = current.item;
+ return x;
+ } finally {
+ takeLock.unlock();
+ putLock.unlock();
+ }
+ }
+
+ 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();
+ 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();
+ }
+ } finally {
+ takeLock.unlock();
+ putLock.unlock();
+ }
+ }
+ }
+
+ /**
+ * 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,
+ * followed by a null
+ * @param s the stream
+ */
+ private void writeObject(java.io.ObjectOutputStream s)
+ throws java.io.IOException {
+
+ fullyLock();
+ try {
+ // Write out any hidden stuff, plus capacity
+ s.defaultWriteObject();
+
+ // Write out all elements in the proper order.
+ for (Node<E> p = head.next; p != null; p = p.next)
+ s.writeObject(p.item);
+
+ // Use trailing null as sentinel
+ s.writeObject(null);
+ } finally {
+ fullyUnlock();
+ }
+ }
+
+ /**
+ * Reconstitute this 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();
+
+ count.set(0);
+ last = head = new Node<E>(null);
+
+ // Read in all elements and place in queue
+ for (;;) {
+ E item = (E)s.readObject();
+ if (item == null)
+ break;
+ add(item);
+ }
+ }
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/PriorityBlockingQueue.java b/libjava/classpath/external/jsr166/java/util/concurrent/PriorityBlockingQueue.java
new file mode 100644
index 000000000..9466aa477
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/PriorityBlockingQueue.java
@@ -0,0 +1,563 @@
+/*
+ * 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.concurrent.locks.*;
+import java.util.*;
+
+/**
+ * An unbounded {@linkplain BlockingQueue blocking queue} that uses
+ * the same ordering rules as class {@link PriorityQueue} and supplies
+ * blocking retrieval operations. While this queue is logically
+ * unbounded, attempted additions may fail due to resource exhaustion
+ * (causing <tt>OutOfMemoryError</tt>). This class does not permit
+ * <tt>null</tt> elements. A priority queue relying on {@linkplain
+ * Comparable natural ordering} also does not permit insertion of
+ * non-comparable objects (doing so results in
+ * <tt>ClassCastException</tt>).
+ *
+ * <p>This class and its iterator implement all of the
+ * <em>optional</em> methods of the {@link Collection} and {@link
+ * Iterator} interfaces. The Iterator provided in method {@link
+ * #iterator()} is <em>not</em> guaranteed to traverse the elements of
+ * the PriorityBlockingQueue in any particular order. If you need
+ * ordered traversal, consider using
+ * <tt>Arrays.sort(pq.toArray())</tt>. Also, method <tt>drainTo</tt>
+ * can be used to <em>remove</em> some or all elements in priority
+ * order and place them in another collection.
+ *
+ * <p>Operations on this class make no guarantees about the ordering
+ * of elements with equal priority. If you need to enforce an
+ * ordering, you can define custom classes or comparators that use a
+ * secondary key to break ties in primary priority values. For
+ * example, here is a class that applies first-in-first-out
+ * tie-breaking to comparable elements. To use it, you would insert a
+ * <tt>new FIFOEntry(anEntry)</tt> instead of a plain entry object.
+ *
+ * <pre>
+ * class FIFOEntry&lt;E extends Comparable&lt;? super E&gt;&gt;
+ * implements Comparable&lt;FIFOEntry&lt;E&gt;&gt; {
+ * final static AtomicLong seq = new AtomicLong();
+ * final long seqNum;
+ * final E entry;
+ * public FIFOEntry(E entry) {
+ * seqNum = seq.getAndIncrement();
+ * this.entry = entry;
+ * }
+ * public E getEntry() { return entry; }
+ * public int compareTo(FIFOEntry&lt;E&gt; other) {
+ * int res = entry.compareTo(other.entry);
+ * if (res == 0 &amp;&amp; other.entry != this.entry)
+ * res = (seqNum &lt; other.seqNum ? -1 : 1);
+ * return res;
+ * }
+ * }</pre>
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <E> the type of elements held in this collection
+ */
+public class PriorityBlockingQueue<E> extends AbstractQueue<E>
+ implements BlockingQueue<E>, java.io.Serializable {
+ private static final long serialVersionUID = 5595510919245408276L;
+
+ private final PriorityQueue<E> q;
+ private final ReentrantLock lock = new ReentrantLock(true);
+ private final Condition notEmpty = lock.newCondition();
+
+ /**
+ * Creates a <tt>PriorityBlockingQueue</tt> with the default
+ * initial capacity (11) that orders its elements according to
+ * their {@linkplain Comparable natural ordering}.
+ */
+ public PriorityBlockingQueue() {
+ q = new PriorityQueue<E>();
+ }
+
+ /**
+ * Creates a <tt>PriorityBlockingQueue</tt> with the specified
+ * initial capacity that orders its elements according to their
+ * {@linkplain Comparable natural ordering}.
+ *
+ * @param initialCapacity the initial capacity for this priority queue
+ * @throws IllegalArgumentException if <tt>initialCapacity</tt> is less
+ * than 1
+ */
+ public PriorityBlockingQueue(int initialCapacity) {
+ q = new PriorityQueue<E>(initialCapacity, null);
+ }
+
+ /**
+ * Creates a <tt>PriorityBlockingQueue</tt> with the specified initial
+ * capacity that orders its elements according to the specified
+ * comparator.
+ *
+ * @param initialCapacity the initial capacity for this priority queue
+ * @param comparator the comparator that will be used to order this
+ * priority queue. If {@code null}, the {@linkplain Comparable
+ * natural ordering} of the elements will be used.
+ * @throws IllegalArgumentException if <tt>initialCapacity</tt> is less
+ * than 1
+ */
+ public PriorityBlockingQueue(int initialCapacity,
+ Comparator<? super E> comparator) {
+ q = new PriorityQueue<E>(initialCapacity, comparator);
+ }
+
+ /**
+ * Creates a <tt>PriorityBlockingQueue</tt> containing the elements
+ * in the specified collection. If the specified collection is a
+ * {@link SortedSet} or a {@link PriorityQueue}, this
+ * priority queue will be ordered according to the same ordering.
+ * Otherwise, this priority queue will be ordered according to the
+ * {@linkplain Comparable natural ordering} of its elements.
+ *
+ * @param c the collection whose elements are to be placed
+ * into this priority queue
+ * @throws ClassCastException if elements of the specified collection
+ * cannot be compared to one another according to the priority
+ * queue's ordering
+ * @throws NullPointerException if the specified collection or any
+ * of its elements are null
+ */
+ public PriorityBlockingQueue(Collection<? extends E> c) {
+ q = new PriorityQueue<E>(c);
+ }
+
+ /**
+ * Inserts the specified element into this priority queue.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> (as specified by {@link Collection#add})
+ * @throws ClassCastException if the specified element cannot be compared
+ * with elements currently in the priority queue according to the
+ * priority queue's ordering
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean add(E e) {
+ return offer(e);
+ }
+
+ /**
+ * Inserts the specified element into this priority queue.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> (as specified by {@link Queue#offer})
+ * @throws ClassCastException if the specified element cannot be compared
+ * with elements currently in the priority queue according to the
+ * priority queue's ordering
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean offer(E e) {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ boolean ok = q.offer(e);
+ assert ok;
+ notEmpty.signal();
+ return true;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Inserts the specified element into this priority queue. As the queue is
+ * unbounded this method will never block.
+ *
+ * @param e the element to add
+ * @throws ClassCastException if the specified element cannot be compared
+ * with elements currently in the priority queue according to the
+ * priority queue's ordering
+ * @throws NullPointerException if the specified element is null
+ */
+ public void put(E e) {
+ offer(e); // never need to block
+ }
+
+ /**
+ * Inserts the specified element into this priority queue. As the queue is
+ * unbounded this method will never block.
+ *
+ * @param e the element to add
+ * @param timeout This parameter is ignored as the method never blocks
+ * @param unit This parameter is ignored as the method never blocks
+ * @return <tt>true</tt>
+ * @throws ClassCastException if the specified element cannot be compared
+ * with elements currently in the priority queue according to the
+ * priority queue's ordering
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean offer(E e, long timeout, TimeUnit unit) {
+ return offer(e); // never need to block
+ }
+
+ public E poll() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return q.poll();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E take() throws InterruptedException {
+ final ReentrantLock lock = this.lock;
+ lock.lockInterruptibly();
+ try {
+ try {
+ while (q.size() == 0)
+ notEmpty.await();
+ } catch (InterruptedException ie) {
+ notEmpty.signal(); // propagate to non-interrupted thread
+ throw ie;
+ }
+ E x = q.poll();
+ assert x != null;
+ return x;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E poll(long timeout, TimeUnit unit) throws InterruptedException {
+ long nanos = unit.toNanos(timeout);
+ final ReentrantLock lock = this.lock;
+ lock.lockInterruptibly();
+ try {
+ for (;;) {
+ E x = q.poll();
+ if (x != null)
+ return x;
+ if (nanos <= 0)
+ return null;
+ try {
+ nanos = notEmpty.awaitNanos(nanos);
+ } catch (InterruptedException ie) {
+ notEmpty.signal(); // propagate to non-interrupted thread
+ throw ie;
+ }
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E peek() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return q.peek();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns the comparator used to order the elements in this queue,
+ * or <tt>null</tt> if this queue uses the {@linkplain Comparable
+ * natural ordering} of its elements.
+ *
+ * @return the comparator used to order the elements in this queue,
+ * or <tt>null</tt> if this queue uses the natural
+ * ordering of its elements
+ */
+ public Comparator<? super E> comparator() {
+ return q.comparator();
+ }
+
+ public int size() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return q.size();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Always returns <tt>Integer.MAX_VALUE</tt> because
+ * a <tt>PriorityBlockingQueue</tt> is not capacity constrained.
+ * @return <tt>Integer.MAX_VALUE</tt>
+ */
+ public int remainingCapacity() {
+ return Integer.MAX_VALUE;
+ }
+
+ /**
+ * Removes a single instance of the specified element from this queue,
+ * 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 {@code true} if and only 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
+ */
+ public boolean remove(Object o) {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return q.remove(o);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns {@code true} if this queue contains the specified element.
+ * More formally, returns {@code true} if and only if this queue contains
+ * at least one element {@code e} such that {@code o.equals(e)}.
+ *
+ * @param o object to be checked for containment in this queue
+ * @return <tt>true</tt> if this queue contains the specified element
+ */
+ public boolean contains(Object o) {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return q.contains(o);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns an array containing all of the elements in this queue.
+ * The returned array elements are in no particular order.
+ *
+ * <p>The returned array will be "safe" in that no references to it are
+ * maintained by this queue. (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 queue
+ */
+ public Object[] toArray() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return q.toArray();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+
+ public String toString() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return q.toString();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws UnsupportedOperationException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public int drainTo(Collection<? super E> c) {
+ if (c == null)
+ throw new NullPointerException();
+ if (c == this)
+ throw new IllegalArgumentException();
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ int n = 0;
+ E e;
+ while ( (e = q.poll()) != null) {
+ c.add(e);
+ ++n;
+ }
+ return n;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @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();
+ if (maxElements <= 0)
+ return 0;
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ int n = 0;
+ E e;
+ while (n < maxElements && (e = q.poll()) != null) {
+ c.add(e);
+ ++n;
+ }
+ return n;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Atomically removes all of the elements from this queue.
+ * The queue will be empty after this call returns.
+ */
+ public void clear() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ q.clear();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns an array containing all of the elements in this queue; the
+ * runtime type of the returned array is that of the specified array.
+ * The returned array elements are in no particular order.
+ * If the queue 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 queue.
+ *
+ * <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>.
+ *
+ * <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.
+ * The following code can be used to dump the queue into a newly
+ * allocated array of <tt>String</tt>:
+ *
+ * <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>.
+ *
+ * @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
+ * same runtime type is allocated for this purpose
+ * @return an array containing all of the elements in this queue
+ * @throws ArrayStoreException if the runtime type of the specified array
+ * is not a supertype of the runtime type of every element in
+ * this queue
+ * @throws NullPointerException if the specified array is null
+ */
+ public <T> T[] toArray(T[] a) {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return q.toArray(a);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns an iterator over the elements in this queue. The
+ * iterator does not return the elements in any particular order.
+ * The returned <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.
+ *
+ * @return an iterator over the elements in this queue
+ */
+ public Iterator<E> iterator() {
+ return new Itr(toArray());
+ }
+
+ /**
+ * Snapshot iterator that works off copy of underlying q array.
+ */
+ private class Itr implements Iterator<E> {
+ final Object[] array; // Array of all elements
+ int cursor; // index of next element to return;
+ int lastRet; // index of last element, or -1 if no such
+
+ Itr(Object[] array) {
+ lastRet = -1;
+ this.array = array;
+ }
+
+ public boolean hasNext() {
+ return cursor < array.length;
+ }
+
+ public E next() {
+ if (cursor >= array.length)
+ throw new NoSuchElementException();
+ lastRet = cursor;
+ return (E)array[cursor++];
+ }
+
+ public void remove() {
+ if (lastRet < 0)
+ throw new IllegalStateException();
+ Object x = array[lastRet];
+ lastRet = -1;
+ // Traverse underlying queue to find == element,
+ // not just a .equals element.
+ lock.lock();
+ try {
+ for (Iterator it = q.iterator(); it.hasNext(); ) {
+ if (it.next() == x) {
+ it.remove();
+ return;
+ }
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+ }
+
+ /**
+ * Saves the state to a stream (that is, serializes it). This
+ * merely wraps default serialization within lock. The
+ * serialization strategy for items is left to underlying
+ * Queue. Note that locking is not needed on deserialization, so
+ * readObject is not defined, just relying on default.
+ */
+ private void writeObject(java.io.ObjectOutputStream s)
+ throws java.io.IOException {
+ lock.lock();
+ try {
+ s.defaultWriteObject();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/RejectedExecutionException.java b/libjava/classpath/external/jsr166/java/util/concurrent/RejectedExecutionException.java
new file mode 100644
index 000000000..30b043d66
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/RejectedExecutionException.java
@@ -0,0 +1,62 @@
+/*
+ * 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;
+
+/**
+ * Exception thrown by an {@link Executor} when a task cannot be
+ * accepted for execution.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class RejectedExecutionException extends RuntimeException {
+ private static final long serialVersionUID = -375805702767069545L;
+
+ /**
+ * Constructs a <tt>RejectedExecutionException</tt> with no detail message.
+ * The cause is not initialized, and may subsequently be
+ * initialized by a call to {@link #initCause(Throwable) initCause}.
+ */
+ public RejectedExecutionException() { }
+
+ /**
+ * Constructs a <tt>RejectedExecutionException</tt> with the
+ * specified detail message. The cause is not initialized, and may
+ * subsequently be initialized by a call to {@link
+ * #initCause(Throwable) initCause}.
+ *
+ * @param message the detail message
+ */
+ public RejectedExecutionException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a <tt>RejectedExecutionException</tt> with the
+ * specified detail message and cause.
+ *
+ * @param message the detail message
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method)
+ */
+ public RejectedExecutionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Constructs a <tt>RejectedExecutionException</tt> with the
+ * specified cause. The detail message is set to: <pre> (cause ==
+ * null ? null : cause.toString())</pre> (which typically contains
+ * the class and detail message of <tt>cause</tt>).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method)
+ */
+ public RejectedExecutionException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/RejectedExecutionHandler.java b/libjava/classpath/external/jsr166/java/util/concurrent/RejectedExecutionHandler.java
new file mode 100644
index 000000000..4b4bbeab1
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/RejectedExecutionHandler.java
@@ -0,0 +1,33 @@
+/*
+ * 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 handler for tasks that cannot be executed by a {@link
+ * ThreadPoolExecutor}.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public interface RejectedExecutionHandler {
+
+ /**
+ * Method that may be invoked by a {@link ThreadPoolExecutor} when
+ * <tt>execute</tt> cannot accept a task. This may occur when no
+ * more threads or queue slots are available because their bounds
+ * would be exceeded, or upon shutdown of the Executor.
+ *
+ * In the absence other alternatives, the method may throw an
+ * unchecked {@link RejectedExecutionException}, which will be
+ * propagated to the caller of <tt>execute</tt>.
+ *
+ * @param r the runnable task requested to be executed
+ * @param executor the executor attempting to execute this task
+ * @throws RejectedExecutionException if there is no remedy
+ */
+ void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/RunnableFuture.java b/libjava/classpath/external/jsr166/java/util/concurrent/RunnableFuture.java
new file mode 100644
index 000000000..d74211d13
--- /dev/null
+++ b/libjava/classpath/external/jsr166/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/libjava/classpath/external/jsr166/java/util/concurrent/RunnableScheduledFuture.java b/libjava/classpath/external/jsr166/java/util/concurrent/RunnableScheduledFuture.java
new file mode 100644
index 000000000..0e8cc328c
--- /dev/null
+++ b/libjava/classpath/external/jsr166/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/libjava/classpath/external/jsr166/java/util/concurrent/ScheduledExecutorService.java b/libjava/classpath/external/jsr166/java/util/concurrent/ScheduledExecutorService.java
new file mode 100644
index 000000000..c170c4a52
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/ScheduledExecutorService.java
@@ -0,0 +1,159 @@
+/*
+ * 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.concurrent.atomic.*;
+import java.util.*;
+
+/**
+ * An {@link ExecutorService} that can schedule commands to run after a given
+ * delay, or to execute periodically.
+ *
+ * <p> The <tt>schedule</tt> methods create tasks with various delays
+ * and return a task object that can be used to cancel or check
+ * execution. The <tt>scheduleAtFixedRate</tt> and
+ * <tt>scheduleWithFixedDelay</tt> methods create and execute tasks
+ * that run periodically until cancelled.
+ *
+ * <p> Commands submitted using the {@link Executor#execute} and
+ * {@link ExecutorService} <tt>submit</tt> methods are scheduled with
+ * a requested delay of zero. Zero and negative delays (but not
+ * periods) are also allowed in <tt>schedule</tt> methods, and are
+ * treated as requests for immediate execution.
+ *
+ * <p>All <tt>schedule</tt> methods accept <em>relative</em> delays and
+ * periods as arguments, not absolute times or dates. It is a simple
+ * matter to transform an absolute time represented as a {@link
+ * java.util.Date} to the required form. For example, to schedule at
+ * a certain future <tt>date</tt>, you can use: <tt>schedule(task,
+ * date.getTime() - System.currentTimeMillis(),
+ * TimeUnit.MILLISECONDS)</tt>. Beware however that expiration of a
+ * relative delay need not coincide with the current <tt>Date</tt> at
+ * which the task is enabled due to network time synchronization
+ * protocols, clock drift, or other factors.
+ *
+ * The {@link Executors} class provides convenient factory methods for
+ * the ScheduledExecutorService implementations provided in this package.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * Here is a class with a method that sets up a ScheduledExecutorService
+ * to beep every ten seconds for an hour:
+ *
+ * <pre>
+ * import static java.util.concurrent.TimeUnit.*;
+ * class BeeperControl {
+ * private final ScheduledExecutorService scheduler =
+ * Executors.newScheduledThreadPool(1);
+ *
+ * public void beepForAnHour() {
+ * final Runnable beeper = new Runnable() {
+ * public void run() { System.out.println("beep"); }
+ * };
+ * final ScheduledFuture&lt;?&gt; beeperHandle =
+ * scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);
+ * scheduler.schedule(new Runnable() {
+ * public void run() { beeperHandle.cancel(true); }
+ * }, 60 * 60, SECONDS);
+ * }
+ * }
+ * </pre>
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public interface ScheduledExecutorService extends ExecutorService {
+
+ /**
+ * Creates and executes a one-shot action that becomes enabled
+ * after the given delay.
+ *
+ * @param command the task to execute
+ * @param delay the time from now to delay execution
+ * @param unit the time unit of the delay parameter
+ * @return a ScheduledFuture representing pending completion of
+ * the task and whose <tt>get()</tt> method will return
+ * <tt>null</tt> upon completion
+ * @throws RejectedExecutionException if the task cannot be
+ * scheduled for execution
+ * @throws NullPointerException if command is null
+ */
+ public ScheduledFuture<?> schedule(Runnable command,
+ long delay, TimeUnit unit);
+
+ /**
+ * Creates and executes a ScheduledFuture that becomes enabled after the
+ * given delay.
+ *
+ * @param callable the function to execute
+ * @param delay the time from now to delay execution
+ * @param unit the time unit of the delay parameter
+ * @return a ScheduledFuture that can be used to extract result or cancel
+ * @throws RejectedExecutionException if the task cannot be
+ * scheduled for execution
+ * @throws NullPointerException if callable is null
+ */
+ public <V> ScheduledFuture<V> schedule(Callable<V> callable,
+ long delay, TimeUnit unit);
+
+ /**
+ * Creates and executes a periodic action that becomes enabled first
+ * after the given initial delay, and subsequently with the given
+ * period; that is executions will commence after
+ * <tt>initialDelay</tt> then <tt>initialDelay+period</tt>, then
+ * <tt>initialDelay + 2 * period</tt>, and so on.
+ * If any execution of the task
+ * encounters an exception, subsequent executions are suppressed.
+ * Otherwise, the task will only terminate via cancellation or
+ * termination of the executor. If any execution of this task
+ * takes longer than its period, then subsequent executions
+ * may start late, but will not concurrently execute.
+ *
+ * @param command the task to execute
+ * @param initialDelay the time to delay first execution
+ * @param period the period between successive executions
+ * @param unit the time unit of the initialDelay and period parameters
+ * @return a ScheduledFuture representing pending completion of
+ * the task, and whose <tt>get()</tt> method will throw an
+ * exception upon cancellation
+ * @throws RejectedExecutionException if the task cannot be
+ * scheduled for execution
+ * @throws NullPointerException if command is null
+ * @throws IllegalArgumentException if period less than or equal to zero
+ */
+ public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
+ long initialDelay,
+ long period,
+ TimeUnit unit);
+
+ /**
+ * Creates and executes a periodic action that becomes enabled first
+ * after the given initial delay, and subsequently with the
+ * given delay between the termination of one execution and the
+ * commencement of the next. If any execution of the task
+ * encounters an exception, subsequent executions are suppressed.
+ * Otherwise, the task will only terminate via cancellation or
+ * termination of the executor.
+ *
+ * @param command the task to execute
+ * @param initialDelay the time to delay first execution
+ * @param delay the delay between the termination of one
+ * execution and the commencement of the next
+ * @param unit the time unit of the initialDelay and delay parameters
+ * @return a ScheduledFuture representing pending completion of
+ * the task, and whose <tt>get()</tt> method will throw an
+ * exception upon cancellation
+ * @throws RejectedExecutionException if the task cannot be
+ * scheduled for execution
+ * @throws NullPointerException if command is null
+ * @throws IllegalArgumentException if delay less than or equal to zero
+ */
+ public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
+ long initialDelay,
+ long delay,
+ TimeUnit unit);
+
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/ScheduledFuture.java b/libjava/classpath/external/jsr166/java/util/concurrent/ScheduledFuture.java
new file mode 100644
index 000000000..239d681f6
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/ScheduledFuture.java
@@ -0,0 +1,19 @@
+/*
+ * 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 delayed result-bearing action that can be cancelled.
+ * Usually a scheduled future is the result of scheduling
+ * a task with a {@link ScheduledExecutorService}.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <V> The result type returned by this Future
+ */
+public interface ScheduledFuture<V> extends Delayed, Future<V> {
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/ScheduledThreadPoolExecutor.java b/libjava/classpath/external/jsr166/java/util/concurrent/ScheduledThreadPoolExecutor.java
new file mode 100644
index 000000000..f08b9ac2e
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/ScheduledThreadPoolExecutor.java
@@ -0,0 +1,626 @@
+/*
+ * 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.concurrent.atomic.*;
+import java.util.*;
+
+/**
+ * A {@link ThreadPoolExecutor} that can additionally schedule
+ * commands to run after a given delay, or to execute
+ * periodically. This class is preferable to {@link java.util.Timer}
+ * when multiple worker threads are needed, or when the additional
+ * flexibility or capabilities of {@link ThreadPoolExecutor} (which
+ * this class extends) are required.
+ *
+ * <p> Delayed tasks execute no sooner than they are enabled, but
+ * without any real-time guarantees about when, after they are
+ * enabled, they will commence. Tasks scheduled for exactly the same
+ * execution time are enabled in first-in-first-out (FIFO) order of
+ * submission.
+ *
+ * <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
+ * <tt>corePoolSize</tt> threads and an unbounded queue, adjustments
+ * to <tt>maximumPoolSize</tt> have no useful effect.
+ *
+ * <p><b>Extension notes:</b> This class overrides {@link
+ * AbstractExecutorService} <tt>submit</tt> methods to generate
+ * internal 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
+ * <tt>decorateTask</tt> (one version each for <tt>Runnable</tt> and
+ * <tt>Callable</tt>) that can be used to customize the concrete task
+ * types used to execute commands entered via <tt>execute</tt>,
+ * <tt>submit</tt>, <tt>schedule</tt>, <tt>scheduleAtFixedRate</tt>,
+ * and <tt>scheduleWithFixedDelay</tt>. By default, a
+ * <tt>ScheduledThreadPoolExecutor</tt> uses a task type extending
+ * {@link FutureTask}. However, this may be modified or replaced using
+ * subclasses of the form:
+ *
+ * <pre>
+ * public class CustomScheduledExecutor extends ScheduledThreadPoolExecutor {
+ *
+ * static class CustomTask&lt;V&gt; implements RunnableScheduledFuture&lt;V&gt; { ... }
+ *
+ * protected &lt;V&gt; RunnableScheduledFuture&lt;V&gt; decorateTask(
+ * Runnable r, RunnableScheduledFuture&lt;V&gt; task) {
+ * return new CustomTask&lt;V&gt;(r, task);
+ * }
+ *
+ * protected &lt;V&gt; RunnableScheduledFuture&lt;V&gt; decorateTask(
+ * Callable&lt;V&gt; c, RunnableScheduledFuture&lt;V&gt; task) {
+ * return new CustomTask&lt;V&gt;(c, task);
+ * }
+ * // ... add constructors, etc.
+ * }
+ * </pre>
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class ScheduledThreadPoolExecutor
+ extends ThreadPoolExecutor
+ implements ScheduledExecutorService {
+
+ /**
+ * False if should cancel/suppress periodic tasks on shutdown.
+ */
+ private volatile boolean continueExistingPeriodicTasksAfterShutdown;
+
+ /**
+ * False if should cancel non-periodic tasks on shutdown.
+ */
+ private volatile boolean executeExistingDelayedTasksAfterShutdown = true;
+
+ /**
+ * Sequence number to break scheduling ties, and in turn to
+ * guarantee FIFO order among tied entries.
+ */
+ private static final AtomicLong sequencer = new AtomicLong(0);
+
+ /** Base of nanosecond timings, to avoid wrapping */
+ private static final long NANO_ORIGIN = System.nanoTime();
+
+ /**
+ * Returns nanosecond time offset by origin
+ */
+ final long now() {
+ return System.nanoTime() - NANO_ORIGIN;
+ }
+
+ private class ScheduledFutureTask<V>
+ extends FutureTask<V> implements RunnableScheduledFuture<V> {
+
+ /** Sequence number to break ties FIFO */
+ private final long sequenceNumber;
+ /** The time the task is enabled to execute in nanoTime units */
+ private long time;
+ /**
+ * Period in nanoseconds for repeating tasks. A positive
+ * value indicates fixed-rate execution. A negative value
+ * indicates fixed-delay execution. A value of 0 indicates a
+ * non-repeating task.
+ */
+ private final long period;
+
+ /**
+ * Creates a one-shot action with given nanoTime-based trigger time.
+ */
+ ScheduledFutureTask(Runnable r, V result, long ns) {
+ super(r, result);
+ this.time = ns;
+ this.period = 0;
+ this.sequenceNumber = sequencer.getAndIncrement();
+ }
+
+ /**
+ * Creates a periodic action with given nano time and period.
+ */
+ ScheduledFutureTask(Runnable r, V result, long ns, long period) {
+ super(r, result);
+ this.time = ns;
+ this.period = period;
+ this.sequenceNumber = sequencer.getAndIncrement();
+ }
+
+ /**
+ * Creates a one-shot action with given nanoTime-based trigger.
+ */
+ ScheduledFutureTask(Callable<V> callable, long ns) {
+ super(callable);
+ this.time = ns;
+ this.period = 0;
+ this.sequenceNumber = sequencer.getAndIncrement();
+ }
+
+ public long getDelay(TimeUnit unit) {
+ long d = unit.convert(time - now(), TimeUnit.NANOSECONDS);
+ return d;
+ }
+
+ public int compareTo(Delayed other) {
+ if (other == this) // compare zero ONLY if same object
+ return 0;
+ if (other instanceof ScheduledFutureTask) {
+ ScheduledFutureTask<?> x = (ScheduledFutureTask<?>)other;
+ long diff = time - x.time;
+ if (diff < 0)
+ return -1;
+ else if (diff > 0)
+ return 1;
+ else if (sequenceNumber < x.sequenceNumber)
+ return -1;
+ else
+ return 1;
+ }
+ long d = (getDelay(TimeUnit.NANOSECONDS) -
+ other.getDelay(TimeUnit.NANOSECONDS));
+ return (d == 0)? 0 : ((d < 0)? -1 : 1);
+ }
+
+ /**
+ * Returns true if this is a periodic (not a one-shot) action.
+ *
+ * @return true if periodic
+ */
+ public boolean isPeriodic() {
+ return period != 0;
+ }
+
+ /**
+ * Runs a periodic task.
+ */
+ private void runPeriodic() {
+ boolean ok = ScheduledFutureTask.super.runAndReset();
+ boolean down = isShutdown();
+ // Reschedule if not cancelled and not shutdown or policy allows
+ if (ok && (!down ||
+ (getContinueExistingPeriodicTasksAfterShutdownPolicy() &&
+ !isTerminating()))) {
+ long p = period;
+ if (p > 0)
+ time += p;
+ else
+ time = now() - p;
+ // Classpath local: ecj from eclipse 3.1 does not
+ // compile this.
+ // ScheduledThreadPoolExecutor.super.getQueue().add(this);
+ ScheduledThreadPoolExecutor.super.getQueue().add((Runnable) this);
+ }
+ // This might have been the final executed delayed
+ // task. Wake up threads to check.
+ else if (down)
+ interruptIdleWorkers();
+ }
+
+ /**
+ * Overrides FutureTask version so as to reset/requeue if periodic.
+ */
+ public void run() {
+ if (isPeriodic())
+ runPeriodic();
+ else
+ ScheduledFutureTask.super.run();
+ }
+ }
+
+ /**
+ * Specialized variant of ThreadPoolExecutor.execute for delayed tasks.
+ */
+ private void delayedExecute(Runnable command) {
+ if (isShutdown()) {
+ reject(command);
+ return;
+ }
+ // Prestart a thread if necessary. We cannot prestart it
+ // running the task because the task (probably) shouldn't be
+ // run yet, so thread will just idle until delay elapses.
+ if (getPoolSize() < getCorePoolSize())
+ prestartCoreThread();
+
+ super.getQueue().add(command);
+ }
+
+ /**
+ * Cancels and clears the queue of all tasks that should not be run
+ * due to shutdown policy.
+ */
+ private void cancelUnwantedTasks() {
+ boolean keepDelayed = getExecuteExistingDelayedTasksAfterShutdownPolicy();
+ boolean keepPeriodic = getContinueExistingPeriodicTasksAfterShutdownPolicy();
+ if (!keepDelayed && !keepPeriodic)
+ super.getQueue().clear();
+ else if (keepDelayed || keepPeriodic) {
+ Object[] entries = super.getQueue().toArray();
+ for (int i = 0; i < entries.length; ++i) {
+ Object e = entries[i];
+ if (e instanceof RunnableScheduledFuture) {
+ RunnableScheduledFuture<?> t = (RunnableScheduledFuture<?>)e;
+ if (t.isPeriodic()? !keepPeriodic : !keepDelayed)
+ t.cancel(false);
+ }
+ }
+ entries = null;
+ purge();
+ }
+ }
+
+ public boolean remove(Runnable task) {
+ if (!(task instanceof RunnableScheduledFuture))
+ return false;
+ return getQueue().remove(task);
+ }
+
+ /**
+ * 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 ScheduledThreadPoolExecutor with the given core
+ * pool size.
+ *
+ * @param corePoolSize the number of threads to keep in the pool,
+ * even if they are idle
+ * @throws IllegalArgumentException if <tt>corePoolSize &lt; 0</tt>
+ */
+ public ScheduledThreadPoolExecutor(int corePoolSize) {
+ super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
+ new DelayedWorkQueue());
+ }
+
+ /**
+ * Creates a new ScheduledThreadPoolExecutor with the given
+ * initial parameters.
+ *
+ * @param corePoolSize the number of threads to keep in the pool,
+ * even if they are idle
+ * @param threadFactory the factory to use when the executor
+ * creates a new thread
+ * @throws IllegalArgumentException if <tt>corePoolSize &lt; 0</tt>
+ * @throws NullPointerException if threadFactory is null
+ */
+ public ScheduledThreadPoolExecutor(int corePoolSize,
+ ThreadFactory threadFactory) {
+ super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
+ new DelayedWorkQueue(), threadFactory);
+ }
+
+ /**
+ * Creates a new ScheduledThreadPoolExecutor with the given
+ * initial parameters.
+ *
+ * @param corePoolSize the number of threads to keep in the pool,
+ * even if they are idle
+ * @param handler the handler to use when execution is blocked
+ * because the thread bounds and queue capacities are reached
+ * @throws IllegalArgumentException if <tt>corePoolSize &lt; 0</tt>
+ * @throws NullPointerException if handler is null
+ */
+ public ScheduledThreadPoolExecutor(int corePoolSize,
+ RejectedExecutionHandler handler) {
+ super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
+ new DelayedWorkQueue(), handler);
+ }
+
+ /**
+ * Creates a new ScheduledThreadPoolExecutor with the given
+ * initial parameters.
+ *
+ * @param corePoolSize the number of threads to keep in the pool,
+ * even if they are idle
+ * @param threadFactory the factory to use when the executor
+ * creates a new thread
+ * @param handler the handler to use when execution is blocked
+ * because the thread bounds and queue capacities are reached.
+ * @throws IllegalArgumentException if <tt>corePoolSize &lt; 0</tt>
+ * @throws NullPointerException if threadFactory or handler is null
+ */
+ public ScheduledThreadPoolExecutor(int corePoolSize,
+ ThreadFactory threadFactory,
+ RejectedExecutionHandler handler) {
+ super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
+ new DelayedWorkQueue(), threadFactory, handler);
+ }
+
+ public ScheduledFuture<?> schedule(Runnable command,
+ long delay,
+ TimeUnit unit) {
+ if (command == null || unit == null)
+ throw new NullPointerException();
+ long triggerTime = now() + unit.toNanos(delay);
+ RunnableScheduledFuture<?> t = decorateTask(command,
+ new ScheduledFutureTask<Boolean>(command, null, triggerTime));
+ delayedExecute(t);
+ return t;
+ }
+
+ public <V> ScheduledFuture<V> schedule(Callable<V> callable,
+ long delay,
+ TimeUnit unit) {
+ if (callable == null || unit == null)
+ throw new NullPointerException();
+ if (delay < 0) delay = 0;
+ long triggerTime = now() + unit.toNanos(delay);
+ RunnableScheduledFuture<V> t = decorateTask(callable,
+ new ScheduledFutureTask<V>(callable, triggerTime));
+ delayedExecute(t);
+ return t;
+ }
+
+ public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
+ long initialDelay,
+ long period,
+ TimeUnit unit) {
+ if (command == null || unit == null)
+ throw new NullPointerException();
+ if (period <= 0)
+ throw new IllegalArgumentException();
+ if (initialDelay < 0) initialDelay = 0;
+ long triggerTime = now() + unit.toNanos(initialDelay);
+ RunnableScheduledFuture<?> t = decorateTask(command,
+ new ScheduledFutureTask<Object>(command,
+ null,
+ triggerTime,
+ unit.toNanos(period)));
+ delayedExecute(t);
+ return t;
+ }
+
+ public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
+ long initialDelay,
+ long delay,
+ TimeUnit unit) {
+ if (command == null || unit == null)
+ throw new NullPointerException();
+ if (delay <= 0)
+ throw new IllegalArgumentException();
+ if (initialDelay < 0) initialDelay = 0;
+ long triggerTime = now() + unit.toNanos(initialDelay);
+ RunnableScheduledFuture<?> t = decorateTask(command,
+ new ScheduledFutureTask<Boolean>(command,
+ null,
+ triggerTime,
+ unit.toNanos(-delay)));
+ delayedExecute(t);
+ return t;
+ }
+
+
+ /**
+ * Executes command with zero required delay. This has effect
+ * equivalent to <tt>schedule(command, 0, anyUnit)</tt>. Note
+ * that inspections of the queue and of the list returned by
+ * <tt>shutdownNow</tt> will access the zero-delayed
+ * {@link ScheduledFuture}, not the <tt>command</tt> itself.
+ *
+ * @param command the task to execute
+ * @throws RejectedExecutionException at discretion of
+ * <tt>RejectedExecutionHandler</tt>, if task cannot be accepted
+ * for execution because the executor has been shut down.
+ * @throws NullPointerException if command is null
+ */
+ public void execute(Runnable command) {
+ if (command == null)
+ throw new NullPointerException();
+ schedule(command, 0, TimeUnit.NANOSECONDS);
+ }
+
+ // Override AbstractExecutorService methods
+
+ public Future<?> submit(Runnable task) {
+ return schedule(task, 0, TimeUnit.NANOSECONDS);
+ }
+
+ public <T> Future<T> submit(Runnable task, T result) {
+ return schedule(Executors.callable(task, result),
+ 0, TimeUnit.NANOSECONDS);
+ }
+
+ public <T> Future<T> submit(Callable<T> task) {
+ return schedule(task, 0, TimeUnit.NANOSECONDS);
+ }
+
+ /**
+ * Sets the policy on whether to continue executing existing periodic
+ * tasks even when this executor has been <tt>shutdown</tt>. In
+ * this case, these tasks will only terminate upon
+ * <tt>shutdownNow</tt>, or after setting the policy to
+ * <tt>false</tt> when already shutdown. This value is by default
+ * false.
+ *
+ * @param value if true, continue after shutdown, else don't.
+ * @see #getContinueExistingPeriodicTasksAfterShutdownPolicy
+ */
+ public void setContinueExistingPeriodicTasksAfterShutdownPolicy(boolean value) {
+ continueExistingPeriodicTasksAfterShutdown = value;
+ if (!value && isShutdown())
+ cancelUnwantedTasks();
+ }
+
+ /**
+ * Gets the policy on whether to continue executing existing
+ * periodic tasks even when this executor has been
+ * <tt>shutdown</tt>. In this case, these tasks will only
+ * terminate upon <tt>shutdownNow</tt> or after setting the policy
+ * to <tt>false</tt> when already shutdown. This value is by
+ * default false.
+ *
+ * @return true if will continue after shutdown
+ * @see #setContinueExistingPeriodicTasksAfterShutdownPolicy
+ */
+ public boolean getContinueExistingPeriodicTasksAfterShutdownPolicy() {
+ return continueExistingPeriodicTasksAfterShutdown;
+ }
+
+ /**
+ * Sets the policy on whether to execute existing delayed
+ * tasks even when this executor has been <tt>shutdown</tt>. In
+ * this case, these tasks will only terminate upon
+ * <tt>shutdownNow</tt>, or after setting the policy to
+ * <tt>false</tt> when already shutdown. This value is by default
+ * true.
+ *
+ * @param value if true, execute after shutdown, else don't.
+ * @see #getExecuteExistingDelayedTasksAfterShutdownPolicy
+ */
+ public void setExecuteExistingDelayedTasksAfterShutdownPolicy(boolean value) {
+ executeExistingDelayedTasksAfterShutdown = value;
+ if (!value && isShutdown())
+ cancelUnwantedTasks();
+ }
+
+ /**
+ * Gets the policy on whether to execute existing delayed
+ * tasks even when this executor has been <tt>shutdown</tt>. In
+ * this case, these tasks will only terminate upon
+ * <tt>shutdownNow</tt>, or after setting the policy to
+ * <tt>false</tt> when already shutdown. This value is by default
+ * true.
+ *
+ * @return true if will execute after shutdown
+ * @see #setExecuteExistingDelayedTasksAfterShutdownPolicy
+ */
+ public boolean getExecuteExistingDelayedTasksAfterShutdownPolicy() {
+ return executeExistingDelayedTasksAfterShutdown;
+ }
+
+
+ /**
+ * Initiates an orderly shutdown in which previously submitted
+ * tasks are executed, but no new tasks will be accepted. If the
+ * <tt>ExecuteExistingDelayedTasksAfterShutdownPolicy</tt> has
+ * been set <tt>false</tt>, existing delayed tasks whose delays
+ * have not yet elapsed are cancelled. And unless the
+ * <tt>ContinueExistingPeriodicTasksAfterShutdownPolicy</tt> has
+ * been set <tt>true</tt>, future executions of existing periodic
+ * tasks will be cancelled.
+ */
+ public void shutdown() {
+ cancelUnwantedTasks();
+ super.shutdown();
+ }
+
+ /**
+ * Attempts to stop all actively executing tasks, halts the
+ * processing of waiting tasks, and returns a list of the tasks
+ * that were awaiting execution.
+ *
+ * <p>There are no guarantees beyond best-effort attempts to stop
+ * processing actively executing tasks. This implementation
+ * cancels tasks via {@link Thread#interrupt}, so any task that
+ * fails to respond to interrupts may never terminate.
+ *
+ * @return list of tasks that never commenced execution. Each
+ * element of this list is a {@link ScheduledFuture},
+ * including those tasks submitted using <tt>execute</tt>, which
+ * are for scheduling purposes used as the basis of a zero-delay
+ * <tt>ScheduledFuture</tt>.
+ * @throws SecurityException {@inheritDoc}
+ */
+ public List<Runnable> shutdownNow() {
+ return super.shutdownNow();
+ }
+
+ /**
+ * Returns the task queue used by this executor. Each element of
+ * this queue is a {@link ScheduledFuture}, including those
+ * tasks submitted using <tt>execute</tt> which are for scheduling
+ * purposes used as the basis of a zero-delay
+ * <tt>ScheduledFuture</tt>. Iteration over this queue is
+ * <em>not</em> guaranteed to traverse tasks in the order in
+ * which they will execute.
+ *
+ * @return the task queue
+ */
+ public BlockingQueue<Runnable> getQueue() {
+ return super.getQueue();
+ }
+
+ /**
+ * An annoying wrapper class to convince javac to use a
+ * DelayQueue<RunnableScheduledFuture> as a BlockingQueue<Runnable>
+ */
+ private static class DelayedWorkQueue
+ extends AbstractCollection<Runnable>
+ implements BlockingQueue<Runnable> {
+
+ private final DelayQueue<RunnableScheduledFuture> dq = new DelayQueue<RunnableScheduledFuture>();
+ public Runnable poll() { return dq.poll(); }
+ public Runnable peek() { return dq.peek(); }
+ public Runnable take() throws InterruptedException { return dq.take(); }
+ public Runnable poll(long timeout, TimeUnit unit) throws InterruptedException {
+ return dq.poll(timeout, unit);
+ }
+
+ public boolean add(Runnable x) {
+ return dq.add((RunnableScheduledFuture)x);
+ }
+ public boolean offer(Runnable x) {
+ return dq.offer((RunnableScheduledFuture)x);
+ }
+ public void put(Runnable x) {
+ dq.put((RunnableScheduledFuture)x);
+ }
+ public boolean offer(Runnable x, long timeout, TimeUnit unit) {
+ return dq.offer((RunnableScheduledFuture)x, timeout, unit);
+ }
+
+ public Runnable remove() { return dq.remove(); }
+ public Runnable element() { return dq.element(); }
+ public void clear() { dq.clear(); }
+ public int drainTo(Collection<? super Runnable> c) { return dq.drainTo(c); }
+ public int drainTo(Collection<? super Runnable> c, int maxElements) {
+ return dq.drainTo(c, maxElements);
+ }
+
+ public int remainingCapacity() { return dq.remainingCapacity(); }
+ public boolean remove(Object x) { return dq.remove(x); }
+ public boolean contains(Object x) { return dq.contains(x); }
+ public int size() { return dq.size(); }
+ public boolean isEmpty() { return dq.isEmpty(); }
+ public Object[] toArray() { return dq.toArray(); }
+ public <T> T[] toArray(T[] array) { return dq.toArray(array); }
+ public Iterator<Runnable> iterator() {
+ return new Iterator<Runnable>() {
+ private Iterator<RunnableScheduledFuture> it = dq.iterator();
+ public boolean hasNext() { return it.hasNext(); }
+ public Runnable next() { return it.next(); }
+ public void remove() { it.remove(); }
+ };
+ }
+ }
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/Semaphore.java b/libjava/classpath/external/jsr166/java/util/concurrent/Semaphore.java
new file mode 100644
index 000000000..105236439
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/Semaphore.java
@@ -0,0 +1,681 @@
+/*
+ * 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.locks.*;
+import java.util.concurrent.atomic.*;
+
+/**
+ * A counting semaphore. Conceptually, a semaphore maintains a set of
+ * permits. Each {@link #acquire} blocks if necessary until a permit is
+ * available, and then takes it. Each {@link #release} adds a permit,
+ * potentially releasing a blocking acquirer.
+ * However, no actual permit objects are used; the {@code Semaphore} just
+ * keeps a count of the number available and acts accordingly.
+ *
+ * <p>Semaphores are often used to restrict the number of threads than can
+ * access some (physical or logical) resource. For example, here is
+ * a class that uses a semaphore to control access to a pool of items:
+ * <pre>
+ * class Pool {
+ * private static final int MAX_AVAILABLE = 100;
+ * private final Semaphore available = new Semaphore(MAX_AVAILABLE, true);
+ *
+ * public Object getItem() throws InterruptedException {
+ * available.acquire();
+ * return getNextAvailableItem();
+ * }
+ *
+ * public void putItem(Object x) {
+ * if (markAsUnused(x))
+ * available.release();
+ * }
+ *
+ * // Not a particularly efficient data structure; just for demo
+ *
+ * protected Object[] items = ... whatever kinds of items being managed
+ * protected boolean[] used = new boolean[MAX_AVAILABLE];
+ *
+ * protected synchronized Object getNextAvailableItem() {
+ * for (int i = 0; i < MAX_AVAILABLE; ++i) {
+ * if (!used[i]) {
+ * used[i] = true;
+ * return items[i];
+ * }
+ * }
+ * return null; // not reached
+ * }
+ *
+ * protected synchronized boolean markAsUnused(Object item) {
+ * for (int i = 0; i < MAX_AVAILABLE; ++i) {
+ * if (item == items[i]) {
+ * if (used[i]) {
+ * used[i] = false;
+ * return true;
+ * } else
+ * return false;
+ * }
+ * }
+ * return false;
+ * }
+ *
+ * }
+ * </pre>
+ *
+ * <p>Before obtaining an item each thread must acquire a permit from
+ * the semaphore, guaranteeing that an item is available for use. When
+ * the thread has finished with the item it is returned back to the
+ * pool and a permit is returned to the semaphore, allowing another
+ * thread to acquire that item. Note that no synchronization lock is
+ * held when {@link #acquire} is called as that would prevent an item
+ * from being returned to the pool. The semaphore encapsulates the
+ * synchronization needed to restrict access to the pool, separately
+ * from any synchronization needed to maintain the consistency of the
+ * pool itself.
+ *
+ * <p>A semaphore initialized to one, and which is used such that it
+ * only has at most one permit available, can serve as a mutual
+ * exclusion lock. This is more commonly known as a <em>binary
+ * semaphore</em>, because it only has two states: one permit
+ * available, or zero permits available. When used in this way, the
+ * binary semaphore has the property (unlike many {@link Lock}
+ * implementations), that the &quot;lock&quot; can be released by a
+ * thread other than the owner (as semaphores have no notion of
+ * ownership). This can be useful in some specialized contexts, such
+ * as deadlock recovery.
+ *
+ * <p> The constructor for this class optionally accepts a
+ * <em>fairness</em> parameter. When set false, this class makes no
+ * guarantees about the order in which threads acquire permits. In
+ * particular, <em>barging</em> is permitted, that is, a thread
+ * invoking {@link #acquire} can be allocated a permit ahead of a
+ * thread that has been waiting - logically the new thread places itself at
+ * the head of the queue of waiting threads. When fairness is set true, the
+ * semaphore guarantees that threads invoking any of the {@link
+ * #acquire() acquire} methods are selected to obtain permits in the order in
+ * which their invocation of those methods was processed
+ * (first-in-first-out; FIFO). Note that FIFO ordering necessarily
+ * applies to specific internal points of execution within these
+ * methods. So, it is possible for one thread to invoke
+ * {@code acquire} before another, but reach the ordering point after
+ * the other, and similarly upon return from the method.
+ * Also note that the untimed {@link #tryAcquire() tryAcquire} methods do not
+ * honor the fairness setting, but will take any permits that are
+ * available.
+ *
+ * <p>Generally, semaphores used to control resource access should be
+ * initialized as fair, to ensure that no thread is starved out from
+ * accessing a resource. When using semaphores for other kinds of
+ * synchronization control, the throughput advantages of non-fair
+ * ordering often outweigh fairness considerations.
+ *
+ * <p>This class also provides convenience methods to {@link
+ * #acquire(int) acquire} and {@link #release(int) release} multiple
+ * permits at a time. Beware of the increased risk of indefinite
+ * postponement when these methods are used without fairness set true.
+ *
+ * <p>Memory consistency effects: Actions in a thread prior to calling
+ * a "release" method such as {@code release()}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions following a successful "acquire" method such as {@code acquire()}
+ * in another thread.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ *
+ */
+
+public class Semaphore implements java.io.Serializable {
+ private static final long serialVersionUID = -3222578661600680210L;
+ /** All mechanics via AbstractQueuedSynchronizer subclass */
+ private final Sync sync;
+
+ /**
+ * Synchronization implementation for semaphore. Uses AQS state
+ * to represent permits. Subclassed into fair and nonfair
+ * versions.
+ */
+ abstract static class Sync extends AbstractQueuedSynchronizer {
+ private static final long serialVersionUID = 1192457210091910933L;
+
+ Sync(int permits) {
+ setState(permits);
+ }
+
+ final int getPermits() {
+ return getState();
+ }
+
+ final int nonfairTryAcquireShared(int acquires) {
+ for (;;) {
+ int available = getState();
+ int remaining = available - acquires;
+ if (remaining < 0 ||
+ compareAndSetState(available, remaining))
+ return remaining;
+ }
+ }
+
+ protected final boolean tryReleaseShared(int releases) {
+ for (;;) {
+ int p = getState();
+ if (compareAndSetState(p, p + releases))
+ return true;
+ }
+ }
+
+ final void reducePermits(int reductions) {
+ for (;;) {
+ int current = getState();
+ int next = current - reductions;
+ if (compareAndSetState(current, next))
+ return;
+ }
+ }
+
+ final int drainPermits() {
+ for (;;) {
+ int current = getState();
+ if (current == 0 || compareAndSetState(current, 0))
+ return current;
+ }
+ }
+ }
+
+ /**
+ * NonFair version
+ */
+ final static class NonfairSync extends Sync {
+ private static final long serialVersionUID = -2694183684443567898L;
+
+ NonfairSync(int permits) {
+ super(permits);
+ }
+
+ protected int tryAcquireShared(int acquires) {
+ return nonfairTryAcquireShared(acquires);
+ }
+ }
+
+ /**
+ * Fair version
+ */
+ final static class FairSync extends Sync {
+ private static final long serialVersionUID = 2014338818796000944L;
+
+ FairSync(int permits) {
+ super(permits);
+ }
+
+ protected int tryAcquireShared(int acquires) {
+ Thread current = Thread.currentThread();
+ for (;;) {
+ Thread first = getFirstQueuedThread();
+ if (first != null && first != current)
+ return -1;
+ int available = getState();
+ int remaining = available - acquires;
+ if (remaining < 0 ||
+ compareAndSetState(available, remaining))
+ return remaining;
+ }
+ }
+ }
+
+ /**
+ * Creates a {@code Semaphore} with the given number of
+ * permits and nonfair fairness setting.
+ *
+ * @param permits the initial number of permits available.
+ * This value may be negative, in which case releases
+ * must occur before any acquires will be granted.
+ */
+ public Semaphore(int permits) {
+ sync = new NonfairSync(permits);
+ }
+
+ /**
+ * Creates a {@code Semaphore} with the given number of
+ * permits and the given fairness setting.
+ *
+ * @param permits the initial number of permits available.
+ * This value may be negative, in which case releases
+ * must occur before any acquires will be granted.
+ * @param fair {@code true} if this semaphore will guarantee
+ * first-in first-out granting of permits under contention,
+ * else {@code false}
+ */
+ public Semaphore(int permits, boolean fair) {
+ sync = (fair)? new FairSync(permits) : new NonfairSync(permits);
+ }
+
+ /**
+ * Acquires a permit from this semaphore, blocking until one is
+ * available, or the thread is {@linkplain Thread#interrupt interrupted}.
+ *
+ * <p>Acquires a permit, if one is available and returns immediately,
+ * reducing the number of available permits by one.
+ *
+ * <p>If no permit is available then the current thread becomes
+ * disabled for thread scheduling purposes and lies dormant until
+ * one of two things happens:
+ * <ul>
+ * <li>Some other thread invokes the {@link #release} method for this
+ * semaphore and the current thread is next to be assigned a permit; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread.
+ * </ul>
+ *
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+ * for a permit,
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ *
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public void acquire() throws InterruptedException {
+ sync.acquireSharedInterruptibly(1);
+ }
+
+ /**
+ * Acquires a permit from this semaphore, blocking until one is
+ * available.
+ *
+ * <p>Acquires a permit, if one is available and returns immediately,
+ * reducing the number of available permits by one.
+ *
+ * <p>If no permit is available then the current thread becomes
+ * disabled for thread scheduling purposes and lies dormant until
+ * some other thread invokes the {@link #release} method for this
+ * semaphore and the current thread is next to be assigned a permit.
+ *
+ * <p>If the current thread is {@linkplain Thread#interrupt interrupted}
+ * while waiting for a permit then it will continue to wait, but the
+ * time at which the thread is assigned a permit may change compared to
+ * the time it would have received the permit had no interruption
+ * occurred. When the thread does return from this method its interrupt
+ * status will be set.
+ */
+ public void acquireUninterruptibly() {
+ sync.acquireShared(1);
+ }
+
+ /**
+ * Acquires a permit from this semaphore, only if one is available at the
+ * time of invocation.
+ *
+ * <p>Acquires a permit, if one is available and returns immediately,
+ * with the value {@code true},
+ * reducing the number of available permits by one.
+ *
+ * <p>If no permit is available then this method will return
+ * immediately with the value {@code false}.
+ *
+ * <p>Even when this semaphore has been set to use a
+ * fair ordering policy, a call to {@code tryAcquire()} <em>will</em>
+ * immediately acquire a permit if one is available, whether or not
+ * other threads are currently waiting.
+ * This &quot;barging&quot; behavior can be useful in certain
+ * circumstances, even though it breaks fairness. If you want to honor
+ * the fairness setting, then use
+ * {@link #tryAcquire(long, TimeUnit) tryAcquire(0, TimeUnit.SECONDS) }
+ * which is almost equivalent (it also detects interruption).
+ *
+ * @return {@code true} if a permit was acquired and {@code false}
+ * otherwise
+ */
+ public boolean tryAcquire() {
+ return sync.nonfairTryAcquireShared(1) >= 0;
+ }
+
+ /**
+ * Acquires a permit from this semaphore, if one becomes available
+ * within the given waiting time and the current thread has not
+ * been {@linkplain Thread#interrupt interrupted}.
+ *
+ * <p>Acquires a permit, if one is available and returns immediately,
+ * with the value {@code true},
+ * reducing the number of available permits by one.
+ *
+ * <p>If no permit is available then the current thread becomes
+ * disabled for thread scheduling purposes and lies dormant until
+ * one of three things happens:
+ * <ul>
+ * <li>Some other thread invokes the {@link #release} method for this
+ * semaphore and the current thread is next to be assigned a permit; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread; or
+ * <li>The specified waiting time elapses.
+ * </ul>
+ *
+ * <p>If a permit is acquired then the value {@code true} is returned.
+ *
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+ * to acquire a permit,
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ *
+ * <p>If the specified waiting time elapses then the value {@code false}
+ * is returned. If the time is less than or equal to zero, the method
+ * will not wait at all.
+ *
+ * @param timeout the maximum time to wait for a permit
+ * @param unit the time unit of the {@code timeout} argument
+ * @return {@code true} if a permit was acquired and {@code false}
+ * if the waiting time elapsed before a permit was acquired
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public boolean tryAcquire(long timeout, TimeUnit unit)
+ throws InterruptedException {
+ return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
+ }
+
+ /**
+ * Releases a permit, returning it to the semaphore.
+ *
+ * <p>Releases a permit, increasing the number of available permits by
+ * one. If any threads are trying to acquire a permit, then one is
+ * selected and given the permit that was just released. That thread
+ * is (re)enabled for thread scheduling purposes.
+ *
+ * <p>There is no requirement that a thread that releases a permit must
+ * have acquired that permit by calling {@link #acquire}.
+ * Correct usage of a semaphore is established by programming convention
+ * in the application.
+ */
+ public void release() {
+ sync.releaseShared(1);
+ }
+
+ /**
+ * Acquires the given number of permits from this semaphore,
+ * blocking until all are available,
+ * or the thread is {@linkplain Thread#interrupt interrupted}.
+ *
+ * <p>Acquires the given number of permits, if they are available,
+ * and returns immediately, reducing the number of available permits
+ * by the given amount.
+ *
+ * <p>If insufficient permits are available then the current thread becomes
+ * disabled for thread scheduling purposes and lies dormant until
+ * one of two things happens:
+ * <ul>
+ * <li>Some other thread invokes one of the {@link #release() release}
+ * methods for this semaphore, the current thread is next to be assigned
+ * permits and the number of available permits satisfies this request; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread.
+ * </ul>
+ *
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+ * for a permit,
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ * Any permits that were to be assigned to this thread are instead
+ * assigned to other threads trying to acquire permits, as if
+ * permits had been made available by a call to {@link #release()}.
+ *
+ * @param permits the number of permits to acquire
+ * @throws InterruptedException if the current thread is interrupted
+ * @throws IllegalArgumentException if {@code permits} is negative
+ */
+ public void acquire(int permits) throws InterruptedException {
+ if (permits < 0) throw new IllegalArgumentException();
+ sync.acquireSharedInterruptibly(permits);
+ }
+
+ /**
+ * Acquires the given number of permits from this semaphore,
+ * blocking until all are available.
+ *
+ * <p>Acquires the given number of permits, if they are available,
+ * and returns immediately, reducing the number of available permits
+ * by the given amount.
+ *
+ * <p>If insufficient permits are available then the current thread becomes
+ * disabled for thread scheduling purposes and lies dormant until
+ * some other thread invokes one of the {@link #release() release}
+ * methods for this semaphore, the current thread is next to be assigned
+ * permits and the number of available permits satisfies this request.
+ *
+ * <p>If the current thread is {@linkplain Thread#interrupt interrupted}
+ * while waiting for permits then it will continue to wait and its
+ * position in the queue is not affected. When the thread does return
+ * from this method its interrupt status will be set.
+ *
+ * @param permits the number of permits to acquire
+ * @throws IllegalArgumentException if {@code permits} is negative
+ *
+ */
+ public void acquireUninterruptibly(int permits) {
+ if (permits < 0) throw new IllegalArgumentException();
+ sync.acquireShared(permits);
+ }
+
+ /**
+ * Acquires the given number of permits from this semaphore, only
+ * if all are available at the time of invocation.
+ *
+ * <p>Acquires the given number of permits, if they are available, and
+ * returns immediately, with the value {@code true},
+ * reducing the number of available permits by the given amount.
+ *
+ * <p>If insufficient permits are available then this method will return
+ * immediately with the value {@code false} and the number of available
+ * permits is unchanged.
+ *
+ * <p>Even when this semaphore has been set to use a fair ordering
+ * policy, a call to {@code tryAcquire} <em>will</em>
+ * immediately acquire a permit if one is available, whether or
+ * not other threads are currently waiting. This
+ * &quot;barging&quot; behavior can be useful in certain
+ * circumstances, even though it breaks fairness. If you want to
+ * honor the fairness setting, then use {@link #tryAcquire(int,
+ * long, TimeUnit) tryAcquire(permits, 0, TimeUnit.SECONDS) }
+ * which is almost equivalent (it also detects interruption).
+ *
+ * @param permits the number of permits to acquire
+ * @return {@code true} if the permits were acquired and
+ * {@code false} otherwise
+ * @throws IllegalArgumentException if {@code permits} is negative
+ */
+ public boolean tryAcquire(int permits) {
+ if (permits < 0) throw new IllegalArgumentException();
+ return sync.nonfairTryAcquireShared(permits) >= 0;
+ }
+
+ /**
+ * Acquires the given number of permits from this semaphore, if all
+ * become available within the given waiting time and the current
+ * thread has not been {@linkplain Thread#interrupt interrupted}.
+ *
+ * <p>Acquires the given number of permits, if they are available and
+ * returns immediately, with the value {@code true},
+ * reducing the number of available permits by the given amount.
+ *
+ * <p>If insufficient permits are available then
+ * the current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until one of three things happens:
+ * <ul>
+ * <li>Some other thread invokes one of the {@link #release() release}
+ * methods for this semaphore, the current thread is next to be assigned
+ * permits and the number of available permits satisfies this request; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread; or
+ * <li>The specified waiting time elapses.
+ * </ul>
+ *
+ * <p>If the permits are acquired then the value {@code true} is returned.
+ *
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+ * to acquire the permits,
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ * Any permits that were to be assigned to this thread, are instead
+ * assigned to other threads trying to acquire permits, as if
+ * the permits had been made available by a call to {@link #release()}.
+ *
+ * <p>If the specified waiting time elapses then the value {@code false}
+ * is returned. If the time is less than or equal to zero, the method
+ * will not wait at all. Any permits that were to be assigned to this
+ * thread, are instead assigned to other threads trying to acquire
+ * permits, as if the permits had been made available by a call to
+ * {@link #release()}.
+ *
+ * @param permits the number of permits to acquire
+ * @param timeout the maximum time to wait for the permits
+ * @param unit the time unit of the {@code timeout} argument
+ * @return {@code true} if all permits were acquired and {@code false}
+ * if the waiting time elapsed before all permits were acquired
+ * @throws InterruptedException if the current thread is interrupted
+ * @throws IllegalArgumentException if {@code permits} is negative
+ */
+ public boolean tryAcquire(int permits, long timeout, TimeUnit unit)
+ throws InterruptedException {
+ if (permits < 0) throw new IllegalArgumentException();
+ return sync.tryAcquireSharedNanos(permits, unit.toNanos(timeout));
+ }
+
+ /**
+ * Releases the given number of permits, returning them to the semaphore.
+ *
+ * <p>Releases the given number of permits, increasing the number of
+ * available permits by that amount.
+ * If any threads are trying to acquire permits, then one
+ * is selected and given the permits that were just released.
+ * If the number of available permits satisfies that thread's request
+ * then that thread is (re)enabled for thread scheduling purposes;
+ * otherwise the thread will wait until sufficient permits are available.
+ * If there are still permits available
+ * after this thread's request has been satisfied, then those permits
+ * are assigned in turn to other threads trying to acquire permits.
+ *
+ * <p>There is no requirement that a thread that releases a permit must
+ * have acquired that permit by calling {@link Semaphore#acquire acquire}.
+ * Correct usage of a semaphore is established by programming convention
+ * in the application.
+ *
+ * @param permits the number of permits to release
+ * @throws IllegalArgumentException if {@code permits} is negative
+ */
+ public void release(int permits) {
+ if (permits < 0) throw new IllegalArgumentException();
+ sync.releaseShared(permits);
+ }
+
+ /**
+ * Returns the current number of permits available in this semaphore.
+ *
+ * <p>This method is typically used for debugging and testing purposes.
+ *
+ * @return the number of permits available in this semaphore
+ */
+ public int availablePermits() {
+ return sync.getPermits();
+ }
+
+ /**
+ * Acquires and returns all permits that are immediately available.
+ *
+ * @return the number of permits acquired
+ */
+ public int drainPermits() {
+ return sync.drainPermits();
+ }
+
+ /**
+ * Shrinks the number of available permits by the indicated
+ * reduction. This method can be useful in subclasses that use
+ * semaphores to track resources that become unavailable. This
+ * method differs from {@code acquire} in that it does not block
+ * waiting for permits to become available.
+ *
+ * @param reduction the number of permits to remove
+ * @throws IllegalArgumentException if {@code reduction} is negative
+ */
+ protected void reducePermits(int reduction) {
+ if (reduction < 0) throw new IllegalArgumentException();
+ sync.reducePermits(reduction);
+ }
+
+ /**
+ * Returns {@code true} if this semaphore has fairness set true.
+ *
+ * @return {@code true} if this semaphore has fairness set true
+ */
+ public boolean isFair() {
+ return sync instanceof FairSync;
+ }
+
+ /**
+ * Queries whether any threads are waiting to acquire. Note that
+ * because cancellations may occur at any time, a {@code true}
+ * return does not guarantee that any other thread will ever
+ * acquire. This method is designed primarily for use in
+ * monitoring of the system state.
+ *
+ * @return {@code true} if there may be other threads waiting to
+ * acquire the lock
+ */
+ public final boolean hasQueuedThreads() {
+ return sync.hasQueuedThreads();
+ }
+
+ /**
+ * Returns an estimate of the number of threads waiting to acquire.
+ * The value is only an estimate because the number of threads may
+ * change dynamically while this method traverses internal data
+ * structures. This method is designed for use in monitoring of the
+ * system state, not for synchronization control.
+ *
+ * @return the estimated number of threads waiting for this lock
+ */
+ public final int getQueueLength() {
+ return sync.getQueueLength();
+ }
+
+ /**
+ * Returns a collection containing threads that may be waiting to acquire.
+ * Because the actual set of threads may change dynamically while
+ * constructing this result, the returned collection is only a best-effort
+ * estimate. The elements of the returned collection are in no particular
+ * order. This method is designed to facilitate construction of
+ * subclasses that provide more extensive monitoring facilities.
+ *
+ * @return the collection of threads
+ */
+ protected Collection<Thread> getQueuedThreads() {
+ return sync.getQueuedThreads();
+ }
+
+ /**
+ * Returns a string identifying this semaphore, as well as its state.
+ * The state, in brackets, includes the String {@code "Permits ="}
+ * followed by the number of permits.
+ *
+ * @return a string identifying this semaphore, as well as its state
+ */
+ public String toString() {
+ return super.toString() + "[Permits = " + sync.getPermits() + "]";
+ }
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/SynchronousQueue.java b/libjava/classpath/external/jsr166/java/util/concurrent/SynchronousQueue.java
new file mode 100644
index 000000000..92f586ce8
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/SynchronousQueue.java
@@ -0,0 +1,1127 @@
+/*
+ * Written by Doug Lea, Bill Scherer, and Michael Scott 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.concurrent.locks.*;
+import java.util.concurrent.atomic.*;
+import java.util.*;
+
+/**
+ * A {@linkplain BlockingQueue blocking queue} in which each insert
+ * operation must wait for a corresponding remove operation by another
+ * thread, and vice versa. A synchronous queue does not have any
+ * internal capacity, not even a capacity of one. You cannot
+ * <tt>peek</tt> at a synchronous queue because an element is only
+ * present when you try to remove it; you cannot insert an element
+ * (using any method) unless another thread is trying to remove it;
+ * you cannot iterate as there is nothing to iterate. The
+ * <em>head</em> of the queue is the element that the first queued
+ * inserting thread is trying to add to the queue; if there is no such
+ * queued thread then no element is available for removal and
+ * <tt>poll()</tt> will return <tt>null</tt>. For purposes of other
+ * <tt>Collection</tt> methods (for example <tt>contains</tt>), a
+ * <tt>SynchronousQueue</tt> acts as an empty collection. This queue
+ * does not permit <tt>null</tt> elements.
+ *
+ * <p>Synchronous queues are similar to rendezvous channels used in
+ * CSP and Ada. They are well suited for handoff designs, in which an
+ * object running in one thread must sync up with an object running
+ * in another thread in order to hand it some information, event, or
+ * task.
+ *
+ * <p> This class supports an optional fairness policy for ordering
+ * waiting producer and consumer threads. By default, this ordering
+ * is not guaranteed. However, a queue constructed with fairness set
+ * to <tt>true</tt> grants threads access in FIFO order.
+ *
+ * <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.5
+ * @author Doug Lea and Bill Scherer and Michael Scott
+ * @param <E> the type of elements held in this collection
+ */
+public class SynchronousQueue<E> extends AbstractQueue<E>
+ implements BlockingQueue<E>, java.io.Serializable {
+ private static final long serialVersionUID = -3223113410248163686L;
+
+ /*
+ * This class implements extensions of the dual stack and dual
+ * queue algorithms described in "Nonblocking Concurrent Objects
+ * with Condition Synchronization", by W. N. Scherer III and
+ * M. L. Scott. 18th Annual Conf. on Distributed Computing,
+ * Oct. 2004 (see also
+ * http://www.cs.rochester.edu/u/scott/synchronization/pseudocode/duals.html).
+ * The (Lifo) stack is used for non-fair mode, and the (Fifo)
+ * queue for fair mode. The performance of the two is generally
+ * similar. Fifo usually supports higher throughput under
+ * contention but Lifo maintains higher thread locality in common
+ * applications.
+ *
+ * A dual queue (and similarly stack) is one that at any given
+ * time either holds "data" -- items provided by put operations,
+ * or "requests" -- slots representing take operations, or is
+ * empty. A call to "fulfill" (i.e., a call requesting an item
+ * from a queue holding data or vice versa) dequeues a
+ * complementary node. The most interesting feature of these
+ * queues is that any operation can figure out which mode the
+ * queue is in, and act accordingly without needing locks.
+ *
+ * Both the queue and stack extend abstract class Transferer
+ * defining the single method transfer that does a put or a
+ * take. These are unified into a single method because in dual
+ * data structures, the put and take operations are symmetrical,
+ * so nearly all code can be combined. The resulting transfer
+ * methods are on the long side, but are easier to follow than
+ * they would be if broken up into nearly-duplicated parts.
+ *
+ * The queue and stack data structures share many conceptual
+ * similarities but very few concrete details. For simplicity,
+ * they are kept distinct so that they can later evolve
+ * separately.
+ *
+ * The algorithms here differ from the versions in the above paper
+ * in extending them for use in synchronous queues, as well as
+ * dealing with cancellation. The main differences include:
+ *
+ * 1. The original algorithms used bit-marked pointers, but
+ * the ones here use mode bits in nodes, leading to a number
+ * of further adaptations.
+ * 2. SynchronousQueues must block threads waiting to become
+ * fulfilled.
+ * 3. Support for cancellation via timeout and interrupts,
+ * including cleaning out cancelled nodes/threads
+ * from lists to avoid garbage retention and memory depletion.
+ *
+ * Blocking is mainly accomplished using LockSupport park/unpark,
+ * except that nodes that appear to be the next ones to become
+ * fulfilled first spin a bit (on multiprocessors only). On very
+ * busy synchronous queues, spinning can dramatically improve
+ * throughput. And on less busy ones, the amount of spinning is
+ * small enough not to be noticeable.
+ *
+ * Cleaning is done in different ways in queues vs stacks. For
+ * queues, we can almost always remove a node immediately in O(1)
+ * time (modulo retries for consistency checks) when it is
+ * cancelled. But if it may be pinned as the current tail, it must
+ * wait until some subsequent cancellation. For stacks, we need a
+ * potentially O(n) traversal to be sure that we can remove the
+ * node, but this can run concurrently with other threads
+ * accessing the stack.
+ *
+ * While garbage collection takes care of most node reclamation
+ * issues that otherwise complicate nonblocking algorithms, care
+ * is taken to "forget" references to data, other nodes, and
+ * threads that might be held on to long-term by blocked
+ * threads. In cases where setting to null would otherwise
+ * conflict with main algorithms, this is done by changing a
+ * node's link to now point to the node itself. This doesn't arise
+ * much for Stack nodes (because blocked threads do not hang on to
+ * old head pointers), but references in Queue nodes must be
+ * aggressively forgotten to avoid reachability of everything any
+ * node has ever referred to since arrival.
+ */
+
+ /**
+ * Shared internal API for dual stacks and queues.
+ */
+ static abstract class Transferer {
+ /**
+ * Performs a put or take.
+ *
+ * @param e if non-null, the item to be handed to a consumer;
+ * if null, requests that transfer return an item
+ * offered by producer.
+ * @param timed if this operation should timeout
+ * @param nanos the timeout, in nanoseconds
+ * @return if non-null, the item provided or received; if null,
+ * the operation failed due to timeout or interrupt --
+ * the caller can distinguish which of these occurred
+ * by checking Thread.interrupted.
+ */
+ abstract Object transfer(Object e, boolean timed, long nanos);
+ }
+
+ /** The number of CPUs, for spin control */
+ static final int NCPUS = Runtime.getRuntime().availableProcessors();
+
+ /**
+ * The number of times to spin before blocking in timed waits.
+ * The value is empirically derived -- it works well across a
+ * variety of processors and OSes. Empirically, the best value
+ * seems not to vary with number of CPUs (beyond 2) so is just
+ * a constant.
+ */
+ static final int maxTimedSpins = (NCPUS < 2)? 0 : 32;
+
+ /**
+ * The number of times to spin before blocking in untimed waits.
+ * This is greater than timed value because untimed waits spin
+ * faster since they don't need to check times on each spin.
+ */
+ static final int maxUntimedSpins = maxTimedSpins * 16;
+
+ /**
+ * The number of nanoseconds for which it is faster to spin
+ * rather than to use timed park. A rough estimate suffices.
+ */
+ static final long spinForTimeoutThreshold = 1000L;
+
+ /** Dual stack */
+ static final class TransferStack extends Transferer {
+ /*
+ * This extends Scherer-Scott dual stack algorithm, differing,
+ * among other ways, by using "covering" nodes rather than
+ * bit-marked pointers: Fulfilling operations push on marker
+ * nodes (with FULFILLING bit set in mode) to reserve a spot
+ * to match a waiting node.
+ */
+
+ /* Modes for SNodes, ORed together in node fields */
+ /** Node represents an unfulfilled consumer */
+ static final int REQUEST = 0;
+ /** Node represents an unfulfilled producer */
+ static final int DATA = 1;
+ /** Node is fulfilling another unfulfilled DATA or REQUEST */
+ static final int FULFILLING = 2;
+
+ /** Return true if m has fulfilling bit set */
+ static boolean isFulfilling(int m) { return (m & FULFILLING) != 0; }
+
+ /** Node class for TransferStacks. */
+ static final class SNode {
+ volatile SNode next; // next node in stack
+ volatile SNode match; // the node matched to this
+ volatile Thread waiter; // to control park/unpark
+ Object item; // data; or null for REQUESTs
+ int mode;
+ // Note: item and mode fields don't need to be volatile
+ // since they are always written before, and read after,
+ // other volatile/atomic operations.
+
+ SNode(Object item) {
+ this.item = item;
+ }
+
+ static final AtomicReferenceFieldUpdater<SNode, SNode>
+ nextUpdater = AtomicReferenceFieldUpdater.newUpdater
+ (SNode.class, SNode.class, "next");
+
+ boolean casNext(SNode cmp, SNode val) {
+ return (cmp == next &&
+ nextUpdater.compareAndSet(this, cmp, val));
+ }
+
+ static final AtomicReferenceFieldUpdater<SNode, SNode>
+ matchUpdater = AtomicReferenceFieldUpdater.newUpdater
+ (SNode.class, SNode.class, "match");
+
+ /**
+ * Tries to match node s to this node, if so, waking up thread.
+ * Fulfillers call tryMatch to identify their waiters.
+ * Waiters block until they have been matched.
+ *
+ * @param s the node to match
+ * @return true if successfully matched to s
+ */
+ boolean tryMatch(SNode s) {
+ if (match == null &&
+ matchUpdater.compareAndSet(this, null, s)) {
+ Thread w = waiter;
+ if (w != null) { // waiters need at most one unpark
+ waiter = null;
+ LockSupport.unpark(w);
+ }
+ return true;
+ }
+ return match == s;
+ }
+
+ /**
+ * Tries to cancel a wait by matching node to itself.
+ */
+ void tryCancel() {
+ matchUpdater.compareAndSet(this, null, this);
+ }
+
+ boolean isCancelled() {
+ return match == this;
+ }
+ }
+
+ /** The head (top) of the stack */
+ volatile SNode head;
+
+ static final AtomicReferenceFieldUpdater<TransferStack, SNode>
+ headUpdater = AtomicReferenceFieldUpdater.newUpdater
+ (TransferStack.class, SNode.class, "head");
+
+ boolean casHead(SNode h, SNode nh) {
+ return h == head && headUpdater.compareAndSet(this, h, nh);
+ }
+
+ /**
+ * Creates or resets fields of a node. Called only from transfer
+ * where the node to push on stack is lazily created and
+ * reused when possible to help reduce intervals between reads
+ * and CASes of head and to avoid surges of garbage when CASes
+ * to push nodes fail due to contention.
+ */
+ static SNode snode(SNode s, Object e, SNode next, int mode) {
+ if (s == null) s = new SNode(e);
+ s.mode = mode;
+ s.next = next;
+ return s;
+ }
+
+ /**
+ * Puts or takes an item.
+ */
+ Object transfer(Object e, boolean timed, long nanos) {
+ /*
+ * Basic algorithm is to loop trying one of three actions:
+ *
+ * 1. If apparently empty or already containing nodes of same
+ * mode, try to push node on stack and wait for a match,
+ * returning it, or null if cancelled.
+ *
+ * 2. If apparently containing node of complementary mode,
+ * try to push a fulfilling node on to stack, match
+ * with corresponding waiting node, pop both from
+ * stack, and return matched item. The matching or
+ * unlinking might not actually be necessary because of
+ * other threads performing action 3:
+ *
+ * 3. If top of stack already holds another fulfilling node,
+ * help it out by doing its match and/or pop
+ * operations, and then continue. The code for helping
+ * is essentially the same as for fulfilling, except
+ * that it doesn't return the item.
+ */
+
+ SNode s = null; // constructed/reused as needed
+ int mode = (e == null)? REQUEST : DATA;
+
+ for (;;) {
+ SNode h = head;
+ if (h == null || h.mode == mode) { // empty or same-mode
+ if (timed && nanos <= 0) { // can't wait
+ if (h != null && h.isCancelled())
+ casHead(h, h.next); // pop cancelled node
+ else
+ return null;
+ } else if (casHead(h, s = snode(s, e, h, mode))) {
+ SNode m = awaitFulfill(s, timed, nanos);
+ if (m == s) { // wait was cancelled
+ clean(s);
+ return null;
+ }
+ if ((h = head) != null && h.next == s)
+ casHead(h, s.next); // help s's fulfiller
+ return mode == REQUEST? m.item : s.item;
+ }
+ } else if (!isFulfilling(h.mode)) { // try to fulfill
+ if (h.isCancelled()) // already cancelled
+ casHead(h, h.next); // pop and retry
+ else if (casHead(h, s=snode(s, e, h, FULFILLING|mode))) {
+ for (;;) { // loop until matched or waiters disappear
+ SNode m = s.next; // m is s's match
+ if (m == null) { // all waiters are gone
+ casHead(s, null); // pop fulfill node
+ s = null; // use new node next time
+ break; // restart main loop
+ }
+ SNode mn = m.next;
+ if (m.tryMatch(s)) {
+ casHead(s, mn); // pop both s and m
+ return (mode == REQUEST)? m.item : s.item;
+ } else // lost match
+ s.casNext(m, mn); // help unlink
+ }
+ }
+ } else { // help a fulfiller
+ SNode m = h.next; // m is h's match
+ if (m == null) // waiter is gone
+ casHead(h, null); // pop fulfilling node
+ else {
+ SNode mn = m.next;
+ if (m.tryMatch(h)) // help match
+ casHead(h, mn); // pop both h and m
+ else // lost match
+ h.casNext(m, mn); // help unlink
+ }
+ }
+ }
+ }
+
+ /**
+ * Spins/blocks until node s is matched by a fulfill operation.
+ *
+ * @param s the waiting node
+ * @param timed true if timed wait
+ * @param nanos timeout value
+ * @return matched node, or s if cancelled
+ */
+ SNode awaitFulfill(SNode s, boolean timed, long nanos) {
+ /*
+ * When a node/thread is about to block, it sets its waiter
+ * field and then rechecks state at least one more time
+ * before actually parking, thus covering race vs
+ * fulfiller noticing that waiter is non-null so should be
+ * woken.
+ *
+ * When invoked by nodes that appear at the point of call
+ * to be at the head of the stack, calls to park are
+ * preceded by spins to avoid blocking when producers and
+ * consumers are arriving very close in time. This can
+ * happen enough to bother only on multiprocessors.
+ *
+ * The order of checks for returning out of main loop
+ * reflects fact that interrupts have precedence over
+ * normal returns, which have precedence over
+ * timeouts. (So, on timeout, one last check for match is
+ * done before giving up.) Except that calls from untimed
+ * SynchronousQueue.{poll/offer} don't check interrupts
+ * and don't wait at all, so are trapped in transfer
+ * method rather than calling awaitFulfill.
+ */
+ long lastTime = (timed)? System.nanoTime() : 0;
+ Thread w = Thread.currentThread();
+ SNode h = head;
+ int spins = (shouldSpin(s)?
+ (timed? maxTimedSpins : maxUntimedSpins) : 0);
+ for (;;) {
+ if (w.isInterrupted())
+ s.tryCancel();
+ SNode m = s.match;
+ if (m != null)
+ return m;
+ if (timed) {
+ long now = System.nanoTime();
+ nanos -= now - lastTime;
+ lastTime = now;
+ if (nanos <= 0) {
+ s.tryCancel();
+ continue;
+ }
+ }
+ if (spins > 0)
+ spins = shouldSpin(s)? (spins-1) : 0;
+ else if (s.waiter == null)
+ s.waiter = w; // establish waiter so can park next iter
+ else if (!timed)
+ LockSupport.park(this);
+ else if (nanos > spinForTimeoutThreshold)
+ LockSupport.parkNanos(this, nanos);
+ }
+ }
+
+ /**
+ * Returns true if node s is at head or there is an active
+ * fulfiller.
+ */
+ boolean shouldSpin(SNode s) {
+ SNode h = head;
+ return (h == s || h == null || isFulfilling(h.mode));
+ }
+
+ /**
+ * Unlinks s from the stack.
+ */
+ void clean(SNode s) {
+ s.item = null; // forget item
+ s.waiter = null; // forget thread
+
+ /*
+ * At worst we may need to traverse entire stack to unlink
+ * s. If there are multiple concurrent calls to clean, we
+ * might not see s if another thread has already removed
+ * it. But we can stop when we see any node known to
+ * follow s. We use s.next unless it too is cancelled, in
+ * which case we try the node one past. We don't check any
+ * further because we don't want to doubly traverse just to
+ * find sentinel.
+ */
+
+ SNode past = s.next;
+ if (past != null && past.isCancelled())
+ past = past.next;
+
+ // Absorb cancelled nodes at head
+ SNode p;
+ while ((p = head) != null && p != past && p.isCancelled())
+ casHead(p, p.next);
+
+ // Unsplice embedded nodes
+ while (p != null && p != past) {
+ SNode n = p.next;
+ if (n != null && n.isCancelled())
+ p.casNext(n, n.next);
+ else
+ p = n;
+ }
+ }
+ }
+
+ /** Dual Queue */
+ static final class TransferQueue extends Transferer {
+ /*
+ * This extends Scherer-Scott dual queue algorithm, differing,
+ * among other ways, by using modes within nodes rather than
+ * marked pointers. The algorithm is a little simpler than
+ * that for stacks because fulfillers do not need explicit
+ * nodes, and matching is done by CAS'ing QNode.item field
+ * from non-null to null (for put) or vice versa (for take).
+ */
+
+ /** Node class for TransferQueue. */
+ static final class QNode {
+ volatile QNode next; // next node in queue
+ volatile Object item; // CAS'ed to or from null
+ volatile Thread waiter; // to control park/unpark
+ final boolean isData;
+
+ QNode(Object item, boolean isData) {
+ this.item = item;
+ this.isData = isData;
+ }
+
+ static final AtomicReferenceFieldUpdater<QNode, QNode>
+ nextUpdater = AtomicReferenceFieldUpdater.newUpdater
+ (QNode.class, QNode.class, "next");
+
+ boolean casNext(QNode cmp, QNode val) {
+ return (next == cmp &&
+ nextUpdater.compareAndSet(this, cmp, val));
+ }
+
+ static final AtomicReferenceFieldUpdater<QNode, Object>
+ itemUpdater = AtomicReferenceFieldUpdater.newUpdater
+ (QNode.class, Object.class, "item");
+
+ boolean casItem(Object cmp, Object val) {
+ return (item == cmp &&
+ itemUpdater.compareAndSet(this, cmp, val));
+ }
+
+ /**
+ * Tries to cancel by CAS'ing ref to this as item.
+ */
+ void tryCancel(Object cmp) {
+ itemUpdater.compareAndSet(this, cmp, this);
+ }
+
+ boolean isCancelled() {
+ return item == this;
+ }
+
+ /**
+ * Returns true if this node is known to be off the queue
+ * because its next pointer has been forgotten due to
+ * an advanceHead operation.
+ */
+ boolean isOffList() {
+ return next == this;
+ }
+ }
+
+ /** Head of queue */
+ transient volatile QNode head;
+ /** Tail of queue */
+ transient volatile QNode tail;
+ /**
+ * Reference to a cancelled node that might not yet have been
+ * unlinked from queue because it was the last inserted node
+ * when it cancelled.
+ */
+ transient volatile QNode cleanMe;
+
+ TransferQueue() {
+ QNode h = new QNode(null, false); // initialize to dummy node.
+ head = h;
+ tail = h;
+ }
+
+ static final AtomicReferenceFieldUpdater<TransferQueue, QNode>
+ headUpdater = AtomicReferenceFieldUpdater.newUpdater
+ (TransferQueue.class, QNode.class, "head");
+
+ /**
+ * Tries to cas nh as new head; if successful, unlink
+ * old head's next node to avoid garbage retention.
+ */
+ void advanceHead(QNode h, QNode nh) {
+ if (h == head && headUpdater.compareAndSet(this, h, nh))
+ h.next = h; // forget old next
+ }
+
+ static final AtomicReferenceFieldUpdater<TransferQueue, QNode>
+ tailUpdater = AtomicReferenceFieldUpdater.newUpdater
+ (TransferQueue.class, QNode.class, "tail");
+
+ /**
+ * Tries to cas nt as new tail.
+ */
+ void advanceTail(QNode t, QNode nt) {
+ if (tail == t)
+ tailUpdater.compareAndSet(this, t, nt);
+ }
+
+ static final AtomicReferenceFieldUpdater<TransferQueue, QNode>
+ cleanMeUpdater = AtomicReferenceFieldUpdater.newUpdater
+ (TransferQueue.class, QNode.class, "cleanMe");
+
+ /**
+ * Tries to CAS cleanMe slot.
+ */
+ boolean casCleanMe(QNode cmp, QNode val) {
+ return (cleanMe == cmp &&
+ cleanMeUpdater.compareAndSet(this, cmp, val));
+ }
+
+ /**
+ * Puts or takes an item.
+ */
+ Object transfer(Object e, boolean timed, long nanos) {
+ /* Basic algorithm is to loop trying to take either of
+ * two actions:
+ *
+ * 1. If queue apparently empty or holding same-mode nodes,
+ * try to add node to queue of waiters, wait to be
+ * fulfilled (or cancelled) and return matching item.
+ *
+ * 2. If queue apparently contains waiting items, and this
+ * call is of complementary mode, try to fulfill by CAS'ing
+ * item field of waiting node and dequeuing it, and then
+ * returning matching item.
+ *
+ * In each case, along the way, check for and try to help
+ * advance head and tail on behalf of other stalled/slow
+ * threads.
+ *
+ * The loop starts off with a null check guarding against
+ * seeing uninitialized head or tail values. This never
+ * happens in current SynchronousQueue, but could if
+ * callers held non-volatile/final ref to the
+ * transferer. The check is here anyway because it places
+ * null checks at top of loop, which is usually faster
+ * than having them implicitly interspersed.
+ */
+
+ QNode s = null; // constructed/reused as needed
+ boolean isData = (e != null);
+
+ for (;;) {
+ QNode t = tail;
+ QNode h = head;
+ if (t == null || h == null) // saw uninitialized value
+ continue; // spin
+
+ if (h == t || t.isData == isData) { // empty or same-mode
+ QNode tn = t.next;
+ if (t != tail) // inconsistent read
+ continue;
+ if (tn != null) { // lagging tail
+ advanceTail(t, tn);
+ continue;
+ }
+ if (timed && nanos <= 0) // can't wait
+ return null;
+ if (s == null)
+ s = new QNode(e, isData);
+ if (!t.casNext(null, s)) // failed to link in
+ continue;
+
+ advanceTail(t, s); // swing tail and wait
+ Object x = awaitFulfill(s, e, timed, nanos);
+ if (x == s) { // wait was cancelled
+ clean(t, s);
+ return null;
+ }
+
+ if (!s.isOffList()) { // not already unlinked
+ advanceHead(t, s); // unlink if head
+ if (x != null) // and forget fields
+ s.item = s;
+ s.waiter = null;
+ }
+ return (x != null)? x : e;
+
+ } else { // complementary-mode
+ QNode m = h.next; // node to fulfill
+ if (t != tail || m == null || h != head)
+ continue; // inconsistent read
+
+ Object x = m.item;
+ if (isData == (x != null) || // m already fulfilled
+ x == m || // m cancelled
+ !m.casItem(x, e)) { // lost CAS
+ advanceHead(h, m); // dequeue and retry
+ continue;
+ }
+
+ advanceHead(h, m); // successfully fulfilled
+ LockSupport.unpark(m.waiter);
+ return (x != null)? x : e;
+ }
+ }
+ }
+
+ /**
+ * Spins/blocks until node s is fulfilled.
+ *
+ * @param s the waiting node
+ * @param e the comparison value for checking match
+ * @param timed true if timed wait
+ * @param nanos timeout value
+ * @return matched item, or s if cancelled
+ */
+ Object awaitFulfill(QNode s, Object e, boolean timed, long nanos) {
+ /* Same idea as TransferStack.awaitFulfill */
+ long lastTime = (timed)? System.nanoTime() : 0;
+ Thread w = Thread.currentThread();
+ int spins = ((head.next == s) ?
+ (timed? maxTimedSpins : maxUntimedSpins) : 0);
+ for (;;) {
+ if (w.isInterrupted())
+ s.tryCancel(e);
+ Object x = s.item;
+ if (x != e)
+ return x;
+ if (timed) {
+ long now = System.nanoTime();
+ nanos -= now - lastTime;
+ lastTime = now;
+ if (nanos <= 0) {
+ s.tryCancel(e);
+ continue;
+ }
+ }
+ if (spins > 0)
+ --spins;
+ else if (s.waiter == null)
+ s.waiter = w;
+ else if (!timed)
+ LockSupport.park(this);
+ else if (nanos > spinForTimeoutThreshold)
+ LockSupport.parkNanos(this, nanos);
+ }
+ }
+
+ /**
+ * Gets rid of cancelled node s with original predecessor pred.
+ */
+ void clean(QNode pred, QNode s) {
+ s.waiter = null; // forget thread
+ /*
+ * At any given time, exactly one node on list cannot be
+ * deleted -- the last inserted node. To accommodate this,
+ * if we cannot delete s, we save its predecessor as
+ * "cleanMe", deleting the previously saved version
+ * first. At least one of node s or the node previously
+ * saved can always be deleted, so this always terminates.
+ */
+ while (pred.next == s) { // Return early if already unlinked
+ QNode h = head;
+ QNode hn = h.next; // Absorb cancelled first node as head
+ if (hn != null && hn.isCancelled()) {
+ advanceHead(h, hn);
+ continue;
+ }
+ QNode t = tail; // Ensure consistent read for tail
+ if (t == h)
+ return;
+ QNode tn = t.next;
+ if (t != tail)
+ continue;
+ if (tn != null) {
+ advanceTail(t, tn);
+ continue;
+ }
+ if (s != t) { // If not tail, try to unsplice
+ QNode sn = s.next;
+ if (sn == s || pred.casNext(s, sn))
+ return;
+ }
+ QNode dp = cleanMe;
+ if (dp != null) { // Try unlinking previous cancelled node
+ QNode d = dp.next;
+ QNode dn;
+ if (d == null || // d is gone or
+ d == dp || // d is off list or
+ !d.isCancelled() || // d not cancelled or
+ (d != t && // d not tail and
+ (dn = d.next) != null && // has successor
+ dn != d && // that is on list
+ dp.casNext(d, dn))) // d unspliced
+ casCleanMe(dp, null);
+ if (dp == pred)
+ return; // s is already saved node
+ } else if (casCleanMe(null, pred))
+ return; // Postpone cleaning s
+ }
+ }
+ }
+
+ /**
+ * The transferer. Set only in constructor, but cannot be declared
+ * as final without further complicating serialization. Since
+ * this is accessed only at most once per public method, there
+ * isn't a noticeable performance penalty for using volatile
+ * instead of final here.
+ */
+ private transient volatile Transferer transferer;
+
+ /**
+ * Creates a <tt>SynchronousQueue</tt> with nonfair access policy.
+ */
+ public SynchronousQueue() {
+ this(false);
+ }
+
+ /**
+ * Creates a <tt>SynchronousQueue</tt> with the specified fairness policy.
+ *
+ * @param fair if true, waiting threads contend in FIFO order for
+ * access; otherwise the order is unspecified.
+ */
+ public SynchronousQueue(boolean fair) {
+ transferer = (fair)? new TransferQueue() : new TransferStack();
+ }
+
+ /**
+ * Adds the specified element to this queue, waiting if necessary for
+ * another thread to receive it.
+ *
+ * @throws InterruptedException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public void put(E o) throws InterruptedException {
+ if (o == null) throw new NullPointerException();
+ if (transferer.transfer(o, false, 0) == null) {
+ Thread.interrupted();
+ throw new InterruptedException();
+ }
+ }
+
+ /**
+ * Inserts the specified element into this queue, waiting if necessary
+ * up to the specified wait time for another thread to receive it.
+ *
+ * @return <tt>true</tt> if successful, or <tt>false</tt> if the
+ * specified waiting time elapses before a consumer appears.
+ * @throws InterruptedException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean offer(E o, long timeout, TimeUnit unit)
+ throws InterruptedException {
+ if (o == null) throw new NullPointerException();
+ if (transferer.transfer(o, true, unit.toNanos(timeout)) != null)
+ return true;
+ if (!Thread.interrupted())
+ return false;
+ throw new InterruptedException();
+ }
+
+ /**
+ * Inserts the specified element into this queue, if another thread is
+ * waiting to receive it.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> if the element was added to this queue, else
+ * <tt>false</tt>
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean offer(E e) {
+ if (e == null) throw new NullPointerException();
+ return transferer.transfer(e, true, 0) != null;
+ }
+
+ /**
+ * Retrieves and removes the head of this queue, waiting if necessary
+ * for another thread to insert it.
+ *
+ * @return the head of this queue
+ * @throws InterruptedException {@inheritDoc}
+ */
+ public E take() throws InterruptedException {
+ Object e = transferer.transfer(null, false, 0);
+ if (e != null)
+ return (E)e;
+ Thread.interrupted();
+ throw new InterruptedException();
+ }
+
+ /**
+ * Retrieves and removes the head of this queue, waiting
+ * if necessary up to the specified wait time, for another thread
+ * to insert it.
+ *
+ * @return the head of this queue, or <tt>null</tt> if the
+ * specified waiting time elapses before an element is present.
+ * @throws InterruptedException {@inheritDoc}
+ */
+ public E poll(long timeout, TimeUnit unit) throws InterruptedException {
+ Object e = transferer.transfer(null, true, unit.toNanos(timeout));
+ if (e != null || !Thread.interrupted())
+ return (E)e;
+ throw new InterruptedException();
+ }
+
+ /**
+ * Retrieves and removes the head of this queue, if another thread
+ * is currently making an element available.
+ *
+ * @return the head of this queue, or <tt>null</tt> if no
+ * element is available.
+ */
+ public E poll() {
+ return (E)transferer.transfer(null, true, 0);
+ }
+
+ /**
+ * Always returns <tt>true</tt>.
+ * A <tt>SynchronousQueue</tt> has no internal capacity.
+ *
+ * @return <tt>true</tt>
+ */
+ public boolean isEmpty() {
+ return true;
+ }
+
+ /**
+ * Always returns zero.
+ * A <tt>SynchronousQueue</tt> has no internal capacity.
+ *
+ * @return zero.
+ */
+ public int size() {
+ return 0;
+ }
+
+ /**
+ * Always returns zero.
+ * A <tt>SynchronousQueue</tt> has no internal capacity.
+ *
+ * @return zero.
+ */
+ public int remainingCapacity() {
+ return 0;
+ }
+
+ /**
+ * Does nothing.
+ * A <tt>SynchronousQueue</tt> has no internal capacity.
+ */
+ public void clear() {
+ }
+
+ /**
+ * Always returns <tt>false</tt>.
+ * A <tt>SynchronousQueue</tt> has no internal capacity.
+ *
+ * @param o the element
+ * @return <tt>false</tt>
+ */
+ public boolean contains(Object o) {
+ return false;
+ }
+
+ /**
+ * Always returns <tt>false</tt>.
+ * A <tt>SynchronousQueue</tt> has no internal capacity.
+ *
+ * @param o the element to remove
+ * @return <tt>false</tt>
+ */
+ public boolean remove(Object o) {
+ return false;
+ }
+
+ /**
+ * Returns <tt>false</tt> unless the given collection is empty.
+ * A <tt>SynchronousQueue</tt> has no internal capacity.
+ *
+ * @param c the collection
+ * @return <tt>false</tt> unless given collection is empty
+ */
+ public boolean containsAll(Collection<?> c) {
+ return c.isEmpty();
+ }
+
+ /**
+ * Always returns <tt>false</tt>.
+ * A <tt>SynchronousQueue</tt> has no internal capacity.
+ *
+ * @param c the collection
+ * @return <tt>false</tt>
+ */
+ public boolean removeAll(Collection<?> c) {
+ return false;
+ }
+
+ /**
+ * Always returns <tt>false</tt>.
+ * A <tt>SynchronousQueue</tt> has no internal capacity.
+ *
+ * @param c the collection
+ * @return <tt>false</tt>
+ */
+ public boolean retainAll(Collection<?> c) {
+ return false;
+ }
+
+ /**
+ * Always returns <tt>null</tt>.
+ * A <tt>SynchronousQueue</tt> does not return elements
+ * unless actively waited on.
+ *
+ * @return <tt>null</tt>
+ */
+ public E peek() {
+ 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>.
+ *
+ * @return an empty iterator
+ */
+ public Iterator<E> iterator() {
+ return new EmptyIterator<E>();
+ }
+
+ /**
+ * Returns a zero-length array.
+ * @return a zero-length array
+ */
+ public Object[] toArray() {
+ return new Object[0];
+ }
+
+ /**
+ * Sets the zeroeth element of the specified array to <tt>null</tt>
+ * (if the array has non-zero length) and returns it.
+ *
+ * @param a the array
+ * @return the specified array
+ * @throws NullPointerException if the specified array is null
+ */
+ public <T> T[] toArray(T[] a) {
+ if (a.length > 0)
+ a[0] = null;
+ return a;
+ }
+
+ /**
+ * @throws UnsupportedOperationException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public int drainTo(Collection<? super E> c) {
+ if (c == null)
+ throw new NullPointerException();
+ if (c == this)
+ throw new IllegalArgumentException();
+ int n = 0;
+ E e;
+ while ( (e = poll()) != null) {
+ c.add(e);
+ ++n;
+ }
+ return n;
+ }
+
+ /**
+ * @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();
+ int n = 0;
+ E e;
+ while (n < maxElements && (e = poll()) != null) {
+ c.add(e);
+ ++n;
+ }
+ return n;
+ }
+
+ /*
+ * To cope with serialization strategy in the 1.5 version of
+ * SynchronousQueue, we declare some unused classes and fields
+ * that exist solely to enable serializability across versions.
+ * These fields are never used, so are initialized only if this
+ * object is ever serialized or deserialized.
+ */
+
+ static class WaitQueue implements java.io.Serializable { }
+ static class LifoWaitQueue extends WaitQueue {
+ private static final long serialVersionUID = -3633113410248163686L;
+ }
+ static class FifoWaitQueue extends WaitQueue {
+ private static final long serialVersionUID = -3623113410248163686L;
+ }
+ private ReentrantLock qlock;
+ private WaitQueue waitingProducers;
+ private WaitQueue waitingConsumers;
+
+ /**
+ * Save the state to a stream (that is, serialize it).
+ *
+ * @param s the stream
+ */
+ private void writeObject(java.io.ObjectOutputStream s)
+ throws java.io.IOException {
+ boolean fair = transferer instanceof TransferQueue;
+ if (fair) {
+ qlock = new ReentrantLock(true);
+ waitingProducers = new FifoWaitQueue();
+ waitingConsumers = new FifoWaitQueue();
+ }
+ else {
+ qlock = new ReentrantLock();
+ waitingProducers = new LifoWaitQueue();
+ waitingConsumers = new LifoWaitQueue();
+ }
+ s.defaultWriteObject();
+ }
+
+ private void readObject(final java.io.ObjectInputStream s)
+ throws java.io.IOException, ClassNotFoundException {
+ s.defaultReadObject();
+ if (waitingProducers instanceof FifoWaitQueue)
+ transferer = new TransferQueue();
+ else
+ transferer = new TransferStack();
+ }
+
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/ThreadFactory.java b/libjava/classpath/external/jsr166/java/util/concurrent/ThreadFactory.java
new file mode 100644
index 000000000..eca8dceb0
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/ThreadFactory.java
@@ -0,0 +1,40 @@
+/*
+ * 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;
+
+/**
+ * An object that creates new threads on demand. Using thread factories
+ * removes hardwiring of calls to {@link Thread#Thread(Runnable) new Thread},
+ * enabling applications to use special thread subclasses, priorities, etc.
+ *
+ * <p>
+ * The simplest implementation of this interface is just:
+ * <pre>
+ * class SimpleThreadFactory implements ThreadFactory {
+ * public Thread newThread(Runnable r) {
+ * return new Thread(r);
+ * }
+ * }
+ * </pre>
+ *
+ * The {@link Executors#defaultThreadFactory} method provides a more
+ * useful simple implementation, that sets the created thread context
+ * to known values before returning it.
+ * @since 1.5
+ * @author Doug Lea
+ */
+public interface ThreadFactory {
+
+ /**
+ * Constructs a new <tt>Thread</tt>. Implementations may also initialize
+ * priority, name, daemon status, <tt>ThreadGroup</tt>, etc.
+ *
+ * @param r a runnable to be executed by new thread instance
+ * @return constructed thread
+ */
+ Thread newThread(Runnable r);
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/ThreadPoolExecutor.java b/libjava/classpath/external/jsr166/java/util/concurrent/ThreadPoolExecutor.java
new file mode 100644
index 000000000..e303f14a8
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/ThreadPoolExecutor.java
@@ -0,0 +1,1605 @@
+/*
+ * 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.concurrent.locks.*;
+import java.util.*;
+
+/**
+ * An {@link ExecutorService} that executes each submitted task using
+ * one of possibly several pooled threads, normally configured
+ * using {@link Executors} factory methods.
+ *
+ * <p>Thread pools address two different problems: they usually
+ * provide improved performance when executing large numbers of
+ * asynchronous tasks, due to reduced per-task invocation overhead,
+ * and they provide a means of bounding and managing the resources,
+ * including threads, consumed when executing a collection of tasks.
+ * Each <tt>ThreadPoolExecutor</tt> also maintains some basic
+ * statistics, such as the number of completed tasks.
+ *
+ * <p>To be useful across a wide range of contexts, this class
+ * provides many adjustable parameters and extensibility
+ * hooks. However, programmers are urged to use the more convenient
+ * {@link Executors} factory methods {@link
+ * Executors#newCachedThreadPool} (unbounded thread pool, with
+ * automatic thread reclamation), {@link Executors#newFixedThreadPool}
+ * (fixed size thread pool) and {@link
+ * Executors#newSingleThreadExecutor} (single background thread), that
+ * preconfigure settings for the most common usage
+ * scenarios. Otherwise, use the following guide when manually
+ * configuring and tuning this class:
+ *
+ * <dl>
+ *
+ * <dt>Core and maximum pool sizes</dt>
+ *
+ * <dd>A <tt>ThreadPoolExecutor</tt> will automatically adjust the
+ * pool size
+ * (see {@link ThreadPoolExecutor#getPoolSize})
+ * according to the bounds set by corePoolSize
+ * (see {@link ThreadPoolExecutor#getCorePoolSize})
+ * and
+ * maximumPoolSize
+ * (see {@link ThreadPoolExecutor#getMaximumPoolSize}).
+ * When a new task is submitted in method {@link
+ * ThreadPoolExecutor#execute}, and fewer than corePoolSize threads
+ * are running, a new thread is created to handle the request, even if
+ * other worker threads are idle. If there are more than
+ * corePoolSize but less than maximumPoolSize threads running, a new
+ * thread will be created only if the queue is full. By setting
+ * corePoolSize and maximumPoolSize the same, you create a fixed-size
+ * thread pool. By setting maximumPoolSize to an essentially unbounded
+ * value such as <tt>Integer.MAX_VALUE</tt>, you allow the pool to
+ * accommodate an arbitrary number of concurrent tasks. Most typically,
+ * core and maximum pool sizes are set only upon construction, but they
+ * may also be changed dynamically using {@link
+ * ThreadPoolExecutor#setCorePoolSize} and {@link
+ * ThreadPoolExecutor#setMaximumPoolSize}. <dd>
+ *
+ * <dt> On-demand construction
+ *
+ * <dd> By default, even core threads are initially created and
+ * started only when new tasks arrive, but this can be overridden
+ * dynamically using method {@link
+ * ThreadPoolExecutor#prestartCoreThread} or
+ * {@link ThreadPoolExecutor#prestartAllCoreThreads}.
+ * You probably want to prestart threads if you construct the
+ * pool with a non-empty queue. </dd>
+ *
+ * <dt>Creating new threads</dt>
+ *
+ * <dd>New threads are created using a {@link
+ * java.util.concurrent.ThreadFactory}. If not otherwise specified, a
+ * {@link Executors#defaultThreadFactory} is used, that creates threads to all
+ * be in the same {@link ThreadGroup} and with the same
+ * <tt>NORM_PRIORITY</tt> priority and non-daemon status. By supplying
+ * a different ThreadFactory, you can alter the thread's name, thread
+ * group, priority, daemon status, etc. If a <tt>ThreadFactory</tt> fails to create
+ * a thread when asked by returning null from <tt>newThread</tt>,
+ * the executor will continue, but might
+ * not be able to execute any tasks. </dd>
+ *
+ * <dt>Keep-alive times</dt>
+ *
+ * <dd>If the pool currently has more than corePoolSize threads,
+ * excess threads will be terminated if they have been idle for more
+ * than the keepAliveTime (see {@link
+ * ThreadPoolExecutor#getKeepAliveTime}). This provides a means of
+ * reducing resource consumption when the pool is not being actively
+ * used. If the pool becomes more active later, new threads will be
+ * constructed. This parameter can also be changed dynamically using
+ * method {@link ThreadPoolExecutor#setKeepAliveTime}. Using a value
+ * of <tt>Long.MAX_VALUE</tt> {@link TimeUnit#NANOSECONDS} effectively
+ * 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
+ * ThreadPoolExecutor#allowCoreThreadTimeOut} 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>
+ *
+ * <dd>Any {@link BlockingQueue} may be used to transfer and hold
+ * submitted tasks. The use of this queue interacts with pool sizing:
+ *
+ * <ul>
+ *
+ * <li> If fewer than corePoolSize threads are running, the Executor
+ * always prefers adding a new thread
+ * rather than queuing.</li>
+ *
+ * <li> If corePoolSize or more threads are running, the Executor
+ * always prefers queuing a request rather than adding a new
+ * thread.</li>
+ *
+ * <li> If a request cannot be queued, a new thread is created unless
+ * this would exceed maximumPoolSize, in which case, the task will be
+ * rejected.</li>
+ *
+ * </ul>
+ *
+ * There are three general strategies for queuing:
+ * <ol>
+ *
+ * <li> <em> Direct handoffs.</em> A good default choice for a work
+ * queue is a {@link SynchronousQueue} that hands off tasks to threads
+ * without otherwise holding them. Here, an attempt to queue a task
+ * will fail if no threads are immediately available to run it, so a
+ * new thread will be constructed. This policy avoids lockups when
+ * handling sets of requests that might have internal dependencies.
+ * Direct handoffs generally require unbounded maximumPoolSizes to
+ * avoid rejection of new submitted tasks. This in turn admits the
+ * possibility of unbounded thread growth when commands continue to
+ * arrive on average faster than they can be processed. </li>
+ *
+ * <li><em> Unbounded queues.</em> Using an unbounded queue (for
+ * example a {@link LinkedBlockingQueue} without a predefined
+ * capacity) will cause new tasks to wait in the queue when all
+ * corePoolSize threads are busy. Thus, no more than corePoolSize
+ * threads will ever be created. (And the value of the maximumPoolSize
+ * therefore doesn't have any effect.) This may be appropriate when
+ * each task is completely independent of others, so tasks cannot
+ * affect each others execution; for example, in a web page server.
+ * While this style of queuing can be useful in smoothing out
+ * transient bursts of requests, it admits the possibility of
+ * unbounded work queue growth when commands continue to arrive on
+ * average faster than they can be processed. </li>
+ *
+ * <li><em>Bounded queues.</em> A bounded queue (for example, an
+ * {@link ArrayBlockingQueue}) helps prevent resource exhaustion when
+ * used with finite maximumPoolSizes, but can be more difficult to
+ * tune and control. Queue sizes and maximum pool sizes may be traded
+ * off for each other: Using large queues and small pools minimizes
+ * CPU usage, OS resources, and context-switching overhead, but can
+ * lead to artificially low throughput. If tasks frequently block (for
+ * example if they are I/O bound), a system may be able to schedule
+ * time for more threads than you otherwise allow. Use of small queues
+ * generally requires larger pool sizes, which keeps CPUs busier but
+ * may encounter unacceptable scheduling overhead, which also
+ * decreases throughput. </li>
+ *
+ * </ol>
+ *
+ * </dd>
+ *
+ * <dt>Rejected tasks</dt>
+ *
+ * <dd> New tasks submitted in method {@link
+ * ThreadPoolExecutor#execute} will be <em>rejected</em> when the
+ * Executor has been shut down, and also when the Executor uses finite
+ * bounds for both maximum threads and work queue capacity, and is
+ * saturated. In either case, the <tt>execute</tt> method invokes the
+ * {@link RejectedExecutionHandler#rejectedExecution} method of its
+ * {@link RejectedExecutionHandler}. Four predefined handler policies
+ * are provided:
+ *
+ * <ol>
+ *
+ * <li> In the
+ * default {@link ThreadPoolExecutor.AbortPolicy}, the handler throws a
+ * runtime {@link RejectedExecutionException} upon rejection. </li>
+ *
+ * <li> In {@link
+ * ThreadPoolExecutor.CallerRunsPolicy}, the thread that invokes
+ * <tt>execute</tt> itself runs the task. This provides a simple
+ * feedback control mechanism that will slow down the rate that new
+ * tasks are submitted. </li>
+ *
+ * <li> In {@link ThreadPoolExecutor.DiscardPolicy},
+ * a task that cannot be executed is simply dropped. </li>
+ *
+ * <li>In {@link
+ * ThreadPoolExecutor.DiscardOldestPolicy}, if the executor is not
+ * shut down, the task at the head of the work queue is dropped, and
+ * then execution is retried (which can fail again, causing this to be
+ * repeated.) </li>
+ *
+ * </ol>
+ *
+ * It is possible to define and use other kinds of {@link
+ * RejectedExecutionHandler} classes. Doing so requires some care
+ * especially when policies are designed to work only under particular
+ * capacity or queuing policies. </dd>
+ *
+ * <dt>Hook methods</dt>
+ *
+ * <dd>This class provides <tt>protected</tt> overridable {@link
+ * ThreadPoolExecutor#beforeExecute} and {@link
+ * ThreadPoolExecutor#afterExecute} methods that are called before and
+ * after execution of each task. These can be used to manipulate the
+ * execution environment; for example, reinitializing ThreadLocals,
+ * gathering statistics, or adding log entries. Additionally, method
+ * {@link ThreadPoolExecutor#terminated} can be overridden to perform
+ * any special processing that needs to be done once the Executor has
+ * fully terminated.
+ *
+ * <p>If hook or callback methods throw
+ * exceptions, internal worker threads may in turn fail and
+ * abruptly terminate.</dd>
+ *
+ * <dt>Queue maintenance</dt>
+ *
+ * <dd> Method {@link ThreadPoolExecutor#getQueue} allows access to
+ * the work queue for purposes of monitoring and debugging. Use of
+ * this method for any other purpose is strongly discouraged. Two
+ * supplied methods, {@link ThreadPoolExecutor#remove} and {@link
+ * ThreadPoolExecutor#purge} are available to assist in storage
+ * reclamation when large numbers of queued tasks become
+ * cancelled.</dd>
+ *
+ * <dt>Finalization</dt>
+ *
+ * <dd> A pool that is no longer referenced in a program <em>AND</em>
+ * has no remaining threads will be <tt>shutdown</tt>
+ * automatically. If you would like to ensure that unreferenced pools
+ * are reclaimed even if users forget to call {@link
+ * ThreadPoolExecutor#shutdown}, then you must arrange that unused
+ * threads eventually die, by setting appropriate keep-alive times,
+ * using a lower bound of zero core threads and/or setting {@link
+ * ThreadPoolExecutor#allowCoreThreadTimeOut}. </dd> </dl>
+ *
+ * <p> <b>Extension example</b>. Most extensions of this class
+ * override one or more of the protected hook methods. For example,
+ * here is a subclass that adds a simple pause/resume feature:
+ *
+ * <pre>
+ * class PausableThreadPoolExecutor extends ThreadPoolExecutor {
+ * private boolean isPaused;
+ * private ReentrantLock pauseLock = new ReentrantLock();
+ * private Condition unpaused = pauseLock.newCondition();
+ *
+ * public PausableThreadPoolExecutor(...) { super(...); }
+ *
+ * protected void beforeExecute(Thread t, Runnable r) {
+ * super.beforeExecute(t, r);
+ * pauseLock.lock();
+ * try {
+ * while (isPaused) unpaused.await();
+ * } catch (InterruptedException ie) {
+ * t.interrupt();
+ * } finally {
+ * pauseLock.unlock();
+ * }
+ * }
+ *
+ * public void pause() {
+ * pauseLock.lock();
+ * try {
+ * isPaused = true;
+ * } finally {
+ * pauseLock.unlock();
+ * }
+ * }
+ *
+ * public void resume() {
+ * pauseLock.lock();
+ * try {
+ * isPaused = false;
+ * unpaused.signalAll();
+ * } finally {
+ * pauseLock.unlock();
+ * }
+ * }
+ * }
+ * </pre>
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class ThreadPoolExecutor extends AbstractExecutorService {
+ /**
+ * Only used to force toArray() to produce a Runnable[].
+ */
+ private static final Runnable[] EMPTY_RUNNABLE_ARRAY = new Runnable[0];
+
+ /**
+ * Permission for checking shutdown
+ */
+ private static final RuntimePermission shutdownPerm =
+ new RuntimePermission("modifyThread");
+
+ /**
+ * Queue used for holding tasks and handing off to worker threads.
+ */
+ private final BlockingQueue<Runnable> workQueue;
+
+ /**
+ * Lock held on updates to poolSize, corePoolSize, maximumPoolSize, and
+ * workers set.
+ */
+ private final ReentrantLock mainLock = new ReentrantLock();
+
+ /**
+ * Wait condition to support awaitTermination
+ */
+ private final Condition termination = mainLock.newCondition();
+
+ /**
+ * Set containing all worker threads in pool.
+ */
+ private final HashSet<Worker> workers = new HashSet<Worker>();
+
+ /**
+ * Timeout in nanoseconds for idle threads waiting for work.
+ * Threads use this timeout only when there are more than
+ * corePoolSize present. 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, updated only while holding mainLock,
+ * but volatile to allow concurrent readability even
+ * during updates.
+ */
+ private volatile int corePoolSize;
+
+ /**
+ * Maximum pool size, updated only while holding mainLock
+ * but volatile to allow concurrent readability even
+ * during updates.
+ */
+ private volatile int maximumPoolSize;
+
+ /**
+ * Current pool size, updated only while holding mainLock
+ * but volatile to allow concurrent readability even
+ * during updates.
+ */
+ private volatile int poolSize;
+
+ /**
+ * Lifecycle state
+ */
+ volatile int runState;
+
+ // Special values for runState
+ /** Normal, not-shutdown mode */
+ static final int RUNNING = 0;
+ /** Controlled shutdown mode */
+ static final int SHUTDOWN = 1;
+ /** Immediate shutdown mode */
+ static final int STOP = 2;
+ /** Final state */
+ static final int TERMINATED = 3;
+
+ /**
+ * Handler called when saturated or shutdown in execute.
+ */
+ private volatile RejectedExecutionHandler handler;
+
+ /**
+ * Factory for new threads.
+ */
+ private volatile ThreadFactory threadFactory;
+
+ /**
+ * Tracks largest attained pool size.
+ */
+ private int largestPoolSize;
+
+ /**
+ * Counter for completed tasks. Updated only on termination of
+ * worker threads.
+ */
+ private long completedTaskCount;
+
+ /**
+ * The default rejected execution handler
+ */
+ private static final RejectedExecutionHandler defaultHandler =
+ new AbortPolicy();
+
+ /**
+ * Invokes the rejected execution handler for the given command.
+ */
+ void reject(Runnable command) {
+ handler.rejectedExecution(command, this);
+ }
+
+ /**
+ * Creates and returns a new thread running firstTask as its first
+ * task. Call only while holding mainLock.
+ * @param firstTask the task the new thread should run first (or
+ * null if none)
+ * @return the new thread, or null if threadFactory fails to create thread
+ */
+ private Thread addThread(Runnable firstTask) {
+ if (runState == TERMINATED) // Don't create thread if terminated
+ return null;
+ Worker w = new Worker(firstTask);
+ Thread t = threadFactory.newThread(w);
+ if (t != null) {
+ w.thread = t;
+ workers.add(w);
+ int nt = ++poolSize;
+ if (nt > largestPoolSize)
+ largestPoolSize = nt;
+ }
+ return t;
+ }
+
+ /**
+ * Creates and starts a new thread running firstTask as its first
+ * task, only if fewer than corePoolSize threads are running.
+ * @param firstTask the task the new thread should run first (or
+ * null if none)
+ * @return true if successful.
+ */
+ private boolean addIfUnderCorePoolSize(Runnable firstTask) {
+ Thread t = null;
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ if (poolSize < corePoolSize)
+ t = addThread(firstTask);
+ } finally {
+ mainLock.unlock();
+ }
+ if (t == null)
+ return false;
+ t.start();
+ return true;
+ }
+
+ /**
+ * Creates and starts a new thread only if fewer than maximumPoolSize
+ * threads are running. The new thread runs as its first task the
+ * next task in queue, or if there is none, the given task.
+ * @param firstTask the task the new thread should run first (or
+ * null if none)
+ * @return 0 if a new thread cannot be created, a positive number
+ * if firstTask will be run in a new thread, or a negative number
+ * if a new thread was created but is running some other task, in
+ * which case the caller must try some other way to run firstTask
+ * (perhaps by calling this method again).
+ */
+ private int addIfUnderMaximumPoolSize(Runnable firstTask) {
+ Thread t = null;
+ int status = 0;
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ if (poolSize < maximumPoolSize) {
+ Runnable next = workQueue.poll();
+ if (next == null) {
+ next = firstTask;
+ status = 1;
+ } else
+ status = -1;
+ t = addThread(next);
+ }
+ } finally {
+ mainLock.unlock();
+ }
+ if (t == null)
+ return 0;
+ t.start();
+ return status;
+ }
+
+
+ /**
+ * Gets the next task for a worker thread to run.
+ * @return the task
+ */
+ Runnable getTask() {
+ for (;;) {
+ try {
+ switch (runState) {
+ case RUNNING: {
+ // untimed wait if core and not allowing core timeout
+ if (poolSize <= corePoolSize && !allowCoreThreadTimeOut)
+ return workQueue.take();
+
+ long timeout = keepAliveTime;
+ if (timeout <= 0) // die immediately for 0 timeout
+ return null;
+ Runnable r = workQueue.poll(timeout, TimeUnit.NANOSECONDS);
+ if (r != null)
+ return r;
+ if (poolSize > corePoolSize || allowCoreThreadTimeOut)
+ return null; // timed out
+ // Else, after timeout, the pool shrank. Retry
+ break;
+ }
+
+ case SHUTDOWN: {
+ // Help drain queue
+ Runnable r = workQueue.poll();
+ if (r != null)
+ return r;
+
+ // Check if can terminate
+ if (workQueue.isEmpty()) {
+ interruptIdleWorkers();
+ return null;
+ }
+
+ // Else there could still be delayed tasks in queue.
+ return workQueue.take();
+ }
+
+ case STOP:
+ return null;
+ default:
+ assert false;
+ }
+ } catch (InterruptedException ie) {
+ // On interruption, re-check runstate
+ }
+ }
+ }
+
+ /**
+ * Wakes up all threads that might be waiting for tasks.
+ */
+ void interruptIdleWorkers() {
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ for (Worker w : workers)
+ w.interruptIfIdle();
+ } finally {
+ mainLock.unlock();
+ }
+ }
+
+ /**
+ * Performs bookkeeping for a terminated worker thread.
+ * @param w the worker
+ */
+ void workerDone(Worker w) {
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ completedTaskCount += w.completedTasks;
+ workers.remove(w);
+ if (--poolSize > 0)
+ return;
+
+ // Else, this is the last thread. Deal with potential shutdown.
+
+ int state = runState;
+ assert state != TERMINATED;
+
+ if (state != STOP) {
+ // If there are queued tasks but no threads, create
+ // replacement thread. We must create it initially
+ // idle to avoid orphaned tasks in case addThread
+ // fails. This also handles case of delayed tasks
+ // that will sometime later become runnable.
+ if (!workQueue.isEmpty()) {
+ Thread t = addThread(null);
+ if (t != null)
+ t.start();
+ return;
+ }
+
+ // Otherwise, we can exit without replacement
+ if (state == RUNNING)
+ return;
+ }
+
+ // Either state is STOP, or state is SHUTDOWN and there is
+ // no work to do. So we can terminate.
+ termination.signalAll();
+ runState = TERMINATED;
+ // fall through to call terminate() outside of lock.
+ } finally {
+ mainLock.unlock();
+ }
+
+ assert runState == TERMINATED;
+ terminated();
+ }
+
+ /**
+ * Worker threads
+ */
+ private class Worker implements Runnable {
+
+ /**
+ * The runLock is acquired and released surrounding each task
+ * execution. It mainly protects against interrupts that are
+ * intended to cancel the worker thread from instead
+ * interrupting the task being run.
+ */
+ private final ReentrantLock runLock = new ReentrantLock();
+
+ /**
+ * Initial task to run before entering run loop
+ */
+ private Runnable firstTask;
+
+ /**
+ * Per thread completed task counter; accumulated
+ * into completedTaskCount upon termination.
+ */
+ volatile long completedTasks;
+
+ /**
+ * Thread this worker is running in. Acts as a final field,
+ * but cannot be set until thread is created.
+ */
+ Thread thread;
+
+ Worker(Runnable firstTask) {
+ this.firstTask = firstTask;
+ }
+
+ boolean isActive() {
+ return runLock.isLocked();
+ }
+
+ /**
+ * Interrupts thread if not running a task.
+ */
+ void interruptIfIdle() {
+ final ReentrantLock runLock = this.runLock;
+ if (runLock.tryLock()) {
+ try {
+ thread.interrupt();
+ } finally {
+ runLock.unlock();
+ }
+ }
+ }
+
+ /**
+ * Interrupts thread even if running a task.
+ */
+ void interruptNow() {
+ thread.interrupt();
+ }
+
+ /**
+ * Runs a single task between before/after methods.
+ */
+ private void runTask(Runnable task) {
+ final ReentrantLock runLock = this.runLock;
+ runLock.lock();
+ try {
+ // If not shutting down then clear an outstanding interrupt.
+ if (runState != STOP &&
+ Thread.interrupted() &&
+ runState == STOP) // Re-interrupt if stopped after clearing
+ thread.interrupt();
+ boolean ran = false;
+ beforeExecute(thread, task);
+ try {
+ task.run();
+ ran = true;
+ afterExecute(task, null);
+ ++completedTasks;
+ } catch (RuntimeException ex) {
+ if (!ran)
+ afterExecute(task, ex);
+ // Else the exception occurred within
+ // afterExecute itself in which case we don't
+ // want to call it again.
+ throw ex;
+ }
+ } finally {
+ runLock.unlock();
+ }
+ }
+
+ /**
+ * Main run loop
+ */
+ public void run() {
+ try {
+ Runnable task = firstTask;
+ firstTask = null;
+ while (task != null || (task = getTask()) != null) {
+ runTask(task);
+ task = null; // unnecessary but can help GC
+ }
+ } finally {
+ workerDone(this);
+ }
+ }
+ }
+
+ // Public methods
+
+ /**
+ * Creates a new <tt>ThreadPoolExecutor</tt> with the given initial
+ * parameters and default thread factory and rejected execution handler.
+ * It may be more convenient to use one of the {@link Executors} factory
+ * methods instead of this general purpose constructor.
+ *
+ * @param corePoolSize the number of threads to keep in the
+ * pool, even if they are idle.
+ * @param maximumPoolSize the maximum number of threads to allow in the
+ * pool.
+ * @param keepAliveTime when the number of threads is greater than
+ * the core, this is the maximum time that excess idle threads
+ * will wait for new tasks before terminating.
+ * @param unit the time unit for the keepAliveTime
+ * argument.
+ * @param workQueue the queue to use for holding tasks before they
+ * are executed. This queue will hold only the <tt>Runnable</tt>
+ * tasks submitted by the <tt>execute</tt> method.
+ * @throws IllegalArgumentException if corePoolSize, or
+ * keepAliveTime less than zero, or if maximumPoolSize less than or
+ * equal to zero, or if corePoolSize greater than maximumPoolSize.
+ * @throws NullPointerException if <tt>workQueue</tt> is null
+ */
+ public ThreadPoolExecutor(int corePoolSize,
+ int maximumPoolSize,
+ long keepAliveTime,
+ TimeUnit unit,
+ BlockingQueue<Runnable> workQueue) {
+ this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
+ Executors.defaultThreadFactory(), defaultHandler);
+ }
+
+ /**
+ * Creates a new <tt>ThreadPoolExecutor</tt> with the given initial
+ * parameters and default rejected execution handler.
+ *
+ * @param corePoolSize the number of threads to keep in the
+ * pool, even if they are idle.
+ * @param maximumPoolSize the maximum number of threads to allow in the
+ * pool.
+ * @param keepAliveTime when the number of threads is greater than
+ * the core, this is the maximum time that excess idle threads
+ * will wait for new tasks before terminating.
+ * @param unit the time unit for the keepAliveTime
+ * argument.
+ * @param workQueue the queue to use for holding tasks before they
+ * are executed. This queue will hold only the <tt>Runnable</tt>
+ * tasks submitted by the <tt>execute</tt> method.
+ * @param threadFactory the factory to use when the executor
+ * creates a new thread.
+ * @throws IllegalArgumentException if corePoolSize, or
+ * keepAliveTime less than zero, or if maximumPoolSize less than or
+ * equal to zero, or if corePoolSize greater than maximumPoolSize.
+ * @throws NullPointerException if <tt>workQueue</tt>
+ * or <tt>threadFactory</tt> are null.
+ */
+ public ThreadPoolExecutor(int corePoolSize,
+ int maximumPoolSize,
+ long keepAliveTime,
+ TimeUnit unit,
+ BlockingQueue<Runnable> workQueue,
+ ThreadFactory threadFactory) {
+ this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
+ threadFactory, defaultHandler);
+ }
+
+ /**
+ * Creates a new <tt>ThreadPoolExecutor</tt> with the given initial
+ * parameters and default thread factory.
+ *
+ * @param corePoolSize the number of threads to keep in the
+ * pool, even if they are idle.
+ * @param maximumPoolSize the maximum number of threads to allow in the
+ * pool.
+ * @param keepAliveTime when the number of threads is greater than
+ * the core, this is the maximum time that excess idle threads
+ * will wait for new tasks before terminating.
+ * @param unit the time unit for the keepAliveTime
+ * argument.
+ * @param workQueue the queue to use for holding tasks before they
+ * are executed. This queue will hold only the <tt>Runnable</tt>
+ * tasks submitted by the <tt>execute</tt> method.
+ * @param handler the handler to use when execution is blocked
+ * because the thread bounds and queue capacities are reached.
+ * @throws IllegalArgumentException if corePoolSize, or
+ * keepAliveTime less than zero, or if maximumPoolSize less than or
+ * equal to zero, or if corePoolSize greater than maximumPoolSize.
+ * @throws NullPointerException if <tt>workQueue</tt>
+ * or <tt>handler</tt> are null.
+ */
+ public ThreadPoolExecutor(int corePoolSize,
+ int maximumPoolSize,
+ long keepAliveTime,
+ TimeUnit unit,
+ BlockingQueue<Runnable> workQueue,
+ RejectedExecutionHandler handler) {
+ this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
+ Executors.defaultThreadFactory(), handler);
+ }
+
+ /**
+ * Creates a new <tt>ThreadPoolExecutor</tt> with the given initial
+ * parameters.
+ *
+ * @param corePoolSize the number of threads to keep in the
+ * pool, even if they are idle.
+ * @param maximumPoolSize the maximum number of threads to allow in the
+ * pool.
+ * @param keepAliveTime when the number of threads is greater than
+ * the core, this is the maximum time that excess idle threads
+ * will wait for new tasks before terminating.
+ * @param unit the time unit for the keepAliveTime
+ * argument.
+ * @param workQueue the queue to use for holding tasks before they
+ * are executed. This queue will hold only the <tt>Runnable</tt>
+ * tasks submitted by the <tt>execute</tt> method.
+ * @param threadFactory the factory to use when the executor
+ * creates a new thread.
+ * @param handler the handler to use when execution is blocked
+ * because the thread bounds and queue capacities are reached.
+ * @throws IllegalArgumentException if corePoolSize, or
+ * keepAliveTime less than zero, or if maximumPoolSize less than or
+ * equal to zero, or if corePoolSize greater than maximumPoolSize.
+ * @throws NullPointerException if <tt>workQueue</tt>
+ * or <tt>threadFactory</tt> or <tt>handler</tt> are null.
+ */
+ public ThreadPoolExecutor(int corePoolSize,
+ int maximumPoolSize,
+ long keepAliveTime,
+ TimeUnit unit,
+ BlockingQueue<Runnable> workQueue,
+ ThreadFactory threadFactory,
+ RejectedExecutionHandler handler) {
+ if (corePoolSize < 0 ||
+ maximumPoolSize <= 0 ||
+ maximumPoolSize < corePoolSize ||
+ keepAliveTime < 0)
+ throw new IllegalArgumentException();
+ if (workQueue == null || threadFactory == null || handler == null)
+ throw new NullPointerException();
+ this.corePoolSize = corePoolSize;
+ this.maximumPoolSize = maximumPoolSize;
+ this.workQueue = workQueue;
+ this.keepAliveTime = unit.toNanos(keepAliveTime);
+ this.threadFactory = threadFactory;
+ this.handler = handler;
+ }
+
+
+ /**
+ * Executes the given task sometime in the future. The task
+ * may execute in a new thread or in an existing pooled thread.
+ *
+ * If the task cannot be submitted for execution, either because this
+ * executor has been shutdown or because its capacity has been reached,
+ * the task is handled by the current <tt>RejectedExecutionHandler</tt>.
+ *
+ * @param command the task to execute
+ * @throws RejectedExecutionException at discretion of
+ * <tt>RejectedExecutionHandler</tt>, if task cannot be accepted
+ * for execution
+ * @throws NullPointerException if command is null
+ */
+ public void execute(Runnable command) {
+ if (command == null)
+ throw new NullPointerException();
+ for (;;) {
+ if (runState != RUNNING) {
+ reject(command);
+ return;
+ }
+ if (poolSize < corePoolSize && addIfUnderCorePoolSize(command))
+ return;
+ if (workQueue.offer(command))
+ return;
+ int status = addIfUnderMaximumPoolSize(command);
+ if (status > 0) // created new thread
+ return;
+ if (status == 0) { // failed to create thread
+ reject(command);
+ return;
+ }
+ // Retry if created a new thread but it is busy with another task
+ }
+ }
+
+ /**
+ * 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.
+ * @throws SecurityException if a security manager exists and
+ * shutting down this ExecutorService may manipulate threads that
+ * the caller is not permitted to modify because it does not hold
+ * {@link java.lang.RuntimePermission}<tt>("modifyThread")</tt>,
+ * or the security manager's <tt>checkAccess</tt> method denies access.
+ */
+ public void shutdown() {
+ // Fail if caller doesn't have modifyThread permission.
+ SecurityManager security = System.getSecurityManager();
+ if (security != null)
+ security.checkPermission(shutdownPerm);
+
+ boolean fullyTerminated = false;
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ if (workers.size() > 0) {
+ // Check if caller can modify worker threads. This
+ // might not be true even if passed above check, if
+ // the SecurityManager treats some threads specially.
+ if (security != null) {
+ for (Worker w: workers)
+ security.checkAccess(w.thread);
+ }
+
+ int state = runState;
+ if (state == RUNNING) // don't override shutdownNow
+ runState = SHUTDOWN;
+
+ try {
+ for (Worker w: workers)
+ w.interruptIfIdle();
+ } catch (SecurityException se) {
+ // If SecurityManager allows above checks, but
+ // then unexpectedly throws exception when
+ // interrupting threads (which it ought not do),
+ // back out as cleanly as we can. Some threads may
+ // have been killed but we remain in non-shutdown
+ // state.
+ runState = state;
+ throw se;
+ }
+ }
+ else { // If no workers, trigger full termination now
+ fullyTerminated = true;
+ runState = TERMINATED;
+ termination.signalAll();
+ }
+ } finally {
+ mainLock.unlock();
+ }
+ if (fullyTerminated)
+ terminated();
+ }
+
+
+ /**
+ * Attempts to stop all actively executing tasks, halts the
+ * processing of waiting tasks, and returns a list of the tasks
+ * that were awaiting execution.
+ *
+ * <p>There are no guarantees beyond best-effort attempts to stop
+ * processing actively executing tasks. This implementation
+ * cancels tasks via {@link Thread#interrupt}, so any task that
+ * fails to respond to interrupts may never terminate.
+ *
+ * @return list of tasks that never commenced execution
+ * @throws SecurityException if a security manager exists and
+ * shutting down this ExecutorService may manipulate threads that
+ * the caller is not permitted to modify because it does not hold
+ * {@link java.lang.RuntimePermission}<tt>("modifyThread")</tt>,
+ * or the security manager's <tt>checkAccess</tt> method denies access.
+ */
+ public List<Runnable> shutdownNow() {
+ // Almost the same code as shutdown()
+ SecurityManager security = System.getSecurityManager();
+ if (security != null)
+ security.checkPermission(shutdownPerm);
+
+ boolean fullyTerminated = false;
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ if (workers.size() > 0) {
+ if (security != null) {
+ for (Worker w: workers)
+ security.checkAccess(w.thread);
+ }
+
+ int state = runState;
+ if (state != TERMINATED)
+ runState = STOP;
+ try {
+ for (Worker w : workers)
+ w.interruptNow();
+ } catch (SecurityException se) {
+ runState = state; // back out;
+ throw se;
+ }
+ }
+ else { // If no workers, trigger full termination now
+ fullyTerminated = true;
+ runState = TERMINATED;
+ termination.signalAll();
+ }
+ } finally {
+ mainLock.unlock();
+ }
+ if (fullyTerminated)
+ terminated();
+ return Arrays.asList(workQueue.toArray(EMPTY_RUNNABLE_ARRAY));
+ }
+
+ public boolean isShutdown() {
+ return runState != RUNNING;
+ }
+
+ /**
+ * Returns true if this executor is in the process of terminating
+ * after <tt>shutdown</tt> or <tt>shutdownNow</tt> but has not
+ * completely terminated. This method may be useful for
+ * debugging. A return of <tt>true</tt> reported a sufficient
+ * period after shutdown may indicate that submitted tasks have
+ * ignored or suppressed interruption, causing this executor not
+ * to properly terminate.
+ * @return true if terminating but not yet terminated.
+ */
+ public boolean isTerminating() {
+ return runState == STOP;
+ }
+
+ public boolean isTerminated() {
+ return runState == TERMINATED;
+ }
+
+ public boolean awaitTermination(long timeout, TimeUnit unit)
+ throws InterruptedException {
+ long nanos = unit.toNanos(timeout);
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ for (;;) {
+ if (runState == TERMINATED)
+ return true;
+ if (nanos <= 0)
+ return false;
+ nanos = termination.awaitNanos(nanos);
+ }
+ } finally {
+ mainLock.unlock();
+ }
+ }
+
+ /**
+ * Invokes <tt>shutdown</tt> when this executor is no longer
+ * referenced.
+ */
+ protected void finalize() {
+ shutdown();
+ }
+
+ /**
+ * Sets the thread factory used to create new threads.
+ *
+ * @param threadFactory the new thread factory
+ * @throws NullPointerException if threadFactory is null
+ * @see #getThreadFactory
+ */
+ public void setThreadFactory(ThreadFactory threadFactory) {
+ if (threadFactory == null)
+ throw new NullPointerException();
+ this.threadFactory = threadFactory;
+ }
+
+ /**
+ * Returns the thread factory used to create new threads.
+ *
+ * @return the current thread factory
+ * @see #setThreadFactory
+ */
+ public ThreadFactory getThreadFactory() {
+ return threadFactory;
+ }
+
+ /**
+ * Sets a new handler for unexecutable tasks.
+ *
+ * @param handler the new handler
+ * @throws NullPointerException if handler is null
+ * @see #getRejectedExecutionHandler
+ */
+ public void setRejectedExecutionHandler(RejectedExecutionHandler handler) {
+ if (handler == null)
+ throw new NullPointerException();
+ this.handler = handler;
+ }
+
+ /**
+ * Returns the current handler for unexecutable tasks.
+ *
+ * @return the current handler
+ * @see #setRejectedExecutionHandler
+ */
+ public RejectedExecutionHandler getRejectedExecutionHandler() {
+ return handler;
+ }
+
+ /**
+ * Returns the task queue used by this executor. Access to the
+ * task queue is intended primarily for debugging and monitoring.
+ * This queue may be in active use. Retrieving the task queue
+ * does not prevent queued tasks from executing.
+ *
+ * @return the task queue
+ */
+ public BlockingQueue<Runnable> getQueue() {
+ return workQueue;
+ }
+
+ /**
+ * Removes this task from the executor's internal queue if it is
+ * present, thus causing it not to be run if it has not already
+ * started.
+ *
+ * <p> This method may be useful as one part of a cancellation
+ * scheme. It may fail to remove tasks that have been converted
+ * into other forms before being placed on the internal queue. For
+ * example, a task entered using <tt>submit</tt> might be
+ * converted into a form that maintains <tt>Future</tt> status.
+ * However, in such cases, method {@link ThreadPoolExecutor#purge}
+ * may be used to remove those Futures that have been cancelled.
+ *
+ * @param task the task to remove
+ * @return true if the task was removed
+ */
+ public boolean remove(Runnable task) {
+ return getQueue().remove(task);
+ }
+
+
+ /**
+ * Tries to remove from the work queue all {@link Future}
+ * tasks that have been cancelled. This method can be useful as a
+ * storage reclamation operation, that has no other impact on
+ * functionality. Cancelled tasks are never executed, but may
+ * accumulate in work queues until worker threads can actively
+ * remove them. Invoking this method instead tries to remove them now.
+ * However, this method may fail to remove tasks in
+ * the presence of interference by other threads.
+ */
+ public void purge() {
+ // Fail if we encounter interference during traversal
+ try {
+ Iterator<Runnable> it = getQueue().iterator();
+ while (it.hasNext()) {
+ Runnable r = it.next();
+ if (r instanceof Future<?>) {
+ Future<?> c = (Future<?>)r;
+ if (c.isCancelled())
+ it.remove();
+ }
+ }
+ }
+ catch (ConcurrentModificationException ex) {
+ return;
+ }
+ }
+
+ /**
+ * Sets the core 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 terminated when
+ * they next become idle. If larger, new threads will, if needed,
+ * be started to execute any queued tasks.
+ *
+ * @param corePoolSize the new core size
+ * @throws IllegalArgumentException if <tt>corePoolSize</tt>
+ * less than zero
+ * @see #getCorePoolSize
+ */
+ public void setCorePoolSize(int corePoolSize) {
+ if (corePoolSize < 0)
+ throw new IllegalArgumentException();
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ int extra = this.corePoolSize - corePoolSize;
+ this.corePoolSize = corePoolSize;
+ if (extra < 0) {
+ int n = workQueue.size();
+ // We have to create initially-idle threads here
+ // because we otherwise have no recourse about
+ // what to do with a dequeued task if addThread fails.
+ while (extra++ < 0 && n-- > 0 && poolSize < corePoolSize ) {
+ Thread t = addThread(null);
+ if (t != null)
+ t.start();
+ else
+ break;
+ }
+ }
+ else if (extra > 0 && poolSize > corePoolSize) {
+ Iterator<Worker> it = workers.iterator();
+ while (it.hasNext() &&
+ extra-- > 0 &&
+ poolSize > corePoolSize &&
+ workQueue.remainingCapacity() == 0)
+ it.next().interruptIfIdle();
+ }
+ } finally {
+ mainLock.unlock();
+ }
+ }
+
+ /**
+ * Returns the core number of threads.
+ *
+ * @return the core number of threads
+ * @see #setCorePoolSize
+ */
+ public int getCorePoolSize() {
+ return corePoolSize;
+ }
+
+ /**
+ * Starts a core thread, causing it to idly wait for work. This
+ * overrides the default policy of starting core threads only when
+ * new tasks are executed. This method will return <tt>false</tt>
+ * if all core threads have already been started.
+ * @return true if a thread was started
+ */
+ public boolean prestartCoreThread() {
+ return addIfUnderCorePoolSize(null);
+ }
+
+ /**
+ * Starts all core threads, causing them to idly wait for work. This
+ * overrides the default policy of starting core threads only when
+ * new tasks are executed.
+ * @return the number of threads started.
+ */
+ public int prestartAllCoreThreads() {
+ int n = 0;
+ while (addIfUnderCorePoolSize(null))
+ ++n;
+ return n;
+ }
+
+ /**
+ * 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 <tt>true</tt> if core threads are allowed to time out,
+ * else <tt>false</tt>
+ *
+ * @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 <tt>true</tt>. This method
+ * should in general be called before the pool is actively used.
+ * @param value <tt>true</tt> if should time out, else <tt>false</tt>
+ * @throws IllegalArgumentException if value is <tt>true</tt>
+ * 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");
+
+ allowCoreThreadTimeOut = value;
+ }
+
+ /**
+ * 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
+ * terminated when they next become idle.
+ *
+ * @param maximumPoolSize the new maximum
+ * @throws IllegalArgumentException if the new maximum is
+ * less than or equal to zero, or
+ * less than the {@linkplain #getCorePoolSize core pool size}
+ * @see #getMaximumPoolSize
+ */
+ public void setMaximumPoolSize(int maximumPoolSize) {
+ if (maximumPoolSize <= 0 || maximumPoolSize < corePoolSize)
+ throw new IllegalArgumentException();
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ int extra = this.maximumPoolSize - maximumPoolSize;
+ this.maximumPoolSize = maximumPoolSize;
+ if (extra > 0 && poolSize > maximumPoolSize) {
+ Iterator<Worker> it = workers.iterator();
+ while (it.hasNext() &&
+ extra > 0 &&
+ poolSize > maximumPoolSize) {
+ it.next().interruptIfIdle();
+ --extra;
+ }
+ }
+ } finally {
+ mainLock.unlock();
+ }
+ }
+
+ /**
+ * Returns the maximum allowed number of threads.
+ *
+ * @return the maximum allowed number of threads
+ * @see #setMaximumPoolSize
+ */
+ public int getMaximumPoolSize() {
+ return maximumPoolSize;
+ }
+
+ /**
+ * Sets the time limit for which threads may remain idle before
+ * being terminated. If there are more than the core number of
+ * threads currently in the pool, after waiting this amount of
+ * time without processing a task, excess threads will be
+ * terminated. This overrides any value set in the constructor.
+ * @param time the time to wait. A time value of zero will cause
+ * excess threads to terminate immediately after executing tasks.
+ * @param unit the time unit of the time argument
+ * @throws IllegalArgumentException if time less than zero or
+ * if time is zero and allowsCoreThreadTimeOut
+ * @see #getKeepAliveTime
+ */
+ 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");
+ this.keepAliveTime = unit.toNanos(time);
+ }
+
+ /**
+ * Returns the thread keep-alive time, which is the amount of time
+ * which threads in excess of the core pool size may remain
+ * idle before being terminated.
+ *
+ * @param unit the desired time unit of the result
+ * @return the time limit
+ * @see #setKeepAliveTime
+ */
+ public long getKeepAliveTime(TimeUnit unit) {
+ return unit.convert(keepAliveTime, TimeUnit.NANOSECONDS);
+ }
+
+ /* Statistics */
+
+ /**
+ * Returns the current number of threads in the pool.
+ *
+ * @return the number of threads
+ */
+ public int getPoolSize() {
+ return poolSize;
+ }
+
+ /**
+ * Returns the approximate number of threads that are actively
+ * executing tasks.
+ *
+ * @return the number of threads
+ */
+ public int getActiveCount() {
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ int n = 0;
+ for (Worker w : workers) {
+ if (w.isActive())
+ ++n;
+ }
+ return n;
+ } finally {
+ mainLock.unlock();
+ }
+ }
+
+ /**
+ * Returns the largest number of threads that have ever
+ * simultaneously been in the pool.
+ *
+ * @return the number of threads
+ */
+ public int getLargestPoolSize() {
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ return largestPoolSize;
+ } finally {
+ mainLock.unlock();
+ }
+ }
+
+ /**
+ * Returns the approximate total number of tasks that have been
+ * scheduled for execution. Because the states of tasks and
+ * threads may change dynamically during computation, the returned
+ * value is only an approximation, but one that does not ever
+ * decrease across successive calls.
+ *
+ * @return the number of tasks
+ */
+ public long getTaskCount() {
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ long n = completedTaskCount;
+ for (Worker w : workers) {
+ n += w.completedTasks;
+ if (w.isActive())
+ ++n;
+ }
+ return n + workQueue.size();
+ } finally {
+ mainLock.unlock();
+ }
+ }
+
+ /**
+ * Returns the approximate total number of tasks that have
+ * completed execution. Because the states of tasks and threads
+ * may change dynamically during computation, the returned value
+ * is only an approximation, but one that does not ever decrease
+ * across successive calls.
+ *
+ * @return the number of tasks
+ */
+ public long getCompletedTaskCount() {
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ long n = completedTaskCount;
+ for (Worker w : workers)
+ n += w.completedTasks;
+ return n;
+ } finally {
+ mainLock.unlock();
+ }
+ }
+
+ /**
+ * Method invoked prior to executing the given Runnable in the
+ * given thread. This method is invoked by thread <tt>t</tt> that
+ * will execute task <tt>r</tt>, and may be used to re-initialize
+ * ThreadLocals, or to perform logging.
+ *
+ * <p>This implementation does nothing, but may be customized in
+ * subclasses. Note: To properly nest multiple overridings, subclasses
+ * should generally invoke <tt>super.beforeExecute</tt> at the end of
+ * this method.
+ *
+ * @param t the thread that will run task r.
+ * @param r the task that will be executed.
+ */
+ protected void beforeExecute(Thread t, Runnable r) { }
+
+ /**
+ * Method invoked upon completion of execution of the given Runnable.
+ * This method is invoked by the thread that executed the task. If
+ * non-null, the Throwable is the uncaught <tt>RuntimeException</tt>
+ * or <tt>Error</tt> that caused execution to terminate abruptly.
+ *
+ * <p><b>Note:</b> When actions are enclosed in tasks (such as
+ * {@link FutureTask}) either explicitly or via methods such as
+ * <tt>submit</tt>, these task objects catch and maintain
+ * computational exceptions, and so they do not cause abrupt
+ * termination, and the internal exceptions are <em>not</em>
+ * passed to this method.
+ *
+ * <p>This implementation does nothing, but may be customized in
+ * subclasses. Note: To properly nest multiple overridings, subclasses
+ * should generally invoke <tt>super.afterExecute</tt> at the
+ * beginning of this method.
+ *
+ * @param r the runnable that has completed.
+ * @param t the exception that caused termination, or null if
+ * execution completed normally.
+ */
+ protected void afterExecute(Runnable r, Throwable t) { }
+
+ /**
+ * Method invoked when the Executor has terminated. Default
+ * implementation does nothing. Note: To properly nest multiple
+ * overridings, subclasses should generally invoke
+ * <tt>super.terminated</tt> within this method.
+ */
+ protected void terminated() { }
+
+ /**
+ * A handler for rejected tasks that runs the rejected task
+ * directly in the calling thread of the <tt>execute</tt> method,
+ * unless the executor has been shut down, in which case the task
+ * is discarded.
+ */
+ public static class CallerRunsPolicy implements RejectedExecutionHandler {
+ /**
+ * Creates a <tt>CallerRunsPolicy</tt>.
+ */
+ public CallerRunsPolicy() { }
+
+ /**
+ * Executes task r in the caller's thread, unless the executor
+ * has been shut down, in which case the task is discarded.
+ * @param r the runnable task requested to be executed
+ * @param e the executor attempting to execute this task
+ */
+ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
+ if (!e.isShutdown()) {
+ r.run();
+ }
+ }
+ }
+
+ /**
+ * A handler for rejected tasks that throws a
+ * <tt>RejectedExecutionException</tt>.
+ */
+ public static class AbortPolicy implements RejectedExecutionHandler {
+ /**
+ * Creates an <tt>AbortPolicy</tt>.
+ */
+ public AbortPolicy() { }
+
+ /**
+ * Always throws RejectedExecutionException.
+ * @param r the runnable task requested to be executed
+ * @param e the executor attempting to execute this task
+ * @throws RejectedExecutionException always.
+ */
+ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
+ throw new RejectedExecutionException();
+ }
+ }
+
+ /**
+ * A handler for rejected tasks that silently discards the
+ * rejected task.
+ */
+ public static class DiscardPolicy implements RejectedExecutionHandler {
+ /**
+ * Creates a <tt>DiscardPolicy</tt>.
+ */
+ public DiscardPolicy() { }
+
+ /**
+ * Does nothing, which has the effect of discarding task r.
+ * @param r the runnable task requested to be executed
+ * @param e the executor attempting to execute this task
+ */
+ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
+ }
+ }
+
+ /**
+ * A handler for rejected tasks that discards the oldest unhandled
+ * request and then retries <tt>execute</tt>, unless the executor
+ * is shut down, in which case the task is discarded.
+ */
+ public static class DiscardOldestPolicy implements RejectedExecutionHandler {
+ /**
+ * Creates a <tt>DiscardOldestPolicy</tt> for the given executor.
+ */
+ public DiscardOldestPolicy() { }
+
+ /**
+ * Obtains and ignores the next task that the executor
+ * would otherwise execute, if one is immediately available,
+ * and then retries execution of task r, unless the executor
+ * is shut down, in which case task r is instead discarded.
+ * @param r the runnable task requested to be executed
+ * @param e the executor attempting to execute this task
+ */
+ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
+ if (!e.isShutdown()) {
+ e.getQueue().poll();
+ e.execute(r);
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/TimeUnit.java b/libjava/classpath/external/jsr166/java/util/concurrent/TimeUnit.java
new file mode 100644
index 000000000..2cd3d06ab
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/TimeUnit.java
@@ -0,0 +1,331 @@
+/*
+ * 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 <tt>TimeUnit</tt> represents time durations at a given unit of
+ * granularity and provides utility methods to convert across units,
+ * and to perform timing and delay operations in these units. A
+ * <tt>TimeUnit</tt> does not maintain time information, but only
+ * helps organize and use time representations that may be maintained
+ * separately across various contexts. A nanosecond is defined as one
+ * thousandth of a microsecond, a microsecond as one thousandth of a
+ * millisecond, a millisecond as one thousandth of a second, a minute
+ * as sixty seconds, an hour as sixty minutes, and a day as twenty four
+ * hours.
+ *
+ * <p>A <tt>TimeUnit</tt> is mainly used to inform time-based methods
+ * how a given timing parameter should be interpreted. For example,
+ * the following code will timeout in 50 milliseconds if the {@link
+ * java.util.concurrent.locks.Lock lock} is not available:
+ *
+ * <pre> Lock lock = ...;
+ * if ( lock.tryLock(50L, TimeUnit.MILLISECONDS) ) ...
+ * </pre>
+ * while this code will timeout in 50 seconds:
+ * <pre>
+ * Lock lock = ...;
+ * if ( lock.tryLock(50L, TimeUnit.SECONDS) ) ...
+ * </pre>
+ *
+ * Note however, that there is no guarantee that a particular timeout
+ * implementation will be able to notice the passage of time at the
+ * same granularity as the given <tt>TimeUnit</tt>.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public enum TimeUnit {
+ NANOSECONDS {
+ public long toNanos(long d) { return d; }
+ public long toMicros(long d) { return d/(C1/C0); }
+ public long toMillis(long d) { return d/(C2/C0); }
+ public long toSeconds(long d) { return d/(C3/C0); }
+ public long toMinutes(long d) { return d/(C4/C0); }
+ public long toHours(long d) { return d/(C5/C0); }
+ public long toDays(long d) { return d/(C6/C0); }
+ public long convert(long d, TimeUnit u) { return u.toNanos(d); }
+ int excessNanos(long d, long m) { return (int)(d - (m*C2)); }
+ },
+ MICROSECONDS {
+ public long toNanos(long d) { return x(d, C1/C0, MAX/(C1/C0)); }
+ public long toMicros(long d) { return d; }
+ public long toMillis(long d) { return d/(C2/C1); }
+ public long toSeconds(long d) { return d/(C3/C1); }
+ public long toMinutes(long d) { return d/(C4/C1); }
+ public long toHours(long d) { return d/(C5/C1); }
+ public long toDays(long d) { return d/(C6/C1); }
+ public long convert(long d, TimeUnit u) { return u.toMicros(d); }
+ int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); }
+ },
+ 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)); }
+ public long toMillis(long d) { return d; }
+ public long toSeconds(long d) { return d/(C3/C2); }
+ public long toMinutes(long d) { return d/(C4/C2); }
+ public long toHours(long d) { return d/(C5/C2); }
+ public long toDays(long d) { return d/(C6/C2); }
+ public long convert(long d, TimeUnit u) { return u.toMillis(d); }
+ int excessNanos(long d, long m) { return 0; }
+ },
+ 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)); }
+ public long toMillis(long d) { return x(d, C3/C2, MAX/(C3/C2)); }
+ public long toSeconds(long d) { return d; }
+ public long toMinutes(long d) { return d/(C4/C3); }
+ public long toHours(long d) { return d/(C5/C3); }
+ public long toDays(long d) { return d/(C6/C3); }
+ public long convert(long d, TimeUnit u) { return u.toSeconds(d); }
+ int excessNanos(long d, long m) { return 0; }
+ },
+ 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
+ static final long C0 = 1L;
+ static final long C1 = C0 * 1000L;
+ static final long C2 = C1 * 1000L;
+ static final long C3 = C2 * 1000L;
+ static final long C4 = C3 * 60L;
+ static final long C5 = C4 * 60L;
+ static final long C6 = C5 * 24L;
+
+ static final long MAX = Long.MAX_VALUE;
+
+ /**
+ * Scale d by m, checking for overflow.
+ * This has a short name to make above code more readable.
+ */
+ static long x(long d, long m, long over) {
+ if (d > over) return Long.MAX_VALUE;
+ if (d < -over) return Long.MIN_VALUE;
+ return d * m;
+ }
+
+ // To maintain full signature compatibility with 1.5, and to improve the
+ // clarity of the generated javadoc (see 6287639: Abstract methods in
+ // enum classes should not be listed as abstract), method convert
+ // etc. are not declared abstract but otherwise act as abstract methods.
+
+ /**
+ * Convert the given time duration in the given unit to this
+ * unit. Conversions from finer to coarser granularities
+ * truncate, so lose precision. For example converting
+ * <tt>999</tt> milliseconds to seconds results in
+ * <tt>0</tt>. Conversions from coarser to finer granularities
+ * with arguments that would numerically overflow saturate to
+ * <tt>Long.MIN_VALUE</tt> if negative or <tt>Long.MAX_VALUE</tt>
+ * if positive.
+ *
+ * <p>For example, to convert 10 minutes to milliseconds, use:
+ * <tt>TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)</tt>
+ *
+ * @param sourceDuration the time duration in the given <tt>sourceUnit</tt>
+ * @param sourceUnit the unit of the <tt>sourceDuration</tt> argument
+ * @return the converted duration in this unit,
+ * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
+ * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+ */
+ public long convert(long sourceDuration, TimeUnit sourceUnit) {
+ throw new AbstractMethodError();
+ }
+
+ /**
+ * Equivalent to <tt>NANOSECONDS.convert(duration, this)</tt>.
+ * @param duration the duration
+ * @return the converted duration,
+ * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
+ * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+ * @see #convert
+ */
+ public long toNanos(long duration) {
+ throw new AbstractMethodError();
+ }
+
+ /**
+ * Equivalent to <tt>MICROSECONDS.convert(duration, this)</tt>.
+ * @param duration the duration
+ * @return the converted duration,
+ * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
+ * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+ * @see #convert
+ */
+ public long toMicros(long duration) {
+ throw new AbstractMethodError();
+ }
+
+ /**
+ * Equivalent to <tt>MILLISECONDS.convert(duration, this)</tt>.
+ * @param duration the duration
+ * @return the converted duration,
+ * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
+ * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+ * @see #convert
+ */
+ public long toMillis(long duration) {
+ throw new AbstractMethodError();
+ }
+
+ /**
+ * Equivalent to <tt>SECONDS.convert(duration, this)</tt>.
+ * @param duration the duration
+ * @return the converted duration,
+ * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
+ * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+ * @see #convert
+ */
+ public long toSeconds(long duration) {
+ throw new AbstractMethodError();
+ }
+
+ /**
+ * Equivalent to <tt>MINUTES.convert(duration, this)</tt>.
+ * @param duration the duration
+ * @return the converted duration,
+ * 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
+ */
+ public long toMinutes(long duration) {
+ throw new AbstractMethodError();
+ }
+
+ /**
+ * Equivalent to <tt>HOURS.convert(duration, this)</tt>.
+ * @param duration the duration
+ * @return the converted duration,
+ * 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
+ */
+ public long toHours(long duration) {
+ throw new AbstractMethodError();
+ }
+
+ /**
+ * Equivalent to <tt>DAYS.convert(duration, this)</tt>.
+ * @param duration the duration
+ * @return the converted duration
+ * @see #convert
+ * @since 1.6
+ */
+ public long toDays(long duration) {
+ throw new AbstractMethodError();
+ }
+
+ /**
+ * Utility to compute the excess-nanosecond argument to wait,
+ * sleep, join.
+ * @param d the duration
+ * @param m the number of milliseconds
+ * @return the number of nanoseconds
+ */
+ abstract int excessNanos(long d, long m);
+
+ /**
+ * Performs a timed <tt>Object.wait</tt> using this time unit.
+ * This is a convenience method that converts timeout arguments
+ * into the form required by the <tt>Object.wait</tt> method.
+ *
+ * <p>For example, you could implement a blocking <tt>poll</tt>
+ * method (see {@link BlockingQueue#poll BlockingQueue.poll})
+ * using:
+ *
+ * <pre> public synchronized Object poll(long timeout, TimeUnit unit) throws InterruptedException {
+ * while (empty) {
+ * unit.timedWait(this, timeout);
+ * ...
+ * }
+ * }</pre>
+ *
+ * @param obj the object to wait on
+ * @param timeout the maximum time to wait. If less than
+ * or equal to zero, do not wait at all.
+ * @throws InterruptedException if interrupted while waiting.
+ * @see Object#wait(long, int)
+ */
+ public void timedWait(Object obj, long timeout)
+ throws InterruptedException {
+ if (timeout > 0) {
+ long ms = toMillis(timeout);
+ int ns = excessNanos(timeout, ms);
+ obj.wait(ms, ns);
+ }
+ }
+
+ /**
+ * Performs a timed <tt>Thread.join</tt> using this time unit.
+ * This is a convenience method that converts time arguments into the
+ * form required by the <tt>Thread.join</tt> method.
+ * @param thread the thread to wait for
+ * @param timeout the maximum time to wait. If less than
+ * or equal to zero, do not wait at all.
+ * @throws InterruptedException if interrupted while waiting.
+ * @see Thread#join(long, int)
+ */
+ public void timedJoin(Thread thread, long timeout)
+ throws InterruptedException {
+ if (timeout > 0) {
+ long ms = toMillis(timeout);
+ int ns = excessNanos(timeout, ms);
+ thread.join(ms, ns);
+ }
+ }
+
+ /**
+ * Performs a <tt>Thread.sleep</tt> using this unit.
+ * This is a convenience method that converts time arguments into the
+ * form required by the <tt>Thread.sleep</tt> method.
+ * @param timeout the minimum time to sleep. If less than
+ * or equal to zero, do not sleep at all.
+ * @throws InterruptedException if interrupted while sleeping.
+ * @see Thread#sleep
+ */
+ public void sleep(long timeout) throws InterruptedException {
+ if (timeout > 0) {
+ long ms = toMillis(timeout);
+ int ns = excessNanos(timeout, ms);
+ Thread.sleep(ms, ns);
+ }
+ }
+
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/TimeoutException.java b/libjava/classpath/external/jsr166/java/util/concurrent/TimeoutException.java
new file mode 100644
index 000000000..8b84f28e5
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/TimeoutException.java
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+/**
+ * Exception thrown when a blocking operation times out. Blocking
+ * operations for which a timeout is specified need a means to
+ * indicate that the timeout has occurred. For many such operations it
+ * is possible to return a value that indicates timeout; when that is
+ * not possible or desirable then <tt>TimeoutException</tt> should be
+ * declared and thrown.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class TimeoutException extends Exception {
+ private static final long serialVersionUID = 1900926677490660714L;
+
+ /**
+ * Constructs a <tt>TimeoutException</tt> with no specified detail
+ * message.
+ */
+ public TimeoutException() {}
+
+ /**
+ * Constructs a <tt>TimeoutException</tt> with the specified detail
+ * message.
+ *
+ * @param message the detail message
+ */
+ public TimeoutException(String message) {
+ super(message);
+ }
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicBoolean.java b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicBoolean.java
new file mode 100644
index 000000000..bd823bd2c
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicBoolean.java
@@ -0,0 +1,133 @@
+/*
+ * 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.atomic;
+import sun.misc.Unsafe;
+
+/**
+ * A <tt>boolean</tt> value that may be updated atomically. See the
+ * {@link java.util.concurrent.atomic} package specification for
+ * description of the properties of atomic variables. An
+ * <tt>AtomicBoolean</tt> is used in applications such as atomically
+ * updated flags, and cannot be used as a replacement for a
+ * {@link java.lang.Boolean}.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class AtomicBoolean implements java.io.Serializable {
+ private static final long serialVersionUID = 4654671469794556979L;
+ // setup to use Unsafe.compareAndSwapInt for updates
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private static final long valueOffset;
+
+ static {
+ try {
+ valueOffset = unsafe.objectFieldOffset
+ (AtomicBoolean.class.getDeclaredField("value"));
+ } catch (Exception ex) { throw new Error(ex); }
+ }
+
+ private volatile int value;
+
+ /**
+ * Creates a new <tt>AtomicBoolean</tt> with the given initial value.
+ *
+ * @param initialValue the initial value
+ */
+ public AtomicBoolean(boolean initialValue) {
+ value = initialValue ? 1 : 0;
+ }
+
+ /**
+ * Creates a new <tt>AtomicBoolean</tt> with initial value <tt>false</tt>.
+ */
+ public AtomicBoolean() {
+ }
+
+ /**
+ * Returns the current value.
+ *
+ * @return the current value
+ */
+ public final boolean get() {
+ return value != 0;
+ }
+
+ /**
+ * Atomically sets the value to the given updated value
+ * if the current value <tt>==</tt> the expected value.
+ *
+ * @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.
+ */
+ public final boolean compareAndSet(boolean expect, boolean update) {
+ int e = expect ? 1 : 0;
+ int u = update ? 1 : 0;
+ return unsafe.compareAndSwapInt(this, valueOffset, e, u);
+ }
+
+ /**
+ * Atomically sets the value to the given updated value
+ * if the current value <tt>==</tt> the expected value.
+ * May fail spuriously and does not provide ordering guarantees,
+ * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
+ *
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful.
+ */
+ public boolean weakCompareAndSet(boolean expect, boolean update) {
+ int e = expect ? 1 : 0;
+ int u = update ? 1 : 0;
+ return unsafe.compareAndSwapInt(this, valueOffset, e, u);
+ }
+
+ /**
+ * Unconditionally sets to the given value.
+ *
+ * @param newValue the new value
+ */
+ public final void set(boolean newValue) {
+ value = newValue ? 1 : 0;
+ }
+
+ /**
+ * 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
+ * @return the previous value
+ */
+ public final boolean getAndSet(boolean newValue) {
+ for (;;) {
+ boolean current = get();
+ if (compareAndSet(current, newValue))
+ return current;
+ }
+ }
+
+ /**
+ * Returns the String representation of the current value.
+ * @return the String representation of the current value.
+ */
+ public String toString() {
+ return Boolean.toString(get());
+ }
+
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicInteger.java b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicInteger.java
new file mode 100644
index 000000000..0f723f613
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicInteger.java
@@ -0,0 +1,234 @@
+/*
+ * 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.atomic;
+import sun.misc.Unsafe;
+
+/**
+ * An <tt>int</tt> value that may be updated atomically. See the
+ * {@link java.util.concurrent.atomic} package specification for
+ * description of the properties of atomic variables. An
+ * <tt>AtomicInteger</tt> is used in applications such as atomically
+ * incremented counters, and cannot be used as a replacement for an
+ * {@link java.lang.Integer}. However, this class does extend
+ * <tt>Number</tt> to allow uniform access by tools and utilities that
+ * deal with numerically-based classes.
+ *
+ * @since 1.5
+ * @author Doug Lea
+*/
+public class AtomicInteger extends Number implements java.io.Serializable {
+ private static final long serialVersionUID = 6214790243416807050L;
+
+ // setup to use Unsafe.compareAndSwapInt for updates
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private static final long valueOffset;
+
+ static {
+ try {
+ valueOffset = unsafe.objectFieldOffset
+ (AtomicInteger.class.getDeclaredField("value"));
+ } catch (Exception ex) { throw new Error(ex); }
+ }
+
+ private volatile int value;
+
+ /**
+ * Creates a new AtomicInteger with the given initial value.
+ *
+ * @param initialValue the initial value
+ */
+ public AtomicInteger(int initialValue) {
+ value = initialValue;
+ }
+
+ /**
+ * Creates a new AtomicInteger with initial value <tt>0</tt>.
+ */
+ public AtomicInteger() {
+ }
+
+ /**
+ * Gets the current value.
+ *
+ * @return the current value
+ */
+ public final int get() {
+ return value;
+ }
+
+ /**
+ * Sets to the given value.
+ *
+ * @param newValue the new value
+ */
+ public final void set(int newValue) {
+ value = newValue;
+ }
+
+ /**
+ * 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
+ * @return the previous value
+ */
+ public final int getAndSet(int newValue) {
+ for (;;) {
+ int current = get();
+ if (compareAndSet(current, newValue))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically sets the value to the given updated value
+ * if the current value <tt>==</tt> the expected value.
+ *
+ * @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.
+ */
+ public final boolean compareAndSet(int expect, int update) {
+ return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
+ }
+
+ /**
+ * Atomically sets the value to the given updated value
+ * if the current value <tt>==</tt> the expected value.
+ * May fail spuriously and does not provide ordering guarantees,
+ * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
+ *
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful.
+ */
+ public final boolean weakCompareAndSet(int expect, int update) {
+ return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
+ }
+
+ /**
+ * Atomically increments by one the current value.
+ *
+ * @return the previous value
+ */
+ public final int getAndIncrement() {
+ for (;;) {
+ int current = get();
+ int next = current + 1;
+ if (compareAndSet(current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically decrements by one the current value.
+ *
+ * @return the previous value
+ */
+ public final int getAndDecrement() {
+ for (;;) {
+ int current = get();
+ int next = current - 1;
+ if (compareAndSet(current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically adds the given value to the current value.
+ *
+ * @param delta the value to add
+ * @return the previous value
+ */
+ public final int getAndAdd(int delta) {
+ for (;;) {
+ int current = get();
+ int next = current + delta;
+ if (compareAndSet(current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically increments by one the current value.
+ *
+ * @return the updated value
+ */
+ public final int incrementAndGet() {
+ for (;;) {
+ int current = get();
+ int next = current + 1;
+ if (compareAndSet(current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Atomically decrements by one the current value.
+ *
+ * @return the updated value
+ */
+ public final int decrementAndGet() {
+ for (;;) {
+ int current = get();
+ int next = current - 1;
+ if (compareAndSet(current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Atomically adds the given value to the current value.
+ *
+ * @param delta the value to add
+ * @return the updated value
+ */
+ public final int addAndGet(int delta) {
+ for (;;) {
+ int current = get();
+ int next = current + delta;
+ if (compareAndSet(current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Returns the String representation of the current value.
+ * @return the String representation of the current value.
+ */
+ public String toString() {
+ return Integer.toString(get());
+ }
+
+
+ public int intValue() {
+ return get();
+ }
+
+ public long longValue() {
+ return (long)get();
+ }
+
+ public float floatValue() {
+ return (float)get();
+ }
+
+ public double doubleValue() {
+ return (double)get();
+ }
+
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicIntegerArray.java b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicIntegerArray.java
new file mode 100644
index 000000000..2ad754fda
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicIntegerArray.java
@@ -0,0 +1,255 @@
+/*
+ * 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.atomic;
+import sun.misc.Unsafe;
+import java.util.*;
+
+/**
+ * An <tt>int</tt> array in which elements may be updated atomically.
+ * See the {@link java.util.concurrent.atomic} package
+ * specification for description of the properties of atomic
+ * variables.
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class AtomicIntegerArray implements java.io.Serializable {
+ private static final long serialVersionUID = 2862133569453604235L;
+
+ // setup to use Unsafe.compareAndSwapInt for updates
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ 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) {
+ if (i < 0 || i >= array.length)
+ throw new IndexOutOfBoundsException("index " + i);
+ return base + i * scale;
+ }
+
+ /**
+ * Creates a new AtomicIntegerArray of given length.
+ *
+ * @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);
+ }
+
+ /**
+ * Creates a new AtomicIntegerArray with the same length as, and
+ * all elements copied from, the given array.
+ *
+ * @param array the array to copy elements from
+ * @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]);
+ }
+ }
+
+ /**
+ * Returns the length of the array.
+ *
+ * @return the length of the array
+ */
+ public final int length() {
+ return array.length;
+ }
+
+ /**
+ * Gets the current value at position <tt>i</tt>.
+ *
+ * @param i the index
+ * @return the current value
+ */
+ public final int get(int i) {
+ return unsafe.getIntVolatile(array, rawIndex(i));
+ }
+
+ /**
+ * Sets the element at position <tt>i</tt> to the given value.
+ *
+ * @param i the index
+ * @param newValue the new value
+ */
+ public final void set(int i, int newValue) {
+ unsafe.putIntVolatile(array, rawIndex(i), newValue);
+ }
+
+ /**
+ * Eventually sets the element at position <tt>i</tt> 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, rawIndex(i), newValue);
+ }
+
+ /**
+ * Atomically sets the element at position <tt>i</tt> to the given
+ * value and returns the old value.
+ *
+ * @param i the index
+ * @param newValue the new value
+ * @return the previous value
+ */
+ public final int getAndSet(int i, int newValue) {
+ while (true) {
+ int current = get(i);
+ if (compareAndSet(i, current, newValue))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically sets the element at position <tt>i</tt> to the given
+ * updated value if the current value <tt>==</tt> the expected value.
+ *
+ * @param i the index
+ * @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.
+ */
+ public final boolean compareAndSet(int i, int expect, int update) {
+ return unsafe.compareAndSwapInt(array, rawIndex(i),
+ expect, update);
+ }
+
+ /**
+ * Atomically sets the element at position <tt>i</tt> to the given
+ * updated value if the current value <tt>==</tt> the expected value.
+ * May fail spuriously and does not provide ordering guarantees,
+ * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
+ *
+ * @param i the index
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful.
+ */
+ public final boolean weakCompareAndSet(int i, int expect, int update) {
+ return compareAndSet(i, expect, update);
+ }
+
+ /**
+ * Atomically increments by one the element at index <tt>i</tt>.
+ *
+ * @param i the index
+ * @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;
+ }
+ }
+
+ /**
+ * Atomically decrements by one the element at index <tt>i</tt>.
+ *
+ * @param i the index
+ * @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;
+ }
+ }
+
+ /**
+ * Atomically adds the given value to the element at index <tt>i</tt>.
+ *
+ * @param i the index
+ * @param delta the value to add
+ * @return the previous value
+ */
+ public final int getAndAdd(int i, int delta) {
+ while (true) {
+ int current = get(i);
+ int next = current + delta;
+ if (compareAndSet(i, current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically increments by one the element at index <tt>i</tt>.
+ *
+ * @param i the index
+ * @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;
+ }
+ }
+
+ /**
+ * Atomically decrements by one the element at index <tt>i</tt>.
+ *
+ * @param i the index
+ * @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;
+ }
+ }
+
+ /**
+ * Atomically adds the given value to the element at index <tt>i</tt>.
+ *
+ * @param i the index
+ * @param delta the value to add
+ * @return the updated value
+ */
+ public final int addAndGet(int i, int delta) {
+ while (true) {
+ int current = get(i);
+ int next = current + delta;
+ if (compareAndSet(i, current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Returns 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);
+ }
+
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
new file mode 100644
index 000000000..c957bbf3f
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
@@ -0,0 +1,316 @@
+/*
+ * 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.atomic;
+import sun.misc.Unsafe;
+import java.lang.reflect.*;
+
+/**
+ * A reflection-based utility that enables atomic updates to
+ * designated <tt>volatile int</tt> fields of designated classes.
+ * This class is designed for use in atomic data structures in which
+ * several fields of the same node are independently subject to atomic
+ * updates.
+ *
+ * <p>Note that the guarantees of the {@code compareAndSet}
+ * method in this class are weaker than in other atomic classes.
+ * Because this class cannot ensure that all uses of the field
+ * are appropriate for purposes of atomic access, it can
+ * guarantee atomicity only with respect to other invocations of
+ * {@code compareAndSet} and {@code set} on the same updater.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <T> The type of the object holding the updatable field
+ */
+public abstract class AtomicIntegerFieldUpdater<T> {
+ /**
+ * Creates and returns an updater for objects with the given field.
+ * The Class argument is needed to check that reflective types and
+ * generic types match.
+ *
+ * @param tclass the class of the objects holding the field
+ * @param fieldName the name of the field to be updated
+ * @return the updater
+ * @throws IllegalArgumentException if the field is not a
+ * volatile integer type
+ * @throws RuntimeException with a nested reflection-based
+ * exception if the class does not hold field or is the wrong type
+ */
+ public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
+ return new AtomicIntegerFieldUpdaterImpl<U>(tclass, fieldName);
+ }
+
+ /**
+ * Protected do-nothing constructor for use by subclasses.
+ */
+ protected AtomicIntegerFieldUpdater() {
+ }
+
+ /**
+ * Atomically sets the field of the given object managed by this updater
+ * to the given updated value if the current value <tt>==</tt> the
+ * expected value. This method is guaranteed to be atomic with respect to
+ * other calls to <tt>compareAndSet</tt> and <tt>set</tt>, but not
+ * necessarily with respect to other changes in the field.
+ *
+ * @param obj An object whose field to conditionally set
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful
+ * @throws ClassCastException if <tt>obj</tt> is not an instance
+ * of the class possessing the field established in the constructor
+ */
+ public abstract boolean compareAndSet(T obj, int expect, int update);
+
+ /**
+ * Atomically sets the field of the given object managed by this updater
+ * to the given updated value if the current value <tt>==</tt> the
+ * expected value. This method is guaranteed to be atomic with respect to
+ * other calls to <tt>compareAndSet</tt> and <tt>set</tt>, but not
+ * necessarily with respect to other changes in the field.
+ * May fail spuriously and does not provide ordering guarantees,
+ * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
+ *
+ * @param obj An object whose field to conditionally set
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful
+ * @throws ClassCastException if <tt>obj</tt> is not an instance
+ * of the class possessing the field established in the constructor
+ */
+ public abstract boolean weakCompareAndSet(T obj, int expect, int update);
+
+ /**
+ * Sets the field of the given object managed by this updater to the
+ * given updated value. This operation is guaranteed to act as a volatile
+ * store with respect to subsequent invocations of
+ * <tt>compareAndSet</tt>.
+ *
+ * @param obj An object whose field to set
+ * @param newValue the new value
+ */
+ 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.
+ *
+ * @param obj An object whose field to get
+ * @return the current value
+ */
+ public abstract int get(T obj);
+
+ /**
+ * Atomically sets the field of the given object managed by this updater
+ * to the given value and returns the old value.
+ *
+ * @param obj An object whose field to get and set
+ * @param newValue the new value
+ * @return the previous value
+ */
+ public int getAndSet(T obj, int newValue) {
+ for (;;) {
+ int current = get(obj);
+ if (compareAndSet(obj, current, newValue))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically increments by one the current value of the field of the
+ * given object managed by this updater.
+ *
+ * @param obj An object whose field to get and set
+ * @return the previous value
+ */
+ public int getAndIncrement(T obj) {
+ for (;;) {
+ int current = get(obj);
+ int next = current + 1;
+ if (compareAndSet(obj, current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically decrements by one the current value of the field of the
+ * given object managed by this updater.
+ *
+ * @param obj An object whose field to get and set
+ * @return the previous value
+ */
+ public int getAndDecrement(T obj) {
+ for (;;) {
+ int current = get(obj);
+ int next = current - 1;
+ if (compareAndSet(obj, current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically adds the given value to the current value of the field of
+ * the given object managed by this updater.
+ *
+ * @param obj An object whose field to get and set
+ * @param delta the value to add
+ * @return the previous value
+ */
+ public int getAndAdd(T obj, int delta) {
+ for (;;) {
+ int current = get(obj);
+ int next = current + delta;
+ if (compareAndSet(obj, current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically increments by one the current value of the field of the
+ * given object managed by this updater.
+ *
+ * @param obj An object whose field to get and set
+ * @return the updated value
+ */
+ public int incrementAndGet(T obj) {
+ for (;;) {
+ int current = get(obj);
+ int next = current + 1;
+ if (compareAndSet(obj, current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Atomically decrements by one the current value of the field of the
+ * given object managed by this updater.
+ *
+ * @param obj An object whose field to get and set
+ * @return the updated value
+ */
+ public int decrementAndGet(T obj) {
+ for (;;) {
+ int current = get(obj);
+ int next = current - 1;
+ if (compareAndSet(obj, current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Atomically adds the given value to the current value of the field of
+ * the given object managed by this updater.
+ *
+ * @param obj An object whose field to get and set
+ * @param delta the value to add
+ * @return the updated value
+ */
+ public int addAndGet(T obj, int delta) {
+ for (;;) {
+ int current = get(obj);
+ int next = current + delta;
+ if (compareAndSet(obj, current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Standard hotspot implementation using intrinsics
+ */
+ private static class AtomicIntegerFieldUpdaterImpl<T> extends AtomicIntegerFieldUpdater<T> {
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private final long offset;
+ private final Class<T> tclass;
+ private final Class cclass;
+
+ AtomicIntegerFieldUpdaterImpl(Class<T> tclass, String fieldName) {
+ Field field = null;
+ Class caller = null;
+ int modifiers = 0;
+ try {
+ field = tclass.getDeclaredField(fieldName);
+ caller = sun.reflect.Reflection.getCallerClass(3);
+ modifiers = field.getModifiers();
+ sun.reflect.misc.ReflectUtil.ensureMemberAccess(
+ caller, tclass, null, modifiers);
+ sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+ } catch(Exception ex) {
+ throw new RuntimeException(ex);
+ }
+
+ Class fieldt = field.getType();
+ if (fieldt != int.class)
+ throw new IllegalArgumentException("Must be integer type");
+
+ if (!Modifier.isVolatile(modifiers))
+ throw new IllegalArgumentException("Must be volatile type");
+
+ this.cclass = (Modifier.isProtected(modifiers) &&
+ caller != tclass) ? caller : null;
+ this.tclass = tclass;
+ offset = unsafe.objectFieldOffset(field);
+ }
+
+ private void fullCheck(T obj) {
+ if (!tclass.isInstance(obj))
+ throw new ClassCastException();
+ if (cclass != null)
+ ensureProtectedAccess(obj);
+ }
+
+ public boolean compareAndSet(T obj, int expect, int update) {
+ if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+ return unsafe.compareAndSwapInt(obj, offset, expect, update);
+ }
+
+ public boolean weakCompareAndSet(T obj, int expect, int update) {
+ if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+ return unsafe.compareAndSwapInt(obj, offset, expect, update);
+ }
+
+ public void set(T obj, int newValue) {
+ if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+ 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);
+ }
+
+ private void ensureProtectedAccess(T obj) {
+ if (cclass.isInstance(obj)) {
+ return;
+ }
+ throw new RuntimeException(
+ new IllegalAccessException("Class " +
+ cclass.getName() +
+ " can not access a protected member of class " +
+ tclass.getName() +
+ " using an instance of " +
+ obj.getClass().getName()
+ )
+ );
+ }
+ }
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicLong.java b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicLong.java
new file mode 100644
index 000000000..fa254ba62
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicLong.java
@@ -0,0 +1,248 @@
+/*
+ * 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.atomic;
+import sun.misc.Unsafe;
+
+/**
+ * A <tt>long</tt> value that may be updated atomically. See the
+ * {@link java.util.concurrent.atomic} package specification for
+ * description of the properties of atomic variables. An
+ * <tt>AtomicLong</tt> is used in applications such as atomically
+ * incremented sequence numbers, and cannot be used as a replacement
+ * for a {@link java.lang.Long}. However, this class does extend
+ * <tt>Number</tt> to allow uniform access by tools and utilities that
+ * deal with numerically-based classes.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class AtomicLong extends Number implements java.io.Serializable {
+ private static final long serialVersionUID = 1927816293512124184L;
+
+ // setup to use Unsafe.compareAndSwapLong for updates
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private static final long valueOffset;
+
+ /**
+ * Records whether the underlying JVM supports lockless
+ * CompareAndSet for longs. While the unsafe.CompareAndSetLong
+ * method works in either case, some constructions should be
+ * handled at Java level to avoid locking user-visible locks.
+ */
+ static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
+
+ /**
+ * Returns whether underlying JVM supports lockless CompareAndSet
+ * for longs. Called only once and cached in VM_SUPPORTS_LONG_CAS.
+ */
+ private static native boolean VMSupportsCS8();
+
+ static {
+ try {
+ valueOffset = unsafe.objectFieldOffset
+ (AtomicLong.class.getDeclaredField("value"));
+ } catch (Exception ex) { throw new Error(ex); }
+ }
+
+ private volatile long value;
+
+ /**
+ * Creates a new AtomicLong with the given initial value.
+ *
+ * @param initialValue the initial value
+ */
+ public AtomicLong(long initialValue) {
+ value = initialValue;
+ }
+
+ /**
+ * Creates a new AtomicLong with initial value <tt>0</tt>.
+ */
+ public AtomicLong() {
+ }
+
+ /**
+ * Gets the current value.
+ *
+ * @return the current value
+ */
+ public final long get() {
+ return value;
+ }
+
+ /**
+ * Sets to the given value.
+ *
+ * @param newValue the new value
+ */
+ public final void set(long newValue) {
+ value = newValue;
+ }
+
+ /**
+ * 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
+ * @return the previous value
+ */
+ public final long getAndSet(long newValue) {
+ while (true) {
+ long current = get();
+ if (compareAndSet(current, newValue))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically sets the value to the given updated value
+ * if the current value <tt>==</tt> the expected value.
+ *
+ * @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.
+ */
+ public final boolean compareAndSet(long expect, long update) {
+ return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
+ }
+
+ /**
+ * Atomically sets the value to the given updated value
+ * if the current value <tt>==</tt> the expected value.
+ * May fail spuriously and does not provide ordering guarantees,
+ * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
+ *
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful.
+ */
+ public final boolean weakCompareAndSet(long expect, long update) {
+ return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
+ }
+
+ /**
+ * Atomically increments by one the current value.
+ *
+ * @return the previous value
+ */
+ public final long getAndIncrement() {
+ while (true) {
+ long current = get();
+ long next = current + 1;
+ if (compareAndSet(current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically decrements by one the current value.
+ *
+ * @return the previous value
+ */
+ public final long getAndDecrement() {
+ while (true) {
+ long current = get();
+ long next = current - 1;
+ if (compareAndSet(current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically adds the given value to the current value.
+ *
+ * @param delta the value to add
+ * @return the previous value
+ */
+ public final long getAndAdd(long delta) {
+ while (true) {
+ long current = get();
+ long next = current + delta;
+ if (compareAndSet(current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically increments by one the current value.
+ *
+ * @return the updated value
+ */
+ public final long incrementAndGet() {
+ for (;;) {
+ long current = get();
+ long next = current + 1;
+ if (compareAndSet(current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Atomically decrements by one the current value.
+ *
+ * @return the updated value
+ */
+ public final long decrementAndGet() {
+ for (;;) {
+ long current = get();
+ long next = current - 1;
+ if (compareAndSet(current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Atomically adds the given value to the current value.
+ *
+ * @param delta the value to add
+ * @return the updated value
+ */
+ public final long addAndGet(long delta) {
+ for (;;) {
+ long current = get();
+ long next = current + delta;
+ if (compareAndSet(current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Returns the String representation of the current value.
+ * @return the String representation of the current value.
+ */
+ public String toString() {
+ return Long.toString(get());
+ }
+
+
+ public int intValue() {
+ return (int)get();
+ }
+
+ public long longValue() {
+ return (long)get();
+ }
+
+ public float floatValue() {
+ return (float)get();
+ }
+
+ public double doubleValue() {
+ return (double)get();
+ }
+
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicLongArray.java b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicLongArray.java
new file mode 100644
index 000000000..c582cba54
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicLongArray.java
@@ -0,0 +1,255 @@
+/*
+ * 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.atomic;
+import sun.misc.Unsafe;
+import java.util.*;
+
+/**
+ * A <tt>long</tt> array in which elements may be updated atomically.
+ * See the {@link java.util.concurrent.atomic} package specification
+ * for description of the properties of atomic variables.
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class AtomicLongArray implements java.io.Serializable {
+ private static final long serialVersionUID = -2308431214976778248L;
+
+ // setup to use Unsafe.compareAndSwapInt for updates
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ 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) {
+ if (i < 0 || i >= array.length)
+ throw new IndexOutOfBoundsException("index " + i);
+ return base + i * scale;
+ }
+
+ /**
+ * Creates a new AtomicLongArray of given length.
+ *
+ * @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);
+ }
+
+ /**
+ * Creates a new AtomicLongArray with the same length as, and
+ * all elements copied from, the given array.
+ *
+ * @param array the array to copy elements from
+ * @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]);
+ }
+ }
+
+ /**
+ * Returns the length of the array.
+ *
+ * @return the length of the array
+ */
+ public final int length() {
+ return array.length;
+ }
+
+ /**
+ * Gets the current value at position <tt>i</tt>.
+ *
+ * @param i the index
+ * @return the current value
+ */
+ public final long get(int i) {
+ return unsafe.getLongVolatile(array, rawIndex(i));
+ }
+
+ /**
+ * Sets the element at position <tt>i</tt> to the given value.
+ *
+ * @param i the index
+ * @param newValue the new value
+ */
+ public final void set(int i, long newValue) {
+ unsafe.putLongVolatile(array, rawIndex(i), newValue);
+ }
+
+ /**
+ * Eventually sets the element at position <tt>i</tt> 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, rawIndex(i), newValue);
+ }
+
+
+ /**
+ * Atomically sets the element at position <tt>i</tt> to the given value
+ * and returns the old value.
+ *
+ * @param i the index
+ * @param newValue the new value
+ * @return the previous value
+ */
+ public final long getAndSet(int i, long newValue) {
+ while (true) {
+ long current = get(i);
+ if (compareAndSet(i, current, newValue))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically sets the value to the given updated value
+ * if the current value <tt>==</tt> the expected value.
+ *
+ * @param i the index
+ * @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.
+ */
+ public final boolean compareAndSet(int i, long expect, long update) {
+ return unsafe.compareAndSwapLong(array, rawIndex(i),
+ expect, update);
+ }
+
+ /**
+ * Atomically sets the value to the given updated value
+ * if the current value <tt>==</tt> the expected value.
+ * May fail spuriously and does not provide ordering guarantees,
+ * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
+ *
+ * @param i the index
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful.
+ */
+ public final boolean weakCompareAndSet(int i, long expect, long update) {
+ return compareAndSet(i, expect, update);
+ }
+
+ /**
+ * Atomically increments by one the element at index <tt>i</tt>.
+ *
+ * @param i the index
+ * @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;
+ }
+ }
+
+ /**
+ * Atomically decrements by one the element at index <tt>i</tt>.
+ *
+ * @param i the index
+ * @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;
+ }
+ }
+
+ /**
+ * Atomically adds the given value to the element at index <tt>i</tt>.
+ *
+ * @param i the index
+ * @param delta the value to add
+ * @return the previous value
+ */
+ public final long getAndAdd(int i, long delta) {
+ while (true) {
+ long current = get(i);
+ long next = current + delta;
+ if (compareAndSet(i, current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically increments by one the element at index <tt>i</tt>.
+ *
+ * @param i the index
+ * @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;
+ }
+ }
+
+ /**
+ * Atomically decrements by one the element at index <tt>i</tt>.
+ *
+ * @param i the index
+ * @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;
+ }
+ }
+
+ /**
+ * Atomically adds the given value to the element at index <tt>i</tt>.
+ *
+ * @param i the index
+ * @param delta the value to add
+ * @return the updated value
+ */
+ public long addAndGet(int i, long delta) {
+ while (true) {
+ long current = get(i);
+ long next = current + delta;
+ if (compareAndSet(i, current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Returns 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);
+ }
+
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicLongFieldUpdater.java b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
new file mode 100644
index 000000000..f6135d1fc
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
@@ -0,0 +1,406 @@
+/*
+ * 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.atomic;
+import sun.misc.Unsafe;
+import java.lang.reflect.*;
+
+/**
+ * A reflection-based utility that enables atomic updates to
+ * designated <tt>volatile long</tt> fields of designated classes.
+ * This class is designed for use in atomic data structures in which
+ * several fields of the same node are independently subject to atomic
+ * updates.
+ *
+ * <p>Note that the guarantees of the {@code compareAndSet}
+ * method in this class are weaker than in other atomic classes.
+ * Because this class cannot ensure that all uses of the field
+ * are appropriate for purposes of atomic access, it can
+ * guarantee atomicity only with respect to other invocations of
+ * {@code compareAndSet} and {@code set} on the same updater.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <T> The type of the object holding the updatable field
+ */
+public abstract class AtomicLongFieldUpdater<T> {
+ /**
+ * Creates and returns an updater for objects with the given field.
+ * The Class argument is needed to check that reflective types and
+ * generic types match.
+ *
+ * @param tclass the class of the objects holding the field
+ * @param fieldName the name of the field to be updated.
+ * @return the updater
+ * @throws IllegalArgumentException if the field is not a
+ * volatile long type.
+ * @throws RuntimeException with a nested reflection-based
+ * exception if the class does not hold field or is the wrong type.
+ */
+ public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
+ if (AtomicLong.VM_SUPPORTS_LONG_CAS)
+ return new CASUpdater<U>(tclass, fieldName);
+ else
+ return new LockedUpdater<U>(tclass, fieldName);
+ }
+
+ /**
+ * Protected do-nothing constructor for use by subclasses.
+ */
+ protected AtomicLongFieldUpdater() {
+ }
+
+ /**
+ * Atomically sets the field of the given object managed by this updater
+ * to the given updated value if the current value <tt>==</tt> the
+ * expected value. This method is guaranteed to be atomic with respect to
+ * other calls to <tt>compareAndSet</tt> and <tt>set</tt>, but not
+ * necessarily with respect to other changes in the field.
+ *
+ * @param obj An object whose field to conditionally set
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful.
+ * @throws ClassCastException if <tt>obj</tt> is not an instance
+ * of the class possessing the field established in the constructor.
+ */
+ public abstract boolean compareAndSet(T obj, long expect, long update);
+
+ /**
+ * Atomically sets the field of the given object managed by this updater
+ * to the given updated value if the current value <tt>==</tt> the
+ * expected value. This method is guaranteed to be atomic with respect to
+ * other calls to <tt>compareAndSet</tt> and <tt>set</tt>, but not
+ * necessarily with respect to other changes in the field.
+ * May fail spuriously and does not provide ordering guarantees,
+ * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
+ *
+ * @param obj An object whose field to conditionally set
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful.
+ * @throws ClassCastException if <tt>obj</tt> is not an instance
+ * of the class possessing the field established in the constructor.
+ */
+ public abstract boolean weakCompareAndSet(T obj, long expect, long update);
+
+ /**
+ * Sets the field of the given object managed by this updater to the
+ * given updated value. This operation is guaranteed to act as a volatile
+ * store with respect to subsequent invocations of
+ * <tt>compareAndSet</tt>.
+ *
+ * @param obj An object whose field to set
+ * @param newValue the new value
+ */
+ 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.
+ *
+ * @param obj An object whose field to get
+ * @return the current value
+ */
+ public abstract long get(T obj);
+
+ /**
+ * Atomically sets the field of the given object managed by this updater
+ * to the given value and returns the old value.
+ *
+ * @param obj An object whose field to get and set
+ * @param newValue the new value
+ * @return the previous value
+ */
+ public long getAndSet(T obj, long newValue) {
+ for (;;) {
+ long current = get(obj);
+ if (compareAndSet(obj, current, newValue))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically increments by one the current value of the field of the
+ * given object managed by this updater.
+ *
+ * @param obj An object whose field to get and set
+ * @return the previous value
+ */
+ public long getAndIncrement(T obj) {
+ for (;;) {
+ long current = get(obj);
+ long next = current + 1;
+ if (compareAndSet(obj, current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically decrements by one the current value of the field of the
+ * given object managed by this updater.
+ *
+ * @param obj An object whose field to get and set
+ * @return the previous value
+ */
+ public long getAndDecrement(T obj) {
+ for (;;) {
+ long current = get(obj);
+ long next = current - 1;
+ if (compareAndSet(obj, current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically adds the given value to the current value of the field of
+ * the given object managed by this updater.
+ *
+ * @param obj An object whose field to get and set
+ * @param delta the value to add
+ * @return the previous value
+ */
+ public long getAndAdd(T obj, long delta) {
+ for (;;) {
+ long current = get(obj);
+ long next = current + delta;
+ if (compareAndSet(obj, current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically increments by one the current value of the field of the
+ * given object managed by this updater.
+ *
+ * @param obj An object whose field to get and set
+ * @return the updated value
+ */
+ public long incrementAndGet(T obj) {
+ for (;;) {
+ long current = get(obj);
+ long next = current + 1;
+ if (compareAndSet(obj, current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Atomically decrements by one the current value of the field of the
+ * given object managed by this updater.
+ *
+ * @param obj An object whose field to get and set
+ * @return the updated value
+ */
+ public long decrementAndGet(T obj) {
+ for (;;) {
+ long current = get(obj);
+ long next = current - 1;
+ if (compareAndSet(obj, current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Atomically adds the given value to the current value of the field of
+ * the given object managed by this updater.
+ *
+ * @param obj An object whose field to get and set
+ * @param delta the value to add
+ * @return the updated value
+ */
+ public long addAndGet(T obj, long delta) {
+ for (;;) {
+ long current = get(obj);
+ long next = current + delta;
+ if (compareAndSet(obj, current, next))
+ return next;
+ }
+ }
+
+ private static class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private final long offset;
+ private final Class<T> tclass;
+ private final Class cclass;
+
+ CASUpdater(Class<T> tclass, String fieldName) {
+ Field field = null;
+ Class caller = null;
+ int modifiers = 0;
+ try {
+ field = tclass.getDeclaredField(fieldName);
+ caller = sun.reflect.Reflection.getCallerClass(3);
+ modifiers = field.getModifiers();
+ sun.reflect.misc.ReflectUtil.ensureMemberAccess(
+ caller, tclass, null, modifiers);
+ sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+ } catch(Exception ex) {
+ throw new RuntimeException(ex);
+ }
+
+ Class fieldt = field.getType();
+ if (fieldt != long.class)
+ throw new IllegalArgumentException("Must be long type");
+
+ if (!Modifier.isVolatile(modifiers))
+ throw new IllegalArgumentException("Must be volatile type");
+
+ this.cclass = (Modifier.isProtected(modifiers) &&
+ caller != tclass) ? caller : null;
+ this.tclass = tclass;
+ offset = unsafe.objectFieldOffset(field);
+ }
+
+ private void fullCheck(T obj) {
+ if (!tclass.isInstance(obj))
+ throw new ClassCastException();
+ if (cclass != null)
+ ensureProtectedAccess(obj);
+ }
+
+ public boolean compareAndSet(T obj, long expect, long update) {
+ if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+ return unsafe.compareAndSwapLong(obj, offset, expect, update);
+ }
+
+ public boolean weakCompareAndSet(T obj, long expect, long update) {
+ if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+ return unsafe.compareAndSwapLong(obj, offset, expect, update);
+ }
+
+ public void set(T obj, long newValue) {
+ if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+ 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);
+ }
+
+ private void ensureProtectedAccess(T obj) {
+ if (cclass.isInstance(obj)) {
+ return;
+ }
+ throw new RuntimeException (
+ new IllegalAccessException("Class " +
+ cclass.getName() +
+ " can not access a protected member of class " +
+ tclass.getName() +
+ " using an instance of " +
+ obj.getClass().getName()
+ )
+ );
+ }
+ }
+
+
+ private static class LockedUpdater<T> extends AtomicLongFieldUpdater<T> {
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private final long offset;
+ private final Class<T> tclass;
+ private final Class cclass;
+
+ LockedUpdater(Class<T> tclass, String fieldName) {
+ Field field = null;
+ Class caller = null;
+ int modifiers = 0;
+ try {
+ field = tclass.getDeclaredField(fieldName);
+ caller = sun.reflect.Reflection.getCallerClass(3);
+ modifiers = field.getModifiers();
+ sun.reflect.misc.ReflectUtil.ensureMemberAccess(
+ caller, tclass, null, modifiers);
+ sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+ } catch(Exception ex) {
+ throw new RuntimeException(ex);
+ }
+
+ Class fieldt = field.getType();
+ if (fieldt != long.class)
+ throw new IllegalArgumentException("Must be long type");
+
+ if (!Modifier.isVolatile(modifiers))
+ throw new IllegalArgumentException("Must be volatile type");
+
+ this.cclass = (Modifier.isProtected(modifiers) &&
+ caller != tclass) ? caller : null;
+ this.tclass = tclass;
+ offset = unsafe.objectFieldOffset(field);
+ }
+
+ private void fullCheck(T obj) {
+ if (!tclass.isInstance(obj))
+ throw new ClassCastException();
+ if (cclass != null)
+ ensureProtectedAccess(obj);
+ }
+
+ public boolean compareAndSet(T obj, long expect, long update) {
+ if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+ synchronized(this) {
+ long v = unsafe.getLong(obj, offset);
+ if (v != expect)
+ return false;
+ unsafe.putLong(obj, offset, update);
+ return true;
+ }
+ }
+
+ public boolean weakCompareAndSet(T obj, long expect, long update) {
+ return compareAndSet(obj, expect, update);
+ }
+
+ public void set(T obj, long newValue) {
+ if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+ synchronized(this) {
+ unsafe.putLong(obj, offset, newValue);
+ }
+ }
+
+ public void lazySet(T obj, long newValue) {
+ set(obj, newValue);
+ }
+
+ public long get(T obj) {
+ if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+ synchronized(this) {
+ return unsafe.getLong(obj, offset);
+ }
+ }
+
+ private void ensureProtectedAccess(T obj) {
+ if (cclass.isInstance(obj)) {
+ return;
+ }
+ throw new RuntimeException (
+ new IllegalAccessException("Class " +
+ cclass.getName() +
+ " can not access a protected member of class " +
+ tclass.getName() +
+ " using an instance of " +
+ obj.getClass().getName()
+ )
+ );
+ }
+ }
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicMarkableReference.java b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicMarkableReference.java
new file mode 100644
index 000000000..85335b737
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicMarkableReference.java
@@ -0,0 +1,161 @@
+/*
+ * 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.atomic;
+
+/**
+ * An <tt>AtomicMarkableReference</tt> maintains an object reference
+ * along with a mark bit, that can be updated atomically.
+ * <p>
+ * <p> Implementation note. This implementation maintains markable
+ * references by creating internal objects representing "boxed"
+ * [reference, boolean] pairs.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <V> The type of object referred to by this reference
+ */
+public class AtomicMarkableReference<V> {
+
+ private static class ReferenceBooleanPair<T> {
+ private final T reference;
+ private final boolean bit;
+ ReferenceBooleanPair(T r, boolean i) {
+ reference = r; bit = i;
+ }
+ }
+
+ private final AtomicReference<ReferenceBooleanPair<V>> atomicRef;
+
+ /**
+ * Creates a new <tt>AtomicMarkableReference</tt> with the given
+ * initial values.
+ *
+ * @param initialRef the initial reference
+ * @param initialMark the initial mark
+ */
+ public AtomicMarkableReference(V initialRef, boolean initialMark) {
+ atomicRef = new AtomicReference<ReferenceBooleanPair<V>> (new ReferenceBooleanPair<V>(initialRef, initialMark));
+ }
+
+ /**
+ * Returns the current value of the reference.
+ *
+ * @return the current value of the reference
+ */
+ public V getReference() {
+ return atomicRef.get().reference;
+ }
+
+ /**
+ * Returns the current value of the mark.
+ *
+ * @return the current value of the mark
+ */
+ public boolean isMarked() {
+ return atomicRef.get().bit;
+ }
+
+ /**
+ * Returns the current values of both the reference and the mark.
+ * Typical usage is <tt>boolean[1] holder; ref = v.get(holder); </tt>.
+ *
+ * @param markHolder an array of size of at least one. On return,
+ * <tt>markholder[0]</tt> will hold the value of the mark.
+ * @return the current value of the reference
+ */
+ public V get(boolean[] markHolder) {
+ ReferenceBooleanPair<V> p = atomicRef.get();
+ markHolder[0] = p.bit;
+ return p.reference;
+ }
+
+ /**
+ * Atomically sets the value of both the reference and mark
+ * to the given update values if the
+ * current reference is <tt>==</tt> to the expected reference
+ * and the current mark is equal to the expected mark.
+ * May fail spuriously and does not provide ordering guarantees,
+ * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
+ *
+ * @param expectedReference the expected value of the reference
+ * @param newReference the new value for the reference
+ * @param expectedMark the expected value of the mark
+ * @param newMark the new value for the mark
+ * @return true if successful
+ */
+ public boolean weakCompareAndSet(V expectedReference,
+ V newReference,
+ boolean expectedMark,
+ boolean newMark) {
+ ReferenceBooleanPair<V> current = atomicRef.get();
+ return expectedReference == current.reference &&
+ expectedMark == current.bit &&
+ ((newReference == current.reference && newMark == current.bit) ||
+ atomicRef.weakCompareAndSet(current,
+ new ReferenceBooleanPair<V>(newReference,
+ newMark)));
+ }
+
+ /**
+ * Atomically sets the value of both the reference and mark
+ * to the given update values if the
+ * current reference is <tt>==</tt> to the expected reference
+ * and the current mark is equal to the expected mark.
+ *
+ * @param expectedReference the expected value of the reference
+ * @param newReference the new value for the reference
+ * @param expectedMark the expected value of the mark
+ * @param newMark the new value for the mark
+ * @return true if successful
+ */
+ public boolean compareAndSet(V expectedReference,
+ V newReference,
+ boolean expectedMark,
+ boolean newMark) {
+ ReferenceBooleanPair<V> current = atomicRef.get();
+ return expectedReference == current.reference &&
+ expectedMark == current.bit &&
+ ((newReference == current.reference && newMark == current.bit) ||
+ atomicRef.compareAndSet(current,
+ new ReferenceBooleanPair<V>(newReference,
+ newMark)));
+ }
+
+ /**
+ * Unconditionally sets the value of both the reference and mark.
+ *
+ * @param newReference the new value for the reference
+ * @param newMark the new value for the mark
+ */
+ public void set(V newReference, boolean newMark) {
+ ReferenceBooleanPair<V> current = atomicRef.get();
+ if (newReference != current.reference || newMark != current.bit)
+ atomicRef.set(new ReferenceBooleanPair<V>(newReference, newMark));
+ }
+
+ /**
+ * Atomically sets the value of the mark to the given update value
+ * if the current reference is <tt>==</tt> to the expected
+ * reference. Any given invocation of this operation may fail
+ * (return <tt>false</tt>) spuriously, but repeated invocation
+ * when the current value holds the expected value and no other
+ * thread is also attempting to set the value will eventually
+ * succeed.
+ *
+ * @param expectedReference the expected value of the reference
+ * @param newMark the new value for the mark
+ * @return true if successful
+ */
+ public boolean attemptMark(V expectedReference, boolean newMark) {
+ ReferenceBooleanPair<V> current = atomicRef.get();
+ return expectedReference == current.reference &&
+ (newMark == current.bit ||
+ atomicRef.compareAndSet
+ (current, new ReferenceBooleanPair<V>(expectedReference,
+ newMark)));
+ }
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicReference.java b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicReference.java
new file mode 100644
index 000000000..e7c989c2b
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicReference.java
@@ -0,0 +1,124 @@
+/*
+ * 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.atomic;
+import sun.misc.Unsafe;
+
+/**
+ * An object reference that may be updated atomically. See the {@link
+ * java.util.concurrent.atomic} package specification for description
+ * of the properties of atomic variables.
+ * @since 1.5
+ * @author Doug Lea
+ * @param <V> The type of object referred to by this reference
+ */
+public class AtomicReference<V> implements java.io.Serializable {
+ private static final long serialVersionUID = -1848883965231344442L;
+
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private static final long valueOffset;
+
+ static {
+ try {
+ valueOffset = unsafe.objectFieldOffset
+ (AtomicReference.class.getDeclaredField("value"));
+ } catch (Exception ex) { throw new Error(ex); }
+ }
+
+ private volatile V value;
+
+ /**
+ * Creates a new AtomicReference with the given initial value.
+ *
+ * @param initialValue the initial value
+ */
+ public AtomicReference(V initialValue) {
+ value = initialValue;
+ }
+
+ /**
+ * Creates a new AtomicReference with null initial value.
+ */
+ public AtomicReference() {
+ }
+
+ /**
+ * Gets the current value.
+ *
+ * @return the current value
+ */
+ public final V get() {
+ return value;
+ }
+
+ /**
+ * Sets to the given value.
+ *
+ * @param newValue the new value
+ */
+ public final void set(V newValue) {
+ value = newValue;
+ }
+
+ /**
+ * 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 <tt>==</tt> the expected value.
+ * @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.
+ */
+ public final boolean compareAndSet(V expect, V update) {
+ return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
+ }
+
+ /**
+ * Atomically sets the value to the given updated value
+ * if the current value <tt>==</tt> the expected value.
+ * May fail spuriously and does not provide ordering guarantees,
+ * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
+ *
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful.
+ */
+ public final boolean weakCompareAndSet(V expect, V update) {
+ return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
+ }
+
+ /**
+ * Atomically sets to the given value and returns the old value.
+ *
+ * @param newValue the new value
+ * @return the previous value
+ */
+ public final V getAndSet(V newValue) {
+ while (true) {
+ V x = get();
+ if (compareAndSet(x, newValue))
+ return x;
+ }
+ }
+
+ /**
+ * Returns the String representation of the current value.
+ * @return the String representation of the current value.
+ */
+ public String toString() {
+ return String.valueOf(get());
+ }
+
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicReferenceArray.java b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicReferenceArray.java
new file mode 100644
index 000000000..91b601ed9
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicReferenceArray.java
@@ -0,0 +1,163 @@
+/*
+ * 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.atomic;
+import sun.misc.Unsafe;
+import java.util.*;
+
+/**
+ * An array of object references in which elements may be updated
+ * atomically. See the {@link java.util.concurrent.atomic} package
+ * specification for description of the properties of atomic
+ * variables.
+ * @since 1.5
+ * @author Doug Lea
+ * @param <E> The base class of elements held in this array
+ */
+public class AtomicReferenceArray<E> implements java.io.Serializable {
+ private static final long serialVersionUID = -6209656149925076980L;
+
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ 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) {
+ if (i < 0 || i >= array.length)
+ throw new IndexOutOfBoundsException("index " + i);
+ return base + i * scale;
+ }
+
+ /**
+ * Creates a new AtomicReferenceArray of given length.
+ * @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);
+ }
+
+ /**
+ * Creates a new AtomicReferenceArray with the same length as, and
+ * all elements copied from, the given array.
+ *
+ * @param array the array to copy elements from
+ * @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);
+ }
+ }
+
+ /**
+ * Returns the length of the array.
+ *
+ * @return the length of the array
+ */
+ public final int length() {
+ return array.length;
+ }
+
+ /**
+ * Gets the current value at position <tt>i</tt>.
+ *
+ * @param i the index
+ * @return the current value
+ */
+ public final E get(int i) {
+ return (E) unsafe.getObjectVolatile(array, rawIndex(i));
+ }
+
+ /**
+ * Sets the element at position <tt>i</tt> to the given value.
+ *
+ * @param i the index
+ * @param newValue the new value
+ */
+ public final void set(int i, E newValue) {
+ unsafe.putObjectVolatile(array, rawIndex(i), newValue);
+ }
+
+ /**
+ * Eventually sets the element at position <tt>i</tt> 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, rawIndex(i), newValue);
+ }
+
+
+ /**
+ * Atomically sets the element at position <tt>i</tt> to the given
+ * value and returns the old value.
+ *
+ * @param i the index
+ * @param newValue the new value
+ * @return the previous value
+ */
+ public final E getAndSet(int i, E newValue) {
+ while (true) {
+ E current = get(i);
+ if (compareAndSet(i, current, newValue))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically sets the element at position <tt>i</tt> to the given
+ * updated value if the current value <tt>==</tt> the expected value.
+ * @param i the index
+ * @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.
+ */
+ public final boolean compareAndSet(int i, E expect, E update) {
+ return unsafe.compareAndSwapObject(array, rawIndex(i),
+ expect, update);
+ }
+
+ /**
+ * Atomically sets the element at position <tt>i</tt> to the given
+ * updated value if the current value <tt>==</tt> the expected value.
+ * May fail spuriously and does not provide ordering guarantees,
+ * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
+ *
+ * @param i the index
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful.
+ */
+ public final boolean weakCompareAndSet(int i, E expect, E update) {
+ return compareAndSet(i, expect, update);
+ }
+
+ /**
+ * Returns 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);
+ }
+
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
new file mode 100644
index 000000000..24014a9df
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
@@ -0,0 +1,275 @@
+/*
+ * 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.atomic;
+import sun.misc.Unsafe;
+import java.lang.reflect.*;
+
+/**
+ * A reflection-based utility that enables atomic updates to
+ * designated <tt>volatile</tt> reference fields of designated
+ * classes. This class is designed for use in atomic data structures
+ * in which several reference fields of the same node are
+ * independently subject to atomic updates. For example, a tree node
+ * might be declared as
+ *
+ * <pre>
+ * class Node {
+ * private volatile Node left, right;
+ *
+ * private static final AtomicReferenceFieldUpdater&lt;Node, Node&gt; leftUpdater =
+ * AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left");
+ * private static AtomicReferenceFieldUpdater&lt;Node, Node&gt; rightUpdater =
+ * AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right");
+ *
+ * Node getLeft() { return left; }
+ * boolean compareAndSetLeft(Node expect, Node update) {
+ * return leftUpdater.compareAndSet(this, expect, update);
+ * }
+ * // ... and so on
+ * }
+ * </pre>
+ *
+ * <p>Note that the guarantees of the {@code compareAndSet}
+ * method in this class are weaker than in other atomic classes.
+ * Because this class cannot ensure that all uses of the field
+ * are appropriate for purposes of atomic access, it can
+ * guarantee atomicity only with respect to other invocations of
+ * {@code compareAndSet} and {@code set} on the same updater.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <T> The type of the object holding the updatable field
+ * @param <V> The type of the field
+ */
+public abstract class AtomicReferenceFieldUpdater<T, V> {
+
+ /**
+ * Creates and returns an updater for objects with the given field.
+ * The Class arguments are needed to check that reflective types and
+ * generic types match.
+ *
+ * @param tclass the class of the objects holding the field.
+ * @param vclass the class of the field
+ * @param fieldName the name of the field to be updated.
+ * @return the updater
+ * @throws IllegalArgumentException if the field is not a volatile reference type.
+ * @throws RuntimeException with a nested reflection-based
+ * exception if the class does not hold field or is the wrong type.
+ */
+ public static <U, W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass, Class<W> vclass, String fieldName) {
+ return new AtomicReferenceFieldUpdaterImpl<U,W>(tclass,
+ vclass,
+ fieldName);
+ }
+
+ /**
+ * Protected do-nothing constructor for use by subclasses.
+ */
+ protected AtomicReferenceFieldUpdater() {
+ }
+
+ /**
+ * Atomically sets the field of the given object managed by this updater
+ * to the given updated value if the current value <tt>==</tt> the
+ * expected value. This method is guaranteed to be atomic with respect to
+ * other calls to <tt>compareAndSet</tt> and <tt>set</tt>, but not
+ * necessarily with respect to other changes in the field.
+ *
+ * @param obj An object whose field to conditionally set
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful.
+ */
+ public abstract boolean compareAndSet(T obj, V expect, V update);
+
+ /**
+ * Atomically sets the field of the given object managed by this updater
+ * to the given updated value if the current value <tt>==</tt> the
+ * expected value. This method is guaranteed to be atomic with respect to
+ * other calls to <tt>compareAndSet</tt> and <tt>set</tt>, but not
+ * necessarily with respect to other changes in the field.
+ * May fail spuriously and does not provide ordering guarantees,
+ * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
+ *
+ * @param obj An object whose field to conditionally set
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful.
+ */
+ public abstract boolean weakCompareAndSet(T obj, V expect, V update);
+
+ /**
+ * Sets the field of the given object managed by this updater to the
+ * given updated value. This operation is guaranteed to act as a volatile
+ * store with respect to subsequent invocations of
+ * <tt>compareAndSet</tt>.
+ *
+ * @param obj An object whose field to set
+ * @param newValue the new value
+ */
+ 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.
+ *
+ * @param obj An object whose field to get
+ * @return the current value
+ */
+ public abstract V get(T obj);
+
+ /**
+ * Atomically sets the field of the given object managed by this updater
+ * to the given value and returns the old value.
+ *
+ * @param obj An object whose field to get and set
+ * @param newValue the new value
+ * @return the previous value
+ */
+ public V getAndSet(T obj, V newValue) {
+ for (;;) {
+ V current = get(obj);
+ if (compareAndSet(obj, current, newValue))
+ return current;
+ }
+ }
+
+ private static final class AtomicReferenceFieldUpdaterImpl<T,V>
+ extends AtomicReferenceFieldUpdater<T,V> {
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private final long offset;
+ private final Class<T> tclass;
+ private final Class<V> vclass;
+ private final Class cclass;
+
+ /*
+ * Internal type checks within all update methods contain
+ * internal inlined optimizations checking for the common
+ * cases where the class is final (in which case a simple
+ * getClass comparison suffices) or is of type Object (in
+ * which case no check is needed because all objects are
+ * instances of Object). The Object case is handled simply by
+ * setting vclass to null in constructor. The targetCheck and
+ * updateCheck methods are invoked when these faster
+ * screenings fail.
+ */
+
+ AtomicReferenceFieldUpdaterImpl(Class<T> tclass,
+ Class<V> vclass,
+ String fieldName) {
+ Field field = null;
+ Class fieldClass = null;
+ Class caller = null;
+ int modifiers = 0;
+ try {
+ field = tclass.getDeclaredField(fieldName);
+ caller = sun.reflect.Reflection.getCallerClass(3);
+ modifiers = field.getModifiers();
+ sun.reflect.misc.ReflectUtil.ensureMemberAccess(
+ caller, tclass, null, modifiers);
+ sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+ fieldClass = field.getType();
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+
+ if (vclass != fieldClass)
+ throw new ClassCastException();
+
+ if (!Modifier.isVolatile(modifiers))
+ throw new IllegalArgumentException("Must be volatile type");
+
+ this.cclass = (Modifier.isProtected(modifiers) &&
+ caller != tclass) ? caller : null;
+ this.tclass = tclass;
+ if (vclass == Object.class)
+ this.vclass = null;
+ else
+ this.vclass = vclass;
+ offset = unsafe.objectFieldOffset(field);
+ }
+
+ void targetCheck(T obj) {
+ if (!tclass.isInstance(obj))
+ throw new ClassCastException();
+ if (cclass != null)
+ ensureProtectedAccess(obj);
+ }
+
+ void updateCheck(T obj, V update) {
+ if (!tclass.isInstance(obj) ||
+ (update != null && vclass != null && !vclass.isInstance(update)))
+ throw new ClassCastException();
+ if (cclass != null)
+ ensureProtectedAccess(obj);
+ }
+
+ public boolean compareAndSet(T obj, V expect, V update) {
+ if (obj == null || obj.getClass() != tclass || cclass != null ||
+ (update != null && vclass != null &&
+ vclass != update.getClass()))
+ updateCheck(obj, update);
+ return unsafe.compareAndSwapObject(obj, offset, expect, update);
+ }
+
+ public boolean weakCompareAndSet(T obj, V expect, V update) {
+ // same implementation as strong form for now
+ if (obj == null || obj.getClass() != tclass || cclass != null ||
+ (update != null && vclass != null &&
+ vclass != update.getClass()))
+ updateCheck(obj, update);
+ return unsafe.compareAndSwapObject(obj, offset, expect, update);
+ }
+
+ public void set(T obj, V newValue) {
+ if (obj == null || obj.getClass() != tclass || cclass != null ||
+ (newValue != null && vclass != null &&
+ vclass != newValue.getClass()))
+ updateCheck(obj, newValue);
+ 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);
+ return (V)unsafe.getObjectVolatile(obj, offset);
+ }
+
+ private void ensureProtectedAccess(T obj) {
+ if (cclass.isInstance(obj)) {
+ return;
+ }
+ throw new RuntimeException (
+ new IllegalAccessException("Class " +
+ cclass.getName() +
+ " can not access a protected member of class " +
+ tclass.getName() +
+ " using an instance of " +
+ obj.getClass().getName()
+ )
+ );
+ }
+ }
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicStampedReference.java b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicStampedReference.java
new file mode 100644
index 000000000..558808216
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicStampedReference.java
@@ -0,0 +1,165 @@
+/*
+ * 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.atomic;
+
+/**
+ * An <tt>AtomicStampedReference</tt> maintains an object reference
+ * along with an integer "stamp", that can be updated atomically.
+ *
+ * <p> Implementation note. This implementation maintains stamped
+ * references by creating internal objects representing "boxed"
+ * [reference, integer] pairs.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <V> The type of object referred to by this reference
+ */
+public class AtomicStampedReference<V> {
+
+ private static class ReferenceIntegerPair<T> {
+ private final T reference;
+ private final int integer;
+ ReferenceIntegerPair(T r, int i) {
+ reference = r; integer = i;
+ }
+ }
+
+ private final AtomicReference<ReferenceIntegerPair<V>> atomicRef;
+
+ /**
+ * Creates a new <tt>AtomicStampedReference</tt> with the given
+ * initial values.
+ *
+ * @param initialRef the initial reference
+ * @param initialStamp the initial stamp
+ */
+ public AtomicStampedReference(V initialRef, int initialStamp) {
+ atomicRef = new AtomicReference<ReferenceIntegerPair<V>>
+ (new ReferenceIntegerPair<V>(initialRef, initialStamp));
+ }
+
+ /**
+ * Returns the current value of the reference.
+ *
+ * @return the current value of the reference
+ */
+ public V getReference() {
+ return atomicRef.get().reference;
+ }
+
+ /**
+ * Returns the current value of the stamp.
+ *
+ * @return the current value of the stamp
+ */
+ public int getStamp() {
+ return atomicRef.get().integer;
+ }
+
+ /**
+ * Returns the current values of both the reference and the stamp.
+ * Typical usage is <tt>int[1] holder; ref = v.get(holder); </tt>.
+ *
+ * @param stampHolder an array of size of at least one. On return,
+ * <tt>stampholder[0]</tt> will hold the value of the stamp.
+ * @return the current value of the reference
+ */
+ public V get(int[] stampHolder) {
+ ReferenceIntegerPair<V> p = atomicRef.get();
+ stampHolder[0] = p.integer;
+ return p.reference;
+ }
+
+ /**
+ * Atomically sets the value of both the reference and stamp
+ * to the given update values if the
+ * current reference is <tt>==</tt> to the expected reference
+ * and the current stamp is equal to the expected stamp.
+ * May fail spuriously and does not provide ordering guarantees,
+ * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
+ *
+ * @param expectedReference the expected value of the reference
+ * @param newReference the new value for the reference
+ * @param expectedStamp the expected value of the stamp
+ * @param newStamp the new value for the stamp
+ * @return true if successful
+ */
+ public boolean weakCompareAndSet(V expectedReference,
+ V newReference,
+ int expectedStamp,
+ int newStamp) {
+ ReferenceIntegerPair<V> current = atomicRef.get();
+ return expectedReference == current.reference &&
+ expectedStamp == current.integer &&
+ ((newReference == current.reference &&
+ newStamp == current.integer) ||
+ atomicRef.weakCompareAndSet(current,
+ new ReferenceIntegerPair<V>(newReference,
+ newStamp)));
+ }
+
+ /**
+ * Atomically sets the value of both the reference and stamp
+ * to the given update values if the
+ * current reference is <tt>==</tt> to the expected reference
+ * and the current stamp is equal to the expected stamp.
+ *
+ * @param expectedReference the expected value of the reference
+ * @param newReference the new value for the reference
+ * @param expectedStamp the expected value of the stamp
+ * @param newStamp the new value for the stamp
+ * @return true if successful
+ */
+ public boolean compareAndSet(V expectedReference,
+ V newReference,
+ int expectedStamp,
+ int newStamp) {
+ ReferenceIntegerPair<V> current = atomicRef.get();
+ return expectedReference == current.reference &&
+ expectedStamp == current.integer &&
+ ((newReference == current.reference &&
+ newStamp == current.integer) ||
+ atomicRef.compareAndSet(current,
+ new ReferenceIntegerPair<V>(newReference,
+ newStamp)));
+ }
+
+
+ /**
+ * Unconditionally sets the value of both the reference and stamp.
+ *
+ * @param newReference the new value for the reference
+ * @param newStamp the new value for the stamp
+ */
+ public void set(V newReference, int newStamp) {
+ ReferenceIntegerPair<V> current = atomicRef.get();
+ if (newReference != current.reference || newStamp != current.integer)
+ atomicRef.set(new ReferenceIntegerPair<V>(newReference, newStamp));
+ }
+
+ /**
+ * Atomically sets the value of the stamp to the given update value
+ * if the current reference is <tt>==</tt> to the expected
+ * reference. Any given invocation of this operation may fail
+ * (return <tt>false</tt>) spuriously, but repeated invocation
+ * when the current value holds the expected value and no other
+ * thread is also attempting to set the value will eventually
+ * succeed.
+ *
+ * @param expectedReference the expected value of the reference
+ * @param newStamp the new value for the stamp
+ * @return true if successful
+ */
+ public boolean attemptStamp(V expectedReference, int newStamp) {
+ ReferenceIntegerPair<V> current = atomicRef.get();
+ return expectedReference == current.reference &&
+ (newStamp == current.integer ||
+ atomicRef.compareAndSet(current,
+ new ReferenceIntegerPair<V>(expectedReference,
+ newStamp)));
+ }
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/locks/AbstractOwnableSynchronizer.java b/libjava/classpath/external/jsr166/java/util/concurrent/locks/AbstractOwnableSynchronizer.java
new file mode 100644
index 000000000..f3780e5a6
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/locks/AbstractOwnableSynchronizer.java
@@ -0,0 +1,57 @@
+/*
+ * 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;
+
+/**
+ * A synchronizer that may be exclusively owned by a thread. This
+ * class provides a basis for creating locks and related synchronizers
+ * that may entail a notion of ownership. The
+ * <tt>AbstractOwnableSynchronizer</tt> class itself does not manage or
+ * use this information. However, subclasses and tools may use
+ * appropriately maintained values to help control and monitor access
+ * and provide diagnostics.
+ *
+ * @since 1.6
+ * @author Doug Lea
+ */
+public abstract class AbstractOwnableSynchronizer
+ implements java.io.Serializable {
+
+ /** Use serial ID even though all fields transient. */
+ private static final long serialVersionUID = 3737899427754241961L;
+
+ /**
+ * Empty constructor for use by subclasses.
+ */
+ protected AbstractOwnableSynchronizer() { }
+
+ /**
+ * The current owner of exclusive mode synchronization.
+ */
+ private transient Thread exclusiveOwnerThread;
+
+ /**
+ * Sets the thread that currently owns exclusive access. A
+ * <tt>null</tt> argument indicates that no thread owns access.
+ * This method does not otherwise impose any synchronization or
+ * <tt>volatile</tt> field accesses.
+ */
+ protected final void setExclusiveOwnerThread(Thread t) {
+ exclusiveOwnerThread = t;
+ }
+
+ /**
+ * Returns the thread last set by
+ * <tt>setExclusiveOwnerThread</tt>, or <tt>null</tt> if never
+ * set. This method does not otherwise impose any synchronization
+ * or <tt>volatile</tt> field accesses.
+ * @return the owner thread
+ */
+ protected final Thread getExclusiveOwnerThread() {
+ return exclusiveOwnerThread;
+ }
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java b/libjava/classpath/external/jsr166/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java
new file mode 100644
index 000000000..45d744bb8
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java
@@ -0,0 +1,1934 @@
+/*
+ * 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.
+ *
+ * <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 {
+ /** 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;
+ /** 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;
+
+ /**
+ * 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. (Use of this value here
+ * has nothing to do with the other uses
+ * of the field, but simplifies mechanics.)
+ * 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 only using
+ * CAS.
+ */
+ 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 once during enqueuing, and
+ * nulled out (for sake of GC) when no longer needed. Upon
+ * cancellation, we cannot adjust this field, but can notice
+ * status and bypass the node if cancelled. 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.
+ */
+ 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.
+ * @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
+ Node h = new Node(); // Dummy header
+ h.next = node;
+ node.prev = h;
+ if (compareAndSetHead(h)) {
+ tail = node;
+ return h;
+ }
+ }
+ else {
+ node.prev = t;
+ if (compareAndSetTail(t, node)) {
+ t.next = node;
+ return t;
+ }
+ }
+ }
+ }
+
+ /**
+ * Creates and enqueues node for given thread and mode.
+ *
+ * @param current the thread
+ * @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) {
+ /*
+ * Try to clear status in anticipation of signalling. It is
+ * OK if this fails or if status is changed by waiting thread.
+ */
+ compareAndSetWaitStatus(node, Node.SIGNAL, 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);
+ }
+
+ /**
+ * Sets head of queue, and checks if successor may be waiting
+ * in shared mode, if so propagating if propagate > 0.
+ *
+ * @param pred the node holding waitStatus for node
+ * @param node the node
+ * @param propagate the return value from a tryAcquireShared
+ */
+ private void setHeadAndPropagate(Node node, long propagate) {
+ setHead(node);
+ if (propagate > 0 && node.waitStatus != 0) {
+ /*
+ * Don't bother fully figuring out successor. If it
+ * looks null, call unparkSuccessor anyway to be safe.
+ */
+ Node s = node.next;
+ if (s == null || s.isShared())
+ unparkSuccessor(node);
+ }
+ }
+
+ // Utilities for various versions of acquire
+
+ /**
+ * Cancels an ongoing attempt to acquire.
+ *
+ * @param node the node
+ */
+ private void cancelAcquire(Node node) {
+ if (node != null) { // Ignore if node doesn't exist
+ node.thread = null;
+ // Can use unconditional write instead of CAS here
+ node.waitStatus = Node.CANCELLED;
+ unparkSuccessor(node);
+ }
+ }
+
+ /**
+ * 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 s = pred.waitStatus;
+ if (s < 0)
+ /*
+ * This node has already set status asking a release
+ * to signal it, so it can safely park
+ */
+ return true;
+ if (s > 0)
+ /*
+ * Predecessor was cancelled. Move up to its predecessor
+ * and indicate retry.
+ */
+ node.prev = pred.prev;
+ else
+ /*
+ * 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, 0, 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) {
+ try {
+ boolean interrupted = false;
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head && tryAcquire(arg)) {
+ setHead(node);
+ p.next = null; // help GC
+ return interrupted;
+ }
+ if (shouldParkAfterFailedAcquire(p, node) &&
+ parkAndCheckInterrupt())
+ interrupted = true;
+ }
+ } catch (RuntimeException ex) {
+ cancelAcquire(node);
+ throw ex;
+ }
+ }
+
+ /**
+ * Acquires in exclusive interruptible mode.
+ * @param arg the acquire argument
+ */
+ private void doAcquireInterruptibly(long arg)
+ throws InterruptedException {
+ final Node node = addWaiter(Node.EXCLUSIVE);
+ try {
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head && tryAcquire(arg)) {
+ setHead(node);
+ p.next = null; // help GC
+ return;
+ }
+ if (shouldParkAfterFailedAcquire(p, node) &&
+ parkAndCheckInterrupt())
+ break;
+ }
+ } catch (RuntimeException ex) {
+ cancelAcquire(node);
+ throw ex;
+ }
+ // Arrive here only if interrupted
+ cancelAcquire(node);
+ throw new InterruptedException();
+ }
+
+ /**
+ * 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);
+ try {
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head && tryAcquire(arg)) {
+ setHead(node);
+ p.next = null; // help GC
+ return true;
+ }
+ if (nanosTimeout <= 0) {
+ cancelAcquire(node);
+ return false;
+ }
+ if (nanosTimeout > spinForTimeoutThreshold &&
+ shouldParkAfterFailedAcquire(p, node))
+ LockSupport.parkNanos(this, nanosTimeout);
+ long now = System.nanoTime();
+ nanosTimeout -= now - lastTime;
+ lastTime = now;
+ if (Thread.interrupted())
+ break;
+ }
+ } catch (RuntimeException ex) {
+ cancelAcquire(node);
+ throw ex;
+ }
+ // Arrive here only if interrupted
+ cancelAcquire(node);
+ throw new InterruptedException();
+ }
+
+ /**
+ * Acquires in shared uninterruptible mode.
+ * @param arg the acquire argument
+ */
+ private void doAcquireShared(long arg) {
+ final Node node = addWaiter(Node.SHARED);
+ 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();
+ return;
+ }
+ }
+ if (shouldParkAfterFailedAcquire(p, node) &&
+ parkAndCheckInterrupt())
+ interrupted = true;
+ }
+ } catch (RuntimeException ex) {
+ cancelAcquire(node);
+ throw ex;
+ }
+ }
+
+ /**
+ * Acquires in shared interruptible mode.
+ * @param arg the acquire argument
+ */
+ private void doAcquireSharedInterruptibly(long arg)
+ throws InterruptedException {
+ final Node node = addWaiter(Node.SHARED);
+ 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
+ return;
+ }
+ }
+ if (shouldParkAfterFailedAcquire(p, node) &&
+ parkAndCheckInterrupt())
+ break;
+ }
+ } catch (RuntimeException ex) {
+ cancelAcquire(node);
+ throw ex;
+ }
+ // Arrive here only if interrupted
+ cancelAcquire(node);
+ throw new InterruptedException();
+ }
+
+ /**
+ * 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);
+ 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
+ return true;
+ }
+ }
+ if (nanosTimeout <= 0) {
+ cancelAcquire(node);
+ return false;
+ }
+ if (nanosTimeout > spinForTimeoutThreshold &&
+ shouldParkAfterFailedAcquire(p, node))
+ LockSupport.parkNanos(this, nanosTimeout);
+ long now = System.nanoTime();
+ nanosTimeout -= now - lastTime;
+ lastTime = now;
+ if (Thread.interrupted())
+ break;
+ }
+ } catch (RuntimeException ex) {
+ cancelAcquire(node);
+ throw ex;
+ }
+ // Arrive here only if interrupted
+ cancelAcquire(node);
+ throw new InterruptedException();
+ }
+
+ // 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)) {
+ Node h = head;
+ if (h != null && h.waitStatus != 0)
+ unparkSuccessor(h);
+ 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 h.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;
+ }
+
+ /**
+ * Return {@code true} if the apparent first queued thread, if one
+ * exists, is not waiting in exclusive mode. Used only as a heuristic
+ * in ReentrantReadWriteLock.
+ */
+ final boolean apparentlyFirstQueuedIsExclusive() {
+ Node h, s;
+ return ((h = head) != null && (s = h.next) != null &&
+ s.nextWaiter != Node.SHARED);
+ }
+
+ /**
+ * Return {@code true} if the queue is empty or if the given thread
+ * is at the head of the queue. This is reliable only if
+ * <tt>current</tt> is actually Thread.currentThread() of caller.
+ */
+ final boolean isFirst(Thread current) {
+ Node h, s;
+ return ((h = head) == null ||
+ ((s = h.next) != null && s.thread == current) ||
+ fullIsFirst(current));
+ }
+
+ final boolean fullIsFirst(Thread current) {
+ // same idea as fullGetFirstQueuedThread
+ Node h, s;
+ Thread firstThread = null;
+ if (((h = head) != null && (s = h.next) != null &&
+ s.prev == head && (firstThread = s.thread) != null))
+ return firstThread == current;
+ Node t = tail;
+ while (t != null && t != head) {
+ Thread tt = t.thread;
+ if (tt != null)
+ firstThread = tt;
+ t = t.prev;
+ }
+ return firstThread == current || firstThread == null;
+ }
+
+
+ // 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 c = p.waitStatus;
+ if (c > 0 || !compareAndSetWaitStatus(p, c, 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) {
+ try {
+ long savedState = getState();
+ if (release(savedState))
+ return savedState;
+ } catch (RuntimeException ex) {
+ node.waitStatus = Node.CANCELLED;
+ throw ex;
+ }
+ // reach here if release fails
+ node.waitStatus = Node.CANCELLED;
+ throw new IllegalMonitorStateException();
+ }
+
+ // 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 node = new Node(Thread.currentThread(), Node.CONDITION);
+ Node t = lastWaiter;
+ 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);
+ }
+
+ /**
+ * Returns true if given node is on this condition queue.
+ * Call only when holding lock.
+ */
+ private boolean isOnConditionQueue(Node node) {
+ return node.next != null || node == lastWaiter;
+ }
+
+ /**
+ * Unlinks a cancelled waiter node from condition queue. This
+ * is called when cancellation occurred during condition wait,
+ * not lock wait, and is called only after lock has been
+ * re-acquired by a cancelled waiter and the node is not known
+ * to already have been dequeued. It 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.
+ */
+ private void unlinkCancelledWaiter(Node node) {
+ Node t = firstWaiter;
+ Node trail = null;
+ while (t != null) {
+ if (t == node) {
+ Node next = t.nextWaiter;
+ if (trail == null)
+ firstWaiter = next;
+ else
+ trail.nextWaiter = next;
+ if (lastWaiter == node)
+ lastWaiter = trail;
+ break;
+ }
+ trail = t;
+ t = t.nextWaiter;
+ }
+ }
+
+ // 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 exception
+ * </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 (isOnConditionQueue(node))
+ unlinkCancelledWaiter(node);
+ 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 (isOnConditionQueue(node))
+ unlinkCancelledWaiter(node);
+ 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 (isOnConditionQueue(node))
+ unlinkCancelledWaiter(node);
+ 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;
+ }
+ 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 (isOnConditionQueue(node))
+ unlinkCancelledWaiter(node);
+ 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;
+
+ 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"));
+
+ } 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);
+ }
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/locks/AbstractQueuedSynchronizer.java b/libjava/classpath/external/jsr166/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
new file mode 100644
index 000000000..647f4fcbc
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
@@ -0,0 +1,2159 @@
+/*
+ * 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;
+
+/**
+ * Provides a framework for implementing blocking locks and related
+ * synchronizers (semaphores, events, etc) that rely on
+ * first-in-first-out (FIFO) wait queues. This class is designed to
+ * be a useful basis for most kinds of synchronizers that rely on a
+ * single atomic <tt>int</tt> value to represent state. Subclasses
+ * must define the protected methods that change this state, and which
+ * define what that state means in terms of this object being acquired
+ * or released. Given these, the other methods in this class carry
+ * out all queuing and blocking mechanics. Subclasses can maintain
+ * other state fields, but only the atomically updated <tt>int</tt>
+ * value manipulated using methods {@link #getState}, {@link
+ * #setState} and {@link #compareAndSetState} is tracked with respect
+ * to synchronization.
+ *
+ * <p>Subclasses should be defined as non-public internal helper
+ * classes that are used to implement the synchronization properties
+ * of their enclosing class. Class
+ * <tt>AbstractQueuedSynchronizer</tt> does not implement any
+ * synchronization interface. Instead it defines methods such as
+ * {@link #acquireInterruptibly} that can be invoked as
+ * appropriate by concrete locks and related synchronizers to
+ * implement their public methods.
+ *
+ * <p>This class supports either or both a default <em>exclusive</em>
+ * mode and a <em>shared</em> mode. When acquired in exclusive mode,
+ * attempted acquires by other threads cannot succeed. Shared mode
+ * acquires by multiple threads may (but need not) succeed. This class
+ * does not &quot;understand&quot; these differences except in the
+ * mechanical sense that when a shared mode acquire succeeds, the next
+ * waiting thread (if one exists) must also determine whether it can
+ * acquire as well. Threads waiting in the different modes share the
+ * same FIFO queue. Usually, implementation subclasses support only
+ * one of these modes, but both can come into play for example in a
+ * {@link ReadWriteLock}. Subclasses that support only exclusive or
+ * only shared modes need not define the methods supporting the unused mode.
+ *
+ * <p>This class defines a nested {@link ConditionObject} class that
+ * can be used as a {@link Condition} implementation by subclasses
+ * supporting exclusive mode for which method {@link
+ * #isHeldExclusively} reports whether synchronization is exclusively
+ * held with respect to the current thread, method {@link #release}
+ * invoked with the current {@link #getState} value fully releases
+ * this object, and {@link #acquire}, given this saved state value,
+ * eventually restores this object to its previous acquired state. No
+ * <tt>AbstractQueuedSynchronizer</tt> method otherwise creates such a
+ * condition, so if this constraint cannot be met, do not use it. The
+ * behavior of {@link ConditionObject} depends of course on the
+ * semantics of its synchronizer implementation.
+ *
+ * <p>This class provides inspection, instrumentation, and monitoring
+ * methods for the internal queue, as well as similar methods for
+ * condition objects. These can be exported as desired into classes
+ * using an <tt>AbstractQueuedSynchronizer</tt> for their
+ * synchronization mechanics.
+ *
+ * <p>Serialization of this class stores only the underlying atomic
+ * integer maintaining state, so deserialized objects have empty
+ * thread queues. Typical subclasses requiring serializability will
+ * define a <tt>readObject</tt> method that restores this to a known
+ * initial state upon deserialization.
+ *
+ * <h3>Usage</h3>
+ *
+ * <p>To use this class as the basis of a synchronizer, redefine the
+ * following methods, as applicable, by inspecting and/or modifying
+ * the synchronization state using {@link #getState}, {@link
+ * #setState} and/or {@link #compareAndSetState}:
+ *
+ * <ul>
+ * <li> {@link #tryAcquire}
+ * <li> {@link #tryRelease}
+ * <li> {@link #tryAcquireShared}
+ * <li> {@link #tryReleaseShared}
+ * <li> {@link #isHeldExclusively}
+ *</ul>
+ *
+ * Each of these methods by default throws {@link
+ * UnsupportedOperationException}. Implementations of these methods
+ * must be internally thread-safe, and should in general be short and
+ * not block. Defining these methods is the <em>only</em> supported
+ * 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:
+ *
+ * <pre>
+ * Acquire:
+ * while (!tryAcquire(arg)) {
+ * <em>enqueue thread if it is not already queued</em>;
+ * <em>possibly block current thread</em>;
+ * }
+ *
+ * Release:
+ * if (tryRelease(arg))
+ * <em>unblock the first queued thread</em>;
+ * </pre>
+ *
+ * (Shared mode is similar but may involve cascading signals.)
+ *
+ * <p>Because checks in acquire are invoked before enqueuing, a newly
+ * acquiring thread may <em>barge</em> ahead of others that are
+ * blocked and queued. However, you can, if desired, define
+ * <tt>tryAcquire</tt> and/or <tt>tryAcquireShared</tt> to disable
+ * barging by internally invoking one or more of the inspection
+ * methods. In particular, a strict FIFO lock can define
+ * <tt>tryAcquire</tt> to immediately return <tt>false</tt> if {@link
+ * #getFirstQueuedThread} does not return the current thread. A
+ * normally preferable non-strict fair version can immediately return
+ * <tt>false</tt> only if {@link #hasQueuedThreads} returns
+ * <tt>true</tt> and <tt>getFirstQueuedThread</tt> is not the current
+ * thread; or equivalently, that <tt>getFirstQueuedThread</tt> is both
+ * non-null and not the current thread. Further variations are
+ * possible.
+ *
+ * <p>Throughput and scalability are generally highest for the
+ * default barging (also known as <em>greedy</em>,
+ * <em>renouncement</em>, and <em>convoy-avoidance</em>) strategy.
+ * While this is not guaranteed to be fair or starvation-free, earlier
+ * queued threads are allowed to recontend before later queued
+ * threads, and each recontention has an unbiased chance to succeed
+ * against incoming threads. Also, while acquires do not
+ * &quot;spin&quot; in the usual sense, they may perform multiple
+ * invocations of <tt>tryAcquire</tt> interspersed with other
+ * computations before blocking. This gives most of the benefits of
+ * spins when exclusive synchronization is only briefly held, without
+ * most of the liabilities when it isn't. If so desired, you can
+ * augment this by preceding calls to acquire methods with
+ * "fast-path" checks, possibly prechecking {@link #hasContended}
+ * and/or {@link #hasQueuedThreads} to only do so if the synchronizer
+ * is likely not to be contended.
+ *
+ * <p>This class provides an efficient and scalable basis for
+ * synchronization in part by specializing its range of use to
+ * synchronizers that can rely on <tt>int</tt> state, acquire, and
+ * release parameters, and an internal FIFO wait queue. When this does
+ * not suffice, you can build synchronizers from a lower level using
+ * {@link java.util.concurrent.atomic atomic} classes, your own custom
+ * {@link java.util.Queue} classes, and {@link LockSupport} blocking
+ * support.
+ *
+ * <h3>Usage Examples</h3>
+ *
+ * <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. 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>
+ * class Mutex implements Lock, java.io.Serializable {
+ *
+ * // Our internal helper class
+ * private static class Sync extends AbstractQueuedSynchronizer {
+ * // Report whether in locked state
+ * protected boolean isHeldExclusively() {
+ * return getState() == 1;
+ * }
+ *
+ * // Acquire the lock if state is zero
+ * public boolean tryAcquire(int acquires) {
+ * assert acquires == 1; // Otherwise unused
+ * 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;
+ * }
+ *
+ * // Provide a Condition
+ * Condition newCondition() { return new ConditionObject(); }
+ *
+ * // Deserialize properly
+ * private void readObject(ObjectInputStream s)
+ * throws IOException, ClassNotFoundException {
+ * s.defaultReadObject();
+ * setState(0); // reset to unlocked state
+ * }
+ * }
+ *
+ * // The sync object does all the hard work. We just forward to it.
+ * private final Sync sync = new Sync();
+ *
+ * public void lock() { sync.acquire(1); }
+ * public boolean tryLock() { return sync.tryAcquire(1); }
+ * public void unlock() { sync.release(1); }
+ * public Condition newCondition() { return sync.newCondition(); }
+ * public boolean isLocked() { return sync.isHeldExclusively(); }
+ * public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }
+ * public void lockInterruptibly() throws InterruptedException {
+ * sync.acquireInterruptibly(1);
+ * }
+ * public boolean tryLock(long timeout, TimeUnit unit)
+ * throws InterruptedException {
+ * return sync.tryAcquireNanos(1, unit.toNanos(timeout));
+ * }
+ * }
+ * </pre>
+ *
+ * <p>Here is a latch class that is like a {@link CountDownLatch}
+ * except that it only requires a single <tt>signal</tt> to
+ * fire. Because a latch is non-exclusive, it uses the <tt>shared</tt>
+ * acquire and release methods.
+ *
+ * <pre>
+ * class BooleanLatch {
+ *
+ * private static class Sync extends AbstractQueuedSynchronizer {
+ * boolean isSignalled() { return getState() != 0; }
+ *
+ * protected int tryAcquireShared(int ignore) {
+ * return isSignalled()? 1 : -1;
+ * }
+ *
+ * protected boolean tryReleaseShared(int ignore) {
+ * setState(1);
+ * return true;
+ * }
+ * }
+ *
+ * private final Sync sync = new Sync();
+ * public boolean isSignalled() { return sync.isSignalled(); }
+ * public void signal() { sync.releaseShared(1); }
+ * public void await() throws InterruptedException {
+ * sync.acquireSharedInterruptibly(1);
+ * }
+ * }
+ * </pre>
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public abstract class AbstractQueuedSynchronizer
+ extends AbstractOwnableSynchronizer
+ implements java.io.Serializable {
+
+ private static final long serialVersionUID = 7373984972572414691L;
+
+ /**
+ * Creates a new <tt>AbstractQueuedSynchronizer</tt> instance
+ * with initial synchronization state of zero.
+ */
+ protected AbstractQueuedSynchronizer() { }
+
+ /**
+ * 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.
+ *
+ * <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 {
+ /** 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;
+ /** 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;
+
+ /**
+ * 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. (Use of this value here
+ * has nothing to do with the other uses
+ * of the field, but simplifies mechanics.)
+ * 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 only using
+ * CAS.
+ */
+ 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 once during enqueuing, and
+ * nulled out (for sake of GC) when no longer needed. Upon
+ * cancellation, we cannot adjust this field, but can notice
+ * status and bypass the node if cancelled. 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.
+ */
+ 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.
+ * @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 int 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 int 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(int 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(int expect, int update) {
+ // See below for intrinsics setup to support this
+ return unsafe.compareAndSwapInt(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
+ Node h = new Node(); // Dummy header
+ h.next = node;
+ node.prev = h;
+ if (compareAndSetHead(h)) {
+ tail = node;
+ return h;
+ }
+ }
+ else {
+ node.prev = t;
+ if (compareAndSetTail(t, node)) {
+ t.next = node;
+ return t;
+ }
+ }
+ }
+ }
+
+ /**
+ * Creates and enqueues node for given thread and mode.
+ *
+ * @param current the thread
+ * @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) {
+ /*
+ * Try to clear status in anticipation of signalling. It is
+ * OK if this fails or if status is changed by waiting thread.
+ */
+ compareAndSetWaitStatus(node, Node.SIGNAL, 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);
+ }
+
+ /**
+ * Sets head of queue, and checks if successor may be waiting
+ * in shared mode, if so propagating if propagate > 0.
+ *
+ * @param pred the node holding waitStatus for node
+ * @param node the node
+ * @param propagate the return value from a tryAcquireShared
+ */
+ private void setHeadAndPropagate(Node node, int propagate) {
+ setHead(node);
+ if (propagate > 0 && node.waitStatus != 0) {
+ /*
+ * Don't bother fully figuring out successor. If it
+ * looks null, call unparkSuccessor anyway to be safe.
+ */
+ Node s = node.next;
+ if (s == null || s.isShared())
+ unparkSuccessor(node);
+ }
+ }
+
+ // Utilities for various versions of acquire
+
+ /**
+ * Cancels an ongoing attempt to acquire.
+ *
+ * @param node the node
+ */
+ private void cancelAcquire(Node node) {
+ if (node != null) { // Ignore if node doesn't exist
+ node.thread = null;
+ // Can use unconditional write instead of CAS here
+ node.waitStatus = Node.CANCELLED;
+ unparkSuccessor(node);
+ }
+ }
+
+ /**
+ * 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 s = pred.waitStatus;
+ if (s < 0)
+ /*
+ * This node has already set status asking a release
+ * to signal it, so it can safely park
+ */
+ return true;
+ if (s > 0)
+ /*
+ * Predecessor was cancelled. Move up to its predecessor
+ * and indicate retry.
+ */
+ node.prev = pred.prev;
+ else
+ /*
+ * 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, 0, 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, int arg) {
+ try {
+ boolean interrupted = false;
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head && tryAcquire(arg)) {
+ setHead(node);
+ p.next = null; // help GC
+ return interrupted;
+ }
+ if (shouldParkAfterFailedAcquire(p, node) &&
+ parkAndCheckInterrupt())
+ interrupted = true;
+ }
+ } catch (RuntimeException ex) {
+ cancelAcquire(node);
+ throw ex;
+ }
+ }
+
+ /**
+ * Acquires in exclusive interruptible mode.
+ * @param arg the acquire argument
+ */
+ private void doAcquireInterruptibly(int arg)
+ throws InterruptedException {
+ final Node node = addWaiter(Node.EXCLUSIVE);
+ try {
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head && tryAcquire(arg)) {
+ setHead(node);
+ p.next = null; // help GC
+ return;
+ }
+ if (shouldParkAfterFailedAcquire(p, node) &&
+ parkAndCheckInterrupt())
+ break;
+ }
+ } catch (RuntimeException ex) {
+ cancelAcquire(node);
+ throw ex;
+ }
+ // Arrive here only if interrupted
+ cancelAcquire(node);
+ throw new InterruptedException();
+ }
+
+ /**
+ * Acquires in exclusive timed mode.
+ *
+ * @param arg the acquire argument
+ * @param nanosTimeout max wait time
+ * @return {@code true} if acquired
+ */
+ private boolean doAcquireNanos(int arg, long nanosTimeout)
+ throws InterruptedException {
+ long lastTime = System.nanoTime();
+ final Node node = addWaiter(Node.EXCLUSIVE);
+ try {
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head && tryAcquire(arg)) {
+ setHead(node);
+ p.next = null; // help GC
+ return true;
+ }
+ if (nanosTimeout <= 0) {
+ cancelAcquire(node);
+ return false;
+ }
+ if (nanosTimeout > spinForTimeoutThreshold &&
+ shouldParkAfterFailedAcquire(p, node))
+ LockSupport.parkNanos(this, nanosTimeout);
+ long now = System.nanoTime();
+ nanosTimeout -= now - lastTime;
+ lastTime = now;
+ if (Thread.interrupted())
+ break;
+ }
+ } catch (RuntimeException ex) {
+ cancelAcquire(node);
+ throw ex;
+ }
+ // Arrive here only if interrupted
+ cancelAcquire(node);
+ throw new InterruptedException();
+ }
+
+ /**
+ * Acquires in shared uninterruptible mode.
+ * @param arg the acquire argument
+ */
+ private void doAcquireShared(int arg) {
+ final Node node = addWaiter(Node.SHARED);
+ try {
+ boolean interrupted = false;
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head) {
+ int r = tryAcquireShared(arg);
+ if (r >= 0) {
+ setHeadAndPropagate(node, r);
+ p.next = null; // help GC
+ if (interrupted)
+ selfInterrupt();
+ return;
+ }
+ }
+ if (shouldParkAfterFailedAcquire(p, node) &&
+ parkAndCheckInterrupt())
+ interrupted = true;
+ }
+ } catch (RuntimeException ex) {
+ cancelAcquire(node);
+ throw ex;
+ }
+ }
+
+ /**
+ * Acquires in shared interruptible mode.
+ * @param arg the acquire argument
+ */
+ private void doAcquireSharedInterruptibly(int arg)
+ throws InterruptedException {
+ final Node node = addWaiter(Node.SHARED);
+ try {
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head) {
+ int r = tryAcquireShared(arg);
+ if (r >= 0) {
+ setHeadAndPropagate(node, r);
+ p.next = null; // help GC
+ return;
+ }
+ }
+ if (shouldParkAfterFailedAcquire(p, node) &&
+ parkAndCheckInterrupt())
+ break;
+ }
+ } catch (RuntimeException ex) {
+ cancelAcquire(node);
+ throw ex;
+ }
+ // Arrive here only if interrupted
+ cancelAcquire(node);
+ throw new InterruptedException();
+ }
+
+ /**
+ * Acquires in shared timed mode.
+ *
+ * @param arg the acquire argument
+ * @param nanosTimeout max wait time
+ * @return {@code true} if acquired
+ */
+ private boolean doAcquireSharedNanos(int arg, long nanosTimeout)
+ throws InterruptedException {
+
+ long lastTime = System.nanoTime();
+ final Node node = addWaiter(Node.SHARED);
+ try {
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head) {
+ int r = tryAcquireShared(arg);
+ if (r >= 0) {
+ setHeadAndPropagate(node, r);
+ p.next = null; // help GC
+ return true;
+ }
+ }
+ if (nanosTimeout <= 0) {
+ cancelAcquire(node);
+ return false;
+ }
+ if (nanosTimeout > spinForTimeoutThreshold &&
+ shouldParkAfterFailedAcquire(p, node))
+ LockSupport.parkNanos(this, nanosTimeout);
+ long now = System.nanoTime();
+ nanosTimeout -= now - lastTime;
+ lastTime = now;
+ if (Thread.interrupted())
+ break;
+ }
+ } catch (RuntimeException ex) {
+ cancelAcquire(node);
+ throw ex;
+ }
+ // Arrive here only if interrupted
+ cancelAcquire(node);
+ throw new InterruptedException();
+ }
+
+ // 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(int 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(int 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 int tryAcquireShared(int 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(int 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(int 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(int 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(int 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(int 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(int 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(int 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(int 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(int arg) {
+ if (tryReleaseShared(arg)) {
+ Node h = head;
+ if (h != null && h.waitStatus != 0)
+ unparkSuccessor(h);
+ 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 h.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;
+ }
+
+ /**
+ * Return {@code true} if the apparent first queued thread, if one
+ * exists, is not waiting in exclusive mode. Used only as a heuristic
+ * in ReentrantReadWriteLock.
+ */
+ final boolean apparentlyFirstQueuedIsExclusive() {
+ Node h, s;
+ return ((h = head) != null && (s = h.next) != null &&
+ s.nextWaiter != Node.SHARED);
+ }
+
+ /**
+ * Return {@code true} if the queue is empty or if the given thread
+ * is at the head of the queue. This is reliable only if
+ * <tt>current</tt> is actually Thread.currentThread() of caller.
+ */
+ final boolean isFirst(Thread current) {
+ Node h, s;
+ return ((h = head) == null ||
+ ((s = h.next) != null && s.thread == current) ||
+ fullIsFirst(current));
+ }
+
+ final boolean fullIsFirst(Thread current) {
+ // same idea as fullGetFirstQueuedThread
+ Node h, s;
+ Thread firstThread = null;
+ if (((h = head) != null && (s = h.next) != null &&
+ s.prev == head && (firstThread = s.thread) != null))
+ return firstThread == current;
+ Node t = tail;
+ while (t != null && t != head) {
+ Thread tt = t.thread;
+ if (tt != null)
+ firstThread = tt;
+ t = t.prev;
+ }
+ return firstThread == current || firstThread == null;
+ }
+
+
+ // 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() {
+ int 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 c = p.waitStatus;
+ if (c > 0 || !compareAndSetWaitStatus(p, c, 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 int fullyRelease(Node node) {
+ try {
+ int savedState = getState();
+ if (release(savedState))
+ return savedState;
+ } catch (RuntimeException ex) {
+ node.waitStatus = Node.CANCELLED;
+ throw ex;
+ }
+ // reach here if release fails
+ node.waitStatus = Node.CANCELLED;
+ throw new IllegalMonitorStateException();
+ }
+
+ // 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
+ * AbstractQueuedSynchronizer} 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>AbstractQueuedSynchronizer</tt>.
+ *
+ * <p>This class is Serializable, but all fields are transient,
+ * so deserialized conditions have no waiters.
+ */
+ 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 node = new Node(Thread.currentThread(), Node.CONDITION);
+ Node t = lastWaiter;
+ 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);
+ }
+
+ /**
+ * Returns true if given node is on this condition queue.
+ * Call only when holding lock.
+ */
+ private boolean isOnConditionQueue(Node node) {
+ return node.next != null || node == lastWaiter;
+ }
+
+ /**
+ * Unlinks a cancelled waiter node from condition queue. This
+ * is called when cancellation occurred during condition wait,
+ * not lock wait, and is called only after lock has been
+ * re-acquired by a cancelled waiter and the node is not known
+ * to already have been dequeued. It 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.
+ */
+ private void unlinkCancelledWaiter(Node node) {
+ Node t = firstWaiter;
+ Node trail = null;
+ while (t != null) {
+ if (t == node) {
+ Node next = t.nextWaiter;
+ if (trail == null)
+ firstWaiter = next;
+ else
+ trail.nextWaiter = next;
+ if (lastWaiter == node)
+ lastWaiter = trail;
+ break;
+ }
+ trail = t;
+ t = t.nextWaiter;
+ }
+ }
+
+ // 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();
+ int 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 exception
+ * </ol>
+ */
+ public final void await() throws InterruptedException {
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ Node node = addConditionWaiter();
+ int 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 (isOnConditionQueue(node))
+ unlinkCancelledWaiter(node);
+ 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();
+ int 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 (isOnConditionQueue(node))
+ unlinkCancelledWaiter(node);
+ 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();
+ int 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 (isOnConditionQueue(node))
+ unlinkCancelledWaiter(node);
+ 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();
+ int savedState = fullyRelease(node);
+ long lastTime = System.nanoTime();
+ boolean timedout = false;
+ int interruptMode = 0;
+ while (!isOnSyncQueue(node)) {
+ if (nanosTimeout <= 0L) {
+ timedout = 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 (isOnConditionQueue(node))
+ unlinkCancelledWaiter(node);
+ 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(AbstractQueuedSynchronizer sync) {
+ return sync == AbstractQueuedSynchronizer.this;
+ }
+
+ /**
+ * Queries whether any threads are waiting on this condition.
+ * Implements {@link AbstractQueuedSynchronizer#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 AbstractQueuedSynchronizer#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 AbstractQueuedSynchronizer#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 AtomicInteger, 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;
+
+ static {
+ try {
+ stateOffset = unsafe.objectFieldOffset
+ (AbstractQueuedSynchronizer.class.getDeclaredField("state"));
+ headOffset = unsafe.objectFieldOffset
+ (AbstractQueuedSynchronizer.class.getDeclaredField("head"));
+ tailOffset = unsafe.objectFieldOffset
+ (AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
+ waitStatusOffset = unsafe.objectFieldOffset
+ (Node.class.getDeclaredField("waitStatus"));
+
+ } 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);
+ }
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/locks/Condition.java b/libjava/classpath/external/jsr166/java/util/concurrent/locks/Condition.java
new file mode 100644
index 000000000..5d24128e1
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/locks/Condition.java
@@ -0,0 +1,435 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.locks;
+import java.util.concurrent.*;
+import java.util.Date;
+
+/**
+ * {@code Condition} factors out the {@code Object} monitor
+ * methods ({@link Object#wait() wait}, {@link Object#notify notify}
+ * and {@link Object#notifyAll notifyAll}) into distinct objects to
+ * give the effect of having multiple wait-sets per object, by
+ * combining them with the use of arbitrary {@link Lock} implementations.
+ * Where a {@code Lock} replaces the use of {@code synchronized} methods
+ * and statements, a {@code Condition} replaces the use of the Object
+ * monitor methods.
+ *
+ * <p>Conditions (also known as <em>condition queues</em> or
+ * <em>condition variables</em>) provide a means for one thread to
+ * suspend execution (to &quot;wait&quot;) until notified by another
+ * thread that some state condition may now be true. Because access
+ * to this shared state information occurs in different threads, it
+ * must be protected, so a lock of some form is associated with the
+ * condition. The key property that waiting for a condition provides
+ * is that it <em>atomically</em> releases the associated lock and
+ * suspends the current thread, just like {@code Object.wait}.
+ *
+ * <p>A {@code Condition} instance is intrinsically bound to a lock.
+ * To obtain a {@code Condition} instance for a particular {@link Lock}
+ * instance use its {@link Lock#newCondition newCondition()} method.
+ *
+ * <p>As an example, suppose we have a bounded buffer which supports
+ * {@code put} and {@code take} methods. If a
+ * {@code take} is attempted on an empty buffer, then the thread will block
+ * until an item becomes available; if a {@code put} is attempted on a
+ * full buffer, then the thread will block until a space becomes available.
+ * We would like to keep waiting {@code put} threads and {@code take}
+ * threads in separate wait-sets so that we can use the optimization of
+ * only notifying a single thread at a time when items or spaces become
+ * available in the buffer. This can be achieved using two
+ * {@link Condition} instances.
+ * <pre>
+ * class BoundedBuffer {
+ * <b>final Lock lock = new ReentrantLock();</b>
+ * final Condition notFull = <b>lock.newCondition(); </b>
+ * final Condition notEmpty = <b>lock.newCondition(); </b>
+ *
+ * final Object[] items = new Object[100];
+ * int putptr, takeptr, count;
+ *
+ * public void put(Object x) throws InterruptedException {
+ * <b>lock.lock();
+ * try {</b>
+ * while (count == items.length)
+ * <b>notFull.await();</b>
+ * items[putptr] = x;
+ * if (++putptr == items.length) putptr = 0;
+ * ++count;
+ * <b>notEmpty.signal();</b>
+ * <b>} finally {
+ * lock.unlock();
+ * }</b>
+ * }
+ *
+ * public Object take() throws InterruptedException {
+ * <b>lock.lock();
+ * try {</b>
+ * while (count == 0)
+ * <b>notEmpty.await();</b>
+ * Object x = items[takeptr];
+ * if (++takeptr == items.length) takeptr = 0;
+ * --count;
+ * <b>notFull.signal();</b>
+ * return x;
+ * <b>} finally {
+ * lock.unlock();
+ * }</b>
+ * }
+ * }
+ * </pre>
+ *
+ * (The {@link java.util.concurrent.ArrayBlockingQueue} class provides
+ * this functionality, so there is no reason to implement this
+ * sample usage class.)
+ *
+ * <p>A {@code Condition} implementation can provide behavior and semantics
+ * that is
+ * different from that of the {@code Object} monitor methods, such as
+ * guaranteed ordering for notifications, or not requiring a lock to be held
+ * when performing notifications.
+ * If an implementation provides such specialized semantics then the
+ * implementation must document those semantics.
+ *
+ * <p>Note that {@code Condition} instances are just normal objects and can
+ * themselves be used as the target in a {@code synchronized} statement,
+ * and can have their own monitor {@link Object#wait wait} and
+ * {@link Object#notify notification} methods invoked.
+ * Acquiring the monitor lock of a {@code Condition} instance, or using its
+ * monitor methods, has no specified relationship with acquiring the
+ * {@link Lock} associated with that {@code Condition} or the use of its
+ * {@linkplain #await waiting} and {@linkplain #signal signalling} methods.
+ * It is recommended that to avoid confusion you never use {@code Condition}
+ * instances in this way, except perhaps within their own implementation.
+ *
+ * <p>Except where noted, passing a {@code null} value for any parameter
+ * will result in a {@link NullPointerException} being thrown.
+ *
+ * <h3>Implementation Considerations</h3>
+ *
+ * <p>When waiting upon a {@code Condition}, a &quot;<em>spurious
+ * wakeup</em>&quot; is permitted to occur, in
+ * general, as a concession to the underlying platform semantics.
+ * This has little practical impact on most application programs as a
+ * {@code Condition} should always be waited upon in a loop, testing
+ * the state predicate that is being waited for. An implementation is
+ * free to remove the possibility of spurious wakeups but it is
+ * recommended that applications programmers always assume that they can
+ * occur and so always wait in a loop.
+ *
+ * <p>The three forms of condition waiting
+ * (interruptible, non-interruptible, and timed) may differ in their ease of
+ * implementation on some platforms and in their performance characteristics.
+ * In particular, it may be difficult to provide these features and maintain
+ * specific semantics such as ordering guarantees.
+ * Further, the ability to interrupt the actual suspension of the thread may
+ * not always be feasible to implement on all platforms.
+ *
+ * <p>Consequently, an implementation is not required to define exactly the
+ * same guarantees or semantics for all three forms of waiting, nor is it
+ * required to support interruption of the actual suspension of the thread.
+ *
+ * <p>An implementation is required to
+ * clearly document the semantics and guarantees provided by each of the
+ * waiting methods, and when an implementation does support interruption of
+ * thread suspension then it must obey the interruption semantics as defined
+ * in this interface.
+ *
+ * <p>As interruption generally implies cancellation, and checks for
+ * interruption are often infrequent, an implementation can favor responding
+ * to an interrupt over normal method return. This is true even if it can be
+ * shown that the interrupt occurred after another action may have unblocked
+ * the thread. An implementation should document this behavior.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public interface Condition {
+
+ /**
+ * Causes the current thread to wait until it is signalled or
+ * {@linkplain Thread#interrupt interrupted}.
+ *
+ * <p>The lock associated with this {@code Condition} is atomically
+ * released and the current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until <em>one</em> of four things happens:
+ * <ul>
+ * <li>Some other thread invokes the {@link #signal} method for this
+ * {@code Condition} and the current thread happens to be chosen as the
+ * thread to be awakened; or
+ * <li>Some other thread invokes the {@link #signalAll} method for this
+ * {@code Condition}; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts} the
+ * current thread, and interruption of thread suspension is supported; or
+ * <li>A &quot;<em>spurious wakeup</em>&quot; occurs.
+ * </ul>
+ *
+ * <p>In all cases, before this method can return the current thread must
+ * re-acquire the lock associated with this condition. When the
+ * thread returns it is <em>guaranteed</em> to hold this lock.
+ *
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+ * and interruption of thread suspension is supported,
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared. It is not specified, in the first
+ * case, whether or not the test for interruption occurs before the lock
+ * is released.
+ *
+ * <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.
+ *
+ * <p>An implementation can favor responding to an interrupt over normal
+ * method return in response to a signal. In that case the implementation
+ * must ensure that the signal is redirected to another waiting thread, if
+ * there is one.
+ *
+ * @throws InterruptedException if the current thread is interrupted
+ * (and interruption of thread suspension is supported)
+ */
+ void await() throws InterruptedException;
+
+ /**
+ * Causes the current thread to wait until it is signalled.
+ *
+ * <p>The lock associated with this condition is atomically
+ * released and the current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until <em>one</em> of three things happens:
+ * <ul>
+ * <li>Some other thread invokes the {@link #signal} method for this
+ * {@code Condition} and the current thread happens to be chosen as the
+ * thread to be awakened; or
+ * <li>Some other thread invokes the {@link #signalAll} method for this
+ * {@code Condition}; or
+ * <li>A &quot;<em>spurious wakeup</em>&quot; occurs.
+ * </ul>
+ *
+ * <p>In all cases, before this method can return the current thread must
+ * re-acquire the lock associated with this condition. When the
+ * thread returns it is <em>guaranteed</em> to hold this lock.
+ *
+ * <p>If the current thread's interrupted status is set when it enters
+ * this method, or it is {@linkplain Thread#interrupt interrupted}
+ * while waiting, it will continue to wait until signalled. When it finally
+ * returns from this method its interrupted status will still
+ * be set.
+ *
+ * <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 awaitUninterruptibly();
+
+ /**
+ * Causes the current thread to wait until it is signalled or interrupted,
+ * or the specified waiting time elapses.
+ *
+ * <p>The lock associated with this condition is atomically
+ * released and the current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until <em>one</em> of five things happens:
+ * <ul>
+ * <li>Some other thread invokes the {@link #signal} method for this
+ * {@code Condition} and the current thread happens to be chosen as the
+ * thread to be awakened; or
+ * <li>Some other thread invokes the {@link #signalAll} method for this
+ * {@code Condition}; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts} the
+ * current thread, and interruption of thread suspension is supported; or
+ * <li>The specified waiting time elapses; or
+ * <li>A &quot;<em>spurious wakeup</em>&quot; occurs.
+ * </ul>
+ *
+ * <p>In all cases, before this method can return the current thread must
+ * re-acquire the lock associated with this condition. When the
+ * thread returns it is <em>guaranteed</em> to hold this lock.
+ *
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+ * and interruption of thread suspension is supported,
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared. It is not specified, in the first
+ * case, whether or not the test for interruption occurs before the lock
+ * is released.
+ *
+ * <p>The method returns an estimate of the number of nanoseconds
+ * remaining to wait given the supplied {@code nanosTimeout}
+ * value upon return, or a value less than or equal to zero if it
+ * timed out. This value can be used to determine whether and how
+ * long to re-wait in cases where the wait returns but an awaited
+ * condition still does not hold. Typical uses of this method take
+ * the following form:
+ *
+ * <pre>
+ * synchronized boolean aMethod(long timeout, TimeUnit unit) {
+ * long nanosTimeout = unit.toNanos(timeout);
+ * while (!conditionBeingWaitedFor) {
+ * if (nanosTimeout &gt; 0)
+ * nanosTimeout = theCondition.awaitNanos(nanosTimeout);
+ * else
+ * return false;
+ * }
+ * // ...
+ * }
+ * </pre>
+ *
+ * <p> Design note: This method requires a nanosecond argument so
+ * as to avoid truncation errors in reporting remaining times.
+ * Such precision loss would make it difficult for programmers to
+ * ensure that total waiting times are not systematically shorter
+ * than specified when re-waits occur.
+ *
+ * <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.
+ *
+ * <p>An implementation can favor responding to an interrupt over normal
+ * method return in response to a signal, or over indicating the elapse
+ * of the specified waiting time. In either case the implementation
+ * must ensure that the signal is redirected to another waiting thread, if
+ * there is one.
+ *
+ * @param nanosTimeout the maximum time to wait, in nanoseconds
+ * @return an estimate of the {@code nanosTimeout} value minus
+ * the time spent waiting upon return from this method.
+ * A positive value may be used as the argument to a
+ * subsequent call to this method to finish waiting out
+ * the desired time. A value less than or equal to zero
+ * indicates that no time remains.
+ * @throws InterruptedException if the current thread is interrupted
+ * (and interruption of thread suspension is supported)
+ */
+ long awaitNanos(long nanosTimeout) throws InterruptedException;
+
+ /**
+ * Causes the current thread to wait until it is signalled or interrupted,
+ * or the specified waiting time elapses. This method is behaviorally
+ * equivalent to:<br>
+ * <pre>
+ * awaitNanos(unit.toNanos(time)) &gt; 0
+ * </pre>
+ * @param time the maximum time to wait
+ * @param unit the time unit of the {@code time} argument
+ * @return {@code false} if the waiting time detectably elapsed
+ * before return from the method, else {@code true}
+ * @throws InterruptedException if the current thread is interrupted
+ * (and interruption of thread suspension is supported)
+ */
+ boolean await(long time, TimeUnit unit) throws InterruptedException;
+
+ /**
+ * Causes the current thread to wait until it is signalled or interrupted,
+ * or the specified deadline elapses.
+ *
+ * <p>The lock associated with this condition is atomically
+ * released and the current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until <em>one</em> of five things happens:
+ * <ul>
+ * <li>Some other thread invokes the {@link #signal} method for this
+ * {@code Condition} and the current thread happens to be chosen as the
+ * thread to be awakened; or
+ * <li>Some other thread invokes the {@link #signalAll} method for this
+ * {@code Condition}; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts} the
+ * current thread, and interruption of thread suspension is supported; or
+ * <li>The specified deadline elapses; or
+ * <li>A &quot;<em>spurious wakeup</em>&quot; occurs.
+ * </ul>
+ *
+ * <p>In all cases, before this method can return the current thread must
+ * re-acquire the lock associated with this condition. When the
+ * thread returns it is <em>guaranteed</em> to hold this lock.
+ *
+ *
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+ * and interruption of thread suspension is supported,
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared. It is not specified, in the first
+ * case, whether or not the test for interruption occurs before the lock
+ * is released.
+ *
+ *
+ * <p>The return value indicates whether the deadline has elapsed,
+ * which can be used as follows:
+ * <pre>
+ * synchronized boolean aMethod(Date deadline) {
+ * boolean stillWaiting = true;
+ * while (!conditionBeingWaitedFor) {
+ * if (stillWaiting)
+ * stillWaiting = theCondition.awaitUntil(deadline);
+ * else
+ * return false;
+ * }
+ * // ...
+ * }
+ * </pre>
+ *
+ * <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.
+ *
+ * <p>An implementation can favor responding to an interrupt over normal
+ * method return in response to a signal, or over indicating the passing
+ * of the specified deadline. In either case the implementation
+ * must ensure that the signal is redirected to another waiting thread, if
+ * there is one.
+ *
+ * @param deadline the absolute time to wait until
+ * @return {@code false} if the deadline has elapsed upon return, else
+ * {@code true}
+ * @throws InterruptedException if the current thread is interrupted
+ * (and interruption of thread suspension is supported)
+ */
+ boolean awaitUntil(Date deadline) throws InterruptedException;
+
+ /**
+ * Wakes up one waiting thread.
+ *
+ * <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}.
+ */
+ void signal();
+
+ /**
+ * Wakes up all waiting threads.
+ *
+ * <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}.
+ */
+ void signalAll();
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/locks/Lock.java b/libjava/classpath/external/jsr166/java/util/concurrent/locks/Lock.java
new file mode 100644
index 000000000..4b9abd665
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/locks/Lock.java
@@ -0,0 +1,327 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.locks;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * {@code Lock} implementations provide more extensive locking
+ * operations than can be obtained using {@code synchronized} methods
+ * and statements. They allow more flexible structuring, may have
+ * quite different properties, and may support multiple associated
+ * {@link Condition} objects.
+ *
+ * <p>A lock is a tool for controlling access to a shared resource by
+ * multiple threads. Commonly, a lock provides exclusive access to a
+ * shared resource: only one thread at a time can acquire the lock and
+ * all access to the shared resource requires that the lock be
+ * acquired first. However, some locks may allow concurrent access to
+ * a shared resource, such as the read lock of a {@link ReadWriteLock}.
+ *
+ * <p>The use of {@code synchronized} methods or statements provides
+ * access to the implicit monitor lock associated with every object, but
+ * forces all lock acquisition and release to occur in a block-structured way:
+ * when multiple locks are acquired they must be released in the opposite
+ * order, and all locks must be released in the same lexical scope in which
+ * they were acquired.
+ *
+ * <p>While the scoping mechanism for {@code synchronized} methods
+ * and statements makes it much easier to program with monitor locks,
+ * and helps avoid many common programming errors involving locks,
+ * there are occasions where you need to work with locks in a more
+ * flexible way. For example, some algorithms for traversing
+ * concurrently accessed data structures require the use of
+ * &quot;hand-over-hand&quot; or &quot;chain locking&quot;: you
+ * acquire the lock of node A, then node B, then release A and acquire
+ * C, then release B and acquire D and so on. Implementations of the
+ * {@code Lock} interface enable the use of such techniques by
+ * allowing a lock to be acquired and released in different scopes,
+ * and allowing multiple locks to be acquired and released in any
+ * order.
+ *
+ * <p>With this increased flexibility comes additional
+ * responsibility. The absence of block-structured locking removes the
+ * automatic release of locks that occurs with {@code synchronized}
+ * methods and statements. In most cases, the following idiom
+ * should be used:
+ *
+ * <pre><tt> Lock l = ...;
+ * l.lock();
+ * try {
+ * // access the resource protected by this lock
+ * } finally {
+ * l.unlock();
+ * }
+ * </tt></pre>
+ *
+ * When locking and unlocking occur in different scopes, care must be
+ * taken to ensure that all code that is executed while the lock is
+ * held is protected by try-finally or try-catch to ensure that the
+ * lock is released when necessary.
+ *
+ * <p>{@code Lock} implementations provide additional functionality
+ * over the use of {@code synchronized} methods and statements by
+ * providing a non-blocking attempt to acquire a lock ({@link
+ * #tryLock()}), an attempt to acquire the lock that can be
+ * interrupted ({@link #lockInterruptibly}, and an attempt to acquire
+ * the lock that can timeout ({@link #tryLock(long, TimeUnit)}).
+ *
+ * <p>A {@code Lock} class can also provide behavior and semantics
+ * that is quite different from that of the implicit monitor lock,
+ * such as guaranteed ordering, non-reentrant usage, or deadlock
+ * detection. If an implementation provides such specialized semantics
+ * then the implementation must document those semantics.
+ *
+ * <p>Note that {@code Lock} instances are just normal objects and can
+ * themselves be used as the target in a {@code synchronized} statement.
+ * Acquiring the
+ * monitor lock of a {@code Lock} instance has no specified relationship
+ * with invoking any of the {@link #lock} methods of that instance.
+ * It is recommended that to avoid confusion you never use {@code Lock}
+ * instances in this way, except within their own implementation.
+ *
+ * <p>Except where noted, passing a {@code null} value for any
+ * parameter will result in a {@link NullPointerException} being
+ * thrown.
+ *
+ * <h3>Memory Synchronization</h3>
+ *
+ * <p>All {@code Lock} implementations <em>must</em> enforce the same
+ * memory synchronization semantics as provided by the built-in monitor
+ * lock, as described in <a href="http://java.sun.com/docs/books/jls/">
+ * The Java Language Specification, Third Edition (17.4 Memory Model)</a>:
+ * <ul>
+ * <li>A successful {@code lock} operation has the same memory
+ * synchronization effects as a successful <em>Lock</em> action.
+ * <li>A successful {@code unlock} operation has the same
+ * memory synchronization effects as a successful <em>Unlock</em> action.
+ * </ul>
+ *
+ * Unsuccessful locking and unlocking operations, and reentrant
+ * locking/unlocking operations, do not require any memory
+ * synchronization effects.
+ *
+ * <h3>Implementation Considerations</h3>
+ *
+ * <p> The three forms of lock acquisition (interruptible,
+ * non-interruptible, and timed) may differ in their performance
+ * characteristics, ordering guarantees, or other implementation
+ * qualities. Further, the ability to interrupt the <em>ongoing</em>
+ * acquisition of a lock may not be available in a given {@code Lock}
+ * class. Consequently, an implementation is not required to define
+ * exactly the same guarantees or semantics for all three forms of
+ * lock acquisition, nor is it required to support interruption of an
+ * ongoing lock acquisition. An implementation is required to clearly
+ * document the semantics and guarantees provided by each of the
+ * locking methods. It must also obey the interruption semantics as
+ * defined in this interface, to the extent that interruption of lock
+ * acquisition is supported: which is either totally, or only on
+ * method entry.
+ *
+ * <p>As interruption generally implies cancellation, and checks for
+ * interruption are often infrequent, an implementation can favor responding
+ * to an interrupt over normal method return. This is true even if it can be
+ * shown that the interrupt occurred after another action may have unblocked
+ * the thread. An implementation should document this behavior.
+ *
+ * @see ReentrantLock
+ * @see Condition
+ * @see ReadWriteLock
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public interface Lock {
+
+ /**
+ * Acquires the lock.
+ *
+ * <p>If the lock is not available then the current thread becomes
+ * disabled for thread scheduling purposes and lies dormant until the
+ * lock has been acquired.
+ *
+ * <p><b>Implementation Considerations</b>
+ *
+ * <p>A {@code Lock} implementation may be able to detect erroneous use
+ * of the lock, such as an invocation that would cause deadlock, and
+ * may throw an (unchecked) exception in such circumstances. The
+ * circumstances and the exception type must be documented by that
+ * {@code Lock} implementation.
+ */
+ void lock();
+
+ /**
+ * Acquires the lock unless the current thread is
+ * {@linkplain Thread#interrupt interrupted}.
+ *
+ * <p>Acquires the lock if it is available and returns immediately.
+ *
+ * <p>If the lock is not available then the current thread becomes
+ * disabled for thread scheduling purposes and lies dormant until
+ * one of two things happens:
+ *
+ * <ul>
+ * <li>The lock is acquired by the current thread; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts} the
+ * current thread, and interruption of lock acquisition is supported.
+ * </ul>
+ *
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while acquiring the
+ * lock, and interruption of lock acquisition is supported,
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ *
+ * <p><b>Implementation Considerations</b>
+ *
+ * <p>The ability to interrupt a lock acquisition in some
+ * implementations may not be possible, and if possible may be an
+ * expensive operation. The programmer should be aware that this
+ * may be the case. An implementation should document when this is
+ * the case.
+ *
+ * <p>An implementation can favor responding to an interrupt over
+ * normal method return.
+ *
+ * <p>A {@code Lock} implementation may be able to detect
+ * erroneous use of the lock, such as an invocation that would
+ * cause deadlock, and may throw an (unchecked) exception in such
+ * circumstances. The circumstances and the exception type must
+ * be documented by that {@code Lock} implementation.
+ *
+ * @throws InterruptedException if the current thread is
+ * interrupted while acquiring the lock (and interruption
+ * of lock acquisition is supported).
+ */
+ void lockInterruptibly() throws InterruptedException;
+
+ /**
+ * Acquires the lock only if it is free at the time of invocation.
+ *
+ * <p>Acquires the lock if it is available and returns immediately
+ * with the value {@code true}.
+ * If the lock is not available then this method will return
+ * immediately with the value {@code false}.
+ *
+ * <p>A typical usage idiom for this method would be:
+ * <pre>
+ * Lock lock = ...;
+ * if (lock.tryLock()) {
+ * try {
+ * // manipulate protected state
+ * } finally {
+ * lock.unlock();
+ * }
+ * } else {
+ * // perform alternative actions
+ * }
+ * </pre>
+ * This usage ensures that the lock is unlocked if it was acquired, and
+ * doesn't try to unlock if the lock was not acquired.
+ *
+ * @return {@code true} if the lock was acquired and
+ * {@code false} otherwise
+ */
+ boolean tryLock();
+
+ /**
+ * Acquires the lock if it is free within the given waiting time and the
+ * current thread has not been {@linkplain Thread#interrupt interrupted}.
+ *
+ * <p>If the lock is available this method returns immediately
+ * with the value {@code true}.
+ * If the lock is not available then
+ * the current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until one of three things happens:
+ * <ul>
+ * <li>The lock is acquired by the current thread; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts} the
+ * current thread, and interruption of lock acquisition is supported; or
+ * <li>The specified waiting time elapses
+ * </ul>
+ *
+ * <p>If the lock is acquired then the value {@code true} is returned.
+ *
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while acquiring
+ * the lock, and interruption of lock acquisition is supported,
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ *
+ * <p>If the specified waiting time elapses then the value {@code false}
+ * is returned.
+ * If the time is
+ * less than or equal to zero, the method will not wait at all.
+ *
+ * <p><b>Implementation Considerations</b>
+ *
+ * <p>The ability to interrupt a lock acquisition in some implementations
+ * may not be possible, and if possible may
+ * be an expensive operation.
+ * The programmer should be aware that this may be the case. An
+ * implementation should document when this is the case.
+ *
+ * <p>An implementation can favor responding to an interrupt over normal
+ * method return, or reporting a timeout.
+ *
+ * <p>A {@code Lock} implementation may be able to detect
+ * erroneous use of the lock, such as an invocation that would cause
+ * deadlock, and may throw an (unchecked) exception in such circumstances.
+ * The circumstances and the exception type must be documented by that
+ * {@code Lock} implementation.
+ *
+ * @param time the maximum time to wait for the lock
+ * @param unit the time unit of the {@code time} argument
+ * @return {@code true} if the lock was acquired and {@code false}
+ * if the waiting time elapsed before the lock was acquired
+ *
+ * @throws InterruptedException if the current thread is interrupted
+ * while acquiring the lock (and interruption of lock
+ * acquisition is supported)
+ */
+ boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
+
+ /**
+ * Releases the lock.
+ *
+ * <p><b>Implementation Considerations</b>
+ *
+ * <p>A {@code Lock} implementation will usually impose
+ * restrictions on which thread can release a lock (typically only the
+ * holder of the lock can release it) and may throw
+ * an (unchecked) exception if the restriction is violated.
+ * Any restrictions and the exception
+ * type must be documented by that {@code Lock} implementation.
+ */
+ void unlock();
+
+ /**
+ * Returns a new {@link Condition} instance that is bound to this
+ * {@code Lock} instance.
+ *
+ * <p>Before waiting on the condition the lock must be held by the
+ * current thread.
+ * A call to {@link Condition#await()} will atomically release the lock
+ * before waiting and re-acquire the lock before the wait returns.
+ *
+ * <p><b>Implementation Considerations</b>
+ *
+ * <p>The exact operation of the {@link Condition} instance depends on
+ * the {@code Lock} implementation and must be documented by that
+ * implementation.
+ *
+ * @return A new {@link Condition} instance for this {@code Lock} instance
+ * @throws UnsupportedOperationException if this {@code Lock}
+ * implementation does not support conditions
+ */
+ Condition newCondition();
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/locks/LockSupport.java b/libjava/classpath/external/jsr166/java/util/concurrent/locks/LockSupport.java
new file mode 100644
index 000000000..28728ae2b
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/locks/LockSupport.java
@@ -0,0 +1,352 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.locks;
+import java.util.concurrent.*;
+import sun.misc.Unsafe;
+
+
+/**
+ * Basic thread blocking primitives for creating locks and other
+ * synchronization classes.
+ *
+ * <p>This class associates, with each thread that uses it, a permit
+ * (in the sense of the {@link java.util.concurrent.Semaphore
+ * Semaphore} class). A call to {@code park} will return immediately
+ * if the permit is available, consuming it in the process; otherwise
+ * it <em>may</em> block. A call to {@code unpark} makes the permit
+ * available, if it was not already available. (Unlike with Semaphores
+ * though, permits do not accumulate. There is at most one.)
+ *
+ * <p>Methods {@code park} and {@code unpark} provide efficient
+ * means of blocking and unblocking threads that do not encounter the
+ * problems that cause the deprecated methods {@code Thread.suspend}
+ * and {@code Thread.resume} to be unusable for such purposes: Races
+ * between one thread invoking {@code park} and another thread trying
+ * to {@code unpark} it will preserve liveness, due to the
+ * permit. Additionally, {@code park} will return if the caller's
+ * thread was interrupted, and timeout versions are supported. The
+ * {@code park} method may also return at any other time, for "no
+ * reason", so in general must be invoked within a loop that rechecks
+ * conditions upon return. In this sense {@code park} serves as an
+ * optimization of a "busy wait" that does not waste as much time
+ * 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}
+ * method is designed for use only in constructions of the form:
+ * <pre>while (!canProceed()) { ... LockSupport.park(this); }</pre>
+ * where neither {@code canProceed} nor any other actions prior to the
+ * call to {@code park} entail locking or blocking. Because only one
+ * permit is associated with each thread, any intermediary uses of
+ * {@code park} could interfere with its intended effects.
+ *
+ * <p><b>Sample Usage.</b> Here is a sketch of a first-in-first-out
+ * non-reentrant lock class:
+ * <pre>{@code
+ * class FIFOMutex {
+ * private final AtomicBoolean locked = new AtomicBoolean(false);
+ * private final Queue<Thread> waiters
+ * = new ConcurrentLinkedQueue<Thread>();
+ *
+ * public void lock() {
+ * boolean wasInterrupted = false;
+ * Thread current = Thread.currentThread();
+ * waiters.add(current);
+ *
+ * // Block while not first in queue or cannot acquire lock
+ * while (waiters.peek() != current ||
+ * !locked.compareAndSet(false, true)) {
+ * LockSupport.park(this);
+ * if (Thread.interrupted()) // ignore interrupts while waiting
+ * wasInterrupted = true;
+ * }
+ *
+ * waiters.remove();
+ * if (wasInterrupted) // reassert interrupt status on exit
+ * current.interrupt();
+ * }
+ *
+ * public void unlock() {
+ * locked.set(false);
+ * LockSupport.unpark(waiters.peek());
+ * }
+ * }}</pre>
+ */
+
+public class LockSupport {
+ private LockSupport() {} // Cannot be instantiated.
+
+ // Hotspot implementation via intrinsics API
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ 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
+ * was not already available. If the thread was blocked on
+ * {@code park} then it will unblock. Otherwise, its next call
+ * to {@code park} is guaranteed not to block. This operation
+ * is not guaranteed to have any effect at all if the given
+ * thread has not been started.
+ *
+ * @param thread the thread to unpark, or {@code null}, in which case
+ * this operation has no effect
+ */
+ public static void unpark(Thread thread) {
+ if (thread != null)
+ unsafe.unpark(thread);
+ }
+
+ /**
+ * 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
+ * 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.
+ */
+ public static void park() {
+ unsafe.park(false, 0L);
+ }
+
+ /**
+ * 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 nanos the maximum number of nanoseconds to wait
+ */
+ public static void parkNanos(long nanos) {
+ if (nanos > 0)
+ unsafe.park(false, nanos);
+ }
+
+ /**
+ * 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 deadline the absolute time, in milliseconds from the Epoch,
+ * to wait until
+ */
+ public static void parkUntil(long deadline) {
+ unsafe.park(true, deadline);
+ }
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/locks/ReadWriteLock.java b/libjava/classpath/external/jsr166/java/util/concurrent/locks/ReadWriteLock.java
new file mode 100644
index 000000000..484f68d15
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/locks/ReadWriteLock.java
@@ -0,0 +1,104 @@
+/*
+ * 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;
+
+/**
+ * A <tt>ReadWriteLock</tt> maintains a pair of associated {@link
+ * Lock locks}, one for read-only operations and one for writing.
+ * The {@link #readLock read lock} may be held simultaneously by
+ * multiple reader threads, so long as there are no writers. The
+ * {@link #writeLock write lock} is exclusive.
+ *
+ * <p>All <tt>ReadWriteLock</tt> implementations must guarantee that
+ * the memory synchronization effects of <tt>writeLock</tt> operations
+ * (as specified in the {@link Lock} interface) also hold with respect
+ * to the associated <tt>readLock</tt>. That is, a thread successfully
+ * acquiring the read lock will see all updates made upon previous
+ * release of the write lock.
+ *
+ * <p>A read-write lock allows for a greater level of concurrency in
+ * accessing shared data than that permitted by a mutual exclusion lock.
+ * It exploits the fact that while only a single thread at a time (a
+ * <em>writer</em> thread) can modify the shared data, in many cases any
+ * number of threads can concurrently read the data (hence <em>reader</em>
+ * threads).
+ * In theory, the increase in concurrency permitted by the use of a read-write
+ * lock will lead to performance improvements over the use of a mutual
+ * exclusion lock. In practice this increase in concurrency will only be fully
+ * realized on a multi-processor, and then only if the access patterns for
+ * the shared data are suitable.
+ *
+ * <p>Whether or not a read-write lock will improve performance over the use
+ * of a mutual exclusion lock depends on the frequency that the data is
+ * read compared to being modified, the duration of the read and write
+ * operations, and the contention for the data - that is, the number of
+ * threads that will try to read or write the data at the same time.
+ * For example, a collection that is initially populated with data and
+ * thereafter infrequently modified, while being frequently searched
+ * (such as a directory of some kind) is an ideal candidate for the use of
+ * a read-write lock. However, if updates become frequent then the data
+ * spends most of its time being exclusively locked and there is little, if any
+ * increase in concurrency. Further, if the read operations are too short
+ * the overhead of the read-write lock implementation (which is inherently
+ * more complex than a mutual exclusion lock) can dominate the execution
+ * cost, particularly as many read-write lock implementations still serialize
+ * all threads through a small section of code. Ultimately, only profiling
+ * and measurement will establish whether the use of a read-write lock is
+ * suitable for your application.
+ *
+ *
+ * <p>Although the basic operation of a read-write lock is straight-forward,
+ * there are many policy decisions that an implementation must make, which
+ * may affect the effectiveness of the read-write lock in a given application.
+ * Examples of these policies include:
+ * <ul>
+ * <li>Determining whether to grant the read lock or the write lock, when
+ * both readers and writers are waiting, at the time that a writer releases
+ * the write lock. Writer preference is common, as writes are expected to be
+ * short and infrequent. Reader preference is less common as it can lead to
+ * lengthy delays for a write if the readers are frequent and long-lived as
+ * expected. Fair, or &quot;in-order&quot; implementations are also possible.
+ *
+ * <li>Determining whether readers that request the read lock while a
+ * reader is active and a writer is waiting, are granted the read lock.
+ * Preference to the reader can delay the writer indefinitely, while
+ * preference to the writer can reduce the potential for concurrency.
+ *
+ * <li>Determining whether the locks are reentrant: can a thread with the
+ * write lock reacquire it? Can it acquire a read lock while holding the
+ * write lock? Is the read lock itself reentrant?
+ *
+ * <li>Can the write lock be downgraded to a read lock without allowing
+ * an intervening writer? Can a read lock be upgraded to a write lock,
+ * in preference to other waiting readers or writers?
+ *
+ * </ul>
+ * You should consider all of these things when evaluating the suitability
+ * of a given implementation for your application.
+ *
+ * @see ReentrantReadWriteLock
+ * @see Lock
+ * @see ReentrantLock
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public interface ReadWriteLock {
+ /**
+ * Returns the lock used for reading.
+ *
+ * @return the lock used for reading.
+ */
+ Lock readLock();
+
+ /**
+ * Returns the lock used for writing.
+ *
+ * @return the lock used for writing.
+ */
+ Lock writeLock();
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/locks/ReentrantLock.java b/libjava/classpath/external/jsr166/java/util/concurrent/locks/ReentrantLock.java
new file mode 100644
index 000000000..4a2fc175c
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/locks/ReentrantLock.java
@@ -0,0 +1,740 @@
+/*
+ * 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.*;
+
+/**
+ * A reentrant mutual exclusion {@link Lock} with the same basic
+ * behavior and semantics as the implicit monitor lock accessed using
+ * {@code synchronized} methods and statements, but with extended
+ * capabilities.
+ *
+ * <p>A {@code ReentrantLock} is <em>owned</em> by the thread last
+ * successfully locking, but not yet unlocking it. A thread invoking
+ * {@code lock} will return, successfully acquiring the lock, when
+ * the lock is not owned by another thread. The method will return
+ * immediately if the current thread already owns the lock. This can
+ * be checked using methods {@link #isHeldByCurrentThread}, and {@link
+ * #getHoldCount}.
+ *
+ * <p>The constructor for this class accepts an optional
+ * <em>fairness</em> parameter. When set {@code true}, under
+ * contention, locks favor granting access to the longest-waiting
+ * thread. Otherwise this lock does not guarantee any particular
+ * access order. Programs using fair locks accessed by many threads
+ * may display lower overall throughput (i.e., are slower; often much
+ * slower) than those using the default setting, but have smaller
+ * variances in times to obtain locks and guarantee lack of
+ * starvation. Note however, that fairness of locks does not guarantee
+ * fairness of thread scheduling. Thus, one of many threads using a
+ * fair lock may obtain it multiple times in succession while other
+ * active threads are not progressing and not currently holding the
+ * lock.
+ * Also note that the untimed {@link #tryLock() tryLock} method does not
+ * honor the fairness setting. It will succeed if the lock
+ * is available even if other threads are waiting.
+ *
+ * <p>It is recommended practice to <em>always</em> immediately
+ * follow a call to {@code lock} with a {@code try} block, most
+ * typically in a before/after construction such as:
+ *
+ * <pre>
+ * class X {
+ * private final ReentrantLock lock = new ReentrantLock();
+ * // ...
+ *
+ * public void m() {
+ * lock.lock(); // block until condition holds
+ * try {
+ * // ... method body
+ * } finally {
+ * lock.unlock()
+ * }
+ * }
+ * }
+ * </pre>
+ *
+ * <p>In addition to implementing the {@link Lock} interface, this
+ * class defines methods {@code isLocked} and
+ * {@code getLockQueueLength}, as well as some associated
+ * {@code protected} access methods that may be useful for
+ * instrumentation and monitoring.
+ *
+ * <p>Serialization of this class behaves in the same way as built-in
+ * locks: a deserialized lock is in the unlocked state, regardless of
+ * its state when serialized.
+ *
+ * <p>This lock supports a maximum of 2147483647 recursive locks by
+ * the same thread. Attempts to exceed this limit result in
+ * {@link Error} throws from locking methods.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class ReentrantLock implements Lock, java.io.Serializable {
+ private static final long serialVersionUID = 7373984872572414699L;
+ /** Synchronizer providing all implementation mechanics */
+ private final Sync sync;
+
+ /**
+ * Base of synchronization control for this lock. Subclassed
+ * into fair and nonfair versions below. Uses AQS state to
+ * represent the number of holds on the lock.
+ */
+ static abstract class Sync extends AbstractQueuedSynchronizer {
+ private static final long serialVersionUID = -5179523762034025860L;
+
+ /**
+ * Performs {@link Lock#lock}. The main reason for subclassing
+ * is to allow fast path for nonfair version.
+ */
+ abstract void lock();
+
+ /**
+ * Performs non-fair tryLock. tryAcquire is
+ * implemented in subclasses, but both need nonfair
+ * try for trylock method.
+ */
+ final boolean nonfairTryAcquire(int acquires) {
+ final Thread current = Thread.currentThread();
+ int c = getState();
+ if (c == 0) {
+ if (compareAndSetState(0, acquires)) {
+ setExclusiveOwnerThread(current);
+ return true;
+ }
+ }
+ else if (current == getExclusiveOwnerThread()) {
+ int nextc = c + acquires;
+ if (nextc < 0) // overflow
+ throw new Error("Maximum lock count exceeded");
+ setState(nextc);
+ return true;
+ }
+ return false;
+ }
+
+ protected final boolean tryRelease(int releases) {
+ int c = getState() - releases;
+ if (Thread.currentThread() != getExclusiveOwnerThread())
+ throw new IllegalMonitorStateException();
+ boolean free = false;
+ if (c == 0) {
+ free = true;
+ setExclusiveOwnerThread(null);
+ }
+ setState(c);
+ return free;
+ }
+
+ protected final boolean isHeldExclusively() {
+ // While we must in general read state before owner,
+ // we don't need to do so to check if current thread is owner
+ return getExclusiveOwnerThread() == Thread.currentThread();
+ }
+
+ final ConditionObject newCondition() {
+ return new ConditionObject();
+ }
+
+ // Methods relayed from outer class
+
+ final Thread getOwner() {
+ return getState() == 0 ? null : getExclusiveOwnerThread();
+ }
+
+ final int getHoldCount() {
+ return isHeldExclusively() ? getState() : 0;
+ }
+
+ final boolean isLocked() {
+ return getState() != 0;
+ }
+
+ /**
+ * Reconstitutes this lock instance from a stream.
+ * @param s the stream
+ */
+ private void readObject(java.io.ObjectInputStream s)
+ throws java.io.IOException, ClassNotFoundException {
+ s.defaultReadObject();
+ setState(0); // reset to unlocked state
+ }
+ }
+
+ /**
+ * Sync object for non-fair locks
+ */
+ final static class NonfairSync extends Sync {
+ private static final long serialVersionUID = 7316153563782823691L;
+
+ /**
+ * Performs lock. Try immediate barge, backing up to normal
+ * acquire on failure.
+ */
+ final void lock() {
+ if (compareAndSetState(0, 1))
+ setExclusiveOwnerThread(Thread.currentThread());
+ else
+ acquire(1);
+ }
+
+ protected final boolean tryAcquire(int acquires) {
+ return nonfairTryAcquire(acquires);
+ }
+ }
+
+ /**
+ * Sync object for fair locks
+ */
+ final static class FairSync extends Sync {
+ private static final long serialVersionUID = -3000897897090466540L;
+
+ final void lock() {
+ acquire(1);
+ }
+
+ /**
+ * Fair version of tryAcquire. Don't grant access unless
+ * recursive call or no waiters or is first.
+ */
+ protected final boolean tryAcquire(int acquires) {
+ final Thread current = Thread.currentThread();
+ int c = getState();
+ if (c == 0) {
+ if (isFirst(current) &&
+ compareAndSetState(0, acquires)) {
+ setExclusiveOwnerThread(current);
+ return true;
+ }
+ }
+ else if (current == getExclusiveOwnerThread()) {
+ int nextc = c + acquires;
+ if (nextc < 0)
+ throw new Error("Maximum lock count exceeded");
+ setState(nextc);
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Creates an instance of {@code ReentrantLock}.
+ * This is equivalent to using {@code ReentrantLock(false)}.
+ */
+ public ReentrantLock() {
+ sync = new NonfairSync();
+ }
+
+ /**
+ * Creates an instance of {@code ReentrantLock} with the
+ * given fairness policy.
+ *
+ * @param fair {@code true} if this lock should use a fair ordering policy
+ */
+ public ReentrantLock(boolean fair) {
+ sync = (fair)? new FairSync() : new NonfairSync();
+ }
+
+ /**
+ * Acquires the lock.
+ *
+ * <p>Acquires the lock if it is not held by another thread and returns
+ * immediately, setting the lock hold count to one.
+ *
+ * <p>If the current thread already holds the lock then the hold
+ * count is incremented by one and the method returns immediately.
+ *
+ * <p>If the lock is held by another thread then the
+ * current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until the lock has been acquired,
+ * at which time the lock hold count is set to one.
+ */
+ public void lock() {
+ sync.lock();
+ }
+
+ /**
+ * Acquires the lock unless the current thread is
+ * {@linkplain Thread#interrupt interrupted}.
+ *
+ * <p>Acquires the lock if it is not held by another thread and returns
+ * immediately, setting the lock hold count to one.
+ *
+ * <p>If the current thread already holds this lock then the hold count
+ * is incremented by one and the method returns immediately.
+ *
+ * <p>If the lock is held by another thread then the
+ * current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until one of two things happens:
+ *
+ * <ul>
+ *
+ * <li>The lock is acquired by the current thread; or
+ *
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts} the
+ * current thread.
+ *
+ * </ul>
+ *
+ * <p>If the lock is acquired by the current thread then the lock hold
+ * count is set to one.
+ *
+ * <p>If the current thread:
+ *
+ * <ul>
+ *
+ * <li>has its interrupted status set on entry to this method; or
+ *
+ * <li>is {@linkplain Thread#interrupt interrupted} while acquiring
+ * the lock,
+ *
+ * </ul>
+ *
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ *
+ * <p>In this implementation, as this method is an explicit
+ * interruption point, preference is given to responding to the
+ * interrupt over normal or reentrant acquisition of the lock.
+ *
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public void lockInterruptibly() throws InterruptedException {
+ sync.acquireInterruptibly(1);
+ }
+
+ /**
+ * Acquires the lock only if it is not held by another thread at the time
+ * of invocation.
+ *
+ * <p>Acquires the lock if it is not held by another thread and
+ * returns immediately with the value {@code true}, setting the
+ * lock hold count to one. Even when this lock has been set to use a
+ * fair ordering policy, a call to {@code tryLock()} <em>will</em>
+ * immediately acquire the lock if it is available, whether or not
+ * other threads are currently waiting for the lock.
+ * This &quot;barging&quot; behavior can be useful in certain
+ * circumstances, even though it breaks fairness. If you want to honor
+ * the fairness setting for this lock, then use
+ * {@link #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
+ * which is almost equivalent (it also detects interruption).
+ *
+ * <p> If the current thread already holds this lock then the hold
+ * count is incremented by one and the method returns {@code true}.
+ *
+ * <p>If the lock is held by another thread then this method will return
+ * immediately with the value {@code false}.
+ *
+ * @return {@code true} if the lock was free and was acquired by the
+ * current thread, or the lock was already held by the current
+ * thread; and {@code false} otherwise
+ */
+ public boolean tryLock() {
+ return sync.nonfairTryAcquire(1);
+ }
+
+ /**
+ * Acquires the lock if it is not held by another thread within the given
+ * waiting time and the current thread has not been
+ * {@linkplain Thread#interrupt interrupted}.
+ *
+ * <p>Acquires the lock if it is not held by another thread and returns
+ * immediately with the value {@code true}, setting the lock hold count
+ * to one. If this lock has been set to use a fair ordering policy then
+ * an available lock <em>will not</em> be acquired if any other threads
+ * are waiting for the lock. This is in contrast to the {@link #tryLock()}
+ * method. If you want a timed {@code tryLock} that does permit barging on
+ * a fair lock then combine the timed and un-timed forms together:
+ *
+ * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
+ * </pre>
+ *
+ * <p>If the current thread
+ * already holds this lock then the hold count is incremented by one and
+ * the method returns {@code true}.
+ *
+ * <p>If the lock is held by another thread then the
+ * current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until one of three things happens:
+ *
+ * <ul>
+ *
+ * <li>The lock is acquired by the current thread; or
+ *
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread; or
+ *
+ * <li>The specified waiting time elapses
+ *
+ * </ul>
+ *
+ * <p>If the lock is acquired then the value {@code true} is returned and
+ * the lock hold count is set to one.
+ *
+ * <p>If the current thread:
+ *
+ * <ul>
+ *
+ * <li>has its interrupted status set on entry to this method; or
+ *
+ * <li>is {@linkplain Thread#interrupt interrupted} while
+ * acquiring the lock,
+ *
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ *
+ * <p>If the specified waiting time elapses then the value {@code false}
+ * is returned. If the time is less than or equal to zero, the method
+ * will not wait at all.
+ *
+ * <p>In this implementation, as this method is an explicit
+ * interruption point, preference is given to responding to the
+ * interrupt over normal or reentrant acquisition of the lock, and
+ * over reporting the elapse of the waiting time.
+ *
+ * @param timeout the time to wait for the lock
+ * @param unit the time unit of the timeout argument
+ * @return {@code true} if the lock was free and was acquired by the
+ * current thread, or the lock was already held by the current
+ * thread; and {@code false} if the waiting time elapsed before
+ * the lock could be acquired
+ * @throws InterruptedException if the current thread is interrupted
+ * @throws NullPointerException if the time unit is null
+ *
+ */
+ public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
+ return sync.tryAcquireNanos(1, unit.toNanos(timeout));
+ }
+
+ /**
+ * Attempts to release this lock.
+ *
+ * <p>If the current thread is the holder of this lock then the hold
+ * count is decremented. If the hold count is now zero then the lock
+ * is released. If the current thread is not the holder of this
+ * lock then {@link IllegalMonitorStateException} is thrown.
+ *
+ * @throws IllegalMonitorStateException if the current thread does not
+ * hold this lock
+ */
+ public void unlock() {
+ sync.release(1);
+ }
+
+ /**
+ * Returns a {@link Condition} instance for use with this
+ * {@link Lock} instance.
+ *
+ * <p>The returned {@link Condition} instance supports the same
+ * usages as do the {@link Object} monitor methods ({@link
+ * Object#wait() wait}, {@link Object#notify notify}, and {@link
+ * Object#notifyAll notifyAll}) when used with the built-in
+ * monitor lock.
+ *
+ * <ul>
+ *
+ * <li>If this lock is not held when any of the {@link Condition}
+ * {@linkplain Condition#await() waiting} or {@linkplain
+ * Condition#signal signalling} methods are called, then an {@link
+ * IllegalMonitorStateException} is thrown.
+ *
+ * <li>When the condition {@linkplain Condition#await() waiting}
+ * methods are called the lock is released and, before they
+ * return, the lock is reacquired and the lock hold count restored
+ * to what it was when the method was called.
+ *
+ * <li>If a thread is {@linkplain Thread#interrupt interrupted}
+ * while waiting then the wait will terminate, an {@link
+ * InterruptedException} will be thrown, and the thread's
+ * interrupted status will be cleared.
+ *
+ * <li> Waiting threads are signalled in FIFO order.
+ *
+ * <li>The ordering of lock reacquisition for threads returning
+ * from waiting methods is the same as for threads initially
+ * acquiring the lock, which is in the default case not specified,
+ * but for <em>fair</em> locks favors those threads that have been
+ * waiting the longest.
+ *
+ * </ul>
+ *
+ * @return the Condition object
+ */
+ public Condition newCondition() {
+ return sync.newCondition();
+ }
+
+ /**
+ * Queries the number of holds on this lock by the current thread.
+ *
+ * <p>A thread has a hold on a lock for each lock action that is not
+ * matched by an unlock action.
+ *
+ * <p>The hold count information is typically only used for testing and
+ * debugging purposes. For example, if a certain section of code should
+ * not be entered with the lock already held then we can assert that
+ * fact:
+ *
+ * <pre>
+ * class X {
+ * ReentrantLock lock = new ReentrantLock();
+ * // ...
+ * public void m() {
+ * assert lock.getHoldCount() == 0;
+ * lock.lock();
+ * try {
+ * // ... method body
+ * } finally {
+ * lock.unlock();
+ * }
+ * }
+ * }
+ * </pre>
+ *
+ * @return the number of holds on this lock by the current thread,
+ * or zero if this lock is not held by the current thread
+ */
+ public int getHoldCount() {
+ return sync.getHoldCount();
+ }
+
+ /**
+ * Queries if this lock is held by the current thread.
+ *
+ * <p>Analogous to the {@link Thread#holdsLock} method for built-in
+ * monitor locks, this method is typically used for debugging and
+ * testing. For example, a method that should only be called while
+ * a lock is held can assert that this is the case:
+ *
+ * <pre>
+ * class X {
+ * ReentrantLock lock = new ReentrantLock();
+ * // ...
+ *
+ * public void m() {
+ * assert lock.isHeldByCurrentThread();
+ * // ... method body
+ * }
+ * }
+ * </pre>
+ *
+ * <p>It can also be used to ensure that a reentrant lock is used
+ * in a non-reentrant manner, for example:
+ *
+ * <pre>
+ * class X {
+ * ReentrantLock lock = new ReentrantLock();
+ * // ...
+ *
+ * public void m() {
+ * assert !lock.isHeldByCurrentThread();
+ * lock.lock();
+ * try {
+ * // ... method body
+ * } finally {
+ * lock.unlock();
+ * }
+ * }
+ * }
+ * </pre>
+ *
+ * @return {@code true} if current thread holds this lock and
+ * {@code false} otherwise
+ */
+ public boolean isHeldByCurrentThread() {
+ return sync.isHeldExclusively();
+ }
+
+ /**
+ * Queries if this lock is held by any thread. This method is
+ * designed for use in monitoring of the system state,
+ * not for synchronization control.
+ *
+ * @return {@code true} if any thread holds this lock and
+ * {@code false} otherwise
+ */
+ public boolean isLocked() {
+ return sync.isLocked();
+ }
+
+ /**
+ * Returns {@code true} if this lock has fairness set true.
+ *
+ * @return {@code true} if this lock has fairness set true
+ */
+ public final boolean isFair() {
+ return sync instanceof FairSync;
+ }
+
+ /**
+ * Returns the thread that currently owns this lock, or
+ * {@code null} if not owned. When this method is called by a
+ * thread that is not the owner, the return value reflects a
+ * best-effort approximation of current lock status. For example,
+ * the owner may be momentarily {@code null} even if there are
+ * threads trying to acquire the lock but have not yet done so.
+ * This method is designed to facilitate construction of
+ * subclasses that provide more extensive lock monitoring
+ * facilities.
+ *
+ * @return the owner, or {@code null} if not owned
+ */
+ protected Thread getOwner() {
+ return sync.getOwner();
+ }
+
+ /**
+ * Queries whether any threads are waiting to acquire this lock. Note that
+ * because cancellations may occur at any time, a {@code true}
+ * return does not guarantee that any other thread will ever
+ * acquire this lock. This method is designed primarily for use in
+ * monitoring of the system state.
+ *
+ * @return {@code true} if there may be other threads waiting to
+ * acquire the lock
+ */
+ public final boolean hasQueuedThreads() {
+ return sync.hasQueuedThreads();
+ }
+
+
+ /**
+ * Queries whether the given thread is waiting to acquire this
+ * lock. Note that because cancellations may occur at any time, a
+ * {@code true} return does not guarantee that this thread
+ * will ever acquire this lock. This method is designed primarily for use
+ * in monitoring of the system state.
+ *
+ * @param thread the thread
+ * @return {@code true} if the given thread is queued waiting for this lock
+ * @throws NullPointerException if the thread is null
+ */
+ public final boolean hasQueuedThread(Thread thread) {
+ return sync.isQueued(thread);
+ }
+
+
+ /**
+ * Returns an estimate of the number of threads waiting to
+ * acquire this lock. The value is only an estimate because the number of
+ * threads may change dynamically while this method traverses
+ * internal data structures. This method is designed for use in
+ * monitoring of the system state, not for synchronization
+ * control.
+ *
+ * @return the estimated number of threads waiting for this lock
+ */
+ public final int getQueueLength() {
+ return sync.getQueueLength();
+ }
+
+ /**
+ * Returns a collection containing threads that may be waiting to
+ * acquire this lock. Because the actual set of threads may change
+ * dynamically while constructing this result, the returned
+ * collection is only a best-effort estimate. The elements of the
+ * returned collection are in no particular order. This method is
+ * designed to facilitate construction of subclasses that provide
+ * more extensive monitoring facilities.
+ *
+ * @return the collection of threads
+ */
+ protected Collection<Thread> getQueuedThreads() {
+ return sync.getQueuedThreads();
+ }
+
+ /**
+ * Queries whether any threads are waiting on the given condition
+ * associated with this lock. Note that because timeouts and
+ * interrupts may occur at any time, a {@code true} return does
+ * not guarantee that a future {@code signal} will awaken any
+ * threads. This method is designed primarily for use in
+ * monitoring of the system state.
+ *
+ * @param condition the condition
+ * @return {@code true} if there are any waiting threads
+ * @throws IllegalMonitorStateException if this lock is not held
+ * @throws IllegalArgumentException if the given condition is
+ * not associated with this lock
+ * @throws NullPointerException if the condition is null
+ */
+ public boolean hasWaiters(Condition condition) {
+ if (condition == null)
+ throw new NullPointerException();
+ if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
+ throw new IllegalArgumentException("not owner");
+ return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
+ }
+
+ /**
+ * Returns an estimate of the number of threads waiting on the
+ * given condition associated with this lock. Note that because
+ * timeouts and interrupts may occur at any time, the estimate
+ * serves only as an upper bound on the actual number of waiters.
+ * This method is designed for use in monitoring of the system
+ * state, not for synchronization control.
+ *
+ * @param condition the condition
+ * @return the estimated number of waiting threads
+ * @throws IllegalMonitorStateException if this lock is not held
+ * @throws IllegalArgumentException if the given condition is
+ * not associated with this lock
+ * @throws NullPointerException if the condition is null
+ */
+ public int getWaitQueueLength(Condition condition) {
+ if (condition == null)
+ throw new NullPointerException();
+ if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
+ throw new IllegalArgumentException("not owner");
+ return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
+ }
+
+ /**
+ * Returns a collection containing those threads that may be
+ * waiting on the given condition associated with this lock.
+ * Because the actual set of threads may change dynamically while
+ * constructing this result, the returned collection is only a
+ * best-effort estimate. The elements of the returned collection
+ * are in no particular order. This method is designed to
+ * facilitate construction of subclasses that provide more
+ * extensive condition monitoring facilities.
+ *
+ * @param condition the condition
+ * @return the collection of threads
+ * @throws IllegalMonitorStateException if this lock is not held
+ * @throws IllegalArgumentException if the given condition is
+ * not associated with this lock
+ * @throws NullPointerException if the condition is null
+ */
+ protected Collection<Thread> getWaitingThreads(Condition condition) {
+ if (condition == null)
+ throw new NullPointerException();
+ if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
+ throw new IllegalArgumentException("not owner");
+ return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
+ }
+
+ /**
+ * Returns a string identifying this lock, as well as its lock state.
+ * The state, in brackets, includes either the String {@code "Unlocked"}
+ * or the String {@code "Locked by"} followed by the
+ * {@linkplain Thread#getName name} of the owning thread.
+ *
+ * @return a string identifying this lock, as well as its lock state
+ */
+ public String toString() {
+ Thread o = sync.getOwner();
+ return super.toString() + ((o == null) ?
+ "[Unlocked]" :
+ "[Locked by thread " + o.getName() + "]");
+ }
+}
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/locks/ReentrantReadWriteLock.java b/libjava/classpath/external/jsr166/java/util/concurrent/locks/ReentrantReadWriteLock.java
new file mode 100644
index 000000000..a6eadff5b
--- /dev/null
+++ b/libjava/classpath/external/jsr166/java/util/concurrent/locks/ReentrantReadWriteLock.java
@@ -0,0 +1,1346 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.locks;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+import java.util.*;
+
+/**
+ * An implementation of {@link ReadWriteLock} supporting similar
+ * semantics to {@link ReentrantLock}.
+ * <p>This class has the following properties:
+ *
+ * <ul>
+ * <li><b>Acquisition order</b>
+ *
+ * <p> This class does not impose a reader or writer preference
+ * ordering for lock access. However, it does support an optional
+ * <em>fairness</em> policy.
+ *
+ * <dl>
+ * <dt><b><i>Non-fair mode (default)</i></b>
+ * <dd>When constructed as non-fair (the default), the order of entry
+ * to the read and write lock is unspecified, subject to reentrancy
+ * constraints. A nonfair lock that is continously contended may
+ * indefinitely postpone one or more reader or writer threads, but
+ * will normally have higher throughput than a fair lock.
+ * <p>
+ *
+ * <dt><b><i>Fair mode</i></b>
+ * <dd> When constructed as fair, threads contend for entry using an
+ * approximately arrival-order policy. When the currently held lock
+ * is released either the longest-waiting single writer thread will
+ * be assigned the write lock, or if there is a group of reader threads
+ * waiting longer than all waiting writer threads, that group will be
+ * assigned the read lock.
+ *
+ * <p>A thread that tries to acquire a fair read lock (non-reentrantly)
+ * will block if either the write lock is held, or there is a waiting
+ * writer thread. The thread will not acquire the read lock until
+ * after the oldest currently waiting writer thread has acquired and
+ * released the write lock. Of course, if a waiting writer abandons
+ * its wait, leaving one or more reader threads as the longest waiters
+ * in the queue with the write lock free, then those readers will be
+ * assigned the read lock.
+ *
+ * <p>A thread that tries to acquire a fair write lock (non-reentrantly)
+ * will block unless both the read lock and write lock are free (which
+ * implies there are no waiting threads). (Note that the non-blocking
+ * {@link ReadLock#tryLock()} and {@link WriteLock#tryLock()} methods
+ * do not honor this fair setting and will acquire the lock if it is
+ * possible, regardless of waiting threads.)
+ * <p>
+ * </dl>
+ *
+ * <li><b>Reentrancy</b>
+ *
+ * <p>This lock allows both readers and writers to reacquire read or
+ * write locks in the style of a {@link ReentrantLock}. Non-reentrant
+ * readers are not allowed until all write locks held by the writing
+ * thread have been released.
+ *
+ * <p>Additionally, a writer can acquire the read lock, but not
+ * vice-versa. Among other applications, reentrancy can be useful
+ * when write locks are held during calls or callbacks to methods that
+ * perform reads under read locks. If a reader tries to acquire the
+ * write lock it will never succeed.
+ *
+ * <li><b>Lock downgrading</b>
+ * <p>Reentrancy also allows downgrading from the write lock to a read lock,
+ * by acquiring the write lock, then the read lock and then releasing the
+ * write lock. However, upgrading from a read lock to the write lock is
+ * <b>not</b> possible.
+ *
+ * <li><b>Interruption of lock acquisition</b>
+ * <p>The read lock and write lock both support interruption during lock
+ * acquisition.
+ *
+ * <li><b>{@link Condition} support</b>
+ * <p>The write lock provides a {@link Condition} implementation that
+ * behaves in the same way, with respect to the write lock, as the
+ * {@link Condition} implementation provided by
+ * {@link ReentrantLock#newCondition} does for {@link ReentrantLock}.
+ * This {@link Condition} can, of course, only be used with the write lock.
+ *
+ * <p>The read lock does not support a {@link Condition} and
+ * {@code readLock().newCondition()} throws
+ * {@code UnsupportedOperationException}.
+ *
+ * <li><b>Instrumentation</b>
+ * <p>This class supports methods to determine whether locks
+ * are held or contended. These methods are designed for monitoring
+ * system state, not for synchronization control.
+ * </ul>
+ *
+ * <p>Serialization of this class behaves in the same way as built-in
+ * locks: a deserialized lock is in the unlocked state, regardless of
+ * its state when serialized.
+ *
+ * <p><b>Sample usages</b>. Here is a code sketch showing how to exploit
+ * reentrancy to perform lock downgrading after updating a cache (exception
+ * handling is elided for simplicity):
+ * <pre>
+ * class CachedData {
+ * Object data;
+ * volatile boolean cacheValid;
+ * ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
+ *
+ * void processCachedData() {
+ * rwl.readLock().lock();
+ * if (!cacheValid) {
+ * // Must release read lock before acquiring write lock
+ * rwl.readLock().unlock();
+ * rwl.writeLock().lock();
+ * // Recheck state because another thread might have acquired
+ * // write lock and changed state before we did.
+ * if (!cacheValid) {
+ * data = ...
+ * cacheValid = true;
+ * }
+ * // Downgrade by acquiring read lock before releasing write lock
+ * rwl.readLock().lock();
+ * rwl.writeLock().unlock(); // Unlock write, still hold read
+ * }
+ *
+ * use(data);
+ * rwl.readLock().unlock();
+ * }
+ * }
+ * </pre>
+ *
+ * ReentrantReadWriteLocks can be used to improve concurrency in some
+ * uses of some kinds of Collections. This is typically worthwhile
+ * only when the collections are expected to be large, accessed by
+ * more reader threads than writer threads, and entail operations with
+ * overhead that outweighs synchronization overhead. For example, here
+ * is a class using a TreeMap that is expected to be large and
+ * concurrently accessed.
+ *
+ * <pre>{@code
+ * class RWDictionary {
+ * private final Map<String, Data> m = new TreeMap<String, Data>();
+ * private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
+ * private final Lock r = rwl.readLock();
+ * private final Lock w = rwl.writeLock();
+ *
+ * public Data get(String key) {
+ * r.lock();
+ * try { return m.get(key); }
+ * finally { r.unlock(); }
+ * }
+ * public String[] allKeys() {
+ * r.lock();
+ * try { return m.keySet().toArray(); }
+ * finally { r.unlock(); }
+ * }
+ * public Data put(String key, Data value) {
+ * w.lock();
+ * try { return m.put(key, value); }
+ * finally { w.unlock(); }
+ * }
+ * public void clear() {
+ * w.lock();
+ * try { m.clear(); }
+ * finally { w.unlock(); }
+ * }
+ * }}</pre>
+ *
+ * <h3>Implementation Notes</h3>
+ *
+ * <p>This lock supports a maximum of 65535 recursive write locks
+ * and 65535 read locks. Attempts to exceed these limits result in
+ * {@link Error} throws from locking methods.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ *
+ */
+public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable {
+ private static final long serialVersionUID = -6992448646407690164L;
+ /** Inner class providing readlock */
+ private final ReentrantReadWriteLock.ReadLock readerLock;
+ /** Inner class providing writelock */
+ private final ReentrantReadWriteLock.WriteLock writerLock;
+ /** Performs all synchronization mechanics */
+ private final Sync sync;
+
+ /**
+ * Creates a new {@code ReentrantReadWriteLock} with
+ * default (nonfair) ordering properties.
+ */
+ public ReentrantReadWriteLock() {
+ this(false);
+ }
+
+ /**
+ * Creates a new {@code ReentrantReadWriteLock} with
+ * the given fairness policy.
+ *
+ * @param fair {@code true} if this lock should use a fair ordering policy
+ */
+ public ReentrantReadWriteLock(boolean fair) {
+ sync = (fair)? new FairSync() : new NonfairSync();
+ readerLock = new ReadLock(this);
+ writerLock = new WriteLock(this);
+ }
+
+ public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }
+ public ReentrantReadWriteLock.ReadLock readLock() { return readerLock; }
+
+ /**
+ * Synchronization implementation for ReentrantReadWriteLock.
+ * Subclassed into fair and nonfair versions.
+ */
+ static abstract class Sync extends AbstractQueuedSynchronizer {
+ private static final long serialVersionUID = 6317671515068378041L;
+
+ /*
+ * Read vs write count extraction constants and functions.
+ * Lock state is logically divided into two shorts: The lower
+ * one representing the exclusive (writer) lock hold count,
+ * and the upper the shared (reader) hold count.
+ */
+
+ static final int SHARED_SHIFT = 16;
+ static final int SHARED_UNIT = (1 << SHARED_SHIFT);
+ static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;
+ static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
+
+ /** Returns the number of shared holds represented in count */
+ static int sharedCount(int c) { return c >>> SHARED_SHIFT; }
+ /** Returns the number of exclusive holds represented in count */
+ static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
+
+ /**
+ * A counter for per-thread read hold counts.
+ * Maintained as a ThreadLocal; cached in cachedHoldCounter
+ */
+ static final class HoldCounter {
+ int count;
+ // Use id, not reference, to avoid garbage retention
+ final long tid = Thread.currentThread().getId();
+ /** Decrement if positive; return previous value */
+ int tryDecrement() {
+ int c = count;
+ if (c > 0)
+ count = c - 1;
+ return c;
+ }
+ }
+
+ /**
+ * ThreadLocal subclass. Easiest to explicitly define for sake
+ * of deserialization mechanics.
+ */
+ static final class ThreadLocalHoldCounter
+ extends ThreadLocal<HoldCounter> {
+ public HoldCounter initialValue() {
+ return new HoldCounter();
+ }
+ }
+
+ /**
+ * The number of read locks held by current thread.
+ * Initialized only in constructor and readObject.
+ */
+ transient ThreadLocalHoldCounter readHolds;
+
+ /**
+ * The hold count of the last thread to successfully acquire
+ * readLock. This saves ThreadLocal lookup in the common case
+ * where the next thread to release is the last one to
+ * acquire. This is non-volatile since it is just used
+ * as a heuristic, and would be great for threads to cache.
+ */
+ transient HoldCounter cachedHoldCounter;
+
+ Sync() {
+ readHolds = new ThreadLocalHoldCounter();
+ setState(getState()); // ensures visibility of readHolds
+ }
+
+ /*
+ * Acquires and releases use the same code for fair and
+ * nonfair locks, but differ in whether/how they allow barging
+ * when queues are non-empty.
+ */
+
+ /**
+ * Return true if a reader thread that is otherwise
+ * eligible for lock should block because of policy
+ * for overtaking other waiting threads.
+ */
+ abstract boolean readerShouldBlock(Thread current);
+
+ /**
+ * Return true if a writer thread that is otherwise
+ * eligible for lock should block because of policy
+ * for overtaking other waiting threads.
+ */
+ abstract boolean writerShouldBlock(Thread current);
+
+ /*
+ * Note that tryRelease and tryAcquire can be called by
+ * Conditions. So it is possible that their arguments contain
+ * both read and write holds that are all released during a
+ * condition wait and re-established in tryAcquire.
+ */
+
+ protected final boolean tryRelease(int releases) {
+ int nextc = getState() - releases;
+ if (Thread.currentThread() != getExclusiveOwnerThread())
+ throw new IllegalMonitorStateException();
+ if (exclusiveCount(nextc) == 0) {
+ setExclusiveOwnerThread(null);
+ setState(nextc);
+ return true;
+ } else {
+ setState(nextc);
+ return false;
+ }
+ }
+
+ protected final boolean tryAcquire(int acquires) {
+ /*
+ * Walkthrough:
+ * 1. if read count nonzero or write count nonzero
+ * and owner is a different thread, fail.
+ * 2. If count would saturate, fail. (This can only
+ * happen if count is already nonzero.)
+ * 3. Otherwise, this thread is eligible for lock if
+ * it is either a reentrant acquire or
+ * queue policy allows it. If so, update state
+ * and set owner.
+ */
+ Thread current = Thread.currentThread();
+ int c = getState();
+ int w = exclusiveCount(c);
+ if (c != 0) {
+ // (Note: if c != 0 and w == 0 then shared count != 0)
+ if (w == 0 || current != getExclusiveOwnerThread())
+ return false;
+ if (w + exclusiveCount(acquires) > MAX_COUNT)
+ throw new Error("Maximum lock count exceeded");
+ }
+ if ((w == 0 && writerShouldBlock(current)) ||
+ !compareAndSetState(c, c + acquires))
+ return false;
+ setExclusiveOwnerThread(current);
+ return true;
+ }
+
+ protected final boolean tryReleaseShared(int unused) {
+ HoldCounter rh = cachedHoldCounter;
+ Thread current = Thread.currentThread();
+ if (rh == null || rh.tid != current.getId())
+ rh = readHolds.get();
+ if (rh.tryDecrement() <= 0)
+ throw new IllegalMonitorStateException();
+ for (;;) {
+ int c = getState();
+ int nextc = c - SHARED_UNIT;
+ if (compareAndSetState(c, nextc))
+ return nextc == 0;
+ }
+ }
+
+ protected final int tryAcquireShared(int unused) {
+ /*
+ * Walkthrough:
+ * 1. If write lock held by another thread, fail
+ * 2. If count saturated, throw error
+ * 3. Otherwise, this thread is eligible for
+ * lock wrt state, so ask if it should block
+ * because of queue policy. If not, try
+ * to grant by CASing state and updating count.
+ * Note that step does not check for reentrant
+ * acquires, which is postponed to full version
+ * to avoid having to check hold count in
+ * the more typical non-reentrant case.
+ * 4. If step 3 fails either because thread
+ * apparently not eligible or CAS fails,
+ * chain to version with full retry loop.
+ */
+ Thread current = Thread.currentThread();
+ int c = getState();
+ if (exclusiveCount(c) != 0 &&
+ getExclusiveOwnerThread() != current)
+ return -1;
+ if (sharedCount(c) == MAX_COUNT)
+ throw new Error("Maximum lock count exceeded");
+ if (!readerShouldBlock(current) &&
+ compareAndSetState(c, c + SHARED_UNIT)) {
+ HoldCounter rh = cachedHoldCounter;
+ if (rh == null || rh.tid != current.getId())
+ cachedHoldCounter = rh = readHolds.get();
+ rh.count++;
+ return 1;
+ }
+ return fullTryAcquireShared(current);
+ }
+
+ /**
+ * Full version of acquire for reads, that handles CAS misses
+ * and reentrant reads not dealt with in tryAcquireShared.
+ */
+ final int fullTryAcquireShared(Thread current) {
+ /*
+ * This code is in part redundant with that in
+ * tryAcquireShared but is simpler overall by not
+ * complicating tryAcquireShared with interactions between
+ * retries and lazily reading hold counts.
+ */
+ HoldCounter rh = cachedHoldCounter;
+ if (rh == null || rh.tid != current.getId())
+ rh = readHolds.get();
+ for (;;) {
+ int c = getState();
+ int w = exclusiveCount(c);
+ if ((w != 0 && getExclusiveOwnerThread() != current) ||
+ ((rh.count | w) == 0 && readerShouldBlock(current)))
+ return -1;
+ if (sharedCount(c) == MAX_COUNT)
+ throw new Error("Maximum lock count exceeded");
+ if (compareAndSetState(c, c + SHARED_UNIT)) {
+ cachedHoldCounter = rh; // cache for release
+ rh.count++;
+ return 1;
+ }
+ }
+ }
+
+ /**
+ * Performs tryLock for write, enabling barging in both modes.
+ * This is identical in effect to tryAcquire except for lack
+ * of calls to writerShouldBlock
+ */
+ final boolean tryWriteLock() {
+ Thread current = Thread.currentThread();
+ int c = getState();
+ if (c != 0) {
+ int w = exclusiveCount(c);
+ if (w == 0 ||current != getExclusiveOwnerThread())
+ return false;
+ if (w == MAX_COUNT)
+ throw new Error("Maximum lock count exceeded");
+ }
+ if (!compareAndSetState(c, c + 1))
+ return false;
+ setExclusiveOwnerThread(current);
+ return true;
+ }
+
+ /**
+ * Performs tryLock for read, enabling barging in both modes.
+ * This is identical in effect to tryAcquireShared except for
+ * lack of calls to readerShouldBlock
+ */
+ final boolean tryReadLock() {
+ Thread current = Thread.currentThread();
+ for (;;) {
+ int c = getState();
+ if (exclusiveCount(c) != 0 &&
+ getExclusiveOwnerThread() != current)
+ return false;
+ if (sharedCount(c) == MAX_COUNT)
+ throw new Error("Maximum lock count exceeded");
+ if (compareAndSetState(c, c + SHARED_UNIT)) {
+ HoldCounter rh = cachedHoldCounter;
+ if (rh == null || rh.tid != current.getId())
+ cachedHoldCounter = rh = readHolds.get();
+ rh.count++;
+ return true;
+ }
+ }
+ }
+
+ protected final boolean isHeldExclusively() {
+ // While we must in general read state before owner,
+ // we don't need to do so to check if current thread is owner
+ return getExclusiveOwnerThread() == Thread.currentThread();
+ }
+
+ // Methods relayed to outer class
+
+ final ConditionObject newCondition() {
+ return new ConditionObject();
+ }
+
+ final Thread getOwner() {
+ // Must read state before owner to ensure memory consistency
+ return ((exclusiveCount(getState()) == 0)?
+ null :
+ getExclusiveOwnerThread());
+ }
+
+ final int getReadLockCount() {
+ return sharedCount(getState());
+ }
+
+ final boolean isWriteLocked() {
+ return exclusiveCount(getState()) != 0;
+ }
+
+ final int getWriteHoldCount() {
+ return isHeldExclusively() ? exclusiveCount(getState()) : 0;
+ }
+
+ final int getReadHoldCount() {
+ return getReadLockCount() == 0? 0 : readHolds.get().count;
+ }
+
+ /**
+ * Reconstitute this lock instance from a stream
+ * @param s the stream
+ */
+ private void readObject(java.io.ObjectInputStream s)
+ throws java.io.IOException, ClassNotFoundException {
+ s.defaultReadObject();
+ readHolds = new ThreadLocalHoldCounter();
+ setState(0); // reset to unlocked state
+ }
+
+ final int getCount() { return getState(); }
+ }
+
+ /**
+ * Nonfair version of Sync
+ */
+ final static class NonfairSync extends Sync {
+ private static final long serialVersionUID = -8159625535654395037L;
+ final boolean writerShouldBlock(Thread current) {
+ return false; // writers can always barge
+ }
+ final boolean readerShouldBlock(Thread current) {
+ /* As a heuristic to avoid indefinite writer starvation,
+ * block if the thread that momentarily appears to be head
+ * of queue, if one exists, is a waiting writer. This is
+ * only a probablistic effect since a new reader will not
+ * block if there is a waiting writer behind other enabled
+ * readers that have not yet drained from the queue.
+ */
+ return apparentlyFirstQueuedIsExclusive();
+ }
+ }
+
+ /**
+ * Fair version of Sync
+ */
+ final static class FairSync extends Sync {
+ private static final long serialVersionUID = -2274990926593161451L;
+ final boolean writerShouldBlock(Thread current) {
+ // only proceed if queue is empty or current thread at head
+ return !isFirst(current);
+ }
+ final boolean readerShouldBlock(Thread current) {
+ // only proceed if queue is empty or current thread at head
+ return !isFirst(current);
+ }
+ }
+
+ /**
+ * The lock returned by method {@link ReentrantReadWriteLock#readLock}.
+ */
+ public static class ReadLock implements Lock, java.io.Serializable {
+ private static final long serialVersionUID = -5992448646407690164L;
+ private final Sync sync;
+
+ /**
+ * Constructor for use by subclasses
+ *
+ * @param lock the outer lock object
+ * @throws NullPointerException if the lock is null
+ */
+ protected ReadLock(ReentrantReadWriteLock lock) {
+ sync = lock.sync;
+ }
+
+ /**
+ * Acquires the read lock.
+ *
+ * <p>Acquires the read lock if the write lock is not held by
+ * another thread and returns immediately.
+ *
+ * <p>If the write lock is held by another thread then
+ * the current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until the read lock has been acquired.
+ */
+ public void lock() {
+ sync.acquireShared(1);
+ }
+
+ /**
+ * Acquires the read lock unless the current thread is
+ * {@linkplain Thread#interrupt interrupted}.
+ *
+ * <p>Acquires the read lock if the write lock is not held
+ * by another thread and returns immediately.
+ *
+ * <p>If the write lock is held by another thread then the
+ * current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until one of two things happens:
+ *
+ * <ul>
+ *
+ * <li>The read lock is acquired by the current thread; or
+ *
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread.
+ *
+ * </ul>
+ *
+ * <p>If the current thread:
+ *
+ * <ul>
+ *
+ * <li>has its interrupted status set on entry to this method; or
+ *
+ * <li>is {@linkplain Thread#interrupt interrupted} while
+ * acquiring the read lock,
+ *
+ * </ul>
+ *
+ * then {@link InterruptedException} is thrown and the current
+ * thread's interrupted status is cleared.
+ *
+ * <p>In this implementation, as this method is an explicit
+ * interruption point, preference is given to responding to
+ * the interrupt over normal or reentrant acquisition of the
+ * lock.
+ *
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public void lockInterruptibly() throws InterruptedException {
+ sync.acquireSharedInterruptibly(1);
+ }
+
+ /**
+ * Acquires the read lock only if the write lock is not held by
+ * another thread at the time of invocation.
+ *
+ * <p>Acquires the read lock if the write lock is not held by
+ * another thread and returns immediately with the value
+ * {@code true}. Even when this lock has been set to use a
+ * fair ordering policy, a call to {@code tryLock()}
+ * <em>will</em> immediately acquire the read lock if it is
+ * available, whether or not other threads are currently
+ * waiting for the read lock. This &quot;barging&quot; behavior
+ * can be useful in certain circumstances, even though it
+ * breaks fairness. If you want to honor the fairness setting
+ * for this lock, then use {@link #tryLock(long, TimeUnit)
+ * tryLock(0, TimeUnit.SECONDS) } which is almost equivalent
+ * (it also detects interruption).
+ *
+ * <p>If the write lock is held by another thread then
+ * this method will return immediately with the value
+ * {@code false}.
+ *
+ * @return {@code true} if the read lock was acquired
+ */
+ public boolean tryLock() {
+ return sync.tryReadLock();
+ }
+
+ /**
+ * Acquires the read lock if the write lock is not held by
+ * another thread within the given waiting time and the
+ * current thread has not been {@linkplain Thread#interrupt
+ * interrupted}.
+ *
+ * <p>Acquires the read lock if the write lock is not held by
+ * another thread and returns immediately with the value
+ * {@code true}. If this lock has been set to use a fair
+ * ordering policy then an available lock <em>will not</em> be
+ * acquired if any other threads are waiting for the
+ * lock. This is in contrast to the {@link #tryLock()}
+ * method. If you want a timed {@code tryLock} that does
+ * permit barging on a fair lock then combine the timed and
+ * un-timed forms together:
+ *
+ * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
+ * </pre>
+ *
+ * <p>If the write lock is held by another thread then the
+ * current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until one of three things happens:
+ *
+ * <ul>
+ *
+ * <li>The read lock is acquired by the current thread; or
+ *
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread; or
+ *
+ * <li>The specified waiting time elapses.
+ *
+ * </ul>
+ *
+ * <p>If the read lock is acquired then the value {@code true} is
+ * returned.
+ *
+ * <p>If the current thread:
+ *
+ * <ul>
+ *
+ * <li>has its interrupted status set on entry to this method; or
+ *
+ * <li>is {@linkplain Thread#interrupt interrupted} while
+ * acquiring the read lock,
+ *
+ * </ul> then {@link InterruptedException} is thrown and the
+ * current thread's interrupted status is cleared.
+ *
+ * <p>If the specified waiting time elapses then the value
+ * {@code false} is returned. If the time is less than or
+ * equal to zero, the method will not wait at all.
+ *
+ * <p>In this implementation, as this method is an explicit
+ * interruption point, preference is given to responding to
+ * the interrupt over normal or reentrant acquisition of the
+ * lock, and over reporting the elapse of the waiting time.
+ *
+ * @param timeout the time to wait for the read lock
+ * @param unit the time unit of the timeout argument
+ * @return {@code true} if the read lock was acquired
+ * @throws InterruptedException if the current thread is interrupted
+ * @throws NullPointerException if the time unit is null
+ *
+ */
+ public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
+ return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
+ }
+
+ /**
+ * Attempts to release this lock.
+ *
+ * <p> If the number of readers is now zero then the lock
+ * is made available for write lock attempts.
+ */
+ public void unlock() {
+ sync.releaseShared(1);
+ }
+
+ /**
+ * Throws {@code UnsupportedOperationException} because
+ * {@code ReadLocks} do not support conditions.
+ *
+ * @throws UnsupportedOperationException always
+ */
+ public Condition newCondition() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns a string identifying this lock, as well as its lock state.
+ * The state, in brackets, includes the String {@code "Read locks ="}
+ * followed by the number of held read locks.
+ *
+ * @return a string identifying this lock, as well as its lock state
+ */
+ public String toString() {
+ int r = sync.getReadLockCount();
+ return super.toString() +
+ "[Read locks = " + r + "]";
+ }
+ }
+
+ /**
+ * The lock returned by method {@link ReentrantReadWriteLock#writeLock}.
+ */
+ public static class WriteLock implements Lock, java.io.Serializable {
+ private static final long serialVersionUID = -4992448646407690164L;
+ private final Sync sync;
+
+ /**
+ * Constructor for use by subclasses
+ *
+ * @param lock the outer lock object
+ * @throws NullPointerException if the lock is null
+ */
+ protected WriteLock(ReentrantReadWriteLock lock) {
+ sync = lock.sync;
+ }
+
+ /**
+ * Acquires the write lock.
+ *
+ * <p>Acquires the write lock if neither the read nor write lock
+ * are held by another thread
+ * and returns immediately, setting the write lock hold count to
+ * one.
+ *
+ * <p>If the current thread already holds the write lock then the
+ * hold count is incremented by one and the method returns
+ * immediately.
+ *
+ * <p>If the lock is held by another thread then the current
+ * thread becomes disabled for thread scheduling purposes and
+ * lies dormant until the write lock has been acquired, at which
+ * time the write lock hold count is set to one.
+ */
+ public void lock() {
+ sync.acquire(1);
+ }
+
+ /**
+ * Acquires the write lock unless the current thread is
+ * {@linkplain Thread#interrupt interrupted}.
+ *
+ * <p>Acquires the write lock if neither the read nor write lock
+ * are held by another thread
+ * and returns immediately, setting the write lock hold count to
+ * one.
+ *
+ * <p>If the current thread already holds this lock then the
+ * hold count is incremented by one and the method returns
+ * immediately.
+ *
+ * <p>If the lock is held by another thread then the current
+ * thread becomes disabled for thread scheduling purposes and
+ * lies dormant until one of two things happens:
+ *
+ * <ul>
+ *
+ * <li>The write lock is acquired by the current thread; or
+ *
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread.
+ *
+ * </ul>
+ *
+ * <p>If the write lock is acquired by the current thread then the
+ * lock hold count is set to one.
+ *
+ * <p>If the current thread:
+ *
+ * <ul>
+ *
+ * <li>has its interrupted status set on entry to this method;
+ * or
+ *
+ * <li>is {@linkplain Thread#interrupt interrupted} while
+ * acquiring the write lock,
+ *
+ * </ul>
+ *
+ * then {@link InterruptedException} is thrown and the current
+ * thread's interrupted status is cleared.
+ *
+ * <p>In this implementation, as this method is an explicit
+ * interruption point, preference is given to responding to
+ * the interrupt over normal or reentrant acquisition of the
+ * lock.
+ *
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public void lockInterruptibly() throws InterruptedException {
+ sync.acquireInterruptibly(1);
+ }
+
+ /**
+ * Acquires the write lock only if it is not held by another thread
+ * at the time of invocation.
+ *
+ * <p>Acquires the write lock if neither the read nor write lock
+ * are held by another thread
+ * and returns immediately with the value {@code true},
+ * setting the write lock hold count to one. Even when this lock has
+ * been set to use a fair ordering policy, a call to
+ * {@code tryLock()} <em>will</em> immediately acquire the
+ * lock if it is available, whether or not other threads are
+ * currently waiting for the write lock. This &quot;barging&quot;
+ * behavior can be useful in certain circumstances, even
+ * though it breaks fairness. If you want to honor the
+ * fairness setting for this lock, then use {@link
+ * #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
+ * which is almost equivalent (it also detects interruption).
+ *
+ * <p> If the current thread already holds this lock then the
+ * hold count is incremented by one and the method returns
+ * {@code true}.
+ *
+ * <p>If the lock is held by another thread then this method
+ * will return immediately with the value {@code false}.
+ *
+ * @return {@code true} if the lock was free and was acquired
+ * by the current thread, or the write lock was already held
+ * by the current thread; and {@code false} otherwise.
+ */
+ public boolean tryLock( ) {
+ return sync.tryWriteLock();
+ }
+
+ /**
+ * Acquires the write lock if it is not held by another thread
+ * within the given waiting time and the current thread has
+ * not been {@linkplain Thread#interrupt interrupted}.
+ *
+ * <p>Acquires the write lock if neither the read nor write lock
+ * are held by another thread
+ * and returns immediately with the value {@code true},
+ * setting the write lock hold count to one. If this lock has been
+ * set to use a fair ordering policy then an available lock
+ * <em>will not</em> be acquired if any other threads are
+ * waiting for the write lock. This is in contrast to the {@link
+ * #tryLock()} method. If you want a timed {@code tryLock}
+ * that does permit barging on a fair lock then combine the
+ * timed and un-timed forms together:
+ *
+ * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
+ * </pre>
+ *
+ * <p>If the current thread already holds this lock then the
+ * hold count is incremented by one and the method returns
+ * {@code true}.
+ *
+ * <p>If the lock is held by another thread then the current
+ * thread becomes disabled for thread scheduling purposes and
+ * lies dormant until one of three things happens:
+ *
+ * <ul>
+ *
+ * <li>The write lock is acquired by the current thread; or
+ *
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread; or
+ *
+ * <li>The specified waiting time elapses
+ *
+ * </ul>
+ *
+ * <p>If the write lock is acquired then the value {@code true} is
+ * returned and the write lock hold count is set to one.
+ *
+ * <p>If the current thread:
+ *
+ * <ul>
+ *
+ * <li>has its interrupted status set on entry to this method;
+ * or
+ *
+ * <li>is {@linkplain Thread#interrupt interrupted} while
+ * acquiring the write lock,
+ *
+ * </ul>
+ *
+ * then {@link InterruptedException} is thrown and the current
+ * thread's interrupted status is cleared.
+ *
+ * <p>If the specified waiting time elapses then the value
+ * {@code false} is returned. If the time is less than or
+ * equal to zero, the method will not wait at all.
+ *
+ * <p>In this implementation, as this method is an explicit
+ * interruption point, preference is given to responding to
+ * the interrupt over normal or reentrant acquisition of the
+ * lock, and over reporting the elapse of the waiting time.
+ *
+ * @param timeout the time to wait for the write lock
+ * @param unit the time unit of the timeout argument
+ *
+ * @return {@code true} if the lock was free and was acquired
+ * by the current thread, or the write lock was already held by the
+ * current thread; and {@code false} if the waiting time
+ * elapsed before the lock could be acquired.
+ *
+ * @throws InterruptedException if the current thread is interrupted
+ * @throws NullPointerException if the time unit is null
+ *
+ */
+ public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
+ return sync.tryAcquireNanos(1, unit.toNanos(timeout));
+ }
+
+ /**
+ * Attempts to release this lock.
+ *
+ * <p>If the current thread is the holder of this lock then
+ * the hold count is decremented. If the hold count is now
+ * zero then the lock is released. If the current thread is
+ * not the holder of this lock then {@link
+ * IllegalMonitorStateException} is thrown.
+ *
+ * @throws IllegalMonitorStateException if the current thread does not
+ * hold this lock.
+ */
+ public void unlock() {
+ sync.release(1);
+ }
+
+ /**
+ * Returns a {@link Condition} instance for use with this
+ * {@link Lock} instance.
+ * <p>The returned {@link Condition} instance supports the same
+ * usages as do the {@link Object} monitor methods ({@link
+ * Object#wait() wait}, {@link Object#notify notify}, and {@link
+ * Object#notifyAll notifyAll}) when used with the built-in
+ * monitor lock.
+ *
+ * <ul>
+ *
+ * <li>If this write lock is not held when any {@link
+ * Condition} method is called then an {@link
+ * IllegalMonitorStateException} is thrown. (Read locks are
+ * held independently of write locks, so are not checked or
+ * affected. However it is essentially always an error to
+ * invoke a condition waiting method when the current thread
+ * has also acquired read locks, since other threads that
+ * could unblock it will not be able to acquire the write
+ * lock.)
+ *
+ * <li>When the condition {@linkplain Condition#await() waiting}
+ * methods are called the write lock is released and, before
+ * they return, the write lock is reacquired and the lock hold
+ * count restored to what it was when the method was called.
+ *
+ * <li>If a thread is {@linkplain Thread#interrupt interrupted} while
+ * waiting then the wait will terminate, an {@link
+ * InterruptedException} will be thrown, and the thread's
+ * interrupted status will be cleared.
+ *
+ * <li> Waiting threads are signalled in FIFO order.
+ *
+ * <li>The ordering of lock reacquisition for threads returning
+ * from waiting methods is the same as for threads initially
+ * acquiring the lock, which is in the default case not specified,
+ * but for <em>fair</em> locks favors those threads that have been
+ * waiting the longest.
+ *
+ * </ul>
+ *
+ * @return the Condition object
+ */
+ public Condition newCondition() {
+ return sync.newCondition();
+ }
+
+ /**
+ * Returns a string identifying this lock, as well as its lock
+ * state. The state, in brackets includes either the String
+ * {@code "Unlocked"} or the String {@code "Locked by"}
+ * followed by the {@linkplain Thread#getName name} of the owning thread.
+ *
+ * @return a string identifying this lock, as well as its lock state
+ */
+ public String toString() {
+ Thread o = sync.getOwner();
+ return super.toString() + ((o == null) ?
+ "[Unlocked]" :
+ "[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
+
+ /**
+ * Returns {@code true} if this lock has fairness set true.
+ *
+ * @return {@code true} if this lock has fairness set true
+ */
+ public final boolean isFair() {
+ return sync instanceof FairSync;
+ }
+
+ /**
+ * Returns the thread that currently owns the write lock, or
+ * {@code null} if not owned. When this method is called by a
+ * thread that is not the owner, the return value reflects a
+ * best-effort approximation of current lock status. For example,
+ * the owner may be momentarily {@code null} even if there are
+ * threads trying to acquire the lock but have not yet done so.
+ * This method is designed to facilitate construction of
+ * subclasses that provide more extensive lock monitoring
+ * facilities.
+ *
+ * @return the owner, or {@code null} if not owned
+ */
+ protected Thread getOwner() {
+ return sync.getOwner();
+ }
+
+ /**
+ * Queries the number of read locks held for this lock. This
+ * method is designed for use in monitoring system state, not for
+ * synchronization control.
+ * @return the number of read locks held.
+ */
+ public int getReadLockCount() {
+ return sync.getReadLockCount();
+ }
+
+ /**
+ * Queries if the write lock is held by any thread. This method is
+ * designed for use in monitoring system state, not for
+ * synchronization control.
+ *
+ * @return {@code true} if any thread holds the write lock and
+ * {@code false} otherwise
+ */
+ public boolean isWriteLocked() {
+ return sync.isWriteLocked();
+ }
+
+ /**
+ * Queries if the write lock is held by the current thread.
+ *
+ * @return {@code true} if the current thread holds the write lock and
+ * {@code false} otherwise
+ */
+ public boolean isWriteLockedByCurrentThread() {
+ return sync.isHeldExclusively();
+ }
+
+ /**
+ * Queries the number of reentrant write holds on this lock by the
+ * current thread. A writer thread has a hold on a lock for
+ * each lock action that is not matched by an unlock action.
+ *
+ * @return the number of holds on the write lock by the current thread,
+ * or zero if the write lock is not held by the current thread
+ */
+ public int getWriteHoldCount() {
+ return sync.getWriteHoldCount();
+ }
+
+ /**
+ * 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
+ * collection is only a best-effort estimate. The elements of the
+ * returned collection are in no particular order. This method is
+ * designed to facilitate construction of subclasses that provide
+ * more extensive lock monitoring facilities.
+ *
+ * @return the collection of threads
+ */
+ protected Collection<Thread> getQueuedWriterThreads() {
+ return sync.getExclusiveQueuedThreads();
+ }
+
+ /**
+ * Returns a collection containing threads that may be waiting to
+ * acquire the read lock. Because the actual set of threads may
+ * change dynamically while constructing this result, the returned
+ * collection is only a best-effort estimate. The elements of the
+ * returned collection are in no particular order. This method is
+ * designed to facilitate construction of subclasses that provide
+ * more extensive lock monitoring facilities.
+ *
+ * @return the collection of threads
+ */
+ protected Collection<Thread> getQueuedReaderThreads() {
+ return sync.getSharedQueuedThreads();
+ }
+
+ /**
+ * Queries whether any threads are waiting to acquire the read or
+ * write lock. Note that because cancellations may occur at any
+ * time, a {@code true} return does not guarantee that any other
+ * thread will ever acquire a lock. This method is designed
+ * primarily for use in monitoring of the system state.
+ *
+ * @return {@code true} if there may be other threads waiting to
+ * acquire the lock
+ */
+ public final boolean hasQueuedThreads() {
+ return sync.hasQueuedThreads();
+ }
+
+ /**
+ * Queries whether the given thread is waiting to acquire either
+ * the read or write lock. Note that because cancellations may
+ * occur at any time, a {@code true} return does not guarantee
+ * that this thread will ever acquire a lock. This method is
+ * designed primarily for use in monitoring of the system state.
+ *
+ * @param thread the thread
+ * @return {@code true} if the given thread is queued waiting for this lock
+ * @throws NullPointerException if the thread is null
+ */
+ public final boolean hasQueuedThread(Thread thread) {
+ return sync.isQueued(thread);
+ }
+
+ /**
+ * Returns an estimate of the number of threads waiting to acquire
+ * either the read or write lock. The value is only an estimate
+ * because the number of threads may change dynamically while this
+ * method traverses internal data structures. This method is
+ * designed for use in monitoring of the system state, not for
+ * synchronization control.
+ *
+ * @return the estimated number of threads waiting for this lock
+ */
+ public final int getQueueLength() {
+ return sync.getQueueLength();
+ }
+
+ /**
+ * Returns a collection containing threads that may be waiting to
+ * acquire either the read or write lock. Because the actual set
+ * of threads may change dynamically while constructing this
+ * result, the returned collection is only a best-effort estimate.
+ * The elements of the returned collection are in no particular
+ * order. This method is designed to facilitate construction of
+ * subclasses that provide more extensive monitoring facilities.
+ *
+ * @return the collection of threads
+ */
+ protected Collection<Thread> getQueuedThreads() {
+ return sync.getQueuedThreads();
+ }
+
+ /**
+ * Queries whether any threads are waiting on the given condition
+ * associated with the write lock. Note that because timeouts and
+ * interrupts may occur at any time, a {@code true} return does
+ * not guarantee that a future {@code signal} will awaken any
+ * threads. This method is designed primarily for use in
+ * monitoring of the system state.
+ *
+ * @param condition the condition
+ * @return {@code true} if there are any waiting threads
+ * @throws IllegalMonitorStateException if this lock is not held
+ * @throws IllegalArgumentException if the given condition is
+ * not associated with this lock
+ * @throws NullPointerException if the condition is null
+ */
+ public boolean hasWaiters(Condition condition) {
+ if (condition == null)
+ throw new NullPointerException();
+ if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
+ throw new IllegalArgumentException("not owner");
+ return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
+ }
+
+ /**
+ * Returns an estimate of the number of threads waiting on the
+ * given condition associated with the write lock. Note that because
+ * timeouts and interrupts may occur at any time, the estimate
+ * serves only as an upper bound on the actual number of waiters.
+ * This method is designed for use in monitoring of the system
+ * state, not for synchronization control.
+ *
+ * @param condition the condition
+ * @return the estimated number of waiting threads
+ * @throws IllegalMonitorStateException if this lock is not held
+ * @throws IllegalArgumentException if the given condition is
+ * not associated with this lock
+ * @throws NullPointerException if the condition is null
+ */
+ public int getWaitQueueLength(Condition condition) {
+ if (condition == null)
+ throw new NullPointerException();
+ if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
+ throw new IllegalArgumentException("not owner");
+ return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
+ }
+
+ /**
+ * Returns a collection containing those threads that may be
+ * waiting on the given condition associated with the write lock.
+ * Because the actual set of threads may change dynamically while
+ * constructing this result, the returned collection is only a
+ * best-effort estimate. The elements of the returned collection
+ * are in no particular order. This method is designed to
+ * facilitate construction of subclasses that provide more
+ * extensive condition monitoring facilities.
+ *
+ * @param condition the condition
+ * @return the collection of threads
+ * @throws IllegalMonitorStateException if this lock is not held
+ * @throws IllegalArgumentException if the given condition is
+ * not associated with this lock
+ * @throws NullPointerException if the condition is null
+ */
+ protected Collection<Thread> getWaitingThreads(Condition condition) {
+ if (condition == null)
+ throw new NullPointerException();
+ if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
+ throw new IllegalArgumentException("not owner");
+ return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
+ }
+
+ /**
+ * Returns a string identifying this lock, as well as its lock state.
+ * The state, in brackets, includes the String {@code "Write locks ="}
+ * followed by the number of reentrantly held write locks, and the
+ * String {@code "Read locks ="} followed by the number of held
+ * read locks.
+ *
+ * @return a string identifying this lock, as well as its lock state
+ */
+ public String toString() {
+ int c = sync.getCount();
+ int w = Sync.exclusiveCount(c);
+ int r = Sync.sharedCount(c);
+
+ return super.toString() +
+ "[Write locks = " + w + ", Read locks = " + r + "]";
+ }
+
+}