14
14
package org .asynchttpclient .netty ;
15
15
16
16
import static org .asynchttpclient .util .DateUtils .unpreciseMillisTime ;
17
- import static org .asynchttpclient .util .MiscUtils .getCause ;
18
17
import static io .netty .util .internal .PlatformDependent .*;
19
18
import io .netty .channel .Channel ;
20
19
21
20
import java .util .concurrent .CancellationException ;
22
21
import java .util .concurrent .CompletableFuture ;
23
- import java .util .concurrent .CountDownLatch ;
24
22
import java .util .concurrent .ExecutionException ;
23
+ import java .util .concurrent .Executor ;
25
24
import java .util .concurrent .Future ;
26
25
import java .util .concurrent .TimeUnit ;
27
26
import java .util .concurrent .TimeoutException ;
28
27
import java .util .concurrent .atomic .AtomicIntegerFieldUpdater ;
29
- import java .util .concurrent .atomic .AtomicReferenceFieldUpdater ;
30
28
31
29
import org .asynchttpclient .AsyncHandler ;
30
+ import org .asynchttpclient .ListenableFuture ;
32
31
import org .asynchttpclient .Realm ;
33
32
import org .asynchttpclient .Request ;
34
33
import org .asynchttpclient .channel .ChannelPoolPartitioning ;
35
- import org .asynchttpclient .future .AbstractListenableFuture ;
36
34
import org .asynchttpclient .netty .channel .ChannelState ;
37
35
import org .asynchttpclient .netty .channel .Channels ;
38
36
import org .asynchttpclient .netty .request .NettyRequest ;
47
45
*
48
46
* @param <V> the result type
49
47
*/
50
- public final class NettyResponseFuture <V > extends AbstractListenableFuture <V > {
48
+ public final class NettyResponseFuture <V > implements ListenableFuture <V > {
51
49
52
50
private static final Logger LOGGER = LoggerFactory .getLogger (NettyResponseFuture .class );
53
51
54
52
private static final AtomicIntegerFieldUpdater <NettyResponseFuture <?>> REDIRECT_COUNT_UPDATER = newAtomicIntegerFieldUpdater (NettyResponseFuture .class , "redirectCount" );
55
53
private static final AtomicIntegerFieldUpdater <NettyResponseFuture <?>> CURRENT_RETRY_UPDATER = newAtomicIntegerFieldUpdater (NettyResponseFuture .class , "currentRetry" );
56
- @ SuppressWarnings ("rawtypes" )
57
- // FIXME see https://github.com/netty/netty/pull/4669
58
- private static final AtomicReferenceFieldUpdater <NettyResponseFuture , Object > CONTENT_UPDATER = newAtomicReferenceFieldUpdater (NettyResponseFuture .class , "content" );
59
- @ SuppressWarnings ("rawtypes" )
60
- // FIXME see https://github.com/netty/netty/pull/4669
61
- private static final AtomicReferenceFieldUpdater <NettyResponseFuture , ExecutionException > EX_EX_UPDATER = newAtomicReferenceFieldUpdater (NettyResponseFuture .class , "exEx" );
62
54
63
55
private final long start = unpreciseMillisTime ();
64
56
private final ChannelPoolPartitioning connectionPoolPartitioning ;
65
57
private final ProxyServer proxyServer ;
66
58
private final int maxRetry ;
67
- private final CountDownLatch latch = new CountDownLatch ( 1 );
59
+ private final CompletableFuture < V > future = new CompletableFuture <>( );
68
60
69
61
// state mutated from outside the event loop
70
62
// TODO check if they are indeed mutated outside the event loop
@@ -89,8 +81,6 @@ public final class NettyResponseFuture<V> extends AbstractListenableFuture<V> {
89
81
// volatile where we need CAS ops
90
82
private volatile int redirectCount = 0 ;
91
83
private volatile int currentRetry = 0 ;
92
- private volatile V content ;
93
- private volatile ExecutionException exEx ;
94
84
95
85
// volatile where we don't need CAS ops
96
86
private volatile long touch = unpreciseMillisTime ();
@@ -160,40 +150,35 @@ public boolean cancel(boolean force) {
160
150
LOGGER .warn ("cancel" , t );
161
151
}
162
152
}
163
- latch . countDown ();
164
- runListeners ( );
153
+
154
+ future . cancel ( false );
165
155
return true ;
166
156
}
167
157
168
158
@ Override
169
159
public V get () throws InterruptedException , ExecutionException {
170
- latch .await ();
171
- return getContent ();
160
+ return future .get ();
172
161
}
173
162
174
163
@ Override
175
164
public V get (long l , TimeUnit tu ) throws InterruptedException , TimeoutException , ExecutionException {
176
- if (!latch .await (l , tu ))
177
- throw new TimeoutException ();
178
- return getContent ();
165
+ return future .get (l , tu );
179
166
}
180
167
181
168
private V getContent () throws ExecutionException {
169
+ if (future .isDone ()) {
170
+ try {
171
+ return future .get ();
172
+ } catch (InterruptedException e ) {
173
+ throw new RuntimeException ("unreachable" , e );
174
+ }
175
+ }
182
176
183
- if (isCancelled ())
184
- throw new CancellationException ();
185
-
186
- ExecutionException e = EX_EX_UPDATER .get (this );
187
- if (e != null )
188
- throw e ;
189
-
190
- @ SuppressWarnings ("unchecked" )
191
- V update = (V ) CONTENT_UPDATER .get (this );
192
177
// No more retry
193
178
CURRENT_RETRY_UPDATER .set (this , maxRetry );
194
179
if (contentProcessedField .getAndSet (this , 1 ) == 0 ) {
195
180
try {
196
- update = asyncHandler .onCompleted ();
181
+ future . complete ( asyncHandler .onCompleted () );
197
182
} catch (Throwable ex ) {
198
183
if (onThrowableCalledField .getAndSet (this , 1 ) == 0 ) {
199
184
try {
@@ -202,15 +187,14 @@ private V getContent() throws ExecutionException {
202
187
} catch (Throwable t ) {
203
188
LOGGER .debug ("asyncHandler.onThrowable" , t );
204
189
}
205
- throw new RuntimeException (ex );
206
190
} finally {
207
191
cancelTimeouts ();
208
192
}
209
193
}
194
+ future .completeExceptionally (ex );
210
195
}
211
- CONTENT_UPDATER .compareAndSet (this , null , update );
212
196
}
213
- return update ;
197
+ return future . getNow ( null ) ;
214
198
}
215
199
216
200
// org.asynchttpclient.ListenableFuture
@@ -229,22 +213,19 @@ public final void done() {
229
213
230
214
try {
231
215
getContent ();
216
+ } catch (ExecutionException ignored ) {
232
217
233
- } catch (ExecutionException t ) {
234
- return ;
235
218
} catch (RuntimeException t ) {
236
- EX_EX_UPDATER . compareAndSet ( this , null , new ExecutionException ( getCause ( t )) );
237
-
238
- } finally {
239
- latch . countDown () ;
219
+ future . completeExceptionally ( t );
220
+ } catch ( Throwable t ) {
221
+ future . completeExceptionally ( t );
222
+ throw t ;
240
223
}
241
-
242
- runListeners ();
243
224
}
244
225
245
226
public final void abort (final Throwable t ) {
246
227
247
- EX_EX_UPDATER . compareAndSet ( this , null , new ExecutionException ( t ) );
228
+ future . completeExceptionally ( t );
248
229
249
230
if (terminateAndExit ())
250
231
return ;
@@ -256,8 +237,6 @@ public final void abort(final Throwable t) {
256
237
LOGGER .debug ("asyncHandler.onThrowable" , te );
257
238
}
258
239
}
259
- latch .countDown ();
260
- runListeners ();
261
240
}
262
241
263
242
@ Override
@@ -266,22 +245,14 @@ public void touch() {
266
245
}
267
246
268
247
@ Override
269
- public CompletableFuture <V > toCompletableFuture () {
270
- CompletableFuture <V > completable = new CompletableFuture <>();
271
- addListener (new Runnable () {
272
- @ Override
273
- @ SuppressWarnings ("unchecked" )
274
- public void run () {
275
- ExecutionException e = EX_EX_UPDATER .get (NettyResponseFuture .this );
276
- if (e != null )
277
- completable .completeExceptionally (e .getCause ());
278
- else
279
- completable .complete ((V ) CONTENT_UPDATER .get (NettyResponseFuture .this ));
280
- }
281
-
282
- }, null );
248
+ public ListenableFuture <V > addListener (Runnable listener , Executor exec ) {
249
+ future .whenCompleteAsync ((r , v ) -> listener .run (), exec );
250
+ return this ;
251
+ }
283
252
284
- return completable ;
253
+ @ Override
254
+ public CompletableFuture <V > toCompletableFuture () {
255
+ return future ;
285
256
}
286
257
287
258
// INTERNAL
@@ -498,10 +469,9 @@ public String toString() {
498
469
",\n \t isCancelled=" + isCancelled + //
499
470
",\n \t asyncHandler=" + asyncHandler + //
500
471
",\n \t nettyRequest=" + nettyRequest + //
501
- ",\n \t content =" + content + //
472
+ ",\n \t future =" + future + //
502
473
",\n \t uri=" + getUri () + //
503
474
",\n \t keepAlive=" + keepAlive + //
504
- ",\n \t exEx=" + exEx + //
505
475
",\n \t redirectCount=" + redirectCount + //
506
476
",\n \t timeoutsHolder=" + timeoutsHolder + //
507
477
",\n \t inAuth=" + inAuth + //
0 commit comments