import type { FromChunkWorker, ToChunkWorker } from "./workers/chunk_messages.ts"; // leave a core for the main thread, more than 4 doesnt help much const POOL_SIZE = Math.max(1, Math.min(4, (navigator.hardwareConcurrency ?? 4) - 1)); export class ChunkWorkerPool { readonly size = POOL_SIZE; #workers: Worker[] = []; #next = 0; constructor(on_message: (message: FromChunkWorker) => void) { for (let i = 0; i < this.size; i += 1) { const worker = new Worker(new URL("./workers/chunk_worker.js", import.meta.url), { type: "module" }); worker.onmessage = (event: MessageEvent) => on_message(event.data); worker.onerror = (event) => console.error("Chunk worker error:", event.message); this.#workers.push(worker); } } broadcast(message: ToChunkWorker) { for (const worker of this.#workers) { worker.postMessage(message); } } // round robin, results can come back out of order post(message: ToChunkWorker, transfer: Transferable[] = []) { const worker = this.#workers[this.#next]; this.#next = (this.#next + 1) % this.#workers.length; worker.postMessage(message, transfer); } terminate() { for (const worker of this.#workers) { worker.terminate(); } this.#workers = []; } }