miso

Native (mobile)

Effects, subscriptions and threads

Because an IO closure can't cross the thread boundary (only JSON-serialised actions can), cross-thread work is expressed as dispatching an action to the thread that should handle it. Two combinators do this:

runOnBG action
run action's update on the background thread (BTS). Used by a main-thread event handler that needs to change shared state, since the BTS solely owns the model.
runOnMain action
run action's update on the main thread (MTS). Used by a BTS effect that needs an imperative main-thread operation (see Miso.Native.MainThread).

Each ships only the given action to the target thread (or dispatches it locally when already there), where its update runs exactly once. Sibling effects in the current update are unaffected, and nothing is double-executed. Off the native runtime both are an ordinary local dispatch, equivalent to issue.

Subscriptions and threads

A Sub is dynamic — it is just a Sink action -> IO () run in a forked thread — and a component's subs are started on every thread it mounts on. So a sub runs on both the BTS and the MTS (once each), and each copy dispatches into its own thread's scheduler.

Because a sub is ordinary runtime IO — unlike a static event handler, whose thread is fixed at compile time — it selects its own thread at runtime with the mts / bts booleans. This is the dynamic analogue of a handler's *Main variant:

-- background-only: open the socket once, feed the model
wsSub sink = when bts (websocketConnect "wss://…" sink)

-- main-thread-only: drive an imperative animation
animSub _ = when mts (eachFrame step)