moonbitstack/moonzero/threading does not have a README file

    RoutineGroup

    pub struct RoutineGroup {
    tasks : Array[async () -> Unit]
    }

    A set of tasks that are started together and joined together.

    Bodies are collected first and run at wait, which is what makes the group usable while the tasks they depend on are still being decided: a fan-out whose width comes from the data does not have to know that width up front.

    RoutineGroup::len

    fn RoutineGroup::len(self : RoutineGroup) -> Int

    How many bodies are waiting.

    RoutineGroup::new

    A group with nothing in it.

    RoutineGroup::run

    fn RoutineGroup::run(self : RoutineGroup, body : async () -> Unit) -> Unit

    Add a body to the group. The bodies run concurrently when wait is called.

    RoutineGroup::wait

    async fn RoutineGroup::wait(self : RoutineGroup) -> Unit

    Run every body concurrently and return when all of them have finished. A body that raises cancels the others and the failure reaches the caller.

    StableRunner

    pub struct StableRunner[T] {
    queue :
    Queue
    [T]
    }

    A runner that keeps only the newest pending item: pushing while the consumer is busy replaces what it will take next, so a burst collapses to its last value.

    A service uses it for work that is idempotent and worth doing only once — a configuration reload, a cache refresh, a re-index triggered by a write.

    StableRunner::close

    fn[T] StableRunner::close(self : StableRunner[T]) -> Unit

    Stop accepting work and wake the consumer so it can finish.

    StableRunner::new

    fn[T] StableRunner::new() -> StableRunner[T]

    A stable runner with nothing pending. The queue holds one item and drops the oldest when a newer one arrives, so a producer never waits and never queues more than one turn of work.

    StableRunner::push

    async fn[T] StableRunner::push(self : StableRunner[T], item : T) -> Unit

    Make item the pending one, replacing whatever was pending. The queue holds one item and discards the older one, so this never waits for the consumer.

    StableRunner::run

    async fn[T] StableRunner::run(self : StableRunner[T], handle : async (T) -> Unit) -> Unit

    Take the pending item and hand it to handle, one at a time, until the runner is closed.

    TaskRunner

    pub struct TaskRunner[T] {
    queue :
    Queue
    [T]
    }

    A queue drained by one consumer: push hands work over and returns, run is the loop that takes it. What a service uses when the work must not run on the request's own task — a write-behind, a slow notification.

    TaskRunner::close

    fn[T] TaskRunner::close(self : TaskRunner[T]) -> Unit

    Stop accepting work and wake the consumer so it can finish.

    TaskRunner::new

    fn[T] TaskRunner::new() -> TaskRunner[T]

    A runner with an unbounded queue.

    TaskRunner::push

    async fn[T] TaskRunner::push(self : TaskRunner[T], item : T) -> Unit

    Hand one item to the consumer, waiting if the queue is bounded and full.

    TaskRunner::run

    async fn[T] TaskRunner::run(self : TaskRunner[T], handle : async (T) -> Unit) -> Unit

    Drain the queue, handing each item to handle, until the runner is closed. A handler that raises stops the loop and the failure reaches whoever is waiting for the service.

    TaskRunner::try_push

    fn[T] TaskRunner::try_push(self : TaskRunner[T], item : T) -> Bool

    Try to hand one item over without waiting; false when the queue is full or already closed.