Skuld.Fiber (skuld v0.26.0)

View Source

Cooperative fiber primitive for the FiberPool scheduler.

A Fiber wraps a computation that can be run incrementally, suspended when it yields, and resumed with a value. This is the fundamental building block for cooperative concurrency in Skuld.

Sum Type

A fiber is always exactly one of these states — no status atom, no nil fields:

  • %Fiber.Pending{id, computation, env} — ready to start
  • %Fiber.InternalSuspended{id, k, suspend, env} — suspended, needs scheduler
  • %Fiber.ExternalSuspended{id, k, env} — suspended, external callback
  • %Fiber.Completed{id, result, env} — finished successfully
  • %Fiber.Errored{id, error, env} — finished with error
  • %Fiber.Cancelled{id, reason, env} — cancelled before completion

Lifecycle

  1. Create with new/2 — returns %Pending{}
  2. Run with run_until_suspend/1 — returns %Completed{}, %InternalSuspended{}, %ExternalSuspended{}, or %Errored{}
  3. Resume with resume/2 — suspended fiber runs again until completion/suspension/error
  4. Cancel with cancel/2 — invokes leave_scope cleanup, returns %Cancelled{}

Usage

Fibers are typically managed by a FiberPool, not used directly. The FiberPool scheduler handles running fibers, tracking suspensions, and resuming when results are available.

Summary

Types

t()

A fiber in any state.

Functions

Cancel a fiber, invoking leave_scope cleanup for suspended fibers.

Create a new fiber from a computation.

Resume a suspended fiber with a value.

Run a pending fiber until it completes, suspends, or errors.

Check if a fiber is in a terminal state (completed, cancelled, or errored).

Types

t()

A fiber in any state.

Callers pattern-match on the struct name to determine state: %Pending{}, %InternalSuspended{}, %ExternalSuspended{}, %Completed{}, %Errored{}, %Cancelled{}.

Functions

cancel(fiber, reason \\ :cancelled)

@spec cancel(t(), term()) :: t()

Cancel a fiber, invoking leave_scope cleanup for suspended fibers.

For suspended fibers, creates a %Cancelled{} sentinel and runs it through the leave_scope chain, giving scoped effects an opportunity to clean up resources.

For %Pending{} fibers, no scopes have been entered yet so no cleanup is needed.

For already-terminal fibers (%Completed{}, %Cancelled{}, %Errored{}), cancel is a no-op — the fiber is returned unchanged.

Parameters

  • fiber - The fiber to cancel
  • reason - The cancellation reason (default: :cancelled)

Example

fiber = Fiber.cancel(fiber, :timeout)
assert match?(%Fiber.Cancelled{}, fiber)

new(comp, env)

Create a new fiber from a computation.

The fiber starts as %Pending{} with the computation and env stored, ready to be run with run_until_suspend/1.

Parameters

  • comp - The computation to run as a fiber
  • env - The environment to run in (typically inherited from parent)

Example

fiber = Fiber.new(my_comp, env)
assert match?(%Fiber.Pending{}, fiber)

resume(fiber, value)

Resume a suspended fiber with a value.

Takes a suspended fiber and resumes it by calling the suspended continuation with the provided value. Returns the fiber with updated state — same contract as run_until_suspend/1.

Parameters

  • fiber - A fiber in suspended state (%InternalSuspended{} or %ExternalSuspended{})
  • value - The value to resume with (typically a result from an effect)

Example

fiber = Fiber.run_until_suspend(fiber)
# ... later, when we have a result ...
fiber = Fiber.resume(fiber, result)
case fiber do
  %Fiber.Completed{result: result} -> result
  _ -> # suspended again or errored
end

run_until_suspend(fiber)

Run a pending fiber until it completes, suspends, or errors.

Takes a %Pending{} fiber and runs its computation. Returns one of:

  • %Completed{result, env} — finished successfully
  • %InternalSuspended{k, suspend, env} — suspended for scheduler
  • %ExternalSuspended{k, env} — suspended for external callback
  • %Errored{error, env} — finished with error

A suspended fiber can be resumed with resume/2.

Example

fiber = Fiber.new(my_comp, env)
fiber = Fiber.run_until_suspend(fiber)
case fiber do
  %Fiber.Completed{result: result} -> IO.puts("Done: #{inspect(result)}")
  %Fiber.InternalSuspended{} -> IO.puts("Suspended, can resume later")
  %Fiber.Errored{error: error} -> IO.puts("Error: #{inspect(error)}")
end

terminal?(arg1)

@spec terminal?(t()) :: boolean()

Check if a fiber is in a terminal state (completed, cancelled, or errored).