teksilo-async 0.9.0

Optional main-thread async executor for Teksilo — spawn_local / spawn_blocking driven by the app event loop.
Documentation

teksilo-async — optional main-thread async executor for Teksilo

Teksilo keeps the view layer synchronous: "async is the backend's concern." Most background→UI flows are best served by the reactive data path (ctx.subscribe_event(...) + Signal::set). This crate is the opt-in escape hatch for the cases that want imperative async — writing linear async / .await inside a handler, sequencing several awaits in one place.

use teksilo_async::{TeksiloAppBuilderAsyncExt, EventContextAsyncExt, spawn_blocking};

TeksiloAppBuilder::new().install_async() /* ... */ .run();

// inside a handler:
let status = self.status.clone();           // Signal<Status> (Rc clone)
ctx.spawn_local(async move {
    status.set(Status::Loading);
    let bytes = spawn_blocking(move || std::fs::read(path)).await;
    status.set(Status::from(bytes));         // resume on the UI thread → set Signal
})
.detach();

Model

  • The executor is single-threaded and !Send; spawn_local futures live on the UI thread and capture Rc-based Signals, mutating them on resume. There is no EventContext after .await (it is borrow-transient), so UI updates flow through owned handles (Signals) — the reactive model.
  • For a one-shot ambient op after the work finishes (open_window, send_intent, …), spawn_local_with delivers the result to a callback with a fresh EventContext.
  • [spawn_blocking] offloads blocking work to an OS thread and awaits the result — no async runtime required.

The executor is driven once per event-loop turn via the async-agnostic on_loop_tick hook; it sleeps (zero idle CPU) until a task is woken, including from a spawn_blocking worker thread.

teksilo-tokio / teksilo-async-std build on this crate to add reactor support so native-ecosystem futures (tokio::time, sockets, reqwest, …) can be .awaited directly in UI code.