From 54115430f5a486e8a3f2d1a3a1208d13a26b833f Mon Sep 17 00:00:00 2001 From: Filip Tibell Date: Wed, 23 Apr 2025 22:17:21 +0200 Subject: [PATCH] Migrate lune-std-task to use async-io instead of tokio for better scheduler integration + remove temp test file --- Cargo.lock | 11 ++++++----- crates/lune-std-task/Cargo.toml | 3 ++- crates/lune-std-task/src/lib.rs | 24 ++++++++++++---------- test.luau | 35 --------------------------------- 4 files changed, 22 insertions(+), 51 deletions(-) delete mode 100644 test.luau diff --git a/Cargo.lock b/Cargo.lock index b05ff44..9d7f791 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -214,9 +214,9 @@ dependencies = [ [[package]] name = "async-io" -version = "2.3.4" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" +checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" dependencies = [ "async-lock", "cfg-if 1.0.0", @@ -990,9 +990,9 @@ checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" -version = "2.3.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" dependencies = [ "fastrand", "futures-core", @@ -1743,10 +1743,11 @@ dependencies = [ name = "lune-std-task" version = "0.1.2" dependencies = [ + "async-io", + "futures-lite", "lune-utils", "mlua", "mlua-luau-scheduler", - "tokio", ] [[package]] diff --git a/crates/lune-std-task/Cargo.toml b/crates/lune-std-task/Cargo.toml index b6be857..d0332b6 100644 --- a/crates/lune-std-task/Cargo.toml +++ b/crates/lune-std-task/Cargo.toml @@ -16,6 +16,7 @@ workspace = true mlua = { version = "0.10.3", features = ["luau"] } mlua-luau-scheduler = { version = "0.0.2", path = "../mlua-luau-scheduler" } -tokio = { version = "1", default-features = false, features = ["time"] } +async-io = "2.4" +futures-lite = "2.6" lune-utils = { version = "0.1.3", path = "../lune-utils" } diff --git a/crates/lune-std-task/src/lib.rs b/crates/lune-std-task/src/lib.rs index 2e0523d..1cc56e6 100644 --- a/crates/lune-std-task/src/lib.rs +++ b/crates/lune-std-task/src/lib.rs @@ -1,15 +1,13 @@ #![allow(clippy::cargo_common_metadata)] -use std::time::Duration; +use std::time::{Duration, Instant}; + +use async_io::Timer; +use futures_lite::future::yield_now; use mlua::prelude::*; use mlua_luau_scheduler::Functions; -use tokio::{ - task::yield_now, - time::{sleep, Instant}, -}; - use lune_utils::TableBuilder; /** @@ -60,11 +58,17 @@ async fn wait(lua: Lua, secs: Option) -> LuaResult { } async fn wait_inner(_: Lua, secs: Option) -> LuaResult { + // One millisecond is a reasonable minimum sleep duration, + // anything lower than this runs the risk of completing the + // the below timer instantly, without giving control to the OS ... let duration = Duration::from_secs_f64(secs.unwrap_or_default()); - + let duration = duration.max(Duration::from_millis(1)); + // ... however, we should still _guarantee_ that whatever + // coroutine that calls this sleep function always yields, + // even if the timer is able to complete without doing so + yield_now().await; + // We may then sleep as normal let before = Instant::now(); - sleep(duration).await; - let after = Instant::now(); - + let after = Timer::after(duration).await; Ok((after - before).as_secs_f64()) } diff --git a/test.luau b/test.luau deleted file mode 100644 index e095075..0000000 --- a/test.luau +++ /dev/null @@ -1,35 +0,0 @@ -local task = require("@lune/task") - -local started = os.clock() - -local amount = 400000 -local batches = 5 -local per_batch = amount / batches - -for current = 1, batches do - local thread = coroutine.running() - - print(`Batch {current} / {batches}`) - - for i = 1, per_batch do - --print("Spawning thread #" .. i) - task.spawn(function() - print("[BEFORE] Thread number", i) - task.wait(0.1) - --_TEST_ASYNC_WORK(0.1) - print("[AFTER] Thread number", i) - if i == per_batch then - print("Last thread in batch #" .. current) - assert( - coroutine.status(thread) == "suspended", - `Thread {i} has status {coroutine.status(thread)}` - ) - task.spawn(thread) - end - end) - end - - coroutine.yield() -end -local took = os.clock() - started -print(`Spawned {amount} sleeping threads in {took}s`)