View Javadoc

1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  package org.apache.http.concurrent;
28  
29  import java.util.concurrent.ExecutionException;
30  import java.util.concurrent.Future;
31  import java.util.concurrent.TimeUnit;
32  import java.util.concurrent.TimeoutException;
33  
34  /**
35   * Basic implementation of the {@link Future} interface. <tt>BasicFuture<tt>
36   * can be put into a completed state by invoking any of the following methods:
37   * {@link #cancel()}, {@link #failed(Exception)}, or {@link #completed(Object)}.
38   *
39   * @param <T> the future result type of an asynchronous operation.
40   * @since 4.2
41   */
42  public class BasicFuture<T> implements Future<T>, Cancellable {
43  
44      private final FutureCallback<T> callback;
45  
46      private volatile boolean completed;
47      private volatile boolean cancelled;
48      private volatile T result;
49      private volatile Exception ex;
50  
51      public BasicFuture(final FutureCallback<T> callback) {
52          super();
53          this.callback = callback;
54      }
55  
56      public boolean isCancelled() {
57          return this.cancelled;
58      }
59  
60      public boolean isDone() {
61          return this.completed;
62      }
63  
64      private T getResult() throws ExecutionException {
65          if (this.ex != null) {
66              throw new ExecutionException(this.ex);
67          }
68          return this.result;
69      }
70  
71      public synchronized T get() throws InterruptedException, ExecutionException {
72          while (!this.completed) {
73              wait();
74          }
75          return getResult();
76      }
77  
78      public synchronized T get(long timeout, final TimeUnit unit)
79              throws InterruptedException, ExecutionException, TimeoutException {
80          long msecs = unit.toMillis(timeout);
81          long startTime = (msecs <= 0) ? 0 : System.currentTimeMillis();
82          long waitTime = msecs;
83          if (this.completed) {
84              return getResult();
85          } else if (waitTime <= 0) {
86              throw new TimeoutException();
87          } else {
88              for (;;) {
89                  wait(waitTime);
90                  if (this.completed) {
91                      return getResult();
92                  } else {
93                      waitTime = msecs - (System.currentTimeMillis() - startTime);
94                      if (waitTime <= 0) {
95                          throw new TimeoutException();
96                      }
97                  }
98              }
99          }
100     }
101 
102     public boolean completed(final T result) {
103         synchronized(this) {
104             if (this.completed) {
105                 return false;
106             }
107             this.completed = true;
108             this.result = result;
109             notifyAll();
110         }
111         if (this.callback != null) {
112             this.callback.completed(result);
113         }
114         return true;
115     }
116 
117     public boolean failed(final Exception exception) {
118         synchronized(this) {
119             if (this.completed) {
120                 return false;
121             }
122             this.completed = true;
123             this.ex = exception;
124             notifyAll();
125         }
126         if (this.callback != null) {
127             this.callback.failed(exception);
128         }
129         return true;
130     }
131 
132     public boolean cancel(boolean mayInterruptIfRunning) {
133         synchronized(this) {
134             if (this.completed) {
135                 return false;
136             }
137             this.completed = true;
138             this.cancelled = true;
139             notifyAll();
140         }
141         if (this.callback != null) {
142             this.callback.cancelled();
143         }
144         return true;
145     }
146 
147     public boolean cancel() {
148         return cancel(true);
149     }
150 
151 }