Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

$threads->join() only returns one argument??? BUG?

by rr (Sexton)
on Jun 11, 2003 at 22:04 UTC ( #265203=perlquestion: print w/replies, xml ) Need Help??

rr has asked for the wisdom of the Perl Monks concerning the following question:


Hello,

While writing a threaded perl program which does parrallel http get's I have a in the subroutine I pass to threads->create line that returns like this:

sub _generic_http_get { ... return ($return_s, $return_h, $body_s, $ti); }
After creating a few threads, I attempt to join them like this:
foreach(@threads) { my($status, $header, $body, $time) = $_->join(); ... }
Unfortunately I only ever receive back the last return value (a float containting time taken to execute the get). I can run this subroutine and collect the return arguments exactly the same way without threads and it works.

Is there a bug or limitation to the number of arguments a thread can return on join in perl 5.8.0 (Linux)? I rtfm'd and such and found nothing talking of this.

Thanks!

rr

Replies are listed 'Best First'.
Re: $threads->join() only returns one argument??? BUG?
by Chmrr (Vicar) on Jun 12, 2003 at 03:39 UTC

    This is pretty obviously a bug. The context that is applied to the $thr->join call is the context that the threads->new call was in. That is:

    my $thr = threads->new( sub { return (1,2,3) }); my @a = $thr->join(); print "return is @a\n";

    ..fails, while..

    my ($thr) = threads->new( sub { return (1,2,3) }); my @a = $thr->join(); print "return is @a\n";

    ..works fine. Note the difference in parens on the my $thr line. I'm going to poke at the threads code on this one.

    Update: Upon reflection and looking at the code, it makes sense in a perverse way. Because the subroutine/thread starts execution upon creation, someone could call wantarray from it off the top. If the context was determined at join time, there would be no way to determine the proper wantarray value. In fact, this behavior is documented in bleedperl's threads.pm (search for "context").

    perl -pe '"I lo*`+$^X$\"$]!$/"=~m%(.*)%s;$_=$1;y^`+*^e v^#$&V"+@( NO CARRIER'

      Thanks, I was just running into this issue myself. Even several of the code snippets out there for threads do not take this into account. This one is used in several places
      use Thread; $thr = new Thread \&sub1; @ReturnData = $thr->join; print "Thread returned @ReturnData"; sub sub1 { return "Fifty-six", "foo", 2; }
      It returns two. Some keywords: perl thread return values join multiple last array

      20100226 Janitored by Corion: Added formatting, code tags, as per Writeup Formatting Tips

        Just what I needed. Thanks!
      Thanks for info brain was blasted lol
Re: $threads->join() only returns one argument??? BUG?
by BrowserUk (Patriarch) on Jun 11, 2003 at 22:33 UTC

    I'm not sure if it counts as a bug, but I encountered the same thing and couldn't find anything in the docs that suggested it should or shouldn't be able to return a list.

    The simplest solution I came up with was join the list on the return and split it at the other end.

    use threads; my $t = threads->create( sub{ sleep 10; return join $;, 'fred', 1, 1.123 } ); print split $;, $t->join;

    Usual caveats about choice of seperator apply. $; seems as good a choice as any for most things.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller


      perlthrtut explicitly says that you can return a list, but the example code doesn't work as advertised:

      use threads; $thr = threads->new(\&sub1); @ReturnData = $thr->join; print "Thread returned @ReturnData"; sub sub1 { return "Fifty-six", "foo", 2; }

      prints "Thread returned 2". It looks like if the return statement returns a list you'll get the last element, and if you wrap it up inside an array (e.g., return @array = ("Fifty-six", "foo", 2)) it'll put it in scalar context no matter what the lvalue of the join(). Weird.

      Another option is to return an array reference and assign it to a scalar left of the join, or to pass a reference to a shared array into the threaded sub and have it populated.

      use threads; use threads::shared; share(@array); $thr = threads->new("sub1"); @ReturnData = $thr->join; print "Thread returned @ReturnData\n"; print "Thread populated @array\n"; sub sub1 { @array = ("Fifty-six", "foo", 2) }

      prints "Thread returned 3" and "Thread populated Fifty-six foo 2".


      "The dead do not recognize context" -- Kai, Lexx

        I missed that bit. Truth is I've never read perlthrtut beyond the first couple of paras because it seemed to be dealing with threads at a very general level which I'm already reasonably comfortable with. It also goes into way to much detail about all the different flavours of threads which perl doesn't use for my taste.

        There definitely seem to be a few bugs still in the 5.8 implementation. Much of it deriving from the inherently non-reentrant nature of the perl core from what I can work out. There's also a lack of good sample code right now.


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller


Re: $threads->join() only returns one argument??? BUG?
by gmpassos (Priest) on Jun 12, 2003 at 06:25 UTC
    How about return an ARRAY ref?

    use threads; my $t = threads->create( sub{ sleep 3; return([qw(a b c)]) ; } ); my $ret = ($t->join) ; print ">> @$ret\n" ;
    But you have pointed an interesting point, since it should return all the list! I never come to this problem, that is a bug, or at least not documented!

    Have you posted this to PerlBug? http://rt.perl.org/perlbug/

    Graciliano M. P.
    "The creativity is the expression of the liberty".


      Hello,

      I did work around this by returning a ref to an array, but it definatly should work as documented.

      I see from a post above that the behaivior is docoumented somewhere and I'll dig it up.

      Thanks for the pointer to perlbug, I'll post something there.

      Again, thanks to all of your for your responses!

      rr

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://265203]
Approved by djantzen
Front-paged by arthas
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (3)
As of 2022-07-04 00:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?