Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/nio/ch/PendingFuture.java
38918 views
/*1* Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.nio.ch;2627import java.nio.channels.*;28import java.util.concurrent.*;29import java.io.IOException;3031/**32* A Future for a pending I/O operation. A PendingFuture allows for the33* attachment of an additional arbitrary context object and a timer task.34*/3536final class PendingFuture<V,A> implements Future<V> {37private static final CancellationException CANCELLED =38new CancellationException();3940private final AsynchronousChannel channel;41private final CompletionHandler<V,? super A> handler;42private final A attachment;4344// true if result (or exception) is available45private volatile boolean haveResult;46private volatile V result;47private volatile Throwable exc;4849// latch for waiting (created lazily if needed)50private CountDownLatch latch;5152// optional timer task that is cancelled when result becomes available53private Future<?> timeoutTask;5455// optional context object56private volatile Object context;5758PendingFuture(AsynchronousChannel channel,59CompletionHandler<V,? super A> handler,60A attachment,61Object context)62{63this.channel = channel;64this.handler = handler;65this.attachment = attachment;66this.context = context;67}6869PendingFuture(AsynchronousChannel channel,70CompletionHandler<V,? super A> handler,71A attachment)72{73this.channel = channel;74this.handler = handler;75this.attachment = attachment;76}7778PendingFuture(AsynchronousChannel channel) {79this(channel, null, null);80}8182PendingFuture(AsynchronousChannel channel, Object context) {83this(channel, null, null, context);84}8586AsynchronousChannel channel() {87return channel;88}8990CompletionHandler<V,? super A> handler() {91return handler;92}9394A attachment() {95return attachment;96}9798void setContext(Object context) {99this.context = context;100}101102Object getContext() {103return context;104}105106void setTimeoutTask(Future<?> task) {107synchronized (this) {108if (haveResult) {109task.cancel(false);110} else {111this.timeoutTask = task;112}113}114}115116// creates latch if required; return true if caller needs to wait117private boolean prepareForWait() {118synchronized (this) {119if (haveResult) {120return false;121} else {122if (latch == null)123latch = new CountDownLatch(1);124return true;125}126}127}128129/**130* Sets the result, or a no-op if the result or exception is already set.131*/132void setResult(V res) {133synchronized (this) {134if (haveResult)135return;136result = res;137haveResult = true;138if (timeoutTask != null)139timeoutTask.cancel(false);140if (latch != null)141latch.countDown();142}143}144145/**146* Sets the result, or a no-op if the result or exception is already set.147*/148void setFailure(Throwable x) {149if (!(x instanceof IOException) && !(x instanceof SecurityException))150x = new IOException(x);151synchronized (this) {152if (haveResult)153return;154exc = x;155haveResult = true;156if (timeoutTask != null)157timeoutTask.cancel(false);158if (latch != null)159latch.countDown();160}161}162163/**164* Sets the result165*/166void setResult(V res, Throwable x) {167if (x == null) {168setResult(res);169} else {170setFailure(x);171}172}173174@Override175public V get() throws ExecutionException, InterruptedException {176if (!haveResult) {177boolean needToWait = prepareForWait();178if (needToWait)179latch.await();180}181if (exc != null) {182if (exc == CANCELLED)183throw new CancellationException();184throw new ExecutionException(exc);185}186return result;187}188189@Override190public V get(long timeout, TimeUnit unit)191throws ExecutionException, InterruptedException, TimeoutException192{193if (!haveResult) {194boolean needToWait = prepareForWait();195if (needToWait)196if (!latch.await(timeout, unit)) throw new TimeoutException();197}198if (exc != null) {199if (exc == CANCELLED)200throw new CancellationException();201throw new ExecutionException(exc);202}203return result;204}205206Throwable exception() {207return (exc != CANCELLED) ? exc : null;208}209210V value() {211return result;212}213214@Override215public boolean isCancelled() {216return (exc == CANCELLED);217}218219@Override220public boolean isDone() {221return haveResult;222}223224@Override225public boolean cancel(boolean mayInterruptIfRunning) {226synchronized (this) {227if (haveResult)228return false; // already completed229230// notify channel231if (channel() instanceof Cancellable)232((Cancellable)channel()).onCancel(this);233234// set result and cancel timer235exc = CANCELLED;236haveResult = true;237if (timeoutTask != null)238timeoutTask.cancel(false);239}240241// close channel if forceful cancel242if (mayInterruptIfRunning) {243try {244channel().close();245} catch (IOException ignore) { }246}247248// release waiters249if (latch != null)250latch.countDown();251return true;252}253}254255256