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      public boolean cancel(final boolean mayInterruptIfRunning) {
60          this.lock.lock();
61          try {
62              if (this.completed) {
63                  return false;
64              }
65              this.completed = true;
66              this.cancelled = true;
67              if (this.callback != null) {
68                  this.callback.cancelled();
69              }
70              this.condition.signalAll();
71              return true;
72          } finally {
73              this.lock.unlock();
74          }
75      }
76  
77      public boolean isCancelled() {
78          return this.cancelled;
79      }
80  
81      public boolean isDone() {
82          return this.completed;
83      }
84  
85      public T get() throws InterruptedException, ExecutionException {
86          try {
87              return get(0, TimeUnit.MILLISECONDS);
88          } catch (final TimeoutException ex) {
89              throw new ExecutionException(ex);
90          }
91      }
92  
93      public T get(
94              final long timeout,
95              final TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
96          Args.notNull(unit, "Time unit");
97          this.lock.lock();
98          try {
99              if (this.completed) {
100                 return this.result;
101             }
102             this.result = getPoolEntry(timeout, unit);
103             this.completed = true;
104             if (this.callback != null) {
105                 this.callback.completed(this.result);
106             }
107             return result;
108         } catch (final IOException ex) {
109             this.completed = true;
110             this.result = null;
111             if (this.callback != null) {
112                 this.callback.failed(ex);
113             }
114             throw new ExecutionException(ex);
115         } finally {
116             this.lock.unlock();
117         }
118     }
119 
120     protected abstract T getPoolEntry(
121             long timeout, TimeUnit unit) throws IOException, InterruptedException, TimeoutException;
122 
123     public boolean await(final Date deadline) throws InterruptedException {
124         this.lock.lock();
125         try {
126             if (this.cancelled) {
127                 throw new InterruptedException("Operation interrupted");
128             }
129             final boolean success;
130             if (deadline != null) {
131                 success = this.condition.awaitUntil(deadline);
132             } else {
133                 this.condition.await();
134                 success = true;
135             }
136             if (this.cancelled) {
137                 throw new InterruptedException("Operation interrupted");
138             }
139             return success;
140         } finally {
141             this.lock.unlock();
142         }
143 
144     }
145 
146     public void wakeup() {
147         this.lock.lock();
148         try {
149             this.condition.signalAll();
150         } finally {
151             this.lock.unlock();
152         }
153     }
154 
155 }