| // Copyright 2017 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| $262.agent = (function () { |
| |
| var workers = []; |
| var i32a = null; |
| var pendingReports = []; |
| |
| // Agents call Atomics.wait on this location to sleep. |
| var SLEEP_LOC = 0; |
| // 1 if the started worker is ready, 0 otherwise. |
| var START_LOC = 1; |
| // The number of workers that have received the broadcast. |
| var BROADCAST_LOC = 2; |
| // Each worker has a count of outstanding reports; worker N uses memory |
| // location [WORKER_REPORT_LOC + N]. |
| var WORKER_REPORT_LOC = 3; |
| |
| function workerScript(script) { |
| return ` |
| var index; |
| var i32a = null; |
| var broadcasts = []; |
| var pendingReceiver = null; |
| |
| function handleBroadcast() { |
| if (pendingReceiver && broadcasts.length > 0) { |
| pendingReceiver.apply(null, broadcasts.shift()); |
| pendingReceiver = null; |
| } |
| }; |
| |
| var onmessage = function(msg) { |
| switch (msg.kind) { |
| case 'start': |
| i32a = msg.i32a; |
| index = msg.index; |
| (0, eval)(\`${script}\`); |
| break; |
| |
| case 'broadcast': |
| Atomics.add(i32a, ${BROADCAST_LOC}, 1); |
| broadcasts.push([msg.sab, msg.id]); |
| handleBroadcast(); |
| break; |
| } |
| }; |
| |
| var $262 = { |
| agent: { |
| receiveBroadcast(receiver) { |
| pendingReceiver = receiver; |
| handleBroadcast(); |
| }, |
| |
| report(msg) { |
| postMessage(String(msg)); |
| Atomics.add(i32a, ${WORKER_REPORT_LOC} + index, 1); |
| }, |
| |
| sleep(s) { Atomics.wait(i32a, ${SLEEP_LOC}, 0, s); }, |
| |
| leaving() {} |
| } |
| };`; |
| } |
| |
| var agent = { |
| start(script) { |
| if (i32a === null) { |
| i32a = new Int32Array(new SharedArrayBuffer(256)); |
| } |
| var w = new Worker(workerScript(script)); |
| w.index = workers.length; |
| w.postMessage({kind: 'start', i32a: i32a, index: w.index}); |
| workers.push(w); |
| }, |
| |
| broadcast(sab, id) { |
| if (!(sab instanceof SharedArrayBuffer)) { |
| throw new TypeError('sab must be a SharedArrayBuffer.'); |
| } |
| |
| Atomics.store(i32a, BROADCAST_LOC, 0); |
| |
| for (var w of workers) { |
| w.postMessage({kind: 'broadcast', sab: sab, id: id|0}); |
| } |
| |
| while (Atomics.load(i32a, BROADCAST_LOC) != workers.length) {} |
| }, |
| |
| getReport() { |
| for (var w of workers) { |
| while (Atomics.load(i32a, WORKER_REPORT_LOC + w.index) > 0) { |
| pendingReports.push(w.getMessage()); |
| Atomics.sub(i32a, WORKER_REPORT_LOC + w.index, 1); |
| } |
| } |
| |
| return pendingReports.shift() || null; |
| }, |
| |
| sleep(s) { Atomics.wait(i32a, SLEEP_LOC, 0, s); } |
| }; |
| return agent; |
| |
| })(); |