@babylonjs/core
Version:
Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.
120 lines • 4.09 kB
JavaScript
/**
* Helper class to push actions to a pool of workers.
*/
export class WorkerPool {
/**
* Constructor
* @param workers Array of workers to use for actions
*/
constructor(workers) {
this._pendingActions = new Array();
this._workerInfos = workers.map((worker) => ({
workerPromise: Promise.resolve(worker),
idle: true,
}));
}
/**
* Terminates all workers and clears any pending actions.
*/
dispose() {
for (const workerInfo of this._workerInfos) {
workerInfo.workerPromise.then((worker) => {
worker.terminate();
});
}
this._workerInfos.length = 0;
this._pendingActions.length = 0;
}
/**
* 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.
*/
push(action) {
if (!this._executeOnIdleWorker(action)) {
this._pendingActions.push(action);
}
}
_executeOnIdleWorker(action) {
for (const workerInfo of this._workerInfos) {
if (workerInfo.idle) {
this._execute(workerInfo, action);
return true;
}
}
return false;
}
_execute(workerInfo, action) {
workerInfo.idle = false;
workerInfo.workerPromise.then((worker) => {
action(worker, () => {
const nextAction = this._pendingActions.shift();
if (nextAction) {
this._execute(workerInfo, nextAction);
}
else {
workerInfo.idle = true;
}
});
});
}
}
/**
* Similar to the WorkerPool class except it creates and destroys workers automatically with a maximum of `maxWorkers` workers.
* Workers are terminated when it is idle for at least `idleTimeElapsedBeforeRelease` milliseconds.
*/
export class AutoReleaseWorkerPool extends WorkerPool {
constructor(maxWorkers, createWorkerAsync, options = AutoReleaseWorkerPool.DefaultOptions) {
super([]);
this._maxWorkers = maxWorkers;
this._createWorkerAsync = createWorkerAsync;
this._options = options;
}
push(action) {
if (!this._executeOnIdleWorker(action)) {
if (this._workerInfos.length < this._maxWorkers) {
const workerInfo = {
workerPromise: this._createWorkerAsync(),
idle: false,
};
this._workerInfos.push(workerInfo);
this._execute(workerInfo, action);
}
else {
this._pendingActions.push(action);
}
}
}
_execute(workerInfo, action) {
// Reset the idle timeout.
if (workerInfo.timeoutId) {
clearTimeout(workerInfo.timeoutId);
delete workerInfo.timeoutId;
}
super._execute(workerInfo, (worker, onComplete) => {
action(worker, () => {
onComplete();
if (workerInfo.idle) {
// Schedule the worker to be terminated after the elapsed time.
workerInfo.timeoutId = setTimeout(() => {
workerInfo.workerPromise.then((worker) => {
worker.terminate();
});
const indexOf = this._workerInfos.indexOf(workerInfo);
if (indexOf !== -1) {
this._workerInfos.splice(indexOf, 1);
}
}, this._options.idleTimeElapsedBeforeRelease);
}
});
});
}
}
/**
* Default options for the constructor.
* Override to change the defaults.
*/
AutoReleaseWorkerPool.DefaultOptions = {
idleTimeElapsedBeforeRelease: 1000,
};
//# sourceMappingURL=workerPool.js.map