3

このように作成されたファイルハンドルオブジェクトがあります(わかりやすくするために少し編集されています):

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_PVGVDevel::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

このテストに合格できるようにハンドルの作成を調整する方法についての支援をいただければ幸いです。

4

1 に答える 1

2

関連付けられたファイル ハンドルは、perl では部分的にしか実装されておらず、EV では機能しません。一般に、関連付けられたハンドルをイベント ライブラリで動作させることはできません。いくつかの特定のケースは機能する可能性がありますが、関連付けられたハンドルが使用されるほとんどの場合、基になるファイル記述子の準備通知​​が準備に関連していないため、動作しません。結ばれたハンドルの通知。

あなたの目標が実際のファイル記述子の周りにラッパーを単に持つことである場合、それを行う1つの方法は、IO::Handleおよび/またはFileHandleが行うことをコピーすることです(非常に醜いですが、perlで機能する唯一の方法です)、またはそれらを基本クラスとして使用します。これでは、読み書きをフックするなどの興味深いことはできませんが、それらをフックすると、イベント ライブラリとの互換性が失われる可能性があります。

もう 1 つの方法は、perlio レイヤー (PerlIO::via) を実装することです。私の経験では、このモジュールは少し脆弱ですが、すべてのオプションを提供します。繰り返しになりますが、ファイル記述子を実際の I/O から分離するバッファリングやさらに興味深いものを導入すると、機能しなくなります。

最後に、新しいタイプのハンドルを追加する場合は、新しいウォッチャー タイプを作成できます。これは、関数 my_handle_io_watcher を使用してハンドルを取得し、準備ができているかどうかをチェックし、必要な種類の低レベル ウォッチャーを作成するのと同じくらい簡単です。

于 2014-06-04T14:59:11.463 に答える