View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.util;
20  
21  import java.io.IOException;
22  import java.util.concurrent.CancellationException;
23  import java.util.concurrent.CountDownLatch;
24  import java.util.concurrent.ExecutionException;
25  import java.util.concurrent.Future;
26  import java.util.concurrent.TimeUnit;
27  import java.util.concurrent.TimeoutException;
28  import java.util.concurrent.atomic.AtomicBoolean;
29  
30  public class FuturePromise<C> implements Future<C>,Promise<C>
31  {
32      private static Throwable COMPLETED=new Throwable();
33      private final AtomicBoolean _done=new AtomicBoolean(false);
34      private final CountDownLatch _latch=new CountDownLatch(1);
35      private Throwable _cause;
36      private C _result;
37      
38      public FuturePromise()
39      {}
40  
41      public FuturePromise(C result)
42      {
43          _cause=COMPLETED;
44          _result=result;
45          _done.set(true);
46          _latch.countDown();
47      }
48  
49      public FuturePromise(C ctx, Throwable failed)
50      {
51          _result=ctx;
52          _cause=failed;
53          _done.set(true);
54          _latch.countDown();
55      }
56  
57      @Override
58      public void succeeded(C result)
59      {
60          if (_done.compareAndSet(false,true))
61          {
62              _result=result;
63              _cause=COMPLETED;
64              _latch.countDown();
65          }
66      }
67  
68      @Override
69      public void failed(Throwable cause)
70      {
71          if (_done.compareAndSet(false,true))
72          {
73              _cause=cause;
74              _latch.countDown();
75          }
76      }
77  
78      @Override
79      public boolean cancel(boolean mayInterruptIfRunning)
80      {
81          if (_done.compareAndSet(false,true))
82          {
83              _result=null;
84              _cause=new CancellationException();
85              _latch.countDown();
86              return true;
87          }
88          return false;
89      }
90  
91      @Override
92      public boolean isCancelled()
93      {
94          if (_done.get())
95          {
96              try
97              {
98                  _latch.await();
99              }
100             catch (InterruptedException e)
101             {
102                 throw new RuntimeException(e);
103             }
104             return _cause instanceof CancellationException;
105         }
106         return false;
107     }
108 
109     @Override
110     public boolean isDone()
111     {
112         return _done.get() && _latch.getCount()==0;
113     }
114 
115     @Override
116     public C get() throws InterruptedException, ExecutionException
117     {
118         _latch.await();
119         if (_cause==COMPLETED)
120             return _result;
121         if (_cause instanceof CancellationException)
122             throw (CancellationException) new CancellationException().initCause(_cause);
123         throw new ExecutionException(_cause);
124     }
125 
126     @Override
127     public C get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
128     {
129         if (!_latch.await(timeout,unit))
130             throw new TimeoutException();
131 
132         if (_cause==COMPLETED)
133             return _result;
134         if (_cause instanceof TimeoutException)
135             throw (TimeoutException)_cause;
136         if (_cause instanceof CancellationException)
137             throw (CancellationException) new CancellationException().initCause(_cause);
138         throw new ExecutionException(_cause);
139     }
140 
141     public static void rethrow(ExecutionException e) throws IOException
142     {
143         Throwable cause=e.getCause();
144         if (cause instanceof IOException)
145             throw (IOException)cause;
146         if (cause instanceof Error)
147             throw (Error)cause;
148         if (cause instanceof RuntimeException)
149             throw (RuntimeException)cause;
150         throw new RuntimeException(cause);
151     }
152     
153     @Override
154     public String toString()
155     {
156         return String.format("FutureCallback@%x{%b,%b,%s}",hashCode(),_done,_cause==COMPLETED,_result);
157     }
158     
159 }