На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
  
    > Как вызвать Ruby функцию не из нитки интерпретатора? , встраиваю интерпретатор Ruby... есть проблемы с синхронизацией
      Всем привет!

      Начал изучать Ruby интерпретатор и написал расширение на C++ на платформе Win32. Встроил расширение Ruby с помощью SWIGа. Мое расширение принимает сообщения, пересылаемые по каналу коммуникации, то есть создает сервер и ждет прихода сообщений. Если в расширении я сделаю WaitForSingleObject() и другую блокируемую операцию, то это приведет к блокировке нитки интерпретатора. При этом в Ruby я запускаю еще несколько параллельных нитей, которые также заблокируются.

      Поэтому я не могу использовать синхронные механизмы приема сообщений и вынужден пользоваться асинхронными режимами. Поэтому при старте сервера и вызове метода Run() моего расширения, я создаю новую нитку через CreateThread() (не нитка интерпретатора) и никаких блокировок не происходит, контроль возвращается нитке Ruby интерпретатора.

      Ниже написана часть моего Ruby кода, которая запускает нить, которая запускает сервер приема сообщений в новой нитке. Также я написал класс расширения RubyCallback, который реализует интерфейс обратного вызова из C++ в Ruby. У класса RubyCallback есть метод call(), который вызывает rb_funcall(). Если новых сообщений нет, то нитка Ruby receiver_thread засыпает до прихода новых сообщений, когда callback функция не пробудит нитку и не выполнится Receive() метод.

      receiver_thread = Thread.new do
      cb = RubyCallback::RubyCallback.new(Thread.current, "wakeup")

      ccinit = InterComm::CC_INIT.new
      ccinit.pAlertObject = cb #регистрирую callback

      cc = InterComm::Communication.new
      ret = cc.Init(ccinit)
      if (ret)
      puts "InterComm INIT OK"
      end
      ret = cc.Run() # here new native listener thread starts
      if (ret)
      puts "InterComm RUN OK"
      end

      loop do
      mess = cc.Receive()
      if (mess == nil)
      puts "not Receive, fall a sleep...\n"
      Thread.stop # нитка засыпает до прихода нового сообщения
      else
      puts mess.MessageData
      end
      end

      end

      Когда приходит новое сообщение, расширение вызывает callback функцию из Ruby, как бы говоря, что пришло новое сообщение, давай читай. В расширении при этом вызывается call() метод callback интерфейса, который вызывает rb_funcall(), но приложение при этом начинает себя странно вести. Очень редко такой вызов отрабатывает, но только 1 раз. Чаще приложение падает или намертво зависает в вызове rb_funcall().

      Я знаю, что Ruby интерпретатор не предназначен для многопоточного использования. Посоветуйте кто-нибудь как я могу корректно вызвать Ruby функцию в контексте нитки интепретатора из C++ не из нитки интерпретатора? Или как можно запланировать выполнение функции или поместить вызов в очередь выполнения?

      Заранее спасибо всем!
      1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
      0 пользователей:


      Рейтинг@Mail.ru
      [ Script execution time: 0,0127 ]   [ 14 queries used ]   [ Generated: 6.07.25, 10:12 GMT ]