Skip to content

Commit

Permalink
Merge pull request #418 from cunarist/allow-choosing-async-runtime
Browse files Browse the repository at this point in the history
Allow choosing async runtime
  • Loading branch information
temeddix authored Sep 9, 2024
2 parents 731fa27 + 42f0a8b commit 2864053
Show file tree
Hide file tree
Showing 15 changed files with 230 additions and 201 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/quality_control.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ jobs:
# That's why we are checking only the library crate.
- name: Check for errors with all features enabled
working-directory: rust_crate/
run: cargo clippy --all-features
run: |
cargo clippy --all-features
cargo clippy --all-features --target wasm32-unknown-unknown
- name: Analyze code
run: |
Expand Down
1 change: 0 additions & 1 deletion documentation/docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,5 @@ Customizing the behavior of the Rinf crate is possible through its crate feature
rinf = { version = "0.0.0", features = ["feature-name"] }
```

- `rt-multi-thread`: Starts a worker thread for each CPU core available on the system within the `tokio` runtime by enabling its `rt-multi-thread` feature. By default, the `tokio` runtime uses only one thread. Enabling this feature allows the `tokio` runtime to utilize all the cores on your computer. This feature does not affect applications on the web platform.
- `show-backtrace`: Prints the full backtrace in the CLI when a panic occurs in debug mode. In general, backtrace is not very helpful when debugging async apps, so consider using [`tracing`](https://crates.io/crates/tracing) for logging purposes. Note that this feature does not affect debugging on the web platform.
- `bevy`: Implements the `Event` trait from `bevy_ecs` for `DartSignal`, allowing Bevy's entity component system to listen for events from Dart.
9 changes: 7 additions & 2 deletions flutter_ffi_plugin/example/native/hub/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ crate-type = ["lib", "cdylib", "staticlib"]
[dependencies]
rinf = "6.15.0"
prost = "0.13.0"
tokio = { version = "1", features = ["rt", "sync", "time"] }
tokio_with_wasm = { version = "0.6.3", features = ["rt", "sync", "time"] }
tokio = { version = "1", features = ["rt", "sync", "time", "macros"] }
tokio_with_wasm = { version = "0.7.1", features = [
"rt",
"sync",
"time",
"macros",
] }
wasm-bindgen = "0.2.93"
sample_crate = { path = "../sample_crate" }
12 changes: 11 additions & 1 deletion flutter_ffi_plugin/example/native/hub/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ mod messages;
mod sample_functions;

// use tokio;
use common::*;
use tokio_with_wasm::alias as tokio;

rinf::write_interface!();
Expand All @@ -15,8 +16,17 @@ rinf::write_interface!();
// such as `tokio::fs::File::open`.
// If you really need to use blocking code,
// use `tokio::task::spawn_blocking`.
async fn main() {
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<()> {
// Spawn the concurrent tasks.
tokio::spawn(sample_functions::tell_numbers());
tokio::spawn(sample_functions::stream_fractal());
tokio::spawn(sample_functions::run_debug_tests());

// Get the shutdown receiver from Rinf.
// This receiver will await a signal from Dart shutdown.
let shutdown_receiver = rinf::get_shutdown_receiver()?;
shutdown_receiver.await;

Ok(())
}
14 changes: 5 additions & 9 deletions flutter_ffi_plugin/example/native/hub/src/sample_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,19 @@ use crate::messages;
use crate::tokio;
use rinf::debug_print;
use std::time::Duration;
use tokio::sync::Mutex;

// Using the `cfg` macro enables conditional statement.
#[cfg(debug_assertions)]
const IS_DEBUG_MODE: bool = true;
static IS_DEBUG_MODE: bool = true;
#[cfg(not(debug_assertions))]
const IS_DEBUG_MODE: bool = false;

// This is one of the ways to keep a global mutable state in Rust.
// You can also use `tokio::sync::RwLock` or `std::lazy::LazyLock`.
static VECTOR: Mutex<Vec<bool>> = Mutex::const_new(Vec::new());
static IS_DEBUG_MODE: bool = false;

// Business logic for the counter widget.
pub async fn tell_numbers() -> Result<()> {
use messages::counter_number::*;

let mut vector = Vec::new();

// Stream getter is generated from a marked Protobuf message.
let receiver = SampleNumberInput::get_dart_signal_receiver()?;
while let Some(dart_signal) = receiver.recv().await {
Expand All @@ -30,8 +27,7 @@ pub async fn tell_numbers() -> Result<()> {
let letter = number_input.letter;
debug_print!("{letter}");

// Use the global state and perform a simple calculation.
let mut vector = VECTOR.lock().await;
// Perform a simple calculation.
vector.push(true);
let current_number = (vector.len() as i32) * 7;

Expand Down
4 changes: 2 additions & 2 deletions flutter_ffi_plugin/template/native/hub/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ crate-type = ["lib", "cdylib", "staticlib"]
[dependencies]
rinf = "6.15.0"
prost = "0.12.6"
tokio = { version = "1", features = ["rt"] }
tokio = { version = "1", features = ["rt", "macros"] }

# Uncomment below to target the web.
# tokio_with_wasm = { version = "0.6.0", features = ["rt"] }
# tokio_with_wasm = { version = "0.6.0", features = ["rt", "macros"] }
# wasm-bindgen = "0.2.92"
14 changes: 13 additions & 1 deletion flutter_ffi_plugin/template/native/hub/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,31 @@ rinf::write_interface!();
// such as `tokio::fs::File::open`.
// If you really need to use blocking code,
// use `tokio::task::spawn_blocking`.
async fn main() {
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<()> {
// Spawn the concurrent tasks.
tokio::spawn(communicate());

// Get the shutdown receiver from Rinf.
// This receiver will await a signal from Dart shutdown.
let shutdown_receiver = rinf::get_shutdown_receiver()?;
shutdown_receiver.await;

Ok(())
}

async fn communicate() -> Result<()> {
use messages::basic::*;

// Send signals to Dart like below.
SmallNumber { number: 7 }.send_signal_to_dart();

// Get receivers that listen to Dart signals like below.
let receiver = SmallText::get_dart_signal_receiver()?;
while let Some(dart_signal) = receiver.recv().await {
let message: SmallText = dart_signal.message;
rinf::debug_print!("{message:?}");
}

Ok(())
}
2 changes: 0 additions & 2 deletions rust_crate/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ documentation = "https://rinf.cunarist.com"
rust-version = "1.70"

[features]
rt-multi-thread = ["tokio/rt-multi-thread"]
show-backtrace = ["backtrace"]
bevy = ["bevy_ecs"]

Expand All @@ -23,7 +22,6 @@ protoc-prebuilt = "0.3.0"
home = "0.5.9"
which = "6.0.0"
allo-isolate = "0.1.25"
tokio = { version = "1", features = ["rt"] }

[target.'cfg(target_family = "wasm")'.dependencies]
js-sys = "0.3.69"
Expand Down
10 changes: 7 additions & 3 deletions rust_crate/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use std::fmt;
pub enum RinfError {
LockDartIsolate,
NoDartIsolate,
BuildRuntime,
LockShutdownReceiver,
NoShutdownReceiver,
LockMessageChannel,
BrokenMessageChannel,
ClosedMessageChannel,
Expand All @@ -24,8 +25,11 @@ impl fmt::Display for RinfError {
RinfError::NoDartIsolate => {
write!(f, "Dart isolate for Rust signals was not created.")
}
RinfError::BuildRuntime => {
write!(f, "Could not build the tokio runtime.")
RinfError::LockShutdownReceiver => {
write!(f, "Could not acquire the shutdown receiver lock.")
}
RinfError::NoShutdownReceiver => {
write!(f, "Shutdown receiver was not created.")
}
RinfError::LockMessageChannel => {
write!(f, "Could not acquire the message channel lock.")
Expand Down
14 changes: 6 additions & 8 deletions rust_crate/src/interface.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::error::RinfError;
use std::future::Future;

#[cfg(not(target_family = "wasm"))]
use super::interface_os::*;
Expand Down Expand Up @@ -27,23 +26,22 @@ pub struct DartSignal<T> {
/// the `Runtime` object itself might be moved between threads,
/// along with all the tasks it manages.
#[cfg(not(target_family = "wasm"))]
pub fn start_rust_logic<F, T>(main_future: F) -> Result<(), RinfError>
pub fn start_rust_logic<F, T>(main_fn: F) -> Result<(), RinfError>
where
F: Future<Output = T> + Send + 'static,
T: Send + 'static,
F: Fn() -> T + Send + 'static,
{
start_rust_logic_real(main_future)
start_rust_logic_real(main_fn)
}

/// Runs the async main function in Rust.
/// On the web, futures usually don't implement the `Send` trait
/// because JavaScript environment is fundamentally single-threaded.
#[cfg(target_family = "wasm")]
pub fn start_rust_logic<F>(main_future: F) -> Result<(), RinfError>
pub fn start_rust_logic<F, T>(main_fn: F) -> Result<(), RinfError>
where
F: Future + 'static,
F: Fn() -> T + 'static,
{
start_rust_logic_real(main_future)
start_rust_logic_real(main_fn)
}

/// Send a signal to Dart.
Expand Down
Loading

0 comments on commit 2864053

Please sign in to comment.