Created
July 15, 2015 21:43
-
-
Save auroranockert/3465b1432cfcec40890c to your computer and use it in GitHub Desktop.
Random actor framework?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<head> | |
<script src='process.js'></script> | |
</head> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void function () { | |
function Runtime() { | |
this.processes = [] | |
this.runnable = new Set() | |
this.current_id = 0 | |
this.current_process = null | |
} | |
Runtime.prototype.run = function () { | |
var current = new Set(this.runnable) | |
this.runnable.clear() | |
for (var id of current) { | |
var process = this.processes[id] | |
if (process) { | |
this.current_process = process | |
try { | |
var next = process._generator.next() | |
} catch (e) { | |
console.debug('%s crashed!', process.process_id.toString()) | |
var next = { done: true, value: e } | |
} | |
if (next.done) { | |
this.terminate(process, next.value) | |
} else { | |
if (process._mailbox.length > 0 || process._killed.length > 0) { | |
this.runnable.add(id) | |
} | |
} | |
} | |
} | |
this.current_process = null | |
if (this.runnable.size > 0) { | |
setTimeout(this.run.bind(this), 0) | |
} | |
} | |
Runtime.prototype.terminate = function (process, reason) { | |
var pid = process.process_id | |
for (var id of process._linked) { | |
this.processes[id].kill(pid, reason) | |
} | |
delete this.processes[process.id] | |
} | |
Runtime.prototype.new_id = function () { | |
return this.current_id++ | |
} | |
Runtime.prototype.register = function (process) { | |
var id = this.new_id() | |
this.processes[id] = process | |
this.runnable.add(process) | |
return id | |
} | |
var runtime = new Runtime() | |
var runnable = runtime.runnable | |
window.runtime = runtime | |
function Process(f) { | |
this._killed = [] | |
this._linked = new Set() | |
this._mailbox = [] | |
this._generator = f.call(this) | |
this.id = runtime.register(this) | |
this.process_id = new ProcessID(this.id) | |
} | |
Process.prototype.receive = function* () { | |
while (this._mailbox.length == 0 || this._killed.length > 0) { | |
if (this._killed.length > 0) { | |
var args = this._killed.pop() | |
this.on_kill(args[0], args[1]) | |
} else { | |
yield undefined | |
} | |
} | |
return this._mailbox.pop() | |
} | |
Process.prototype.send = function (message) { | |
this._mailbox.push(message) | |
runnable.add(this.id) | |
if (!runtime.current_process) { | |
setTimeout(runtime.run.bind(runtime), 0) | |
} | |
} | |
Process.prototype.kill = function (process, reason) { | |
this._killed.push([process, reason]) | |
runnable.add(this.id) | |
if (!runtime.current_process) { | |
setTimeout(runtime.run.bind(runtime), 0) | |
} | |
} | |
Process.prototype.on_kill = function (process, reason) { | |
throw reason | |
} | |
Process.prototype.link = function (pid) { | |
var process = runtime.processes[pid._id] | |
if (process) { | |
process._linked.add(this.id) | |
} | |
} | |
Process.prototype.unlink = function (pid) { | |
var process = runtime.processes[pid._id] | |
if (process) { | |
process._linked.delete(this.id) | |
} | |
} | |
function ProcessID(id) { | |
this._id = id | |
} | |
ProcessID.prototype.send = function (message) { | |
var process = runtime.processes[this._id] | |
if (process) { | |
return process.send(message) | |
} | |
} | |
ProcessID.prototype.kill = function (message) { | |
var process = runtime.processes[this._id] | |
var current_pid = runtime.current_process ? runtime.current_process.process_id : null | |
if (process) { | |
return process.kill(current_pid, message) | |
} | |
} | |
ProcessID.prototype.toString = function () { | |
return '<ProcessID for ' + this._id + '>' | |
} | |
window.spawn = function (f) { | |
var process = new Process(f) | |
return process.process_id | |
} | |
window.spawn_link = function (f) { | |
var pid = spawn(f) | |
runtime.current_process.link(pid) | |
return pid | |
} | |
setTimeout(runtime.run.bind(runtime), 0) | |
}() | |
var outer = spawn(function* () { | |
var inner_0 = spawn_link(function* () { | |
while (true) { | |
var value = yield* this.receive() | |
console.log("Inner 0: " + value) | |
} | |
}) | |
var inner_1 = spawn_link(function* () { | |
var value = yield* this.receive() | |
console.log("Inner 1: " + value) | |
return "Hello!" | |
}) | |
this.on_kill = function (sender, message) { | |
console.log("%s tried to kill me! They sent '%s'!", (sender || 'The main thread').toString(), message) | |
if (!sender) { inner_0.kill(message) } | |
} | |
while (true) { | |
var value = yield* this.receive() | |
console.log("Outer: " + value) | |
inner_0.send(value) | |
inner_1.send(value) | |
} | |
}) | |
setTimeout(function () { outer.send('HERP!') }, 100) | |
setTimeout(function () { outer.send('DERP!') }, 200) | |
setTimeout(function () { outer.kill('HERPADERP!'); outer.send('URP!') }, 250) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment