@@ -298,7 +298,7 @@ struct IdlePopper<'a, T, K> {
298298}
299299
300300impl < ' a , T : Poolable + ' a , K : Debug > IdlePopper < ' a , T , K > {
301- fn pop ( self , expiration : & Expiration ) -> Option < Idle < T > > {
301+ fn pop ( self , expiration : & Expiration , now : Instant ) -> Option < Idle < T > > {
302302 while let Some ( entry) = self . list . pop ( ) {
303303 // If the connection has been closed, or is older than our idle
304304 // timeout, simply drop it and keep looking...
@@ -312,7 +312,7 @@ impl<'a, T: Poolable + 'a, K: Debug> IdlePopper<'a, T, K> {
312312 //
313313 // In that case, we could just break out of the loop and drop the
314314 // whole list...
315- if expiration. expires ( entry. idle_at ) {
315+ if expiration. expires ( entry. idle_at , now ) {
316316 trace ! ( "removing expired connection for {:?}" , self . key) ;
317317 continue ;
318318 }
@@ -321,7 +321,7 @@ impl<'a, T: Poolable + 'a, K: Debug> IdlePopper<'a, T, K> {
321321 #[ cfg( feature = "http2" ) ]
322322 Reservation :: Shared ( to_reinsert, to_checkout) => {
323323 self . list . push ( Idle {
324- idle_at : Instant :: now ( ) ,
324+ idle_at : now,
325325 value : to_reinsert,
326326 } ) ;
327327 to_checkout
@@ -340,6 +340,12 @@ impl<'a, T: Poolable + 'a, K: Debug> IdlePopper<'a, T, K> {
340340}
341341
342342impl < T : Poolable , K : Key > PoolInner < T , K > {
343+ fn now ( & self ) -> Instant {
344+ self . timer
345+ . as_ref ( )
346+ . map_or_else ( || Instant :: now ( ) , |t| t. now ( ) )
347+ }
348+
343349 fn put ( & mut self , key : K , value : T , __pool_ref : & Arc < Mutex < PoolInner < T , K > > > ) {
344350 if value. can_share ( ) && self . idle . contains_key ( & key) {
345351 trace ! ( "put; existing idle HTTP/2 connection for {:?}" , key) ;
@@ -386,6 +392,7 @@ impl<T: Poolable, K: Key> PoolInner<T, K> {
386392 Some ( value) => {
387393 // borrow-check scope...
388394 {
395+ let now = self . now ( ) ;
389396 let idle_list = self . idle . entry ( key. clone ( ) ) . or_default ( ) ;
390397 if self . max_idle_per_host <= idle_list. len ( ) {
391398 trace ! ( "max idle per host for {:?}, dropping connection" , key) ;
@@ -395,7 +402,7 @@ impl<T: Poolable, K: Key> PoolInner<T, K> {
395402 debug ! ( "pooling idle connection for {:?}" , key) ;
396403 idle_list. push ( Idle {
397404 value,
398- idle_at : Instant :: now ( ) ,
405+ idle_at : now,
399406 } ) ;
400407 }
401408
@@ -477,7 +484,7 @@ impl<T: Poolable, K: Key> PoolInner<T, K> {
477484 fn clear_expired ( & mut self ) {
478485 let dur = self . timeout . expect ( "interval assumes timeout" ) ;
479486
480- let now = Instant :: now ( ) ;
487+ let now = self . now ( ) ;
481488 //self.last_idle_check_at = now;
482489
483490 self . idle . retain ( |key, values| {
@@ -649,6 +656,7 @@ impl<T: Poolable, K: Key> Checkout<T, K> {
649656 let entry = {
650657 let mut inner = self . pool . inner . as_ref ( ) ?. lock ( ) . unwrap ( ) ;
651658 let expiration = Expiration :: new ( inner. timeout ) ;
659+ let now = inner. now ( ) ;
652660 let maybe_entry = inner. idle . get_mut ( & self . key ) . and_then ( |list| {
653661 trace ! ( "take? {:?}: expiration = {:?}" , self . key, expiration. 0 ) ;
654662 // A block to end the mutable borrow on list,
@@ -658,7 +666,7 @@ impl<T: Poolable, K: Key> Checkout<T, K> {
658666 key : & self . key ,
659667 list,
660668 } ;
661- popper. pop ( & expiration)
669+ popper. pop ( & expiration, now )
662670 }
663671 . map ( |e| ( e, list. is_empty ( ) ) )
664672 } ) ;
@@ -762,10 +770,10 @@ impl Expiration {
762770 Expiration ( dur)
763771 }
764772
765- fn expires ( & self , instant : Instant ) -> bool {
773+ fn expires ( & self , instant : Instant , now : Instant ) -> bool {
766774 match self . 0 {
767775 // Avoid `Instant::elapsed` to avoid issues like rust-lang/rust#86470.
768- Some ( timeout) => Instant :: now ( ) . saturating_duration_since ( instant) > timeout,
776+ Some ( timeout) => now. saturating_duration_since ( instant) > timeout,
769777 None => false ,
770778 }
771779 }
@@ -785,7 +793,7 @@ impl<T: Poolable + 'static, K: Key> IdleTask<T, K> {
785793 async fn run ( self ) {
786794 use futures_util:: future;
787795
788- let mut sleep = self . timer . sleep_until ( Instant :: now ( ) + self . duration ) ;
796+ let mut sleep = self . timer . sleep_until ( self . timer . now ( ) + self . duration ) ;
789797 let mut on_pool_drop = self . pool_drop_notifier ;
790798 loop {
791799 match future:: select ( & mut on_pool_drop, & mut sleep) . await {
@@ -801,7 +809,7 @@ impl<T: Poolable + 'static, K: Key> IdleTask<T, K> {
801809 }
802810 }
803811
804- let deadline = Instant :: now ( ) + self . duration ;
812+ let deadline = self . timer . now ( ) + self . duration ;
805813 self . timer . reset ( & mut sleep, deadline) ;
806814 }
807815 }
@@ -976,7 +984,16 @@ mod tests {
976984 }
977985
978986 #[ tokio:: test]
979- async fn test_pool_timer_removes_expired ( ) {
987+ async fn test_pool_timer_removes_expired_realtime ( ) {
988+ test_pool_timer_removes_expired_inner ( ) . await
989+ }
990+
991+ #[ tokio:: test( start_paused = true ) ]
992+ async fn test_pool_timer_removes_expired_faketime ( ) {
993+ test_pool_timer_removes_expired_inner ( ) . await
994+ }
995+
996+ async fn test_pool_timer_removes_expired_inner ( ) {
980997 let pool = Pool :: new (
981998 super :: Config {
982999 idle_timeout : Some ( Duration :: from_millis ( 10 ) ) ,
0 commit comments