| Crates.io | native-executor |
| lib.rs | native-executor |
| version | 0.7.0 |
| created_at | 2025-08-31 14:09:59.976816+00 |
| updated_at | 2025-12-05 11:45:01.998664+00 |
| description | Platform-native async task executor |
| homepage | |
| repository | https://github.com/waterui/native-executor |
| max_upload_size | |
| id | 1818587 |
| size | 88,085 |
Platform-native async task executor that leverages OS event loops (GCD, GDK) for optimal performance.
use native_executor::{spawn_local, timer::Timer};
use std::time::Duration;
// Spawn a task with default priority
let handle = spawn_local(async {
println!("Starting async task");
Timer::after(Duration::from_secs(1)).await;
println!("Task completed after 1 second");
});
// Keep the task alive: awaiting is structured; detach for fire-and-forget.
handle.detach();
// Keep the main thread alive to allow tasks to complete
std::thread::sleep(Duration::from_secs(2));
All spawn* functions return AsyncTask handles that own the task lifecycle. Dropping the
handle without calling .await or .detach() cancels the task immediately. Awaiting the
handle gives structured shutdown and propagates panics; detach() opts out and lets the task
run to completion in the background when you truly need fire-and-forget behavior.
use native_executor::{spawn, spawn_local, spawn_main, spawn_with_priority, Priority};
spawn(async { /* default priority */ });
spawn_local(async { /* non-Send, main thread */ });
spawn_main(async { /* Send, main thread */ });
spawn_with_priority(async { /* background work */ }, Priority::Background);
use native_executor::timer::{Timer, sleep};
use std::time::Duration;
async {
Timer::after(Duration::from_millis(100)).await; // Precise timing
Timer::after_secs(2).await; // Convenience method
sleep(1).await; // Simple sleep
};
use native_executor::mailbox::Mailbox;
use std::{cell::RefCell, collections::HashMap};
let mailbox = Mailbox::main(RefCell::new(HashMap::<String, i32>::new()));
// Send fire-and-forget updates
mailbox.handle(|map| {
map.borrow_mut().insert("key".to_string(), 42);
});
// Cross-thread with main-thread execution
let main_val = MainValue::new(String::from("UI data"));
async {
let len = main_val.handle(|s| s.len()).await;
};
Current: Apple platforms (macOS, iOS, tvOS, watchOS) via Grand Central Dispatch, Android (native worker queues)
Planned: Linux (GDK)
Unsupported platforms fail at compile-time with clear error messages.
The optional polyfill feature (enabled by default) provides a simulated
executor for targets without a native implementation. Its behavior is as
follows:
wasm32 targets the feature is a no-op – the native
executors and timers always take precedence.polyfill feature is
enabled. Disabling it makes the lack of a native executor a hard error.native_executor::polyfill::start_main_executor() on a
dedicated thread before using spawn_main or spawn_local.Example setup for unsupported targets:
#[cfg(all(feature = "polyfill", not(any(target_vendor = "apple", target_arch = "wasm32", target_os = "android"))))]
std::thread::spawn(|| native_executor::polyfill::start_main_executor());
cargo run --example simple_task # Basic spawning
cargo run --example priority # Priority control
cargo run --example timers # High-precision timing
cargo run --example main_thread # Main thread execution
cargo run --example local_value # Thread-safe containers
This project is licensed under the MIT License.