Ruby Threading не будет переключать контекст - PullRequest
2 голосов
/ 27 апреля 2011

Использование 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 - это блокирующий вызов библиотеки, который открывает MIDI-секвенсор ALSA и ожидает входные события в нем.По сути, я хочу, чтобы мой код постоянно печатался «в цикле foo» и в то же время мог получать события MIDI ALSA и распечатывать их также на консоль (что start_alsa_listener делает, когда получает событие).

Проблема в том, что когда я запускаю приведенный выше код, при запуске bar () он никогда не переключается обратно на foo ().

start_alsa_listener - это расширение ruby ​​C, которое выглядит следующим образом:

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

Возможно, это связано с тем, что в Ruby я что-то не так делаю с потоками, или, может быть, что-то связано с опросом, или, возможно, что-то связано с тем, как ALSA обрабатывает потоки.Любая помощь приветствуется.

Ответы [ 2 ]

3 голосов
/ 27 апреля 2011

Показанный вами цикл заблокирует весь интерпретатор (при условии, что poll блокирует), как сказал Стив. Вам нужно вызвать poll (), используя rb_thread_blocking_region из API Ruby (MRI / YARV) C.

2 голосов
/ 27 апреля 2011

Без cext эти двое бегут в паралеле.GIL не позволяет двум потокам работать одновременно с расширением C, потому что он не может знать, что он потокобезопасен.

...