import { IDisposable } from "../scene"; interface WorkerInfo { worker: Worker; active: boolean; } /** * Helper class to push actions to a pool of workers. */ export class WorkerPool implements IDisposable { private _workerInfos: Array; private _pendingActions = new Array<(worker: Worker, onComplete: () => void) => void>(); /** * Constructor * @param workers Array of workers to use for actions */ constructor(workers: Array) { this._workerInfos = workers.map((worker) => ({ worker: worker, active: false })); } /** * Terminates all workers and clears any pending actions. */ public dispose(): void { for (const workerInfo of this._workerInfos) { workerInfo.worker.terminate(); } delete this._workerInfos; delete this._pendingActions; } /** * Pushes an action to the worker pool. If all the workers are active, the action will be * pended until a worker has completed its action. * @param action The action to perform. Call onComplete when the action is complete. */ public push(action: (worker: Worker, onComplete: () => void) => void): void { for (const workerInfo of this._workerInfos) { if (!workerInfo.active) { this._execute(workerInfo, action); return; } } this._pendingActions.push(action); } private _execute(workerInfo: WorkerInfo, action: (worker: Worker, onComplete: () => void) => void): void { workerInfo.active = true; action(workerInfo.worker, () => { workerInfo.active = false; const nextAction = this._pendingActions.shift(); if (nextAction) { this._execute(workerInfo, nextAction); } }); } }