使用EV(perl)的合成文件句柄

时间:2014-06-03 08:02:00

标签: perl libev anyevent

我有一个创建的文件句柄对象(为了清晰起见,略微编辑):

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 个答案:

答案 0 :(得分:2)

绑定文件句柄仅部分在perl中实现,并且不起作用 与EV。绑定的句柄不能与事件库一起使用 general:虽然某些特定情况可能有效但在大多数情况下都是并列的 使用句柄,因为准备通知而无法工作 底层文件描述符与准备就绪通知无关 绑手。

如果你的目标只是在真实文件周围有一个东西包装器 描述符,然后一种方法是复制IO :: Handle和/或 FileHandle做(非常难看,但是在perl中工作的唯一方式),或者使用 它们作为基类。这不允许你做有趣的事情 比如挂钩读写,但是抓住它们的可能性就是它们 与事件库不兼容。

另一种方法是实现perlio层(PerlIO :: via)。在我的 经验,这个模块有点脆弱,但给你所有的 选项。再次,如果你介绍缓冲或更有趣的事情 将文件描述符与实际I / O分离,然后无法进行 工作

最后,如果要添加新类型的句柄,则可以创建 一种新的观察者类型。这可以像拥有一个功能一样简单 my_handle_io_watcher接受你的处理,检查准备情况和 创造了所需的低级观察者。