|
|
'use strict';
Object.defineProperty(exports, '__esModule', { value: true }); exports.default = void 0;
var _types = require('./types');
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
class Farm { constructor(numOfWorkers, callback, computeWorkerKey) { _defineProperty(this, '_computeWorkerKey', void 0);
_defineProperty(this, '_cacheKeys', void 0);
_defineProperty(this, '_callback', void 0);
_defineProperty(this, '_last', void 0);
_defineProperty(this, '_locks', void 0);
_defineProperty(this, '_numOfWorkers', void 0);
_defineProperty(this, '_offset', void 0);
_defineProperty(this, '_queue', void 0);
this._cacheKeys = Object.create(null); this._callback = callback; this._last = []; this._locks = []; this._numOfWorkers = numOfWorkers; this._offset = 0; this._queue = [];
if (computeWorkerKey) { this._computeWorkerKey = computeWorkerKey; } }
doWork(method, ...args) { const customMessageListeners = new Set();
const addCustomMessageListener = listener => { customMessageListeners.add(listener); return () => { customMessageListeners.delete(listener); }; };
const onCustomMessage = message => { customMessageListeners.forEach(listener => listener(message)); };
const promise = new Promise((resolve, reject) => { const computeWorkerKey = this._computeWorkerKey; const request = [_types.CHILD_MESSAGE_CALL, false, method, args]; let worker = null; let hash = null;
if (computeWorkerKey) { hash = computeWorkerKey.call(this, method, ...args); worker = hash == null ? null : this._cacheKeys[hash]; }
const onStart = worker => { if (hash != null) { this._cacheKeys[hash] = worker; } };
const onEnd = (error, result) => { customMessageListeners.clear();
if (error) { reject(error); } else { resolve(result); } };
const task = { onCustomMessage, onEnd, onStart, request };
if (worker) { this._enqueue(task, worker.getWorkerId()); } else { this._push(task); } }); promise.UNSTABLE_onCustomMessage = addCustomMessageListener; return promise; }
_getNextTask(workerId) { let queueHead = this._queue[workerId];
while (queueHead && queueHead.task.request[1]) { queueHead = queueHead.next || null; }
this._queue[workerId] = queueHead; return queueHead && queueHead.task; }
_process(workerId) { if (this._isLocked(workerId)) { return this; }
const task = this._getNextTask(workerId);
if (!task) { return this; }
const onEnd = (error, result) => { task.onEnd(error, result);
this._unlock(workerId);
this._process(workerId); };
task.request[1] = true;
this._lock(workerId);
this._callback( workerId, task.request, task.onStart, onEnd, task.onCustomMessage );
return this; }
_enqueue(task, workerId) { const item = { next: null, task };
if (task.request[1]) { return this; }
if (this._queue[workerId]) { this._last[workerId].next = item; } else { this._queue[workerId] = item; }
this._last[workerId] = item;
this._process(workerId);
return this; }
_push(task) { for (let i = 0; i < this._numOfWorkers; i++) { this._enqueue(task, (this._offset + i) % this._numOfWorkers); }
this._offset++; return this; }
_lock(workerId) { this._locks[workerId] = true; }
_unlock(workerId) { this._locks[workerId] = false; }
_isLocked(workerId) { return this._locks[workerId]; } }
exports.default = Farm;
|