Skip to content

Commit

Permalink
Merge pull request #372 from cunarist/single-threaded-runtime
Browse files Browse the repository at this point in the history
Optional multi-threaded runtime
  • Loading branch information
temeddix committed Jun 15, 2024
2 parents 0e328c9 + 4cba370 commit c3c5243
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 11 deletions.
12 changes: 11 additions & 1 deletion documentation/docs/configuration.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Configuration

You can customize some Rinf behaviors by configuring the `pubspec.yaml` file. Rinf will change its behaviors by reading the fields below. All fields are optional and it's not necessary to write them.
## 📋 YAML File

You can customize the behavior of Rinf CLI commands by configuring the `pubspec.yaml` file. All fields are optional and it's not necessary to write them.

```yaml title="pubspec.yaml"
rinf:
Expand All @@ -16,3 +18,11 @@ You can check the current configuration status by running the command below in t
```bash title="CLI"
rinf config
```

## 📦 Crate Features

```toml title="native/hub/Cargo.toml"
rinf = { version = "0.0.0", features = ["feature-name"] }
```

- `multi-worker`: Starts a worker thread for each CPU core available on the system within the `tokio` runtime. 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.
2 changes: 1 addition & 1 deletion documentation/docs/frequently-asked-questions.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ android {

### How does concurrency work under the hood?

On native platforms, Dart runs in a single thread as usual, while Rust utilizes the async `tokio` runtime to take advantage of all cores on the computer, allowing async tasks to run efficiently within that runtime.
On native platforms, Dart runs in the main thread, while Rust utilizes the async `tokio` runtime, allowing async tasks to run efficiently within a separate thread.

On the web, Dart and Rust both run inside JavaScript's async event loop in the main thread, with Rust `Future`s being converted into JavaScript `Promise`s internally. This is a necessary constraint because [webassembly component proposal](https://github.com/WebAssembly/proposals) is not stabilized as of February 2024.

Expand Down
2 changes: 1 addition & 1 deletion flutter_ffi_plugin/example/native/hub/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ crate-type = ["lib", "cdylib", "staticlib"]
rinf = "6.12.1"
prost = "0.12.6"
tokio = { version = "1", features = ["rt", "sync", "macros", "time"] }
tokio_with_wasm = { version = "0.5.3", features = [
tokio_with_wasm = { version = "0.6.1", features = [
"rt",
"sync",
"macros",
Expand Down
2 changes: 1 addition & 1 deletion flutter_ffi_plugin/template/native/hub/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ prost = "0.12.6"
tokio = { version = "1", features = ["sync"] }

# Uncomment below to target the web.
# tokio_with_wasm = { version = "0.5.3", features = ["sync"] }
# tokio_with_wasm = { version = "0.6.0", features = ["sync"] }
# wasm-bindgen = "0.2.92"
3 changes: 3 additions & 0 deletions rust_crate/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ repository = "https://github.com/cunarist/rinf"
documentation = "https://rinf.cunarist.com"
rust-version = "1.70"

[features]
multi-worker = []

[target.'cfg(not(target_family = "wasm"))'.dependencies]
os-thread-local = "0.1.3"
backtrace = "0.3.69"
Expand Down
21 changes: 19 additions & 2 deletions rust_crate/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,27 @@ pub struct DartSignal<T> {
pub binary: Vec<u8>,
}

/// Runs the main function in Rust.
/// Runs the async main function in Rust.
/// On native platforms, futures usually implement the `Send` trait
/// to be safely sent between threads.
/// Even in a single-threaded (current-thread) runtime,
/// 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>(main_future: F) -> Result<()>
where
F: Future + Send + 'static,
{
start_rust_logic_real(main_future)
}

/// 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<()>
where
F: Future<Output = ()> + Send + 'static,
F: Future + 'static,
{
start_rust_logic_real(main_future)
}
Expand Down
16 changes: 13 additions & 3 deletions rust_crate/src/interface_os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ static TOKIO_RUNTIME: TokioRuntime = OnceLock::new();

pub fn start_rust_logic_real<F>(main_future: F) -> Result<()>
where
F: Future<Output = ()> + Send + 'static,
F: Future + Send + 'static,
{
// Enable backtrace output for panics.
#[cfg(debug_assertions)]
Expand All @@ -42,9 +42,19 @@ where
}));
}

// Run the main function.
// Build the tokio runtime.
#[cfg(not(feature = "multi-worker"))]
let tokio_runtime = Builder::new_multi_thread()
.worker_threads(1)
.enable_all()
.build()?;
#[cfg(feature = "multi-worker")]
let tokio_runtime = Builder::new_multi_thread().enable_all().build()?;
tokio_runtime.spawn(main_future);

// Run the main function.
tokio_runtime.spawn(async {
main_future.await;
});
TOKIO_RUNTIME
.get_or_init(|| ThreadLocal::new(|| RefCell::new(None)))
.with(move |cell| {
Expand Down
6 changes: 4 additions & 2 deletions rust_crate/src/interface_web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use wasm_bindgen_futures::spawn_local;

pub fn start_rust_logic_real<F>(main_future: F) -> Result<()>
where
F: Future<Output = ()> + Send + 'static,
F: Future + 'static,
{
// Add kind description for panics.
#[cfg(debug_assertions)]
Expand All @@ -17,7 +17,9 @@ where
}

// Run the main function.
spawn_local(main_future);
spawn_local(async {
main_future.await;
});

Ok(())
}
Expand Down

0 comments on commit c3c5243

Please sign in to comment.