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.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  import org.apache.http.util.Args;
41  
42  @ThreadSafe
43  abstract class PoolEntryFuture<T> implements Future<T> {
44  
45      private final Lock lock;
46      private final FutureCallback<T> callback;
47      private final Condition condition;
48      private volatile boolean cancelled;
49      private volatile boolean completed;
50      private T result;
51  
52      PoolEntryFuture(final Lock lock, final FutureCallback<T> callback) {
53          super();
54          this.lock = lock;
55          this.condition = lock.newCondition();
56          this.callback = callback;
57      }
58  
59      @Override
60      public boolean cancel(final boolean mayInterruptIfRunning) {
61          this.lock.lock();
62          try {
63              if (this.completed) {
64                  return false;
65              }
66              this.completed = true;
67              this.cancelled = true;
68              if (this.callback != null) {
69                  this.callback.cancelled();
70              }
71              this.condition.signalAll();
72              return true;
73          } finally {
74              this.lock.unlock();
75          }
76      }
77  
78      @Override
79      public boolean isCancelled() {
80          return this.cancelled;
81      }
82  
83      @Override
84      public boolean isDone() {
85          return this.completed;
86      }
87  
88      @Override
89      public T get() throws InterruptedException, ExecutionException {
90          try {
91              return get(0, TimeUnit.MILLISECONDS);
92          } catch (final TimeoutException ex) {
93              throw new ExecutionException(ex);
94          }
95      }
96  
97      @Override
98      public T get(
99              final long timeout,
100             final TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
101         Args.notNull(unit, "Time unit");
102         this.lock.lock();
103         try {
104             if (this.completed) {
105                 return this.result;
106             }
107             this.result = getPoolEntry(timeout, unit);
108             this.completed = true;
109             if (this.callback != null) {
110                 this.callback.completed(this.result);
111             }
112             return result;
113         } catch (final IOException ex) {
114             this.completed = true;
115             this.result = null;
116             if (this.callback != null) {
117                 this.callback.failed(ex);
118             }
119             throw new ExecutionException(ex);
120         } finally {
121             this.lock.unlock();
122         }
123     }
124 
125     protected abstract T getPoolEntry(
126             long timeout, TimeUnit unit) throws IOException, InterruptedException, TimeoutException;
127 
128     public boolean await(final Date deadline) throws InterruptedException {
129         this.lock.lock();
130         try {
131             if (this.cancelled) {
132                 throw new InterruptedException("Operation interrupted");
133             }
134             final boolean success;
135             if (deadline != null) {
136                 success = this.condition.awaitUntil(deadline);
137             } else {
138                 this.condition.await();
139                 success = true;
140             }
141             if (this.cancelled) {
142                 throw new InterruptedException("Operation interrupted");
143             }
144             return success;
145         } finally {
146             this.lock.unlock();
147         }
148 
149     }
150 
151     public void wakeup() {
152         this.lock.lock();
153         try {
154             this.condition.signalAll();
155         } finally {
156             this.lock.unlock();
157         }
158     }
159 
160 }