<?xml version='1.0' encoding="utf-8"?>
      <rss version='2.0'>
      <channel>
      <title>Форум на Исходниках.RU</title>
      <link>https://forum.sources.ru</link>
      <description>Форум на Исходниках.RU</description>
      <generator>Форум на Исходниках.RU</generator>
  	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=329493&amp;view=findpost&amp;p=2867028</guid>
        <pubDate>Fri, 01 Apr 2011 13:28:04 +0000</pubDate>
        <title>Как вызвать Ruby функцию не из нитки интерпретатора?</title>
        <link>https://forum.sources.ru/index.php?showtopic=329493&amp;view=findpost&amp;p=2867028</link>
        <description><![CDATA[sungurik: Всем привет&#33;<br><br>Начал изучать Ruby интерпретатор и написал расширение на C++ на платформе Win32. Встроил расширение Ruby с помощью SWIGа. Мое расширение принимает сообщения, пересылаемые по каналу коммуникации, то есть создает сервер и ждет прихода сообщений. Если в расширении я сделаю WaitForSingleObject() и другую блокируемую операцию, то это приведет к блокировке нитки интерпретатора. При этом в Ruby я запускаю еще несколько параллельных нитей, которые также заблокируются.<br><br>Поэтому я не могу использовать синхронные механизмы приема сообщений и вынужден пользоваться асинхронными режимами. Поэтому при старте сервера и вызове метода Run() моего расширения, я создаю новую нитку через CreateThread() (не нитка интерпретатора) и никаких блокировок не происходит, контроль возвращается нитке Ruby интерпретатора.<br><br>Ниже написана часть моего Ruby кода, которая запускает нить, которая запускает сервер приема сообщений в новой нитке. Также я написал класс расширения RubyCallback, который реализует интерфейс обратного вызова из C++ в Ruby. У класса RubyCallback есть метод call(), который вызывает rb_funcall(). Если новых сообщений нет, то нитка Ruby receiver_thread засыпает до прихода новых сообщений, когда callback функция не пробудит нитку и не выполнится Receive() метод. <br><br>receiver_thread = Thread.new do<br>  cb = RubyCallback::RubyCallback.new(Thread.current, &quot;wakeup&quot;)<br><br>  ccinit = InterComm::CC_INIT.new<br>  ccinit.pAlertObject = cb              #регистрирую callback<br><br>  cc = InterComm::Communication.new<br>  ret = cc.Init(ccinit)<br>  if (ret)<br>  puts &quot;InterComm INIT OK&quot;<br>  end<br>  ret = cc.Run()  # here new native listener thread starts<br>  if (ret)<br>  puts &quot;InterComm RUN OK&quot;<br>  end<br><br>  loop do<br>    mess = cc.Receive()<br>    if (mess == nil)<br>        puts &quot;not Receive, fall a sleep...&#092;n&quot;<br>        Thread.stop                       # нитка засыпает до прихода нового сообщения<br>    else<br>        puts mess.MessageData<br>    end<br>  end<br><br>end<br><br>Когда приходит новое сообщение, расширение вызывает callback функцию из Ruby, как бы говоря, что пришло новое сообщение, давай читай. В расширении при этом вызывается call() метод callback интерфейса, который вызывает rb_funcall(), но приложение при этом начинает себя странно вести. Очень редко такой вызов отрабатывает, но только 1 раз. Чаще приложение падает или намертво зависает в вызове rb_funcall().<br><br>Я знаю, что Ruby интерпретатор не предназначен для многопоточного использования.  Посоветуйте кто-нибудь как я могу корректно вызвать Ruby функцию в контексте нитки интепретатора из C++ не из нитки интерпретатора? Или как можно запланировать выполнение функции или поместить вызов в очередь выполнения?<br><br>Заранее спасибо всем&#33;]]></description>
        <author>sungurik</author>
        <category>Ruby</category>
      </item>
	
      </channel>
      </rss>
	