From: Toby DiPasquale Date: 2005-10-17T07:30:39+09:00 Subject: Re: convert fd to IO object in extension? On Mon, Oct 17, 2005 at 06:31:04AM +0900, ES wrote: > > > >#include "ruby.h" > >[...] > >int fd; > >OpenFile *fptr; > > > >if (!rb_respond_to( io_obj, rb_intern( "sysread"))) > > rb_raise( rb_eTypeError, "instance of IO needed"); > >GetOpenFile( rb_io_get_io( io_obj), fptr); > >fd = fileno( fptr->f); > > > > > >Since both Socket and File are subclasses of IO, this will work for both > >network sockets and disk file I/O. The above is correct because sysread is > >currently only implemented by instances of IO. Caching the return value of > >the rb_intern( "sysread") call is also preferable (see > >ruby-1.8.3/marshal.c). > > Works. rb_io_get_io() is not available to extensions, so just get rid of that call (leaving the io_obj part) since you've already verified that its an IO instance by then (and thus GetOpenFile() and the rest will succeed). I discovered this after writing the email ;-) > Ah, I see.. I am still somewhat curious. I am assuming that you are already > storing those IO instances somewhere you can reach them. That being the case > and the IO instance *already referencing the FD*, why do you need explicit > mapping? Yeah, I wasn't ;-) I was asking the original question in order to _avoid_ having to build up such a store of IO instances. Here's what happens now: 0. Caller creates an instance of Epoll 1. Caller opens IO object of some sort 2. Caller calls Epoll#update on the new IO object, which will internally add the IO object to a Hash and also call epoll_ctl( EPOLL_CTL_ADD) to add it to the epoll device. 3. Caller calls Epoll#poll which internally calls epoll_wait(2) and when that returns, builds an array of 2-cell arrays, the first cell containing the IO object that matched the fd returned from epoll_wait(2) (resolved with the help of the Hash above) and the second cell containing the event bitmask returned for that fd. For every fd returned by epoll_wait(2), there will be a 2-cell array in the returned array from Epoll#poll. I thought I could avoid having to store all active IO objects if two things were true: a) epoll removes the fd from its device when its close(2)'d b) Ruby had a way to reverse-map a fd to an active IO instance I knew a) was true, but b) is not. Thus, I am now using a Hash, just like Zed in Ruby/Event. Consequently, this is why I want to hook into IO#close, so I can call Epoll#delete in order to remove the IO instance from the Hash (which is now necessary, since I'm keeping track of them all). > If for some reason you need to work with the sockets separately from the > IO instances (though I can not imagine why), you should still be able to > use the IO to read and write data normally. Any other socket manipulation > you can do independently of the IO, just with the sockets themselves and > then just have the IO reference its FD. Perhaps I am missing some crucial > insight to your architecture, though? No I don't need to do this. My only concern was to take the fd that epoll_wait(2) returns and somehow map it back to the IO instance so that it would be usable in the calling Ruby script. > >However, this fails because at the time of definition, the module doesn't > >have a close method. I want to shadow the close method of IO in order to > >automatically call the cleanup method in the associated Epoll object. > >Anybody know a way of doing that? I feel like I've seen this kind of thing > >before, but I can't remember where. > > You can use the hook method Module#included. This isn't working for me when I use Object#extend instead of Module#include. adidas~> irb irb(main):001:0> module A irb(main):002:1> def A.included( mod) irb(main):003:2> puts "#{self} included in #{mod}" irb(main):004:2> end irb(main):005:1> end => nil irb(main):006:0> x = "String" => "String" irb(main):007:0> x.extend A => "String" irb(main):008:0> module Enumerable irb(main):009:1> include A irb(main):010:1> end A included in Enumerable => Enumerable irb(main):011:0> quit adidas~> Any thoughts on making it work with Object#extend? -- Toby DiPasquale