View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 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 FutureCallback implements Future<Void>,Callback
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      
37      public FutureCallback()
38      {}
39  
40      public FutureCallback(boolean completed)
41      {
42          if (completed)
43          {
44              _cause=COMPLETED;
45              _done.set(true);
46              _latch.countDown();
47          }
48      }
49  
50      public FutureCallback(Throwable failed)
51      {
52          _cause=failed;
53          _done.set(true);
54          _latch.countDown();
55      }
56  
57      @Override
58      public void succeeded()
59      {
60          if (_done.compareAndSet(false,true))
61          {
62              _cause=COMPLETED;
63              _latch.countDown();
64          }
65      }
66  
67      @Override
68      public void failed(Throwable cause)
69      {
70          if (_done.compareAndSet(false,true))
71          {
72              _cause=cause;
73              _latch.countDown();
74          }
75      }
76  
77      @Override
78      public boolean cancel(boolean mayInterruptIfRunning)
79      {
80          if (_done.compareAndSet(false,true))
81          {
82              _cause=new CancellationException();
83              _latch.countDown();
84              return true;
85          }
86          return false;
87      }
88  
89      @Override
90      public boolean isCancelled()
91      {
92          if (_done.get())
93          {
94              try
95              {
96                  _latch.await();
97              }
98              catch (InterruptedException e)
99              {
100                 throw new RuntimeException(e);
101             }
102             return _cause instanceof CancellationException;
103         }
104         return false;
105     }
106 
107     @Override
108     public boolean isDone()
109     {
110         return _done.get() && _latch.getCount()==0;
111     }
112 
113     @Override
114     public Void get() throws InterruptedException, ExecutionException
115     {
116         _latch.await();
117         if (_cause==COMPLETED)
118             return null;
119         if (_cause instanceof CancellationException)
120             throw (CancellationException) new CancellationException().initCause(_cause);
121         throw new ExecutionException(_cause);
122     }
123 
124     @Override
125     public Void get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
126     {
127         if (!_latch.await(timeout,unit))
128             throw new TimeoutException();
129 
130         if (_cause==COMPLETED)
131             return null;
132         if (_cause instanceof TimeoutException)
133             throw (TimeoutException)_cause;
134         if (_cause instanceof CancellationException)
135             throw (CancellationException) new CancellationException().initCause(_cause);
136         throw new ExecutionException(_cause);
137     }
138 
139     public static void rethrow(ExecutionException e) throws IOException
140     {
141         Throwable cause=e.getCause();
142         if (cause instanceof IOException)
143             throw (IOException)cause;
144         if (cause instanceof Error)
145             throw (Error)cause;
146         if (cause instanceof RuntimeException)
147             throw (RuntimeException)cause;
148         throw new RuntimeException(cause);
149     }
150     
151     @Override
152     public String toString()
153     {
154         return String.format("FutureCallback@%x{%b,%b}",hashCode(),_done.get(),_cause==COMPLETED);
155     }
156     
157 }