1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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 }