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.Iterator;
24  import java.util.List;
25  
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 Directory Project (mina-dev@directory.apache.org)
34   * @version $Rev: 555855 $, $Date: 2007-07-13 12:19:00 +0900 (금, 13  7월 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 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      /**
60       * Creates a new instance which uses the specified object as a lock.
61       */
62      public DefaultIoFuture(IoSession session, Object lock) {
63          if (lock == null) {
64              throw new NullPointerException("lock");
65          }
66          this.session = session;
67          this.lock = lock;
68      }
69  
70      public IoSession getSession() {
71          return session;
72      }
73  
74      public Object getLock() {
75          return lock;
76      }
77  
78      public void join() {
79          synchronized (lock) {
80              while (!ready) {
81                  try {
82                      lock.wait();
83                  } catch (InterruptedException e) {
84                  }
85              }
86          }
87      }
88  
89      public boolean join(long timeoutInMillis) {
90          long startTime = (timeoutInMillis <= 0) ? 0 : System
91                  .currentTimeMillis();
92          long waitTime = timeoutInMillis;
93  
94          synchronized (lock) {
95              if (ready) {
96                  return ready;
97              } else if (waitTime <= 0) {
98                  return ready;
99              }
100 
101             for (;;) {
102                 try {
103                     lock.wait(waitTime);
104                 } catch (InterruptedException e) {
105                 }
106 
107                 if (ready)
108                     return true;
109                 else {
110                     waitTime = timeoutInMillis
111                             - (System.currentTimeMillis() - startTime);
112                     if (waitTime <= 0) {
113                         return ready;
114                     }
115                 }
116             }
117         }
118     }
119 
120     public boolean isReady() {
121         synchronized (lock) {
122             return ready;
123         }
124     }
125 
126     /**
127      * Sets the result of the asynchronous operation, and mark it as finished.
128      */
129     protected void setValue(Object newValue) {
130         synchronized (lock) {
131             // Allow only once.
132             if (ready) {
133                 return;
134             }
135 
136             result = newValue;
137             ready = true;
138             lock.notifyAll();
139 
140             notifyListeners();
141         }
142     }
143 
144     /**
145      * Returns the result of the asynchronous operation.
146      */
147     protected Object getValue() {
148         synchronized (lock) {
149             return result;
150         }
151     }
152 
153     public void addListener(IoFutureListener listener) {
154         if (listener == null) {
155             throw new NullPointerException("listener");
156         }
157 
158         synchronized (lock) {
159             if (firstListener == null) {
160                 firstListener = listener;
161             } else {
162                 if (otherListeners == null) {
163                     otherListeners = new ArrayList(1);
164                 }
165                 otherListeners.add(listener);
166             }
167             if (ready) {
168                 listener.operationComplete(this);
169             }
170         }
171     }
172 
173     public void removeListener(IoFutureListener listener) {
174         if (listener == null) {
175             throw new NullPointerException("listener");
176         }
177 
178         synchronized (lock) {
179             if (listener == firstListener) {
180                 if (otherListeners != null && !otherListeners.isEmpty()) {
181                     firstListener = (IoFutureListener) otherListeners.remove(0);
182                 } else {
183                     firstListener = null;
184                 }
185             } else if (otherListeners != null) {
186                 otherListeners.remove(listener);
187             }
188         }
189     }
190 
191     private void notifyListeners() {
192         synchronized (lock) {
193             if (firstListener != null) {
194                 firstListener.operationComplete(this);
195                 if (otherListeners != null) {
196                     for (Iterator i = otherListeners.iterator(); i.hasNext();) {
197                         ((IoFutureListener) i.next()).operationComplete(this);
198                     }
199                 }
200             }
201         }
202     }
203 }