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}