thread - pannous/warp GitHub Wiki

async threading follows the go/zig path to be invoked on the caller side.
On the callee side, functions are agnostic whether they are called in a synchronous or asynchronous way.
This way function coloring and the huge syntactic and semantic async/await overhead mess is avoided:

shared done = false
go { sleep 1s; print "second"; done = true }
print "first"
last = after done return "third"
print await last or "no third"

prints first, second, third. A task works on copies (task): only shared values (and shared arrays) are seen by every task (decision P106), so done is declared shared; after on a variable that is not shared is an error. cancel last stops the waiting task, and await last or "no third" then gives the fallback:

shared done = false
last = after done return "third"
cancel last
print await last or "no third"

The after keyword creates an (aspect oriented) implicit signal listener on the variable done: a task that waits until the condition holds, then gives its value. (Write after (n == 5) return x with parentheses for now.)

Concurrent or asynchronous tasks can be paused, stopped, etc

Avoiding Function coloring: https://news.ycombinator.com/item?id=28657358

Prior art: Bend/HVM

The parallel let comes from Bend 2 (HigherOrderCO, Victor Taelin):

a b = sum(d - 1) sum(d - 1)   # Bend

The parallel let is written without let: names on the left, as many calls on the right. let a b = … is not it: let before two names defines a function a of b, so it fails with "let needs a value".

runs both calls at once: the first as a task, the second on the current thread, then waits for the first. As in Bend's runtime BendRT, a fork met while all cores are busy runs as a plain call, so a recursive split forks only its top levels. Bend's earlier runtime HVM (interaction nets) is not used: Bend itself left it. Ideas taken, no code copied.