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}