diff options
Diffstat (limited to 'src/actors/scala/actors/threadpool')
39 files changed, 0 insertions, 12472 deletions
diff --git a/src/actors/scala/actors/threadpool/AbstractCollection.java b/src/actors/scala/actors/threadpool/AbstractCollection.java deleted file mode 100644 index 195a0064ab..0000000000 --- a/src/actors/scala/actors/threadpool/AbstractCollection.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Written by Dawid Kurzyniec, based on public domain code written by Doug Lea - * and publicly available documentation, and released to the public domain, as - * explained at http://creativecommons.org/licenses/publicdomain - */ - -package scala.actors.threadpool; -import scala.actors.threadpool.helpers.Utils; - -/** - * Overrides toArray() and toArray(Object[]) in AbstractCollection to provide - * implementations valid for concurrent collections. - * - * @author Doug Lea - * @author Dawid Kurzyniec - */ -public abstract class AbstractCollection extends java.util.AbstractCollection { - - /** - * Sole constructor. (For invocation by subclass constructors, typically - * implicit.) - */ - protected AbstractCollection() { super(); } - - public Object[] toArray() { - return Utils.collectionToArray(this); - } - - public Object[] toArray(Object[] a) { - return Utils.collectionToArray(this, a); - } -} diff --git a/src/actors/scala/actors/threadpool/AbstractExecutorService.java b/src/actors/scala/actors/threadpool/AbstractExecutorService.java deleted file mode 100644 index 4a12aa3c28..0000000000 --- a/src/actors/scala/actors/threadpool/AbstractExecutorService.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * 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 scala.actors.threadpool; - -import scala.actors.threadpool.helpers.*; -import java.util.Collection; -import java.util.ArrayList; -import java.util.List; -import java.util.Iterator; - -/** - * 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<V> implements RunnableFuture<V> {...} - * - * protected <V> RunnableFuture<V> newTaskFor(Callable<V> c) { - * return new CustomTask<V>(c); - * } - * protected <V> RunnableFuture<V> newTaskFor(Runnable r, V v) { - * return new CustomTask<V>(r, v); - * } - * // ... 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 RunnableFuture newTaskFor(Runnable runnable, Object value) { - return new FutureTask(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 RunnableFuture newTaskFor(Callable callable) { - return new FutureTask(callable); - } - - /** - * @throws RejectedExecutionException {@inheritDoc} - * @throws NullPointerException {@inheritDoc} - */ - public Future submit(Runnable task) { - if (task == null) throw new NullPointerException(); - RunnableFuture ftask = newTaskFor(task, null); - execute(ftask); - return ftask; - } - - /** - * @throws RejectedExecutionException {@inheritDoc} - * @throws NullPointerException {@inheritDoc} - */ - public Future submit(Runnable task, Object result) { - if (task == null) throw new NullPointerException(); - RunnableFuture ftask = newTaskFor(task, result); - execute(ftask); - return ftask; - } - - /** - * @throws RejectedExecutionException {@inheritDoc} - * @throws NullPointerException {@inheritDoc} - */ - public Future submit(Callable task) { - if (task == null) throw new NullPointerException(); - RunnableFuture ftask = newTaskFor(task); - execute(ftask); - return ftask; - } - - /** - * the main mechanics of invokeAny. - */ - private Object doInvokeAny(Collection 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> futures = new ArrayList<Future>(ntasks); - ExecutorCompletionService ecs = - new ExecutorCompletionService(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)? Utils.nanoTime() : 0; - Iterator it = tasks.iterator(); - - // Start one task for sure; the rest incrementally - futures.add(ecs.submit((Callable)it.next())); - --ntasks; - int active = 1; - - for (;;) { - Future f = ecs.poll(); - if (f == null) { - if (ntasks > 0) { - --ntasks; - futures.add(ecs.submit((Callable)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 = Utils.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 (Iterator f = futures.iterator(); f.hasNext();) - ((Future)f.next()).cancel(true); - } - } - - public Object invokeAny(Collection tasks) - throws InterruptedException, ExecutionException { - try { - return doInvokeAny(tasks, false, 0); - } catch (TimeoutException cannotHappen) { - assert false; - return null; - } - } - - public Object invokeAny(Collection tasks, - long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException { - return doInvokeAny(tasks, true, unit.toNanos(timeout)); - } - - public List<Future> invokeAll(Collection tasks) throws InterruptedException { - if (tasks == null) - throw new NullPointerException(); - List<Future> futures = new ArrayList<Future>(tasks.size()); - boolean done = false; - try { - for (Iterator t = tasks.iterator(); t.hasNext();) { - RunnableFuture f = newTaskFor((Callable)t.next()); - futures.add(f); - execute(f); - } - for (Iterator i = futures.iterator(); i.hasNext();) { - Future f = (Future) i.next(); - if (!f.isDone()) { - try { - f.get(); - } catch (CancellationException ignore) { - } catch (ExecutionException ignore) { - } - } - } - done = true; - return futures; - } finally { - if (!done) - for (Iterator i = futures.iterator(); i.hasNext();) { - Future f = (Future) i.next(); - f.cancel(true); - } - } - } - - public List<Future> invokeAll(Collection tasks, - long timeout, TimeUnit unit) - throws InterruptedException { - if (tasks == null || unit == null) - throw new NullPointerException(); - long nanos = unit.toNanos(timeout); - List<Future> futures = new ArrayList<Future>(tasks.size()); - boolean done = false; - try { - for (Iterator t = tasks.iterator(); t.hasNext();) - futures.add(newTaskFor((Callable)t.next())); - - long lastTime = Utils.nanoTime(); - - // Interleave time checks and calls to execute in case - // executor doesn't have any/much parallelism. - Iterator it = futures.iterator(); - while (it.hasNext()) { - execute((Runnable)(it.next())); - long now = Utils.nanoTime(); - nanos -= (now - lastTime); - lastTime = now; - if (nanos <= 0) - return futures; - } - - for (Iterator i = futures.iterator(); i.hasNext();) { - Future f = (Future)i.next(); - 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 = Utils.nanoTime(); - nanos -= now - lastTime; - lastTime = now; - } - } - done = true; - return futures; - } finally { - if (!done) - for (Iterator i = futures.iterator(); i.hasNext();) { - Future f = (Future) i.next(); - f.cancel(true); - } - } - } - -} diff --git a/src/actors/scala/actors/threadpool/AbstractQueue.java b/src/actors/scala/actors/threadpool/AbstractQueue.java deleted file mode 100644 index 84ddc136bc..0000000000 --- a/src/actors/scala/actors/threadpool/AbstractQueue.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * 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 scala.actors.threadpool; - -import java.util.Iterator; -import java.util.Collection; -import java.util.NoSuchElementException; - -/** - * This class provides skeletal implementations of some {@link Queue} - * operations. The implementations in this class are appropriate when - * the base implementation does <em>not</em> allow <tt>null</tt> - * elements. Methods {@link #add add}, {@link #remove remove}, and - * {@link #element element} are based on {@link #offer offer}, {@link - * #poll poll}, and {@link #peek peek}, respectively but throw - * exceptions instead of indicating failure via <tt>false</tt> or - * <tt>null</tt> returns. - * - * <p> A <tt>Queue</tt> implementation that extends this class must - * minimally define a method {@link Queue#offer} which does not permit - * insertion of <tt>null</tt> elements, along with methods {@link - * Queue#peek}, {@link Queue#poll}, {@link Collection#size}, and a - * {@link Collection#iterator} supporting {@link - * Iterator#remove}. Typically, additional methods will be overridden - * as well. If these requirements cannot be met, consider instead - * subclassing {@link AbstractCollection}. - * - * <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 - */ -public abstract class AbstractQueue - extends AbstractCollection - implements Queue { - - /** - * Constructor for use by subclasses. - */ - protected AbstractQueue() { - } - - /** - * 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. - * - * <p>This implementation returns <tt>true</tt> if <tt>offer</tt> succeeds, - * else throws an <tt>IllegalStateException</tt>. - * - * @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 and - * this queue does not permit null elements - * @throws IllegalArgumentException if some property of this element - * prevents it from being added to this queue - */ - public boolean add(Object e) { - if (offer(e)) - return true; - else - throw new IllegalStateException("Queue full"); - } - - /** - * Retrieves and removes the head of this queue. This method differs - * from {@link #poll poll} only in that it throws an exception if this - * queue is empty. - * - * <p>This implementation returns the result of <tt>poll</tt> - * unless the queue is empty. - * - * @return the head of this queue - * @throws NoSuchElementException if this queue is empty - */ - public Object remove() { - Object x = poll(); - if (x != null) - return x; - else - throw new NoSuchElementException(); - } - - - /** - * Retrieves, but does not remove, the head of this queue. This method - * differs from {@link #peek peek} only in that it throws an exception if - * this queue is empty. - * - * <p>This implementation returns the result of <tt>peek</tt> - * unless the queue is empty. - * - * @return the head of this queue - * @throws NoSuchElementException if this queue is empty - */ - public Object element() { - Object x = peek(); - if (x != null) - return x; - else - throw new NoSuchElementException(); - } - - /** - * Removes all of the elements from this queue. - * The queue will be empty after this call returns. - * - * <p>This implementation repeatedly invokes {@link #poll poll} until it - * returns <tt>null</tt>. - */ - public void clear() { - while (poll() != null) - ; - } - - /** - * Adds all of the elements in the specified collection to this - * queue. Attempts to addAll of 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. - * - * <p>This implementation iterates over the specified collection, - * and adds each element returned by the iterator to this - * queue, in turn. A runtime exception encountered while - * trying to add an element (including, in particular, a - * <tt>null</tt> element) may result in only some of the elements - * having been successfully added when the associated exception is - * thrown. - * - * @param c collection containing elements to be added to this queue - * @return <tt>true</tt> if this queue changed as a result of the call - * @throws ClassCastException if the class of an element of the specified - * collection prevents it from being added to this queue - * @throws NullPointerException if the specified collection contains a - * null element and this queue does not permit null elements, - * or if the specified collection is null - * @throws IllegalArgumentException if some property of an element of the - * specified collection prevents it from being added to this - * queue, or if the specified collection is this queue - * @throws IllegalStateException if not all the elements can be added at - * this time due to insertion restrictions - * @see #add(Object) - */ - public boolean addAll(Collection c) { - if (c == null) - throw new NullPointerException(); - if (c == this) - throw new IllegalArgumentException(); - boolean modified = false; - Iterator e = c.iterator(); - while (e.hasNext()) { - if (add(e.next())) - modified = true; - } - return modified; - } - -} diff --git a/src/actors/scala/actors/threadpool/Arrays.java b/src/actors/scala/actors/threadpool/Arrays.java deleted file mode 100644 index 85e7c8fa00..0000000000 --- a/src/actors/scala/actors/threadpool/Arrays.java +++ /dev/null @@ -1,811 +0,0 @@ -/* - * Written by Dawid Kurzyniec, based on code written by Doug Lea with assistance - * from members of JCP JSR-166 Expert Group. Released to the public domain, - * as explained at http://creativecommons.org/licenses/publicdomain. - */ - -package scala.actors.threadpool; - -import java.lang.reflect.Array; -import java.util.List; -import java.util.ArrayList; -import java.util.Comparator; - -public class Arrays { - - private Arrays() {} - - public static void sort(long[] a) { - java.util.Arrays.sort(a); - } - - public static void sort(long[] a, int fromIndex, int toIndex) { - java.util.Arrays.sort(a, fromIndex, toIndex); - } - - public static void sort(int[] a) { - java.util.Arrays.sort(a); - } - - public static void sort(int[] a, int fromIndex, int toIndex) { - java.util.Arrays.sort(a, fromIndex, toIndex); - } - - public static void sort(short[] a) { - java.util.Arrays.sort(a); - } - - public static void sort(short[] a, int fromIndex, int toIndex) { - java.util.Arrays.sort(a, fromIndex, toIndex); - } - - public static void sort(char[] a) { - java.util.Arrays.sort(a); - } - - public static void sort(char[] a, int fromIndex, int toIndex) { - java.util.Arrays.sort(a, fromIndex, toIndex); - } - - public static void sort(byte[] a) { - java.util.Arrays.sort(a); - } - - public static void sort(byte[] a, int fromIndex, int toIndex) { - java.util.Arrays.sort(a, fromIndex, toIndex); - } - - public static void sort(double[] a) { - java.util.Arrays.sort(a); - } - - public static void sort(double[] a, int fromIndex, int toIndex) { - java.util.Arrays.sort(a, fromIndex, toIndex); - } - - public static void sort(float[] a) { - java.util.Arrays.sort(a); - } - - public static void sort(float[] a, int fromIndex, int toIndex) { - java.util.Arrays.sort(a, fromIndex, toIndex); - } - - - public static void sort(Object[] a) { - java.util.Arrays.sort(a); - } - - public static void sort(Object[] a, int fromIndex, int toIndex) { - java.util.Arrays.sort(a, fromIndex, toIndex); - } - - public static void sort(Object[] a, Comparator c) { - java.util.Arrays.sort(a, c); - } - - public static void sort(Object[] a, int fromIndex, int toIndex, Comparator c) { - java.util.Arrays.sort(a, fromIndex, toIndex, c); - } - - - // Searching - - public static int binarySearch(long[] a, long key) { - return java.util.Arrays.binarySearch(a, key); - } - - public static int binarySearch(int[] a, int key) { - return java.util.Arrays.binarySearch(a, key); - } - - public static int binarySearch(short[] a, short key) { - return java.util.Arrays.binarySearch(a, key); - } - - public static int binarySearch(char[] a, char key) { - return java.util.Arrays.binarySearch(a, key); - } - - public static int binarySearch(byte[] a, byte key) { - return java.util.Arrays.binarySearch(a, key); - } - - public static int binarySearch(double[] a, double key) { - return java.util.Arrays.binarySearch(a, key); - } - - public static int binarySearch(float[] a, float key) { - return java.util.Arrays.binarySearch(a, key); - } - - public static int binarySearch(Object[] a, Object key) { - return java.util.Arrays.binarySearch(a, key); - } - - public static int binarySearch(Object[] a, Object key, Comparator c) { - return java.util.Arrays.binarySearch(a, key, c); - } - - - // Equality Testing - - public static boolean equals(long[] a, long[] a2) { - return java.util.Arrays.equals(a, a2); - } - - public static boolean equals(int[] a, int[] a2) { - return java.util.Arrays.equals(a, a2); - } - - public static boolean equals(short[] a, short a2[]) { - return java.util.Arrays.equals(a, a2); - } - - public static boolean equals(char[] a, char[] a2) { - return java.util.Arrays.equals(a, a2); - } - - public static boolean equals(byte[] a, byte[] a2) { - return java.util.Arrays.equals(a, a2); - } - - public static boolean equals(boolean[] a, boolean[] a2) { - return java.util.Arrays.equals(a, a2); - } - - public static boolean equals(double[] a, double[] a2) { - return java.util.Arrays.equals(a, a2); - } - - public static boolean equals(float[] a, float[] a2) { - return java.util.Arrays.equals(a, a2); - } - - public static boolean equals(Object[] a, Object[] a2) { - return java.util.Arrays.equals(a, a2); - } - - - // Filling - - public static void fill(long[] a, long val) { - java.util.Arrays.fill(a, val); - } - - public static void fill(long[] a, int fromIndex, int toIndex, long val) { - java.util.Arrays.fill(a, fromIndex, toIndex, val); - } - - public static void fill(int[] a, int val) { - java.util.Arrays.fill(a, val); - } - - public static void fill(int[] a, int fromIndex, int toIndex, int val) { - java.util.Arrays.fill(a, fromIndex, toIndex, val); - } - - public static void fill(short[] a, short val) { - java.util.Arrays.fill(a, val); - } - - public static void fill(short[] a, int fromIndex, int toIndex, short val) { - java.util.Arrays.fill(a, fromIndex, toIndex, val); - } - - public static void fill(char[] a, char val) { - java.util.Arrays.fill(a, val); - } - - public static void fill(char[] a, int fromIndex, int toIndex, char val) { - java.util.Arrays.fill(a, fromIndex, toIndex, val); - } - - public static void fill(byte[] a, byte val) { - java.util.Arrays.fill(a, val); - } - - public static void fill(byte[] a, int fromIndex, int toIndex, byte val) { - java.util.Arrays.fill(a, fromIndex, toIndex, val); - } - - public static void fill(boolean[] a, boolean val) { - java.util.Arrays.fill(a, val); - } - - public static void fill(boolean[] a, int fromIndex, int toIndex, - boolean val) { - java.util.Arrays.fill(a, fromIndex, toIndex, val); - } - - public static void fill(double[] a, double val) { - java.util.Arrays.fill(a, val); - } - - public static void fill(double[] a, int fromIndex, int toIndex,double val) { - java.util.Arrays.fill(a, fromIndex, toIndex, val); - } - - public static void fill(float[] a, float val) { - java.util.Arrays.fill(a, val); - } - - public static void fill(float[] a, int fromIndex, int toIndex, float val) { - java.util.Arrays.fill(a, fromIndex, toIndex, val); - } - - public static void fill(Object[] a, Object val) { - java.util.Arrays.fill(a, val); - } - - public static void fill(Object[] a, int fromIndex, int toIndex, Object val) { - java.util.Arrays.fill(a, fromIndex, toIndex, val); - } - - - // Cloning - - /** - * @since 1.6 - */ - public static Object[] copyOf(Object[] original, int newLength) { - return copyOf(original, newLength, original.getClass()); - } - - /** - * @since 1.6 - */ - public static Object[] copyOf(Object[] original, int newLength, Class newType) { - Object[] arr = (newType == Object[].class) ? new Object[newLength] : - (Object[])Array.newInstance(newType.getComponentType(), newLength); - int len = (original.length < newLength ? original.length : newLength); - System.arraycopy(original, 0, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static byte[] copyOf(byte[] original, int newLength) { - byte[] arr = new byte[newLength]; - int len = (original.length < newLength ? original.length : newLength); - System.arraycopy(original, 0, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static short[] copyOf(short[] original, int newLength) { - short[] arr = new short[newLength]; - int len = (original.length < newLength ? original.length : newLength); - System.arraycopy(original, 0, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static int[] copyOf(int[] original, int newLength) { - int[] arr = new int[newLength]; - int len = (original.length < newLength ? original.length : newLength); - System.arraycopy(original, 0, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static long[] copyOf(long[] original, int newLength) { - long[] arr = new long[newLength]; - int len = (original.length < newLength ? original.length : newLength); - System.arraycopy(original, 0, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static char[] copyOf(char[] original, int newLength) { - char[] arr = new char[newLength]; - int len = (original.length < newLength ? original.length : newLength); - System.arraycopy(original, 0, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static float[] copyOf(float[] original, int newLength) { - float[] arr = new float[newLength]; - int len = (original.length < newLength ? original.length : newLength); - System.arraycopy(original, 0, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static double[] copyOf(double[] original, int newLength) { - double[] arr = new double[newLength]; - int len = (original.length < newLength ? original.length : newLength); - System.arraycopy(original, 0, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static boolean[] copyOf(boolean[] original, int newLength) { - boolean[] arr = new boolean[newLength]; - int len = (original.length < newLength ? original.length : newLength); - System.arraycopy(original, 0, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static Object[] copyOfRange(Object[] original, int from, int to) { - return copyOfRange(original, from, to, original.getClass()); - } - - /** - * @since 1.6 - */ - public static Object[] copyOfRange(Object[] original, int from, int to, Class newType) { - int newLength = to - from; - if (newLength < 0) throw new IllegalArgumentException(from + " > " + to); - Object[] arr = (newType == Object[].class) ? new Object[newLength] : - (Object[])Array.newInstance(newType.getComponentType(), newLength); - int ceil = original.length-from; - int len = (ceil < newLength) ? ceil : newLength; - System.arraycopy(original, from, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static byte[] copyOfRange(byte[] original, int from, int to) { - int newLength = to - from; - if (newLength < 0) throw new IllegalArgumentException(from + " > " + to); - byte[] arr = new byte[newLength]; - int ceil = original.length-from; - int len = (ceil < newLength) ? ceil : newLength; - System.arraycopy(original, from, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static short[] copyOfRange(short[] original, int from, int to) { - int newLength = to - from; - if (newLength < 0) throw new IllegalArgumentException(from + " > " + to); - short[] arr = new short[newLength]; - int ceil = original.length-from; - int len = (ceil < newLength) ? ceil : newLength; - System.arraycopy(original, from, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static int[] copyOfRange(int[] original, int from, int to) { - int newLength = to - from; - if (newLength < 0) throw new IllegalArgumentException(from + " > " + to); - int[] arr = new int[newLength]; - int ceil = original.length-from; - int len = (ceil < newLength) ? ceil : newLength; - System.arraycopy(original, from, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static long[] copyOfRange(long[] original, int from, int to) { - int newLength = to - from; - if (newLength < 0) throw new IllegalArgumentException(from + " > " + to); - long[] arr = new long[newLength]; - int ceil = original.length-from; - int len = (ceil < newLength) ? ceil : newLength; - System.arraycopy(original, from, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static char[] copyOfRange(char[] original, int from, int to) { - int newLength = to - from; - if (newLength < 0) throw new IllegalArgumentException(from + " > " + to); - char[] arr = new char[newLength]; - int ceil = original.length-from; - int len = (ceil < newLength) ? ceil : newLength; - System.arraycopy(original, from, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static float[] copyOfRange(float[] original, int from, int to) { - int newLength = to - from; - if (newLength < 0) throw new IllegalArgumentException(from + " > " + to); - float[] arr = new float[newLength]; - int ceil = original.length-from; - int len = (ceil < newLength) ? ceil : newLength; - System.arraycopy(original, from, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static double[] copyOfRange(double[] original, int from, int to) { - int newLength = to - from; - if (newLength < 0) throw new IllegalArgumentException(from + " > " + to); - double[] arr = new double[newLength]; - int ceil = original.length-from; - int len = (ceil < newLength) ? ceil : newLength; - System.arraycopy(original, from, arr, 0, len); - return arr; - } - - /** - * @since 1.6 - */ - public static boolean[] copyOfRange(boolean[] original, int from, int to) { - int newLength = to - from; - if (newLength < 0) throw new IllegalArgumentException(from + " > " + to); - boolean[] arr = new boolean[newLength]; - int ceil = original.length-from; - int len = (ceil < newLength) ? ceil : newLength; - System.arraycopy(original, from, arr, 0, len); - return arr; - } - - - public static List asList(Object[] a) { - return java.util.Arrays.asList(a); - } - - /** - * @since 1.5 - */ - public static int hashCode(long a[]) { - if (a == null) return 0; - int hash = 1; - for (int i=0; i<a.length; i++) { - long e = a[i]; - hash = 31*hash + (int)(e ^ (e >>> 32)); - } - return hash; - } - - /** - * @since 1.5 - */ - public static int hashCode(int a[]) { - if (a == null) return 0; - int hash = 1; - for (int i=0; i<a.length; i++) { - hash = 31*hash + a[i]; - } - return hash; - } - - /** - * @since 1.5 - */ - public static int hashCode(short a[]) { - if (a == null) return 0; - int hash = 1; - for (int i=0; i<a.length; i++) { - hash = 31*hash + a[i]; - } - return hash; - } - - /** - * @since 1.5 - */ - public static int hashCode(char a[]) { - if (a == null) return 0; - int hash = 1; - for (int i=0; i<a.length; i++) { - hash = 31*hash + a[i]; - } - return hash; - } - - /** - * @since 1.5 - */ - public static int hashCode(byte a[]) { - if (a == null) return 0; - int hash = 1; - for (int i=0; i<a.length; i++) { - hash = 31*hash + a[i]; - } - return hash; - } - - /** - * @since 1.5 - */ - public static int hashCode(boolean a[]) { - if (a == null) return 0; - int hash = 1; - for (int i=0; i<a.length; i++) { - hash = 31*hash + (a[i] ? 1231 : 1237); - } - return hash; - } - - /** - * @since 1.5 - */ - public static int hashCode(float a[]) { - if (a == null) return 0; - int hash = 1; - for (int i=0; i<a.length; i++) { - hash = 31*hash + Float.floatToIntBits(a[i]); - } - return hash; - } - - /** - * @since 1.5 - */ - public static int hashCode(double a[]) { - if (a == null) return 0; - int hash = 1; - for (int i=0; i<a.length; i++) { - long e = Double.doubleToLongBits(a[i]); - hash = 31*hash + (int)(e ^ (e >>> 32)); - } - return hash; - } - - /** - * @since 1.5 - */ - public static int hashCode(Object a[]) { - if (a == null) return 0; - int hash = 1; - for (int i=0; i<a.length; i++) { - Object e = a[i]; - hash = 31*hash + (e == null ? 0 : e.hashCode()); - } - return hash; - } - - /** - * @since 1.5 - */ - public static int deepHashCode(Object a[]) { - if (a == null) return 0; - int hash = 1; - for (int i=0; i<a.length; i++) { - Object e = a[i]; - hash = 31*hash + - (e instanceof Object[] ? deepHashCode((Object[])e) : - (e instanceof byte[] ? hashCode((byte[])e) : - (e instanceof short[] ? hashCode((short[])e) : - (e instanceof int[] ? hashCode((int[])e) : - (e instanceof long[] ? hashCode((long[])e) : - (e instanceof char[] ? hashCode((char[])e) : - (e instanceof boolean[] ? hashCode((boolean[])e) : - (e instanceof float[] ? hashCode((float[])e) : - (e instanceof double[] ? hashCode((double[])e) : - (e != null ? e.hashCode() : 0)))))))))); - } - return hash; - - } - - /** - * @since 1.5 - */ - public static boolean deepEquals(Object[] a1, Object[] a2) { - if (a1 == a2) return true; - if (a1 == null || a2==null) return false; - int len = a1.length; - if (len != a2.length) return false; - for (int i = 0; i < len; i++) { - Object e1 = a1[i]; - Object e2 = a2[i]; - if (e1 == e2) continue; - if (e1 == null) return false; - boolean eq = - (e1.getClass() != e2.getClass() || e1.getClass().isArray()) ? - e1.equals(e2) : - (e1 instanceof Object[] && e2 instanceof Object[]) ? - deepEquals((Object[])e1, (Object[])e2) : - (e1 instanceof byte[] && e2 instanceof byte[]) ? - equals((byte[])e1, (byte[])e2) : - (e1 instanceof short[] && e2 instanceof short[]) ? - equals((short[])e1, (short[])e2) : - (e1 instanceof int[] && e2 instanceof int[]) ? - equals((int[])e1, (int[])e2) : - (e1 instanceof long[] && e2 instanceof long[]) ? - equals((long[])e1, (long[])e2) : - (e1 instanceof char[] && e2 instanceof char[]) ? - equals((char[])e1, (char[])e2) : - (e1 instanceof boolean[] && e2 instanceof boolean[]) ? - equals((boolean[])e1, (boolean[])e2) : - (e1 instanceof float[] && e2 instanceof float[]) ? - equals((float[])e1, (float[])e2) : - (e1 instanceof double[] && e2 instanceof double[]) ? - equals((double[])e1, (double[])e2) : - e1.equals(e2); - - if (!eq) return false; - } - return true; - } - - /** - * @since 1.5 - */ - public static String toString(long[] a) { - if (a == null) return "null"; - if (a.length == 0) return "[]"; - StringBuffer buf = new StringBuffer(); - buf.append('[').append(a[0]); - for (int i=1; i<a.length; i++) buf.append(", ").append(a[i]); - buf.append(']'); - return buf.toString(); - } - - /** - * @since 1.5 - */ - public static String toString(int[] a) { - if (a == null) return "null"; - if (a.length == 0) return "[]"; - StringBuffer buf = new StringBuffer(); - buf.append('[').append(a[0]); - for (int i=1; i<a.length; i++) buf.append(", ").append(a[i]); - buf.append(']'); - return buf.toString(); - } - - /** - * @since 1.5 - */ - public static String toString(short[] a) { - if (a == null) return "null"; - if (a.length == 0) return "[]"; - StringBuffer buf = new StringBuffer(); - buf.append('[').append(a[0]); - for (int i=1; i<a.length; i++) buf.append(", ").append(a[i]); - buf.append(']'); - return buf.toString(); - } - - /** - * @since 1.5 - */ - public static String toString(char[] a) { - if (a == null) return "null"; - if (a.length == 0) return "[]"; - StringBuffer buf = new StringBuffer(); - buf.append('[').append(a[0]); - for (int i=1; i<a.length; i++) buf.append(", ").append(a[i]); - buf.append(']'); - return buf.toString(); - } - - /** - * @since 1.5 - */ - public static String toString(byte[] a) { - if (a == null) return "null"; - if (a.length == 0) return "[]"; - StringBuffer buf = new StringBuffer(); - buf.append('[').append(a[0]); - for (int i=1; i<a.length; i++) buf.append(", ").append(a[i]); - buf.append(']'); - return buf.toString(); - } - - /** - * @since 1.5 - */ - public static String toString(boolean[] a) { - if (a == null) return "null"; - if (a.length == 0) return "[]"; - StringBuffer buf = new StringBuffer(); - buf.append('[').append(a[0]); - for (int i=1; i<a.length; i++) buf.append(", ").append(a[i]); - buf.append(']'); - return buf.toString(); - } - - /** - * @since 1.5 - */ - public static String toString(float[] a) { - if (a == null) return "null"; - if (a.length == 0) return "[]"; - StringBuffer buf = new StringBuffer(); - buf.append('[').append(a[0]); - for (int i=1; i<a.length; i++) buf.append(", ").append(a[i]); - buf.append(']'); - return buf.toString(); - } - - /** - * @since 1.5 - */ - public static String toString(double[] a) { - if (a == null) return "null"; - if (a.length == 0) return "[]"; - StringBuffer buf = new StringBuffer(); - buf.append('[').append(a[0]); - for (int i=1; i<a.length; i++) buf.append(", ").append(a[i]); - buf.append(']'); - return buf.toString(); - } - - /** - * @since 1.5 - */ - public static String toString(Object[] a) { - if (a == null) return "null"; - if (a.length == 0) return "[]"; - StringBuffer buf = new StringBuffer(); - buf.append('[').append(a[0]); - for (int i=1; i<a.length; i++) buf.append(", ").append(a[i]); - buf.append(']'); - return buf.toString(); - } - - /** - * @since 1.5 - */ - public static String deepToString(Object[] a) { - if (a == null) return "null"; - StringBuffer buf = new StringBuffer(); - deepToString(a, buf, new ArrayList()); - return buf.toString(); - } - - private static void deepToString(Object[] a, StringBuffer buf, List seen) { - seen.add(a); - buf.append('['); - for (int i = 0; i < a.length; i++) { - if (i>0) buf.append(", "); - Object e = a[i]; - if (e == null) { - buf.append("null"); - } - else if (!e.getClass().isArray()) { - buf.append(e.toString()); - } - else if (e instanceof Object[]) { - if (seen.contains(e)) buf.append("[...]"); - else deepToString((Object[])e, buf, seen); - } - else { - // primitive arr - buf.append( - (e instanceof byte[]) ? toString( (byte[]) e) : - (e instanceof short[]) ? toString( (short[]) e) : - (e instanceof int[]) ? toString( (int[]) e) : - (e instanceof long[]) ? toString( (long[]) e) : - (e instanceof char[]) ? toString( (char[]) e) : - (e instanceof boolean[]) ? toString( (boolean[]) e) : - (e instanceof float[]) ? toString( (float[]) e) : - (e instanceof double[]) ? toString( (double[]) e) : ""); - } - } - buf.append(']'); - seen.remove(seen.size()-1); - } -} diff --git a/src/actors/scala/actors/threadpool/AtomicInteger.java b/src/actors/scala/actors/threadpool/AtomicInteger.java deleted file mode 100644 index eedb84512a..0000000000 --- a/src/actors/scala/actors/threadpool/AtomicInteger.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * 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 scala.actors.threadpool; - -/** - * An {@code int} value that may be updated atomically. See the - * {@link edu.emory.mathcs.backport.java.util.concurrent.atomic} package specification for - * description of the properties of atomic variables. An - * {@code AtomicInteger} 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 - * {@code Number} 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; - - 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 {@code 0}. - */ - 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 synchronized void set(int newValue) { - value = newValue; - } - - /** - * Eventually sets to the given value. - * - * @param newValue the new value - * @since 1.6 - */ - public final synchronized void lazySet(int newValue) { - value = newValue; - } - - /** - * Atomically sets to the given value and returns the old value. - * - * @param newValue the new value - * @return the previous value - */ - public final synchronized int getAndSet(int newValue) { - int old = value; - value = newValue; - return old; - } - - /** - * Atomically sets the value to the given updated value - * if the current value {@code ==} 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 synchronized boolean compareAndSet(int expect, int update) { - if (value == expect) { - value = update; - return true; - } - else { - return false; - } - } - - /** - * Atomically sets the value to the given updated value - * if the current value {@code ==} the expected value. - * - * <p>May <a href="package-summary.html#Spurious">fail spuriously</a> - * and does not provide ordering guarantees, so is only rarely an - * appropriate alternative to {@code compareAndSet}. - * - * @param expect the expected value - * @param update the new value - * @return true if successful. - */ - public final synchronized boolean weakCompareAndSet(int expect, int update) { - if (value == expect) { - value = update; - return true; - } - else { - return false; - } - } - - - /** - * Atomically increments by one the current value. - * - * @return the previous value - */ - public final synchronized int getAndIncrement() { - return value++; - } - - - /** - * Atomically decrements by one the current value. - * - * @return the previous value - */ - public final synchronized int getAndDecrement() { - return value--; - } - - - /** - * Atomically adds the given value to the current value. - * - * @param delta the value to add - * @return the previous value - */ - public final synchronized int getAndAdd(int delta) { - int old = value; - value += delta; - return old; - } - - /** - * Atomically increments by one the current value. - * - * @return the updated value - */ - public final synchronized int incrementAndGet() { - return ++value; - } - - /** - * Atomically decrements by one the current value. - * - * @return the updated value - */ - public final synchronized int decrementAndGet() { - return --value; - } - - - /** - * Atomically adds the given value to the current value. - * - * @param delta the value to add - * @return the updated value - */ - public final synchronized int addAndGet(int delta) { - return value += delta; - } - - /** - * 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/src/actors/scala/actors/threadpool/BlockingQueue.java b/src/actors/scala/actors/threadpool/BlockingQueue.java deleted file mode 100644 index 4b8c201b85..0000000000 --- a/src/actors/scala/actors/threadpool/BlockingQueue.java +++ /dev/null @@ -1,344 +0,0 @@ -/* - * 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 scala.actors.threadpool; - -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 "close" or "shutdown" 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 java.util.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/src/actors/scala/actors/threadpool/Callable.java b/src/actors/scala/actors/threadpool/Callable.java deleted file mode 100644 index f1b200c022..0000000000 --- a/src/actors/scala/actors/threadpool/Callable.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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 scala.actors.threadpool; - -/** - * 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 - */ -public interface Callable { - /** - * Computes a result, or throws an exception if unable to do so. - * - * @return computed result - * @throws Exception if unable to compute a result - */ - Object call() throws Exception; -} diff --git a/src/actors/scala/actors/threadpool/CancellationException.java b/src/actors/scala/actors/threadpool/CancellationException.java deleted file mode 100644 index c2163b83c7..0000000000 --- a/src/actors/scala/actors/threadpool/CancellationException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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 scala.actors.threadpool; - -/** - * 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/src/actors/scala/actors/threadpool/CompletionService.java b/src/actors/scala/actors/threadpool/CompletionService.java deleted file mode 100644 index 219ab7affa..0000000000 --- a/src/actors/scala/actors/threadpool/CompletionService.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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 scala.actors.threadpool; - -/** - * 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 { - /** - * 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 submit(Callable 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 submit(Runnable task, Object 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 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 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 poll(long timeout, TimeUnit unit) throws InterruptedException; -} diff --git a/src/actors/scala/actors/threadpool/ExecutionException.java b/src/actors/scala/actors/threadpool/ExecutionException.java deleted file mode 100644 index 912f965acf..0000000000 --- a/src/actors/scala/actors/threadpool/ExecutionException.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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 scala.actors.threadpool; - -/** - * 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/src/actors/scala/actors/threadpool/Executor.java b/src/actors/scala/actors/threadpool/Executor.java deleted file mode 100644 index e444e64dff..0000000000 --- a/src/actors/scala/actors/threadpool/Executor.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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 scala.actors.threadpool; - -/** - * 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<Runnable> tasks = new ArrayDeque<Runnable>(); - * 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/src/actors/scala/actors/threadpool/ExecutorCompletionService.java b/src/actors/scala/actors/threadpool/ExecutorCompletionService.java deleted file mode 100644 index 02e9bbe297..0000000000 --- a/src/actors/scala/actors/threadpool/ExecutorCompletionService.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * 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 scala.actors.threadpool; -import scala.actors.threadpool.*; // for javadoc (till 6280605 is fixed) - -/** - * 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<Callable<Result>> solvers) - * throws InterruptedException, ExecutionException { - * CompletionService<Result> ecs - * = new ExecutorCompletionService<Result>(e); - * for (Callable<Result> s : solvers) - * ecs.submit(s); - * int n = solvers.size(); - * for (int i = 0; i < 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<Callable<Result>> solvers) - * throws InterruptedException { - * CompletionService<Result> ecs - * = new ExecutorCompletionService<Result>(e); - * int n = solvers.size(); - * List<Future<Result>> futures - * = new ArrayList<Future<Result>>(n); - * Result result = null; - * try { - * for (Callable<Result> s : solvers) - * futures.add(ecs.submit(s)); - * for (int i = 0; i < n; ++i) { - * try { - * Result r = ecs.take().get(); - * if (r != null) { - * result = r; - * break; - * } - * } catch (ExecutionException ignore) {} - * } - * } - * finally { - * for (Future<Result> f : futures) - * f.cancel(true); - * } - * - * if (result != null) - * use(result); - * } - * </pre> - */ -public class ExecutorCompletionService implements CompletionService { - private final Executor executor; - private final AbstractExecutorService aes; - private final BlockingQueue completionQueue; - - /** - * FutureTask extension to enqueue upon completion - */ - private class QueueingFuture extends FutureTask { - QueueingFuture(RunnableFuture task) { - super(task, null); - this.task = task; - } - protected void done() { completionQueue.add(task); } - private final Future task; - } - - private RunnableFuture newTaskFor(Callable task) { - if (aes == null) - return new FutureTask(task); - else - return aes.newTaskFor(task); - } - - private RunnableFuture newTaskFor(Runnable task, Object result) { - if (aes == null) - return new FutureTask(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(); - } - - /** - * 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. This queue is - * treated as unbounded -- failed attempted <tt>Queue.add</tt> - * operations for completed tasks cause them not to be - * retrievable. - * @throws NullPointerException if executor or completionQueue are <tt>null</tt> - */ - public ExecutorCompletionService(Executor executor, - BlockingQueue 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 submit(Callable task) { - if (task == null) throw new NullPointerException(); - RunnableFuture f = newTaskFor(task); - executor.execute(new QueueingFuture(f)); - return f; - } - - public Future submit(Runnable task, Object result) { - if (task == null) throw new NullPointerException(); - RunnableFuture f = newTaskFor(task, result); - executor.execute(new QueueingFuture(f)); - return f; - } - - public Future take() throws InterruptedException { - return (Future)completionQueue.take(); - } - - public Future poll() { - return (Future)completionQueue.poll(); - } - - public Future poll(long timeout, TimeUnit unit) throws InterruptedException { - return (Future)completionQueue.poll(timeout, unit); - } - -} diff --git a/src/actors/scala/actors/threadpool/ExecutorService.java b/src/actors/scala/actors/threadpool/ExecutorService.java deleted file mode 100644 index d3a9a3b8a8..0000000000 --- a/src/actors/scala/actors/threadpool/ExecutorService.java +++ /dev/null @@ -1,331 +0,0 @@ -/* - * 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 scala.actors.threadpool; - -import scala.actors.threadpool.*; // for javadoc (till 6280605 is fixed) -import java.util.List; -import java.util.Collection; - -/** - * 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 reject new tasks. Two different methods are provided for - * shutting down an <tt>ExecutorService</tt>. The {@link #shutdown} - * method will allow previously submitted tasks to execute before - * terminating, while the {@link #shutdownNow} method prevents waiting - * tasks from starting and attempts to stop currently executing tasks. - * Upon termination, an executor has no tasks actively executing, no - * tasks 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 implements Runnable { - * 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 run() { // run the service - * 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 on socket - * } - * } - * </pre> - * - * The following method shuts down an <tt>ExecutorService</tt> in two phases, - * first by calling <tt>shutdown</tt> to reject incoming tasks, and then - * calling <tt>shutdownNow</tt>, if necessary, to cancel any lingering tasks: - * - * <pre> - * void shutdownAndAwaitTermination(ExecutorService pool) { - * pool.shutdown(); // Disable new tasks from being submitted - * try { - * // Wait a while for existing tasks to terminate - * if (!pool.awaitTermination(60, TimeUnit.SECONDS)) { - * pool.shutdownNow(); // Cancel currently executing tasks - * // Wait a while for tasks to respond to being cancelled - * if (!pool.awaitTermination(60, TimeUnit.SECONDS)) - * System.err.println("Pool did not terminate"); - * } - * } catch (InterruptedException ie) { - * // (Re-)Cancel if current thread also interrupted - * pool.shutdownNow(); - * // Preserve interrupt status - * Thread.currentThread().interrupt(); - * } - * } - * </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 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 - */ - Future submit(Callable 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 - */ - Future submit(Runnable task, Object 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 - */ - - List invokeAll(Collection 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 - */ - List invokeAll(Collection 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 - */ - Object invokeAny(Collection 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 - */ - Object invokeAny(Collection tasks, long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException; -} diff --git a/src/actors/scala/actors/threadpool/Executors.java b/src/actors/scala/actors/threadpool/Executors.java deleted file mode 100644 index 49a127a8db..0000000000 --- a/src/actors/scala/actors/threadpool/Executors.java +++ /dev/null @@ -1,667 +0,0 @@ -/* - * 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 scala.actors.threadpool; -//import edu.emory.mathcs.backport.java.util.*; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedExceptionAction; -import java.security.AccessControlException; -import java.util.List; -import java.util.Collection; - -/** - * 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 <= 0</tt> - */ - public static ExecutorService newFixedThreadPool(int nThreads) { - return new ThreadPoolExecutor(nThreads, nThreads, - 0L, TimeUnit.MILLISECONDS, - new LinkedBlockingQueue()); - } - - /** - * 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 <= 0</tt> - */ - public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) { - return new ThreadPoolExecutor(nThreads, nThreads, - 0L, TimeUnit.MILLISECONDS, - new LinkedBlockingQueue(), - 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())); - } - - /** - * 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(), - 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()); - } - - /** - * 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(), - 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 < 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 < 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 Callable callable(Runnable task, Object result) { - if (task == null) - throw new NullPointerException(); - return new RunnableAdapter(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 callable(Runnable task) { - if (task == null) - throw new NullPointerException(); - return new RunnableAdapter(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 callable(final PrivilegedAction action) { - if (action == null) - throw new NullPointerException(); - return new Callable() { - 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 callable(final PrivilegedExceptionAction action) { - if (action == null) - throw new NullPointerException(); - return new Callable() { - 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 Callable privilegedCallable(Callable callable) { - if (callable == null) - throw new NullPointerException(); - return new PrivilegedCallable(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 Callable privilegedCallableUsingCurrentClassLoader(Callable callable) { - if (callable == null) - throw new NullPointerException(); - return new PrivilegedCallableUsingCurrentClassLoader(callable); - } - - // Non-public classes supporting the public methods - - /** - * A callable that runs given task and returns given result - */ - static final class RunnableAdapter implements Callable { - final Runnable task; - final Object result; - RunnableAdapter(Runnable task, Object result) { - this.task = task; - this.result = result; - } - public Object call() { - task.run(); - return result; - } - } - - /** - * A callable that runs under established access control settings - */ - static final class PrivilegedCallable implements Callable { - private final AccessControlContext acc; - private final Callable task; - private Object result; - private Exception exception; - PrivilegedCallable(Callable task) { - this.task = task; - this.acc = AccessController.getContext(); - } - - public Object call() throws Exception { - AccessController.doPrivileged(new PrivilegedAction() { - public Object 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 implements Callable { - private final ClassLoader ccl; - private final AccessControlContext acc; - private final Callable task; - private Object result; - private Exception exception; - PrivilegedCallableUsingCurrentClassLoader(Callable task) { - this.task = task; - this.ccl = Thread.currentThread().getContextClassLoader(); - this.acc = AccessController.getContext(); - acc.checkPermission(new RuntimePermission("getContextClassLoader")); - acc.checkPermission(new RuntimePermission("setContextClassLoader")); - } - - public Object call() throws Exception { - AccessController.doPrivileged(new PrivilegedAction() { - public Object 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() { - 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 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 Future submit(Callable task) { - return e.submit(task); - } - public Future submit(Runnable task, Object result) { - return e.submit(task, result); - } - public List<Future> invokeAll(Collection tasks) - throws InterruptedException { - return e.invokeAll(tasks); - } - public List<Future> invokeAll(Collection tasks, - long timeout, TimeUnit unit) - throws InterruptedException { - return e.invokeAll(tasks, timeout, unit); - } - public Object invokeAny(Collection tasks) - throws InterruptedException, ExecutionException { - return e.invokeAny(tasks); - } - public Object invokeAny(Collection 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 ScheduledFuture schedule(Callable 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/src/actors/scala/actors/threadpool/Future.java b/src/actors/scala/actors/threadpool/Future.java deleted file mode 100644 index 5e1b3d414a..0000000000 --- a/src/actors/scala/actors/threadpool/Future.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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 scala.actors.threadpool; -import scala.actors.threadpool.*; // for javadoc (till 6280605 is fixed) - -/** - * 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<?></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<String> future - * = executor.submit(new Callable<String>() { - * 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<String> future = - * new FutureTask<String>(new Callable<String>() { - * 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 - */ -public interface Future { - - /** - * 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 - */ - Object 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 - */ - Object get(long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException; -} diff --git a/src/actors/scala/actors/threadpool/FutureTask.java b/src/actors/scala/actors/threadpool/FutureTask.java deleted file mode 100644 index d4dcfe38b3..0000000000 --- a/src/actors/scala/actors/threadpool/FutureTask.java +++ /dev/null @@ -1,310 +0,0 @@ -/* - * 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 scala.actors.threadpool; - -import scala.actors.threadpool.*; // for javadoc -import scala.actors.threadpool.helpers.*; - -/** - * 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 - */ -public class FutureTask implements RunnableFuture { - - /** State value representing that task is ready to run */ - private static final int READY = 0; - /** 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 callable; - /** The result to return from get() */ - private Object result; - /** The exception to throw from get() */ - private Throwable exception; - - private int state; - - /** - * 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; - - /** - * 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 callable) { - if (callable == null) - throw new NullPointerException(); - this.callable = 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<?> f = new FutureTask<Object>(runnable, null)</tt> - * @throws NullPointerException if runnable is null - */ - public FutureTask(Runnable runnable, Object result) { - this(Executors.callable(runnable, result)); - } - - public synchronized boolean isCancelled() { - return state == CANCELLED; - } - - public synchronized boolean isDone() { - return ranOrCancelled() && runner == null; - } - - public boolean cancel(boolean mayInterruptIfRunning) { - synchronized (this) { - if (ranOrCancelled()) return false; - state = CANCELLED; - if (mayInterruptIfRunning) { - Thread r = runner; - if (r != null) r.interrupt(); - } - runner = null; - notifyAll(); - } - done(); - return true; - } - - /** - * @throws CancellationException {@inheritDoc} - */ - public synchronized Object get() - throws InterruptedException, ExecutionException - { - waitFor(); - return getResult(); - } - - /** - * @throws CancellationException {@inheritDoc} - */ - public synchronized Object get(long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException - { - waitFor(unit.toNanos(timeout)); - return getResult(); - } - - /** - * 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(Object v) { - setCompleted(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) { - setFailed(t); - } - - /** - * Sets this Future to the result of its computation - * unless it has been cancelled. - */ - public void run() { - synchronized (this) { - if (state != READY) return; - state = RUNNING; - runner = Thread.currentThread(); - } - try { - set(callable.call()); - } - catch (Throwable ex) { - setException(ex); - } - } - - /** - * 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() { - synchronized (this) { - if (state != READY) return false; - state = RUNNING; - runner = Thread.currentThread(); - } - try { - callable.call(); // don't set result - synchronized (this) { - runner = null; - if (state == RUNNING) { - state = READY; - return true; - } - else { - return false; - } - } - } - catch (Throwable ex) { - setException(ex); - return false; - } - } - - // PRE: lock owned - private boolean ranOrCancelled() { - return (state & (RAN | CANCELLED)) != 0; - } - - /** - * Marks the task as completed. - * @param result the result of a task. - */ - private void setCompleted(Object result) { - synchronized (this) { - if (ranOrCancelled()) return; - this.state = RAN; - this.result = result; - this.runner = null; - notifyAll(); - } - - // invoking callbacks *after* setting future as completed and - // outside the synchronization block makes it safe to call - // interrupt() from within callback code (in which case it will be - // ignored rather than cause deadlock / illegal state exception) - done(); - } - - /** - * Marks the task as failed. - * @param exception the cause of abrupt completion. - */ - private void setFailed(Throwable exception) { - synchronized (this) { - if (ranOrCancelled()) return; - this.state = RAN; - this.exception = exception; - this.runner = null; - notifyAll(); - } - - // invoking callbacks *after* setting future as completed and - // outside the synchronization block makes it safe to call - // interrupt() from within callback code (in which case it will be - // ignored rather than cause deadlock / illegal state exception) - done(); - } - - /** - * Waits for the task to complete. - * PRE: lock owned - */ - private void waitFor() throws InterruptedException { - while (!isDone()) { - wait(); - } - } - - /** - * Waits for the task to complete for timeout nanoseconds or throw - * TimeoutException if still not completed after that - * PRE: lock owned - */ - private void waitFor(long nanos) throws InterruptedException, TimeoutException { - if (nanos < 0) throw new IllegalArgumentException(); - if (isDone()) return; - long deadline = Utils.nanoTime() + nanos; - while (nanos > 0) { - TimeUnit.NANOSECONDS.timedWait(this, nanos); - if (isDone()) return; - nanos = deadline - Utils.nanoTime(); - } - throw new TimeoutException(); - } - - /** - * Gets the result of the task. - * - * PRE: task completed - * PRE: lock owned - */ - private Object getResult() throws ExecutionException { - if (state == CANCELLED) { - throw new CancellationException(); - } - if (exception != null) { - throw new ExecutionException(exception); - } - return result; - } - - // todo: consider - //public String toString() { - // return callable.toString(); - //} -} diff --git a/src/actors/scala/actors/threadpool/LinkedBlockingQueue.java b/src/actors/scala/actors/threadpool/LinkedBlockingQueue.java deleted file mode 100644 index 15f1085ec6..0000000000 --- a/src/actors/scala/actors/threadpool/LinkedBlockingQueue.java +++ /dev/null @@ -1,843 +0,0 @@ -/* - * 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 scala.actors.threadpool; - -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.ReentrantLock; -import java.util.AbstractQueue; -import java.util.Collection; -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * An optionally-bounded {@linkplain BlockingQueue blocking queue} based on - * linked nodes. - * 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 java.util.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. - * - * Visibility between writers and readers is provided as follows: - * - * Whenever an element is enqueued, the putLock is acquired and - * count updated. A subsequent reader guarantees visibility to the - * enqueued Node by either acquiring the putLock (via fullyLock) - * or by acquiring the takeLock, and then reading n = count.get(); - * this gives visibility to the first n items. - * - * To implement weakly consistent iterators, it appears we need to - * keep all Nodes GC-reachable from a predecessor dequeued Node. - * That would cause two problems: - * - allow a rogue Iterator to cause unbounded memory retention - * - cause cross-generational linking of old Nodes to new Nodes if - * a Node was tenured while live, which generational GCs have a - * hard time dealing with, causing repeated major collections. - * However, only non-deleted Nodes need to be reachable from - * dequeued Nodes, and reachability does not necessarily have to - * be of the kind understood by the GC. We use the trick of - * linking a Node that has just been dequeued to itself. Such a - * self-link implicitly means to advance to head.next. - */ - - /** - * Linked list node class - */ - static class Node<E> { - E item; - - /** - * One of: - * - the real successor Node - * - this Node, meaning the successor is head.next - * - null, meaning there is no successor (this is the last node) - */ - Node<E> next; - - Node(E x) { item = x; } - } - - /** 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. - * Invariant: head.item == null - */ - private transient Node<E> head; - - /** - * Tail of linked list. - * Invariant: last.next == null - */ - 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 enqueue(E x) { - // assert putLock.isHeldByCurrentThread(); - // assert last.next == null; - last = last.next = new Node<E>(x); - } - - /** - * Removes a node from head of queue. - * - * @return the node - */ - private E dequeue() { - // assert takeLock.isHeldByCurrentThread(); - // assert head.item == null; - Node<E> h = head; - Node<E> first = h.next; - h.next = h; // help GC - head = first; - E x = first.item; - first.item = null; - return x; - } - - /** - * Lock to prevent both puts and takes. - */ - void fullyLock() { - putLock.lock(); - takeLock.lock(); - } - - /** - * Unlock to allow both puts and takes. - */ - void fullyUnlock() { - takeLock.unlock(); - putLock.unlock(); - } - -// /** -// * Tells whether both locks are held by current thread. -// */ -// boolean isFullyLocked() { -// return (putLock.isHeldByCurrentThread() && -// takeLock.isHeldByCurrentThread()); -// } - - /** - * Creates a {@code LinkedBlockingQueue} with a capacity of - * {@link Integer#MAX_VALUE}. - */ - public LinkedBlockingQueue() { - this(Integer.MAX_VALUE); - } - - /** - * Creates a {@code LinkedBlockingQueue} with the given (fixed) capacity. - * - * @param capacity the capacity of this queue - * @throws IllegalArgumentException if {@code capacity} 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 {@code LinkedBlockingQueue} with a capacity of - * {@link Integer#MAX_VALUE}, initially containing the elements of the - * given collection, - * added in traversal order of the collection's iterator. - * - * @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); - final ReentrantLock putLock = this.putLock; - putLock.lock(); // Never contended, but necessary for visibility - try { - int n = 0; - for (E e : c) { - if (e == null) - throw new NullPointerException(); - if (n == capacity) - throw new IllegalStateException("Queue full"); - enqueue(e); - ++n; - } - count.set(n); - } finally { - putLock.unlock(); - } - } - - - // 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 {@code size} of this queue. - * - * <p>Note that you <em>cannot</em> always tell if an attempt to insert - * an element will succeed by inspecting {@code remainingCapacity} - * 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. - */ - while (count.get() == capacity) { - notFull.await(); - } - enqueue(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 {@code true} if successful, or {@code false} 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 { - while (count.get() == capacity) { - if (nanos <= 0) - return false; - nanos = notFull.awaitNanos(nanos); - } - enqueue(e); - c = count.getAndIncrement(); - if (c + 1 < capacity) - notFull.signal(); - } 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 {@code true} upon success and {@code false} if this queue - * is full. - * When using a capacity-restricted queue, this method is generally - * preferable to method {@link BlockingQueue#add add}, which can fail to - * 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) { - enqueue(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 { - while (count.get() == 0) { - notEmpty.await(); - } - x = dequeue(); - 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 { - while (count.get() == 0) { - if (nanos <= 0) - return null; - nanos = notEmpty.awaitNanos(nanos); - } - x = dequeue(); - c = count.getAndDecrement(); - if (c > 1) - notEmpty.signal(); - } 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 = dequeue(); - 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(); - } - } - - /** - * Unlinks interior Node p with predecessor trail. - */ - void unlink(Node<E> p, Node<E> trail) { - // assert isFullyLocked(); - // p.next is not changed, to allow iterators that are - // traversing p to maintain their weak-consistency guarantee. - p.item = null; - trail.next = p.next; - if (last == p) - last = trail; - if (count.getAndDecrement() == capacity) - notFull.signal(); - } - - /** - * Removes a single instance of the specified element from this queue, - * if it is present. More formally, removes an element {@code e} such - * that {@code o.equals(e)}, if this queue contains one or more such - * elements. - * Returns {@code true} if this queue contained the specified element - * (or equivalently, if this queue changed as a result of the call). - * - * @param o element to be removed from this queue, if present - * @return {@code true} if this queue changed as a result of the call - */ - public boolean remove(Object o) { - if (o == null) return false; - fullyLock(); - try { - for (Node<E> trail = head, p = trail.next; - p != null; - trail = p, p = p.next) { - if (o.equals(p.item)) { - unlink(p, trail); - return true; - } - } - return false; - } finally { - fullyUnlock(); - } - } - - /** - * 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 - * {@code null}. - * - * <p>Like the {@link #toArray()} method, this method acts as bridge between - * array-based and collection-based APIs. Further, this method allows - * precise control over the runtime type of the output array, and may, - * under certain circumstances, be used to save allocation costs. - * - * <p>Suppose {@code x} is a queue known to contain only strings. - * The following code can be used to dump the queue into a newly - * allocated array of {@code String}: - * - * <pre> - * String[] y = x.toArray(new String[0]);</pre> - * - * Note that {@code toArray(new Object[0])} is identical in function to - * {@code toArray()}. - * - * @param a the array into which the elements of the 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 - */ - @SuppressWarnings("unchecked") - 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<E> 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 { - for (Node<E> p, h = head; (p = h.next) != null; h = p) { - h.next = h; - p.item = null; - } - head = last; - // assert head.item == null && head.next == null; - if (count.getAndSet(0) == capacity) - notFull.signal(); - } finally { - fullyUnlock(); - } - } - - /** - * @throws UnsupportedOperationException {@inheritDoc} - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException {@inheritDoc} - * @throws IllegalArgumentException {@inheritDoc} - */ - public int drainTo(Collection<? super E> c) { - return drainTo(c, Integer.MAX_VALUE); - } - - /** - * @throws UnsupportedOperationException {@inheritDoc} - * @throws ClassCastException {@inheritDoc} - * @throws NullPointerException {@inheritDoc} - * @throws IllegalArgumentException {@inheritDoc} - */ - public int drainTo(Collection<? super E> c, int maxElements) { - if (c == null) - throw new NullPointerException(); - if (c == this) - throw new IllegalArgumentException(); - boolean signalNotFull = false; - final ReentrantLock takeLock = this.takeLock; - takeLock.lock(); - try { - int n = Math.min(maxElements, count.get()); - // count.get provides visibility to first n Nodes - Node<E> h = head; - int i = 0; - try { - while (i < n) { - Node<E> p = h.next; - c.add(p.item); - p.item = null; - h.next = h; - h = p; - ++i; - } - return n; - } finally { - // Restore invariants even if c.add() threw - if (i > 0) { - // assert h.item == null; - head = h; - signalNotFull = (count.getAndAdd(-i) == capacity); - } - } - } finally { - takeLock.unlock(); - if (signalNotFull) - signalNotFull(); - } - } - - /** - * Returns an iterator over the elements in this queue in proper sequence. - * The returned {@code Iterator} is a "weakly consistent" iterator that - * will never throw {@link java.util.ConcurrentModificationException - * ConcurrentModificationException}, - * and guarantees to traverse elements as they existed upon - * construction of the iterator, and may (but is not guaranteed to) - * reflect any modifications subsequent to construction. - * - * @return an iterator over the elements in this queue in proper sequence - */ - public Iterator<E> iterator() { - return new Itr(); - } - - private class Itr implements Iterator<E> { - /* - * Basic weakly-consistent iterator. At all times hold the next - * item to hand out so that if hasNext() reports true, we will - * still have it to return even if lost race with a take etc. - */ - private Node<E> current; - private Node<E> lastRet; - private E currentElement; - - Itr() { - fullyLock(); - try { - current = head.next; - if (current != null) - currentElement = current.item; - } finally { - fullyUnlock(); - } - } - - public boolean hasNext() { - return current != null; - } - - /** - * Returns the next live successor of p, or null if no such. - * - * Unlike other traversal methods, iterators need to handle both: - * - dequeued nodes (p.next == p) - * - (possibly multiple) interior removed nodes (p.item == null) - */ - private Node<E> nextNode(Node<E> p) { - for (;;) { - Node<E> s = p.next; - if (s == p) - return head.next; - if (s == null || s.item != null) - return s; - p = s; - } - } - - public E next() { - fullyLock(); - try { - if (current == null) - throw new NoSuchElementException(); - E x = currentElement; - lastRet = current; - current = nextNode(current); - currentElement = (current == null) ? null : current.item; - return x; - } finally { - fullyUnlock(); - } - } - - public void remove() { - if (lastRet == null) - throw new IllegalStateException(); - fullyLock(); - try { - Node<E> node = lastRet; - lastRet = null; - for (Node<E> trail = head, p = trail.next; - p != null; - trail = p, p = p.next) { - if (p == node) { - unlink(p, trail); - break; - } - } - } finally { - fullyUnlock(); - } - } - } - - /** - * Save the state to a stream (that is, serialize it). - * - * @serialData The capacity is emitted (int), followed by all of - * its elements (each an {@code Object}) in the proper order, - * followed by a null - * @param s the stream - */ - private void writeObject(java.io.ObjectOutputStream s) - throws java.io.IOException { - - 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 (;;) { - @SuppressWarnings("unchecked") - E item = (E)s.readObject(); - if (item == null) - break; - add(item); - } - } -} diff --git a/src/actors/scala/actors/threadpool/Perf.java b/src/actors/scala/actors/threadpool/Perf.java deleted file mode 100644 index 0f262b444f..0000000000 --- a/src/actors/scala/actors/threadpool/Perf.java +++ /dev/null @@ -1,28 +0,0 @@ -package scala.actors.threadpool; - -/** - * Compilation stub for pre-1.4.2 JREs. Thanks to it, the whole backport - * package compiles and works with 1.4.2 as well as wih earlier JREs, and takes - * advantage of native Perf class when running on 1.4.2 while seamlessly - * falling back to System.currentTimeMillis() on previous JREs. This class - * should NOT be included in the binary distribution of backport. - * - * @author Dawid Kurzyniec - * @version 1.0 - */ -public final class Perf { - - private static final Perf perf = new Perf(); - - public static Perf getPerf() { return perf; } - - private Perf() {} - - public long highResCounter() { - return System.currentTimeMillis(); - } - - public long highResFrequency() { - return 1000L; - } -} diff --git a/src/actors/scala/actors/threadpool/Queue.java b/src/actors/scala/actors/threadpool/Queue.java deleted file mode 100644 index f952e9d94c..0000000000 --- a/src/actors/scala/actors/threadpool/Queue.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * 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 scala.actors.threadpool; - -import java.util.Collection; - -/** - * A collection designed for holding elements prior to processing. - * Besides basic {@link java.util.Collection Collection} operations, - * queues provide additional insertion, extraction, and inspection - * operations. Each of these methods exists in two forms: one throws - * an exception if the operation fails, the other returns a special - * value (either <tt>null</tt> or <tt>false</tt>, depending on the - * operation). The latter form of the insert operation is designed - * specifically for use with capacity-restricted <tt>Queue</tt> - * implementations; in most implementations, insert operations cannot - * fail. - * - * <p> - * <table BORDER CELLPADDING=3 CELLSPACING=1> - * <tr> - * <td></td> - * <td ALIGN=CENTER><em>Throws exception</em></td> - * <td ALIGN=CENTER><em>Returns special value</em></td> - * </tr> - * <tr> - * <td><b>Insert</b></td> - * <td>{@link #add add(e)}</td> - * <td>{@link #offer offer(e)}</td> - * </tr> - * <tr> - * <td><b>Remove</b></td> - * <td>{@link #remove remove()}</td> - * <td>{@link #poll poll()}</td> - * </tr> - * <tr> - * <td><b>Examine</b></td> - * <td>{@link #element element()}</td> - * <td>{@link #peek peek()}</td> - * </tr> - * </table> - * - * <p>Queues typically, but do not necessarily, order elements in a - * FIFO (first-in-first-out) manner. Among the exceptions are - * priority queues, which order elements according to a supplied - * comparator, or the elements' natural ordering, and LIFO queues (or - * stacks) which order the elements LIFO (last-in-first-out). - * Whatever the ordering used, the <em>head</em> of the queue is that - * element which would be removed by a call to {@link #remove() } or - * {@link #poll()}. In a FIFO queue, all new elements are inserted at - * the <em> tail</em> of the queue. Other kinds of queues may use - * different placement rules. Every <tt>Queue</tt> implementation - * must specify its ordering properties. - * - * <p>The {@link #offer offer} method inserts an element if possible, - * otherwise returning <tt>false</tt>. This differs from the {@link - * java.util.Collection#add Collection.add} method, which can fail to - * add an element only by throwing an unchecked exception. The - * <tt>offer</tt> method is designed for use when failure is a normal, - * rather than exceptional occurrence, for example, in fixed-capacity - * (or "bounded") queues. - * - * <p>The {@link #remove()} and {@link #poll()} methods remove and - * return the head of the queue. - * Exactly which element is removed from the queue is a - * function of the queue's ordering policy, which differs from - * implementation to implementation. The <tt>remove()</tt> and - * <tt>poll()</tt> methods differ only in their behavior when the - * queue is empty: the <tt>remove()</tt> method throws an exception, - * while the <tt>poll()</tt> method returns <tt>null</tt>. - * - * <p>The {@link #element()} and {@link #peek()} methods return, but do - * not remove, the head of the queue. - * - * <p>The <tt>Queue</tt> interface does not define the <i>blocking queue - * methods</i>, which are common in concurrent programming. These methods, - * which wait for elements to appear or for space to become available, are - * defined in the {@link edu.emory.mathcs.backport.java.util.concurrent.BlockingQueue} interface, which - * extends this interface. - * - * <p><tt>Queue</tt> implementations generally do not allow insertion - * of <tt>null</tt> elements, although some implementations, such as - * {@link LinkedList}, do not prohibit insertion of <tt>null</tt>. - * Even in the implementations that permit it, <tt>null</tt> should - * not be inserted into a <tt>Queue</tt>, as <tt>null</tt> is also - * used as a special return value by the <tt>poll</tt> method to - * indicate that the queue contains no elements. - * - * <p><tt>Queue</tt> implementations generally do not define - * element-based versions of methods <tt>equals</tt> and - * <tt>hashCode</tt> but instead inherit the identity based versions - * from class <tt>Object</tt>, because element-based equality is not - * always well-defined for queues with the same elements but different - * ordering properties. - * - * - * <p>This interface is a member of the - * <a href="{@docRoot}/../technotes/guides/collections/index.html"> - * Java Collections Framework</a>. - * - * @see java.util.Collection - * @see LinkedList - * @see PriorityQueue - * @see edu.emory.mathcs.backport.java.util.concurrent.LinkedBlockingQueue - * @see edu.emory.mathcs.backport.java.util.concurrent.BlockingQueue - * @see edu.emory.mathcs.backport.java.util.concurrent.ArrayBlockingQueue - * @see edu.emory.mathcs.backport.java.util.concurrent.LinkedBlockingQueue - * @see edu.emory.mathcs.backport.java.util.concurrent.PriorityBlockingQueue - * @since 1.5 - * @author Doug Lea - */ -public interface Queue extends Collection { - /** - * 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. - * - * @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 and - * this queue not permit null elements - * @throws IllegalArgumentException if some property of this element - * prevents it from being added to this queue - */ - boolean add(Object e); - - /** - * Inserts the specified element into this queue if it is possible to do - * so immediately without violating capacity restrictions. - * 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 and - * this queue does not permit null elements - * @throws IllegalArgumentException if some property of this element - * prevents it from being added to this queue - */ - boolean offer(Object e); - - /** - * Retrieves and removes the head of this queue. This method differs - * from {@link #poll poll} only in that it throws an exception if this - * queue is empty. - * is empty. - * - * @return the head of this queue - * @throws NoSuchElementException if this queue is empty - */ - Object remove(); - - /** - * Retrieves and removes the head of this queue, - * or returns <tt>null</tt> if this queue is empty. - * - * @return the head of this queue, or <tt>null</tt> if this queue is empty - */ - Object poll(); - - /** - * Retrieves, but does not remove, the head of this queue. This method - * differs from {@link #peek peek} only in that it throws an exception - * if this queue is empty. - * - * @return the head of this queue - * @throws NoSuchElementException if this queue is empty - */ - Object element(); - - /** - * Retrieves, but does not remove, the head of this queue, - * or returns <tt>null</tt> if this queue is empty. - * - * @return the head of this queue, or <tt>null</tt> if this queue is empty - */ - Object peek(); -} diff --git a/src/actors/scala/actors/threadpool/RejectedExecutionException.java b/src/actors/scala/actors/threadpool/RejectedExecutionException.java deleted file mode 100644 index 1b61d35974..0000000000 --- a/src/actors/scala/actors/threadpool/RejectedExecutionException.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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 scala.actors.threadpool; - -/** - * 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/src/actors/scala/actors/threadpool/RejectedExecutionHandler.java b/src/actors/scala/actors/threadpool/RejectedExecutionHandler.java deleted file mode 100644 index 86e6d18a40..0000000000 --- a/src/actors/scala/actors/threadpool/RejectedExecutionHandler.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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 scala.actors.threadpool; - -/** - * 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 - * {@link ThreadPoolExecutor#execute execute} 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. - * - * <p>In the absence of other alternatives, the method may throw - * an unchecked {@link RejectedExecutionException}, which will be - * propagated to the caller of {@code execute}. - * - * @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/src/actors/scala/actors/threadpool/RunnableFuture.java b/src/actors/scala/actors/threadpool/RunnableFuture.java deleted file mode 100644 index bbd63a2d92..0000000000 --- a/src/actors/scala/actors/threadpool/RunnableFuture.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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 scala.actors.threadpool; - -/** - * 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 - */ -public interface RunnableFuture extends Runnable, Future { - /** - * Sets this Future to the result of its computation - * unless it has been cancelled. - */ - void run(); -} diff --git a/src/actors/scala/actors/threadpool/SynchronousQueue.java b/src/actors/scala/actors/threadpool/SynchronousQueue.java deleted file mode 100644 index 739b0043dd..0000000000 --- a/src/actors/scala/actors/threadpool/SynchronousQueue.java +++ /dev/null @@ -1,833 +0,0 @@ -/* - * 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 scala.actors.threadpool; -import scala.actors.threadpool.locks.*; -//import edu.emory.mathcs.backport.java.util.*; -import java.util.Collection; -import java.util.Iterator; -import scala.actors.threadpool.helpers.Utils; -import java.util.NoSuchElementException; - -/** - * 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. 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 - */ -public class SynchronousQueue extends AbstractQueue - implements BlockingQueue, java.io.Serializable { - private static final long serialVersionUID = -3223113410248163686L; - - /* - This implementation divides actions into two cases for puts: - - * An arriving producer that does not already have a waiting consumer - creates a node holding item, and then waits for a consumer to take it. - * An arriving producer that does already have a waiting consumer fills - the slot node created by the consumer, and notifies it to continue. - - And symmetrically, two for takes: - - * An arriving consumer that does not already have a waiting producer - creates an empty slot node, and then waits for a producer to fill it. - * An arriving consumer that does already have a waiting producer takes - item from the node created by the producer, and notifies it to continue. - - When a put or take waiting for the actions of its counterpart - aborts due to interruption or timeout, it marks the node - it created as "CANCELLED", which causes its counterpart to retry - the entire put or take sequence. - - This requires keeping two simple queues, waitingProducers and - waitingConsumers. Each of these can be FIFO (preserves fairness) - or LIFO (improves throughput). - */ - - /** Lock protecting both wait queues */ - private final ReentrantLock qlock; - /** Queue holding waiting puts */ - private final WaitQueue waitingProducers; - /** Queue holding waiting takes */ - private final WaitQueue waitingConsumers; - - /** - * Creates a <tt>SynchronousQueue</tt> with nonfair access policy. - */ - public SynchronousQueue() { - this(false); - } - - /** - * Creates a <tt>SynchronousQueue</tt> with specified fairness policy. - * @param fair if true, threads contend in FIFO order for access; - * otherwise the order is unspecified. - */ - public SynchronousQueue(boolean fair) { - if (fair) { - qlock = new ReentrantLock(true); - waitingProducers = new FifoWaitQueue(); - waitingConsumers = new FifoWaitQueue(); - } - else { - qlock = new ReentrantLock(); - waitingProducers = new LifoWaitQueue(); - waitingConsumers = new LifoWaitQueue(); - } - } - - /** - * Queue to hold waiting puts/takes; specialized to Fifo/Lifo below. - * These queues have all transient fields, but are serializable - * in order to recover fairness settings when deserialized. - */ - static abstract class WaitQueue implements java.io.Serializable { - /** Creates, adds, and returns node for x. */ - abstract Node enq(Object x); - /** Removes and returns node, or null if empty. */ - abstract Node deq(); - /** Removes a cancelled node to avoid garbage retention. */ - abstract void unlink(Node node); - /** Returns true if a cancelled node might be on queue. */ - abstract boolean shouldUnlink(Node node); - } - - /** - * FIFO queue to hold waiting puts/takes. - */ - static final class FifoWaitQueue extends WaitQueue implements java.io.Serializable { - private static final long serialVersionUID = -3623113410248163686L; - private transient Node head; - private transient Node last; - - Node enq(Object x) { - Node p = new Node(x); - if (last == null) - last = head = p; - else - last = last.next = p; - return p; - } - - Node deq() { - Node p = head; - if (p != null) { - if ((head = p.next) == null) - last = null; - p.next = null; - } - return p; - } - - boolean shouldUnlink(Node node) { - return (node == last || node.next != null); - } - - void unlink(Node node) { - Node p = head; - Node trail = null; - while (p != null) { - if (p == node) { - Node next = p.next; - if (trail == null) - head = next; - else - trail.next = next; - if (last == node) - last = trail; - break; - } - trail = p; - p = p.next; - } - } - } - - /** - * LIFO queue to hold waiting puts/takes. - */ - static final class LifoWaitQueue extends WaitQueue implements java.io.Serializable { - private static final long serialVersionUID = -3633113410248163686L; - private transient Node head; - - Node enq(Object x) { - return head = new Node(x, head); - } - - Node deq() { - Node p = head; - if (p != null) { - head = p.next; - p.next = null; - } - return p; - } - - boolean shouldUnlink(Node node) { - // Return false if already dequeued or is bottom node (in which - // case we might retain at most one garbage node) - return (node == head || node.next != null); - } - - void unlink(Node node) { - Node p = head; - Node trail = null; - while (p != null) { - if (p == node) { - Node next = p.next; - if (trail == null) - head = next; - else - trail.next = next; - break; - } - trail = p; - p = p.next; - } - } - } - - /** - * Unlinks the given node from consumer queue. Called by cancelled - * (timeout, interrupt) waiters to avoid garbage retention in the - * absence of producers. - */ - private void unlinkCancelledConsumer(Node node) { - // Use a form of double-check to avoid unnecessary locking and - // traversal. The first check outside lock might - // conservatively report true. - if (waitingConsumers.shouldUnlink(node)) { - qlock.lock(); - try { - if (waitingConsumers.shouldUnlink(node)) - waitingConsumers.unlink(node); - } finally { - qlock.unlock(); - } - } - } - - /** - * Unlinks the given node from producer queue. Symmetric - * to unlinkCancelledConsumer. - */ - private void unlinkCancelledProducer(Node node) { - if (waitingProducers.shouldUnlink(node)) { - qlock.lock(); - try { - if (waitingProducers.shouldUnlink(node)) - waitingProducers.unlink(node); - } finally { - qlock.unlock(); - } - } - } - - /** - * Nodes each maintain an item and handle waits and signals for - * getting and setting it. The class extends - * AbstractQueuedSynchronizer to manage blocking, using AQS state - * 0 for waiting, 1 for ack, -1 for cancelled. - */ - static final class Node implements java.io.Serializable { - private static final long serialVersionUID = -3223113410248163686L; - - /** Synchronization state value representing that node acked */ - private static final int ACK = 1; - /** Synchronization state value representing that node cancelled */ - private static final int CANCEL = -1; - - int state = 0; - - /** The item being transferred */ - Object item; - /** Next node in wait queue */ - Node next; - - /** Creates a node with initial item */ - Node(Object x) { item = x; } - - /** Creates a node with initial item and next */ - Node(Object x, Node n) { item = x; next = n; } - - /** - * Takes item and nulls out field (for sake of GC) - * - * PRE: lock owned - */ - private Object extract() { - Object x = item; - item = null; - return x; - } - - /** - * Tries to cancel on interrupt; if so rethrowing, - * else setting interrupt state - * - * PRE: lock owned - */ - private void checkCancellationOnInterrupt(InterruptedException ie) - throws InterruptedException - { - if (state == 0) { - state = CANCEL; - notify(); - throw ie; - } - Thread.currentThread().interrupt(); - } - - /** - * Fills in the slot created by the consumer and signal consumer to - * continue. - */ - synchronized boolean setItem(Object x) { - if (state != 0) return false; - item = x; - state = ACK; - notify(); - return true; - } - - /** - * Removes item from slot created by producer and signal producer - * to continue. - */ - synchronized Object getItem() { - if (state != 0) return null; - state = ACK; - notify(); - return extract(); - } - - /** - * Waits for a consumer to take item placed by producer. - */ - synchronized void waitForTake() throws InterruptedException { - try { - while (state == 0) wait(); - } catch (InterruptedException ie) { - checkCancellationOnInterrupt(ie); - } - } - - /** - * Waits for a producer to put item placed by consumer. - */ - synchronized Object waitForPut() throws InterruptedException { - try { - while (state == 0) wait(); - } catch (InterruptedException ie) { - checkCancellationOnInterrupt(ie); - } - return extract(); - } - - private boolean attempt(long nanos) throws InterruptedException { - if (state != 0) return true; - if (nanos <= 0) { - state = CANCEL; - notify(); - return false; - } - long deadline = Utils.nanoTime() + nanos; - while (true) { - TimeUnit.NANOSECONDS.timedWait(this, nanos); - if (state != 0) return true; - nanos = deadline - Utils.nanoTime(); - if (nanos <= 0) { - state = CANCEL; - notify(); - return false; - } - } - } - - /** - * Waits for a consumer to take item placed by producer or time out. - */ - synchronized boolean waitForTake(long nanos) throws InterruptedException { - try { - if (!attempt(nanos)) return false; - } catch (InterruptedException ie) { - checkCancellationOnInterrupt(ie); - } - return true; - } - - /** - * Waits for a producer to put item placed by consumer, or time out. - */ - synchronized Object waitForPut(long nanos) throws InterruptedException { - try { - if (!attempt(nanos)) return null; - } catch (InterruptedException ie) { - checkCancellationOnInterrupt(ie); - } - return extract(); - } - } - - /** - * 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(Object e) throws InterruptedException { - if (e == null) throw new NullPointerException(); - final ReentrantLock qlock = this.qlock; - - for (;;) { - Node node; - boolean mustWait; - if (Thread.interrupted()) throw new InterruptedException(); - qlock.lock(); - try { - node = waitingConsumers.deq(); - if ( (mustWait = (node == null)) ) - node = waitingProducers.enq(e); - } finally { - qlock.unlock(); - } - - if (mustWait) { - try { - node.waitForTake(); - return; - } catch (InterruptedException ex) { - unlinkCancelledProducer(node); - throw ex; - } - } - - else if (node.setItem(e)) - return; - - // else consumer cancelled, so retry - } - } - - /** - * 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(Object e, long timeout, TimeUnit unit) throws InterruptedException { - if (e == null) throw new NullPointerException(); - long nanos = unit.toNanos(timeout); - final ReentrantLock qlock = this.qlock; - for (;;) { - Node node; - boolean mustWait; - if (Thread.interrupted()) throw new InterruptedException(); - qlock.lock(); - try { - node = waitingConsumers.deq(); - if ( (mustWait = (node == null)) ) - node = waitingProducers.enq(e); - } finally { - qlock.unlock(); - } - - if (mustWait) { - try { - boolean x = node.waitForTake(nanos); - if (!x) - unlinkCancelledProducer(node); - return x; - } catch (InterruptedException ex) { - unlinkCancelledProducer(node); - throw ex; - } - } - - else if (node.setItem(e)) - return true; - - // else consumer cancelled, so retry - } - } - - /** - * 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 Object take() throws InterruptedException { - final ReentrantLock qlock = this.qlock; - for (;;) { - Node node; - boolean mustWait; - - if (Thread.interrupted()) throw new InterruptedException(); - qlock.lock(); - try { - node = waitingProducers.deq(); - if ( (mustWait = (node == null)) ) - node = waitingConsumers.enq(null); - } finally { - qlock.unlock(); - } - - if (mustWait) { - try { - Object x = node.waitForPut(); - return (Object)x; - } catch (InterruptedException ex) { - unlinkCancelledConsumer(node); - throw ex; - } - } - else { - Object x = node.getItem(); - if (x != null) - return (Object)x; - // else cancelled, so retry - } - } - } - - /** - * 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 Object poll(long timeout, TimeUnit unit) throws InterruptedException { - long nanos = unit.toNanos(timeout); - final ReentrantLock qlock = this.qlock; - - for (;;) { - Node node; - boolean mustWait; - - if (Thread.interrupted()) throw new InterruptedException(); - qlock.lock(); - try { - node = waitingProducers.deq(); - if ( (mustWait = (node == null)) ) - node = waitingConsumers.enq(null); - } finally { - qlock.unlock(); - } - - if (mustWait) { - try { - Object x = node.waitForPut(nanos); - if (x == null) - unlinkCancelledConsumer(node); - return (Object)x; - } catch (InterruptedException ex) { - unlinkCancelledConsumer(node); - throw ex; - } - } - else { - Object x = node.getItem(); - if (x != null) - return (Object)x; - // else cancelled, so retry - } - } - } - - // Untimed nonblocking versions - - /** - * 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(Object e) { - if (e == null) throw new NullPointerException(); - final ReentrantLock qlock = this.qlock; - - for (;;) { - Node node; - qlock.lock(); - try { - node = waitingConsumers.deq(); - } finally { - qlock.unlock(); - } - if (node == null) - return false; - - else if (node.setItem(e)) - return true; - // else retry - } - } - - /** - * 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 Object poll() { - final ReentrantLock qlock = this.qlock; - for (;;) { - Node node; - qlock.lock(); - try { - node = waitingProducers.deq(); - } finally { - qlock.unlock(); - } - if (node == null) - return null; - - else { - Object x = node.getItem(); - if (x != null) - return (Object)x; - // else retry - } - } - } - - /** - * 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 object to be checked for containment in this queue - * @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 the given collection is empty - * @throws NullPointerException if the specified collection is null - */ - 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 Object peek() { - return null; - } - - - static class EmptyIterator implements Iterator { - public boolean hasNext() { - return false; - } - public Object 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 iterator() { - return new EmptyIterator(); - } - - - /** - * 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 Object[] toArray(Object[] 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 c) { - if (c == null) - throw new NullPointerException(); - if (c == this) - throw new IllegalArgumentException(); - int n = 0; - Object 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 c, int maxElements) { - if (c == null) - throw new NullPointerException(); - if (c == this) - throw new IllegalArgumentException(); - int n = 0; - Object e; - while (n < maxElements && (e = poll()) != null) { - c.add(e); - ++n; - } - return n; - } -} diff --git a/src/actors/scala/actors/threadpool/ThreadFactory.java b/src/actors/scala/actors/threadpool/ThreadFactory.java deleted file mode 100644 index ed6e90ccaa..0000000000 --- a/src/actors/scala/actors/threadpool/ThreadFactory.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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 scala.actors.threadpool; - -/** - * 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 {@code Thread}. Implementations may also initialize - * priority, name, daemon status, {@code ThreadGroup}, etc. - * - * @param r a runnable to be executed by new thread instance - * @return constructed thread, or {@code null} if the request to - * create a thread is rejected - */ - Thread newThread(Runnable r); -} diff --git a/src/actors/scala/actors/threadpool/ThreadPoolExecutor.java b/src/actors/scala/actors/threadpool/ThreadPoolExecutor.java deleted file mode 100644 index 11e35b034c..0000000000 --- a/src/actors/scala/actors/threadpool/ThreadPoolExecutor.java +++ /dev/null @@ -1,1968 +0,0 @@ -/* - * 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 scala.actors.threadpool; -import scala.actors.threadpool.locks.*; -import scala.actors.threadpool.helpers.Utils; -import java.util.HashSet; -import java.util.List; -import java.util.Iterator; -import java.util.ArrayList; -import java.util.ConcurrentModificationException; - -/** - * 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 {@code ThreadPoolExecutor} 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 {@code ThreadPoolExecutor} will automatically adjust the - * pool size (see {@link #getPoolSize}) - * according to the bounds set by - * corePoolSize (see {@link #getCorePoolSize}) and - * maximumPoolSize (see {@link #getMaximumPoolSize}). - * - * When a new task is submitted in method {@link #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 {@code Integer.MAX_VALUE}, 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 #setCorePoolSize} and {@link #setMaximumPoolSize}. </dd> - * - * <dt>On-demand construction</dt> - * - * <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 #prestartCoreThread} or {@link - * #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 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 {@code NORM_PRIORITY} 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 {@code ThreadFactory} fails to create a thread when asked - * by returning null from {@code newThread}, the executor will - * continue, but might not be able to execute any tasks. Threads - * should possess the "modifyThread" {@code RuntimePermission}. If - * worker threads or other threads using the pool do not possess this - * permission, service may be degraded: configuration changes may not - * take effect in a timely manner, and a shutdown pool may remain in a - * state in which termination is possible but not completed.</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 #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 #setKeepAliveTime}. Using a value - * of {@code Long.MAX_VALUE} {@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 - * #allowCoreThreadTimeOut(boolean)} can be used to apply this - * time-out policy to core threads as well, so long as the - * keepAliveTime value is non-zero. </dd> - * - * <dt>Queuing</dt> - * - * <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 #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 {@code - * execute} 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 {@code execute} 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 {@code protected} overridable {@link - * #beforeExecute} and {@link #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 #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 #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 #remove} and {@link #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 {@code shutdown} automatically. If - * you would like to ensure that unreferenced pools are reclaimed even - * if users forget to call {@link #shutdown}, then you must arrange - * that unused threads eventually die, by setting appropriate - * keep-alive times, using a lower bound of zero core threads and/or - * setting {@link #allowCoreThreadTimeOut(boolean)}. </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> {@code - * 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 { - /** - * The main pool control state, ctl, is an atomic integer packing - * two conceptual fields - * workerCount, indicating the effective number of threads - * runState, indicating whether running, shutting down etc - * - * In order to pack them into one int, we limit workerCount to - * (2^29)-1 (about 500 million) threads rather than (2^31)-1 (2 - * billion) otherwise representable. If this is ever an issue in - * the future, the variable can be changed to be an AtomicLong, - * and the shift/mask constants below adjusted. But until the need - * arises, this code is a bit faster and simpler using an int. - * - * The workerCount is the number of workers that have been - * permitted to start and not permitted to stop. The value may be - * transiently different from the actual number of live threads, - * for example when a ThreadFactory fails to create a thread when - * asked, and when exiting threads are still performing - * bookkeeping before terminating. The user-visible pool size is - * reported as the current size of the workers set. - * - * The runState provides the main lifecyle control, taking on values: - * - * RUNNING: Accept new tasks and process queued tasks - * SHUTDOWN: Don't accept new tasks, but process queued tasks - * STOP: Don't accept new tasks, don't process queued tasks, - * and interrupt in-progress tasks - * TIDYING: All tasks have terminated, workerCount is zero, - * the thread transitioning to state TIDYING - * will run the terminated() hook method - * TERMINATED: terminated() has completed - * - * The numerical order among these values matters, to allow - * ordered comparisons. The runState monotonically increases over - * time, but need not hit each state. The transitions are: - * - * RUNNING -> SHUTDOWN - * On invocation of shutdown(), perhaps implicitly in finalize() - * (RUNNING or SHUTDOWN) -> STOP - * On invocation of shutdownNow() - * SHUTDOWN -> TIDYING - * When both queue and pool are empty - * STOP -> TIDYING - * When pool is empty - * TIDYING -> TERMINATED - * When the terminated() hook method has completed - * - * Threads waiting in awaitTermination() will return when the - * state reaches TERMINATED. - * - * Detecting the transition from SHUTDOWN to TIDYING is less - * straightforward than you'd like because the queue may become - * empty after non-empty and vice versa during SHUTDOWN state, but - * we can only terminate if, after seeing that it is empty, we see - * that workerCount is 0 (which sometimes entails a recheck -- see - * below). - */ - private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); - private static final int COUNT_BITS = 29; // Integer.SIZE - 3; - private static final int CAPACITY = (1 << COUNT_BITS) - 1; - - // runState is stored in the high-order bits - private static final int RUNNING = -1 << COUNT_BITS; - private static final int SHUTDOWN = 0 << COUNT_BITS; - private static final int STOP = 1 << COUNT_BITS; - private static final int TIDYING = 2 << COUNT_BITS; - private static final int TERMINATED = 3 << COUNT_BITS; - - // Packing and unpacking ctl - private static int runStateOf(int c) { return c & ~CAPACITY; } - private static int workerCountOf(int c) { return c & CAPACITY; } - private static int ctlOf(int rs, int wc) { return rs | wc; } - - /* - * Bit field accessors that don't require unpacking ctl. - * These depend on the bit layout and on workerCount being never negative. - */ - - private static boolean runStateLessThan(int c, int s) { - return c < s; - } - - private static boolean runStateAtLeast(int c, int s) { - return c >= s; - } - - private static boolean isRunning(int c) { - return c < SHUTDOWN; - } - - /** - * Attempt to CAS-increment the workerCount field of ctl. - */ - private boolean compareAndIncrementWorkerCount(int expect) { - return ctl.compareAndSet(expect, expect + 1); - } - - /** - * Attempt to CAS-decrement the workerCount field of ctl. - */ - private boolean compareAndDecrementWorkerCount(int expect) { - return ctl.compareAndSet(expect, expect - 1); - } - - /** - * Decrements the workerCount field of ctl. This is called only on - * abrupt termination of a thread (see processWorkerExit). Other - * decrements are performed within getTask. - */ - private void decrementWorkerCount() { - do {} while (! compareAndDecrementWorkerCount(ctl.get())); - } - - /** - * The queue used for holding tasks and handing off to worker - * threads. We do not require that workQueue.poll() returning - * null necessarily means that workQueue.isEmpty(), so rely - * solely on isEmpty to see if the queue is empty (which we must - * do for example when deciding whether to transition from - * SHUTDOWN to TIDYING). This accommodates special-purpose - * queues such as DelayQueues for which poll() is allowed to - * return null even if it may later return non-null when delays - * expire. - */ - private final BlockingQueue workQueue; - - // TODO: DK: mainLock is used in lock(); try { ... } finally { unlock(); } - // Consider replacing with synchronized {} if performance reasons exist - /** - * Lock held on access to workers set and related bookkeeping. - * While we could use a concurrent set of some sort, it turns out - * to be generally preferable to use a lock. Among the reasons is - * that this serializes interruptIdleWorkers, which avoids - * unnecessary interrupt storms, especially during shutdown. - * Otherwise exiting threads would concurrently interrupt those - * that have not yet interrupted. It also simplifies some of the - * associated statistics bookkeeping of largestPoolSize etc. We - * also hold mainLock on shutdown and shutdownNow, for the sake of - * ensuring workers set is stable while separately checking - * permission to interrupt and actually interrupting. - */ - public final ReentrantLock mainLock = new ReentrantLock(); - - /** - * Set containing all worker threads in pool. Accessed only when - * holding mainLock. - */ - public final HashSet workers = new HashSet(); - - /** - * Wait condition to support awaitTermination - */ - private final Condition termination = mainLock.newCondition(); - - /** - * Tracks largest attained pool size. Accessed only under - * mainLock. - */ - private int largestPoolSize; - - /** - * Counter for completed tasks. Updated only on termination of - * worker threads. Accessed only under mainLock. - */ - private long completedTaskCount; - - /* - * All user control parameters are declared as volatiles so that - * ongoing actions are based on freshest values, but without need - * for locking, since no internal invariants depend on them - * changing synchronously with respect to other actions. - */ - - /** - * Factory for new threads. All threads are created using this - * factory (via method addWorker). All callers must be prepared - * for addWorker to fail, which may reflect a system or user's - * policy limiting the number of threads. Even though it is not - * treated as an error, failure to create threads may result in - * new tasks being rejected or existing ones remaining stuck in - * the queue. On the other hand, no special precautions exist to - * handle OutOfMemoryErrors that might be thrown while trying to - * create threads, since there is generally no recourse from - * within this class. - */ - private volatile ThreadFactory threadFactory; - - /** - * Handler called when saturated or shutdown in execute. - */ - private volatile RejectedExecutionHandler handler; - - /** - * Timeout in nanoseconds for idle threads waiting for work. - * Threads use this timeout when there are more than corePoolSize - * present or if allowCoreThreadTimeOut. Otherwise they wait - * forever for new work. - */ - private volatile long keepAliveTime; - - /** - * If false (default), core threads stay alive even when idle. - * If true, core threads use keepAliveTime to time out waiting - * for work. - */ - private volatile boolean allowCoreThreadTimeOut; - - /** - * Core pool size is the minimum number of workers to keep alive - * (and not allow to time out etc) unless allowCoreThreadTimeOut - * is set, in which case the minimum is zero. - */ - private volatile int corePoolSize; - - /** - * Maximum pool size. Note that the actual maximum is internally - * bounded by CAPACITY. - */ - private volatile int maximumPoolSize; - - /** - * The default rejected execution handler - */ - private static final RejectedExecutionHandler defaultHandler = - new AbortPolicy(); - - /** - * Permission required for callers of shutdown and shutdownNow. - * We additionally require (see checkShutdownAccess) that callers - * have permission to actually interrupt threads in the worker set - * (as governed by Thread.interrupt, which relies on - * ThreadGroup.checkAccess, which in turn relies on - * SecurityManager.checkAccess). Shutdowns are attempted only if - * these checks pass. - * - * All actual invocations of Thread.interrupt (see - * interruptIdleWorkers and interruptWorkers) ignore - * SecurityExceptions, meaning that the attempted interrupts - * silently fail. In the case of shutdown, they should not fail - * unless the SecurityManager has inconsistent policies, sometimes - * allowing access to a thread and sometimes not. In such cases, - * failure to actually interrupt threads may disable or delay full - * termination. Other uses of interruptIdleWorkers are advisory, - * and failure to actually interrupt will merely delay response to - * configuration changes so is not handled exceptionally. - */ - private static final RuntimePermission shutdownPerm = - new RuntimePermission("modifyThread"); - - /** - * Class Worker mainly maintains interrupt control state for - * threads running tasks, along with other minor bookkeeping. This - * class opportunistically extends ReentrantLock to simplify - * acquiring and releasing a lock surrounding each task execution. - * This protects against interrupts that are intended to wake up a - * worker thread waiting for a task from instead interrupting a - * task being run. - */ - public final class Worker extends ReentrantLock implements Runnable { - /** - * This class will never be serialized, but we provide a - * serialVersionUID to suppress a javac warning. - */ - private static final long serialVersionUID = 6138294804551838833L; - - /** Thread this worker is running in. Null if factory fails. */ - public final Thread thread; - /** Initial task to run. Possibly null. */ - Runnable firstTask; - /** Per-thread task counter */ - volatile long completedTasks; - - /** - * Creates with given first task and thread from ThreadFactory. - * @param firstTask the first task (null if none) - */ - Worker(Runnable firstTask) { - this.firstTask = firstTask; - this.thread = getThreadFactory().newThread(this); - } - - /** Delegates main run loop to outer runWorker */ - public void run() { - runWorker(this); - } - } - - /* - * Methods for setting control state - */ - - /** - * Transitions runState to given target, or leaves it alone if - * already at least the given target. - * - * @param targetState the desired state, either SHUTDOWN or STOP - * (but not TIDYING or TERMINATED -- use tryTerminate for that) - */ - private void advanceRunState(int targetState) { - for (;;) { - int c = ctl.get(); - if (runStateAtLeast(c, targetState) || - ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c)))) - break; - } - } - - /** - * Transitions to TERMINATED state if either (SHUTDOWN and pool - * and queue empty) or (STOP and pool empty). If otherwise - * eligible to terminate but workerCount is nonzero, interrupts an - * idle worker to ensure that shutdown signals propagate. This - * method must be called following any action that might make - * termination possible -- reducing worker count or removing tasks - * from the queue during shutdown. The method is non-private to - * allow access from ScheduledThreadPoolExecutor. - */ - final void tryTerminate() { - for (;;) { - int c = ctl.get(); - if (isRunning(c) || - runStateAtLeast(c, TIDYING) || - (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty())) - return; - if (workerCountOf(c) != 0) { // Eligible to terminate - interruptIdleWorkers(ONLY_ONE); - return; - } - - final ReentrantLock mainLock = this.mainLock; - mainLock.lock(); - try { - if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) { - try { - terminated(); - } finally { - ctl.set(ctlOf(TERMINATED, 0)); - termination.signalAll(); - } - return; - } - } finally { - mainLock.unlock(); - } - // else retry on failed CAS - } - } - - /* - * Methods for controlling interrupts to worker threads. - */ - - /** - * If there is a security manager, makes sure caller has - * permission to shut down threads in general (see shutdownPerm). - * If this passes, additionally makes sure the caller is allowed - * to interrupt each worker thread. This might not be true even if - * first check passed, if the SecurityManager treats some threads - * specially. - */ - private void checkShutdownAccess() { - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkPermission(shutdownPerm); - final ReentrantLock mainLock = this.mainLock; - mainLock.lock(); - try { - for (Iterator itr = workers.iterator(); itr.hasNext();) { - Worker w = (Worker)itr.next(); - security.checkAccess(w.thread); - } - } finally { - mainLock.unlock(); - } - } - } - - /** - * Interrupts all threads, even if active. Ignores SecurityExceptions - * (in which case some threads may remain uninterrupted). - */ - private void interruptWorkers() { - final ReentrantLock mainLock = this.mainLock; - mainLock.lock(); - try { - for (Iterator itr = workers.iterator(); itr.hasNext();) { - Worker w = (Worker)itr.next(); - try { - w.thread.interrupt(); - } catch (SecurityException ignore) { - } - } - } finally { - mainLock.unlock(); - } - } - - /** - * Interrupts threads that might be waiting for tasks (as - * indicated by not being locked) so they can check for - * termination or configuration changes. Ignores - * SecurityExceptions (in which case some threads may remain - * uninterrupted). - * - * @param onlyOne If true, interrupt at most one worker. This is - * called only from tryTerminate when termination is otherwise - * enabled but there are still other workers. In this case, at - * most one waiting worker is interrupted to propagate shutdown - * signals in case all threads are currently waiting. - * Interrupting any arbitrary thread ensures that newly arriving - * workers since shutdown began will also eventually exit. - * To guarantee eventual termination, it suffices to always - * interrupt only one idle worker, but shutdown() interrupts all - * idle workers so that redundant workers exit promptly, not - * waiting for a straggler task to finish. - */ - private void interruptIdleWorkers(boolean onlyOne) { - final ReentrantLock mainLock = this.mainLock; - mainLock.lock(); - try { - Iterator it = workers.iterator(); - while (it.hasNext()) { - Worker w = (Worker)it.next(); - Thread t = w.thread; - if (!t.isInterrupted() && w.tryLock()) { - try { - t.interrupt(); - } catch (SecurityException ignore) { - } finally { - w.unlock(); - } - } - if (onlyOne) - break; - } - } finally { - mainLock.unlock(); - } - } - - /** - * Common form of interruptIdleWorkers, to avoid having to - * remember what the boolean argument means. - */ - private void interruptIdleWorkers() { - interruptIdleWorkers(false); - } - - private static final boolean ONLY_ONE = true; - - /** - * Ensures that unless the pool is stopping, the current thread - * does not have its interrupt set. This requires a double-check - * of state in case the interrupt was cleared concurrently with a - * shutdownNow -- if so, the interrupt is re-enabled. - */ - private void clearInterruptsForTaskRun() { - if (runStateLessThan(ctl.get(), STOP) && - Thread.interrupted() && - runStateAtLeast(ctl.get(), STOP)) - Thread.currentThread().interrupt(); - } - - /* - * Misc utilities, most of which are also exported to - * ScheduledThreadPoolExecutor - */ - - /** - * Invokes the rejected execution handler for the given command. - * Package-protected for use by ScheduledThreadPoolExecutor. - */ - final void reject(Runnable command) { - handler.rejectedExecution(command, this); - } - - /** - * Performs any further cleanup following run state transition on - * invocation of shutdown. A no-op here, but used by - * ScheduledThreadPoolExecutor to cancel delayed tasks. - */ - void onShutdown() { - } - - /** - * State check needed by ScheduledThreadPoolExecutor to - * enable running tasks during shutdown. - * - * @param shutdownOK true if should return true if SHUTDOWN - */ - final boolean isRunningOrShutdown(boolean shutdownOK) { - int rs = runStateOf(ctl.get()); - return rs == RUNNING || (rs == SHUTDOWN && shutdownOK); - } - - /** - * Drains the task queue into a new list, normally using - * drainTo. But if the queue is a DelayQueue or any other kind of - * queue for which poll or drainTo may fail to remove some - * elements, it deletes them one by one. - */ - private List drainQueue() { - BlockingQueue q = workQueue; - List<Runnable> taskList = new ArrayList<Runnable>(); - q.drainTo(taskList); - if (!q.isEmpty()) { - Runnable[] arr = (Runnable[])q.toArray(new Runnable[0]); - for (int i=0; i<arr.length; i++) { - Runnable r = arr[i]; - if (q.remove(r)) - taskList.add(r); - } - } - return taskList; - } - - /* - * Methods for creating, running and cleaning up after workers - */ - - /** - * Checks if a new worker can be added with respect to current - * pool state and the given bound (either core or maximum). If so, - * the worker count is adjusted accordingly, and, if possible, a - * new worker is created and started running firstTask as its - * first task. This method returns false if the pool is stopped or - * eligible to shut down. It also returns false if the thread - * factory fails to create a thread when asked, which requires a - * backout of workerCount, and a recheck for termination, in case - * the existence of this worker was holding up termination. - * - * @param firstTask the task the new thread should run first (or - * null if none). Workers are created with an initial first task - * (in method execute()) to bypass queuing when there are fewer - * than corePoolSize threads (in which case we always start one), - * or when the queue is full (in which case we must bypass queue). - * Initially idle threads are usually created via - * prestartCoreThread or to replace other dying workers. - * - * @param core if true use corePoolSize as bound, else - * maximumPoolSize. (A boolean indicator is used here rather than a - * value to ensure reads of fresh values after checking other pool - * state). - * @return true if successful - */ - private boolean addWorker(Runnable firstTask, boolean core) { - retry: - for (;;) { - int c = ctl.get(); - int rs = runStateOf(c); - - // Check if queue empty only if necessary. - if (rs >= SHUTDOWN && - ! (rs == SHUTDOWN && - firstTask == null && - ! workQueue.isEmpty())) - return false; - - for (;;) { - int wc = workerCountOf(c); - if (wc >= CAPACITY || - wc >= (core ? corePoolSize : maximumPoolSize)) - return false; - if (compareAndIncrementWorkerCount(c)) - break retry; - c = ctl.get(); // Re-read ctl - if (runStateOf(c) != rs) - continue retry; - // else CAS failed due to workerCount change; retry inner loop - } - } - - Worker w = new Worker(firstTask); - Thread t = w.thread; - - final ReentrantLock mainLock = this.mainLock; - mainLock.lock(); - try { - // Recheck while holding lock. - // Back out on ThreadFactory failure or if - // shut down before lock acquired. - int c = ctl.get(); - int rs = runStateOf(c); - - if (t == null || - (rs >= SHUTDOWN && - ! (rs == SHUTDOWN && - firstTask == null))) { - decrementWorkerCount(); - tryTerminate(); - return false; - } - - workers.add(w); - - int s = workers.size(); - if (s > largestPoolSize) - largestPoolSize = s; - } finally { - mainLock.unlock(); - } - - t.start(); - // It is possible (but unlikely) for a thread to have been - // added to workers, but not yet started, during transition to - // STOP, which could result in a rare missed interrupt, - // because Thread.interrupt is not guaranteed to have any effect - // on a non-yet-started Thread (see Thread#interrupt). - if (runStateOf(ctl.get()) == STOP && ! t.isInterrupted()) - t.interrupt(); - - return true; - } - - /** - * Performs cleanup and bookkeeping for a dying worker. Called - * only from worker threads. Unless completedAbruptly is set, - * assumes that workerCount has already been adjusted to account - * for exit. This method removes thread from worker set, and - * possibly terminates the pool or replaces the worker if either - * it exited due to user task exception or if fewer than - * corePoolSize workers are running or queue is non-empty but - * there are no workers. - * - * @param w the worker - * @param completedAbruptly if the worker died due to user exception - */ - private void processWorkerExit(Worker w, boolean completedAbruptly) { - if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted - decrementWorkerCount(); - - final ReentrantLock mainLock = this.mainLock; - mainLock.lock(); - try { - completedTaskCount += w.completedTasks; - workers.remove(w); - } finally { - mainLock.unlock(); - } - - tryTerminate(); - - int c = ctl.get(); - if (runStateLessThan(c, STOP)) { - if (!completedAbruptly) { - int min = allowCoreThreadTimeOut ? 0 : corePoolSize; - if (min == 0 && ! workQueue.isEmpty()) - min = 1; - if (workerCountOf(c) >= min) - return; // replacement not needed - } - addWorker(null, false); - } - } - - /** - * Performs blocking or timed wait for a task, depending on - * current configuration settings, or returns null if this worker - * must exit because of any of: - * 1. There are more than maximumPoolSize workers (due to - * a call to setMaximumPoolSize). - * 2. The pool is stopped. - * 3. The pool is shutdown and the queue is empty. - * 4. This worker timed out waiting for a task, and timed-out - * workers are subject to termination (that is, - * {@code allowCoreThreadTimeOut || workerCount > corePoolSize}) - * both before and after the timed wait. - * - * @return task, or null if the worker must exit, in which case - * workerCount is decremented - */ - private Runnable getTask() { - boolean timedOut = false; // Did the last poll() time out? - - retry: - for (;;) { - int c = ctl.get(); - int rs = runStateOf(c); - - // Check if queue empty only if necessary. - if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) { - decrementWorkerCount(); - return null; - } - - boolean timed; // Are workers subject to culling? - - for (;;) { - int wc = workerCountOf(c); - timed = allowCoreThreadTimeOut || wc > corePoolSize; - - if (wc <= maximumPoolSize && ! (timedOut && timed)) - break; - if (compareAndDecrementWorkerCount(c)) - return null; - c = ctl.get(); // Re-read ctl - if (runStateOf(c) != rs) - continue retry; - // else CAS failed due to workerCount change; retry inner loop - } - - try { - Runnable r = timed ? - (Runnable)workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : - (Runnable)workQueue.take(); - if (r != null) - return r; - timedOut = true; - } catch (InterruptedException retry) { - timedOut = false; - } - } - } - - /** - * Main worker run loop. Repeatedly gets tasks from queue and - * executes them, while coping with a number of issues: - * - * 1. We may start out with an initial task, in which case we - * don't need to get the first one. Otherwise, as long as pool is - * running, we get tasks from getTask. If it returns null then the - * worker exits due to changed pool state or configuration - * parameters. Other exits result from exception throws in - * external code, in which case completedAbruptly holds, which - * usually leads processWorkerExit to replace this thread. - * - * 2. Before running any task, the lock is acquired to prevent - * other pool interrupts while the task is executing, and - * clearInterruptsForTaskRun called to ensure that unless pool is - * stopping, this thread does not have its interrupt set. - * - * 3. Each task run is preceded by a call to beforeExecute, which - * might throw an exception, in which case we cause thread to die - * (breaking loop with completedAbruptly true) without processing - * the task. - * - * 4. Assuming beforeExecute completes normally, we run the task, - * gathering any of its thrown exceptions to send to - * afterExecute. We separately handle RuntimeException, Error - * (both of which the specs guarantee that we trap) and arbitrary - * Throwables. Because we cannot rethrow Throwables within - * Runnable.run, we wrap them within Errors on the way out (to the - * thread's UncaughtExceptionHandler). Any thrown exception also - * conservatively causes thread to die. - * - * 5. After task.run completes, we call afterExecute, which may - * also throw an exception, which will also cause thread to - * die. According to JLS Sec 14.20, this exception is the one that - * will be in effect even if task.run throws. - * - * The net effect of the exception mechanics is that afterExecute - * and the thread's UncaughtExceptionHandler have as accurate - * information as we can provide about any problems encountered by - * user code. - * - * @param w the worker - */ - final void runWorker(Worker w) { - Runnable task = w.firstTask; - w.firstTask = null; - boolean completedAbruptly = true; - try { - while (task != null || (task = getTask()) != null) { - w.lock(); - clearInterruptsForTaskRun(); - try { - beforeExecute(w.thread, task); - Throwable thrown = null; - try { - task.run(); - } catch (RuntimeException x) { - thrown = x; throw x; - } catch (Error x) { - thrown = x; throw x; - } catch (Throwable x) { - thrown = x; throw new Error(x); - } finally { - afterExecute(task, thrown); - } - } finally { - task = null; - w.completedTasks++; - w.unlock(); - } - } - completedAbruptly = false; - } finally { - processWorkerExit(w, completedAbruptly); - } - } - - // Public constructors and methods - - /** - * Creates a new {@code ThreadPoolExecutor} 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, unless {@code allowCoreThreadTimeOut} is set - * @param maximumPoolSize the maximum number of threads to allow in the - * pool - * @param keepAliveTime when the number of threads is greater than - * 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 {@code keepAliveTime} argument - * @param workQueue the queue to use for holding tasks before they are - * executed. This queue will hold only the {@code Runnable} - * tasks submitted by the {@code execute} method. - * @throws IllegalArgumentException if one of the following holds:<br> - * {@code corePoolSize < 0}<br> - * {@code keepAliveTime < 0}<br> - * {@code maximumPoolSize <= 0}<br> - * {@code maximumPoolSize < corePoolSize} - * @throws NullPointerException if {@code workQueue} is null - */ - public ThreadPoolExecutor(int corePoolSize, - int maximumPoolSize, - long keepAliveTime, - TimeUnit unit, - BlockingQueue workQueue) { - this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, - Executors.defaultThreadFactory(), defaultHandler); - } - - /** - * Creates a new {@code ThreadPoolExecutor} 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, unless {@code allowCoreThreadTimeOut} is set - * @param maximumPoolSize the maximum number of threads to allow in the - * pool - * @param keepAliveTime when the number of threads is greater than - * 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 {@code keepAliveTime} argument - * @param workQueue the queue to use for holding tasks before they are - * executed. This queue will hold only the {@code Runnable} - * tasks submitted by the {@code execute} method. - * @param threadFactory the factory to use when the executor - * creates a new thread - * @throws IllegalArgumentException if one of the following holds:<br> - * {@code corePoolSize < 0}<br> - * {@code keepAliveTime < 0}<br> - * {@code maximumPoolSize <= 0}<br> - * {@code maximumPoolSize < corePoolSize} - * @throws NullPointerException if {@code workQueue} - * or {@code threadFactory} is null - */ - public ThreadPoolExecutor(int corePoolSize, - int maximumPoolSize, - long keepAliveTime, - TimeUnit unit, - BlockingQueue workQueue, - ThreadFactory threadFactory) { - this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, - threadFactory, defaultHandler); - } - - /** - * Creates a new {@code ThreadPoolExecutor} 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, unless {@code allowCoreThreadTimeOut} is set - * @param maximumPoolSize the maximum number of threads to allow in the - * pool - * @param keepAliveTime when the number of threads is greater than - * 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 {@code keepAliveTime} argument - * @param workQueue the queue to use for holding tasks before they are - * executed. This queue will hold only the {@code Runnable} - * tasks submitted by the {@code execute} method. - * @param handler the handler to use when execution is blocked - * because the thread bounds and queue capacities are reached - * @throws IllegalArgumentException if one of the following holds:<br> - * {@code corePoolSize < 0}<br> - * {@code keepAliveTime < 0}<br> - * {@code maximumPoolSize <= 0}<br> - * {@code maximumPoolSize < corePoolSize} - * @throws NullPointerException if {@code workQueue} - * or {@code handler} is null - */ - public ThreadPoolExecutor(int corePoolSize, - int maximumPoolSize, - long keepAliveTime, - TimeUnit unit, - BlockingQueue workQueue, - RejectedExecutionHandler handler) { - this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, - Executors.defaultThreadFactory(), handler); - } - - /** - * Creates a new {@code ThreadPoolExecutor} with the given initial - * parameters. - * - * @param corePoolSize the number of threads to keep in the pool, even - * if they are idle, unless {@code allowCoreThreadTimeOut} is set - * @param maximumPoolSize the maximum number of threads to allow in the - * pool - * @param keepAliveTime when the number of threads is greater than - * 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 {@code keepAliveTime} argument - * @param workQueue the queue to use for holding tasks before they are - * executed. This queue will hold only the {@code Runnable} - * tasks submitted by the {@code execute} 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 one of the following holds:<br> - * {@code corePoolSize < 0}<br> - * {@code keepAliveTime < 0}<br> - * {@code maximumPoolSize <= 0}<br> - * {@code maximumPoolSize < corePoolSize} - * @throws NullPointerException if {@code workQueue} - * or {@code threadFactory} or {@code handler} is null - */ - public ThreadPoolExecutor(int corePoolSize, - int maximumPoolSize, - long keepAliveTime, - TimeUnit unit, - BlockingQueue 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 {@code RejectedExecutionHandler}. - * - * @param command the task to execute - * @throws RejectedExecutionException at discretion of - * {@code RejectedExecutionHandler}, if the task - * cannot be accepted for execution - * @throws NullPointerException if {@code command} is null - */ - public void execute(Runnable command) { - if (command == null) - throw new NullPointerException(); - /* - * Proceed in 3 steps: - * - * 1. If fewer than corePoolSize threads are running, try to - * start a new thread with the given command as its first - * task. The call to addWorker atomically checks runState and - * workerCount, and so prevents false alarms that would add - * threads when it shouldn't, by returning false. - * - * 2. If a task can be successfully queued, then we still need - * to double-check whether we should have added a thread - * (because existing ones died since last checking) or that - * the pool shut down since entry into this method. So we - * recheck state and if necessary roll back the enqueuing if - * stopped, or start a new thread if there are none. - * - * 3. If we cannot queue task, then we try to add a new - * thread. If it fails, we know we are shut down or saturated - * and so reject the task. - */ - int c = ctl.get(); - if (workerCountOf(c) < corePoolSize) { - if (addWorker(command, true)) - return; - c = ctl.get(); - } - if (isRunning(c) && workQueue.offer(command)) { - int recheck = ctl.get(); - if (! isRunning(recheck) && remove(command)) - reject(command); - else if (workerCountOf(recheck) == 0) - addWorker(null, false); - } - else if (!addWorker(command, false)) - reject(command); - } - - /** - * 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 {@inheritDoc} - */ - public void shutdown() { - final ReentrantLock mainLock = this.mainLock; - mainLock.lock(); - try { - checkShutdownAccess(); - advanceRunState(SHUTDOWN); - interruptIdleWorkers(); - onShutdown(); // hook for ScheduledThreadPoolExecutor - } finally { - mainLock.unlock(); - } - tryTerminate(); - } - - /** - * Attempts to stop all actively executing tasks, halts the - * processing of waiting tasks, and returns a list of the tasks - * that were awaiting execution. These tasks are drained (removed) - * from the task queue upon return from this method. - * - * <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. - * - * @throws SecurityException {@inheritDoc} - */ - public List shutdownNow() { - List tasks; - final ReentrantLock mainLock = this.mainLock; - mainLock.lock(); - try { - checkShutdownAccess(); - advanceRunState(STOP); - interruptWorkers(); - tasks = drainQueue(); - } finally { - mainLock.unlock(); - } - tryTerminate(); - return tasks; - } - - public boolean isShutdown() { - return ! isRunning(ctl.get()); - } - - /** - * Returns true if this executor is in the process of terminating - * after {@link #shutdown} or {@link #shutdownNow} but has not - * completely terminated. This method may be useful for - * debugging. A return of {@code true} 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() { - int c = ctl.get(); - return ! isRunning(c) && runStateLessThan(c, TERMINATED); - } - - public boolean isTerminated() { - return runStateAtLeast(ctl.get(), TERMINATED); - } - - public boolean awaitTermination(long timeout, TimeUnit unit) - throws InterruptedException { - long nanos = unit.toNanos(timeout); - long deadline = Utils.nanoTime() + nanos; - final ReentrantLock mainLock = this.mainLock; - mainLock.lock(); - try { - if (runStateAtLeast(ctl.get(), TERMINATED)) - return true; - while (nanos > 0) { - termination.await(nanos, TimeUnit.NANOSECONDS); - if (runStateAtLeast(ctl.get(), TERMINATED)) - return true; - nanos = deadline - Utils.nanoTime(); - } - return false; - } finally { - mainLock.unlock(); - } - } - - /** - * Invokes {@code shutdown} when this executor is no longer - * referenced and it has no threads. - */ - 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; - } - - /** - * 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 {@code corePoolSize < 0} - * @see #getCorePoolSize - */ - public void setCorePoolSize(int corePoolSize) { - if (corePoolSize < 0) - throw new IllegalArgumentException(); - int delta = corePoolSize - this.corePoolSize; - this.corePoolSize = corePoolSize; - if (workerCountOf(ctl.get()) > corePoolSize) - interruptIdleWorkers(); - else if (delta > 0) { - // We don't really know how many new threads are "needed". - // As a heuristic, prestart enough new workers (up to new - // core size) to handle the current number of tasks in - // queue, but stop if queue becomes empty while doing so. - int k = Math.min(delta, workQueue.size()); - while (k-- > 0 && addWorker(null, true)) { - if (workQueue.isEmpty()) - break; - } - } - } - - /** - * 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 {@code false} - * if all core threads have already been started. - * - * @return {@code true} if a thread was started - */ - public boolean prestartCoreThread() { - return workerCountOf(ctl.get()) < corePoolSize && - addWorker(null, true); - } - - /** - * 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 (addWorker(null, true)) - ++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 {@code true} if core threads are allowed to time out, - * else {@code false} - * - * @since 1.6 - */ - public boolean allowsCoreThreadTimeOut() { - return allowCoreThreadTimeOut; - } - - /** - * Sets the policy governing whether core threads may time out and - * terminate if no tasks arrive within the keep-alive time, being - * replaced if needed when new tasks arrive. When false, core - * threads are never terminated due to lack of incoming - * tasks. When true, the same keep-alive policy applying to - * non-core threads applies also to core threads. To avoid - * continual thread replacement, the keep-alive time must be - * greater than zero when setting {@code true}. This method - * should in general be called before the pool is actively used. - * - * @param value {@code true} if should time out, else {@code false} - * @throws IllegalArgumentException if value is {@code true} - * and the current keep-alive time is not greater than zero - * - * @since 1.6 - */ - public void allowCoreThreadTimeOut(boolean value) { - if (value && keepAliveTime <= 0) - throw new IllegalArgumentException("Core threads must have nonzero keep alive times"); - if (value != allowCoreThreadTimeOut) { - allowCoreThreadTimeOut = value; - if (value) - interruptIdleWorkers(); - } - } - - /** - * Sets the maximum allowed number of threads. This overrides any - * value set in the constructor. If the new value is smaller than - * the current value, excess existing threads will be - * 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(); - this.maximumPoolSize = maximumPoolSize; - if (workerCountOf(ctl.get()) > maximumPoolSize) - interruptIdleWorkers(); - } - - /** - * 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 {@code time} argument - * @throws IllegalArgumentException if {@code time} less than zero or - * if {@code time} is zero and {@code 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"); - long keepAliveTime = unit.toNanos(time); - long delta = keepAliveTime - this.keepAliveTime; - this.keepAliveTime = keepAliveTime; - if (delta < 0) - interruptIdleWorkers(); - } - - /** - * Returns the thread keep-alive time, which is the amount of time - * that 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); - } - - /* User-level queue utilities */ - - /** - * 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 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 {@code submit} might be - * converted into a form that maintains {@code Future} status. - * However, in such cases, method {@link #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) { - boolean removed = workQueue.remove(task); - tryTerminate(); // In case SHUTDOWN and now empty - return removed; - } - - /** - * 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() { - final BlockingQueue q = workQueue; - try { - Iterator it = q.iterator(); - while (it.hasNext()) { - Runnable r = (Runnable)it.next(); - if (r instanceof Future && ((Future)r).isCancelled()) - it.remove(); - } - } catch (ConcurrentModificationException fallThrough) { - // Take slow path if we encounter interference during traversal. - // Make copy for traversal and call remove for cancelled entries. - // The slow path is more likely to be O(N*N). - Object[] arr = q.toArray(); - for (int i=0; i<arr.length; i++) { - Object r = arr[i]; - if (r instanceof Future && ((Future)r).isCancelled()) - q.remove(r); - } - } - - tryTerminate(); // In case SHUTDOWN and now empty - } - - /* Statistics */ - - /** - * Returns the current number of threads in the pool. - * - * @return the number of threads - */ - public int getPoolSize() { - final ReentrantLock mainLock = this.mainLock; - mainLock.lock(); - try { - // Remove rare and surprising possibility of - // isTerminated() && getPoolSize() > 0 - return runStateAtLeast(ctl.get(), TIDYING) ? 0 - : workers.size(); - } finally { - mainLock.unlock(); - } - } - - /** - * 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 (Iterator itr = workers.iterator(); itr.hasNext();) { - Worker w = (Worker)itr.next(); - if (w.isLocked()) - ++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 ever been - * scheduled for execution. Because the states of tasks and - * threads may change dynamically during computation, the returned - * value is only an approximation. - * - * @return the number of tasks - */ - public long getTaskCount() { - final ReentrantLock mainLock = this.mainLock; - mainLock.lock(); - try { - long n = completedTaskCount; - for (Iterator itr = workers.iterator(); itr.hasNext();) { - Worker w = (Worker)itr.next(); - n += w.completedTasks; - if (w.isLocked()) - ++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 (Iterator itr = workers.iterator(); itr.hasNext();) { - Worker w = (Worker)itr.next(); - n += w.completedTasks; - } - return n; - } finally { - mainLock.unlock(); - } - } - - /* Extension hooks */ - - /** - * Method invoked prior to executing the given Runnable in the - * given thread. This method is invoked by thread {@code t} that - * will execute task {@code r}, 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 {@code super.beforeExecute} at the end of - * this method. - * - * @param t the thread that will run task {@code 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 {@code RuntimeException} - * or {@code Error} that caused execution to terminate abruptly. - * - * <p>This implementation does nothing, but may be customized in - * subclasses. Note: To properly nest multiple overridings, subclasses - * should generally invoke {@code super.afterExecute} at the - * beginning of this method. - * - * <p><b>Note:</b> When actions are enclosed in tasks (such as - * {@link FutureTask}) either explicitly or via methods such as - * {@code submit}, 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. If you would like to trap both kinds of - * failures in this method, you can further probe for such cases, - * as in this sample subclass that prints either the direct cause - * or the underlying exception if a task has been aborted: - * - * <pre> {@code - * class ExtendedExecutor extends ThreadPoolExecutor { - * // ... - * protected void afterExecute(Runnable r, Throwable t) { - * super.afterExecute(r, t); - * if (t == null && r instanceof Future<?>) { - * try { - * Object result = ((Future<?>) r).get(); - * } catch (CancellationException ce) { - * t = ce; - * } catch (ExecutionException ee) { - * t = ee.getCause(); - * } catch (InterruptedException ie) { - * Thread.currentThread().interrupt(); // ignore/reset - * } - * } - * if (t != null) - * System.out.println(t); - * } - * }}</pre> - * - * @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 - * {@code super.terminated} within this method. - */ - protected void terminated() { } - - /* Predefined RejectedExecutionHandlers */ - - /** - * A handler for rejected tasks that runs the rejected task - * directly in the calling thread of the {@code execute} method, - * unless the executor has been shut down, in which case the task - * is discarded. - */ - public static class CallerRunsPolicy implements RejectedExecutionHandler { - /** - * Creates a {@code CallerRunsPolicy}. - */ - 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 - * {@code RejectedExecutionException}. - */ - public static class AbortPolicy implements RejectedExecutionHandler { - /** - * Creates an {@code AbortPolicy}. - */ - 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 {@code DiscardPolicy}. - */ - 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 {@code execute}, unless the executor - * is shut down, in which case the task is discarded. - */ - public static class DiscardOldestPolicy implements RejectedExecutionHandler { - /** - * Creates a {@code DiscardOldestPolicy} 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/src/actors/scala/actors/threadpool/TimeUnit.java b/src/actors/scala/actors/threadpool/TimeUnit.java deleted file mode 100644 index c443750e33..0000000000 --- a/src/actors/scala/actors/threadpool/TimeUnit.java +++ /dev/null @@ -1,407 +0,0 @@ -/* - * 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 scala.actors.threadpool; - -import java.io.InvalidObjectException; -import java.io.ObjectStreamException; - -/** - * 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 - * edu.emory.mathcs.backport.java.util.concurrent.locks.Lock lock} is not available: - * - * <pre> Lock lock = ...; - * if ( lock.tryLock(50L, TimeUnit.MILLISECONDS) ) ... - * </pre> - * while this code will timeout in 50 seconds: - * <pre> - * Lock lock = ...; - * if ( lock.tryLock(50L, TimeUnit.SECONDS) ) ... - * </pre> - * - * Note however, that there is no guarantee that a particular timeout - * implementation will be able to notice the passage of time at the - * same granularity as the given <tt>TimeUnit</tt>. - * - * @since 1.5 - * @author Doug Lea - */ -public abstract class TimeUnit implements java.io.Serializable { - - public static final TimeUnit NANOSECONDS = new TimeUnit(0, "NANOSECONDS") { - private final static long serialVersionUID = 535148490883208361L; - public long toNanos(long d) { return d; } - public long toMicros(long d) { return d/(C1/C0); } - public long toMillis(long d) { return d/(C2/C0); } - public long toSeconds(long d) { return d/(C3/C0); } - public long toMinutes(long d) { return d/(C4/C0); } - public long toHours(long d) { return d/(C5/C0); } - public long toDays(long d) { return d/(C6/C0); } - public long convert(long d, TimeUnit u) { return u.toNanos(d); } - int excessNanos(long d, long m) { return (int)(d - (m*C2)); } - }; - public static final TimeUnit MICROSECONDS = new TimeUnit(1, "MICROSECONDS") { - private final static long serialVersionUID = 2185906575929579108L; - public long toNanos(long d) { return x(d, C1/C0, MAX/(C1/C0)); } - public long toMicros(long d) { return d; } - public long toMillis(long d) { return d/(C2/C1); } - public long toSeconds(long d) { return d/(C3/C1); } - public long toMinutes(long d) { return d/(C4/C1); } - public long toHours(long d) { return d/(C5/C1); } - public long toDays(long d) { return d/(C6/C1); } - public long convert(long d, TimeUnit u) { return u.toMicros(d); } - int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); } - }; - public static final TimeUnit MILLISECONDS = new TimeUnit(2, "MILLISECONDS") { - private final static long serialVersionUID = 9032047794123325184L; - public long toNanos(long d) { return x(d, C2/C0, MAX/(C2/C0)); } - public long toMicros(long d) { return x(d, C2/C1, MAX/(C2/C1)); } - public long toMillis(long d) { return d; } - public long toSeconds(long d) { return d/(C3/C2); } - public long toMinutes(long d) { return d/(C4/C2); } - public long toHours(long d) { return d/(C5/C2); } - public long toDays(long d) { return d/(C6/C2); } - public long convert(long d, TimeUnit u) { return u.toMillis(d); } - int excessNanos(long d, long m) { return 0; } - }; - public static final TimeUnit SECONDS = new TimeUnit(3, "SECONDS") { - private final static long serialVersionUID = 227755028449378390L; - public long toNanos(long d) { return x(d, C3/C0, MAX/(C3/C0)); } - public long toMicros(long d) { return x(d, C3/C1, MAX/(C3/C1)); } - public long toMillis(long d) { return x(d, C3/C2, MAX/(C3/C2)); } - public long toSeconds(long d) { return d; } - public long toMinutes(long d) { return d/(C4/C3); } - public long toHours(long d) { return d/(C5/C3); } - public long toDays(long d) { return d/(C6/C3); } - public long convert(long d, TimeUnit u) { return u.toSeconds(d); } - int excessNanos(long d, long m) { return 0; } - }; - public static final TimeUnit MINUTES = new TimeUnit(4, "MINUTES") { - private final static long serialVersionUID = 1827351566402609187L; - public long toNanos(long d) { return x(d, C4/C0, MAX/(C4/C0)); } - public long toMicros(long d) { return x(d, C4/C1, MAX/(C4/C1)); } - public long toMillis(long d) { return x(d, C4/C2, MAX/(C4/C2)); } - public long toSeconds(long d) { return x(d, C4/C3, MAX/(C4/C3)); } - public long toMinutes(long d) { return d; } - public long toHours(long d) { return d/(C5/C4); } - public long toDays(long d) { return d/(C6/C4); } - public long convert(long d, TimeUnit u) { return u.toMinutes(d); } - int excessNanos(long d, long m) { return 0; } - }; - public static final TimeUnit HOURS = new TimeUnit(5, "HOURS") { - private final static long serialVersionUID = -6438436134732089810L; - public long toNanos(long d) { return x(d, C5/C0, MAX/(C5/C0)); } - public long toMicros(long d) { return x(d, C5/C1, MAX/(C5/C1)); } - public long toMillis(long d) { return x(d, C5/C2, MAX/(C5/C2)); } - public long toSeconds(long d) { return x(d, C5/C3, MAX/(C5/C3)); } - public long toMinutes(long d) { return x(d, C5/C4, MAX/(C5/C4)); } - public long toHours(long d) { return d; } - public long toDays(long d) { return d/(C6/C5); } - public long convert(long d, TimeUnit u) { return u.toHours(d); } - int excessNanos(long d, long m) { return 0; } - }; - public static final TimeUnit DAYS = new TimeUnit(6, "DAYS") { - private final static long serialVersionUID = 567463171959674600L; - public long toNanos(long d) { return x(d, C6/C0, MAX/(C6/C0)); } - public long toMicros(long d) { return x(d, C6/C1, MAX/(C6/C1)); } - public long toMillis(long d) { return x(d, C6/C2, MAX/(C6/C2)); } - public long toSeconds(long d) { return x(d, C6/C3, MAX/(C6/C3)); } - public long toMinutes(long d) { return x(d, C6/C4, MAX/(C6/C4)); } - public long toHours(long d) { return x(d, C6/C5, MAX/(C6/C5)); } - public long toDays(long d) { return d; } - public long convert(long d, TimeUnit u) { return u.toDays(d); } - int excessNanos(long d, long m) { return 0; } - }; - - private static final TimeUnit[] values = new TimeUnit[] - { NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS }; - - public static TimeUnit[] values() { - return (TimeUnit[])values.clone(); - } - - /** - * Returns the enum constant of this type with the specified name. The - * string must match <em>exactly</em> an identifier used to declare an - * enum constant in this type. (Extraneous whitespace characters are not - * permitted.) - * - * @param name the name of the enum constant to be returned - * @return the enum constant with the specified name - * @throws IllegalArgumentException - * if this enum type has no constant with the specified name - */ - public static TimeUnit valueOf(String name) { - for (int i = 0; i < values.length; i++) { - if (values[i].name.equals(name)) { - return values[i]; - } - } - throw new IllegalArgumentException("No enum const TimeUnit." + name); - } - - /** - * The ordinal of this unit. This is useful both for {@link #ordinal()} - * and to maintain serialization consistence with earlier versions. - */ - private final int index; - - /** name of this unit */ - private final String name; - - /** Internal constructor */ - TimeUnit(int index, String name) { - this.index = index; - this.name = name; - } - - // Handy constants for conversion methods - static final long C0 = 1; - static final long C1 = C0 * 1000; - static final long C2 = C1 * 1000; - static final long C3 = C2 * 1000; - static final long C4 = C3 * 60; - static final long C5 = C4 * 60; - static final long C6 = C5 * 24; - - static final long MAX = Long.MAX_VALUE; - - /** - * Scale d by m, checking for overflow. - * This has a short name to make above code more readable. - */ - static long x(long d, long m, long over) { - if (d > over) return Long.MAX_VALUE; - if (d < -over) return Long.MIN_VALUE; - return d * m; - } - - /** - * 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 abstract long convert(long sourceDuration, TimeUnit sourceUnit); - - /** - * 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 abstract long toNanos(long duration); - - /** - * 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 abstract long toMicros(long duration); - - /** - * 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 abstract long toMillis(long duration); - - /** - * 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 abstract long toSeconds(long duration); - - /** - * 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 abstract long toMinutes(long duration); - - /** - * 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 abstract long toHours(long duration); - - /** - * Equivalent to <tt>DAYS.convert(duration, this)</tt>. - * @param duration the duration - * @return the converted duration - * @see #convert - * @since 1.6 - */ - public abstract long toDays(long duration); - - /** - * 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); - - /** - * Returns the name of this enum constant, exactly as declared in its enum - * declaration. <strong>Most programmers should use the - * {@link #toString()} method in preference to this one, as the toString - * method may return a more user-friendly name.</strong> This method is - * designed primarily for use in specialized situations where correctness - * depends on getting the exact name, which will not vary from release to - * release. - * - * @return the name of this enum constant - */ - public String name() { - return name; - } - - /** - * Returns the ordinal of this enumeration constant (its position in its - * enum declaration, where the initial constant is assigned an ordinal of - * zero). Most programmers will have no use for this method. It is - * designed for use by sophisticated enum-based data structures, such as - * <code>EnumSet</code> and <code>EnumMap</code>. - * - * @return the ordinal of this enumeration constant - */ - public int ordinal() { - return index; - } - - /* - * Guarantees that deserialized objects will be referentially equal to the - * standard enumeration objects. - */ - protected Object readResolve() throws ObjectStreamException { - try { - return valueOf(name); - } catch (IllegalArgumentException e) { - throw new InvalidObjectException(name - + " is not a valid enum for TimeUnit"); - } - } - - /** - * 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 java.lang.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 java.lang.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 maximum time to sleep. If less than - * or equal to zero, do not sleep at all. - * @throws InterruptedException if interrupted while sleeping. - * @see java.lang.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); - } - } - - public String toString() { - return name; - } -} diff --git a/src/actors/scala/actors/threadpool/TimeoutException.java b/src/actors/scala/actors/threadpool/TimeoutException.java deleted file mode 100644 index c6fdbe5dc4..0000000000 --- a/src/actors/scala/actors/threadpool/TimeoutException.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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 scala.actors.threadpool; - -/** - * 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/src/actors/scala/actors/threadpool/helpers/FIFOWaitQueue.java b/src/actors/scala/actors/threadpool/helpers/FIFOWaitQueue.java deleted file mode 100644 index 432b851f3e..0000000000 --- a/src/actors/scala/actors/threadpool/helpers/FIFOWaitQueue.java +++ /dev/null @@ -1,85 +0,0 @@ -package scala.actors.threadpool.helpers; - -import java.util.Collection; -import java.util.ArrayList; -import java.util.List; - -/** - * Simple linked list queue used in FIFOSemaphore. - * Methods are not synchronized; they depend on synch of callers. - * Must be public, since it is used by Semaphore (outside this package). - * NOTE: this class is NOT present in java.util.concurrent. - **/ - -public class FIFOWaitQueue extends WaitQueue implements java.io.Serializable { - - private final static long serialVersionUID = 2416444691925378811L; - - protected transient WaitNode head_ = null; - protected transient WaitNode tail_ = null; - - public FIFOWaitQueue() {} - - public void insert(WaitNode w) { - if (tail_ == null) - head_ = tail_ = w; - else { - tail_.next = w; - tail_ = w; - } - } - - public WaitNode extract() { - if (head_ == null) - return null; - else { - WaitNode w = head_; - head_ = w.next; - if (head_ == null) - tail_ = null; - w.next = null; - return w; - } - } - - public void putBack(WaitNode w) { - w.next = head_; - head_ = w; - if (tail_ == null) - tail_ = w; - } - - public boolean hasNodes() { - return head_ != null; - } - - public int getLength() { - int count = 0; - WaitNode node = head_; - while (node != null) { - if (node.waiting) count++; - node = node.next; - } - return count; - } - - public Collection getWaitingThreads() { - List<Thread> list = new ArrayList<Thread>(); - int count = 0; - WaitNode node = head_; - while (node != null) { - if (node.waiting) list.add(node.owner); - node = node.next; - } - return list; - } - - public boolean isWaiting(Thread thread) { - if (thread == null) throw new NullPointerException(); - for (WaitNode node = head_; node != null; node = node.next) { - if (node.waiting && node.owner == thread) return true; - } - return false; - } - -} diff --git a/src/actors/scala/actors/threadpool/helpers/NanoTimer.java b/src/actors/scala/actors/threadpool/helpers/NanoTimer.java deleted file mode 100644 index f3edf13565..0000000000 --- a/src/actors/scala/actors/threadpool/helpers/NanoTimer.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Written by Dawid Kurzyniec and released to the public domain, as explained - * at http://creativecommons.org/licenses/publicdomain - */ -package scala.actors.threadpool.helpers; - -/** - * Interface to specify custom implementation of precise timer. - * - * @author Dawid Kurzyniec - * @version 1.0 - */ -public interface NanoTimer { - /** - * Returns the current value of the most precise available system timer, - * in nanoseconds. This method can only be used to measure elapsed time and - * is not related to any other notion of system or wall-clock time. The - * value returned represents nanoseconds since some fixed but arbitrary - * time (perhaps in the future, so values may be negative). This method - * provides nanosecond precision, but not necessarily nanosecond accuracy. - * No guarantees are made about how frequently values change. Differences - * in successive calls that span greater than approximately 292 years - * (263 nanoseconds) will not accurately compute elapsed time due to - * numerical overflow. - * - * @return The current value of the system timer, in nanoseconds. - */ - long nanoTime(); -} diff --git a/src/actors/scala/actors/threadpool/helpers/ThreadHelpers.java b/src/actors/scala/actors/threadpool/helpers/ThreadHelpers.java deleted file mode 100644 index 13da20c4d6..0000000000 --- a/src/actors/scala/actors/threadpool/helpers/ThreadHelpers.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Written by Dawid Kurzyniec and released to the public domain, as explained - * at http://creativecommons.org/licenses/publicdomain - */ -package scala.actors.threadpool.helpers; - -/** - * Emulation of some new functionality present in java.lang.Thread in J2SE 5.0. - * - * @author Dawid Kurzyniec - * @version 1.0 - */ -public class ThreadHelpers { - - private ThreadHelpers() {} - - /** - * Returns wrapped runnable that ensures that if an exception occurs - * during the execution, the specified exception handler is invoked. - * @param runnable runnable for which exceptions are to be intercepted - * @param handler the exception handler to call when exception occurs - * during execution of the given runnable - * @return wrapped runnable - */ - public static Runnable assignExceptionHandler(final Runnable runnable, - final UncaughtExceptionHandler handler) - { - if (runnable == null || handler == null) { - throw new NullPointerException(); - } - return new Runnable() { - public void run() { - try { - runnable.run(); - } - catch (Throwable error) { - try { - handler.uncaughtException(Thread.currentThread(), error); - } - catch (Throwable ignore) {} - } - } - }; - } - - /** - * Abstraction of the exception handler which receives notifications of - * exceptions occurred possibly in various parts of the system. Exception - * handlers present attractive approach to exception handling in multi-threaded - * systems, as they can handle exceptions that occurred in different threads. - * <p> - * This class is analogous to Thread.UncaughtExceptionHandler in J2SE 5.0. - * Obviously you cannot use it the same way, e.g. you cannot assign the - * handler to the thread so that it is invoked when thread terminates. - * However, it can be {@link ThreadHelpers#assignExceptionHandler emulated}. - */ - public static interface UncaughtExceptionHandler { - /** - * Notification of the uncaught exception that occurred within specified - * thread. - * @param thread the thread where the exception occurred - * @param error the exception - */ - void uncaughtException(Thread thread, Throwable error); - } -} diff --git a/src/actors/scala/actors/threadpool/helpers/Utils.java b/src/actors/scala/actors/threadpool/helpers/Utils.java deleted file mode 100644 index d12389215d..0000000000 --- a/src/actors/scala/actors/threadpool/helpers/Utils.java +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Written by Dawid Kurzyniec, based on code written by Doug Lea with assistance - * from members of JCP JSR-166 Expert Group. Released to the public domain, - * as explained at http://creativecommons.org/licenses/publicdomain. - * - * Thanks to Craig Mattocks for suggesting to use <code>sun.misc.Perf</code>. - */ - -package scala.actors.threadpool.helpers; - -//import edu.emory.mathcs.backport.java.util.*; -import scala.actors.threadpool.*; -import scala.actors.threadpool.locks.*; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.lang.reflect.Array; -import java.util.Iterator; -import java.util.Collection; - -/** - * <p> - * This class groups together the functionality of java.util.concurrent that - * cannot be fully and reliably implemented in backport, but for which some - * form of emulation is possible. - * <p> - * Currently, this class contains methods related to nanosecond-precision - * timing, particularly via the {@link #nanoTime} method. To measure time - * accurately, this method by default uses <code>java.sun.Perf</code> on - * JDK1.4.2 and it falls back to <code>System.currentTimeMillis</code> - * on earlier JDKs. - * - * @author Dawid Kurzyniec - * @version 1.0 - */ -public final class Utils { - - private final static NanoTimer nanoTimer; - private final static String providerProp = - "edu.emory.mathcs.backport.java.util.concurrent.NanoTimerProvider"; - - static { - NanoTimer timer = null; - try { - String nanoTimerClassName = - AccessController.doPrivileged(new PrivilegedAction<String>() { - public String run() { - return System.getProperty(providerProp); - } - }); - if (nanoTimerClassName != null) { - Class cls = Class.forName(nanoTimerClassName); - timer = (NanoTimer) cls.newInstance(); - } - } - catch (Exception e) { - System.err.println("WARNING: unable to load the system-property-defined " + - "nanotime provider; switching to the default"); - e.printStackTrace(); - } - - if (timer == null) { - try { - timer = new SunPerfProvider(); - } - catch (Throwable e) {} - } - - if (timer == null) { - timer = new MillisProvider(); - } - - nanoTimer = timer; - } - - private Utils() {} - - /** - * Returns the current value of the most precise available system timer, - * in nanoseconds. This method can only be used to measure elapsed time and - * is not related to any other notion of system or wall-clock time. The - * value returned represents nanoseconds since some fixed but arbitrary - * time (perhaps in the future, so values may be negative). This method - * provides nanosecond precision, but not necessarily nanosecond accuracy. - * No guarantees are made about how frequently values change. Differences - * in successive calls that span greater than approximately 292 years - * (2^63 nanoseconds) will not accurately compute elapsed time due to - * numerical overflow. - * <p> - * <em>Implementation note:</em>By default, this method uses - * <code>sun.misc.Perf</code> on Java 1.4.2, and falls back to - * System.currentTimeMillis() emulation on earlier JDKs. Custom - * timer can be provided via the system property - * <code>edu.emory.mathcs.backport.java.util.concurrent.NanoTimerProvider</code>. - * The value of the property should name a class implementing - * {@link NanoTimer} interface. - * <p> - * Note: on JDK 1.4.2, <code>sun.misc.Perf</code> timer seems to have - * resolution of the order of 1 microsecond, measured on Linux. - * - * @return The current value of the system timer, in nanoseconds. - */ - public static long nanoTime() { - return nanoTimer.nanoTime(); - } - - /** - * Causes the current thread to wait until it is signalled or interrupted, - * or the specified waiting time elapses. This method originally appears - * in the {@link Condition} interface, but it was moved to here since it - * can only be emulated, with very little accuracy guarantees: the - * efficient implementation requires accurate nanosecond timer and native - * support for nanosecond-precision wait queues, which are not usually - * present in JVMs prior to 1.5. Loss of precision may cause total waiting - * times to be systematically shorter than specified when re-waits occur. - * - * <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 - * edu.emory.mathcs.backport.java.util.concurrent.locks.Condition#signal} - * method for this - * <tt>Condition</tt> and the current thread happens to be chosen as the - * thread to be awakened; or - * <li>Some other thread invokes the {@link - * edu.emory.mathcs.backport.java.util.concurrent.locks.Condition#signalAll} - * method for this - * <tt>Condition</tt>; or - * <li>Some other thread {@link Thread#interrupt interrupts} the current - * thread, and interruption of thread suspension is supported; or - * <li>The specified waiting time elapses; or - * <li>A "<em>spurious wakeup</em>" 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 {@link 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 <tt>nanosTimeout</tt> - * value upon return, or a value less than or equal to zero if it - * timed out. Accuracy of this estimate is directly dependent on the - * accuracy of {@link #nanoTime}. 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 > 0) - * nanosTimeout = theCondition.awaitNanos(nanosTimeout); - * else - * return false; - * } - * // ... - * } - * </pre> - * - * <p><b>Implementation Considerations</b> - * <p>The current thread is assumed to hold the lock associated with this - * <tt>Condition</tt> 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>A condition 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 cond the condition to wait for - * @param nanosTimeout the maximum time to wait, in nanoseconds - * @return A value less than or equal to zero if the wait has - * timed out; otherwise an estimate, that - * is strictly less than the <tt>nanosTimeout</tt> argument, - * of the time still remaining when this method returned. - * - * @throws InterruptedException if the current thread is interrupted (and - * interruption of thread suspension is supported). - */ - public static long awaitNanos(Condition cond, long nanosTimeout) - throws InterruptedException - { - if (nanosTimeout <= 0) return nanosTimeout; - long now = nanoTime(); - cond.await(nanosTimeout, TimeUnit.NANOSECONDS); - return nanosTimeout - (nanoTime() - now); - } - - private static final class SunPerfProvider implements NanoTimer { - final Perf perf; - final long multiplier, divisor; - SunPerfProvider() { - perf = - AccessController.doPrivileged(new PrivilegedAction<Perf>() { - public Perf run() { - return Perf.getPerf(); - } - }); - // trying to avoid BOTH overflow and rounding errors - long numerator = 1000000000; - long denominator = perf.highResFrequency(); - long gcd = gcd(numerator, denominator); - this.multiplier = numerator / gcd; - this.divisor = denominator / gcd; - } - public long nanoTime() { - long ctr = perf.highResCounter(); - - // anything less sophisticated suffers either from rounding errors - // (FP arithmetics, backport v1.0) or overflow, when gcd is small - // (a bug in backport v1.0_01 reported by Ramesh Nethi) - - return ((ctr / divisor) * multiplier) + - (ctr % divisor) * multiplier / divisor; - - // even the above can theoretically cause problems if your JVM is - // running for sufficiently long time, but "sufficiently" means 292 - // years (worst case), or 30,000 years (common case). - - // Details: when the ticks ctr overflows, there is no way to avoid - // discontinuity in computed nanos, even in infinite arithmetics, - // unless we count number of overflows that the ctr went through - // since the JVM started. This follows from the fact that - // (2^64*multiplier/divisor) mod (2^64) > 0 in general case. - // Theoretically we could find out the number of overflows by - // checking System.currentTimeMillis(), but this is unreliable - // since the system time can unpredictably change during the JVM - // lifetime. - // The time to overflow is 2^63 / ticks frequency. With current - // ticks frequencies of several MHz, it gives about 30,000 years - // before the problem happens. If ticks frequency reaches 1 GHz, the - // time to overflow is 292 years. It is unlikely that the frequency - // ever exceeds 1 GHz. We could double the time to overflow - // (to 2^64 / frequency) by using unsigned arithmetics, e.g. by - // adding the following correction whenever the ticks is negative: - // -2*((Long.MIN_VALUE / divisor) * multiplier + - // (Long.MIN_VALUE % divisor) * multiplier / divisor) - // But, with the worst case of as much as 292 years, it does not - // seem justified. - } - } - - private static final class MillisProvider implements NanoTimer { - MillisProvider() {} - public long nanoTime() { - return System.currentTimeMillis() * 1000000; - } - } - - private static long gcd(long a, long b) { - long r; - while (b>0) { r = a % b; a = b; b = r; } - return a; - } - - - public static Object[] collectionToArray(Collection c) { - // guess the array size; expect to possibly be different - int len = c.size(); - Object[] arr = new Object[len]; - Iterator itr = c.iterator(); - int idx = 0; - while (true) { - while (idx < len && itr.hasNext()) { - arr[idx++] = itr.next(); - } - if (!itr.hasNext()) { - if (idx == len) return arr; - // otherwise have to trim - return Arrays.copyOf(arr, idx, Object[].class); - } - // otherwise, have to grow - int newcap = ((arr.length/2)+1)*3; - if (newcap < arr.length) { - // overflow - if (arr.length < Integer.MAX_VALUE) { - newcap = Integer.MAX_VALUE; - } - else { - throw new OutOfMemoryError("required array size too large"); - } - } - arr = Arrays.copyOf(arr, newcap, Object[].class); - len = newcap; - } - } - - public static Object[] collectionToArray(Collection c, Object[] a) { - Class aType = a.getClass(); - // guess the array size; expect to possibly be different - int len = c.size(); - Object[] arr = (a.length >= len ? a : - (Object[])Array.newInstance(aType.getComponentType(), len)); - Iterator itr = c.iterator(); - int idx = 0; - while (true) { - while (idx < len && itr.hasNext()) { - arr[idx++] = itr.next(); - } - if (!itr.hasNext()) { - if (idx == len) return arr; - if (arr == a) { - // orig array -> null terminate - a[idx] = null; - return a; - } - else { - // have to trim - return Arrays.copyOf(arr, idx, aType); - } - } - // otherwise, have to grow - int newcap = ((arr.length/2)+1)*3; - if (newcap < arr.length) { - // overflow - if (arr.length < Integer.MAX_VALUE) { - newcap = Integer.MAX_VALUE; - } - else { - throw new OutOfMemoryError("required array size too large"); - } - } - arr = Arrays.copyOf(arr, newcap, aType); - len = newcap; - } - } -} diff --git a/src/actors/scala/actors/threadpool/helpers/WaitQueue.java b/src/actors/scala/actors/threadpool/helpers/WaitQueue.java deleted file mode 100644 index bcbf29e5c2..0000000000 --- a/src/actors/scala/actors/threadpool/helpers/WaitQueue.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - based on file: QueuedSemaphore.java - Originally written by Doug Lea and released into the public domain. - This may be used for any purposes whatsoever without acknowledgment. - Thanks for the assistance and support of Sun Microsystems Labs, - and everyone contributing, testing, and using this code. - History: - Date Who What - 11Jun1998 dl Create public version - 5Aug1998 dl replaced int counters with longs - 24Aug1999 dl release(n): screen arguments - */ - -package scala.actors.threadpool.helpers; - -import java.util.Collection; -import scala.actors.threadpool.*; - -/** - * Base class for internal queue classes for semaphores, etc. - * Relies on subclasses to actually implement queue mechanics. - * NOTE: this class is NOT present in java.util.concurrent. - **/ - -public abstract class WaitQueue { - - public abstract void insert(WaitNode w); // assumed not to block - public abstract WaitNode extract(); // should return null if empty - public abstract void putBack(WaitNode w); - - public abstract boolean hasNodes(); - public abstract int getLength(); - public abstract Collection getWaitingThreads(); - public abstract boolean isWaiting(Thread thread); - - public static interface QueuedSync { - // invoked with sync on wait node, (atomically) just before enqueuing - boolean recheck(WaitNode node); - // invoked with sync on wait node, (atomically) just before signalling - void takeOver(WaitNode node); - } - - public static class WaitNode { - boolean waiting = true; - WaitNode next = null; - final Thread owner; - - public WaitNode() { - this.owner = Thread.currentThread(); - } - - public Thread getOwner() { - return owner; - } - - public synchronized boolean signal(QueuedSync sync) { - boolean signalled = waiting; - if (signalled) { - waiting = false; - notify(); - sync.takeOver(this); - } - return signalled; - } - - public synchronized boolean doTimedWait(QueuedSync sync, long nanos) - throws InterruptedException - { - if (sync.recheck(this) || !waiting) - return true; - else if (nanos <= 0) { - waiting = false; - return false; - } - else { - long deadline = Utils.nanoTime() + nanos; - try { - for (; ; ) { - TimeUnit.NANOSECONDS.timedWait(this, nanos); - if (!waiting) // definitely signalled - return true; - else { - nanos = deadline - Utils.nanoTime(); - if (nanos <= 0) { // timed out - waiting = false; - return false; - } - } - } - } - catch (InterruptedException ex) { - if (waiting) { // no notification - waiting = false; // invalidate for the signaller - throw ex; - } - else { // thread was interrupted after it was notified - Thread.currentThread().interrupt(); - return true; - } - } - } - } - - public synchronized void doWait(QueuedSync sync) - throws InterruptedException - { - if (!sync.recheck(this)) { - try { - while (waiting) wait(); - } - catch (InterruptedException ex) { - if (waiting) { // no notification - waiting = false; // invalidate for the signaller - throw ex; - } - else { // thread was interrupted after it was notified - Thread.currentThread().interrupt(); - return; - } - } - } - } - - public synchronized void doWaitUninterruptibly(QueuedSync sync) { - if (!sync.recheck(this)) { - boolean wasInterrupted = Thread.interrupted(); - try { - while (waiting) { - try { - wait(); - } - catch (InterruptedException ex) { - wasInterrupted = true; - // no need to notify; if we were signalled, we - // must be not waiting, and we'll act like signalled - } - } - } - finally { - if (wasInterrupted) Thread.currentThread().interrupt(); - } - } - } - } -} - diff --git a/src/actors/scala/actors/threadpool/locks/CondVar.java b/src/actors/scala/actors/threadpool/locks/CondVar.java deleted file mode 100644 index 44df1c0b97..0000000000 --- a/src/actors/scala/actors/threadpool/locks/CondVar.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - File: ConditionVariable.java - Originally written by Doug Lea and released into the public domain. - This may be used for any purposes whatsoever without acknowledgment. - Thanks for the assistance and support of Sun Microsystems Labs, - and everyone contributing, testing, and using this code. - History: - Date Who What - 11Jun1998 dl Create public version - */ - -package scala.actors.threadpool.locks; - -import java.util.Collection; -import java.util.Date; -import scala.actors.threadpool.*; -import scala.actors.threadpool.helpers.*; - -class CondVar implements Condition, java.io.Serializable { - private static final long serialVersionUID = -5009898475638427940L; - - /** The lock **/ - protected final ExclusiveLock lock; - - /** - * Create a new CondVar that relies on the given mutual - * exclusion lock. - * @param lock A non-reentrant mutual exclusion lock. - **/ - - CondVar(ExclusiveLock lock) { - this.lock = lock; - } - - public void awaitUninterruptibly() { - int holdCount = lock.getHoldCount(); - if (holdCount == 0) { - throw new IllegalMonitorStateException(); - } - // avoid instant spurious wakeup if thread already interrupted - boolean wasInterrupted = Thread.interrupted(); - try { - synchronized (this) { - for (int i=holdCount; i>0; i--) lock.unlock(); - try { - wait(); - } - catch (InterruptedException ex) { - wasInterrupted = true; - // may have masked the signal and there is no way - // to tell; we must wake up spuriously - } - } - } - finally { - for (int i=holdCount; i>0; i--) lock.lock(); - if (wasInterrupted) { - Thread.currentThread().interrupt(); - } - } - } - - public void await() throws InterruptedException { - int holdCount = lock.getHoldCount(); - if (holdCount == 0) { - throw new IllegalMonitorStateException(); - } - if (Thread.interrupted()) throw new InterruptedException(); - try { - synchronized (this) { - for (int i=holdCount; i>0; i--) lock.unlock(); - try { - wait(); - } - catch (InterruptedException ex) { - notify(); - throw ex; - } - } - } - finally { - for (int i=holdCount; i>0; i--) lock.lock(); - } - } - - public boolean await(long timeout, TimeUnit unit) throws InterruptedException { - int holdCount = lock.getHoldCount(); - if (holdCount == 0) { - throw new IllegalMonitorStateException(); - } - if (Thread.interrupted()) throw new InterruptedException(); - long nanos = unit.toNanos(timeout); - boolean success = false; - try { - synchronized (this) { - for (int i=holdCount; i>0; i--) lock.unlock(); - try { - if (nanos > 0) { - long start = Utils.nanoTime(); - TimeUnit.NANOSECONDS.timedWait(this, nanos); - // DK: due to coarse-grained (millis) clock, it seems - // preferable to acknowledge timeout (success == false) - // when the equality holds (timing is exact) - success = Utils.nanoTime() - start < nanos; - } - } - catch (InterruptedException ex) { - notify(); - throw ex; - } - } - } - finally { - for (int i=holdCount; i>0; i--) lock.lock(); - } - return success; - } - -// public long awaitNanos(long timeout) throws InterruptedException { -// throw new UnsupportedOperationException(); -// } -// - public boolean awaitUntil(Date deadline) throws InterruptedException { - if (deadline == null) throw new NullPointerException(); - int holdCount = lock.getHoldCount(); - if (holdCount == 0) { - throw new IllegalMonitorStateException(); - } - long abstime = deadline.getTime(); - if (Thread.interrupted()) throw new InterruptedException(); - - boolean success = false; - try { - synchronized (this) { - for (int i=holdCount; i>0; i--) lock.unlock(); - try { - long start = System.currentTimeMillis(); - long msecs = abstime - start; - if (msecs > 0) { - wait(msecs); - // DK: due to coarse-grained (millis) clock, it seems - // preferable to acknowledge timeout (success == false) - // when the equality holds (timing is exact) - success = System.currentTimeMillis() - start < msecs; - } - } - catch (InterruptedException ex) { - notify(); - throw ex; - } - } - } - finally { - for (int i=holdCount; i>0; i--) lock.lock(); - } - return success; - } - - public synchronized void signal() { - if (!lock.isHeldByCurrentThread()) { - throw new IllegalMonitorStateException(); - } - notify(); - } - - public synchronized void signalAll() { - if (!lock.isHeldByCurrentThread()) { - throw new IllegalMonitorStateException(); - } - notifyAll(); - } - - protected ExclusiveLock getLock() { return lock; } - - protected boolean hasWaiters() { - throw new UnsupportedOperationException("Use FAIR version"); - } - - protected int getWaitQueueLength() { - throw new UnsupportedOperationException("Use FAIR version"); - } - - protected Collection getWaitingThreads() { - throw new UnsupportedOperationException("Use FAIR version"); - } - - static interface ExclusiveLock extends Lock { - boolean isHeldByCurrentThread(); - int getHoldCount(); - } -} diff --git a/src/actors/scala/actors/threadpool/locks/Condition.java b/src/actors/scala/actors/threadpool/locks/Condition.java deleted file mode 100644 index 0553684321..0000000000 --- a/src/actors/scala/actors/threadpool/locks/Condition.java +++ /dev/null @@ -1,434 +0,0 @@ -/* - * 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 scala.actors.threadpool.locks; - -import scala.actors.threadpool.*; -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 "wait") 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 edu.emory.mathcs.backport.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 "<em>spurious - * wakeup</em>" 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 "<em>spurious wakeup</em>" 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 "<em>spurious wakeup</em>" 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 -// * <tt>Condition</tt> 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 -// * <tt>Condition</tt>; or -// * <li>Some other thread {@link Thread#interrupt interrupts} the current -// * thread, and interruption of thread suspension is supported; or -// * <li>The specified waiting time elapses; or -// * <li>A "<em>spurious wakeup</em>" 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 {@link 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 <tt>nanosTimeout</tt> -// * 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 > 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 -// * <tt>Condition</tt> 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 A value less than or equal to zero if the wait has -// * timed out; otherwise an estimate, that -// * is strictly less than the <tt>nanosTimeout</tt> argument, -// * of the time still remaining when this method returned. -// * -// * @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)) > 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 "<em>spurious wakeup</em>" 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/src/actors/scala/actors/threadpool/locks/FIFOCondVar.java b/src/actors/scala/actors/threadpool/locks/FIFOCondVar.java deleted file mode 100644 index 144ac54d37..0000000000 --- a/src/actors/scala/actors/threadpool/locks/FIFOCondVar.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - File: ConditionVariable.java - Originally written by Doug Lea and released into the public domain. - This may be used for any purposes whatsoever without acknowledgment. - Thanks for the assistance and support of Sun Microsystems Labs, - and everyone contributing, testing, and using this code. - History: - Date Who What - 11Jun1998 dl Create public version - */ - -package scala.actors.threadpool.locks; - -import java.util.Collection; -import java.util.Date; -import scala.actors.threadpool.*; -import scala.actors.threadpool.helpers.*; - -class FIFOCondVar extends CondVar implements Condition, java.io.Serializable { - private static final long serialVersionUID = -497497271881010475L; - - private static final WaitQueue.QueuedSync sync = new WaitQueue.QueuedSync() { - public boolean recheck(WaitQueue.WaitNode node) { return false; } - public void takeOver(WaitQueue.WaitNode node) {} - }; - - // wait queue; only accessed when holding the lock - private final WaitQueue wq = new FIFOWaitQueue(); - - /** - * Create a new CondVar that relies on the given mutual exclusion lock. - * @param lock A non-reentrant mutual exclusion lock. - */ - FIFOCondVar(ExclusiveLock lock) { - super(lock); - } - - public void awaitUninterruptibly() { - int holdCount = lock.getHoldCount(); - if (holdCount == 0) { - throw new IllegalMonitorStateException(); - } - WaitQueue.WaitNode n = new WaitQueue.WaitNode(); - wq.insert(n); - for (int i=holdCount; i>0; i--) lock.unlock(); - try { - n.doWaitUninterruptibly(sync); - } - finally { - for (int i=holdCount; i>0; i--) lock.lock(); - } - } - - public void await() throws InterruptedException { - int holdCount = lock.getHoldCount(); - if (holdCount == 0) { - throw new IllegalMonitorStateException(); - } - if (Thread.interrupted()) throw new InterruptedException(); - WaitQueue.WaitNode n = new WaitQueue.WaitNode(); - wq.insert(n); - for (int i=holdCount; i>0; i--) lock.unlock(); - try { - n.doWait(sync); - } - finally { - for (int i=holdCount; i>0; i--) lock.lock(); - } - } - - public boolean await(long timeout, TimeUnit unit) throws InterruptedException { - int holdCount = lock.getHoldCount(); - if (holdCount == 0) { - throw new IllegalMonitorStateException(); - } - if (Thread.interrupted()) throw new InterruptedException(); - long nanos = unit.toNanos(timeout); - WaitQueue.WaitNode n = new WaitQueue.WaitNode(); - wq.insert(n); - boolean success = false; - for (int i=holdCount; i>0; i--) lock.unlock(); - try { - success = n.doTimedWait(sync, nanos); - } - finally { - for (int i=holdCount; i>0; i--) lock.lock(); - } - return success; - } - -// public long awaitNanos(long timeout) throws InterruptedException { -// throw new UnsupportedOperationException(); -// } -// - public boolean awaitUntil(Date deadline) throws InterruptedException { - if (deadline == null) throw new NullPointerException(); - long abstime = deadline.getTime(); - long start = System.currentTimeMillis(); - long msecs = abstime - start; - return await(msecs, TimeUnit.MILLISECONDS); - } - - public void signal() { - if (!lock.isHeldByCurrentThread()) { - throw new IllegalMonitorStateException(); - } - for (;;) { - WaitQueue.WaitNode w = wq.extract(); - if (w == null) return; // no one to signal - if (w.signal(sync)) return; // notify if still waiting, else skip - } - } - - public void signalAll() { - if (!lock.isHeldByCurrentThread()) { - throw new IllegalMonitorStateException(); - } - for (;;) { - WaitQueue.WaitNode w = wq.extract(); - if (w == null) return; // no more to signal - w.signal(sync); - } - } - - protected boolean hasWaiters() { - if (!lock.isHeldByCurrentThread()) { - throw new IllegalMonitorStateException(); - } - return wq.hasNodes(); - } - - protected int getWaitQueueLength() { - if (!lock.isHeldByCurrentThread()) { - throw new IllegalMonitorStateException(); - } - return wq.getLength(); - } - - protected Collection getWaitingThreads() { - if (!lock.isHeldByCurrentThread()) { - throw new IllegalMonitorStateException(); - } - return wq.getWaitingThreads(); - } - - -} diff --git a/src/actors/scala/actors/threadpool/locks/Lock.java b/src/actors/scala/actors/threadpool/locks/Lock.java deleted file mode 100644 index 47a4e8e777..0000000000 --- a/src/actors/scala/actors/threadpool/locks/Lock.java +++ /dev/null @@ -1,328 +0,0 @@ -/* - * 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 scala.actors.threadpool.locks; - -import scala.actors.threadpool.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 - * "hand-over-hand" or "chain locking": 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/src/actors/scala/actors/threadpool/locks/ReadWriteLock.java b/src/actors/scala/actors/threadpool/locks/ReadWriteLock.java deleted file mode 100644 index 02983f9bd4..0000000000 --- a/src/actors/scala/actors/threadpool/locks/ReadWriteLock.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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 scala.actors.threadpool.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 "in-order" 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/src/actors/scala/actors/threadpool/locks/ReentrantLock.java b/src/actors/scala/actors/threadpool/locks/ReentrantLock.java deleted file mode 100644 index b42ddd611b..0000000000 --- a/src/actors/scala/actors/threadpool/locks/ReentrantLock.java +++ /dev/null @@ -1,959 +0,0 @@ -/* - * 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 scala.actors.threadpool.locks; - -import java.util.Collection; -import scala.actors.threadpool.*; -import scala.actors.threadpool.helpers.*; - -/** - * 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 - * @author Dawid Kurzyniec - */ -public class ReentrantLock implements Lock, java.io.Serializable, - CondVar.ExclusiveLock { - private static final long serialVersionUID = 7373984872572414699L; - - private final Sync sync; - - /** - * Base of synchronization control for this lock. Subclassed - * into fair and nonfair versions below. - */ - static abstract class Sync implements java.io.Serializable { - private static final long serialVersionUID = -5179523762034025860L; - - protected transient Thread owner_ = null; - protected transient int holds_ = 0; - - protected Sync() {} - - /** - * Performs {@link Lock#lock}. The main reason for subclassing - * is to allow fast path for nonfair version. - */ - public abstract void lock(); - - public abstract void lockInterruptibly() throws InterruptedException; - - final void incHolds() { - int nextHolds = ++holds_; - if (nextHolds < 0) - throw new Error("Maximum lock count exceeded"); - holds_ = nextHolds; - } - - public boolean tryLock() { - Thread caller = Thread.currentThread(); - synchronized (this) { - if (owner_ == null) { - owner_ = caller; - holds_ = 1; - return true; - } - else if (caller == owner_) { - incHolds(); - return true; - } - } - return false; - } - - public abstract boolean tryLock(long nanos) throws InterruptedException; - - public abstract void unlock(); - - public synchronized int getHoldCount() { - return isHeldByCurrentThread() ? holds_ : 0; - } - - public synchronized boolean isHeldByCurrentThread() { - return holds_ > 0 && Thread.currentThread() == owner_; - } - - public synchronized boolean isLocked() { - return owner_ != null; - } - - public abstract boolean isFair(); - - protected synchronized Thread getOwner() { - return owner_; - } - - public boolean hasQueuedThreads() { - throw new UnsupportedOperationException("Use FAIR version"); - } - - public int getQueueLength() { - throw new UnsupportedOperationException("Use FAIR version"); - } - - public Collection getQueuedThreads() { - throw new UnsupportedOperationException("Use FAIR version"); - } - - public boolean isQueued(Thread thread) { - throw new UnsupportedOperationException("Use FAIR version"); - } - } - - /** - * Sync object for non-fair locks - */ - final static class NonfairSync extends Sync { - private static final long serialVersionUID = 7316153563782823691L; - - NonfairSync() {} - - /** - * Performs lock. Try immediate barge, backing up to normal - * acquire on failure. - */ - public void lock() { - Thread caller = Thread.currentThread(); - synchronized (this) { - if (owner_ == null) { - owner_ = caller; - holds_ = 1; - return; - } - else if (caller == owner_) { - incHolds(); - return; - } - else { - boolean wasInterrupted = Thread.interrupted(); - try { - while (true) { - try { - wait(); - } - catch (InterruptedException e) { - wasInterrupted = true; - // no need to notify; if we were signalled, we - // will act as signalled, ignoring the - // interruption - } - if (owner_ == null) { - owner_ = caller; - holds_ = 1; - return; - } - } - } - finally { - if (wasInterrupted) Thread.currentThread().interrupt(); - } - } - } - } - - public void lockInterruptibly() throws InterruptedException { - if (Thread.interrupted()) throw new InterruptedException(); - Thread caller = Thread.currentThread(); - synchronized (this) { - if (owner_ == null) { - owner_ = caller; - holds_ = 1; - return; - } - else if (caller == owner_) { - incHolds(); - return; - } - else { - try { - do { wait(); } while (owner_ != null); - owner_ = caller; - holds_ = 1; - return; - } - catch (InterruptedException ex) { - if (owner_ == null) notify(); - throw ex; - } - } - } - } - - public boolean tryLock(long nanos) throws InterruptedException { - if (Thread.interrupted()) throw new InterruptedException(); - Thread caller = Thread.currentThread(); - - synchronized (this) { - if (owner_ == null) { - owner_ = caller; - holds_ = 1; - return true; - } - else if (caller == owner_) { - incHolds(); - return true; - } - else if (nanos <= 0) - return false; - else { - long deadline = Utils.nanoTime() + nanos; - try { - for (; ; ) { - TimeUnit.NANOSECONDS.timedWait(this, nanos); - if (caller == owner_) { - incHolds(); - return true; - } - else if (owner_ == null) { - owner_ = caller; - holds_ = 1; - return true; - } - else { - nanos = deadline - Utils.nanoTime(); - if (nanos <= 0) - return false; - } - } - } - catch (InterruptedException ex) { - if (owner_ == null) notify(); - throw ex; - } - } - } - } - - public synchronized void unlock() { - if (Thread.currentThread() != owner_) - throw new IllegalMonitorStateException("Not owner"); - - if (--holds_ == 0) { - owner_ = null; - notify(); - } - } - - public final boolean isFair() { - return false; - } - } - - /** - * Sync object for fair locks - */ - final static class FairSync extends Sync implements WaitQueue.QueuedSync { - private static final long serialVersionUID = -3000897897090466540L; - - private transient WaitQueue wq_ = new FIFOWaitQueue(); - - FairSync() {} - - public synchronized boolean recheck(WaitQueue.WaitNode node) { - Thread caller = Thread.currentThread(); - if (owner_ == null) { - owner_ = caller; - holds_ = 1; - return true; - } - else if (caller == owner_) { - incHolds(); - return true; - } - wq_.insert(node); - return false; - } - - public synchronized void takeOver(WaitQueue.WaitNode node) { - // assert (holds_ == 1 && owner_ == Thread.currentThread() - owner_ = node.getOwner(); - } - - public void lock() { - Thread caller = Thread.currentThread(); - synchronized (this) { - if (owner_ == null) { - owner_ = caller; - holds_ = 1; - return; - } - else if (caller == owner_) { - incHolds(); - return; - } - } - WaitQueue.WaitNode n = new WaitQueue.WaitNode(); - n.doWaitUninterruptibly(this); - } - - public void lockInterruptibly() throws InterruptedException { - if (Thread.interrupted()) throw new InterruptedException(); - Thread caller = Thread.currentThread(); - synchronized (this) { - if (owner_ == null) { - owner_ = caller; - holds_ = 1; - return; - } - else if (caller == owner_) { - incHolds(); - return; - } - } - WaitQueue.WaitNode n = new WaitQueue.WaitNode(); - n.doWait(this); - } - - public boolean tryLock(long nanos) throws InterruptedException { - if (Thread.interrupted()) throw new InterruptedException(); - Thread caller = Thread.currentThread(); - synchronized (this) { - if (owner_ == null) { - owner_ = caller; - holds_ = 1; - return true; - } - else if (caller == owner_) { - incHolds(); - return true; - } - } - WaitQueue.WaitNode n = new WaitQueue.WaitNode(); - return n.doTimedWait(this, nanos); - } - - protected synchronized WaitQueue.WaitNode getSignallee(Thread caller) { - if (caller != owner_) - throw new IllegalMonitorStateException("Not owner"); - // assert (holds_ > 0) - if (holds_ >= 2) { // current thread will keep the lock - --holds_; - return null; - } - // assert (holds_ == 1) - WaitQueue.WaitNode w = wq_.extract(); - if (w == null) { // if none, clear for new arrivals - owner_ = null; - holds_ = 0; - } - return w; - } - - public void unlock() { - Thread caller = Thread.currentThread(); - for (;;) { - WaitQueue.WaitNode w = getSignallee(caller); - if (w == null) return; // no one to signal - if (w.signal(this)) return; // notify if still waiting, else skip - } - } - - public final boolean isFair() { - return true; - } - - public synchronized boolean hasQueuedThreads() { - return wq_.hasNodes(); - } - - public synchronized int getQueueLength() { - return wq_.getLength(); - } - - public synchronized Collection getQueuedThreads() { - return wq_.getWaitingThreads(); - } - - public synchronized boolean isQueued(Thread thread) { - return wq_.isWaiting(thread); - } - - private void readObject(java.io.ObjectInputStream in) - throws java.io.IOException, ClassNotFoundException { - in.defaultReadObject(); - synchronized (this) { - wq_ = new FIFOWaitQueue(); - } - } - } - - /** - * 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)? (Sync)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.lockInterruptibly(); - } - - /** - * 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 "barging" behavior can be useful in certain - * circumstances, even though it breaks fairness. If you want to honor - * the fairness setting for this lock, then use - * {@link #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) } - * which is almost equivalent (it also detects interruption). - * - * <p> If the current thread already holds this lock then the hold - * count is incremented by one and the method returns {@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.tryLock(); - } - - /** - * 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.tryLock(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.unlock(); - } - - /** - * 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 isFair() ? (Condition)new FIFOCondVar(this) : new CondVar(this); - } - - /** - * 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.isHeldByCurrentThread(); - } - - /** - * Queries if this lock is held by any thread. This method is - * designed for use in monitoring of the system state, - * not for synchronization control. - * - * @return {@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.isFair(); - } - - /** - * 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 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) { - return asCondVar(condition).hasWaiters(); - } - - /** - * Returns an estimate of the number of threads waiting on the - * given condition associated with this lock. Note that because - * timeouts and interrupts may occur at any time, the estimate - * serves only as an upper bound on the actual number of waiters. - * This method is designed for use in monitoring of the system - * state, not for synchronization control. - * - * @param condition the condition - * @return the estimated number of waiting threads - * @throws IllegalMonitorStateException if this lock is not held - * @throws IllegalArgumentException if the given condition is - * not associated with this lock - * @throws NullPointerException if the condition is null - */ - public int getWaitQueueLength(Condition condition) { - return asCondVar(condition).getWaitQueueLength(); - } - - /** - * Returns a collection containing those threads that may be - * waiting on the given condition associated with this lock. - * Because the actual set of threads may change dynamically while - * constructing this result, the returned collection is only a - * best-effort estimate. The elements of the returned collection - * are in no particular order. This method is designed to - * facilitate construction of subclasses that provide more - * extensive condition monitoring facilities. - * - * @param condition the condition - * @return the collection of threads - * @throws IllegalMonitorStateException if this lock is not held - * @throws IllegalArgumentException if the given condition is - * not associated with this lock - * @throws NullPointerException if the condition is null - */ - protected Collection getWaitingThreads(Condition condition) { - return asCondVar(condition).getWaitingThreads(); - } - - /** - * Returns a string identifying this lock, as well as its lock state. - * The state, in brackets, includes either the String {@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 = getOwner(); - return super.toString() + ((o == null) ? - "[Unlocked]" : - "[Locked by thread " + o.getName() + "]"); - } - - private CondVar asCondVar(Condition condition) { - if (condition == null) - throw new NullPointerException(); - if (!(condition instanceof CondVar)) - throw new IllegalArgumentException("not owner"); - CondVar condVar = (CondVar)condition; - if (condVar.lock != this) - throw new IllegalArgumentException("not owner"); - return condVar; - } -} diff --git a/src/actors/scala/actors/threadpool/locks/ReentrantReadWriteLock.java b/src/actors/scala/actors/threadpool/locks/ReentrantReadWriteLock.java deleted file mode 100644 index 914d242100..0000000000 --- a/src/actors/scala/actors/threadpool/locks/ReentrantReadWriteLock.java +++ /dev/null @@ -1,1341 +0,0 @@ -/* - * 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 scala.actors.threadpool.locks; - -import java.util.HashMap; -import scala.actors.threadpool.*; -import scala.actors.threadpool.helpers.*; - -/** - * 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>The order of entry - * to the read and write lock is unspecified, subject to reentrancy - * constraints. A nonfair lock that is continuously contended may - * indefinitely postpone one or more reader or writer threads, but - * will normally have higher throughput than a fair lock. - * <p> - * - * DEPARTURE FROM java.util.concurrent: this implementation impose - * a writer-preference and thus its acquisition order may be different - * than in java.util.concurrent. - * - * <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 = -3463448656717690166L; - - final ReadLock readerLock_ = new ReadLock(this); - final WriteLock writerLock_ = new WriteLock(this); - - final Sync sync; - - /** - * Creates a new {@code ReentrantReadWriteLock} with - * default (nonfair) ordering properties. - */ - public ReentrantReadWriteLock() { - this.sync = new NonfairSync(); - } - - public Lock writeLock() { return writerLock_; } - public Lock readLock() { return readerLock_; } - - /** - * Synchronization implementation for ReentrantReadWriteLock. - * Subclassed into fair and nonfair versions. - */ - private abstract static class Sync implements java.io.Serializable { - - private static final int NONE = 0; - private static final int READER = 1; - private static final int WRITER = 2; - - transient int activeReaders_ = 0; - transient Thread activeWriter_ = null; - transient int waitingReaders_ = 0; - transient int waitingWriters_ = 0; - - /** Number of acquires on write lock by activeWriter_ thread **/ - transient int writeHolds_ = 0; - - /** Number of acquires on read lock by any reader thread **/ - transient HashMap<Thread, Integer> readers_ = new HashMap<Thread, Integer>(); - - /** cache/reuse the special Integer value one to speed up readlocks **/ - static final Integer IONE = new Integer(1); - - Sync() {} - - /* - Each of these variants is needed to maintain atomicity - of wait counts during wait loops. They could be - made faster by manually inlining each other. We hope that - compilers do this for us though. - */ - - synchronized boolean startReadFromNewReader() { - boolean pass = startRead(); - if (!pass) ++waitingReaders_; - return pass; - } - - synchronized boolean startWriteFromNewWriter() { - boolean pass = startWrite(); - if (!pass) ++waitingWriters_; - return pass; - } - - synchronized boolean startReadFromWaitingReader() { - boolean pass = startRead(); - if (pass) --waitingReaders_; - return pass; - } - - synchronized boolean startWriteFromWaitingWriter() { - boolean pass = startWrite(); - if (pass) --waitingWriters_; - return pass; - } - - /* - A bunch of small synchronized methods are needed - to allow communication from the Lock objects - back to this object, that serves as controller - */ - - synchronized void cancelledWaitingReader() { --waitingReaders_; } - synchronized void cancelledWaitingWriter() { --waitingWriters_; } - - boolean allowReader() { - return (activeWriter_ == null && waitingWriters_ == 0) || - activeWriter_ == Thread.currentThread(); - } - - synchronized boolean startRead() { - Thread t = Thread.currentThread(); - Object c = readers_.get(t); - if (c != null) { // already held -- just increment hold count - readers_.put(t, new Integer( ( (Integer) (c)).intValue() + 1)); - ++activeReaders_; - return true; - } - else if (allowReader()) { - readers_.put(t, IONE); - ++activeReaders_; - return true; - } - else - return false; - } - - synchronized boolean startWrite() { - if (activeWriter_ == Thread.currentThread()) { // already held; re-acquire - ++writeHolds_; - return true; - } - else if (writeHolds_ == 0) { - if (activeReaders_ == 0 || - (readers_.size() == 1 && - readers_.get(Thread.currentThread()) != null)) { - activeWriter_ = Thread.currentThread(); - writeHolds_ = 1; - return true; - } - else - return false; - } - else - return false; - } - - synchronized int endRead() { - Thread t = Thread.currentThread(); - Object c = readers_.get(t); - if (c == null) - throw new IllegalMonitorStateException(); - --activeReaders_; - if (c != IONE) { // more than one hold; decrement count - int h = ( (Integer) (c)).intValue() - 1; - Integer ih = (h == 1) ? IONE : new Integer(h); - readers_.put(t, ih); - return NONE; - } - else { - readers_.remove(t); - - if (writeHolds_ > 0) // a write lock is still held by current thread - return NONE; - else if (activeReaders_ == 0 && waitingWriters_ > 0) - return WRITER; - else - return NONE; - } - } - - synchronized int endWrite() { - if (activeWriter_ != Thread.currentThread()) { - throw new IllegalMonitorStateException(); - } - --writeHolds_; - if (writeHolds_ > 0) // still being held - return NONE; - else { - activeWriter_ = null; - if (waitingReaders_ > 0 && allowReader()) - return READER; - else if (waitingWriters_ > 0) - return WRITER; - else - return NONE; - } - } - - synchronized Thread getOwner() { - return activeWriter_; - } - - synchronized int getReadLockCount() { - return activeReaders_; - } - - synchronized boolean isWriteLocked() { - return activeWriter_ != null; - } - - synchronized boolean isWriteLockedByCurrentThread() { - return activeWriter_ == Thread.currentThread(); - } - - synchronized int getWriteHoldCount() { - return isWriteLockedByCurrentThread() ? writeHolds_ : 0; - } - - synchronized int getReadHoldCount() { - if (activeReaders_ == 0) return 0; - Thread t = Thread.currentThread(); - Integer i = readers_.get(t); - return (i == null) ? 0 : i.intValue(); - } - - final synchronized boolean hasQueuedThreads() { - return waitingWriters_ > 0 || waitingReaders_ > 0; - } - - final synchronized int getQueueLength() { - return waitingWriters_ + waitingReaders_; - } - - private void readObject(java.io.ObjectInputStream in) - throws java.io.IOException, ClassNotFoundException { - in.defaultReadObject(); - // readers_ is transient, need to reinitialize. Let's flush the memory - // and ensure visibility by synchronizing (all other accesses to - // readers_ are also synchronized on "this") - synchronized (this) { - readers_ = new HashMap<Thread, Integer>(); - } - } - } - - /** - * Nonfair version of Sync - */ - private static class NonfairSync extends Sync { - private static final long serialVersionUID = -2392241841540339773L; - - NonfairSync() {} - } - - /** - * The lock returned by method {@link ReentrantReadWriteLock#readLock}. - */ - public static class ReadLock implements Lock, java.io.Serializable { - - private static final long serialVersionUID = -5992448646407690164L; - - final ReentrantReadWriteLock lock; - - /** - * Constructor for use by subclasses - * - * @param lock the outer lock object - * @throws NullPointerException if the lock is null - */ - protected ReadLock(ReentrantReadWriteLock lock) { - if (lock == null) throw new NullPointerException(); - this.lock = lock; - } - - /** - * 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() { - synchronized (this) { - if (lock.sync.startReadFromNewReader()) return; - boolean wasInterrupted = Thread.interrupted(); - try { - while (true) { - try { - ReadLock.this.wait(); - } - catch (InterruptedException ex) { - wasInterrupted = true; - // no need to propagate the potentially masked - // signal, since readers are always notified all - } - if (lock.sync.startReadFromWaitingReader()) return; - } - } - finally { - if (wasInterrupted) Thread.currentThread().interrupt(); - } - } - } - - /** - * 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 { - if (Thread.interrupted()) throw new InterruptedException(); - InterruptedException ie = null; - synchronized (this) { - if (!lock.sync.startReadFromNewReader()) { - for (; ; ) { - try { - ReadLock.this.wait(); - if (lock.sync.startReadFromWaitingReader()) - return; - } - catch (InterruptedException ex) { - lock.sync.cancelledWaitingReader(); - ie = ex; - break; - } - } - } - } - if (ie != null) { - // fall through outside synch on interrupt. - // This notification is not really needed here, - // but may be in plausible subclasses - lock.writerLock_.signalWaiters(); - throw ie; - } - } - - /** - * 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 "barging" behavior - * can be useful in certain circumstances, even though it - * breaks fairness. If you want to honor the fairness setting - * for this lock, then use {@link #tryLock(long, TimeUnit) - * tryLock(0, TimeUnit.SECONDS) } which is almost equivalent - * (it also detects interruption). - * - * <p>If the 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 lock.sync.startRead(); - } - - /** - * 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 { - if (Thread.interrupted()) throw new InterruptedException(); - InterruptedException ie = null; - long nanos = unit.toNanos(timeout); - synchronized (this) { - if (nanos <= 0) - return lock.sync.startRead(); - else if (lock.sync.startReadFromNewReader()) - return true; - else { - long deadline = Utils.nanoTime() + nanos; - for (; ; ) { - try { - TimeUnit.NANOSECONDS.timedWait(ReadLock.this, nanos); - } - catch (InterruptedException ex) { - lock.sync.cancelledWaitingReader(); - ie = ex; - break; - } - if (lock.sync.startReadFromWaitingReader()) - return true; - else { - nanos = deadline - Utils.nanoTime(); - if (nanos <= 0) { - lock.sync.cancelledWaitingReader(); - break; - } - } - } - } - } - // safeguard on interrupt or timeout: - lock.writerLock_.signalWaiters(); - if (ie != null) - throw ie; - else - return false; // timed out - } - - /** - * 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() { - switch (lock.sync.endRead()) { - case Sync.NONE: return; - case Sync.READER: lock.readerLock_.signalWaiters(); return; - case Sync.WRITER: lock.writerLock_.signalWaiters(); return; - } - } - - /** - * Throws {@code UnsupportedOperationException} because - * {@code ReadLocks} do not support conditions. - * - * @throws UnsupportedOperationException always - */ - public Condition newCondition() { - throw new UnsupportedOperationException(); - } - - synchronized void signalWaiters() { - notifyAll(); - } - - /** - * 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 = lock.getReadLockCount(); - return super.toString() + - "[Read locks = " + r + "]"; - } - - } - - /** - * The lock returned by method {@link ReentrantReadWriteLock#writeLock}. - */ - public static class WriteLock implements Lock, CondVar.ExclusiveLock, - java.io.Serializable { - - private static final long serialVersionUID = -4992448646407690164L; - final ReentrantReadWriteLock lock; - - /** - * Constructor for use by subclasses - * - * @param lock the outer lock object - * @throws NullPointerException if the lock is null - */ - protected WriteLock(ReentrantReadWriteLock lock) { - if (lock == null) throw new NullPointerException(); - this.lock = lock; - } - - /** - * 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() { - synchronized (this) { - if (lock.sync.startWriteFromNewWriter()) return; - boolean wasInterrupted = Thread.interrupted(); - try { - while (true) { - try { - WriteLock.this.wait(); - } - catch (InterruptedException ex) { - wasInterrupted = true; - // no need to notify; if we were notified, - // we will act as notified, and succeed in - // startWrite and return - } - if (lock.sync.startWriteFromWaitingWriter()) return; - } - } - finally { - if (wasInterrupted) Thread.currentThread().interrupt(); - } - } - } - - /** - * 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 { - if (Thread.interrupted()) throw new InterruptedException(); - InterruptedException ie = null; - synchronized (this) { - if (!lock.sync.startWriteFromNewWriter()) { - for (; ; ) { - try { - WriteLock.this.wait(); - if (lock.sync.startWriteFromWaitingWriter()) - return; - } - catch (InterruptedException ex) { - lock.sync.cancelledWaitingWriter(); - WriteLock.this.notify(); - ie = ex; - break; - } - } - } - } - if (ie != null) { - // Fall through outside synch on interrupt. - // On exception, we may need to signal readers. - // It is not worth checking here whether it is strictly necessary. - lock.readerLock_.signalWaiters(); - throw ie; - } - } - - /** - * 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 "barging" - * behavior can be useful in certain circumstances, even - * though it breaks fairness. If you want to honor the - * fairness setting for this lock, then use {@link - * #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) } - * which is almost equivalent (it also detects interruption). - * - * <p> If the current thread already holds this lock then the - * hold count is incremented by one and the method returns - * {@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 lock.sync.startWrite(); - } - - /** - * 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 { - if (Thread.interrupted()) throw new InterruptedException(); - InterruptedException ie = null; - long nanos = unit.toNanos(timeout); - synchronized (this) { - if (nanos <= 0) - return lock.sync.startWrite(); - else if (lock.sync.startWriteFromNewWriter()) - return true; - else { - long deadline = Utils.nanoTime() + nanos; - for (; ; ) { - try { - TimeUnit.NANOSECONDS.timedWait(WriteLock.this, nanos); - } - catch (InterruptedException ex) { - lock.sync.cancelledWaitingWriter(); - WriteLock.this.notify(); - ie = ex; - break; - } - if (lock.sync.startWriteFromWaitingWriter()) - return true; - else { - nanos = deadline - Utils.nanoTime(); - if (nanos <= 0) { - lock.sync.cancelledWaitingWriter(); - WriteLock.this.notify(); - break; - } - } - } - } - } - - lock.readerLock_.signalWaiters(); - if (ie != null) - throw ie; - else - return false; // timed out - } - - /** - * 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() { - switch (lock.sync.endWrite()) { - case Sync.NONE: return; - case Sync.READER: lock.readerLock_.signalWaiters(); return; - case Sync.WRITER: lock.writerLock_.signalWaiters(); return; - } - } - - /** - * 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 new CondVar(this); - } - - synchronized void signalWaiters() { - notify(); - } - - /** - * 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 = lock.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 lock.sync.isWriteLockedByCurrentThread(); - } - - /** - * 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 lock.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 false; - } - - /** - * 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.isWriteLockedByCurrentThread(); - } - - /** - * 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 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 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 <tt>true</tt> 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 true if the given thread is queued waiting for this lock. -// * @throws NullPointerException if thread is null -// */ -// public final boolean hasQueuedThread(Thread thread) { -// return sync.isQueued(thread); -// } - - /** - * Returns an estimate of the number of threads waiting to acquire - * 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 getQueuedThreads() { -// return sync.getQueuedThreads(); -// } -// -// /** -// * Queries whether any threads are waiting on the given condition -// * associated with the write lock. Note that because timeouts and -// * interrupts may occur at any time, a <tt>true</tt> return does -// * not guarantee that a future <tt>signal</tt> will awaken any -// * threads. This method is designed primarily for use in -// * monitoring of the system state. -// * @param condition the condition -// * @return <tt>true</tt> if there are any waiting threads. -// * @throws IllegalMonitorStateException if this lock -// * is not held -// * @throws IllegalArgumentException if the given condition is -// * not associated with this lock -// * @throws NullPointerException if condition null -// */ -// public boolean hasWaiters(Condition condition) { -// if (condition == null) -// throw new NullPointerException(); -// if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject)) -// throw new IllegalArgumentException("not owner"); -// return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition); -// } - -// /** -// * Returns an estimate of the number of threads waiting on the -// * given condition associated with the write lock. Note that because -// * timeouts and interrupts may occur at any time, the estimate -// * serves only as an upper bound on the actual number of waiters. -// * This method is designed for use in monitoring of the system -// * state, not for synchronization control. -// * @param condition the condition -// * @return the estimated number of waiting threads. -// * @throws IllegalMonitorStateException if this lock -// * is not held -// * @throws IllegalArgumentException if the given condition is -// * not associated with this lock -// * @throws NullPointerException if condition null -// */ -// public int getWaitQueueLength(Condition condition) { -// if (condition == null) -// throw new NullPointerException(); -// if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject)) -// throw new IllegalArgumentException("not owner"); -// return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition); -// } -// -// /** -// * Returns a collection containing those threads that may be -// * waiting on the given condition associated with the write lock. -// * Because the actual set of threads may change dynamically while -// * constructing this result, the returned collection is only a -// * best-effort estimate. The elements of the returned collection -// * are in no particular order. This method is designed to -// * facilitate construction of subclasses that provide more -// * extensive condition monitoring facilities. -// * @param condition the condition -// * @return the collection of threads -// * @throws IllegalMonitorStateException if this lock -// * is not held -// * @throws IllegalArgumentException if the given condition is -// * not associated with this lock -// * @throws NullPointerException if condition null -// */ -// protected Collection 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() { - return super.toString() + - "[Write locks = " + getWriteHoldCount() + - ", Read locks = " + getReadLockCount() + "]"; - } -} |