Skip to content

Tasks

gale_std.task wraps Elixir Task. The extern handle Task<A> is invariant, as all externally implemented capability types are. Start workers with gale_std.task_supervisor; async takes a worker with no mailbox. Like Elixir, await returns the value and exits on timeout or task failure; yield and shutdown return Option<Result<A, ExitReason>>. These operations must be called by the task owner.

module tasks
alias gale_std.task_supervisor
extern "Process.sleep" sleep(timeout: Timeout) -> :ok
pub fn ok() -> :ok {
:ok
}
pub fn hang() -> :ok {
sleep(:infinity)
}
@doc """
Runs a worker on a task supervisor and waits for `:ok`.
"""
pub fn await_ok() -> :ok {
let supervisor = supervisor(:tasks)
let work = gale_std.task_supervisor.async(supervisor, fn() => ok())
gale_std.task.await(work, 1000)
}
@doc """
Shuts down a worker that never returns.
"""
pub fn cancel_hang() -> Option<Result<:ok, gale_std.process.ExitReason>> {
let supervisor = supervisor(:tasks_hang)
let work = gale_std.task_supervisor.async(supervisor, fn() => hang())
gale_std.task.shutdown(work, :brutal_kill)
}
fn supervisor(name: Atom) -> gale_std.task_supervisor.TaskSupervisorTarget<Atom> {
let options: List<task_supervisor.TaskSupervisorOption> = [(:name, name)]
match gale_std.task_supervisor.start_link(options) {
Ok(started) -> started
Error(_) -> gale_std.task_supervisor.named(name)
}
}

Because task handles are invariant, widening their result type is rejected:

pub fn widen(
task: gale_std.task.Task<Integer>
) -> gale_std.task.Task<Integer | :unknown> {
task
}