7

私はJavaScriptで非常に複雑なシステムを実装することに取り組んできました。これは、とりわけマルチスレッドプロセスをシミュレートする必要があります。実際のマルチスレッドプロセス(カーネルスレッドなど)では、コンテキスト切り替えによってスレッドを切り替えることができます。これが機能するのは、現在のプロセスのプログラムカウンターとレジスターを一時的な構造に保存し、プログラムカウンターとレジスターを他のプロセスに復元してから、前のプロセスで中断したところから再開できるためです。

JavaScriptでこれに似たものを使用できるかどうか知りたいです。私は現在これを行う方法を知らないので、協調マルチタスクを使用してシステムを設計しています。特に、マルチスレッドシミュレーターで実行したい「関数」は、関数の配列に分割されます。「関数」を実行するには、関数の配列全体を反復処理し、次に実行する関数の「プログラムカウンター」を維持しながら、各関数を順番に実行します。これにより、配列内の関数の1つを呼び出し、関数が戻るのを待ってから、実行する必要のある他の関数の配列に切り替えることで、コンテキストスイッチをシミュレートできます。

私の現在のアプローチは機能しますが、このシステムでコードを書くことは困難です。各関数は、いつ中断できるかを具体的に示す必要があります。配列内の関数はすべて別個であるため、関数の異なる部分間でデータを通信するためのロジックは複雑です。代わりに、プリエンプティブマルチタスクが機能するようになることを望んでいました。

私の質問は、外部ソースによって一時停止および再開できる方法で任意のJavaScript関数を実行することは可能ですか?

4

2 に答える 2

4

StratifiedJSをチェックしてください

于 2011-02-07T07:38:35.357 に答える
3

まず、JavaScriptは完全にシングルスレッドであることに言及することが重要です。マルチスレッドをエミュレートすることは、実際には道のりではありません。イベントループに依存する方がはるかに良いでしょう。

前述のように、Webワーカーを使用することはできますが、実際にはブラウザー間のコンプライアンスがないため、Webワーカーは無視します。また、WebワーカーでDOM操作を行うことはできません。

node.jsを見て、イベントループがマルチスレッドの優れた代替手段である理由の背後にある推論を見てみましょう。彼は、なぜそれがこのビデオの良い選択肢であるのかについて非常にうまく触れていると思います。

したがって、関数の配列を作成してそれらを反復処理するのではなく、代わりにイベントを作成し、一連の関数をそれらにバインドして、そのイベントをトリガーすることができます。イベントの非常に軽量な実装は、backbone.jsにあります。

JavaScriptではスレッドが1つしかないため、スレッドを一時停止することはできません。関数にポイントが含まれていないと、関数を一時停止または再開する方法はありません。

これをエミュレートする方法は1つだけです。うまく構築されたJavaScriptを分解し、JavaScriptを一時停止および再開できるシステムを構築するJavaScriptパーサーを作成します。

この関数を例にとってみましょう

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

そしてそれをこれに変換します

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;
}

とで関数を拡張する必要があり.suspendます.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);

また、へのすべての参照をに置き換える必要がありvar a = b()ます

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

私はあなたに憤慨を任せます。今のところ、すべての関数はオブジェクトを返し、が値に設定されているr場合にのみオブジェクトr.rが「返されます」。r.rしたがって、が設定されているかどうか、および関数asyncコールバックがトリガーされているかどうかを確認して、イベントループがまだ「戻っている」かどうかを確認してください。

ねえ、私たちが持っているものを見てください。イベントループの周りでスレッドを実行することにより、スレッドをエミュレートしていました。スレッドをエミュレートするよりも、コードでイベントループをネイティブに使用する方がはるかに優れています。

基本的に、イベントループを再度実行するときに、関数にコードの次の行を実行させる。また、イベントループを一周するときに、特定の「機能」が一時停止または再開されているかどうかを確認します。

簡潔にするために、関数を「関数」に戻すバブリングは実装していません。これをエミュレートするのはそれほど難しいことではありません。

イベントループを直接使用するか、偽のスレッドメソッドを使用して、コードをコンパイルするときに恐ろしく見えないようにコンパイラにコードをコンパイルしてもらいます。

あなたがデッドロックを引き起こした場合、あなたに幸運を祈ります。

于 2011-02-07T08:00:15.173 に答える