Skip to content

Instantly share code, notes, and snippets.

@jaz303
Created August 12, 2013 16:40
Show Gist options
  • Save jaz303/6212654 to your computer and use it in GitHub Desktop.
Save jaz303/6212654 to your computer and use it in GitHub Desktop.
Actors
<!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