@@ -18,7 +18,10 @@ use futures_channel::oneshot;
1818use futures_util:: ready;
1919use tracing:: { debug, trace} ;
2020
21- use crate :: common:: exec:: { self , Exec } ;
21+ use hyper:: rt:: Sleep ;
22+ use hyper:: rt:: Timer as _;
23+
24+ use crate :: common:: { exec, exec:: Exec , timer:: Timer } ;
2225
2326// FIXME: allow() required due to `impl Trait` leaking types to this lint
2427#[ allow( missing_debug_implementations) ]
@@ -97,6 +100,7 @@ struct PoolInner<T, K: Eq + Hash> {
97100 // the Pool completely drops. That way, the interval can cancel immediately.
98101 idle_interval_ref : Option < oneshot:: Sender < Infallible > > ,
99102 exec : Exec ,
103+ timer : Option < Timer > ,
100104 timeout : Option < Duration > ,
101105}
102106
@@ -117,11 +121,13 @@ impl Config {
117121}
118122
119123impl < T , K : Key > Pool < T , K > {
120- pub fn new < E > ( config : Config , executor : E ) -> Pool < T , K >
124+ pub fn new < E , M > ( config : Config , executor : E , timer : Option < M > ) -> Pool < T , K >
121125 where
122126 E : hyper:: rt:: Executor < exec:: BoxSendFuture > + Send + Sync + Clone + ' static ,
127+ M : hyper:: rt:: Timer + Send + Sync + Clone + ' static ,
123128 {
124129 let exec = Exec :: new ( executor) ;
130+ let timer = timer. map ( |t| Timer :: new ( t) ) ;
125131 let inner = if config. is_enabled ( ) {
126132 Some ( Arc :: new ( Mutex :: new ( PoolInner {
127133 connecting : HashSet :: new ( ) ,
@@ -130,6 +136,7 @@ impl<T, K: Key> Pool<T, K> {
130136 max_idle_per_host : config. max_idle_per_host ,
131137 waiters : HashMap :: new ( ) ,
132138 exec,
139+ timer,
133140 timeout : config. idle_timeout ,
134141 } ) ) )
135142 } else {
@@ -411,31 +418,33 @@ impl<T: Poolable, K: Key> PoolInner<T, K> {
411418 self . waiters . remove ( key) ;
412419 }
413420
414- fn spawn_idle_interval ( & mut self , _pool_ref : & Arc < Mutex < PoolInner < T , K > > > ) {
415- // TODO
416- /*
417- let (dur, rx) = {
418- if self.idle_interval_ref.is_some() {
419- return;
420- }
421-
422- if let Some(dur) = self.timeout {
423- let (tx, rx) = oneshot::channel();
424- self.idle_interval_ref = Some(tx);
425- (dur, rx)
426- } else {
427- return;
428- }
421+ fn spawn_idle_interval ( & mut self , pool_ref : & Arc < Mutex < PoolInner < T , K > > > ) {
422+ if self . idle_interval_ref . is_some ( ) {
423+ return ;
424+ }
425+ let dur = if let Some ( dur) = self . timeout {
426+ dur
427+ } else {
428+ return ;
429+ } ;
430+ let timer = if let Some ( timer) = self . timer . clone ( ) {
431+ timer
432+ } else {
433+ return ;
429434 } ;
435+ let ( tx, rx) = oneshot:: channel ( ) ;
436+ self . idle_interval_ref = Some ( tx) ;
430437
431438 let interval = IdleTask {
432- interval: tokio::time::interval(dur),
439+ timer : timer. clone ( ) ,
440+ duration : dur,
441+ deadline : Instant :: now ( ) ,
442+ fut : timer. sleep_until ( Instant :: now ( ) ) , // ready at first tick
433443 pool : WeakOpt :: downgrade ( pool_ref) ,
434444 pool_drop_notifier : rx,
435445 } ;
436446
437447 self . exec . execute ( interval) ;
438- */
439448 }
440449}
441450
@@ -755,11 +764,12 @@ impl Expiration {
755764 }
756765}
757766
758- /*
759767pin_project_lite:: pin_project! {
760768 struct IdleTask <T , K : Key > {
761- #[pin]
762- interval: Interval,
769+ timer: Timer ,
770+ duration: Duration ,
771+ deadline: Instant ,
772+ fut: Pin <Box <dyn Sleep >>,
763773 pool: WeakOpt <Mutex <PoolInner <T , K >>>,
764774 // This allows the IdleTask to be notified as soon as the entire
765775 // Pool is fully dropped, and shutdown. This channel is never sent on,
@@ -784,7 +794,15 @@ impl<T: Poolable + 'static, K: Key> Future for IdleTask<T, K> {
784794 }
785795 }
786796
787- ready!(this.interval.as_mut().poll_tick(cx));
797+ ready ! ( Pin :: new( & mut this. fut) . poll( cx) ) ;
798+ // Set this task to run after the next deadline
799+ // If the poll missed the deadline by a lot, set the deadline
800+ // from the current time instead
801+ * this. deadline = * this. deadline + * this. duration ;
802+ if * this. deadline < Instant :: now ( ) - Duration :: from_millis ( 5 ) {
803+ * this. deadline = Instant :: now ( ) + * this. duration ;
804+ }
805+ * this. fut = this. timer . sleep_until ( * this. deadline ) ;
788806
789807 if let Some ( inner) = this. pool . upgrade ( ) {
790808 if let Ok ( mut inner) = inner. lock ( ) {
@@ -797,7 +815,6 @@ impl<T: Poolable + 'static, K: Key> Future for IdleTask<T, K> {
797815 }
798816 }
799817}
800- */
801818
802819impl < T > WeakOpt < T > {
803820 fn none ( ) -> Self {
@@ -823,7 +840,9 @@ mod tests {
823840 use std:: time:: Duration ;
824841
825842 use super :: { Connecting , Key , Pool , Poolable , Reservation , WeakOpt } ;
826- use crate :: rt:: TokioExecutor ;
843+ use crate :: rt:: { TokioExecutor , TokioTimer } ;
844+
845+ use crate :: common:: timer;
827846
828847 #[ derive( Clone , Debug , PartialEq , Eq , Hash ) ]
829848 struct KeyImpl ( http:: uri:: Scheme , http:: uri:: Authority ) ;
@@ -870,6 +889,7 @@ mod tests {
870889 max_idle_per_host : max_idle,
871890 } ,
872891 TokioExecutor :: new ( ) ,
892+ Option :: < timer:: Timer > :: None ,
873893 ) ;
874894 pool. no_timer ( ) ;
875895 pool
@@ -960,16 +980,14 @@ mod tests {
960980 }
961981
962982 #[ tokio:: test]
963- #[ ignore] // TODO
964983 async fn test_pool_timer_removes_expired ( ) {
965- tokio:: time:: pause ( ) ;
966-
967984 let pool = Pool :: new (
968985 super :: Config {
969986 idle_timeout : Some ( Duration :: from_millis ( 10 ) ) ,
970987 max_idle_per_host : std:: usize:: MAX ,
971988 } ,
972989 TokioExecutor :: new ( ) ,
990+ Some ( TokioTimer :: new ( ) ) ,
973991 ) ;
974992
975993 let key = host_key ( "foo" ) ;
@@ -984,7 +1002,7 @@ mod tests {
9841002 ) ;
9851003
9861004 // Let the timer tick passed the expiration...
987- tokio:: time:: advance ( Duration :: from_millis ( 30 ) ) . await ;
1005+ tokio:: time:: sleep ( Duration :: from_millis ( 30 ) ) . await ;
9881006 // Yield so the Interval can reap...
9891007 tokio:: task:: yield_now ( ) . await ;
9901008
0 commit comments