1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.common.support;
21
22 import java.util.ArrayList;
23 import java.util.List;
24
25 import org.apache.mina.common.ExceptionMonitor;
26 import org.apache.mina.common.IoFuture;
27 import org.apache.mina.common.IoFutureListener;
28 import org.apache.mina.common.IoSession;
29
30
31
32
33
34
35
36 public class DefaultIoFuture implements IoFuture {
37
38 private final IoSession session;
39 private final Object lock;
40 private IoFutureListener firstListener;
41 private List<IoFutureListener> otherListeners;
42 private Object result;
43 private boolean ready;
44 private int waiters;
45
46
47
48
49
50
51 public DefaultIoFuture(IoSession session) {
52 this.session = session;
53 this.lock = this;
54 }
55
56
57
58
59
60
61 public DefaultIoFuture(IoSession session, Object lock) {
62 this.session = session;
63 this.lock = lock;
64 }
65
66 public IoSession getSession() {
67 return session;
68 }
69
70 public Object getLock() {
71 return lock;
72 }
73
74 public void join() {
75 awaitUninterruptibly();
76 }
77
78 public boolean join(long timeoutMillis) {
79 return awaitUninterruptibly(timeoutMillis);
80 }
81
82 private IoFuture awaitUninterruptibly() {
83 synchronized (lock) {
84 while (!ready) {
85 waiters++;
86 try {
87 lock.wait();
88 } catch (InterruptedException e) {
89 } finally {
90 waiters--;
91 }
92 }
93 }
94
95 return this;
96 }
97
98 private boolean awaitUninterruptibly(long timeoutMillis) {
99 try {
100 return await0(timeoutMillis, false);
101 } catch (InterruptedException e) {
102 throw new InternalError();
103 }
104 }
105
106 private boolean await0(long timeoutMillis, boolean interruptable) throws InterruptedException {
107 long startTime = timeoutMillis <= 0 ? 0 : System.currentTimeMillis();
108 long waitTime = timeoutMillis;
109
110 synchronized (lock) {
111 if (ready) {
112 return ready;
113 } else if (waitTime <= 0) {
114 return ready;
115 }
116
117 waiters++;
118 try {
119 for (;;) {
120 try {
121 lock.wait(waitTime);
122 } catch (InterruptedException e) {
123 if (interruptable) {
124 throw e;
125 }
126 }
127
128 if (ready) {
129 return true;
130 } else {
131 waitTime = timeoutMillis
132 - (System.currentTimeMillis() - startTime);
133 if (waitTime <= 0) {
134 return ready;
135 }
136 }
137 }
138 } finally {
139 waiters--;
140 }
141 }
142 }
143
144 public boolean isReady() {
145 synchronized (lock) {
146 return ready;
147 }
148 }
149
150
151
152
153 protected void setValue(Object newValue) {
154 synchronized (lock) {
155
156 if (ready) {
157 return;
158 }
159
160 result = newValue;
161 ready = true;
162 if (waiters > 0) {
163 lock.notifyAll();
164 }
165 }
166
167 notifyListeners();
168 }
169
170
171
172
173 protected Object getValue() {
174 synchronized (lock) {
175 return result;
176 }
177 }
178
179 public void addListener(IoFutureListener listener) {
180 if (listener == null) {
181 throw new NullPointerException("listener");
182 }
183
184 boolean notifyNow = false;
185 synchronized (lock) {
186 if (ready) {
187 notifyNow = true;
188 } else {
189 if (firstListener == null) {
190 firstListener = listener;
191 } else {
192 if (otherListeners == null) {
193 otherListeners = new ArrayList<IoFutureListener>(1);
194 }
195 otherListeners.add(listener);
196 }
197 }
198 }
199
200 if (notifyNow) {
201 notifyListener(listener);
202 }
203 }
204
205 public void removeListener(IoFutureListener listener) {
206 if (listener == null) {
207 throw new NullPointerException("listener");
208 }
209
210 synchronized (lock) {
211 if (!ready) {
212 if (listener == firstListener) {
213 if (otherListeners != null && !otherListeners.isEmpty()) {
214 firstListener = otherListeners.remove(0);
215 } else {
216 firstListener = null;
217 }
218 } else if (otherListeners != null) {
219 otherListeners.remove(listener);
220 }
221 }
222 }
223 }
224
225 private void notifyListeners() {
226
227
228
229 if (firstListener != null) {
230 notifyListener(firstListener);
231 firstListener = null;
232
233 if (otherListeners != null) {
234 for (IoFutureListener l : otherListeners) {
235 notifyListener(l);
236 }
237 otherListeners = null;
238 }
239 }
240 }
241
242 @SuppressWarnings("unchecked")
243 private void notifyListener(IoFutureListener l) {
244 try {
245 l.operationComplete(this);
246 } catch (Throwable t) {
247 ExceptionMonitor.getInstance().exceptionCaught(t);
248 }
249 }
250 }