Created
August 12, 2013 16:40
-
-
Save jaz303/6212654 to your computer and use it in GitHub Desktop.
Actors
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
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Actor</title> | |
<script> | |
// things i wanted to try but never got round to: | |
// | |
// - option to make `actor` a single function that is called once per message | |
// - `tick` should probably just be a periodic message planted on the actor's queue | |
// - when actor is stopped messages should not be delivered. configuration option: queue | drop | |
// - currently no way to access message sender from recipient | |
// (options: message object, first arg, last arg, global state (like Qt)) | |
// - recipient groups/distribution strategies (e.g. 'all' or 'one') | |
// spawn a new actor with optional tick interval | |
// `actor` is an object whose keys map to message handlers | |
// if `interval` is a number, actor's `tick` method will be invoked with this interval | |
function spawn(actor, interval) { | |
var state = 'stopped', | |
queue = [], | |
timer = null, | |
pending = null; | |
actor = actor || {}; | |
actor.tick = actor.tick || function() {}; | |
actor.send = function(recipient, message, args) { | |
if (Array.isArray(recipient)) { | |
recipient.forEach(function(r) { | |
r.deliver(actor, message, args); | |
}); | |
} else { | |
recipient.deliver(actor, message, args); | |
} | |
} | |
actor.start = function() { | |
if (state === 'running') | |
return; | |
state = 'running'; | |
if (typeof interval === 'number') | |
timer = setInterval(actor.tick.bind(actor), interval); | |
} | |
actor.stop = function() { | |
if (state === 'stopped') | |
return; | |
state = 'stopped'; | |
if (timer) { | |
clearInterval(timer); | |
timer = null; | |
} | |
} | |
actor.deliver = function(sender, name, args) { | |
queue.push({ | |
sender : sender, | |
name : name, | |
args : args | |
}); | |
if (pending === null) | |
pending = setTimeout(process, 0); | |
} | |
function process() { | |
while (queue.length) { | |
var msg = queue.shift(); | |
if (typeof actor[msg.name] === 'function') { | |
actor[msg.name].apply(actor, msg.args); | |
} else { | |
console.log("unhandled message '" + msg.name + "' sent to " + actor); | |
} | |
} | |
pending = null; | |
} | |
return actor; | |
} | |
function init() { | |
var a1 = spawn({ | |
tick: function() { | |
this.send([a2, a3], "greet", ["Jason"]); | |
} | |
}, 1000); | |
var a2 = spawn({ | |
greet: function(name) { | |
console.log("hello " + name); | |
this.send(a3, "greet", [name.toUpperCase()]); | |
} | |
}); | |
var a3 = spawn({ | |
greet: function(name) { | |
console.log("hello " + name); | |
} | |
}); | |
a1.start(); | |
a2.start(); | |
a3.start(); | |
} | |
</script> | |
</head> | |
<body onload='init();'></body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment