Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > signaling a ruby thread from a win32 native thread

Reply
Thread Tools

signaling a ruby thread from a win32 native thread

 
 
Vincenzo Piombo
Guest
Posts: n/a
 
      05-06-2004
Hello,
I am working at a ruby application that needs to be notified of some hw
event provided by third party driver/DLL. It should run on Win32.
The hardware events are generated in the context of a native win32 thread,
and I need to handle them in some ruby code. The main ruby process is
meanwhile used to handle a TCP/IP dialog with a GUI.

So basically I need an event queue which a ruby thread can suspend on,
waiting for events pushed in the queue by a win32 native thread.

I did some experiment with ruby API in a ruby extension but didn't succeed
to make it work.
Can you guys tell me whether I'm trying something plainly impossible (in
that case are there alternatives ?) or am I just making some implementation
error ?

Thanks in advance for your help.

Here follows some details:
msgqueue.rb - (a working full ruby test, using SizeQueue to explain what I
want to achieve)
msgqueuesignals.c - (C code of the extension)
msgqueuesignals_test.rb - (ruby code using the msgqueuesignals.so extension)

The last approach works if I undefine the DOLOOP macro, if it is defined I
get the error:
"ERROR #<SystemStackError: c:/ruby/lib/ruby/1.8/thread.rb:259:in `push':
stack level too deep>"
after 42 iterations.

---------------------------------
# msgqueue.rb.

require "thread"

queue = SizedQueue.new(10)

pusher_thread = Thread.new {
100.times {|i|
queue.push(i)
}
queue.push("Quit")
}

popper_thread = Thread.new {
while true
o = queue.pop()
puts o
break if o == "Quit"
end
}

[pusher_thread, popper_thread].each {|t| t.join }
=================================

---------------------------------
// msgqueuesignals.c
#include <windows.h>

#include <stdio.h>
#include "ruby.h"

#define DOLOOP 1

VALUE cMsgqSignals;
int counter = 0;

DWORD WINAPI native_thread(
LPVOID lpParameter // thread data
)
{
int i;
char command[1000];
VALUE errinfo;
int error = 0;


#ifdef DOLOOP
for(i=0; i<100; i++)
{
counter++;
sprintf(command, "$queue.push('%d')", i);
rb_eval_string_protect(command, &error);
if(error)
{
errinfo = rb_inspect(ruby_errinfo);
rb_backtrace();
printf("ERROR %s\n", STR2CSTR(errinfo));
}
}
#endif

rb_eval_string("$queue.push('Quit')");

return 0;
}


static VALUE msgqs_get_count()
{
return INT2FIX(counter);
}

static VALUE msgqs_initialize(VALUE self)
{
HANDLE thread;
DWORD threadid;


rb_eval_string("$queue.push('Start')");

thread = CreateThread(
NULL, // pointer to security attributes
0, // initial thread stack size
native_thread, // pointer to thread function
(LPVOID)0, // argument for new thread
0, // creation flags
&threadid // pointer to receive thread ID
);
Sleep(1); // give the thread a chance to execute
return self;
}


__declspec(dllexport) void Init_msgqueuesignals() {
cMsgqSignals = rb_define_class("MsgQueueSignals", rb_cObject);
rb_define_method(cMsgqSignals, "initialize", msgqs_initialize, 0);
rb_define_method(cMsgqSignals, "count", msgqs_get_count, 0);

}
=================================

---------------------------------
# msgqueuesignals_test.rb
require "thread"
require "msgqueuesignals"

$stdout.sync = true
$queue = Queue.new()
native_pusher = MsgQueueSignals.new

# I need this idle thread not to get a deadlock error when joining the
popper thread
# otherwise ruby thinks no one will ever possibly wake up the popper
idle_thread = Thread.new {
while true
sleep(5000)
$queue.push("Idle")
end
}

popper_thread = Thread.new {
while true
o = $queue.pop()
puts o
break if o == "Quit"
end
}


puts "native_pusher event count: #{native_pusher.count}"
popper_thread.join
puts "native_pusher event count: #{native_pusher.count}"
=================================




 
Reply With Quote
 
 
 
 
nobu.nokada@softhome.net
Guest
Posts: n/a
 
      05-21-2004
Hi,

At Fri, 7 May 2004 03:55:54 +0900,
Vincenzo Piombo wrote in [ruby-talk:99416]:
> I am working at a ruby application that needs to be notified of some hw
> event provided by third party driver/DLL. It should run on Win32.
> The hardware events are generated in the context of a native win32 thread,
> and I need to handle them in some ruby code. The main ruby process is
> meanwhile used to handle a TCP/IP dialog with a GUI.
>
> So basically I need an event queue which a ruby thread can suspend on,
> waiting for events pushed in the queue by a win32 native thread.
>
> I did some experiment with ruby API in a ruby extension but didn't succeed
> to make it work.
> Can you guys tell me whether I'm trying something plainly impossible (in
> that case are there alternatives ?) or am I just making some implementation
> error ?


Current ruby interpreter implementation doesn't allow to be
called from other native threads.

A) You may be possible to use rb_w32_main_context(), which
signals the main thread (native thread on which ruby runs),
handshakes with it and invokes the given function in it.

B) Once I wrote a patch to improve IO.select issue, which it
also provides rb_w32_wait_for_handle() function.
http://nokada.jin.gr.jp/ruby/win32/wait_events.diff
Note that it absolutely is untested.

--
Nobu Nakada


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
JNI thread vs. native thread vs. JNI call bgabrhelik Java 0 09-29-2009 03:33 PM
About win32 native thread Wang Dong Ruby 3 01-18-2007 02:18 AM
Signaling Ruby from C/C++ Asterix Gallier Ruby 20 08-10-2006 02:14 PM
inband-dtmf signaling on Call Manager 3.3 Jim Brunetti Cisco 0 07-08-2004 09:34 PM
signaling another thread Ara.T.Howard Ruby 9 05-07-2004 10:56 PM



Advertisments