10888a09821a98ac0680fad765217302858e70fa4Paul Duffin/*
20888a09821a98ac0680fad765217302858e70fa4Paul Duffin * This file is a modified version of
30888a09821a98ac0680fad765217302858e70fa4Paul Duffin * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/main/java/util/concurrent/AbstractExecutorService.java?revision=1.20
40888a09821a98ac0680fad765217302858e70fa4Paul Duffin * which contained the following notice:
50888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
60888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Written by Doug Lea with assistance from members of JCP JSR-166
70888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Expert Group and released to the public domain, as explained at
80888a09821a98ac0680fad765217302858e70fa4Paul Duffin * http://creativecommons.org/licenses/publicdomain
90888a09821a98ac0680fad765217302858e70fa4Paul Duffin */
100888a09821a98ac0680fad765217302858e70fa4Paul Duffin
110888a09821a98ac0680fad765217302858e70fa4Paul Duffinpackage java.util.concurrent;
120888a09821a98ac0680fad765217302858e70fa4Paul Duffin
130888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.util.*;
140888a09821a98ac0680fad765217302858e70fa4Paul Duffin
150888a09821a98ac0680fad765217302858e70fa4Paul Duffinpublic abstract class AbstractExecutorService implements ExecutorService {
160888a09821a98ac0680fad765217302858e70fa4Paul Duffin
170888a09821a98ac0680fad765217302858e70fa4Paul Duffin    public Future<?> submit(Runnable task) {
180888a09821a98ac0680fad765217302858e70fa4Paul Duffin        if (task == null) throw new NullPointerException();
190888a09821a98ac0680fad765217302858e70fa4Paul Duffin        FutureTask<Object> ftask = new FutureTask<Object>(task, null);
200888a09821a98ac0680fad765217302858e70fa4Paul Duffin        execute(ftask);
210888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return ftask;
220888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
230888a09821a98ac0680fad765217302858e70fa4Paul Duffin
240888a09821a98ac0680fad765217302858e70fa4Paul Duffin    public <T> Future<T> submit(Runnable task, T result) {
250888a09821a98ac0680fad765217302858e70fa4Paul Duffin        if (task == null) throw new NullPointerException();
260888a09821a98ac0680fad765217302858e70fa4Paul Duffin        FutureTask<T> ftask = new FutureTask<T>(task, result);
270888a09821a98ac0680fad765217302858e70fa4Paul Duffin        execute(ftask);
280888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return ftask;
290888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
300888a09821a98ac0680fad765217302858e70fa4Paul Duffin
310888a09821a98ac0680fad765217302858e70fa4Paul Duffin    public <T> Future<T> submit(Callable<T> task) {
320888a09821a98ac0680fad765217302858e70fa4Paul Duffin        if (task == null) throw new NullPointerException();
330888a09821a98ac0680fad765217302858e70fa4Paul Duffin        FutureTask<T> ftask = new FutureTask<T>(task);
340888a09821a98ac0680fad765217302858e70fa4Paul Duffin        execute(ftask);
350888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return ftask;
360888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
370888a09821a98ac0680fad765217302858e70fa4Paul Duffin
380888a09821a98ac0680fad765217302858e70fa4Paul Duffin    private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,
390888a09821a98ac0680fad765217302858e70fa4Paul Duffin                            boolean timed, long nanos)
400888a09821a98ac0680fad765217302858e70fa4Paul Duffin        throws InterruptedException, ExecutionException, TimeoutException {
410888a09821a98ac0680fad765217302858e70fa4Paul Duffin        if (tasks == null)
420888a09821a98ac0680fad765217302858e70fa4Paul Duffin            throw new NullPointerException();
430888a09821a98ac0680fad765217302858e70fa4Paul Duffin        int ntasks = tasks.size();
440888a09821a98ac0680fad765217302858e70fa4Paul Duffin        if (ntasks == 0)
450888a09821a98ac0680fad765217302858e70fa4Paul Duffin            throw new IllegalArgumentException();
460888a09821a98ac0680fad765217302858e70fa4Paul Duffin        List<Future<T>> futures= new ArrayList<Future<T>>(ntasks);
470888a09821a98ac0680fad765217302858e70fa4Paul Duffin        ExecutorCompletionService<T> ecs =
480888a09821a98ac0680fad765217302858e70fa4Paul Duffin            new ExecutorCompletionService<T>(this);
490888a09821a98ac0680fad765217302858e70fa4Paul Duffin
500888a09821a98ac0680fad765217302858e70fa4Paul Duffin        try {
510888a09821a98ac0680fad765217302858e70fa4Paul Duffin            ExecutionException ee = null;
520888a09821a98ac0680fad765217302858e70fa4Paul Duffin            long lastTime = (timed)? System.nanoTime() : 0;
530888a09821a98ac0680fad765217302858e70fa4Paul Duffin            Iterator<? extends Callable<T>> it = tasks.iterator();
540888a09821a98ac0680fad765217302858e70fa4Paul Duffin
550888a09821a98ac0680fad765217302858e70fa4Paul Duffin            futures.add(ecs.submit(it.next()));
560888a09821a98ac0680fad765217302858e70fa4Paul Duffin            --ntasks;
570888a09821a98ac0680fad765217302858e70fa4Paul Duffin            int active = 1;
580888a09821a98ac0680fad765217302858e70fa4Paul Duffin
590888a09821a98ac0680fad765217302858e70fa4Paul Duffin            for (;;) {
600888a09821a98ac0680fad765217302858e70fa4Paul Duffin                Future<T> f = ecs.poll();
610888a09821a98ac0680fad765217302858e70fa4Paul Duffin                if (f == null) {
620888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    if (ntasks > 0) {
630888a09821a98ac0680fad765217302858e70fa4Paul Duffin                        --ntasks;
640888a09821a98ac0680fad765217302858e70fa4Paul Duffin                        futures.add(ecs.submit(it.next()));
650888a09821a98ac0680fad765217302858e70fa4Paul Duffin                        ++active;
660888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    }
670888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    else if (active == 0)
680888a09821a98ac0680fad765217302858e70fa4Paul Duffin                        break;
690888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    else if (timed) {
700888a09821a98ac0680fad765217302858e70fa4Paul Duffin                        f = ecs.poll(nanos, TimeUnit.NANOSECONDS);
710888a09821a98ac0680fad765217302858e70fa4Paul Duffin                        if (f == null)
720888a09821a98ac0680fad765217302858e70fa4Paul Duffin                            throw new TimeoutException();
730888a09821a98ac0680fad765217302858e70fa4Paul Duffin                        long now = System.nanoTime();
740888a09821a98ac0680fad765217302858e70fa4Paul Duffin                        nanos -= now - lastTime;
750888a09821a98ac0680fad765217302858e70fa4Paul Duffin                        lastTime = now;
760888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    }
770888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    else
780888a09821a98ac0680fad765217302858e70fa4Paul Duffin                        f = ecs.take();
790888a09821a98ac0680fad765217302858e70fa4Paul Duffin                }
800888a09821a98ac0680fad765217302858e70fa4Paul Duffin                if (f != null) {
810888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    --active;
820888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    try {
830888a09821a98ac0680fad765217302858e70fa4Paul Duffin                        return f.get();
840888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    } catch (InterruptedException ie) {
850888a09821a98ac0680fad765217302858e70fa4Paul Duffin                        throw ie;
860888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    } catch (ExecutionException eex) {
870888a09821a98ac0680fad765217302858e70fa4Paul Duffin                        ee = eex;
880888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    } catch (RuntimeException rex) {
890888a09821a98ac0680fad765217302858e70fa4Paul Duffin                        ee = new ExecutionException(rex);
900888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    }
910888a09821a98ac0680fad765217302858e70fa4Paul Duffin                }
920888a09821a98ac0680fad765217302858e70fa4Paul Duffin            }
930888a09821a98ac0680fad765217302858e70fa4Paul Duffin
940888a09821a98ac0680fad765217302858e70fa4Paul Duffin            if (ee == null)
950888a09821a98ac0680fad765217302858e70fa4Paul Duffin                ee = new ExecutionException();
960888a09821a98ac0680fad765217302858e70fa4Paul Duffin            throw ee;
970888a09821a98ac0680fad765217302858e70fa4Paul Duffin
980888a09821a98ac0680fad765217302858e70fa4Paul Duffin        } finally {
990888a09821a98ac0680fad765217302858e70fa4Paul Duffin            for (Future<T> f : futures)
1000888a09821a98ac0680fad765217302858e70fa4Paul Duffin                f.cancel(true);
1010888a09821a98ac0680fad765217302858e70fa4Paul Duffin        }
1020888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1030888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1040888a09821a98ac0680fad765217302858e70fa4Paul Duffin    public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
1050888a09821a98ac0680fad765217302858e70fa4Paul Duffin        throws InterruptedException, ExecutionException {
1060888a09821a98ac0680fad765217302858e70fa4Paul Duffin        try {
1070888a09821a98ac0680fad765217302858e70fa4Paul Duffin            return doInvokeAny(tasks, false, 0);
1080888a09821a98ac0680fad765217302858e70fa4Paul Duffin        } catch (TimeoutException cannotHappen) {
1090888a09821a98ac0680fad765217302858e70fa4Paul Duffin            assert false;
1100888a09821a98ac0680fad765217302858e70fa4Paul Duffin            return null;
1110888a09821a98ac0680fad765217302858e70fa4Paul Duffin        }
1120888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1130888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1140888a09821a98ac0680fad765217302858e70fa4Paul Duffin    public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
1150888a09821a98ac0680fad765217302858e70fa4Paul Duffin                           long timeout, TimeUnit unit)
1160888a09821a98ac0680fad765217302858e70fa4Paul Duffin        throws InterruptedException, ExecutionException, TimeoutException {
1170888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return doInvokeAny(tasks, true, unit.toNanos(timeout));
1180888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1190888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1200888a09821a98ac0680fad765217302858e70fa4Paul Duffin    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
1210888a09821a98ac0680fad765217302858e70fa4Paul Duffin        throws InterruptedException {
1220888a09821a98ac0680fad765217302858e70fa4Paul Duffin        if (tasks == null)
1230888a09821a98ac0680fad765217302858e70fa4Paul Duffin            throw new NullPointerException();
1240888a09821a98ac0680fad765217302858e70fa4Paul Duffin        List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
1250888a09821a98ac0680fad765217302858e70fa4Paul Duffin        boolean done = false;
1260888a09821a98ac0680fad765217302858e70fa4Paul Duffin        try {
1270888a09821a98ac0680fad765217302858e70fa4Paul Duffin            for (Callable<T> t : tasks) {
1280888a09821a98ac0680fad765217302858e70fa4Paul Duffin                FutureTask<T> f = new FutureTask<T>(t);
1290888a09821a98ac0680fad765217302858e70fa4Paul Duffin                futures.add(f);
1300888a09821a98ac0680fad765217302858e70fa4Paul Duffin                execute(f);
1310888a09821a98ac0680fad765217302858e70fa4Paul Duffin            }
1320888a09821a98ac0680fad765217302858e70fa4Paul Duffin            for (Future<T> f : futures) {
1330888a09821a98ac0680fad765217302858e70fa4Paul Duffin                if (!f.isDone()) {
1340888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    try {
1350888a09821a98ac0680fad765217302858e70fa4Paul Duffin                        f.get();
1360888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    } catch (CancellationException ignore) {
1370888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    } catch (ExecutionException ignore) {
1380888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    }
1390888a09821a98ac0680fad765217302858e70fa4Paul Duffin                }
1400888a09821a98ac0680fad765217302858e70fa4Paul Duffin            }
1410888a09821a98ac0680fad765217302858e70fa4Paul Duffin            done = true;
1420888a09821a98ac0680fad765217302858e70fa4Paul Duffin            return futures;
1430888a09821a98ac0680fad765217302858e70fa4Paul Duffin        } finally {
1440888a09821a98ac0680fad765217302858e70fa4Paul Duffin            if (!done)
1450888a09821a98ac0680fad765217302858e70fa4Paul Duffin                for (Future<T> f : futures)
1460888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    f.cancel(true);
1470888a09821a98ac0680fad765217302858e70fa4Paul Duffin        }
1480888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1490888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1500888a09821a98ac0680fad765217302858e70fa4Paul Duffin    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
1510888a09821a98ac0680fad765217302858e70fa4Paul Duffin                                         long timeout, TimeUnit unit)
1520888a09821a98ac0680fad765217302858e70fa4Paul Duffin        throws InterruptedException {
1530888a09821a98ac0680fad765217302858e70fa4Paul Duffin        if (tasks == null || unit == null)
1540888a09821a98ac0680fad765217302858e70fa4Paul Duffin            throw new NullPointerException();
1550888a09821a98ac0680fad765217302858e70fa4Paul Duffin        long nanos = unit.toNanos(timeout);
1560888a09821a98ac0680fad765217302858e70fa4Paul Duffin        List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
1570888a09821a98ac0680fad765217302858e70fa4Paul Duffin        boolean done = false;
1580888a09821a98ac0680fad765217302858e70fa4Paul Duffin        try {
1590888a09821a98ac0680fad765217302858e70fa4Paul Duffin            for (Callable<T> t : tasks)
1600888a09821a98ac0680fad765217302858e70fa4Paul Duffin                futures.add(new FutureTask<T>(t));
1610888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1620888a09821a98ac0680fad765217302858e70fa4Paul Duffin            long lastTime = System.nanoTime();
1630888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1640888a09821a98ac0680fad765217302858e70fa4Paul Duffin            Iterator<Future<T>> it = futures.iterator();
1650888a09821a98ac0680fad765217302858e70fa4Paul Duffin            while (it.hasNext()) {
1660888a09821a98ac0680fad765217302858e70fa4Paul Duffin                execute((Runnable)(it.next()));
1670888a09821a98ac0680fad765217302858e70fa4Paul Duffin                long now = System.nanoTime();
1680888a09821a98ac0680fad765217302858e70fa4Paul Duffin                nanos -= now - lastTime;
1690888a09821a98ac0680fad765217302858e70fa4Paul Duffin                lastTime = now;
1700888a09821a98ac0680fad765217302858e70fa4Paul Duffin                if (nanos <= 0)
1710888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    return futures;
1720888a09821a98ac0680fad765217302858e70fa4Paul Duffin            }
1730888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1740888a09821a98ac0680fad765217302858e70fa4Paul Duffin            for (Future<T> f : futures) {
1750888a09821a98ac0680fad765217302858e70fa4Paul Duffin                if (!f.isDone()) {
1760888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    if (nanos <= 0)
1770888a09821a98ac0680fad765217302858e70fa4Paul Duffin                        return futures;
1780888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    try {
1790888a09821a98ac0680fad765217302858e70fa4Paul Duffin                        f.get(nanos, TimeUnit.NANOSECONDS);
1800888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    } catch (CancellationException ignore) {
1810888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    } catch (ExecutionException ignore) {
1820888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    } catch (TimeoutException toe) {
1830888a09821a98ac0680fad765217302858e70fa4Paul Duffin                        return futures;
1840888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    }
1850888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    long now = System.nanoTime();
1860888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    nanos -= now - lastTime;
1870888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    lastTime = now;
1880888a09821a98ac0680fad765217302858e70fa4Paul Duffin                }
1890888a09821a98ac0680fad765217302858e70fa4Paul Duffin            }
1900888a09821a98ac0680fad765217302858e70fa4Paul Duffin            done = true;
1910888a09821a98ac0680fad765217302858e70fa4Paul Duffin            return futures;
1920888a09821a98ac0680fad765217302858e70fa4Paul Duffin        } finally {
1930888a09821a98ac0680fad765217302858e70fa4Paul Duffin            if (!done)
1940888a09821a98ac0680fad765217302858e70fa4Paul Duffin                for (Future<T> f : futures)
1950888a09821a98ac0680fad765217302858e70fa4Paul Duffin                    f.cancel(true);
1960888a09821a98ac0680fad765217302858e70fa4Paul Duffin        }
1970888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1980888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1990888a09821a98ac0680fad765217302858e70fa4Paul Duffin}
200