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

I have this block of code (where $graph is an instance of Boost::Graph)

sub processGraph { print "Total node count = " . $graph->nodecount() . "\n"; print "Total edge count = " . $graph->edgecount() . "\n"; my $nodes = $graph->get_nodes(); my $thr_count = 0; foreach my $node (@$nodes) { my $thr = threads->new(\&calcFoo, $graph, $id, $node); } }

sub calcFoo { my ($graph, $id, $node) = @_; bless $graph; print "$graph\n"; print "Total node count = " . $graph->nodecount() . " in threa +d\n"; }

I am simply trying to pass the graph object to my new thread but the above is simple returning the following:
main=HASH(0x9165900) thread failed to start: Can't call method "nodecount" without a packag +e or object reference at new_processor line 69.
Can someone clear up the syntax of how I pass an object to a subroutine? I tried passing a reference too, and I just can't quite get the syntax right.

Replies are listed 'Best First'.
Re: Syntax for passing objects to subroutine
by Perlbotics (Archbishop) on Aug 12, 2008 at 22:58 UTC
    In calcFoo you re-bless the object into the current package which is probably not Boost::Graph.
Re: Syntax for passing objects to subroutine
by GrandFather (Saint) on Aug 13, 2008 at 02:02 UTC

    An object is a reference so just pass the object. In the sub it is still a reference to the object so simply use it - not need to bless it or anything else.


    Perl reduces RSI - it saves typing
Re: Syntax for passing objects to subroutine
by Your Mother (Archbishop) on Aug 12, 2008 at 22:57 UTC

    It's probably not doing what you think. If the object were a Boost::Graph, it would not print main=HASH(0x9165900), unless it got reblessed into main, but Boost::Graph=HASH(0x800d80). You also seem to be creating things outside the scope in which you're using them. Make sure to run with strict and warnings.

    (Update: my eyes are going: Perlbotics correctly notes below that it is getting reblessed into main.)

Re: Syntax for passing objects to subroutine
by gone2015 (Deacon) on Aug 13, 2008 at 12:37 UTC
    Can someone clear up the syntax of how I pass an object to a subroutine? I tried passing a reference too, and I just can't quite get the syntax right.

    As others have noted, an object -- eg $object -- is a reference to something or other, which has been "blessed". So there is no special syntax for passing objects, you just pass the reference just like any other scalar. Most of the time one can forget that $object is not the object, but is one step removed.

    Perl's parameter handling is, of course, "interesting". Assuming the usual ($a, $b, ...) = @_ ;, arguments are passed by value. Where the argument is an object, the value that is passed is the reference -- which can lead to disappointment if one forgets that the object itself is not passed by value.

    However, what you are doing is deeper than this. You are passing an object from one thread to another.

    Each thread has its own, separate address space, which is a copy of the creating thread's address space, taken at the moment of creation. So... although the creation of the thread looks like a subroutine call, it's not quite -- objects, for example, really are passed by value. Consider:

    my $o = bless { a => 'A', b => 'B' }, "CLASS" ; show('main - pre ', $o) ; my $t = threads->new(\&proc, 'thread', $o) ; $t->join() ; show('main - post', $o) ; sub proc { my ($t, $x) = @_ ; $$x{z} = 'Z' ; show($t, $x) ; } ; sub show { my ($t, $x) = @_ ; printf "%20s: ", $t ; print "$x {", join(", ", map { "$_ => $$x{$_}" } sort keys %$x), " +}\n" ; } ;

    which gives:

    main - pre : CLASS=HASH(0x15c2e88) {a => A, b => B} thread: CLASS=HASH(0x1adee98) {a => A, b => B, z => Z} main - post: CLASS=HASH(0x15c2e88) {a => A, b => B}

    On the other hand, if the value of the object is created 'shared', thus:

    my %s : shared = ( x => 'X', y => 'Y' ) ; my $o = bless \%s, "SHARE" ;

    we get the usual semantics of passing an object:

    main - pre : SHARE=HASH(0x15c4778) {x => X, y => Y} thread: SHARE=HASH(0x1825950) {x => X, y => Y, z => Z} main - post: SHARE=HASH(0x15c4778) {x => X, y => Y, z => Z}

    Love it ? You bet !

    And, just for completeness, returning an object from a thread is fraught... consider:

    my $t = threads->new(\&make, a => 'A', b => 'B') ; my $o = $t->join( +) ; show('main', $o) ; sub make { my %s : shared = @_ ; my $m : shared = bless \%s, "MADE" ; show('thread', $m) ; return $m ; } ; use Scalar::Util qw(reftype) ; sub show { my ($t, $x) = @_ ; printf "%20s: %s", $t, $x ; my $r = reftype($x) || '' ; if ($r eq 'SCALAR') { print " = ", defined($$x) ? "'$$x'" : 'undef +' ; } ; if ($r eq 'ARRAY') { print " = [", join(", ", @$x), "]" ; + } ; if ($r eq 'HASH') { print " = {", join(", ", map { "$_ => $$x{$_ +}" } sort keys %$x), "}" ; } ; print "\n" ; } ;

    which gives:

    thread: MADE=HASH(0x197d4e0) = {a => A, b => B} main: SCALAR(0x1712078) = undef

    and I cannot find a way to make this work -- not even with shared object value and body (as above).