UNPKG

@loaders.gl/worker-utils

Version:

Utilities for running tasks on worker threads

132 lines (131 loc) 4.33 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _globals = require("../env-utils/globals"); var _workerThread = _interopRequireDefault(require("./worker-thread")); var _workerJob = _interopRequireDefault(require("./worker-job")); class WorkerPool { static isSupported() { return _workerThread.default.isSupported(); } constructor(props) { (0, _defineProperty2.default)(this, "name", 'unnamed'); (0, _defineProperty2.default)(this, "source", void 0); (0, _defineProperty2.default)(this, "url", void 0); (0, _defineProperty2.default)(this, "maxConcurrency", 1); (0, _defineProperty2.default)(this, "maxMobileConcurrency", 1); (0, _defineProperty2.default)(this, "onDebug", () => {}); (0, _defineProperty2.default)(this, "reuseWorkers", true); (0, _defineProperty2.default)(this, "props", {}); (0, _defineProperty2.default)(this, "jobQueue", []); (0, _defineProperty2.default)(this, "idleQueue", []); (0, _defineProperty2.default)(this, "count", 0); (0, _defineProperty2.default)(this, "isDestroyed", false); this.source = props.source; this.url = props.url; this.setProps(props); } destroy() { this.idleQueue.forEach(worker => worker.destroy()); this.isDestroyed = true; } setProps(props) { this.props = { ...this.props, ...props }; if (props.name !== undefined) { this.name = props.name; } if (props.maxConcurrency !== undefined) { this.maxConcurrency = props.maxConcurrency; } if (props.maxMobileConcurrency !== undefined) { this.maxMobileConcurrency = props.maxMobileConcurrency; } if (props.reuseWorkers !== undefined) { this.reuseWorkers = props.reuseWorkers; } if (props.onDebug !== undefined) { this.onDebug = props.onDebug; } } async startJob(name) { let onMessage = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : (job, type, data) => job.done(data); let onError = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : (job, error) => job.error(error); const startPromise = new Promise(onStart => { this.jobQueue.push({ name, onMessage, onError, onStart }); return this; }); this._startQueuedJob(); return await startPromise; } async _startQueuedJob() { if (!this.jobQueue.length) { return; } const workerThread = this._getAvailableWorker(); if (!workerThread) { return; } const queuedJob = this.jobQueue.shift(); if (queuedJob) { this.onDebug({ message: 'Starting job', name: queuedJob.name, workerThread, backlog: this.jobQueue.length }); const job = new _workerJob.default(queuedJob.name, workerThread); workerThread.onMessage = data => queuedJob.onMessage(job, data.type, data.payload); workerThread.onError = error => queuedJob.onError(job, error); queuedJob.onStart(job); try { await job.result; } finally { this.returnWorkerToQueue(workerThread); } } } returnWorkerToQueue(worker) { const shouldDestroyWorker = this.isDestroyed || !this.reuseWorkers || this.count > this._getMaxConcurrency(); if (shouldDestroyWorker) { worker.destroy(); this.count--; } else { this.idleQueue.push(worker); } if (!this.isDestroyed) { this._startQueuedJob(); } } _getAvailableWorker() { if (this.idleQueue.length > 0) { return this.idleQueue.shift() || null; } if (this.count < this._getMaxConcurrency()) { this.count++; const name = "".concat(this.name.toLowerCase(), " (#").concat(this.count, " of ").concat(this.maxConcurrency, ")"); return new _workerThread.default({ name, source: this.source, url: this.url }); } return null; } _getMaxConcurrency() { return _globals.isMobile ? this.maxMobileConcurrency : this.maxConcurrency; } } exports.default = WorkerPool; //# sourceMappingURL=worker-pool.js.map