@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
140 lines (108 loc) • 2.97 kB
JavaScript
import { assert } from "../../assert.js";
/**
* Worker manager that will terminate the worker after a timeout if it is idle.
*
*/
export class OnDemandWorkerManager {
/**
* Number of active pending requests
* @type {number}
* @private
*/
__request_count = 0;
/**
* How long to wait before terminating the worker after it becomes idle
* in milliseconds
* @type {number}
* @private
*/
__timeout_ms = 1000;
/**
* ID of the timer set via setTimeout
* @type {number}
* @private
*/
__pending_termination = -1;
/**
*
* @param {WorkerProxy} worker
*/
constructor(worker) {
assert.defined(worker, 'worker');
/**
* @type {WorkerProxy}
*/
this.worker = worker;
}
/**
* Configure how long to wait after processing a request until deciding to shut down the worker.
* The browser limits the number of workers we can have open at once, so releasing them when not in use is critical.
*
* @param {number} delay_ms In milliseconds
*/
setTimeout(delay_ms) {
assert.isNonNegativeInteger(delay_ms, 'delay_ms');
this.__timeout_ms = delay_ms;
}
/**
* @private
*/
terminate = () => {
this.cancelScheduledTermination();
this.worker.stop();
}
/**
* @private
*/
cancelScheduledTermination() {
if (this.__pending_termination < 0) {
// no pending termination
return;
}
clearInterval(this.__pending_termination);
this.__pending_termination = -1;
}
/**
*
* @param {number} timeout
*/
scheduleTermination(timeout) {
this.cancelScheduledTermination();
this.__pending_termination = setTimeout(this.terminate, timeout);
}
/**
* @private
*/
decrement = () => {
this.__request_count--;
if (this.__request_count <= 0 && this.worker.isRunning()) {
this.scheduleTermination(this.__timeout_ms);
}
}
/**
* @private
*/
increment() {
this.__request_count++;
if (!this.worker.isRunning()) {
// worker is down, start it
this.worker.start();
} else {
// worker is up, ensure we're not waiting for it to terminate
this.cancelScheduledTermination();
}
}
/**
* Submit a request to the worker
* @template T
* @param {string} name
* @param {Array} [parameters]
* @return {Promise<T>}
*/
request(name, parameters) {
this.increment();
const promise = this.worker.$submitRequest(name, parameters);
promise.finally(this.decrement);
return promise;
}
}