DefaultIoFuture.java
001 /*
002  *  Licensed to the Apache Software Foundation (ASF) under one
003  *  or more contributor license agreements.  See the NOTICE file
004  *  distributed with this work for additional information
005  *  regarding copyright ownership.  The ASF licenses this file
006  *  to you under the Apache License, Version 2.0 (the
007  *  "License"); you may not use this file except in compliance
008  *  with the License.  You may obtain a copy of the License at
009  *
010  *    http://www.apache.org/licenses/LICENSE-2.0
011  *
012  *  Unless required by applicable law or agreed to in writing,
013  *  software distributed under the License is distributed on an
014  *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015  *  KIND, either express or implied.  See the License for the
016  *  specific language governing permissions and limitations
017  *  under the License.
018  *
019  */
020 package org.apache.mina.common.support;
021 
022 import org.apache.mina.common.IoFuture;
023 import org.apache.mina.common.IoSession;
024 import org.apache.mina.common.IoFutureListener;
025 
026 import java.util.List;
027 import java.util.ArrayList;
028 import java.util.Iterator;
029 
030 /**
031  * A default implementation of {@link org.apache.mina.common.IoFuture}.
032  *
033  * @author The Apache Directory Project (mina-dev@directory.apache.org)
034  */
035 public class DefaultIoFuture implements IoFuture
036 {
037     private final IoSession session;
038     private final Object lock;
039     private List listeners;
040     private Object result;
041     private boolean ready;
042 
043 
044     /**
045      * Creates a new instance.
046      *
047      * @param session an {@link IoSession} which is associated with this future
048      */
049     public DefaultIoFuture( IoSession session )
050     {
051         this.session = session;
052         this.lock = this;
053     }
054 
055     /**
056      * Creates a new instance which uses the specified object as a lock.
057      */
058     public DefaultIoFuture( IoSession session, Object lock )
059     {
060         if( lock == null )
061         {
062             throw new NullPointerException( "lock" );
063         }
064         this.session = session;
065         this.lock = lock;
066     }
067 
068     public IoSession getSession()
069     {
070         return session;
071     }
072 
073     public Object getLock()
074     {
075         return lock;
076     }
077 
078     public void join()
079     {
080         synchronized( lock )
081         {
082             while( !ready )
083             {
084                 try
085                 {
086                     lock.wait();
087                 }
088                 catch( InterruptedException e )
089                 {
090                 }
091             }
092         }
093     }
094 
095     public boolean join( long timeoutInMillis )
096     {
097         long startTime = ( timeoutInMillis <= 0 ) ? 0 : System
098                 .currentTimeMillis();
099         long waitTime = timeoutInMillis;
100 
101         synchronized( lock )
102         {
103             if( ready )
104             {
105                 return ready;
106             }
107             else if( waitTime <= 0 )
108             {
109                 return ready;
110             }
111 
112             for( ;; )
113             {
114                 try
115                 {
116                     lock.wait( waitTime );
117                 }
118                 catch( InterruptedException e )
119                 {
120                 }
121 
122                 if( ready )
123                     return true;
124                 else
125                 {
126                     waitTime = timeoutInMillis - ( System.currentTimeMillis() - startTime );
127                     if( waitTime <= 0 )
128                     {
129                         return ready;
130                     }
131                 }
132             }
133         }
134     }
135 
136     public boolean isReady()
137     {
138         synchronized( lock )
139         {
140             return ready;
141         }
142     }
143 
144     /**
145      * Sets the result of the asynchronous operation, and mark it as finished.
146      */
147     protected void setValue( Object newValue )
148     {
149         synchronized( lock )
150         {
151             // Allow only once.
152             if( ready )
153             {
154                 return;
155             }
156 
157             result = newValue;
158             ready = true;
159             lock.notifyAll();
160 
161             notifyListeners();
162         }
163     }
164 
165     /**
166      * Returns the result of the asynchronous operation.
167      */
168     protected Object getValue()
169     {
170         synchronized( lock )
171         {
172             return result;
173         }
174     }
175 
176     public void addListener( IoFutureListener listener )
177     {
178         if( listener == null )
179         {
180             throw new NullPointerException( "listener" );
181         }
182 
183         synchronized( lock )
184         {
185             if(listeners == null)
186             {
187                  listeners = new ArrayList();
188             }
189             listeners.add( listener );
190             if( ready )
191             {
192                 listener.operationComplete( this );
193             }
194         }
195     }
196 
197     public void removeListener( IoFutureListener listener )
198     {
199         if( listener == null )
200         {
201             throw new NullPointerException( "listener" );
202         }
203 
204         synchronized( lock )
205         {
206             listeners.remove( listener );
207         }
208     }
209 
210     private void notifyListeners()
211     {
212         synchronized( lock )
213         {
214 
215             if(listeners != null)
216             {
217 
218                 for( Iterator i = listeners.iterator(); i.hasNext(); ) {
219                     ( ( IoFutureListener ) i.next() ).operationComplete( this );
220                 }
221             }
222         }
223     }
224 }
225 
226