Skuld.Fiber (skuld v0.25.0)
View SourceCooperative 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
- Create with
new/2— returns%Pending{} - Run with
run_until_suspend/1— returns%Completed{},%InternalSuspended{},%ExternalSuspended{}, or%Errored{} - Resume with
resume/2— suspended fiber runs again until completion/suspension/error - 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
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
@type t() :: Skuld.Fiber.Pending.t() | Skuld.Fiber.InternalSuspended.t() | Skuld.Fiber.ExternalSuspended.t() | Skuld.Fiber.Completed.t() | Skuld.Fiber.Errored.t() | Skuld.Fiber.Cancelled.t()
A fiber in any state.
Callers pattern-match on the struct name to determine state:
%Pending{}, %InternalSuspended{}, %ExternalSuspended{},
%Completed{}, %Errored{}, %Cancelled{}.
Functions
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 cancelreason- The cancellation reason (default::cancelled)
Example
fiber = Fiber.cancel(fiber, :timeout)
assert match?(%Fiber.Cancelled{}, fiber)
@spec new(Skuld.Comp.Types.computation(), Skuld.Comp.Types.env()) :: Skuld.Fiber.Pending.t()
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 fiberenv- The environment to run in (typically inherited from parent)
Example
fiber = Fiber.new(my_comp, env)
assert match?(%Fiber.Pending{}, fiber)
@spec resume( Skuld.Fiber.InternalSuspended.t() | Skuld.Fiber.ExternalSuspended.t(), term() ) :: Skuld.Fiber.Completed.t() | Skuld.Fiber.InternalSuspended.t() | Skuld.Fiber.ExternalSuspended.t() | Skuld.Fiber.Errored.t()
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
@spec run_until_suspend(Skuld.Fiber.Pending.t()) :: Skuld.Fiber.Completed.t() | Skuld.Fiber.InternalSuspended.t() | Skuld.Fiber.ExternalSuspended.t() | Skuld.Fiber.Errored.t()
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
Check if a fiber is in a terminal state (completed, cancelled, or errored).