A pool of a fixed number of worker threads, each operating on its own work queue. Idle threads will try and take work packages from other threads (work-stealing). Each thread is responsible for scheduling and running an arbitrary number of `Fiber`s, as well as taking care of registered timers, signal handlers, and file polling.
import public Data.Nat
import public IO.Async
import public IO.Async.Loop
import public IO.Async.Loop.PollH
import public IO.Async.Loop.SignalH
import public IO.Async.Loop.TimerH0 Task : Typerecord Poll : TypeW : (size : Nat) -> Fin size -> IORef Bool -> IORef (Queue Task) -> IArray size Poll -> Poller -> IORef Nat -> Timer -> Sighandler -> Mutex -> Condition -> Poll.alive : Poll -> IORef BoolReference indicating whether the pool is still alive
.cond : Poll -> ConditionCondition used for sleeping
.lock : Poll -> MutexMutex used for sleeping
.me : ({rec:0} : Poll) -> Fin (size {rec:0})Index of the worker thread corresponding to this state
.poller : Poll -> PollerThe state used for polling file descriptors
.queue : Poll -> IORef (Queue Task)Work queue of this worker
.signals : Poll -> SighandlerState for the signal handler
.size : Poll -> NatNumber of worker threads in the pool
.stealers : Poll -> IORef NatRemaining number of stealers. To reduce contention,
not all idle workers will be allowed to steal work
at the same time
.timer : Poll -> TimerState for schedule actions
.workers : ({rec:0} : Poll) -> IArray (size {rec:0}) PollWork queues of all worker threads
record ThreadPool : TypeA fixed-size pool of `n` physical worker threads.
Tasks are submited to the worker threads in round-robin
fashion: A new task is submitted to the next worker in line,
restarting at the beginning when reaching the last worker.
TP : (size : Nat) -> Vect size ThreadID -> ThreadID -> Vect (S size) Poll -> ThreadPool.ids : ({rec:0} : ThreadPool) -> Vect (size {rec:0}) ThreadID.pollid : ThreadPool -> ThreadID.size : ThreadPool -> Nat.workers : ({rec:0} : ThreadPool) -> Vect (S (size {rec:0})) Pollapp : Subset Nat IsSucc -> List Signal -> IO1 Poller -> Async Poll [] () -> IO ()Starts an epoll-based event loop and runs the given async
program to completion.
`n` : Number of threads to use
`sigs` : The signals to block while running the program.
These are typically the ones dealt with as part of `prog`
`prog` : The program to run
asyncThreads : IO (Subset Nat IsSucc)Reads environment variable `IDRIS2_ASYNC_THREADS` and returns
the number of threads to use. Default: 2.
simpleApp : {default [SIGINT] sigs : List Signal} -> Has SIGINT sigs => Async Poll [] () -> IO ()Simplified version of `app`.
This uses the posix-compatible `poll` call for polling files. For
a faster poller - especially when polling hundreds or thousands of
file descriptors at a time - consider using `IO.Async.Loop.Epoll.epollApp`.
We use environment variable `IDRIS2_ASYNC_THREADS` to determine the
number of threads to use (default: 2) and cancel the running program
on receiving `SIGINT`.
By default, only `SIGINT` is masked, to handle other signals
within your program, give `{sigs = [...]}` as the first
argument. One of the signals must be SIGINT, which is enforced by
the `Has SIGINT sigs` constraint.