Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

[threads] Sharing object through threads

by baxy77bax (Deacon)
on Nov 16, 2009 at 20:48 UTC ( [id://807559]=perlquestion: print w/replies, xml ) Need Help??

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

hi,

hi i have an example script in which i'm trying to share a pre-created object.

#!/usr/bin/perl use strict; use threads; use threads::shared; use tmp; my $rf = tmp->new(); share(my @data); my @threads; for ( my $count = 1; $count <= 10; $count++) { my $t = threads->new(\&sub1, $count); push(@threads,$t); } foreach (@threads) { my $num = $_->join; print "done with $num -- @data\n"; } print "End of main program @data\n"; sub sub1 { my $num = shift; print "started thread $num\n"; print "done with thread $num\n"; push (@data,$rf); return $num; } -------------- module tmp.pm package tmp; sub new { my ($class)=@_; my $hash = {}; bless ($hash,$class); } sub _test { my ($self,$arg) = @_; print "testic $arg\n"; } 1;
the problem i can't do that.
thread failed to start: Invalid value for shared scalar at ./test.pl
is there a way to cheat this!

thnx

Replies are listed 'Best First'.
Re: [threads] Sharing object through threads
by BrowserUk (Patriarch) on Nov 17, 2009 at 10:07 UTC

    If you want to push a ref onto a shared array, you have to share that ref first:

    #!/usr/bin/perl use strict; use threads; use threads::shared; use tmp; my $rf = tmp->new(); share(my @data); my @threads; for ( my $count = 1; $count <= 10; $count++) { my $t = threads->new(\&sub1, $count); push(@threads,$t); } foreach (@threads) { my $num = $_->join; print "done with $num -- @data\n"; } print "End of main program @data\n"; sub sub1 { my $num = shift; print "started thread $num\n"; print "done with thread $num\n"; push (@data,share( $rf )); #### NOTE CHANGE HERE! return $num; }

    With that change, your code runs:

    c:\test>807599.pl started thread 1 done with thread 1 started thread 2 done with thread 2 started thread 3 done with thread 3 started thread 4 done with thread 4 started thread 5 done with thread 5 started thread 6 done with thread 6 started thread 7 done with thread 7 started thread 8 done with thread 8 started thread 9 done with thread 9 started thread 10 done with 1 -- tmp=HASH(0xf4a08) tmp=HASH(0xf4a50) t done with thread 10 done with 2 -- tmp=HASH(0xf4a98) tmp=HASH(0xf4978) t done with 3 -- tmp=HASH(0xf4990) tmp=HASH(0xf4b40) t done with 4 -- tmp=HASH(0xf4b70) tmp=HASH(0xf4ba0) t done with 5 -- tmp=HASH(0xf4bb8) tmp=HASH(0xf4a68) t done with 6 -- tmp=HASH(0xf49d8) tmp=HASH(0xf4ae0) t done with 7 -- tmp=HASH(0xf4c18) tmp=HASH(0xf4b58) t done with 8 -- tmp=HASH(0xf49f0) tmp=HASH(0xf4a50) t done with 9 -- tmp=HASH(0xf4c48) tmp=HASH(0xf4978) t done with 10 -- tmp=HASH(0xf4c60) tmp=HASH(0xf4b40) End of main program tmp=HASH(0xf4c78) tmp=HASH(0xf4

    Note: The ability to share blessed references is a relatively new feature of threads::shared. I have done very little with and I am dubious of its benefits, but it does appear to work!


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      Cool, that seams to work but now another problem appears. i thought i could resolve the problem by sharing an object but it seams i cannot. because in threaded server application it looks like the object shared is type of a globe ($client == IO::Socket::INET=GLOB(0x189a908)) which is unsharable for now.
      #!/usr/bin/perl -w use strict; use IO::Socket; use threads; use threads::shared; my $server = IO::Socket::INET->new( Proto => 'tcp', LocalPort => $ARGV[0], Listen => SOMAXCONN, Reuse => 1); die "can't setup server" unless $server; share(my @jobs); while (my $client = $server->accept()) { $client->autoflush(1); print "[Connect from ". $client->peerhost . ":" . $client->peerpo +rt . "]\n" ; # clients address my $thr = threads->new(sub { push(@jobs,share($client)); ### NOTE THIS IS UNS +HARABLE ### while (<$client>) { if (/test/i){ print $client "looks good, @jobs\n"; } elsif (/quit/i){ print $client "bye\n"; last; } } # finishe while } )->detach; close $client; }
      since you had the similar problem couple a years ago i was wondering if you found the solution or.... (sharing globs)

      thank you

      so the idea is when one client talks server listens and shares its responses with all connected clients

        The situation is that I never succeeded in working out how to make threads::shared share globs.

        I got quite a long way towards that goal, but always found something that prevented my attempts from being completely successful, and did not know enough about the guts of Perl magic to be able to debug it when it went wrong. I remain convinced that if someone with the requisite skills could be recruited to spend a litte time trying, it could be achieved. But those with the requisite skills do not consider threads a high priority it seems. Which is a shame, because IMO, this is the single most limiting factor on the usefulness of threads in perl.

        I do not have a clean alternative for you.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

        Sockets are nothing but file handles. Share the file handle number (fileno($client)) and recreate the object on the other side.

        Catch: You can't close the socket in the parent.

Re: [threads] Sharing object through threads
by Illuminatus (Curate) on Nov 16, 2009 at 21:14 UTC
    While your array is shared, the objects created by tmp->new are not, so I don't think you can push them onto the shared array. If the object is simply a container for a hash, you could pre-declare the hashes as shared, and push them on the shared array instead. Not pretty, but it should work.
Re: [threads] Sharing object through threads
by zentara (Archbishop) on Nov 17, 2009 at 12:32 UTC
Re: [threads] Sharing object through threads
by weismat (Friar) on Nov 17, 2009 at 09:32 UTC
    Threads can not share references - thus you can also work on serialised objects - but this comes with a performance penalty and additional overhead.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (6)
As of 2024-04-23 18:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found