001    /*
002     * Copyright (C) 2012 eXo Platform SAS.
003     *
004     * This is free software; you can redistribute it and/or modify it
005     * under the terms of the GNU Lesser General Public License as
006     * published by the Free Software Foundation; either version 2.1 of
007     * the License, or (at your option) any later version.
008     *
009     * This software is distributed in the hope that it will be useful,
010     * but WITHOUT ANY WARRANTY; without even the implied warranty of
011     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012     * Lesser General Public License for more details.
013     *
014     * You should have received a copy of the GNU Lesser General Public
015     * License along with this software; if not, write to the Free
016     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018     */
019    package org.crsh.util;
020    
021    import java.util.concurrent.*;
022    import java.util.concurrent.locks.Lock;
023    import java.util.concurrent.locks.ReentrantLock;
024    
025    public class LatchedFuture<V> implements Future<V> {
026    
027      /** . */
028      private V value = null;
029    
030      /** . */
031      private final CountDownLatch latch = new CountDownLatch(1);
032    
033      /** . */
034      private final Lock lock = new ReentrantLock();
035    
036      /** The optional listener. */
037      private FutureListener<V> listener;
038    
039      public LatchedFuture() {
040      }
041    
042      public LatchedFuture(V value) {
043        set(value);
044      }
045    
046      public boolean cancel(boolean b) {
047        return false;
048      }
049    
050      public boolean isCancelled() {
051        return false; 
052      }
053    
054      public boolean isDone() {
055        return latch.getCount() == 0;
056      }
057    
058      public V get() throws InterruptedException, ExecutionException {
059        latch.await();
060        return value;
061      }
062    
063      public V get(long l, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException {
064        latch.await(l, timeUnit);
065        return value;
066      }
067    
068      public void addListener(FutureListener<V> listener) {
069        if (listener == null) {
070          throw new NullPointerException();
071        }
072        lock.lock();
073        try {
074    
075          // Avoid double init
076          if (this.listener != null) {
077            throw new IllegalStateException();
078          }
079    
080          // Set state
081          this.listener = listener;
082    
083          //
084          if (latch.getCount() == 0) {
085            listener.completed(value);
086          }
087    
088          //
089        } finally {
090          lock.unlock();
091        }
092      }
093    
094      public void set(V value) {
095        lock.lock();
096        try {
097          if (latch.getCount() > 0) {
098            this.value = value;
099            latch.countDown();
100            if (listener != null) {
101              listener.completed(value);
102            }
103          } else {
104            throw new IllegalStateException();
105          }
106        } finally {
107          lock.unlock();
108        }
109      }
110    }