1 | 'use strict';
|
2 |
|
3 | Object.defineProperty(exports, '__esModule', {
|
4 | value: true
|
5 | });
|
6 | exports.default = void 0;
|
7 |
|
8 | var _types = require('./types');
|
9 |
|
10 | function _defineProperty(obj, key, value) {
|
11 | if (key in obj) {
|
12 | Object.defineProperty(obj, key, {
|
13 | value: value,
|
14 | enumerable: true,
|
15 | configurable: true,
|
16 | writable: true
|
17 | });
|
18 | } else {
|
19 | obj[key] = value;
|
20 | }
|
21 | return obj;
|
22 | }
|
23 |
|
24 | class Farm {
|
25 | constructor(numOfWorkers, callback, computeWorkerKey) {
|
26 | _defineProperty(this, '_computeWorkerKey', void 0);
|
27 |
|
28 | _defineProperty(this, '_cacheKeys', void 0);
|
29 |
|
30 | _defineProperty(this, '_callback', void 0);
|
31 |
|
32 | _defineProperty(this, '_last', void 0);
|
33 |
|
34 | _defineProperty(this, '_locks', void 0);
|
35 |
|
36 | _defineProperty(this, '_numOfWorkers', void 0);
|
37 |
|
38 | _defineProperty(this, '_offset', void 0);
|
39 |
|
40 | _defineProperty(this, '_queue', void 0);
|
41 |
|
42 | this._cacheKeys = Object.create(null);
|
43 | this._callback = callback;
|
44 | this._last = [];
|
45 | this._locks = [];
|
46 | this._numOfWorkers = numOfWorkers;
|
47 | this._offset = 0;
|
48 | this._queue = [];
|
49 |
|
50 | if (computeWorkerKey) {
|
51 | this._computeWorkerKey = computeWorkerKey;
|
52 | }
|
53 | }
|
54 |
|
55 | doWork(method, ...args) {
|
56 | return new Promise((resolve, reject) => {
|
57 | const computeWorkerKey = this._computeWorkerKey;
|
58 | const request = [_types.CHILD_MESSAGE_CALL, false, method, args];
|
59 | let worker = null;
|
60 | let hash = null;
|
61 |
|
62 | if (computeWorkerKey) {
|
63 | hash = computeWorkerKey.call(this, method, ...args);
|
64 | worker = hash == null ? null : this._cacheKeys[hash];
|
65 | }
|
66 |
|
67 | const onStart = worker => {
|
68 | if (hash != null) {
|
69 | this._cacheKeys[hash] = worker;
|
70 | }
|
71 | };
|
72 |
|
73 | const onEnd = (error, result) => {
|
74 | if (error) {
|
75 | reject(error);
|
76 | } else {
|
77 | resolve(result);
|
78 | }
|
79 | };
|
80 |
|
81 | const task = {
|
82 | onEnd,
|
83 | onStart,
|
84 | request
|
85 | };
|
86 |
|
87 | if (worker) {
|
88 | this._enqueue(task, worker.getWorkerId());
|
89 | } else {
|
90 | this._push(task);
|
91 | }
|
92 | });
|
93 | }
|
94 |
|
95 | _getNextTask(workerId) {
|
96 | let queueHead = this._queue[workerId];
|
97 |
|
98 | while (queueHead && queueHead.task.request[1]) {
|
99 | queueHead = queueHead.next || null;
|
100 | }
|
101 |
|
102 | this._queue[workerId] = queueHead;
|
103 | return queueHead && queueHead.task;
|
104 | }
|
105 |
|
106 | _process(workerId) {
|
107 | if (this._isLocked(workerId)) {
|
108 | return this;
|
109 | }
|
110 |
|
111 | const task = this._getNextTask(workerId);
|
112 |
|
113 | if (!task) {
|
114 | return this;
|
115 | }
|
116 |
|
117 | const onEnd = (error, result) => {
|
118 | task.onEnd(error, result);
|
119 |
|
120 | this._unlock(workerId);
|
121 |
|
122 | this._process(workerId);
|
123 | };
|
124 |
|
125 | task.request[1] = true;
|
126 |
|
127 | this._lock(workerId);
|
128 |
|
129 | this._callback(workerId, task.request, task.onStart, onEnd);
|
130 |
|
131 | return this;
|
132 | }
|
133 |
|
134 | _enqueue(task, workerId) {
|
135 | const item = {
|
136 | next: null,
|
137 | task
|
138 | };
|
139 |
|
140 | if (task.request[1]) {
|
141 | return this;
|
142 | }
|
143 |
|
144 | if (this._queue[workerId]) {
|
145 | this._last[workerId].next = item;
|
146 | } else {
|
147 | this._queue[workerId] = item;
|
148 | }
|
149 |
|
150 | this._last[workerId] = item;
|
151 |
|
152 | this._process(workerId);
|
153 |
|
154 | return this;
|
155 | }
|
156 |
|
157 | _push(task) {
|
158 | for (let i = 0; i < this._numOfWorkers; i++) {
|
159 | this._enqueue(task, (this._offset + i) % this._numOfWorkers);
|
160 | }
|
161 |
|
162 | this._offset++;
|
163 | return this;
|
164 | }
|
165 |
|
166 | _lock(workerId) {
|
167 | this._locks[workerId] = true;
|
168 | }
|
169 |
|
170 | _unlock(workerId) {
|
171 | this._locks[workerId] = false;
|
172 | }
|
173 |
|
174 | _isLocked(workerId) {
|
175 | return this._locks[workerId];
|
176 | }
|
177 | }
|
178 |
|
179 | exports.default = Farm;
|