web-dev-qa-db-ja.com

Javascriptセマフォ/テストと設定/ロック?

アトミックテストセット、セマフォ、Javascriptのロックなどはありますか?

カスタムプロトコルを介して非同期のバックグラウンドプロセスを呼び出すjavascriptがあります(バックグラウンドプロセスは、ブラウザーとは無関係の別のプロセスで文字通り実行されます)。競合状態に陥っていると思います。バックグラウンドプロセスはテストとセットの間で戻り、javascript側で物事を台無しにします。実際のセマフォにするには、テストと設定の操作が必要です。

バックグラウンドプロセスを検出し、それらをキューに登録しようとするJavaScriptコードを次に示します。

Call = function () {

var isRunning = true,
    queue = [];

return  {
    // myPublicProperty: "something",

    call: function (method) {
            if (isRunning) {
                console.log("Busy, pushing " + method);
                queue.Push(method);
            } else {
                isRunning = true;
                objccall(method);
            }
        },

        done: function() {
            isRunning = false;
            if (queue.length > 0) {
                Call.call(queue.shift());
            }
        }
    };
}();

呼び出しは、キューイングを実装するシングルトンです。外部プロセスを呼び出したい人はCall.call( "something")を実行します。

何か案は?

47
Parand

JSはマルチスレッド言語ではないため、JavaScriptにはロックセマンティクスがありません。複数のスレッドは、完全に別個のコンテキストでのみ同時に動作できます。 HTML5ワーカースレッド、またはJavaScriptCore APIのコンテキストオブジェクトの複数インスタンスのようなもの(SpiderMonkeyにも同様の概念があると思います)。それらは共有状態を持つことができないため、本質的にすべての実行はアトミックです。

OK

External Process:
<JSObject>.isRunning = true;
doSomething()
<JSObject>.done()

またはそのようなもの(適切なAPIを使用)。その場合、JSがあなたのjsオブジェクトのコンテキストで実行されている場合、JavaScriptエンジンがブロックすることを期待します(これはJavaScriptCoreが行うことです)、おそらくjs実行の周りに手動ロックを配置する必要があります。

このすべてを行うためにどのエンジンを使用していますか?あなたの説明に基づいて、その言語が提供するC/C++ APIを使用して非JS言語のセカンダリスレッドからフラグを設定しているように聞こえ、ほとんどのJSエンジンはAPIを介して行われた状態操作を想定しているため、単一のスレッド、通常はすべての実行が発生する同じスレッドで発生します。

21
olliej

たぶん、基本的な整数セマフォを実装し、変数をDOMに追加してロック/ロック解除し、関数がチェックし続けることを確認するか、タイムアウトになります=)

Mootoolsなどのフレームワークを使用している場合、onCompleteなどのイベントでアプリのフローを処理しようとすることができます。

2
perrohunter

まず、javaScriptがシングルスレッドであることは事実ですが、javaScriptアプリケーションがシリアル化メカニズムを必要としないことは事実ではありません。

簡単な例としては、サーバーへのAjaxリクエストが機能している間、送信ボタンが一定時間フェードアウトする必要がある場合です。非同期Ajaxリクエストが正常に完了すると、ボタンがあった場所にメッセージが表示されます。

ボタンのフェードアウトをキャンセルし、スタイルを「display:none」に設定できるのはいいことですが、Ajaxリクエストが完了するとすぐに、jQueryでは不可能です。また、ソリューションはイベントを使用して2つの同時アクティビティを同期することもできますが、これは基本的に単純な問題にとってはやり過ぎです。

ローテクソリューションはロックをポーリングし、フェードアウトが完了するとロックが解除されますが、$。postで設定された成功コールバックが実行されるまで「server done」メッセージは表示されません。

var gl_lock;
var gl_selfID;

function poll_lock(message) {
     if (gl_lock === 0) {
          $('#output').text(message).fadeIn(200);
          window.clearInterval(gl_selfID);
     }
 } // end of poll_lock

 function worker() {

     // no one gets in or out
     gl_lock = 1;

     $.post(..., data,function() { 
           gl_selfID = window.setInterval(poll_lock, 40, data.message);
      }, "json");

     // end of fadeout unlock the semaphore
     $('#submit-button').fadeOut(400, function() { gl_lock = 0; });

  } // end of worker

最後に、perrohunterがこの議論で以前に提案した行に沿って、これはより詳細な答えだと思います。

1
JackCColeman

私は質問が正確に何を尋ねているのか本当に分かりませんが、ここで私のセマフォオブジェクトをチェックしてください: https://github.com/agamemnus/semaphore.js

1
Agamemnus

私は選択リストに値を入れるajaxのものを持っています。ロックする必要があるので、このようなことをしました。据え置きやパイプなどを使用しても、おそらくもっと簡単にできると思います。

var semaphore=[];

function myFunc(arg){
   var dfd;
   $.when(semaphore[table]).done(
      function(){
            dfd=myFuncInner(arg);
      }
      );
return dfd;
}

function myFuncInner(table){
semaphore[arg] = new $.Deferred();
... 
somethingasynchronous({
    semaphore[arg].resolve();
});

return  semaphore[arg];
}
0
Mark Lester