# Hello, and a question about finding a defined Class from C

**URL:** <https://www.ruby-forum.com/t/hello-and-a-question-about-finding-a-defined-class-from-c/70136>\
**Category:** Ruby\
**Created:** [February 18, 2006, 8:00pm UTC](https://www.ruby-forum.com/t/hello-and-a-question-about-finding-a-defined-class-from-c/70136 "2006-02-18T20:00:21Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jacob\_Repp](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/848f3c/32.png) [@Jacob\_Repp](https://www.ruby-forum.com/u/Jacob_Repp)\
**Post date:** [February 18, 2006, 8:00pm UTC](https://www.ruby-forum.com/t/hello-and-a-question-about-finding-a-defined-class-from-c/70136/1 "2006-02-18T20:00:21Z")

</div>

First of all I would like to say Hello! I am new to Ruby programming  
having just started a few days ago. I have been watching the ruby  
language with interest for a number of years now but finally got the  
interest to dive in. I must say it has been an absolute joy.

If this is the wrong list for a question of this type I would be happy  
to post it elsewhere.

My first project was a UDP client/server which went well up until I  
ran the problem of blocking kernel calls. I have used the ‘io/wait’  
extension which works nicely for simple purposes but for fun I’ve  
written an extension for Win32 IO Completion Ports.

I have the binding code written but currently I cannot get a VALUE  
representing the TCPSocket Class object. I’m trying to define the  
methods async\_send and async\_read in the TCPSocket class currently as  
a test.

```
id = rb_intern("TCPSocket");
if (rb_const_defined(rb_cObject, id))
{
     cTCPSocket = rb_const_get(rb_cObject, id);
     if (TYPE(cTCPSocket) != T_CLASS) {
         rb_raise(rb_eTypeError, "%s is not a class", "TCPSocket");
     }

     rb_define_method(cTCPSocket, "async_send", rb_async_send, 2);
     rb_define_method(cTCPSocket, "async_recv", rb_async_recv, 2);
}
else
{
    rb_raise(rb_eTypeError, "class 'TCPSocket' was not defined you

```

must require ‘socket’");  
}

When I execute the code:

require ‘socket’  
puts Object.constants

I see the constant TCPSocket is defined.

---

<div class="post-metadata">

**Author:** ![Jacob\_Repp](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/848f3c/32.png) [@Jacob\_Repp](https://www.ruby-forum.com/u/Jacob_Repp)\
**Post date:** [February 18, 2006, 8:24pm UTC](https://www.ruby-forum.com/t/hello-and-a-question-about-finding-a-defined-class-from-c/70136/2 "2006-02-18T20:24:38Z")

</div>

Not long after sending this I ran a little experiment to validate the  
symbol IDs were the same between script and C code. My code below was  
correct, the problem was that I was passing -r AIO on the command line  
(in my debugger settings). Hence my extension init was running before  
I had run the require ‘socket’ statement.

If anyone is interested in a IOCP wrapper for ruby on win32 I would  
like to get some feedback/testing on the implementation.

Thanks, -j

---

<div class="post-metadata">

**Author:** ![Jacob\_Repp](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/848f3c/32.png) [@Jacob\_Repp](https://www.ruby-forum.com/u/Jacob_Repp)\
**Post date:** [February 18, 2006, 9:37pm UTC](https://www.ruby-forum.com/t/hello-and-a-question-about-finding-a-defined-class-from-c/70136/3 "2006-02-18T21:37:14Z")

</div>

Jacob Repp wrote:  
…

> My first project was a UDP client/server which went well up until I  
> ran the problem of blocking kernel calls. I have used the ‘io/wait’  
> extension which works nicely for simple purposes but for fun I’ve  
> written an extension for Win32 IO Completion Ports.

Just wondering, why did you decide not to use ruby threads to wait on  
the UDP sockets?

---

<div class="post-metadata">

**Author:** ![Jacob\_Repp](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/848f3c/32.png) [@Jacob\_Repp](https://www.ruby-forum.com/u/Jacob_Repp)\
**Post date:** [February 18, 2006, 10:01pm UTC](https://www.ruby-forum.com/t/hello-and-a-question-about-finding-a-defined-class-from-c/70136/4 "2006-02-18T22:01:30Z")

</div>

It’s not that simple. For example:

# server

server = Thread.new {  
s = UDPSocket.open  
s.bind(nil, 5000)  
while(true)  
data, cli = s.recvfrom(256)  
puts “Server got #{data} from #{cli}”  
Thread.pass  
end  
}  
client = Thread.new {  
s = UDPSocket.open  
s.connect(‘localhost’, 5000)  
while(true)  
s.send(“hello”, 0)  
Thread.pass  
end  
}

The problem occurs on the first call that the sever thread makes to  
recvfrom(). This is a blocking call and since ruby is actually a  
single threaded process (with virtual soft threads) this hangs all of  
the other virtual threads. So for my test app which is trying to run a  
simulation thread as well as handle socket and console IO this becomes  
a problem quickly.

You can get around with ‘io/wait’ with the added ‘ready?’ method:  
while(len = s.ready?)  
data, cli = s.recvfrom(len)

Since I was looking for something to cut my teeth on anyways I decided  
to write an AIO module that mixes async methods into the existing  
socket implementation.

When you require ‘AIO’ it mixes in the methods async\_send(to),  
async\_recv(to), async\_accept, async\_connect.

I’m currently experimenting with how best to handle the completion  
handling. My current thinking is that the IO completion performs a  
specified ruby method call on a receiver. I originally thought I would  
pass a block to the async\* methods to execute on completion but the  
problem is that you usually want to re-call the async method at which  
point you would need another block… kinda messy.

I’m still playing with this part though

---

<div class="post-metadata">

**Author:** ![Jacob\_Repp](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/848f3c/32.png) [@Jacob\_Repp](https://www.ruby-forum.com/u/Jacob_Repp)\
**Post date:** [February 18, 2006, 10:50pm UTC](https://www.ruby-forum.com/t/hello-and-a-question-about-finding-a-defined-class-from-c/70136/5 "2006-02-18T22:50:14Z")

</div>

Jacob Repp wrote:

> end  
> The problem occurs on the first call that the sever thread makes to  
> recvfrom(). This is a blocking call and since ruby is actually a  
> single threaded process (with virtual soft threads) this hangs all of  
> the other virtual threads. So for my test app which is trying to run a  
> simulation thread as well as handle socket and console IO this becomes  
> a problem quickly.

That code works fine for me, using ruby-1.8.4, both linux and windows  
(the one-click msvc-built version).

Also, the Thread.pass is not needed.

I did add a line at the end:

sleep

(You could also use Thread.join(client) or similar.)

---

<div class="post-metadata">

**Author:** ![Jacob\_Repp](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/848f3c/32.png) [@Jacob\_Repp](https://www.ruby-forum.com/u/Jacob_Repp)\
**Post date:** [February 19, 2006, 12:36am UTC](https://www.ruby-forum.com/t/hello-and-a-question-about-finding-a-defined-class-from-c/70136/6 "2006-02-19T00:36:24Z")

</div>

Jacob Repp wrote:

> I followed up and it seems that you’re right, I had assumed the recv  
> was blocking the whole process but it was not. Based on what I’ve seen  
> after some further testing it seems that ‘Kernel#gets’ and  
> ‘Socket#connect’ can both block the process. Is this correct?

Yes, unfortunately, AFAIK. These are known problems on windows.

Search for “gets windows block sockets” on comp.lang.ruby:

[http://groups.google.com/group/comp.lang.ruby/search?group=comp.lang.ruby&q=gets+windows+block+sockets&qt\_g=1&searchnow=Search+this+group](http://groups.google.com/group/comp.lang.ruby/search?group=comp.lang.ruby&q=gets+windows+block+sockets&qt_g=1&searchnow=Search+this+group)

---

<div class="post-metadata">

**Author:** ![Jacob\_Repp](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/848f3c/32.png) [@Jacob\_Repp](https://www.ruby-forum.com/u/Jacob_Repp)\
**Post date:** [February 18, 2006, 11:14pm UTC](https://www.ruby-forum.com/t/hello-and-a-question-about-finding-a-defined-class-from-c/70136/7 "2006-02-18T23:14:34Z")

</div>

I followed up and it seems that you’re right, I had assumed the recv  
was blocking the whole process but it was not. Based on what I’ve seen  
after some further testing it seems that ‘Kernel#gets’ and  
‘Socket#connect’ can both block the process. Is this correct?

Here’s another test using TCPSocket that works just fine as you  
suggested. If you comment out the lines at the bottom where I would  
try to read from the console it freezes the application.

Opening multiple telnet sessions to localhost:5000 shows multiple  
connection threads operating in parallel.

require ‘socket’

def handle\_session(sess)  
puts “accepted session from #{sess}”  
sclient = Thread.new {  
while(1)  
data, cli = sess.recv(256)  
puts “Server got #{data} from #{sess}”  
end  
}  
end  
server = Thread.new {  
s = TCPServer.new(nil, 5000)  
while(true)  
puts “ready to accept next session…”  
sess = s.accept  
handle\_session(sess)  
end  
}  
client = Thread.new {  
s = TCPSocket.open(‘localhost’, 5000)  
puts “client connected…”  
while(true)  
puts “sending hello”  
s.send(“hello”, 0)  
sleep 1  
end  
}  
sleep  
#while(true)  
#line = gets  
#puts line  
#end
