ferroid/runtime/
smol.rs

1use crate::SleepProvider;
2use core::future::Future;
3use core::{
4    pin::Pin,
5    task::{Context, Poll},
6};
7use pin_project_lite::pin_project;
8use smol::Timer;
9
10/// An implementation of [`SleepProvider`] using Smol's timer.
11///
12/// This is the default provider for use in async applications built on Smol.
13pub struct SmolSleep;
14impl SleepProvider for SmolSleep {
15    type Sleep = SmolSleepFuture;
16
17    fn sleep_for(dur: core::time::Duration) -> Self::Sleep {
18        SmolSleepFuture {
19            timer: Timer::after(dur),
20        }
21    }
22}
23
24pin_project! {
25    /// Internal future returned by [`SmolSleep::sleep_for`].
26    ///
27    /// This type wraps a [`smol::Timer`] and implements [`Future`] with `Output
28    /// = ()`, discarding the timer's `Instant` result.
29    ///
30    /// You should not construct or use this type directly. It is only used
31    /// internally by the [`SleepProvider`] implementation for the Smol runtime.
32    #[must_use = "futures do nothing unless you `.await` or poll them"]
33    pub struct SmolSleepFuture {
34        #[pin]
35        timer: Timer,
36    }
37}
38
39impl Future for SmolSleepFuture {
40    type Output = ();
41
42    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
43        match self.project().timer.poll(cx) {
44            Poll::Ready(_) => Poll::Ready(()),
45            Poll::Pending => Poll::Pending,
46        }
47    }
48}
49
50/// An implementation of [`SleepProvider`] using Smol's yield.
51///
52/// This strategy avoids timer-based delays by yielding to the scheduler
53/// immediately, which can improve responsiveness in low-concurrency scenarios.
54///
55/// However, it comes at the cost of more frequent rescheduling, which can
56/// result in tighter polling loops and increased CPU usage under load. In
57/// highly concurrent cases, a timer-based sleep (e.g., [`SmolSleep`]) is often
58/// more efficient due to reduced scheduler churn.
59pub struct SmolYield;
60impl SleepProvider for SmolYield {
61    type Sleep = smol::future::YieldNow;
62
63    fn sleep_for(_dur: core::time::Duration) -> Self::Sleep {
64        smol::future::yield_now()
65    }
66}