001/* 002 * This file is a modified version of 003 * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/main/java/util/concurrent/AbstractExecutorService.java?revision=1.35 004 * which contained the following notice: 005 * 006 * Written by Doug Lea with assistance from members of JCP JSR-166 Expert Group and released to the 007 * public domain, as explained at http://creativecommons.org/publicdomain/zero/1.0/ 008 * 009 * Rationale for copying: 010 * Guava targets JDK5, whose AbstractExecutorService class lacks the newTaskFor protected 011 * customization methods needed by MoreExecutors.listeningDecorator. This class is a copy of 012 * AbstractExecutorService from the JSR166 CVS repository. It contains the desired methods. 013 */ 014 015package com.google.common.util.concurrent; 016 017import static com.google.common.util.concurrent.MoreExecutors.invokeAnyImpl; 018 019import com.google.common.annotations.Beta; 020 021import java.util.ArrayList; 022import java.util.Collection; 023import java.util.Iterator; 024import java.util.List; 025import java.util.concurrent.Callable; 026import java.util.concurrent.CancellationException; 027import java.util.concurrent.ExecutionException; 028import java.util.concurrent.Future; 029import java.util.concurrent.TimeUnit; 030import java.util.concurrent.TimeoutException; 031 032import javax.annotation.Nullable; 033 034/** 035 * Implements {@link ListeningExecutorService} execution methods atop the abstract {@link #execute} 036 * method. More concretely, the {@code submit}, {@code invokeAny} and {@code invokeAll} methods 037 * create {@link ListenableFutureTask} instances and pass them to {@link #execute}. 038 * 039 * <p>In addition to {@link #execute}, subclasses must implement all methods related to shutdown and 040 * termination. 041 * 042 * @author Doug Lea 043 * @since 14.0 044 */ 045@Beta 046public abstract class AbstractListeningExecutorService implements ListeningExecutorService { 047 @Override 048 public ListenableFuture<?> submit(Runnable task) { 049 ListenableFutureTask<Void> ftask = ListenableFutureTask.create(task, null); 050 execute(ftask); 051 return ftask; 052 } 053 054 @Override 055 public <T> ListenableFuture<T> submit(Runnable task, @Nullable T result) { 056 ListenableFutureTask<T> ftask = ListenableFutureTask.create(task, result); 057 execute(ftask); 058 return ftask; 059 } 060 061 @Override 062 public <T> ListenableFuture<T> submit(Callable<T> task) { 063 ListenableFutureTask<T> ftask = ListenableFutureTask.create(task); 064 execute(ftask); 065 return ftask; 066 } 067 068 @Override 069 public <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, 070 ExecutionException { 071 try { 072 return invokeAnyImpl(this, tasks, false, 0); 073 } catch (TimeoutException cannotHappen) { 074 throw new AssertionError(); 075 } 076 } 077 078 @Override 079 public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) 080 throws InterruptedException, ExecutionException, TimeoutException { 081 return invokeAnyImpl(this, tasks, true, unit.toNanos(timeout)); 082 } 083 084 @Override 085 public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) 086 throws InterruptedException { 087 if (tasks == null) { 088 throw new NullPointerException(); 089 } 090 List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size()); 091 boolean done = false; 092 try { 093 for (Callable<T> t : tasks) { 094 ListenableFutureTask<T> f = ListenableFutureTask.create(t); 095 futures.add(f); 096 execute(f); 097 } 098 for (Future<T> f : futures) { 099 if (!f.isDone()) { 100 try { 101 f.get(); 102 } catch (CancellationException ignore) {} catch (ExecutionException ignore) {} 103 } 104 } 105 done = true; 106 return futures; 107 } finally { 108 if (!done) { 109 for (Future<T> f : futures) { 110 f.cancel(true); 111 } 112 } 113 } 114 } 115 116 @Override 117 public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, 118 TimeUnit unit) throws InterruptedException { 119 if (tasks == null || unit == null) { 120 throw new NullPointerException(); 121 } 122 long nanos = unit.toNanos(timeout); 123 List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size()); 124 boolean done = false; 125 try { 126 for (Callable<T> t : tasks) { 127 futures.add(ListenableFutureTask.create(t)); 128 } 129 130 long lastTime = System.nanoTime(); 131 132 // Interleave time checks and calls to execute in case 133 // executor doesn't have any/much parallelism. 134 Iterator<Future<T>> it = futures.iterator(); 135 while (it.hasNext()) { 136 execute((Runnable) (it.next())); 137 long now = System.nanoTime(); 138 nanos -= now - lastTime; 139 lastTime = now; 140 if (nanos <= 0) { 141 return futures; 142 } 143 } 144 145 for (Future<T> f : futures) { 146 if (!f.isDone()) { 147 if (nanos <= 0) { 148 return futures; 149 } 150 try { 151 f.get(nanos, TimeUnit.NANOSECONDS); 152 } catch (CancellationException ignore) {} catch (ExecutionException ignore) {} catch (TimeoutException toe) { 153 return futures; 154 } 155 long now = System.nanoTime(); 156 nanos -= now - lastTime; 157 lastTime = now; 158 } 159 } 160 done = true; 161 return futures; 162 } finally { 163 if (!done) { 164 for (Future<T> f : futures) { 165 f.cancel(true); 166 } 167 } 168 } 169 } 170}