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