最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

multithreading - Simulating context switches in JavaScript? - Stack Overflow

programmeradmin2浏览0评论

I've been working on implementing a pretty plex 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 municating data between different parts of the function is plicated. 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?

I've been working on implementing a pretty plex 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 municating data between different parts of the function is plicated. 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?

Share Improve this question edited Aug 7, 2015 at 14:26 GEOCHET 21.3k15 gold badges77 silver badges99 bronze badges asked Feb 7, 2011 at 6:58 templatetypedeftemplatetypedef 374k111 gold badges944 silver badges1.1k bronze badges 1
  • 3 Obligatory mention of Web Workers whenever someone uses JavaScript and multithreading in the same sentence. – Yi Jiang Commented Feb 7, 2011 at 7:16
Add a ment  | 

2 Answers 2

Reset to default 4

Check StratifiedJS out

First it's important to mention that JavaScript is pletely 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 pliance 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 piler to pile your code so that it doesn't look hideous when you code it.

If you cause dead-locks good luck to you.

发布评论

评论列表(0)

  1. 暂无评论