Skip to content

Commit 808da8c

Browse files
authored
refactor(pool): simplify idle task using async/await (#812)
1 parent f5817c6 commit 808da8c

2 files changed

Lines changed: 32 additions & 46 deletions

File tree

src/core/client/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ where
649649
// Errors are sent via err_tx to ensure they can be checked if the sender (tx) fails.
650650
executor.execute(
651651
conn.with_upgrades()
652-
.map_err(|e| {
652+
.map_err(|e| {
653653
// Log the connection error at debug level for diagnostic purposes.
654654
debug!("client connection error: {:?}", e);
655655
// Log that the error is being sent to the error channel.

src/core/client/pool.rs

Lines changed: 31 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use crate::{
2323
exec::{self, Exec},
2424
timer::Timer,
2525
},
26-
rt::{Sleep, Timer as _},
26+
rt::Timer as _,
2727
},
2828
sync::Mutex,
2929
};
@@ -415,13 +415,11 @@ impl<T: Poolable, K: Key> PoolInner<T, K> {
415415
let interval = IdleTask {
416416
timer: timer.clone(),
417417
duration: dur,
418-
deadline: Instant::now(),
419-
fut: timer.sleep_until(Instant::now()), // ready at first tick
420418
pool: WeakOpt::downgrade(pool_ref),
421419
pool_drop_notifier: rx,
422420
};
423421

424-
self.exec.execute(interval);
422+
self.exec.execute(interval.run());
425423
}
426424
}
427425

@@ -744,55 +742,43 @@ impl Expiration {
744742
}
745743
}
746744

747-
pin_project_lite::pin_project! {
748-
struct IdleTask<T, K: Key> {
749-
timer: Timer,
750-
duration: Duration,
751-
deadline: Instant,
752-
fut: Pin<Box<dyn Sleep>>,
753-
pool: WeakOpt<Mutex<PoolInner<T, K>>>,
754-
// This allows the IdleTask to be notified as soon as the entire
755-
// Pool is fully dropped, and shutdown. This channel is never sent on,
756-
// but Err(Canceled) will be received when the Pool is dropped.
757-
#[pin]
758-
pool_drop_notifier: oneshot::Receiver<Infallible>,
759-
}
745+
struct IdleTask<T, K: Key> {
746+
timer: Timer,
747+
duration: Duration,
748+
pool: WeakOpt<Mutex<PoolInner<T, K>>>,
749+
// This allows the IdleTask to be notified as soon as the entire
750+
// Pool is fully dropped, and shutdown. This channel is never sent on,
751+
// but Err(Canceled) will be received when the Pool is dropped.
752+
pool_drop_notifier: oneshot::Receiver<Infallible>,
760753
}
761754

762-
impl<T: Poolable + 'static, K: Key> Future for IdleTask<T, K> {
763-
type Output = ();
755+
impl<T: Poolable + 'static, K: Key> IdleTask<T, K> {
756+
async fn run(self) {
757+
use futures_util::future;
764758

765-
fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
766-
let mut this = self.project();
759+
let mut sleep = self.timer.sleep_until(Instant::now() + self.duration);
760+
let mut on_pool_drop = self.pool_drop_notifier;
767761
loop {
768-
match this.pool_drop_notifier.as_mut().poll(cx) {
769-
Poll::Ready(Ok(n)) => match n {},
770-
Poll::Pending => (),
771-
Poll::Ready(Err(_canceled)) => {
772-
trace!("pool closed, canceling idle interval");
773-
return Poll::Ready(());
762+
match future::select(&mut on_pool_drop, &mut sleep).await {
763+
future::Either::Left(_) => {
764+
// pool dropped, bah-bye
765+
break;
774766
}
775-
}
776-
777-
ready!(Pin::new(&mut this.fut).poll(cx));
778-
// Set this task to run after the next deadline
779-
// If the poll missed the deadline by a lot, set the deadline
780-
// from the current time instead
781-
*this.deadline += *this.duration;
782-
if *this.deadline < Instant::now() - Duration::from_millis(5) {
783-
*this.deadline = Instant::now() + *this.duration;
784-
}
785-
*this.fut = this.timer.sleep_until(*this.deadline);
767+
future::Either::Right(((), _)) => {
768+
if let Some(inner) = self.pool.upgrade() {
769+
let mut inner = inner.lock();
770+
trace!("idle interval checking for expired");
771+
inner.clear_expired();
772+
drop(inner);
773+
}
786774

787-
if let Some(inner) = this.pool.upgrade() {
788-
let mut inner = inner.lock();
789-
inner.clear_expired();
790-
drop(inner);
791-
trace!("idle interval checking for expired");
792-
continue;
775+
let deadline = Instant::now() + self.duration;
776+
self.timer.reset(&mut sleep, deadline);
777+
}
793778
}
794-
return Poll::Ready(());
795779
}
780+
781+
trace!("pool closed, canceling idle interval");
796782
}
797783
}
798784

0 commit comments

Comments
 (0)