2

MRI Ruby 1.9を使用して、次のようなコードがあります

def foo()
  puts "in foo"
  loop do
    puts "in foo loop"
  end
end

def bar()
  puts "in bar"
  start_alsa_listener
end

foo_thread = Thread.new { foo }
bar_thread = Thread.new { bar }
foo_thread.join
bar_thread.join

start_alsa_listener は、ALSA midi シーケンサーを開き、入力イベントを待機するブロッキング ライブラリ呼び出しです。基本的に、私は自分のコードが常に「in foo loop」に出力され、同時に ALSA midi イベントを受信して​​コンソールにも出力できるようにしたいと考えています (start_alsa_listener はイベントを受信したときに実行します)。

問題は、上記のコードを実行すると、bar() が実行されるとすぐにコンテキストが foo() に切り替わらないことです。

start_alsa_listener は、次のような Ruby C 拡張機能です。

for(;;) {
    poll(/* args */);      /* wait for input data */
    /* print data to console */
}

おそらくそれは、Ruby のスレッド化で間違っていること、またはポーリングに関係していること、または ALSA がスレッドを処理する方法に関係していることに関連している可能性があります。どんな助けでも大歓迎です。

4

2 に答える 2

3

あなたが示したループは、pollスティーブが言ったようにインタプリタ全体をブロックします(ブロックしていると仮定します)。Ruby(MRI / YARV)C APIからrb_thread_blocking_regionを使用してpoll()を呼び出す必要があります。

于 2011-04-27T15:41:13.590 に答える
2

cext がなければ、これら 2 つが並行して実行されます。GIL は、C 拡張機能を使用して 2 つのスレッドを同時に実行することはできません。これは、GIL がスレッドセーフであることを認識できないためです。

于 2011-04-27T15:34:43.173 に答える