1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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 }