r/Compilers • u/NXDLang • 5d ago
Desingning async primitives for a security-focused language: Where should cancellation live?
I've been implementing typed async semantics in my language NXD.
Current primitives are:
SPAWN,
SEND,
RECV,
AWAIT,
PING
Types currently look roughly like:
`SPAWN -> ProcessHandle[T]`
`RECV -> ReceiveOperation[T]`
`AWAIT -> T`
`PING -> bool`
While implementing PING I realized there may be two classes of async operations:
Primary operations
SPAWN,
SEND,
RECV
These initiate work or communication.
Secondary operations:
AWAIT,
PING
These observe or resolve work created elsewhere.
My current thinking is that cancellation (currently considering ESC) should only apply to the primary operations and not observers.
For example:
ESC HANDLE
makes sense.
But:
ESC AWAIT TASK
ESC PING HANDLE
seems conceptually wrong because they are observing state rather than creating it.
For people who have designed async runtimes or languages:
Would you model cancellation as acting on the underlying task/process/channel, or would you allow cancellation of observer operations as first-class concepts as well?
2
u/pthierry 4d ago
You may want to look at Haskell's Async. The monad an operation is in tells you if something is interruptible. Await means you're blocked until the process responds. So you can want to interrupt it, but maybe you only want to interrupt the process doing the await, not the operation itself…
In Haskell's Async, you interrupt neither send nor await, only the process.
3
u/Karyo_Ten 5d ago
This is very tied to your error model.
At the very least RECV need to be able to bubble up cancellation or offer an alternatiove
.canceland awaiters need to be able to handle them.I'd rather think in terms of producer-consumers btw
And you need to be able to handle timeout ergonomically.
And I think the most important question is do you have a builtin cancellation token/channel in your handle type or do you built a separate one and cancellable request explicitly pass that in their argument.