| '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) { | 
|     return 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) => { | 
|         if (error) { | 
|           reject(error); | 
|         } else { | 
|           resolve(result); | 
|         } | 
|       }; | 
|   | 
|       const task = { | 
|         onEnd, | 
|         onStart, | 
|         request | 
|       }; | 
|   | 
|       if (worker) { | 
|         this._enqueue(task, worker.getWorkerId()); | 
|       } else { | 
|         this._push(task); | 
|       } | 
|     }); | 
|   } | 
|   | 
|   _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); | 
|   | 
|     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; |