I have a filehandle object that is created thus (edited slightly for clarity):
sub TIEHANDLE
{
return $_[0] if ref($_[0]);
my $class = shift;
my $self = bless Symbol::gensym(), $class;
return $self;
}
sub new
{
my ($class, $fh, $chunk, $interval, $cb) = @_;
my $self = bless Symbol::gensym(), ref($class) || $class;
tie *$self, $self;
my $data = {
fh => $fh,
};
${*$self}{'data'} = $data;
return $self;
}
sub fileno
{
my $self = $_[0];
return ${*$self}{'data'}->{'fh'}->fileno();
}
*FILENO = \&fileno;
I want to use this with AnyEvent
. It works fine with AnyEvent::Impl::Perl
but fails with
AnyEvent::Impl::EV
. I think that I have tracked it down to this method from EV
:
static int
s_fileno (SV *fh, int wr)
{
dTHX;
SvGETMAGIC (fh);
if (SvROK (fh))
{
fh = SvRV (fh);
SvGETMAGIC (fh);
}
if (SvTYPE (fh) == SVt_PVGV)
return PerlIO_fileno (wr ? IoOFP (sv_2io (fh)) : IoIFP (sv_2io (fh)));
if (SvOK (fh) && (SvIV (fh) >= 0) && (SvIV (fh) < 0x7fffffffL))
return SvIV (fh);
return -1;
}
I think it is failing the SvTYPE (fh) == SVt_PVGV
test. Using Devel::Peek
's Dump() method I get:
SV = PVMG(0x9c98460) at 0x44313b0
REFCNT = 1
FLAGS = (PADMY,ROK)
IV = 0
NV = 0
RV = 0x9c21d00
SV = PVGV(0x9c35510) at 0x9c21d00
REFCNT = 1
FLAGS = (OBJECT,RMG,MULTI)
MAGIC = 0x9a68ee0
MG_VIRTUAL = &PL_vtbl_backref
MG_TYPE = PERL_MAGIC_backref(<)
MG_OBJ = 0x9c217a8
STASH = 0x4374440 "MetadataStream"
NAME = "GEN5"
NAMELEN = 4
GvSTASH = 0x25d01c8 "Symbol"
GP = 0x9a43d50
SV = 0x0
REFCNT = 1
IO = 0x9c214a8
FORM = 0x0
AV = 0x0
HV = 0x9c21ce8
CV = 0x0
CVGEN = 0x0
LINE = 102
FILE = "/usr/share/perl5/Symbol.pm"
FLAGS = 0x2
EGV = 0x9c21d00 "GEN5"
PV = 0x9c21d00 ""
CUR = 0
LEN = 0
Any assistance as to how I might adjust the creation of my handle such that it can pass this test would be appreciated.
tied file handles are only partially implemented in perl, and don't work with EV. Tied handles cannot be made to work with an event library in general: While some specific cases might work, in most cases where tied handles are used, they can't work because the readiness notification of an underlying file descriptor doesn't relate to readiness notifications of the tied handle.
If your goal is to merely have a thing wrapper around a real file descriptor, then one way to do it is to copy what IO::Handle and/or FileHandle do (very ugly, but the only way that works in perl), or use them as base classes. This doesn't allow you to do interesting things such as hooking reads and writes, but chances are hooking them makes them incompatible with event libraries.
Another way is to implement a perlio layer (PerlIO::via). In my experience, this module is a bit fragile, but gives you all the options. Again, if you introduce buffering or more interesting things that decouple the file descriptor from the actual I/O, then it can't be made to work.
Lastly, if you want to add a new type of handle, then you can create a new watcher type. This can be as simple as having a function my_handle_io_watcher that takes your handle, checks for readiness and creates the kind of low-level watcher that is required.