ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/Future.java
(Generate patch)

Comparing jsr166/src/main/java/util/concurrent/Future.java (file contents):
Revision 1.44 by dl, Sat Nov 28 20:08:28 2020 UTC vs.
Revision 1.45 by dl, Fri Mar 18 16:01:42 2022 UTC

# Line 132 | Line 132 | public interface Future<V> {
132       */
133      V get(long timeout, TimeUnit unit)
134          throws InterruptedException, ExecutionException, TimeoutException;
135 +
136 +    /**
137 +     * Returns the computed result, without waiting.
138 +     *
139 +     * <p> This method is for cases where the caller knows that the task has
140 +     * already completed successfully, for example a filter-map of a stream of
141 +     * Future objects where the filter matches tasks that completed successfully.
142 +     * {@snippet lang=java :
143 +     *     results = futures.stream()
144 +     *                .filter(f -> f.state() == Future.State.SUCCESS)
145 +     *                .map(Future::resultNow)
146 +     *                .toList();
147 +     * }
148 +     *
149 +     * @implSpec
150 +     * The default implementation invokes {@code isDone()} to test if the task
151 +     * has completed. If done, it invokes {@code get()} to obtain the result.
152 +     *
153 +     * @return the computed result
154 +     * @throws IllegalStateException if the task has not completed or the task
155 +     * did not complete with a result
156 +     * @since 99
157 +     */
158 +    default V resultNow() {
159 +        if (!isDone())
160 +            throw new IllegalStateException("Task has not completed");
161 +        boolean interrupted = false;
162 +        try {
163 +            while (true) {
164 +                try {
165 +                    return get();
166 +                } catch (InterruptedException e) {
167 +                    interrupted = true;
168 +                } catch (ExecutionException e) {
169 +                    throw new IllegalStateException("Task completed with exception");
170 +                } catch (CancellationException e) {
171 +                    throw new IllegalStateException("Task was cancelled");
172 +                }
173 +            }
174 +        } finally {
175 +            if (interrupted) Thread.currentThread().interrupt();
176 +        }
177 +    }
178 +
179 +    /**
180 +     * Returns the exception thrown by the task, without waiting.
181 +     *
182 +     * <p> This method is for cases where the caller knows that the task
183 +     * has already completed with an exception.
184 +     *
185 +     * @implSpec
186 +     * The default implementation invokes {@code isDone()} to test if the task
187 +     * has completed. If done and not cancelled, it invokes {@code get()} and
188 +     * catches the {@code ExecutionException} to obtain the exception.
189 +     *
190 +     * @return the exception thrown by the task
191 +     * @throws IllegalStateException if the task has not completed, the task
192 +     * completed normally, or the task was cancelled
193 +     * @since 99
194 +     */
195 +    default Throwable exceptionNow() {
196 +        if (!isDone())
197 +            throw new IllegalStateException("Task has not completed");
198 +        if (isCancelled())
199 +            throw new IllegalStateException("Task was cancelled");
200 +        boolean interrupted = false;
201 +        try {
202 +            while (true) {
203 +                try {
204 +                    get();
205 +                    throw new IllegalStateException("Task completed with a result");
206 +                } catch (InterruptedException e) {
207 +                    interrupted = true;
208 +                } catch (ExecutionException e) {
209 +                    return e.getCause();
210 +                }
211 +            }
212 +        } finally {
213 +            if (interrupted) Thread.currentThread().interrupt();
214 +        }
215 +    }
216 +
217 +    /**
218 +     * Represents the computation state.
219 +     * @since 99
220 +     */
221 +    enum State {
222 +        /**
223 +         * The task has not completed.
224 +         */
225 +        RUNNING,
226 +        /**
227 +         * The task completed with a result.
228 +         * @see Future#resultNow()
229 +         */
230 +        SUCCESS,
231 +        /**
232 +         * The task completed with an exception.
233 +         * @see Future#exceptionNow()
234 +         */
235 +        FAILED,
236 +        /**
237 +         * The task was cancelled.
238 +         * @see #cancel(boolean)
239 +         */
240 +        CANCELLED
241 +    }
242 +
243 +    /**
244 +     * {@return the computation state}
245 +     *
246 +     * @implSpec
247 +     * The default implementation uses {@code isDone()}, {@code isCancelled()},
248 +     * and {@code get()} to determine the state.
249 +     *
250 +     * @since 99
251 +     */
252 +    default State state() {
253 +        if (!isDone())
254 +            return State.RUNNING;
255 +        if (isCancelled())
256 +            return State.CANCELLED;
257 +        boolean interrupted = false;
258 +        try {
259 +            while (true) {
260 +                try {
261 +                    get();  // may throw InterruptedException when done
262 +                    return State.SUCCESS;
263 +                } catch (InterruptedException e) {
264 +                    interrupted = true;
265 +                } catch (ExecutionException e) {
266 +                    return State.FAILED;
267 +                }
268 +            }
269 +        } finally {
270 +            if (interrupted) Thread.currentThread().interrupt();
271 +        }
272 +    }
273   }
274 +

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines