A reference to a hash member? (to an object's member variable)

Discussion in 'Perl Misc' started by A. Farber, Aug 22, 2008.

  1. A. Farber

    A. Farber Guest

    Hello,

    I have an object, which reads a header
    from a non-blocking socket and if the header
    indicates, that there is more data to read
    (a chat string) then it will read that too.

    To handle those 2 reading states
    (reading a header; reading a chat string)
    I try to use 3 variables: $buf, $toread, $offset
    and then call sysread($buf, $toread, $offset).

    My problem is, that I need to set
    $buf to _point_ to $self->{REQ_HEADER}
    in the 1st state and to $self->{CHAT}
    in the 2nd state. But I don't know how.

    In C-code (which I'm trying to port to Perl)
    this has been very easy. But in Perl I don't
    know how and rereading "perlref" doesn't help.

    Any hints please?
    Alex

    PS: My complete, but buggy code is below:

    sub read {
    my $self = shift;
    my $fh = $self->{FH};
    my ($buf, $toread, $offset, $nbytes);

    # start or continue reading the request header
    if ($self->{NREAD} < REQ_HEADER_LEN) {
    $buf = $self->{REQ_HEADER};
    $offset = $self->{NREAD};
    $toread = REQ_HEADER_LEN - $offset;
    # start or continue reading the chat string
    } else {
    $buf = $self->{CHAT};
    $offset = $self->{NREAD} - REQ_HEADER_LEN;
    $toread = $self->{LEN} - $offset;
    }

    # XXX the buf is WRONG here:
    $nbytes = $fh->sysread($buf, $toread, $offset);

    unless (defined $nbytes) {
    # interrupted by signal or would block - retry later
    return if $!{EINTR} || $!{EAGAIN} || $!{EWOULDBLOCK};
    # connection interrupted - remove the Apache child
    $self->remove($fh);
    return;
    }

    if (0 == $nbytes) {
    # connection closed - remove the Apache child
    $self->remove($fh);
    return;
    }

    $self->{NREAD} += $nbytes;
    print STDERR "nbytes = $nbytes\n";

    # not done yet - continue reading
    return if $nbytes < $toread;

    if (REQ_HEADER_LEN == $self->{NREAD}) {
    ($self->{SID}, $self->{EVENT}, $self->{MOD}, $self-
    >{LEN}) =

    unpack 'A32xN3', $self->{REQ_HEADER};

    printf STDERR "sid=%s, event=%x, mod=%x, len=%x\n",
    $self->{SID}, $self->{EVENT}, $self->{MOD}, $self-
    >{LEN};


    # not done yet - continue reading (the chat string)
    return if $self->{LEN} > 0;
    }

    print STDERR "done reading";
    #$Poll->mask($fh => POLLOUT);
    }
    A. Farber, Aug 22, 2008
    #1
    1. Advertising

  2. A. Farber

    Guest

    On Fri, 22 Aug 2008 14:15:24 -0700 (PDT), "A. Farber" <> wrote:

    >Hello,
    >
    >I have an object, which reads a header
    >from a non-blocking socket and if the header
    >indicates, that there is more data to read
    >(a chat string) then it will read that too.
    >
    >To handle those 2 reading states
    >(reading a header; reading a chat string)
    >I try to use 3 variables: $buf, $toread, $offset
    >and then call sysread($buf, $toread, $offset).
    >
    >My problem is, that I need to set
    >$buf to _point_ to $self->{REQ_HEADER}
    >in the 1st state and to $self->{CHAT}
    >in the 2nd state. But I don't know how.
    >
    >In C-code (which I'm trying to port to Perl)
    >this has been very easy. But in Perl I don't
    >know how and rereading "perlref" doesn't help.
    >
    >Any hints please?
    >Alex
    >
    >PS: My complete, but buggy code is below:
    >
    >sub read {
    > my $self = shift;
    > my $fh = $self->{FH};
    > my ($buf, $toread, $offset, $nbytes);
    >
    > # start or continue reading the request header
    > if ($self->{NREAD} < REQ_HEADER_LEN) {
    > $buf = $self->{REQ_HEADER};
    > $offset = $self->{NREAD};
    > $toread = REQ_HEADER_LEN - $offset;
    > # start or continue reading the chat string
    > } else {
    > $buf = $self->{CHAT};
    > $offset = $self->{NREAD} - REQ_HEADER_LEN;
    > $toread = $self->{LEN} - $offset;
    > }
    >
    > # XXX the buf is WRONG here:
    > $nbytes = $fh->sysread($buf, $toread, $offset);
    >
    > unless (defined $nbytes) {
    > # interrupted by signal or would block - retry later
    > return if $!{EINTR} || $!{EAGAIN} || $!{EWOULDBLOCK};
    > # connection interrupted - remove the Apache child
    > $self->remove($fh);
    > return;
    > }
    >
    > if (0 == $nbytes) {
    > # connection closed - remove the Apache child
    > $self->remove($fh);
    > return;
    > }
    >
    > $self->{NREAD} += $nbytes;
    > print STDERR "nbytes = $nbytes\n";
    >
    > # not done yet - continue reading
    > return if $nbytes < $toread;
    >
    > if (REQ_HEADER_LEN == $self->{NREAD}) {
    > ($self->{SID}, $self->{EVENT}, $self->{MOD}, $self-
    >>{LEN}) =

    > unpack 'A32xN3', $self->{REQ_HEADER};
    >
    > printf STDERR "sid=%s, event=%x, mod=%x, len=%x\n",
    > $self->{SID}, $self->{EVENT}, $self->{MOD}, $self-
    >>{LEN};

    >
    > # not done yet - continue reading (the chat string)
    > return if $self->{LEN} > 0;
    > }
    >
    > print STDERR "done reading";
    > #$Poll->mask($fh => POLLOUT);
    >}


    I don't know for sure if "$fh->sysread() is valid (it may be),
    but did you try this:

    $nbytes = sysread($fh, $buf, $toread, $offset);

    -------

    sysread FILEHANDLE,SCALAR,LENGTH,OFFSET

    Also, OFFSET, in this case, is not the file offset. But I don't
    know what your trying to achieve.

    "An OFFSET may be specified to place the read data at some place in
    the string other than the beginning. A negative OFFSET specifies
    placement at that many characters counting backwards from the end
    of the string. A positive OFFSET greater than the length of SCALAR
    results in the string being padded to the required size with "\0"
    bytes before the result of the read is appended"


    sln
    , Aug 22, 2008
    #2
    1. Advertising

  3. A. Farber

    Ben Morrow Guest

    Quoth "A. Farber" <>:
    > Hello,
    >
    > I have an object, which reads a header
    > from a non-blocking socket and if the header
    > indicates, that there is more data to read
    > (a chat string) then it will read that too.
    >
    > To handle those 2 reading states
    > (reading a header; reading a chat string)
    > I try to use 3 variables: $buf, $toread, $offset
    > and then call sysread($buf, $toread, $offset).
    >
    > My problem is, that I need to set
    > $buf to _point_ to $self->{REQ_HEADER}
    > in the 1st state and to $self->{CHAT}
    > in the 2nd state. But I don't know how.


    Use

    $bufref = \$self->{REQ_HEADER};

    to take a reference, and

    sysread($$bufref, $toread, $offset);

    to read into the variable referenced. Now go and reread perlref (again
    :) ) and figure out why it works. Note that the first line parses as

    $bufref = \( $self->{REQ_HEADER} );

    and you could write it like that if you think it's clearer.

    If you really object to the explicit ref syntax, you could use
    Data::Alias:

    use Data::Alias;

    alias $buf = $self->{REQ_HEADER};

    but you will need to learn to use references, in the long run.

    Ben

    --
    It will be seen that the Erwhonians are a meek and long-suffering people,
    easily led by the nose, and quick to offer up common sense at the shrine of
    logic, when a philosopher convinces them that their institutions are not based
    on the strictest morality. [Samuel Butler, paraphrased]
    Ben Morrow, Aug 22, 2008
    #3
  4. A. Farber

    Guest

    On Fri, 22 Aug 2008 21:53:40 GMT, wrote:

    >On Fri, 22 Aug 2008 14:15:24 -0700 (PDT), "A. Farber" <> wrote:
    >
    >>Hello,
    >>
    >>I have an object, which reads a header
    >>from a non-blocking socket and if the header
    >>indicates, that there is more data to read
    >>(a chat string) then it will read that too.
    >>
    >>To handle those 2 reading states
    >>(reading a header; reading a chat string)
    >>I try to use 3 variables: $buf, $toread, $offset
    >>and then call sysread($buf, $toread, $offset).
    >>
    >>My problem is, that I need to set
    >>$buf to _point_ to $self->{REQ_HEADER}
    >>in the 1st state and to $self->{CHAT}
    >>in the 2nd state. But I don't know how.
    >>
    >>In C-code (which I'm trying to port to Perl)
    >>this has been very easy. But in Perl I don't
    >>know how and rereading "perlref" doesn't help.
    >>
    >>Any hints please?
    >>Alex
    >>
    >>PS: My complete, but buggy code is below:
    >>
    >>sub read {
    >> my $self = shift;
    >> my $fh = $self->{FH};
    >> my ($buf, $toread, $offset, $nbytes);
    >>
    >> # start or continue reading the request header
    >> if ($self->{NREAD} < REQ_HEADER_LEN) {
    >> $buf = $self->{REQ_HEADER};
    >> $offset = $self->{NREAD};
    >> $toread = REQ_HEADER_LEN - $offset;
    >> # start or continue reading the chat string
    >> } else {
    >> $buf = $self->{CHAT};
    >> $offset = $self->{NREAD} - REQ_HEADER_LEN;
    >> $toread = $self->{LEN} - $offset;
    >> }
    >>
    >> # XXX the buf is WRONG here:
    >> $nbytes = $fh->sysread($buf, $toread, $offset);
    >>
    >> unless (defined $nbytes) {
    >> # interrupted by signal or would block - retry later
    >> return if $!{EINTR} || $!{EAGAIN} || $!{EWOULDBLOCK};
    >> # connection interrupted - remove the Apache child
    >> $self->remove($fh);
    >> return;
    >> }
    >>
    >> if (0 == $nbytes) {
    >> # connection closed - remove the Apache child
    >> $self->remove($fh);
    >> return;
    >> }
    >>
    >> $self->{NREAD} += $nbytes;
    >> print STDERR "nbytes = $nbytes\n";
    >>
    >> # not done yet - continue reading
    >> return if $nbytes < $toread;
    >>
    >> if (REQ_HEADER_LEN == $self->{NREAD}) {
    >> ($self->{SID}, $self->{EVENT}, $self->{MOD}, $self-
    >>>{LEN}) =

    >> unpack 'A32xN3', $self->{REQ_HEADER};
    >>
    >> printf STDERR "sid=%s, event=%x, mod=%x, len=%x\n",
    >> $self->{SID}, $self->{EVENT}, $self->{MOD}, $self-
    >>>{LEN};

    >>
    >> # not done yet - continue reading (the chat string)
    >> return if $self->{LEN} > 0;
    >> }
    >>
    >> print STDERR "done reading";
    >> #$Poll->mask($fh => POLLOUT);
    >>}

    >
    >I don't know for sure if "$fh->sysread() is valid (it may be),
    >but did you try this:
    >
    >$nbytes = sysread($fh, $buf, $toread, $offset);
    >
    >-------
    >
    >sysread FILEHANDLE,SCALAR,LENGTH,OFFSET
    >
    >Also, OFFSET, in this case, is not the file offset. But I don't
    >know what your trying to achieve.
    >
    >"An OFFSET may be specified to place the read data at some place in
    >the string other than the beginning. A negative OFFSET specifies
    >placement at that many characters counting backwards from the end
    >of the string. A positive OFFSET greater than the length of SCALAR
    >results in the string being padded to the required size with "\0"
    >bytes before the result of the read is appended"
    >
    >
    >sln


    It is possible that "reads" need a reference to a buffer, I'm not
    sure.

    So, something like this would be necessary:

    $buf = \$self->{REQ_HEADER};

    unless $self->{REQ_HEADER} is already a SCALAR reference.

    Not sure.


    sln
    , Aug 22, 2008
    #4
  5. A. Farber

    Guest

    "A. Farber" <> wrote:
    >
    > sub read {
    > my $self = shift;
    > my $fh = $self->{FH};
    > my ($buf, $toread, $offset, $nbytes);
    >
    > # start or continue reading the request header
    > if ($self->{NREAD} < REQ_HEADER_LEN) {
    > $buf = $self->{REQ_HEADER};


    Replace above line with $key ="REQ_HEADER";


    > $offset = $self->{NREAD};
    > $toread = REQ_HEADER_LEN - $offset;
    > # start or continue reading the chat string
    > } else {
    > $buf = $self->{CHAT};


    replace with $key = "CHAT";

    > $offset = $self->{NREAD} - REQ_HEADER_LEN;
    > $toread = $self->{LEN} - $offset;
    > }
    >
    > # XXX the buf is WRONG here:
    > $nbytes = $fh->sysread($buf, $toread, $offset);


    replace with

    $nbytes = $fh->sysread($self->{$key}, $toread, $offset);

    (or use references)

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    The costs of publication of this article were defrayed in part by the
    payment of page charges. This article must therefore be hereby marked
    advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
    this fact.
    , Aug 22, 2008
    #5
  6. A. Farber

    A. Farber Guest

    Thank you all
    A. Farber, Aug 23, 2008
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. ce
    Replies:
    1
    Views:
    2,961
  2. rp
    Replies:
    1
    Views:
    491
    red floyd
    Nov 10, 2011
  3. Pokkai Dokkai
    Replies:
    8
    Views:
    121
    Phrogz
    Nov 18, 2007
  4. Srijayanth Sridhar
    Replies:
    19
    Views:
    595
    David A. Black
    Jul 2, 2008
  5. Steve

    hash reference as a hash key

    Steve, Sep 26, 2003, in forum: Perl Misc
    Replies:
    6
    Views:
    107
    Steve
    Sep 28, 2003
Loading...

Share This Page