Skip to content

Commit

Permalink
Merge pull request #3 from 01alchemist/feature/worker-based-threads-w…
Browse files Browse the repository at this point in the history
…ait-wake-integration

Feature/worker based threads wait wake integration
  • Loading branch information
nidin committed Nov 29, 2018
2 parents ea23fe0 + cbaa786 commit e9cf712
Show file tree
Hide file tree
Showing 12 changed files with 439 additions and 6 deletions.
23 changes: 23 additions & 0 deletions examples/atomic-wait-wake/assembly/index.js
@@ -0,0 +1,23 @@
const fs = require("fs");
const path = require("path");

const compiled = new WebAssembly.Module(
fs.readFileSync(path.resolve(__dirname, "..", "build", "atomic.builtins.wasm"))
);
const memory = new WebAssembly.Memory({
initial: 256,
maximum: 256,
shared: true
})
const imports = {
env: {
memory,
abort: (filename, line, column) => {
throw Error("abort called at " + line + ":" + colum);
}
}
};

Object.defineProperty(module, "exports", {
get: () => new WebAssembly.Instance(compiled, imports).exports
});
26 changes: 26 additions & 0 deletions examples/atomic-wait-wake/assembly/index.ts
@@ -0,0 +1,26 @@
import "allocator/atomic";
import { itoa } from "internal/number";

declare function log_str(v: string): void;

var id = 1;
type int = i32;
// type int = i64;

export function setId(_id: i32): void {
id = _id;
}

export function wait(mutexAddr: i32 = 0, value: int = 1): void {
log_str('[WASM][' + itoa<i32>(id) + '] waiting...');
Atomic.store<int>(mutexAddr, value);
Atomic.wait<int>(mutexAddr, value, -1);
log_str('[WASM][' + itoa<i32>(id) + '] waken');
}

export function wake(mutexAddr: i32 = 0, value: int = 0, numAgents: i32 = 1): void {
log_str('[WASM][' + itoa<i32>(id) + '] waking '+ itoa<i32>(numAgents) + ' agent(s)...');
Atomic.store<int>(mutexAddr, value);
var count = Atomic.wake<int>(mutexAddr, numAgents);
log_str('[WASM][' + itoa<i32>(id) + '] waken ' + itoa<i32>(count) + ' agent(s)');
}
6 changes: 6 additions & 0 deletions examples/atomic-wait-wake/assembly/tsconfig.json
@@ -0,0 +1,6 @@
{
"extends": "../../../std/assembly.json",
"include": [
"./**/*.ts"
]
}
8 changes: 8 additions & 0 deletions examples/atomic-wait-wake/build/index.js
@@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
require("allocator/arena");
let str = "A";
function read() {
return str;
}
exports.read = read;
125 changes: 125 additions & 0 deletions examples/atomic-wait-wake/index.html
@@ -0,0 +1,125 @@
<!DOCTYPE html>
<html>
<head>
<title>Atomic wait wake - AssemblyScript</title>
<link rel="icon" href="http://assemblyscript.org/favicon.ico" type="image/x-icon" />
<meta name="viewport" content="user-scalable=0" />
<style>
html,
body {
height: 100%;
margin: 0;
overflow: hidden;
color: #111;
background: #fff;
font-family: sans-serif;
}

body {
border-top: 2px solid #070809;
}

h1 {
padding: 18px 20px 20px;
font-size: 12pt;
margin: 0;
}

a {
color: #111;
text-decoration: none;
}

a:hover {
color: #efbd03;
text-decoration: underline;
}

canvas {
position: absolute;
top: 60px;
left: 20px;
width: calc(100% - 40px);
height: calc(100% - 80px);
background: #070809;
}
.info {
padding: 2rem;
}
</style>
</head>

<body>
<h1>
<a href="https://github.com/WebAssembly/threads">Atomic wait wake</a> in
<a href="http://assemblyscript.org">AssemblyScript</a> (
<a
href="https://github.com/AssemblyScript/assemblyscript/blob/master/examples/shared-memory/assembly/index.ts"
>source</a
>
)
<br>
</h1>
<div class="info">Open console to results</div>
<script>
"use strict";

const memory = new WebAssembly.Memory({
initial: 256,
shared: true,
maximum: 256,
});
const memoryView = new DataView(memory.buffer);
let _exports = {};
const workers = [];
async function init() {
const res = await fetch("build/optimized.wasm");
const buffer = await res.arrayBuffer();
const wasm = await WebAssembly.compile(buffer);
let worker1 = new Worker("./js/worker1.js");
let worker2 = new Worker("./js/worker1.js");
worker1.onmessage = handleMessage;
worker2.onmessage = handleMessage;
workers.push(worker1)
workers.push(worker2);
worker1.postMessage({ command: "init", id:1, memory, wasm });
worker2.postMessage({ command: "init", id:2, memory, wasm });
}
let readyCount = 0;
function handleMessage(event) {
switch(event.data.command){
case "inited":{
readyCount++;
if(readyCount === 2) {
workers[0].postMessage({ command: "wait", value: 1 });
setTimeout(() => {
workers[1].postMessage({ command: "wake", value: 1 });
}, 1000)

setTimeout(() => {
workers[0].postMessage({ command: "wait_js", value: 1 });
}, 1500)
setTimeout(() => {
workers[1].postMessage({ command: "wake", value: 2 });
}, 3000)
// setTimeout(() => {
// workers[0].postMessage({ command: "wait_i64", value: 1 });
// }, 0)
// setTimeout(() => {
// workers[1].postMessage({ command: "wake_i64", value: 2 });
// }, 1000)
setTimeout(() => {
workers[0].postMessage({ command: "wait", value: 1 });
}, 3500)
setTimeout(() => {
workers[1].postMessage({ command: "wake_js", value: 2 });
}, 5000)
}
break;
}
}
}
init();
</script>
</body>
</html>
88 changes: 88 additions & 0 deletions examples/atomic-wait-wake/js/worker1.js
@@ -0,0 +1,88 @@
addEventListener("message", onMessageReceived, false);
let memory = null;
let dataView = null;
let u8 = null;
let i32 = null;
let id = 0;
let _exports = null;
const mutexAddr = 0;
const numAgents = 1;
async function onMessageReceived(e) {
try {
const data = e.data;
switch (data.command) {
case "init": {
id = data.id;
memory = data.memory;
dataView = new DataView(memory.buffer);
u8 = new Uint8Array(memory.buffer);
i32 = new Int32Array(memory.buffer);
const instance = await WebAssembly.instantiate(data.wasm, {
env: {
memory,
abort: function() {},
},
index: {
log: console.log,
log_str,
},
});
const exp = instance.exports;

_exports = exp;
_exports.setId(id);
self.postMessage({ command: "inited" });
break;
}
case "wait": {
_exports.wait(mutexAddr, data.value);
break;
}
case "wait_i64": {
_exports.wait_i64(mutexAddr, data.value);
break;
}
case "wait_js": {
console.log(`[JS][${id}] waiting...`)
Atomics.store(i32, mutexAddr, data.value);
Atomics.wait(i32, mutexAddr, data.value);
console.log(`[JS][${id}] waken`);
break;
}
case "wake": {
_exports.wake(mutexAddr, data.value, numAgents);
console.log('-----')
break;
}
case "wake_i64": {
_exports.wake_i64(mutexAddr, data.value, numAgents);
console.log('-----')
break;
}
case "wake_js": {
console.log(`[JS][${id}] waking ${numAgents} agent(s)...`)
Atomics.store(i32, mutexAddr, data.value);
const count = Atomics.wake(i32, mutexAddr, numAgents);
console.log(`[JS][${id}] waken ${count} agent(s)`)
console.log('-----')
break;
}
}
} catch (e) {
console.log(e);
}
}

function log_str(ptr) {
console.log(readUTF16(ptr, dataView));
}

function readUTF16(ptr, _memoryView) {
_memoryView = _memoryView || memoryView;
const u8a = new Uint8Array(_memoryView.buffer);
const str_len = _memoryView.getUint32(ptr, true);
const utf16 = u8a.subarray(ptr + 4, ptr + (str_len * 2) + 4);
const decoder = new TextDecoder("utf-16");
const _utf16 = utf16.map(a => a);
return decoder.decode(_utf16);
}
19 changes: 19 additions & 0 deletions examples/atomic-wait-wake/js/worker2.js
@@ -0,0 +1,19 @@
addEventListener("message", onMessageReceived, false);
let memory = null;
let i32 = null;
function onMessageReceived(e) {
try {
const data = e.data;
switch (data.command) {
case "init": {
memory = data.memory;
i32 = new Int32Array(memory.buffer);
setTimeout(() => {
Atomics.store(i32, 0, 123);
console.log("Stored", 123);
Atomics.wake(i32, 0, 1);
}, 2000);
}
}
} catch (e) {}
}
16 changes: 16 additions & 0 deletions examples/atomic-wait-wake/package.json
@@ -0,0 +1,16 @@
{
"name": "@assemblyscript/shared-memory-example",
"version": "1.0.0",
"private": true,
"scripts": {
"asbuild:untouched": "asc assembly/index.ts -b build/untouched.wasm -t build/untouched.wat --sourceMap --importMemory --sharedMemory=256 --validate",
"asbuild:optimized": "asc assembly/index.ts -b build/optimized.wasm -t build/optimized.wat -O3 --importMemory --sharedMemory=256 --validate --noAssert",
"asbuild": "npm run asbuild:untouched && npm run asbuild:optimized",
"build": "npm run asbuild",
"server": "http-server . -o -c-1",
"test": "node tests"
},
"devDependencies": {
"http-server": "^0.11.1"
}
}

0 comments on commit e9cf712

Please sign in to comment.