将合成文件句柄与 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
任何有关我如何调整句柄的创建以使其能够通过此测试的帮助将不胜感激。
解决方案
绑定的文件把手仅在Perl中部分实现,并且不与EV一起使用。与事件库一般不能制作绑定的手柄:尽管某些特定情况可能会起作用,但在大多数情况下使用绑定的手柄,它们无法工作,因为基础文件描述符的准备性通知与绑定的手柄的准备性通知无关。
如果您的目标是仅围绕真实文件描述符包装包装器,那么它的一种方法是复制IO :: whand和/或fileHandle的操作(非常丑陋,但在Perl中起作用)或将它们用作基础类。这不允许您执行有趣的事情,例如挂钩阅读和写作,但是很可能会使它们与事件库不兼容。
另一种方法是实现 perlio 层 (PerlIO::via)。根据我的经验,这个模块有点脆弱,但是为您提供了所有选项。同样,如果您引入缓冲或更有趣的内容,将文件描述符与实际I/O分解,则无法使其工作。
最后,如果要添加一种新类型的句柄,则可以创建一个新的观察器类型。这可能很简单,就像拥有一个函数my_handle_io_watcher那样拿走您的手柄,检查准备就绪并创建所需的低级观察器。
不隶属于 StackOverflow