1

「メインスレッド」と SharedArrayBuffer を共有する Worker があります。正しく動作させるには、メイン スレッドが SAB にアクセスする前に、ワーカーが SAB にアクセスできることを確認する必要があります。(編集: ワーカーを作成するコードは、別の関数 (EDIT2: SAB を指す配列を返す) にある必要があります) (おそらく、これはすでに不可能です。教えてください)。

初期コードは次のようになります。

function init() {
  var code = `onmessage = function(event) {
      console.log('starting');
      var buffer=event.data;
      var arr = new Uint32Array(buffer);// I need to have this done before accessing the buffer again from the main
      //some other code, manipulating the array
  }`
  var buffer = new SharedArrayBuffer(BUFFER_ELEMENT_SIZE);
  var blob = new Blob([code], { "type": 'application/javascript' });
  var url = window.URL || window.webkitURL;
  var blobUrl = url.createObjectURL(blob);
  var counter = new Worker(blobUrl);
  counter.postMessage(buffer);
  let res = new Uint32Array(buffer);
  return res;
}

function test (){
  let array = init();
  console.log('main');
  //accessing the SAB again
};

ワーカー コードは常に の後に実行されtest()、コンソールには常に が表示されmain、次にが表示されstartingます。

タイムアウトを使用しても役に立ちません。の次のコードを検討してくださいtest

function test (){
  let array = [];
  console.log('main'); 
  setTimeout(function(){
    array = initSAB();
  },0);
  setTimeout(function(){
    console.log('main');
   //accessing the SAB again
  },0);
  console.log('end');
};

コンソールにはend、最初に 、続いてが表示mainされstartingます。

ただし、test() 関数の外でバッファをグローバル配列に割り当てると、タイムアウトがなくても機能します。

私の質問は次のとおりです。

  • メッセージが送信された (= 受信された) 直後にワーカーが起動しないのはなぜですか? 私の知る限り、ワーカーには独自のイベント キューがあるため、メイン スタックが空になることに依存するべきではありませんか?
  • メッセージの送信後にワーカーがいつ作業を開始するかについての詳細な仕様はありますか?
  • グローバル変数を使用せずに SAB に再度アクセスする前にワーカーが開始されたことを確認する方法はありますか? (忙しい待機を使用することもできますが、注意してください...)おそらく方法はありませんが、確認したいと思います。

編集

より正確には:

  • 完全に並行して実行されるシナリオでは、ワーカーは投稿された直後にメッセージを処理できます。これは明らかにそうではありません。
  • ほとんどの Browser API (および Worker はそのような API) は、コールバック キューを使用して API への呼び出しを処理します。しかし、これが適用されると、タイムアウトのコールバックが実行される前に、メッセージがポスト/処理されます。
  • さらに先へ: postMessage の後に SAB から読み取ってビジー状態にしようとすると、1 つの値が変更されるまでプログラムが無限にブロックされます。私の知る限り、この動作は文書化されておらず、説明できませ

要約すると、postMessage の呼び出しが関数内にある場合、ブラウザーがメッセージを投稿するタイミングを決定し、ワーカーがそれを処理する方法を知りたいです。私はすでに回避策 (グローバル変数) を見つけたので、それが舞台裏でどのように機能するかにもっと興味があります。しかし、誰かが私に実用的な例を見せてくれるなら、私はそれを取ります.

編集2:

グローバル変数を使ったコード(うまく動くコード)はこんな感じ

function init() {
//Unchanged
}

var array = init(); //global

function test (){
  console.log('main');
  //accessing the SAB again
};

を出力startingmainてから、コンソールに出力します。

注目に値すること: Firefox ブラウザー(Chrome はテストされていません)でコードをデバッグすると、グローバル変数( startingbefore main) なしで必要な結果が得られます。誰か説明できますか?

4

2 に答える 2