
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.52] |
![]() |
|
![]() |
|
|
Всем привет!
Начал изучать 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++ не из нитки интерпретатора? Или как можно запланировать выполнение функции или поместить вызов в очередь выполнения? Заранее спасибо всем! |