Ruby thread feat. win32 message cycle

Hi all.
I’ve tried the simple code:

Thread.new{ runMessageCycle}
puts ‘here’

where runMessageCycle is a simple C extension method with Win32 message
cycle:

static VALUE run(VALUE _self)
{
MSG msg;
while (::GetMessage(&msg, NULL, 0, 0))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}

return _self;

}

I’m very surprised that Thread.new don’t returns (“here” will be never
printed).
What is silly with my code?

Thanks,
Victor.

My guess would be that runMessageCycle never returns (until the while
loop
breaks, anyway) so Ruby never gets a chance to execute any more code.
The C
code in the extension doesn’t know anything about Ruby’s thread
scheduler. I
haven’t tried this, but what if you called rb_thread_select with an
empty
descriptor set on each pass through the while loop?

From: Francis C. [mailto:[email protected]]
Sent: Friday, June 30, 2006 5:29 AM

I
haven’t tried this, but what if you called rb_thread_select with an empty
descriptor set on each pass through the while loop?

BTW, where can I find simple examples of usage of rb_thread_select. I’m
very-very not familiar with it :frowning:

V.

From: Francis C. [mailto:[email protected]]
Sent: Friday, June 30, 2006 5:29 AM

}

I’m very surprised that Thread.new don’t returns (“here” will be never
printed).
What is silly with my code?
My guess would be that runMessageCycle never returns (until the while loop
breaks, anyway) so Ruby never gets a chance to execute any more code.

Yes, It never returns. But I’ve thought its not a problem, because in
the
code:
Thread.new{ sleep(10000) }
puts ‘here’
sleep(10000) also virtually never returns, but code works as expected
(prints ‘here’ and exits).

The C
code in the extension doesn’t know anything about Ruby’s thread scheduler.
I
haven’t tried this, but what if you called rb_thread_select with an empty
descriptor set on each pass through the while loop?

Hmmm… Ok, I’ll try. But I think there must be more general solution
for
threading C extension. No?

V.

On 6/29/06, Victor ‘Zverok’ Shepelev [email protected] wrote:

BTW, where can I find simple examples of usage of rb_thread_select. I’m
very-very not familiar with it :frowning:
<<<<<<<<<<<<

None that I’m aware of. If you can’t find anything easier, look in the
source code of EventMachine (grep in the .h files).

On 6/29/06, Victor ‘Zverok’ Shepelev [email protected] wrote:

Yes, It never returns. But I’ve thought its not a problem, because in the
code:
Thread.new{ sleep(10000) }
puts ‘here’
sleep(10000) also virtually never returns, but code works as expected
(prints ‘here’ and exits).
<<<<<<<<<<<<<<<<<<<<<

sleep(10000) is a Ruby call, not a native one. It’s aware that other
Ruby
threads are running. Try doing the same thing on your native thread with
a
native API (I forget what that millisecond-sleep API is on Windows)-
you’ll
find that it blocks your program just as the event loop did.

Hmmm… Ok, I’ll try. But I think there must be more general solution
for
threading C extension. No?<<<<<<<<<<<<<<<<<

You’re wandering into the strange land of native/green thread
interaction. I
won’t be the one to start yet another rehash of this subject ;-). If
you’re
trying to run the Windows GUI event loop, why not just use Ruby tk?

From: Francis C. [mailto:[email protected]]
Sent: Friday, June 30, 2006 6:29 AM

sleep(10000) is a Ruby call, not a native one. It’s aware that other Ruby
threads are running. Try doing the same thing on your native thread with a
native API (I forget what that millisecond-sleep API is on Windows)-
you’ll
find that it blocks your program just as the event loop did.

OK, I’ve got it.

Hmmm… Ok, I’ll try. But I think there must be more general solution
for
threading C extension. No?<<<<<<<<<<<<<<<<<

You’re wandering into the strange land of native/green thread interaction.
I
won’t be the one to start yet another rehash of this subject ;-). If
you’re
trying to run the Windows GUI event loop, why not just use Ruby tk?

Because I’m doing my own GUI library :)))
BTW, here is the solution of my problem (and thank you, the solution was
very close to your advice!):
static VALUE run(VALUE _self)
{
MSG msg;
while (1)
{
::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); //the 1st
gotcha! We need Peek, not Get message
::TranslateMessage(&msg);
::DispatchMessage(&msg);
if(msg.message == WM_QUIT) break;
rb_thread_schedule(); //second gotcha! Give ruby’s scheduler
the possibility to switch
}

return _self;

}

V.

Put some printfs in the C code - I think you’ll find it never gets out
of
GetMessage. If your thread has no windows it may have no events… or
it it
returns a negative value you’ll stay in the loop as long as it gets
errors.

good luck!
JB

From: John B. [mailto:[email protected]]
Sent: Friday, June 30, 2006 7:19 AM

}

I’m very surprised that Thread.new don’t returns (“here” will be never
printed).
Put some printfs in the C code - I think you’ll find it never gets out of
GetMessage. If your thread has no windows it may have no events… or it
it
returns a negative value you’ll stay in the loop as long as it gets
errors.

I’ve already found the solution. In fact, there were 2 errors:

  1. I had to use PeekMessage instead of GetMessage
  2. I had to do rb_thread_schedule() to let Ruby’s scheduler to switch
    threads.

V.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs