-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement sleep and interval for Yew Platform #2784
Merged
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
7b8480f
Rename runtime.
futursolo 50aecd6
Implement sleep and interval.
futursolo b1d9c5a
Replace sleep usage with one provided by the platform.
futursolo 89344b3
Fix imports.
futursolo 8bf99f3
Fix tests.
futursolo 68fcea7
Enable futures on gloo.
futursolo 2968aec
Always inline sleep.
futursolo 67df923
Merge branch 'master' into sleep-interval
futursolo 3193c1e
Fix tests.
futursolo 5f3b15d
Implement sleep in house.
futursolo 9d4c6d4
Remove futures feature.
futursolo 31480c7
Oops.
futursolo 4f1973c
Prevent Excessive Polling.
futursolo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
use std::future::Future; | ||
|
||
pub(crate) mod time; | ||
|
||
static NO_RUNTIME_NOTICE: &str = r#"No runtime configured for this platform, \ | ||
features that requires a runtime can't be used. \ | ||
Either compile with `target_arch = "wasm32", or enable the `tokio` feature."#; | ||
|
||
fn panic_no_runtime() -> ! { | ||
panic!("{}", NO_RUNTIME_NOTICE); | ||
} | ||
|
||
#[inline(always)] | ||
pub(super) fn spawn_local<F>(_f: F) | ||
where | ||
F: Future<Output = ()> + 'static, | ||
{ | ||
panic_no_runtime(); | ||
} | ||
|
||
#[cfg(feature = "ssr")] | ||
pub(crate) async fn run_pinned<F, Fut>(_create_task: F) -> Fut::Output | ||
where | ||
F: FnOnce() -> Fut, | ||
F: Send + 'static, | ||
Fut: Future + 'static, | ||
Fut::Output: Send + 'static, | ||
{ | ||
panic_no_runtime(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
use std::time::Duration; | ||
|
||
use futures::stream::LocalBoxStream; | ||
|
||
use super::panic_no_runtime; | ||
|
||
pub(crate) async fn sleep(_dur: Duration) { | ||
panic_no_runtime(); | ||
} | ||
|
||
pub(crate) fn interval(_dur: Duration) -> LocalBoxStream<'static, ()> { | ||
panic_no_runtime(); | ||
} |
2 changes: 2 additions & 0 deletions
2
packages/yew/src/platform/rt_tokio.rs → packages/yew/src/platform/rt_tokio/mod.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
use std::future::Future; | ||
use std::time::Duration; | ||
|
||
use futures::stream::{Stream, StreamExt}; | ||
use tokio_stream::wrappers::IntervalStream; | ||
|
||
#[inline(always)] | ||
pub(crate) fn sleep(dur: Duration) -> impl Future<Output = ()> { | ||
tokio::time::sleep(dur) | ||
} | ||
|
||
pub(crate) fn interval(dur: Duration) -> impl Stream<Item = ()> { | ||
IntervalStream::new(tokio::time::interval(dur)).then(|_| async {}) | ||
} |
2 changes: 2 additions & 0 deletions
2
packages/yew/src/platform/rt_wasm_bindgen.rs → ...s/yew/src/platform/rt_wasm_bindgen/mod.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
use std::cell::Cell; | ||
use std::future::Future; | ||
use std::pin::Pin; | ||
use std::rc::Rc; | ||
use std::task::{Context, Poll}; | ||
use std::time::Duration; | ||
|
||
use futures::stream; | ||
use futures::stream::Stream; | ||
use gloo::timers::callback::Timeout; | ||
|
||
#[inline(always)] | ||
pub(crate) fn sleep(dur: Duration) -> impl Future<Output = ()> { | ||
pub struct Sleep { | ||
inner: Option<Timeout>, | ||
dur_left: Option<u128>, | ||
timeout_registered: Rc<Cell<bool>>, | ||
} | ||
|
||
impl Future for Sleep { | ||
type Output = (); | ||
|
||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | ||
static I32_MAX_U128: u128 = 2_147_483_647; | ||
static I32_MAX_U32: u32 = 2_147_483_647; | ||
|
||
// If polling before the registered timeout is reached, return Pending. | ||
if self.timeout_registered.get() { | ||
return Poll::Pending; | ||
} | ||
|
||
// set_timeout can only accept maximum of i32, so we wrap around if it gets longer. | ||
let next_timeout = match self.dur_left.map(|m| (m, u32::try_from(m))) { | ||
Some((m_u128, Err(_))) => { | ||
self.dur_left = Some(m_u128 - I32_MAX_U128); | ||
I32_MAX_U32 | ||
} | ||
Some((m_u128, _)) if m_u128 > I32_MAX_U128 => { | ||
self.dur_left = Some(m_u128 - I32_MAX_U128); | ||
I32_MAX_U32 | ||
} | ||
Some((_, Ok(m_u32))) => { | ||
self.dur_left = None; | ||
m_u32 | ||
} | ||
None => return Poll::Ready(()), | ||
}; | ||
|
||
let waker = cx.waker().clone(); | ||
self.timeout_registered.set(true); | ||
let timeout_registered = self.timeout_registered.clone(); | ||
|
||
self.inner = Some(Timeout::new(next_timeout, move || { | ||
timeout_registered.set(false); | ||
waker.wake(); | ||
})); | ||
|
||
Poll::Pending | ||
} | ||
} | ||
|
||
Sleep { | ||
inner: None, | ||
dur_left: Some(dur.as_millis()), | ||
timeout_registered: Cell::new(false).into(), | ||
} | ||
} | ||
|
||
pub(crate) fn interval(dur: Duration) -> impl Stream<Item = ()> { | ||
stream::unfold((), move |_: ()| async move { | ||
sleep(dur).await; | ||
|
||
Some(((), ())) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
//! Utilities for bridging time and tasks. | ||
|
||
use std::future::Future; | ||
use std::time::Duration; | ||
|
||
use futures::stream::Stream; | ||
|
||
use crate::platform::imp::time as imp; | ||
|
||
/// Waits until duration has elapsed. | ||
#[inline(always)] | ||
pub fn sleep(dur: Duration) -> impl Future<Output = ()> { | ||
imp::sleep(dur) | ||
} | ||
|
||
/// Creates a Stream that yields an item after every period has elapsed. | ||
#[inline(always)] | ||
pub fn interval(period: Duration) -> impl Stream<Item = ()> { | ||
imp::interval(period) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why implement it here? What's wrong with the
gloo
implementation? If there's a bug or improvement to be made, I think we should fix it there.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See: rustwasm/gloo#121
The difficulty of patching it with gloo is due to its callback-first API.
Patching
gloo_timers
requires recursively callingsetTimeout
, which is difficult to implement due to ownership rules.It gets worse with
Interval
, as we have to implement it with a series of patchedTimeout
than usingsetInterval
.At that time, it's simply easier to implement Interval with
Stream
and make the API future-first.However, this is a bigger change than it is needed to patch around this behaviour.
I patched it here because we have a future-first API and this have very little impact on code size.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense. I'm not sure who actually is using a timer that's over 24 days long but I'm fine with merging this change.
Patching it in Gloo would be needless (and not small) breaking change