Re: convert fd to IO object in extension?



On Mon, Oct 17, 2005 at 06:31:04AM +0900, ES wrote:
> ><code>
> >#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);
> ></code>
> >
> >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


.



Relevant Pages

  • Re: Can I use a byte array for sound files?
    ... Sound and sockets are off-topic in comp.lang.c but there are some ... You can read *ANY* readable file into a byte array (well, ... of data from the keyboard, and disk files, but it may be a bit more ...
    (comp.lang.c)
  • Re: socket programming
    ... > using sockets we exchange text between endpoints of the socket but ... > first we convert the text to array of bytes and we send it to the other ... For sending a binary integer to an endpoint, ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: File transfer
    ... byte array of that size, ... Ciaran O''Donnell wrote: ... through sockets. ... the receivers end. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: size limit for byte array?
    ... Sockets are streaming in nature, and while you might create a 16KB byte ... array on one end and send off using 1 statement, ... Instead of breaking the loop on "less than full buffer", ... on "empty buffer". ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: [take22 0/4] kevent: Generic event handling mechanism.
    ... epoll vs. kevent_poll always showed the same rates), ... notifications as sockets for maximum perfomance. ... not aware of exact mechanisms used in epoll, kevent poll, and 'kevent' ... "It supports socket notifications, ...
    (Linux-Kernel)