Skip to content

Instantly share code, notes, and snippets.

@auroranockert
Created July 15, 2015 21:43
Show Gist options
  • Save auroranockert/3465b1432cfcec40890c to your computer and use it in GitHub Desktop.
Save auroranockert/3465b1432cfcec40890c to your computer and use it in GitHub Desktop.
Random actor framework?
<head>
<script src='process.js'></script>
</head>
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