1e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera/*
2e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
3e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera *
5e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * This code is free software; you can redistribute it and/or modify it
6e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * under the terms of the GNU General Public License version 2 only, as
7e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * published by the Free Software Foundation.  Oracle designates this
8e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * particular file as subject to the "Classpath" exception as provided
9e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * by Oracle in the LICENSE file that accompanied this code.
10e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera *
11e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * This code is distributed in the hope that it will be useful, but WITHOUT
12e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * version 2 for more details (a copy is included in the LICENSE file that
15e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * accompanied this code).
16e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera *
17e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * You should have received a copy of the GNU General Public License version
18e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * 2 along with this work; if not, write to the Free Software Foundation,
19e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera *
21e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * or visit www.oracle.com if you need additional information or have any
23e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * questions.
24e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera */
25e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
26e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmerapackage sun.nio.ch;
27e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
28e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmeraimport java.nio.channels.*;
29e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmeraimport java.util.concurrent.*;
30e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmeraimport java.io.IOException;
31e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
32e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera/**
33e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * A Future for a pending I/O operation. A PendingFuture allows for the
34e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera * attachment of an additional arbitrary context object and a timer task.
35e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera */
36e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
37e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmerafinal class PendingFuture<V,A> implements Future<V> {
38e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private static final CancellationException CANCELLED =
39e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        new CancellationException();
40e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
41e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private final AsynchronousChannel channel;
42e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private final CompletionHandler<V,? super A> handler;
43e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private final A attachment;
44e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
45e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    // true if result (or exception) is available
46e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private volatile boolean haveResult;
47e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private volatile V result;
48e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private volatile Throwable exc;
49e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
50e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    // latch for waiting (created lazily if needed)
51e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private CountDownLatch latch;
52e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
53e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    // optional timer task that is cancelled when result becomes available
54e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private Future<?> timeoutTask;
55e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
56e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    // optional context object
57e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private volatile Object context;
58e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
59e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    PendingFuture(AsynchronousChannel channel,
60e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                  CompletionHandler<V,? super A> handler,
61e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                  A attachment,
62e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                  Object context)
63e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    {
64e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        this.channel = channel;
65e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        this.handler = handler;
66e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        this.attachment = attachment;
67e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        this.context = context;
68e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
69e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
70e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    PendingFuture(AsynchronousChannel channel,
71e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                  CompletionHandler<V,? super A> handler,
72e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                  A attachment)
73e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    {
74e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        this.channel = channel;
75e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        this.handler = handler;
76e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        this.attachment = attachment;
77e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
78e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
79e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    PendingFuture(AsynchronousChannel channel) {
80e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        this(channel, null, null);
81e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
82e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
83e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    PendingFuture(AsynchronousChannel channel, Object context) {
84e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        this(channel, null, null, context);
85e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
86e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
87e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    AsynchronousChannel channel() {
88e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        return channel;
89e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
90e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
91e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    CompletionHandler<V,? super A> handler() {
92e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        return handler;
93e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
94e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
95e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    A attachment() {
96e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        return attachment;
97e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
98e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
99e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    void setContext(Object context) {
100e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        this.context = context;
101e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
102e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
103e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    Object getContext() {
104e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        return context;
105e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
106e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
107e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    void setTimeoutTask(Future<?> task) {
108e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        synchronized (this) {
109e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (haveResult) {
110e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                task.cancel(false);
111e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            } else {
112e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                this.timeoutTask = task;
113e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            }
114e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
115e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
116e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
117e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    // creates latch if required; return true if caller needs to wait
118e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    private boolean prepareForWait() {
119e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        synchronized (this) {
120e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (haveResult) {
121e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                return false;
122e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            } else {
123e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                if (latch == null)
124e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                    latch = new CountDownLatch(1);
125e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                return true;
126e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            }
127e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
128e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
129e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
130e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    /**
131e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera     * Sets the result, or a no-op if the result or exception is already set.
132e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera     */
133e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    void setResult(V res) {
134e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        synchronized (this) {
135e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (haveResult)
136e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                return;
137e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            result = res;
138e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            haveResult = true;
139e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (timeoutTask != null)
140e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                timeoutTask.cancel(false);
141e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (latch != null)
142e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                latch.countDown();
143e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
144e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
145e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
146e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    /**
147e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera     * Sets the result, or a no-op if the result or exception is already set.
148e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera     */
149e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    void setFailure(Throwable x) {
150e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (!(x instanceof IOException) && !(x instanceof SecurityException))
151e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            x = new IOException(x);
152e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        synchronized (this) {
153e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (haveResult)
154e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                return;
155e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            exc = x;
156e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            haveResult = true;
157e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (timeoutTask != null)
158e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                timeoutTask.cancel(false);
159e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (latch != null)
160e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                latch.countDown();
161e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
162e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
163e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
164e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    /**
165e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera     * Sets the result
166e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera     */
167e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    void setResult(V res, Throwable x) {
168e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (x == null) {
169e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            setResult(res);
170e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        } else {
171e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            setFailure(x);
172e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
173e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
174e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
175e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
176e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    public V get() throws ExecutionException, InterruptedException {
177e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (!haveResult) {
178e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            boolean needToWait = prepareForWait();
179e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (needToWait)
180e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                latch.await();
181e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
182e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (exc != null) {
183e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (exc == CANCELLED)
184e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                throw new CancellationException();
185e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            throw new ExecutionException(exc);
186e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
187e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        return result;
188e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
189e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
190e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
191e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    public V get(long timeout, TimeUnit unit)
192e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        throws ExecutionException, InterruptedException, TimeoutException
193e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    {
194e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (!haveResult) {
195e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            boolean needToWait = prepareForWait();
196e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (needToWait)
197e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                if (!latch.await(timeout, unit)) throw new TimeoutException();
198e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
199e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (exc != null) {
200e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (exc == CANCELLED)
201e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                throw new CancellationException();
202e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            throw new ExecutionException(exc);
203e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
204e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        return result;
205e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
206e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
207e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    Throwable exception() {
208e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        return (exc != CANCELLED) ? exc : null;
209e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
210e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
211e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    V value() {
212e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        return result;
213e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
214e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
215e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
216e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    public boolean isCancelled() {
217e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        return (exc == CANCELLED);
218e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
219e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
220e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
221e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    public boolean isDone() {
222e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        return haveResult;
223e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
224e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
225e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    @Override
226e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    public boolean cancel(boolean mayInterruptIfRunning) {
227e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        synchronized (this) {
228e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (haveResult)
229e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                return false;    // already completed
230e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
231e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            // notify channel
232e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (channel() instanceof Cancellable)
233e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                ((Cancellable)channel()).onCancel(this);
234e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
235e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            // set result and cancel timer
236e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            exc = CANCELLED;
237e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            haveResult = true;
238e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            if (timeoutTask != null)
239e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                timeoutTask.cancel(false);
240e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
241e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
242e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        // close channel if forceful cancel
243e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (mayInterruptIfRunning) {
244e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            try {
245e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera                channel().close();
246e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            } catch (IOException ignore) { }
247e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        }
248e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera
249e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        // release waiters
250e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        if (latch != null)
251e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera            latch.countDown();
252e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera        return true;
253e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera    }
254e318a0eaa02b186f9f135016e95a6282fe9a83cbShubham Ajmera}
255