Module Hegel.Concurrency

Concurrency capabilities for concurrent stateful tests.

A concurrent state machine runs each round by passing one body per worker to spawn_join_n. spawn_join_n must run all of them at the same time and return their outcomes once every body has finished. Hegel uses threads by default.

Pass a capability as ~concurrency to Stateful.run_concurrent or to the run of a module%hegel_concurrent_state_machine:

let%hegel_test counter tc =
  Stateful.run_concurrent
    tc
    (module Counter)
    ~init:(Atomic.make 0)
    ~concurrency:Concurrency.threads
    ~max_concurrency:4
;;

On OxCaml, hegel.jane.concurrent wraps a Jane Street Concurrent.t as a capability.

type outcome = (exn * Stdlib.Printexc.raw_backtrace) option

The result of one worker body: None on success, or the exception it raised with its backtrace.

type 'ctx t = {
  1. spawn_join_n : n:int -> f:('ctx -> int -> outcome) -> outcome list;
}

A concurrency capability. spawn_join_n ~n ~f runs f ctx 0 … f ctx (n - 1) as concurrent tasks and returns their outcomes once all of them have finished. ctx is the context the implementation gives each task, such as a scheduler handle. If f ctx i raises, the exception is recorded as task i's outcome.

val threads : unit t

Runs each body on its own systhread, with () as its context.

val domains : unit t

Runs the bodies in parallel on a pool of domains. Each spawn_join_n ~n ~f call grows the pool to at least max 1 (min n (Domain.recommended_domain_count () - 1)) domains. Each body runs on its own systhread inside a domain.