silk.concurrency.local_scheduler.
A deterministic, single-threaded scheduler for structured Fibers.
When to use#
Use LocalScheduler.execute at the application entry to run one lazy program that uses the
Scheduler and MonotonicClock services. For parallel work on several threads, use
silk.concurrency.thread_pool.
Details#
Each call makes new task storage, a FIFO ready queue, and a private timer source. The root is
task zero, and uses the same Execution<()> storage as each child.
A clock wait in a task parks only that task. When no task is ready, the driver waits on the
parent MonotonicClock for the earliest timer. LocalScheduler.execute returns only after
the root finishes, and it cancels each unfinished descendant first.
Errors#
The typed failure of the root program.
OutOfMemoryErrorif task storage cannot be allocated.StalledErrorif no task is ready, no timer is waiting, and the root is not finished.
Examples#
Run a root program#
import silk.mem.allocator { OutOfMemoryError }
import silk.core.effect { Effect }
import silk.concurrency.fiber { Cancelled, Fiber }
import silk.concurrency.local_scheduler { LocalScheduler, StalledError }
import silk.system.monotonic_clock { MonotonicClock }
import silk.system.monotonic_clock_native { OsMonotonicClock }
import silk.concurrency.scheduler { Scheduler, TaskIdExhaustedError }
effect fn square(value: i32) -> i32 {
// Lets the other ready task run first.
run Fiber.yieldNow()
return value * value
}
effect fn root() -> i32
! OutOfMemoryError | TaskIdExhaustedError | Cancelled
? &mut Scheduler | &mut MonotonicClock {
let three = run Fiber<i32, never>.forkChild(square(3))
let four = run Fiber<i32, never>.forkChild(square(4))
// join parks the root until the child finishes.
let first = run three.join()
let second = run four.join()
if first + second != 25 {
return 1
}
return 0
}
effect fn program() -> i32
! OutOfMemoryError | TaskIdExhaustedError | Cancelled | StalledError {
let mut clock = OsMonotonicClock.make()
let mut scheduler = LocalScheduler.make()
return run scheduler.execute<i32, OutOfMemoryError | TaskIdExhaustedError | Cancelled>(root())
|> Effect.provideMut<MonotonicClock>(&mut clock)
}
effect fn failed<E>(error: E) -> i32 {
drop error
return 1
}
pub fn main() -> i32 {
return run Effect.catchAll(program(), failed)
}Import as LocalScheduler with import silk.concurrency.local_scheduler { LocalScheduler }.
Public declarations: 2.
LocalScheduler#
pub struct LocalSchedulerA deterministic, single-threaded Scheduler provider for structured Fibers.
When to use#
Use LocalScheduler.execute at the application entry to run one lazy program that uses the
Scheduler and MonotonicClock services. For parallel work on several threads, use
silk.concurrency.thread_pool.
Details#
Each call to LocalScheduler.execute makes new task storage, a FIFO ready queue, and a
private timer source. A clock wait in a task parks only that task. When no task is ready, the
driver waits on the parent MonotonicClock for the earliest timer.
Implementation LocalScheduler#
impl LocalSchedulerAssociated function make#
pub fn make() -> LocalSchedulerConstructs a reusable local Scheduler value.
Method execute#
pub effect fn execute<A: 'static, E: 'static>(
self: &mut Self,
program: once Effect<'static;
A
! E
? &mut Scheduler | &mut MonotonicClock
>,
) -> A
! E | OutOfMemoryError | StalledError
? &mut MonotonicClockRuns one lazy root program under this scheduler and returns its result.
Details#
The root becomes task zero. This call owns all task and timer storage of the run. It gives
each task its own Scheduler and MonotonicClock clients, and runs ready tasks in FIFO
order.
A clock read in a task uses one cached mark per driver turn. A wait suspends its task. Tasks
resume in deadline order, then in registration order. When the ready queue is empty, the
driver waits on the parent MonotonicClock for the earliest timer.
Before it returns or fails, it cancels each unfinished descendant and releases the run state.
Errors#
The failure of the root, OutOfMemoryError, or StalledError when no task is ready and no
timer is waiting.
StalledError#
pub struct StalledErrorReports that no task is ready and no event registration remains while the root is incomplete.
Details#
LocalScheduler.execute raises it when no task is ready, no timer is waiting, and the root is
not finished. It cancels and releases the incomplete task tree before it raises this error.
Implementation Debug for StalledError#
impl Debug for StalledErrorOperation debug#
effect fn debug(self: &Self, formatter: &mut Formatter) -> () ! WriterError ? &mut WriterWrites StalledError.
Category: Concurrency.
Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2.