package parallel

Import Path
	github.com/freeeve/gochickpeas/parallel (on go.dev)

Dependency Relation
	imports 3 packages, and imported by 2 packages

Involved Source Files Package parallel provides the chunked worker-pool primitives the engine's kernels build on -- the Go stand-in for rayon's fold/reduce shape. Public engine signatures never expose this package; parallelism stays an implementation detail behind pure-std func values.
Package-Level Functions (total 7)
Chunks reports how many contiguous chunks For/ForWorker split [0, n) into (the load-balancing granularity). NOTE: ForWorker worker indexes are POOL worker ids bounded by Workers(), not by this -- size per-worker scratch with Workers().
Type Parameters: T: any Fold is the rayon fold/reduce shape over [0, n): one accumulator per WORKER (never per chunk or element), each worker folding one contiguous index range in ascending order, then merged with reduce in ascending worker order -- so an order-sensitive associative reduce (a concat) still sees the fully in-order sequence, exactly like the former one-accumulator-per-chunk form. A heavy accumulator (a count slab, a map) is built once per worker instead of once per 4x-oversplit chunk; the oversplit's load-balancing headroom is deliberately traded away here because a fold's per-index cost is near-uniform in the kernels (For/ForWorker keep it). identity is called once per worker plus once for an empty input.
Type Parameters: T: any FoldInto is Fold with caller-owned worker accumulators: accs supplies one pre-seeded accumulator per worker (len(accs) caps the parallelism, further capped by n), each worker folds its contiguous in-order index range into its slot, and reduce merges in ascending worker order -- the same in-order contract as Fold. The returned value aliases accs[0] for reference-typed T, and workers write accs[w] = fold(...), so the caller must reset EVERY accumulator before the next call. Reuse across calls is the point: a map keeps its buckets through clear(), a slab keeps its backing, so a warm call allocates nothing for accumulator state.
For runs body over [0, n) split into contiguous chunks, pulled from a shared counter by a pool of at most Workers() goroutines. The 4x chunk oversplit keeps dynamic load balancing (chunks are independent, so pull order is free), while the goroutine count stays at the worker count -- spawning one goroutine per chunk cost iterative algorithms two allocations per chunk on every pass.
ForWorker is For with a worker identity: body additionally receives the POOL WORKER's stable index in [0, min(Workers(), Chunks(n))) so kernels can keep per-worker scratch (the Go stand-in for thread-locals) in a pre-sized slice -- size it by Workers(). Within a call, one index is owned by exactly one goroutine, which invokes body sequentially for each chunk it pulls, so scratch[worker] is safe to reuse both across a call's chunks and across successive calls.
Join runs the given closures concurrently and blocks until all complete -- the finalize-style N-way join.
Workers is the parallelism ceiling: GOMAXPROCS.