View Javadoc

1   /*
2    * ====================================================================
3    *
4    *  Licensed to the Apache Software Foundation (ASF) under one or more
5    *  contributor license agreements.  See the NOTICE file distributed with
6    *  this work for additional information regarding copyright ownership.
7    *  The ASF licenses this file to You under the Apache License, Version 2.0
8    *  (the "License"); you may not use this file except in compliance with
9    *  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, software
14   *  distributed under the License is distributed on an "AS IS" BASIS,
15   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   *  See the License for the specific language governing permissions and
17   *  limitations under the License.
18   * ====================================================================
19   *
20   * This software consists of voluntary contributions made by many
21   * individuals on behalf of the Apache Software Foundation.  For more
22   * information on the Apache Software Foundation, please see
23   * <http://www.apache.org/>.
24   *
25   */
26  
27  package org.apache.http.pool;
28  
29  import java.io.IOException;
30  import java.util.Date;
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  import java.util.concurrent.locks.Condition;
36  import java.util.concurrent.locks.Lock;
37  
38  import org.apache.http.annotation.ThreadSafe;
39  import org.apache.http.concurrent.FutureCallback;
40  
41  @ThreadSafe
42  abstract class PoolEntryFuture<T> implements Future<T> {
43  
44      private final Lock lock;
45      private final FutureCallback<T> callback;
46      private final Condition condition;
47      private volatile boolean cancelled;
48      private volatile boolean completed;
49      private T result;
50  
51      PoolEntryFuture(final Lock lock, final FutureCallback<T> callback) {
52          super();
53          this.lock = lock;
54          this.condition = lock.newCondition();
55          this.callback = callback;
56      }
57  
58      public boolean cancel(boolean mayInterruptIfRunning) {
59          this.lock.lock();
60          try {
61              if (this.completed) {
62                  return false;
63              }
64              this.completed = true;
65              this.cancelled = true;
66              if (this.callback != null) {
67                  this.callback.cancelled();
68              }
69              this.condition.signalAll();
70              return true;
71          } finally {
72              this.lock.unlock();
73          }
74      }
75  
76      public boolean isCancelled() {
77          return this.cancelled;
78      }
79  
80      public boolean isDone() {
81          return this.completed;
82      }
83  
84      public T get() throws InterruptedException, ExecutionException {
85          try {
86              return get(0, TimeUnit.MILLISECONDS);
87          } catch (TimeoutException ex) {
88              throw new ExecutionException(ex);
89          }
90      }
91  
92      public T get(
93              long timeout,
94              final TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
95          this.lock.lock();
96          try {
97              if (this.completed) {
98                  return this.result;
99              }
100             this.result = getPoolEntry(timeout, unit);
101             this.completed = true;
102             if (this.callback != null) {
103                 this.callback.completed(this.result);
104             }
105             return result;
106         } catch (IOException ex) {
107             this.completed = true;
108             this.result = null;
109             if (this.callback != null) {
110                 this.callback.failed(ex);
111             }
112             throw new ExecutionException(ex);
113         } finally {
114             this.lock.unlock();
115         }
116     }
117 
118     protected abstract T getPoolEntry(
119             long timeout, TimeUnit unit) throws IOException, InterruptedException, TimeoutException;
120 
121     public boolean await(final Date deadline) throws InterruptedException {
122         this.lock.lock();
123         try {
124             if (this.cancelled) {
125                 throw new InterruptedException("Operation interrupted");
126             }
127             boolean success = false;
128             if (deadline != null) {
129                 success = this.condition.awaitUntil(deadline);
130             } else {
131                 this.condition.await();
132                 success = true;
133             }
134             if (this.cancelled) {
135                 throw new InterruptedException("Operation interrupted");
136             }
137             return success;
138         } finally {
139             this.lock.unlock();
140         }
141 
142     }
143 
144     public void wakeup() {
145         this.lock.lock();
146         try {
147             this.condition.signalAll();
148         } finally {
149             this.lock.unlock();
150         }
151     }
152 
153 }