2017-02-21 19:59:05 +00:00
|
|
|
// 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.
|
|
|
|
|
2017-03-13 14:33:07 +00:00
|
|
|
$262.agent = (function () {
|
2017-02-21 19:59:05 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-03-13 14:33:07 +00:00
|
|
|
var $262 = {
|
2017-02-21 19:59:05 +00:00
|
|
|
agent: {
|
|
|
|
receiveBroadcast(receiver) {
|
|
|
|
pendingReceiver = receiver;
|
|
|
|
handleBroadcast();
|
|
|
|
},
|
|
|
|
|
|
|
|
report(msg) {
|
2017-07-06 23:02:13 +00:00
|
|
|
postMessage(String(msg));
|
2017-02-21 19:59:05 +00:00
|
|
|
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) {
|
2017-07-06 23:02:13 +00:00
|
|
|
if (!(sab instanceof SharedArrayBuffer)) {
|
|
|
|
throw new TypeError('sab must be a SharedArrayBuffer.');
|
|
|
|
}
|
|
|
|
|
2017-02-21 19:59:05 +00:00
|
|
|
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;
|
|
|
|
|
|
|
|
})();
|