7

I've been working on implementing a pretty complex system in JavaScript that needs to simulate, among other things, multithreaded processes. In a real multithreaded process (such as a kernel thread) it's possible to switch between threads by context-switching. This works because you can store the current process's program counter and registers to a temporary structure, restore the program counter and registers for some other process, and then resume where you left off in the previous process.

I'm curious whether it's possible to have something similar to this in JavaScript. I currently know no way of doing this and so have been designing the system using cooperative multitasking. In particular, any "function" that I want to run in the multithreading simulator is split up into an array of functions. To execute the "function", I iterate across the array of functions, executing each in order while maintaining a "program counter" of which function to execute next. This allows me to simulate a context switch by calling one of the functions in the array, waiting for the function to return, then switching to some other array of functions that need to be executed.

My current approach works, but it's difficult to write code in this system. Each function has to indicate specifically when it can be interrupted, and because the functions in the array are all separate the logic for communicating data between different parts of the function is complicated. I was hoping to get something closer to preemptive multitasking working instead.

My question is: is it possible to run an arbitrary JavaScript function in a way where it can be suspended and resumed by an external source?

GEOCHET
  • 21,119
  • 15
  • 74
  • 98
templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • 3
    Obligatory mention of [Web Workers](https://developer.mozilla.org/En/Using_web_workers) whenever someone uses JavaScript and multithreading in the same sentence. – Yi Jiang Feb 07 '11 at 07:16

2 Answers2

4

Check StratifiedJS out

qwertymk
  • 34,200
  • 28
  • 121
  • 184
  • 1
    stratifiedjs.org says: "StratifiedJS extends the JavaScript language with a small number of keywords for concurrent programming. It allows you to express asynchronous control flow in a straightforward, structured sequential style." Sounds like what you need – tomg Feb 07 '11 at 21:38
  • @qwertymk- This looks great, but unfortunately (from what I can tell) it's not supported by any web browsers, which somewhat defeats the purpose. This is a great link, though, and I thank you for sharing it! – templatetypedef Feb 16 '11 at 06:53
  • @templatetypedef it is supported by web browsers. Go to [their console](http://onilabs.com/docs#tryit) and try running this: `console.log('waiting 3 seconds....'); hold(3000); console.log('done')` – qwertymk Feb 16 '11 at 18:48
  • @qwertymk- Whoops! Missed that link. Thanks for pointing this out! – templatetypedef Feb 16 '11 at 18:54
3

First it's important to mention that JavaScript is completely single threaded. Emulating multi-threading is really not the way to go. Your far better off relying on eventloops.

As mentioned web workers could be used but there's not really a cross-browser compliance for them so I'll ignore web workers. Also you can't do any DOM manipulation with Web workers.

I would say take a look at node.js to reasoning behind why event loops are a good alternative to multi-threading. I believe he touches quite nicely on why it's a good alternative in this video.

So rather then having an array of functions and iterating over them you can instead create an event and bind a set of functions to them and trigger said event. A very lightweight implementation of events can be found in backbone.js.

You can't just pause a thread in JavaScript because there is only one. There's no way to suspend or resume a function without a function have points in it.

There is only one way to emulate this. Write a JavaScript parser that rips your nicely build JavaScript apart and builds up a system that allows you to suspend and resume your JavaScript.

Take for example this function

function(i) {
    j = i + 1;
    console.log(j);
    return foo(j);
}

and converts it into this

var bar = function(i) {
    var r = {};
    var j = i + 1; 
    var f = function() {
         console.log(j);
         var g = function() {
              return foo(j);
         };
         onNext(g, arguments.callee, this, r);
    };
    onNext(f, arguments.callee, this);
    return r;
}

your going to need to extend Function with .suspend and .resume

Function.prototype.suspend = function() {
     this.__suspended = true;
}

Function.prototype.resume = function() {
     this.__suspended = false;
}

function onNext(callback, function, context, returnObj) {
     if (!function.__suspended) {
          var cb = function() {
              Backbone.Events.unbind("run", cb);
              returnObj.r = callback.call(this);
          }
          Backbone.Events.bind("run", cb);
     }
}

setInterval(function() {
     Backbone.Events.trigger("run");
}, 5);

Also your going to have to replace all references to var a = b() with

callFunctionAsync(b, context, args, function(return) {
    var a = return;
    ...
});

I'll leave implentation upto you. For now all functions return an object r and only when r.r is set to a value has it "returned". So just check around the event loop whether it has "returned" yet by checking if r.r is set and if it has trigger the function async callback.

Hey and look what we've got. Were emulating threads by running them round the event loop. It's a lot better to use the event loop natively in your code rather then emulating threads through it.

Basically get your function to run the next line of its code when you go round the event loop again. And check whether the particular "function" is suspended or resumed when you go round your eventloop.

I didn't implement bubbling the return of the functions back up to the "function" for sake of brevity. This shouldn't be too hard to emulate.

Either use the event loop directly or use fake threaded methods and get a compiler to compile your code so that it doesn't look hideous when you code it.

If you cause dead-locks good luck to you.

Raynos
  • 166,823
  • 56
  • 351
  • 396
  • @Raynos- Thanks for the suggestions! My current implementation is not really using threads as much as implementing a system that requires threading (specifically, the JVM), so I really don't have a choice here. I currently am using events to do this - I have a window timeout that fires periodically to run more of the code. Your suggestion for having each function register a continuation is really great - I'm thinking that I could build a cross-compiler that autogenerates this code for me. Thanks so much for your advice! – templatetypedef Feb 07 '11 at 08:06
  • @templatetypedef If your implementing threading for the JVM why do you need your javascript to be threaded? Are you letting users run javascript code on top of your JVM? It just seems so wrong to do it this way and its really easy to get the threads wrong and break state completely. Any internals of the JVM that require threading can be implemented internally in your javascript using event loops. – Raynos Feb 07 '11 at 08:13
  • @Raynos- It's the other way around - I'm using JavaScript to implement the JVM. :-) It's for an academic project. The challenge is how to best implement JVM-level threads inside of JavaScript while also allowing Java native functions to be implemented natively in JavaScript. – templatetypedef Feb 07 '11 at 08:21
  • @templatetypedef Thats what I mean your using JS to emulate the JVM. Why do you need your javascript to be run threaded. Why can't you just use an eventloop and keep your low level javascript implementation of the JVM relying on the eventloop but have your high level Java code pretending its threaded but delegating to the event loop instead. Also I stubbed out return value bubbling which is a pain in the ass. – Raynos Feb 07 '11 at 08:38
  • @Raynos- I currently am using an event loop to do the interpretation. The problem is dealing with native methods (for example, `Class.forName`). This code is written in JavaScript but has to play nice with the interpreter by not running for a long time and blocking the main loop. Similarly, some native logic (for example, initializing a class) has to interact with monitors and therefore has to be able to suspend execution at some point and resume later on when it's acquired the lock. Hence my desire to get preemptive multitasking working. – templatetypedef Feb 07 '11 at 08:40
  • @templatetypedef rather then emulating threading for this look into something along the lines of [`$.Deferred`](http://stackoverflow.com/questions/4866721/what-are-deferred-objects) it sounds like what you want to do. Go through that entire `node.js` video and you should get a feel for it that this just requires a different way of thinking. Implementing threading is not neccesary and only useful as an academic exercise. – Raynos Feb 07 '11 at 08:46
  • @templatetypedef Oh and futhermore. Build it ontop of node.js its a far better way of doing this. The `onNext` is natively set up in node.js and the EventEmitter's will help a lot. You can spawn new processes in node.js and you extend the source with a C++ plugin to allow real multi-threaded code. It's a significantly more powerful platform. – Raynos Feb 07 '11 at 08:59