hxn

TUTORIAL / 05

Work with asynchronous results

Await a future, read a stream and update a reactive value from Rust.

1. Await one result

The primes example returns a future from Rust. The Haxe caller can await its value or register a handler.

lib.rs · excerpt
pub fn count(limit: i32) -> Result<Future<i32>, &'static str> {
    if limit < 0 {
        return Err("a negative limit");
    }
    Ok(spawn_blocking(move || {
        let count = (2..limit).filter(|number| is_prime(*number)).count();
        Ok::<_, Failure>(count as i32)
    }))
}
Main.hx · excerpt
var count = Primes.count(100000).await();
Sys.println('$count primes below 100000');

await() waits on this thread. For event-loop delivery, use Primes.count(1000).then(count -> Sys.println(count)). The handler runs on the Haxe delivery thread. spawn_blocking uses a native worker thread; on threadless builds it runs before returning. Use spawn or stepped for cooperative work.

2. Read every item

Main.hx · excerpt
var found = [for (prime in Primes.below(30)) prime];
Sys.println(found.join(" "));
Prime stream output
2 3 5 7 11 13 17 19 23 29

Iteration reads items in order. The stream ends when Rust drops its last sender. Use listen for event-loop delivery; a stream’s failure is delivered after earlier items.

3. Follow the latest value

The thermostat example publishes a Rust signal. Haxe derives a value from it and controls delivery explicitly:

lib.rs · excerpt
pub fn turn(&mut self, degrees: f64) -> f64 {
    self.degrees += degrees;
    self.source.set(self.degrees);
    self.degrees
}
Main.hx · excerpt
hxn.Loop.manual = true;

var thermostat = new Thermostat(20);
var target = thermostat.target();

// Derived from the signal, and recomputed when it changes.
var state = new hxn.Computed(() -> target.value > 21 ? "heating" : "idle");
// Runs now, and again whenever anything it read has changed.
hxn.Reactive.effect(() -> Sys.println('set to ${target.value}: ${state.value}'));

thermostat.turn(1.5);
hxn.Loop.sync();

// Two changes before a delivery are delivered as one: a signal
// reports only its latest value.
thermostat.turn(1);
thermostat.turn(-0.5);
hxn.Loop.sync();
Thermostat output
set to 20: idle
set to 21.5: heating
set to 22: heating

A signal delivers the latest state; the two final turns produce one update. Computed tracks the values it reads, and Reactive.effect reruns when they change. Manual loops call Loop.sync(); otherwise hxn uses the Haxe event loop.

Run the examples

From the repository root, run the complete example:

Run primes
cd examples/primes
hxn run hl

Full Rust and Haxe source ↗ · Use hxn run cpp for hxcpp.

For the signal example, return to the repository root and run cd examples/thermostat, then hxn run hl.