View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
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   * A default implementation of {@link IoFuture}.
32   *  
33   * @author The Apache MINA Project (dev@mina.apache.org)
34   * @version $Rev: 561238 $, $Date: 2007-07-31 15:12:43 +0900 (Tue, 31 Jul 2007) $
35   */
36  public class DefaultIoFuture implements IoFuture {
37      private final IoSession session;
38  
39      private final Object lock;
40  
41      private IoFutureListener firstListener;
42  
43      private List<IoFutureListener> otherListeners;
44  
45      private Object result;
46  
47      private boolean ready;
48  
49      /**
50       * Creates a new instance.
51       * 
52       * @param session an {@link IoSession} which is associated with this future
53       */
54      public DefaultIoFuture(IoSession session) {
55          this.session = session;
56          this.lock = this;
57      }
58  
59      public IoSession getSession() {
60          return session;
61      }
62  
63      public void join() {
64          synchronized (lock) {
65              while (!ready) {
66                  try {
67                      lock.wait();
68                  } catch (InterruptedException e) {
69                  }
70              }
71          }
72      }
73  
74      public boolean join(long timeoutMillis) {
75          long startTime = (timeoutMillis <= 0) ? 0 : System.currentTimeMillis();
76          long waitTime = timeoutMillis;
77  
78          synchronized (lock) {
79              if (ready) {
80                  return ready;
81              } else if (waitTime <= 0) {
82                  return ready;
83              }
84  
85              for (;;) {
86                  try {
87                      lock.wait(waitTime);
88                  } catch (InterruptedException e) {
89                  }
90  
91                  if (ready) {
92                      return true;
93                  } else {
94                      waitTime = timeoutMillis
95                              - (System.currentTimeMillis() - startTime);
96                      if (waitTime <= 0) {
97                          return ready;
98                      }
99                  }
100             }
101         }
102     }
103 
104     public boolean isReady() {
105         synchronized (lock) {
106             return ready;
107         }
108     }
109 
110     /**
111      * Sets the result of the asynchronous operation, and mark it as finished.
112      */
113     protected void setValue(Object newValue) {
114         synchronized (lock) {
115             // Allow only once.
116             if (ready) {
117                 return;
118             }
119 
120             result = newValue;
121             ready = true;
122             lock.notifyAll();
123 
124             notifyListeners();
125         }
126     }
127 
128     /**
129      * Returns the result of the asynchronous operation.
130      */
131     protected Object getValue() {
132         synchronized (lock) {
133             return result;
134         }
135     }
136 
137     public void addListener(IoFutureListener listener) {
138         if (listener == null) {
139             throw new NullPointerException("listener");
140         }
141 
142         synchronized (lock) {
143             if (!ready) {
144                 if (firstListener == null) {
145                     firstListener = listener;
146                 } else {
147                     if (otherListeners == null) {
148                         otherListeners = new ArrayList<IoFutureListener>(1);
149                     }
150                     otherListeners.add(listener);
151                 }
152             } else {
153                 notifyListener(listener);
154             }
155         }
156     }
157 
158     public void removeListener(IoFutureListener listener) {
159         if (listener == null) {
160             throw new NullPointerException("listener");
161         }
162 
163         synchronized (lock) {
164             if (listener == firstListener) {
165                 if (otherListeners != null && !otherListeners.isEmpty()) {
166                     firstListener = otherListeners.remove(0);
167                 } else {
168                     firstListener = null;
169                 }
170             } else if (otherListeners != null) {
171                 otherListeners.remove(listener);
172             }
173         }
174     }
175 
176     private void notifyListeners() {
177         synchronized (lock) {
178             if (firstListener != null) {
179                 notifyListener(firstListener);
180                 if (otherListeners != null) {
181                     for (IoFutureListener l : otherListeners) {
182                         notifyListener(l);
183                     }
184                 }
185             }
186         }
187     }
188     
189     private void notifyListener(IoFutureListener l) {
190         try {
191             l.operationComplete(this);
192         } catch (Throwable t) {
193             ExceptionMonitor.getInstance().exceptionCaught(t);
194         }
195     }
196 }