I recently just updated a library to handle worker threads under GWT, and I got to learn a bit more about the unique design of worker threads from javascript.

Here is a quick overview, in case you don't know much about them:

  1. There is no locking in javascript, so worker threads start asynchronously, and the only way to communicate with them is via the postMessage/onmessage API. There is no join(), wait(), synchronized blocks, or other sane threading paradigm you grew used to.
  2. There is no shared state, so every single message is transparently serialized back and forth. Did your thread processed 100MB of data? Well let me serialize that for you to get it on the other thread. Is there some global structure you want to work on parallel with multiple threads - like an image for example? Forget about it.
  3. There is no shared code, so worker threads must be created with their source independently - as a constructor argument. Packaging must be done basically separately for your "thread".

Let me translate this for you: Worker threads are a pain to even package in their own files, you can't call something like:

1
2
3
new Worker(function() { // this would be the worker instance.
    this.postMessage("send data back to parent");
});

No, that would be too easy, since from that method I could be able to access shared state, so let's make it awkward and weird, why not:

1
new Worker("my-worker.js");

and from the new file call:

1
self.postMessage("send message back to parent");

All the libraries, that you use both in your worker, or in your main code? Better load them twice.

But wait, there's more!

The window and document objects are not visible (that would be shared state, invalidating the fabric of JavaScript itself), so adding new scripts can be done via the importScripts function, but that's only if you are from inside a worker. importScripts for the window context? You must be talking the crazy talk. So you get a different approach even in loading external scripts from the different context window/worker.

There is a new object visible named self, that is the worker reference (if it's a script inside a window, self == window). 

So let's say you would want to process async a bunch of data, whenever it's being sent from the parent - again, there is no shared context, well why not go with:

1
2
3
4
5
6
7
8
9
10
11
function doActualProcessing() {
  //...
}
 
self.onmessage = function(ev) {
  // could be long running
  var result = doActualProcessing(ev.data); 
  
  // I hope for your sake, result isn't big in size.
  self.postMessage(result);  
}

Looks simple, isn't it? Except it's in a different bloody file, and did I mentioned that breakpoints in the worker thread code don't stop?

Fascinating.

Disqus Comments

comments powered by Disqus

Twitter

bmst
bmst Inspecting CSS Using IE8 Development Tools ciplogic.com/index.php/blog… #ie8 #dieinafire

20 hours ago via Twitter for Websites

bmst
bmst #justlinuxthings #helpme #socat socat[18386] E unknown option "--help"; use option "-h" for help

4 days ago via Twitter Web Client

putraxor
putraxor In order to understand recursion, one must first understand recursion. (Anonymous)

1 week ago via Twitter for Android • 5 retweets

Germanium

The one to rule them all. The browsers that is.

SharpKnight

SharpKnight is an Android chess game.

MagicGroup

MagicGroup is an eclipse plugin.

Go to top