loaders.gl
Version:
Framework-independent loaders for 3D graphics formats
211 lines (175 loc) • 5.85 kB
JavaScript
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
/* global Worker, URL */
import createWorker from 'webworkify'; // Cache result of webworkify
var cache = new Map();
function getWorkerURL(processor) {
var workerURL = cache.get(processor);
if (!workerURL) {
var blob = createWorker(processor, {
bare: true
});
workerURL = URL.createObjectURL(blob);
cache.set(processor, workerURL);
}
return workerURL;
}
/**
* Process binary data in a worker
* @param processor {function | string} - worker function.
* @returns a Promise creator
*/
export function processWithWorker(processor) {
var workerURL = getWorkerURL(processor);
return function (arrayBuffer) {
return new Promise(function (resolve, reject) {
var worker = new Worker(workerURL);
worker.onmessage = function (message) {
return resolve(message.data);
};
worker.onerror = function (error) {
return reject(error);
};
worker.postMessage(arrayBuffer, [arrayBuffer]);
});
};
}
function getTransferList(object) {
var recursive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
var transfers = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
if (!object) {// ignore
} else if (object instanceof ArrayBuffer) {
transfers.push(object);
} else if (object.buffer && object.buffer instanceof ArrayBuffer) {
// Typed array
transfers.push(object.buffer);
} else if (recursive && _typeof(object) === 'object') {
for (var key in object) {
// Avoid perf hit - only go one level deep
getTransferList(object[key], false, transfers);
}
}
return transfers;
}
/**
* A worker in the WorkerFarm
*/
var WorkerThread =
/*#__PURE__*/
function () {
function WorkerThread(_ref) {
var url = _ref.url,
metadata = _ref.metadata;
_classCallCheck(this, WorkerThread);
this.worker = new Worker(url);
this.isBusy = false;
this.metadata = metadata;
}
_createClass(WorkerThread, [{
key: "process",
value: function process(data) {
var _this = this;
var worker = this.worker;
return new Promise(function (resolve, reject) {
worker.onmessage = function (e) {
_this.isBusy = false;
resolve(e.data);
};
worker.onerror = function (err) {
_this.isBusy = false;
reject(err);
};
_this.isBusy = true;
worker.postMessage(data, getTransferList(data));
});
}
}, {
key: "terminate",
value: function terminate() {
this.worker.terminate();
this.worker = null;
}
}]);
return WorkerThread;
}();
/**
* Process multiple data messages with a fleet of workers
*/
export var WorkerFarm =
/*#__PURE__*/
function () {
/**
* @param processor {function | string} - worker function
* @param maxConcurrency {number} - max count of workers
*/
function WorkerFarm(_ref2) {
var processor = _ref2.processor,
_ref2$maxConcurrency = _ref2.maxConcurrency,
maxConcurrency = _ref2$maxConcurrency === void 0 ? 1 : _ref2$maxConcurrency,
_ref2$debug = _ref2.debug,
debug = _ref2$debug === void 0 ? function () {} : _ref2$debug;
_classCallCheck(this, WorkerFarm);
this.workerURL = getWorkerURL(processor);
this.workers = [];
this.queue = [];
this.debug = debug;
for (var i = 0; i < maxConcurrency; i++) {
this.workers[i] = new WorkerThread({
url: this.workerURL,
metadata: {
name: "".concat(i, "/").concat(maxConcurrency)
}
});
}
}
_createClass(WorkerFarm, [{
key: "destroy",
value: function destroy() {
this.workers.forEach(function (worker) {
return worker.terminate();
});
}
}, {
key: "getAvailableWorker",
value: function getAvailableWorker() {
return this.workers.find(function (worker) {
return !worker.isBusy;
});
}
}, {
key: "next",
value: function next() {
var _this2 = this;
var queue = this.queue;
while (queue.length) {
var worker = this.getAvailableWorker();
if (!worker) {
break;
}
var job = queue.shift();
this.debug({
message: 'processing',
worker: worker.metadata.name,
backlog: queue.length
});
worker.process(job.data).then(job.onResult).catch(job.onError).then(function () {
return _this2.next();
});
}
}
}, {
key: "process",
value: function process(data, onResult, onError) {
this.queue.push({
data: data,
onResult: onResult,
onError: onError
});
this.next();
}
}]);
return WorkerFarm;
}();
//# sourceMappingURL=worker-utils.js.map