Использование синтетического дескриптора файла с EV (perl)
У меня есть объект файлового дескриптора, который создан таким образом (слегка отредактирован для ясности):
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;
Я хочу использовать это с AnyEvent
, Работает нормально с AnyEvent::Impl::Perl
но терпит неудачу с AnyEvent::Impl::EV
, Я думаю, что я проследил это до этого метода из 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;
}
Я думаю, что это терпит неудачу SvTYPE (fh) == SVt_PVGV
тестовое задание. С помощью Devel::Peek
Dump() метод, который я получаю:
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
Буду признателен за любую помощь в том, как я могу настроить создание моего дескриптора так, чтобы он мог пройти этот тест.
1 ответ
Связанные файловые дескрипторы только частично реализованы в Perl и не работают с EV. Связанные дескрипторы нельзя заставить работать с библиотекой событий в целом: хотя некоторые конкретные случаи могут работать, в большинстве случаев, когда используются связанные дескрипторы, они не могут работать, поскольку уведомление о готовности базового дескриптора файла не относится к готовности уведомления о связанной ручке.
Если ваша цель - просто обернуть вещи вокруг реального файлового дескриптора, то один из способов сделать это - скопировать то, что делают IO::Handle и / или FileHandle (очень уродливо, но единственный способ, который работает в perl), или использовать их в качестве базовых классов. Это не позволяет вам делать интересные вещи, такие как перехват чтения и записи, но есть вероятность, что их перехватывание делает их несовместимыми с библиотеками событий.
Другой способ - реализовать слой Perlio (PerlIO::via). По моему опыту, этот модуль немного хрупок, но дает вам все варианты. Опять же, если вы введете буферизацию или более интересные вещи, которые отделяют дескриптор файла от фактического ввода-вывода, тогда он не сможет работать.
Наконец, если вы хотите добавить новый тип дескриптора, вы можете создать новый тип наблюдателя. Это может быть так же просто, как наличие функции my_handle_io_watcher, которая берет ваш дескриптор, проверяет готовность и создает требуемый вид наблюдателя низкого уровня.