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      public boolean isCancelled() {
59          return this.cancelled;
60      }
61  
62      public boolean isDone() {
63          return this.completed;
64      }
65  
66      private T getResult() throws ExecutionException {
67          if (this.ex != null) {
68              throw new ExecutionException(this.ex);
69          }
70          return this.result;
71      }
72  
73      public synchronized T get() throws InterruptedException, ExecutionException {
74          while (!this.completed) {
75              wait();
76          }
77          return getResult();
78      }
79  
80      public synchronized T get(final long timeout, final TimeUnit unit)
81              throws InterruptedException, ExecutionException, TimeoutException {
82          Args.notNull(unit, "Time unit");
83          final long msecs = unit.toMillis(timeout);
84          final long startTime = (msecs <= 0) ? 0 : System.currentTimeMillis();
85          long waitTime = msecs;
86          if (this.completed) {
87              return getResult();
88          } else if (waitTime <= 0) {
89              throw new TimeoutException();
90          } else {
91              for (;;) {
92                  wait(waitTime);
93                  if (this.completed) {
94                      return getResult();
95                  } else {
96                      waitTime = msecs - (System.currentTimeMillis() - startTime);
97                      if (waitTime <= 0) {
98                          throw new TimeoutException();
99                      }
100                 }
101             }
102         }
103     }
104 
105     public boolean completed(final T result) {
106         synchronized(this) {
107             if (this.completed) {
108                 return false;
109             }
110             this.completed = true;
111             this.result = result;
112             notifyAll();
113         }
114         if (this.callback != null) {
115             this.callback.completed(result);
116         }
117         return true;
118     }
119 
120     public boolean failed(final Exception exception) {
121         synchronized(this) {
122             if (this.completed) {
123                 return false;
124             }
125             this.completed = true;
126             this.ex = exception;
127             notifyAll();
128         }
129         if (this.callback != null) {
130             this.callback.failed(exception);
131         }
132         return true;
133     }
134 
135     public boolean cancel(final boolean mayInterruptIfRunning) {
136         synchronized(this) {
137             if (this.completed) {
138                 return false;
139             }
140             this.completed = true;
141             this.cancelled = true;
142             notifyAll();
143         }
144         if (this.callback != null) {
145             this.callback.cancelled();
146         }
147         return true;
148     }
149 
150     public boolean cancel() {
151         return cancel(true);
152     }
153 
154 }