mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			271 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			271 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			Java
		
	
	
	
/*
 | 
						|
 * Written by Doug Lea with assistance from members of JCP JSR-166
 | 
						|
 * Expert Group and released to the public domain, as explained at
 | 
						|
 * http://creativecommons.org/licenses/publicdomain
 | 
						|
 */
 | 
						|
 | 
						|
package java.util.concurrent;
 | 
						|
import java.util.*;
 | 
						|
 | 
						|
/**
 | 
						|
 * Provides default implementations of {@link ExecutorService}
 | 
						|
 * execution methods. This class implements the <tt>submit</tt>,
 | 
						|
 * <tt>invokeAny</tt> and <tt>invokeAll</tt> methods using a
 | 
						|
 * {@link RunnableFuture} returned by <tt>newTaskFor</tt>, which defaults
 | 
						|
 * to the {@link FutureTask} class provided in this package.  For example,
 | 
						|
 * the implementation of <tt>submit(Runnable)</tt> creates an
 | 
						|
 * associated <tt>RunnableFuture</tt> that is executed and
 | 
						|
 * returned. Subclasses may override the <tt>newTaskFor</tt> methods
 | 
						|
 * to return <tt>RunnableFuture</tt> implementations other than
 | 
						|
 * <tt>FutureTask</tt>.
 | 
						|
 *
 | 
						|
 * <p> <b>Extension example</b>. Here is a sketch of a class
 | 
						|
 * that customizes {@link ThreadPoolExecutor} to use
 | 
						|
 * a <tt>CustomTask</tt> class instead of the default <tt>FutureTask</tt>:
 | 
						|
 * <pre>
 | 
						|
 * public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
 | 
						|
 *
 | 
						|
 *   static class CustomTask<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 <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
 | 
						|
        return new FutureTask<T>(runnable, value);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns a <tt>RunnableFuture</tt> for the given callable task.
 | 
						|
     *
 | 
						|
     * @param callable the callable task being wrapped
 | 
						|
     * @return a <tt>RunnableFuture</tt> which when run will call the
 | 
						|
     * underlying callable and which, as a <tt>Future</tt>, will yield
 | 
						|
     * the callable's result as its result and provide for
 | 
						|
     * cancellation of the underlying task.
 | 
						|
     * @since 1.6
 | 
						|
     */
 | 
						|
    protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
 | 
						|
        return new FutureTask<T>(callable);
 | 
						|
    }
 | 
						|
 | 
						|
    public Future<?> submit(Runnable task) {
 | 
						|
        if (task == null) throw new NullPointerException();
 | 
						|
        RunnableFuture<Object> ftask = newTaskFor(task, null);
 | 
						|
        execute(ftask);
 | 
						|
        return ftask;
 | 
						|
    }
 | 
						|
 | 
						|
    public <T> Future<T> submit(Runnable task, T result) {
 | 
						|
        if (task == null) throw new NullPointerException();
 | 
						|
        RunnableFuture<T> ftask = newTaskFor(task, result);
 | 
						|
        execute(ftask);
 | 
						|
        return ftask;
 | 
						|
    }
 | 
						|
 | 
						|
    public <T> Future<T> submit(Callable<T> task) {
 | 
						|
        if (task == null) throw new NullPointerException();
 | 
						|
        RunnableFuture<T> ftask = newTaskFor(task);
 | 
						|
        execute(ftask);
 | 
						|
        return ftask;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * the main mechanics of invokeAny.
 | 
						|
     */
 | 
						|
    private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,
 | 
						|
                            boolean timed, long nanos)
 | 
						|
        throws InterruptedException, ExecutionException, TimeoutException {
 | 
						|
        if (tasks == null)
 | 
						|
            throw new NullPointerException();
 | 
						|
        int ntasks = tasks.size();
 | 
						|
        if (ntasks == 0)
 | 
						|
            throw new IllegalArgumentException();
 | 
						|
        List<Future<T>> futures= new ArrayList<Future<T>>(ntasks);
 | 
						|
        ExecutorCompletionService<T> ecs =
 | 
						|
            new ExecutorCompletionService<T>(this);
 | 
						|
 | 
						|
        // For efficiency, especially in executors with limited
 | 
						|
        // parallelism, check to see if previously submitted tasks are
 | 
						|
        // done before submitting more of them. This interleaving
 | 
						|
        // plus the exception mechanics account for messiness of main
 | 
						|
        // loop.
 | 
						|
 | 
						|
        try {
 | 
						|
            // Record exceptions so that if we fail to obtain any
 | 
						|
            // result, we can throw the last exception we got.
 | 
						|
            ExecutionException ee = null;
 | 
						|
            long lastTime = (timed)? System.nanoTime() : 0;
 | 
						|
            Iterator<? extends Callable<T>> it = tasks.iterator();
 | 
						|
 | 
						|
            // Start one task for sure; the rest incrementally
 | 
						|
            futures.add(ecs.submit(it.next()));
 | 
						|
            --ntasks;
 | 
						|
            int active = 1;
 | 
						|
 | 
						|
            for (;;) {
 | 
						|
                Future<T> f = ecs.poll();
 | 
						|
                if (f == null) {
 | 
						|
                    if (ntasks > 0) {
 | 
						|
                        --ntasks;
 | 
						|
                        futures.add(ecs.submit(it.next()));
 | 
						|
                        ++active;
 | 
						|
                    }
 | 
						|
                    else if (active == 0)
 | 
						|
                        break;
 | 
						|
                    else if (timed) {
 | 
						|
                        f = ecs.poll(nanos, TimeUnit.NANOSECONDS);
 | 
						|
                        if (f == null)
 | 
						|
                            throw new TimeoutException();
 | 
						|
                        long now = System.nanoTime();
 | 
						|
                        nanos -= now - lastTime;
 | 
						|
                        lastTime = now;
 | 
						|
                    }
 | 
						|
                    else
 | 
						|
                        f = ecs.take();
 | 
						|
                }
 | 
						|
                if (f != null) {
 | 
						|
                    --active;
 | 
						|
                    try {
 | 
						|
                        return f.get();
 | 
						|
                    } catch (InterruptedException ie) {
 | 
						|
                        throw ie;
 | 
						|
                    } catch (ExecutionException eex) {
 | 
						|
                        ee = eex;
 | 
						|
                    } catch (RuntimeException rex) {
 | 
						|
                        ee = new ExecutionException(rex);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            if (ee == null)
 | 
						|
                ee = new ExecutionException();
 | 
						|
            throw ee;
 | 
						|
 | 
						|
        } finally {
 | 
						|
            for (Future<T> f : futures)
 | 
						|
                f.cancel(true);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
 | 
						|
        throws InterruptedException, ExecutionException {
 | 
						|
        try {
 | 
						|
            return doInvokeAny(tasks, false, 0);
 | 
						|
        } catch (TimeoutException cannotHappen) {
 | 
						|
            assert false;
 | 
						|
            return null;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
 | 
						|
                           long timeout, TimeUnit unit)
 | 
						|
        throws InterruptedException, ExecutionException, TimeoutException {
 | 
						|
        return doInvokeAny(tasks, true, unit.toNanos(timeout));
 | 
						|
    }
 | 
						|
 | 
						|
    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
 | 
						|
        throws InterruptedException {
 | 
						|
        if (tasks == null)
 | 
						|
            throw new NullPointerException();
 | 
						|
        List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
 | 
						|
        boolean done = false;
 | 
						|
        try {
 | 
						|
            for (Callable<T> t : tasks) {
 | 
						|
                RunnableFuture<T> f = newTaskFor(t);
 | 
						|
                futures.add(f);
 | 
						|
                execute(f);
 | 
						|
            }
 | 
						|
            for (Future<T> f : futures) {
 | 
						|
                if (!f.isDone()) {
 | 
						|
                    try {
 | 
						|
                        f.get();
 | 
						|
                    } catch (CancellationException ignore) {
 | 
						|
                    } catch (ExecutionException ignore) {
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            done = true;
 | 
						|
            return futures;
 | 
						|
        } finally {
 | 
						|
            if (!done)
 | 
						|
                for (Future<T> f : futures)
 | 
						|
                    f.cancel(true);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
 | 
						|
                                         long timeout, TimeUnit unit)
 | 
						|
        throws InterruptedException {
 | 
						|
        if (tasks == null || unit == null)
 | 
						|
            throw new NullPointerException();
 | 
						|
        long nanos = unit.toNanos(timeout);
 | 
						|
        List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
 | 
						|
        boolean done = false;
 | 
						|
        try {
 | 
						|
            for (Callable<T> t : tasks)
 | 
						|
                futures.add(newTaskFor(t));
 | 
						|
 | 
						|
            long lastTime = System.nanoTime();
 | 
						|
 | 
						|
            // Interleave time checks and calls to execute in case
 | 
						|
            // executor doesn't have any/much parallelism.
 | 
						|
            Iterator<Future<T>> it = futures.iterator();
 | 
						|
            while (it.hasNext()) {
 | 
						|
                execute((Runnable)(it.next()));
 | 
						|
                long now = System.nanoTime();
 | 
						|
                nanos -= now - lastTime;
 | 
						|
                lastTime = now;
 | 
						|
                if (nanos <= 0)
 | 
						|
                    return futures;
 | 
						|
            }
 | 
						|
 | 
						|
            for (Future<T> f : futures) {
 | 
						|
                if (!f.isDone()) {
 | 
						|
                    if (nanos <= 0)
 | 
						|
                        return futures;
 | 
						|
                    try {
 | 
						|
                        f.get(nanos, TimeUnit.NANOSECONDS);
 | 
						|
                    } catch (CancellationException ignore) {
 | 
						|
                    } catch (ExecutionException ignore) {
 | 
						|
                    } catch (TimeoutException toe) {
 | 
						|
                        return futures;
 | 
						|
                    }
 | 
						|
                    long now = System.nanoTime();
 | 
						|
                    nanos -= now - lastTime;
 | 
						|
                    lastTime = now;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            done = true;
 | 
						|
            return futures;
 | 
						|
        } finally {
 | 
						|
            if (!done)
 | 
						|
                for (Future<T> f : futures)
 | 
						|
                    f.cancel(true);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
}
 |