@@ -14,6 +14,7 @@ use std::{
14
14
borrow:: Borrow ,
15
15
cmp:: Reverse ,
16
16
collections:: VecDeque ,
17
+ future:: poll_fn,
17
18
future:: Future ,
18
19
hash:: { Hash , Hasher } ,
19
20
str:: FromStr ,
@@ -336,12 +337,34 @@ impl Pool {
336
337
}
337
338
}
338
339
339
- /// Poll the pool for an available connection.
340
- fn poll_new_conn (
341
- & mut self ,
342
- cx : & mut Context < ' _ > ,
343
- queue_id : QueueId ,
344
- ) -> Poll < Result < GetConnInner > > {
340
+ fn queue ( & mut self , cx : & mut Context < ' _ > , queue_id : QueueId ) -> Poll < ( ) > {
341
+ let mut exchange = self . inner . exchange . lock ( ) . unwrap ( ) ;
342
+ exchange. waiting . push ( cx. waker ( ) . clone ( ) , queue_id) ;
343
+ Poll :: Ready ( ( ) )
344
+ }
345
+
346
+ fn poll_higher_priority ( & mut self , cx : & mut Context < ' _ > , queue_id : QueueId ) -> Poll < ( ) > {
347
+ let mut exchange = self . inner . exchange . lock ( ) . unwrap ( ) ;
348
+ let highest = if let Some ( cur) = exchange. waiting . peek_id ( ) {
349
+ queue_id > cur
350
+ } else {
351
+ true
352
+ } ;
353
+ if highest {
354
+ Poll :: Ready ( ( ) )
355
+ } else {
356
+ // to make sure the waker is updated
357
+ exchange. waiting . push ( cx. waker ( ) . clone ( ) , queue_id) ;
358
+ Poll :: Pending
359
+ }
360
+ }
361
+
362
+ async fn queue_and_wait ( & mut self , queue_id : QueueId ) {
363
+ poll_fn ( |cx| self . queue ( cx, queue_id) ) . await ;
364
+ poll_fn ( |cx| self . poll_higher_priority ( cx, queue_id) ) . await ;
365
+ }
366
+
367
+ fn try_new_conn ( & mut self , queue_id : QueueId ) -> Result < Option < GetConnInner > > {
345
368
let mut exchange = self . inner . exchange . lock ( ) . unwrap ( ) ;
346
369
347
370
// NOTE: this load must happen while we hold the lock,
@@ -362,8 +385,7 @@ impl Pool {
362
385
363
386
// If we are not, just queue
364
387
if !highest {
365
- exchange. waiting . push ( cx. waker ( ) . clone ( ) , queue_id) ;
366
- return Poll :: Pending ;
388
+ return Ok ( None ) ;
367
389
}
368
390
369
391
#[ allow( unused_variables) ] // `since` is only used when `hdrhistogram` is enabled
@@ -379,7 +401,7 @@ impl Pool {
379
401
#[ cfg( feature = "hdrhistogram" ) ]
380
402
let metrics = self . metrics ( ) ;
381
403
conn. inner . active_since = Instant :: now ( ) ;
382
- return Poll :: Ready ( Ok ( GetConnInner :: Checking (
404
+ return Ok ( Some ( GetConnInner :: Checking (
383
405
async move {
384
406
conn. stream_mut ( ) ?. check ( ) . await ?;
385
407
#[ cfg( feature = "hdrhistogram" ) ]
@@ -419,7 +441,7 @@ impl Pool {
419
441
#[ cfg( feature = "hdrhistogram" ) ]
420
442
let metrics = self . metrics ( ) ;
421
443
422
- return Poll :: Ready ( Ok ( GetConnInner :: Connecting (
444
+ return Ok ( Some ( GetConnInner :: Connecting (
423
445
async move {
424
446
let conn = Conn :: new ( opts) . await ;
425
447
#[ cfg( feature = "hdrhistogram" ) ]
@@ -437,10 +459,17 @@ impl Pool {
437
459
. boxed ( ) ,
438
460
) ) ) ;
439
461
}
462
+ Ok ( None )
463
+ }
440
464
441
- // Polled, but no conn available? Back into the queue.
442
- exchange. waiting . push ( cx. waker ( ) . clone ( ) , queue_id) ;
443
- Poll :: Pending
465
+ /// Get a new connection from the pool.
466
+ async fn new_conn ( & mut self , queue_id : QueueId ) -> Result < GetConnInner > {
467
+ loop {
468
+ if let Some ( conn) = self . try_new_conn ( queue_id) ? {
469
+ return Ok ( conn) ;
470
+ }
471
+ self . queue_and_wait ( queue_id) . await ;
472
+ }
444
473
}
445
474
446
475
fn unqueue ( & self , queue_id : QueueId ) {
0 commit comments