2828package org .apache .hc .client5 .http .impl .async ;
2929
3030import java .io .InterruptedIOException ;
31- import java .util .concurrent .RejectedExecutionException ;
32- import java .util .concurrent .atomic .AtomicInteger ;
3331import java .util .concurrent .atomic .AtomicReference ;
3432
3533import org .apache .hc .client5 .http .EndpointInfo ;
@@ -63,30 +61,27 @@ class InternalH2AsyncExecRuntime implements AsyncExecRuntime {
6361 private final InternalH2ConnPool connPool ;
6462 private final HandlerFactory <AsyncPushConsumer > pushHandlerFactory ;
6563 private final AtomicReference <Endpoint > sessionRef ;
66- private final int maxQueued ;
67- private final AtomicInteger sharedQueued ;
64+ private final SharedRequestExecutionQueue executionQueue ;
6865 private volatile boolean reusable ;
6966
7067 InternalH2AsyncExecRuntime (
7168 final Logger log ,
7269 final InternalH2ConnPool connPool ,
7370 final HandlerFactory <AsyncPushConsumer > pushHandlerFactory ) {
74- this (log , connPool , pushHandlerFactory , - 1 , null );
71+ this (log , connPool , pushHandlerFactory , null );
7572 }
7673
7774 InternalH2AsyncExecRuntime (
7875 final Logger log ,
7976 final InternalH2ConnPool connPool ,
8077 final HandlerFactory <AsyncPushConsumer > pushHandlerFactory ,
81- final int maxQueued ,
82- final AtomicInteger sharedQueued ) {
78+ final SharedRequestExecutionQueue executionQueue ) {
8379 super ();
8480 this .log = log ;
8581 this .connPool = connPool ;
8682 this .pushHandlerFactory = pushHandlerFactory ;
8783 this .sessionRef = new AtomicReference <>();
88- this .maxQueued = maxQueued ;
89- this .sharedQueued = sharedQueued ;
84+ this .executionQueue = executionQueue ;
9085 }
9186
9287 @ Override
@@ -179,7 +174,6 @@ public boolean isEndpointConnected() {
179174 return endpoint != null && endpoint .session .isOpen ();
180175 }
181176
182-
183177 Endpoint ensureValid () {
184178 final Endpoint endpoint = sessionRef .get ();
185179 if (endpoint == null ) {
@@ -261,49 +255,55 @@ public EndpointInfo getEndpointInfo() {
261255 return null ;
262256 }
263257
264- private boolean tryAcquireSlot () {
265- if (sharedQueued == null || maxQueued <= 0 ) {
266- return true ;
258+ @ Override
259+ public Cancellable execute (
260+ final String id ,
261+ final AsyncClientExchangeHandler exchangeHandler ,
262+ final HttpClientContext context ) {
263+
264+ final Endpoint endpoint = ensureValid ();
265+ final ComplexCancellable complexCancellable = new ComplexCancellable ();
266+
267+ if (executionQueue == null ) {
268+ startExecution (id , endpoint , exchangeHandler , context , complexCancellable );
269+ return complexCancellable ;
267270 }
268- for (;;) {
269- final int q = sharedQueued .get ();
270- if (q >= maxQueued ) {
271- return false ;
272- }
273- if (sharedQueued .compareAndSet (q , q + 1 )) {
271+
272+ final Cancellable queued = executionQueue .enqueue (
273+ () -> {
274+ final AsyncClientExchangeHandler wrapped =
275+ new ReleasingAsyncClientExchangeHandler (exchangeHandler , executionQueue ::completed );
276+ try {
277+ startExecution (id , endpoint , wrapped , context , complexCancellable );
278+ } catch (final RuntimeException ex ) {
279+ wrapped .failed (ex );
280+ }
281+ },
282+ exchangeHandler ::cancel );
283+
284+ return () -> {
285+ if (queued .cancel ()) {
274286 return true ;
275287 }
276- }
277- }
278-
279- private void releaseSlot () {
280- if (sharedQueued != null && maxQueued > 0 ) {
281- sharedQueued .decrementAndGet ();
282- }
288+ return complexCancellable .cancel ();
289+ };
283290 }
284291
285- @ Override
286- public Cancellable execute (
292+ private void startExecution (
287293 final String id ,
288- final AsyncClientExchangeHandler exchangeHandler , final HttpClientContext context ) {
289- final Endpoint endpoint = ensureValid ();
290- if (!tryAcquireSlot ()) {
291- exchangeHandler .failed (new RejectedExecutionException (
292- "Execution pipeline queue limit reached (max=" + maxQueued + ")" ));
293- return Operations .nonCancellable ();
294- }
295- final AsyncClientExchangeHandler actual = sharedQueued != null
296- ? new ReleasingAsyncClientExchangeHandler (exchangeHandler , this ::releaseSlot )
297- : exchangeHandler ;
298- final ComplexCancellable complexCancellable = new ComplexCancellable ();
294+ final Endpoint endpoint ,
295+ final AsyncClientExchangeHandler exchangeHandler ,
296+ final HttpClientContext context ,
297+ final ComplexCancellable complexCancellable ) {
298+
299299 final IOSession session = endpoint .session ;
300300 if (session .isOpen ()) {
301301 if (log .isDebugEnabled ()) {
302302 log .debug ("{} start execution {}" , ConnPoolSupport .getId (endpoint ), id );
303303 }
304304 context .setProtocolVersion (HttpVersion .HTTP_2 );
305305 session .enqueue (
306- new RequestExecutionCommand (actual , pushHandlerFactory , complexCancellable , context ),
306+ new RequestExecutionCommand (exchangeHandler , pushHandlerFactory , complexCancellable , context ),
307307 Command .Priority .NORMAL );
308308 } else {
309309 final HttpRoute route = endpoint .route ;
@@ -321,23 +321,22 @@ public void completed(final IOSession ioSession) {
321321 }
322322 context .setProtocolVersion (HttpVersion .HTTP_2 );
323323 ioSession .enqueue (
324- new RequestExecutionCommand (actual , pushHandlerFactory , complexCancellable , context ),
324+ new RequestExecutionCommand (exchangeHandler , pushHandlerFactory , complexCancellable , context ),
325325 Command .Priority .NORMAL );
326326 }
327327
328328 @ Override
329329 public void failed (final Exception ex ) {
330- actual .failed (ex );
330+ exchangeHandler .failed (ex );
331331 }
332332
333333 @ Override
334334 public void cancelled () {
335- actual .failed (new InterruptedIOException ());
335+ exchangeHandler .failed (new InterruptedIOException ());
336336 }
337337
338338 });
339339 }
340- return complexCancellable ;
341340 }
342341
343342 @ Override
@@ -369,7 +368,7 @@ public String getId() {
369368
370369 @ Override
371370 public AsyncExecRuntime fork () {
372- return new InternalH2AsyncExecRuntime (log , connPool , pushHandlerFactory , maxQueued , sharedQueued );
371+ return new InternalH2AsyncExecRuntime (log , connPool , pushHandlerFactory , executionQueue );
373372 }
374373
375374}
0 commit comments