in reply to threads with shared variables across multiple instances of a module

If you use a package variable, it will be shared by all instances of the class, with or without sharing. Instance variables, even shared instance variables, need to be embedded within the instance.

Try this and see how you get on:

package Counter; use strict; use threads; use threads::shared; sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = {}; my $counter :shared = shift; ## Local shared variable $self->{ counter } = \$counter; ## Store a reference to it in the +object bless($self,$class); return $self; } sub incCounter { my $self = shift; lock ${ $self->{ counter } }; ++${ $self->{ counter } }; } sub getCounter { my $self = shift; lock ${ $self->{ counter } }; ${ $self->{ counter } }; } 1
#! perl -slw use strict; use threads; use Counter; my $t1 = async{ my $c1 = Counter->new( 100 ); $c1->incCounter while $c1->getCounter < 10000; return $c1->getCounter; }; my $t2 = async{ my $c2 = Counter->new( 100 ); $c2->incCounter while $c2->getCounter < 30000; return $c2->getCounter; }; print $t1->join; print $t2->join; __END__ C:\test>junk54 10000 30000

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.
"I'd rather go naked than blow up my ass"

Replies are listed 'Best First'.
Re^2: threads with shared variables across multiple instances of a module
by fert (Acolyte) on Mar 25, 2010 at 18:19 UTC
    Ah yes perfect, thanks! I thought about this, but figured the same problem would occur with the same variable name, but I guess inside of the function its able to have a unique reference to it, great!

    Beats my other hack around using self and sharing parts of the hash - which apparently is possible :D

    Thanks again.

      Yes, you can share individual elements of a hash (using share()):

      use strict; use warnings; use threads; use threads::shared; my %h; share $h{ fred }; $h{fred} = 2; async{ my $a='bill'; lock $h{fred}; $h{fred}=$a; }->join; print $h{fred}; bill

      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.

        can i share the whole hash ?? a can't push in my shared hash pair like this:

        "192.168.0.1:3128" => $client

        $client is a local (defined with "my") variable (socket)

        part of my code:

        ..... use strict; use Socket; use threads; use threads::shared; ....... my %clients :shared; ...... my $server = IO::Socket::INET -> new(.....); ..... while( my $client = $server -> accept ) { ..... ############### in next 2 strings i'm wall!!! i don't know how push $socket (it's refe +rence to NANDLE, isn't it?!) in shared hash %clients, and then get it + back like a handle!! the best error i've had, was "Bad file descriptor" ################ $clients{ "$client_ip:$client_port" } = *client{IO}; # add new socket +to %client syswrite( $$qwe{IO}, "hi, how are you??") || die ":$! _ $@"; ..... }

        help me please, desparing

        perhaps i didn't understand, but i have the same error "Thread 1 terminated abnormally: : Bad file descriptor". can explain to me ?

        6 use strict; 7 use IO::Socket; 9 use threads; 10 use threads::shared; 12 use constant BUFSIZE => 1024; ......... # create port, also "new" try bind, listen 31 my $server = IO::Socket::INET -> new( ............. 41 threads -> create( \&to_client ) || die "$! \n"; # STDIN, send + writed to client you point, like this "192.168.0.1:3128 my message", + also have "list" command # start threads to treat querys 44 while( my $client = $server -> accept ) { 45 my $client_ip = $client -> peerhost(); 46 my $client_port = $client -> peerport(); 47 my $tmp = "$client_ip:$client_port"; 48 ## ????? IN THIS PLACE I WANT TO PUSH SOCKET $client a +s value in hash %clients with key "$client_ip:$client_port" ???? 49 %clients = ( %clients, "$client_ip:$client_port" => fi +leno($client) ) ; # add new socket to %clients 50 54 print "got a connection from: $client_ip:$client_port +$client\n"; 55 $client -> autoflush; # don't buffer 56 57 threads -> create( \&from_client, $client, $client_ip, + $client_port ) || die "$! \n"; #STDOUT, get message from client 58 59 } 60 exit 0; # ****************************************************** 79 # send message to client, or get list of clients 80 sub to_client { 81 my ( $clnt_ip_port, $msg_t, $tmp ); 82 83 while( sysread(STDIN, $tmp, BUFSIZE) ) { 84 #print "debug1 $tmp"; 85 chomp $tmp; # very-very need, difficult to exp +lain =) 86 if( $tmp eq "list" ) { # show list of clients 87 print "connect to this server:\n"; 88 foreach my $z ( keys %clients ) { prin +t "client: $z $clients{$z}\n"; } 89 } 90 elsif ( $tmp =~ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d +{1,3}:\d{4,5}\s.*/ ) { # find in STDIN blank 91 ( $clnt_ip_port, $msg_t ) = ( $tmp =~ +/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{4,5})\s(.*)/ ); # split messa +ge to addres like "192.168.0.1:3128" (it is key fo r %clients) + and message 92 #print "debug1 blank {$clnt_ip_port} {$msg_t}\n"; 93 if ( exists $clients{$clnt_ip_port} ) +{ # if key exist in %clients then send 94 #print "syswrite $clients{$clnt_ip_port} {$msg_t} \n"; ????? IN THIS PLACE I WANT TO GET IT BACK ( SOCKET $client as +value from hash %clients with key "$client_ip:$client_port" ) ???? 95 my $client; 96 my $fileno = $clients{$clnt_ip +_port}; 97 open $client, "+<$fileno" || d +ie "open: $!\n"; 98 syswrite( $client, $msg_t ) || + die ": $! __ $@\n"; 99 close $client; 100 } else { print "don't exist client or +empty message!\n"; } 101 } else { print "wrong value, check and see \"l +ist\" of clients!\n"; } 102 } 103 } 106 # ****************************************************** 107 # STDOUT, get message from client 108 sub from_client { 109 my ( $sock, $clnt_ip, $clnt_port ) = @_;; 110 my $msg_f; 111 112 syswrite( STDOUT, "from $clnt_ip:$clnt_port: $msg_f" ) + while sysread( $sock, $msg_f, BUFSIZE ); 113 print "client at $clnt_ip:$clnt_port closed connection + \n"; 114 delete $clients{"$clnt_ip:$clnt_port"}; # delete socke +t from %client 115 116 $sock -> close; 117 }