Skip to content

Commit

Permalink
feat: add yield_now
Browse files Browse the repository at this point in the history
Needed if loop doesn't yield in and only one thread it available (wasm)
  • Loading branch information
c-git committed Jun 13, 2024
1 parent b1728e0 commit 0722dc8
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 36 deletions.
14 changes: 6 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ tokio = { version = "1", default-features = false, optional = true }
# For compiling to wasm:
[target.'cfg(target_arch = "wasm32")'.dependencies]
wasm-bindgen-futures = "0.4.34"
js-sys = { version = "0.3.69", optional = true }
web-sys = { version = "0.3.69", optional = true }

[dev-dependencies]
futures = "0.3.28"
Expand All @@ -32,16 +34,12 @@ wasm-bindgen-test = "0.3.34"
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
tokio = { version = "1.27.0", default-features = false, features = ["macros", "rt-multi-thread"] }

[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
js-sys = "0.3.69"
web-sys = "0.3.69"
# Uncomment below to include example in tests (already covered by doc-test plus dedicated test)
# [[example]]
# name = "simple_fetch"
# harness = false
# test = true
[[example]]
name = "loop_yield"
required-features = ["yield_now"]

[features]
default = ["native-tokio"]
native-tokio = ["dep:tokio"]
yield_now = ["dep:js-sys", "web-sys"]
# If we add support for other runtimes we need to update CI to test each separately (rn tests all features together)
28 changes: 3 additions & 25 deletions examples/loop_yield.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ async fn common_code() -> Result<(), Box<dyn std::error::Error>> {
} else {
// Still waiting
state = State::AwaitingResponse(rx);
yield_().await;
reqwest_cross::yield_now().await;
}
}
Err(e) => {
Expand All @@ -80,33 +80,11 @@ async fn common_code() -> Result<(), Box<dyn std::error::Error>> {
}

#[cfg(all(test, not(target_arch = "wasm32")))]

mod tests {
use super::*;

#[tokio::test]
async fn test_name() {
common_code().await.unwrap();
super::common_code().await.unwrap();
}
}

/// Yield to other tasks
async fn yield_() {
#[cfg(target_arch = "wasm32")]
sleep_ms(1).await;
#[cfg(not(target_arch = "wasm32"))]
tokio::task::yield_now().await;
}

#[cfg(target_arch = "wasm32")]
// Hack to get async sleep on wasm
// Taken from https://github.com/rustwasm/wasm-bindgen/discussions/3476
async fn sleep_ms(millis: i32) {
let mut cb = |resolve: js_sys::Function, _reject: js_sys::Function| {
web_sys::window()
.unwrap()
.set_timeout_with_callback_and_timeout_and_arguments_0(&resolve, millis)
.expect("Failed to call set_timeout");
};
let p = js_sys::Promise::new(&mut cb);
wasm_bindgen_futures::JsFuture::from(p).await.unwrap();
}
8 changes: 5 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,12 @@ mod native;
#[cfg(target_arch = "wasm32")]
mod wasm;
mod wrappers;
#[cfg(feature = "yield_now")]
mod yield_;

pub use wrappers::fetch;
#[cfg(feature = "yield_now")]
pub use yield_::yield_now;

// TODO 3: Reexport the client so including reqwest directly is not necessary

// TODO 2: Create examples in the examples folder and reference them from the
// docs instead of point ppl at the tests
// TODO 3: Check output of docs
24 changes: 24 additions & 0 deletions src/yield_.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/// Attempts to provide a yield for executor currently in use.
/// There doesn't appear to be one available as yet for wasm_bindgen_futures so
/// a workaround taken from
/// https://github.com/rustwasm/wasm-bindgen/discussions/3476 is used
pub async fn yield_now() {
#[cfg(target_arch = "wasm32")]
sleep_ms(1).await;
#[cfg(not(target_arch = "wasm32"))]
tokio::task::yield_now().await;
}

#[cfg(target_arch = "wasm32")]
// Hack to get async sleep on wasm
// Taken from https://github.com/rustwasm/wasm-bindgen/discussions/3476
async fn sleep_ms(millis: i32) {
let mut cb = |resolve: js_sys::Function, _reject: js_sys::Function| {
web_sys::window()
.unwrap()
.set_timeout_with_callback_and_timeout_and_arguments_0(&resolve, millis)
.expect("Failed to call set_timeout");
};
let p = js_sys::Promise::new(&mut cb);
wasm_bindgen_futures::JsFuture::from(p).await.unwrap();
}

0 comments on commit 0722dc8

Please sign in to comment.