2006-06-11
Migrating Javascript Threads
A while ago in my old weblog I posted some Sisc Scheme code to demonstrate a thread migrating from one Sisc session to another. Since Rhino, the Java based Javascript implementation, has serializable continuations I decided to try porting it to Javascript.
The code demonstrating it is in migrate.js. Loading this into a Rhino session provides a function called 'messageListener' that starts up a socket server that listens for incoming objects on a port. The object should be a function or continuation. When received it's called on a seperate thread.
The 'send' function will send a function to a running message listener. This can be on the same machine or across the network. 'migrateThread' will migrate the currently running thread to another message listener, again this could be on another machine across the network. For example:
Machine A:
js> load("migrate.js")
js> messageListener(10000)
Machine B:
js> load("migrate.js")
js> messageListener(20000)
js> send("host.running.A", 10000, function() { print("Hello A!"); });
This will result in the message 'Hello A!" appearing on machine A. The function is serialised, sent across the network and deserialized and called on A. An example function that does thread migration:
function pingPong(host1, port1, host2, port2) {
while(1) {
print("ping\n");
java.lang.Thread.sleep(1000);
migrateThread(host2, port2);
print("pong\n");
java.lang.Thread.sleep(1000);
migrateThread(host1, port1);
}
}
If run on Machine A, specifying the host and port for machines A and B it will first print 'ping', then sleep for 1,000 milliseconds. Then the thread will migrate to machine B, print 'pong', sleep and migrate back to A, etc.
The code has a workaround for the fact that Rhino doesn't deserialize and serialize to a stream. Instead the functions only work on files. So I serialize to a file first, then read that file and write it to the stream. For deserialisation it reads from the stream, writes it to a file then deserialises from that file. For real world code this should be changed to actually operate on the stream itself, or use random temporary files and clean them up afterwards.
To run the code you'll need to use both js.jar (The Rhino implementation) and xbean.jar (for serializing some of the Javascript objects). An easy way of just getting these to try it out is to use the jars from the Server Side Javascript example and run it with:
java -cp js.jar:xbean.jar org.mozilla.javascript.tools.shell.Main
For Windows, replace the ':' with a ';'.
This was one of the things I talked about and demonstrated at the Unenterprisey Languages Meeting in Wellington on Saturday.