Pergunta

Eu tenho um objeto filehandle que é criado assim (editado um pouco para maior clareza):

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;

Eu quero usar isso com AnyEvent.Funciona bem com AnyEvent::Impl::Perl mas falha comAnyEvent::Impl::EV.Acho que rastreei esse método desde 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;
}

Eu acho que está falhando SvTYPE (fh) == SVt_PVGV teste.Usando Devel::Peekmétodo Dump() que recebo:

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

Qualquer assistência sobre como eu poderia ajustar a criação do meu identificador para que ele passasse neste teste seria apreciada.

Foi útil?

Solução

As alças de arquivo amarradas são implementadas apenas parcialmente no Perl e não funcionam com o EV.Manças amarradas não podem ser feitas para trabalhar com uma biblioteca de eventos em geral:Embora alguns casos específicos possam funcionar, na maioria dos casos em que as alças amarradas são usadas, elas não podem funcionar porque a notificação de prontidão de um descritor de arquivo subjacente não se relaciona com as notificações de prontidão do identificador amarrado.

Se o seu objetivo é apenas ter um embalagem em torno de um descritor de arquivo real, uma maneira de fazer isso é copiar o que io :: handle e/ou FileHandle Do (muito feio, mas a única maneira que funciona em Perl) ou Use -os como classes base.Isso não permite que você faça coisas interessantes, como conectar leituras e gravações, mas as chances estão conectadas as torna incompatíveis com as bibliotecas de eventos.

Outra forma é implementar uma camada perlio (PerlIO::via).Na minha experiência, este módulo é um pouco frágil, mas oferece todas as opções.Novamente, se você apresentar buffers ou coisas mais interessantes que desacoplam o descritor de arquivos da E/S real, não pode ser feito para funcionar.

Por fim, se você deseja adicionar um novo tipo de alça, poderá criar um novo tipo de observador.Isso pode ser tão simples quanto ter uma função my_handle_io_watcher que leva o seu identificador, verifica a prontidão e cria o tipo de observador de baixo nível necessário.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top