4.2. Processes
Introduction to Letlang's concurrency model
A Letlang process is a green-thread running a single function to completion (or
until it crashes). Every process has a unique identifier (a pid
).
Functions have no color, any function can be run in a process. It is up to the caller to decide if a function should be run in a new process or not.
When spawning a new process, its pid is returned, allowing the caller to interact with it.
Example:
func task() -> @ok {
# do stuff
@ok;
}
func main() -> @ok {
(@ok, proc_id) := spawn task();
# do stuff
@ok;
}
In every process, if a side effect (or an exception) is not intercepted/caught
with a do{}
expression (see chapter 3), it bubbles up to
the Letlang runtime.
Example:
func task() -> @ok {
throw @oops;
}
func main() -> @ok {
@ok := do {
task(); # the exception is caught
}
catch @oops {
@ok;
};
spawn task(); # the exception will bubble up to the runtime
# do stuff
@ok;
}
When an exception or an unknown effect bubbles up to the runtime, the process crashes, but not the whole program.
When starting, Letlang starts a node which listens for commands:
When the node spawns a process, it creates a new PID and a mailbox to exchange signals. If the process terminates normally, or panics, it is caught and the node is notified.
NB: The
main
function is automatically spawned as a new process (the first one).
When every process are terminated, the node stops and the program terminates.
This means that the main
function can terminate before the tasks it spawned,
it won’t stop the program.