首页 \ 问答 \ 使用EV(perl)的合成文件句柄(Using synthetic filehandle with EV (perl))

使用EV(perl)的合成文件句柄(Using synthetic filehandle with 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

任何有关如何调整我的句柄创建以便它可以通过此测试的帮助将不胜感激。


I have a filehandle object that is created thus (edited slightly for clarity):

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;

I want to use this with AnyEvent. It works fine with AnyEvent::Impl::Perl but fails with AnyEvent::Impl::EV. I think that I have tracked it down to this method from 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;
}

I think it is failing the SvTYPE (fh) == SVt_PVGV test. Using Devel::Peek's Dump() method I get:

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

Any assistance as to how I might adjust the creation of my handle such that it can pass this test would be appreciated.


原文:https://stackoverflow.com/questions/24009981
更新时间:2022-11-14 15:11

最满意答案

我没有测试过这个,但它应该工作:

phasePath = '/phases/img/';

(function getTheData() {
    $.get("db.php?tstamp=1", function(data){ $("#tstamp p").html(data); });

    $("div[id^=phase]").each(function() {
        var phaseId = $(this).attr('id').substr(5);

        $.get("db.php?phase=" + phaseId, function(data){
            var phaseVal = data;

            if(phaseVal >= 500) {
                var phaseImg = 'red.png';
            } else {
                if(phaseVal >= 400) {
                    var phaseImg = 'amber.png';
                } else {
                    var phaseImg = 'green.png';
                }
            }

            $("p", this).html(data);
            $("img", this).attr("src", phasePath + phaseImg);
        });
    });
})();

setInterval(getTheData, 6000);

希望这可以帮助。


I haven't tested this, but it should work:

phasePath = '/phases/img/';

(function getTheData() {
    $.get("db.php?tstamp=1", function(data){ $("#tstamp p").html(data); });

    $("div[id^=phase]").each(function() {
        var phaseId = $(this).attr('id').substr(5);

        $.get("db.php?phase=" + phaseId, function(data){
            var phaseVal = data;

            if(phaseVal >= 500) {
                var phaseImg = 'red.png';
            } else {
                if(phaseVal >= 400) {
                    var phaseImg = 'amber.png';
                } else {
                    var phaseImg = 'green.png';
                }
            }

            $("p", this).html(data);
            $("img", this).attr("src", phasePath + phaseImg);
        });
    });
})();

setInterval(getTheData, 6000);

Hope this helps.

相关问答

更多