From: ES Date: 2005-10-17T06:31:04+09:00 Subject: Re: convert fd to IO object in extension? Toby DiPasquale wrote: > On Mon, Oct 17, 2005 at 01:43:16AM +0900, ES wrote: > >>You can use IO#for_fd to create an IO object for a given file descriptor; >>scour the source for the C function or just use rb_funcall. This, of >>course, should only be done once after which you refer to the socket >>using the IO object (you can get the FD again with IO#to_i). > > > In a C extension, this is suboptimal. You can instead use: > > > #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. >>I am not sure what you mean by maintaining a Hash; while an explicit >>data structure is by no means necessary, you (presumably) have to have >>some means of referring back to the sockets. This is what the IO object >>would provide, however you store it. Please clarify if I am understanding >>incorrectly. > > > What I meant was that I'd have to maintain a Hash mapping fd's to IO > instances. This Hash would be inserted into when the caller wanted to insert > an IO object into the epoll device. Sorry for the confusion. > > At any rate, it turns out that > > a) Ruby/Event is dead, and > b) Zed was maintaining just such a Hash for the same reason in > Ruby/Event. > > I'll just build a Hash that maps fd's to IO instances and take the memory > hit. 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? 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? >>If you find you need to do some special processing on the FD for each >>read/write/update, you might do well to just subclass IO and augment >>it with that functionality. > > > Speaking of that, that brings me to another question I had. I was trying > to extend IO as follows: > > module EpollExt > attr_accessor :epoller > alias_method :old_close, :close > def close > @epoller.delete( self) > old_close > end > end > > So, then the user of the library would have to extend their IO instances > with that module before they could be used with the Epoll object, like so: > > my_epoll = Epoll.new > [...] > x = File.open( "/tmp/my-tmp", "w") > x.extend( EpollExt) > x.epoller = my_epoll > [...] > > 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. E