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 org.apache.http.util.Args;
30  
31  import java.util.concurrent.ExecutionException;
32  import java.util.concurrent.Future;
33  import java.util.concurrent.TimeUnit;
34  import java.util.concurrent.TimeoutException;
35  
36  /**
37   * Basic implementation of the {@link Future} interface. <tt>BasicFuture<tt>
38   * can be put into a completed state by invoking any of the following methods:
39   * {@link #cancel()}, {@link #failed(Exception)}, or {@link #completed(Object)}.
40   *
41   * @param <T> the future result type of an asynchronous operation.
42   * @since 4.2
43   */
44  public class BasicFuture<T> implements Future<T>, Cancellable {
45  
46      private final FutureCallback<T> callback;
47  
48      private volatile boolean completed;
49      private volatile boolean cancelled;
50      private volatile T result;
51      private volatile Exception ex;
52  
53      public BasicFuture(final FutureCallback<T> callback) {
54          super();
55          this.callback = callback;
56      }
57  
58      @Override
59      public boolean isCancelled() {
60          return this.cancelled;
61      }
62  
63      @Override
64      public boolean isDone() {
65          return this.completed;
66      }
67  
68      private T getResult() throws ExecutionException {
69          if (this.ex != null) {
70              throw new ExecutionException(this.ex);
71          }
72          return this.result;
73      }
74  
75      @Override
76      public synchronized T get() throws InterruptedException, ExecutionException {
77          while (!this.completed) {
78              wait();
79          }
80          return getResult();
81      }
82  
83      @Override
84      public synchronized T get(final long timeout, final TimeUnit unit)
85              throws InterruptedException, ExecutionException, TimeoutException {
86          Args.notNull(unit, "Time unit");
87          final long msecs = unit.toMillis(timeout);
88          final long startTime = (msecs <= 0) ? 0 : System.currentTimeMillis();
89          long waitTime = msecs;
90          if (this.completed) {
91              return getResult();
92          } else if (waitTime <= 0) {
93              throw new TimeoutException();
94          } else {
95              for (;;) {
96                  wait(waitTime);
97                  if (this.completed) {
98                      return getResult();
99                  } else {
100                     waitTime = msecs - (System.currentTimeMillis() - startTime);
101                     if (waitTime <= 0) {
102                         throw new TimeoutException();
103                     }
104                 }
105             }
106         }
107     }
108 
109     public boolean completed(final T result) {
110         synchronized(this) {
111             if (this.completed) {
112                 return false;
113             }
114             this.completed = true;
115             this.result = result;
116             notifyAll();
117         }
118         if (this.callback != null) {
119             this.callback.completed(result);
120         }
121         return true;
122     }
123 
124     public boolean failed(final Exception exception) {
125         synchronized(this) {
126             if (this.completed) {
127                 return false;
128             }
129             this.completed = true;
130             this.ex = exception;
131             notifyAll();
132         }
133         if (this.callback != null) {
134             this.callback.failed(exception);
135         }
136         return true;
137     }
138 
139     @Override
140     public boolean cancel(final boolean mayInterruptIfRunning) {
141         synchronized(this) {
142             if (this.completed) {
143                 return false;
144             }
145             this.completed = true;
146             this.cancelled = true;
147             notifyAll();
148         }
149         if (this.callback != null) {
150             this.callback.cancelled();
151         }
152         return true;
153     }
154 
155     @Override
156     public boolean cancel() {
157         return cancel(true);
158     }
159 
160 }