Documentation

Hale.Base.Control.Concurrent

ThreadId #

A positive natural number. Used for ThreadId.id to encode at the type level that thread IDs are always $\ge 1$.

$$\text{PosNat} := \{n : \mathbb{N} \mid n > 0\}$$

Equations
Instances For
    @[implicit_reducible]
    Equations

    A handle to a forked concurrent thread.

    The id field is never reused within a process (monotonic counter).

    Instances For

      Forking #

      Fork a new green thread. The action is submitted to Lean's thread pool via IO.asTask (default priority) — O(1), no dedicated OS thread spawned. Millions of green threads can be active simultaneously.

      $$\text{forkIO} : \text{IO}\ \text{Unit} \to \text{IO}\ \text{ThreadId}$$

      let tid ← forkIO do
        IO.println "hello from green thread"
      

      The returned ThreadId can be used with killThread for cooperative cancellation, or with waitThread to join.

      Equations
      • One or more equations did not get rendered due to their size.
      Instances For
        def Control.Concurrent.forkFinally {α : Type} (action : IO α) (finally_ : Except IO.Error αIO Unit) :

        Fork a green thread that calls finally with the outcome, whether the action succeeded or threw.

        $$\text{forkFinally} : \text{IO}\ \alpha \to (\text{Except}\ \text{IO.Error}\ \alpha \to \text{IO}\ \text{Unit}) \to \text{IO}\ \text{ThreadId}$$

        Modelled after Haskell's forkFinally.

        Equations
        • One or more equations did not get rendered due to their size.
        Instances For

          Thread control #

          Cooperatively cancel a thread. Sets the thread's CancellationToken.

          $$\text{killThread} : \text{ThreadId} \to \text{BaseIO}\ \text{Unit}$$

          Note: Unlike GHC's killThread, this is cooperative. The target thread must check Std.CancellationToken.isCancelled or use cancellation-aware primitives to actually stop.

          Equations
          Instances For

            Suspend the current thread for at least $\mu s$ microseconds.

            $$\text{threadDelay} : \mathbb{N} \to \text{BaseIO}\ \text{Unit}$$

            Maps to IO.sleep (millisecond granularity, so we round up: $\text{ms} = \lceil \mu s / 1000 \rceil$).

            Equations
            Instances For

              Yield execution to other threads. Equivalent to IO.sleep 0.

              $$\text{yield} : \text{BaseIO}\ \text{Unit}$$

              Equations
              Instances For

                Fair green threads #

                Fork a fair green thread. The Green computation never blocks pool threads when awaiting — suspensions use BaseIO.bindTask to register continuations, freeing the pool thread for other work.

                $$\text{forkGreen} : \text{Green}\ \text{Unit} \to \text{IO}\ \text{ThreadId}$$

                Use Green.await, Green.takeMVar, etc. inside the action to suspend without blocking.

                See Hale.Control.Concurrent.Green for termination, liveness, and fairness guarantees.

                Equations
                • One or more equations did not get rendered due to their size.
                Instances For

                  Await a thread's completion inside a Green computation, without blocking the pool thread.

                  $$\text{waitThreadGreen} : \text{ThreadId} \to \text{Green.Green}\ \text{Unit}$$

                  Equations
                  • One or more equations did not get rendered due to their size.
                  Instances For

                    Waiting #

                    Wait for a thread to finish and return its result. Re-throws if the thread threw an exception.

                    $$\text{waitThread} : \text{ThreadId} \to \text{IO}\ \text{Unit}$$

                    Equations
                    • One or more equations did not get rendered due to their size.
                    Instances For