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

Hi Monks,

This one feels like I am abusing Perl's OO concepts in ways they were never meant to be used, but let's see if anybody has any ideas/experience.

I have a module which has some variables that need to be shared amongst threads it spawns.

my $var : shared = 0;

Which works fine for until you declare a second instance of the module. Then it seems like the namespace of the variable is shared with all other instances of this module, and each instance is sharing the variable.

I can see the uses of this, however what I need is a way to narrow the scope of the sharing of the variable to the instance in question.

Here is some simple sample code that replicates this:

package Counter; use strict; use threads; use threads::shared; my $counter : shared = 0; sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = {}; lock $counter; $counter = shift; bless($self,$class); return $self; } sub incCounter { lock $counter; $counter++; } sub getCounter { return $counter; } 1;

and

#!/usr/bin/perl -w use Counter; my $x = new Counter( 1 ); my $y = new Counter( 10 ); print $x->getCounter()."\n"; print $y->getCounter()."\n"; print "-------------\n"; $x->incCounter(); print $x->getCounter()."\n"; print $y->getCounter()."\n";

I've been playing with sharing a hash, and then somehow generating a unique name for each instance, to guarantee independence of these variables, but that seems a bit...nasty.

So can perl do this? Can I have multiple instances of a module with shared variables that are only shared among the child threads of each instance? Again I realize Thread::Pool must be thread safe across multiple instances, so there has to be a way, I think its just a question of how nasty the solution is..

Replies are listed 'Best First'.
Re: threads with shared variables across multiple instances of a module
by BrowserUk (Patriarch) on Mar 25, 2010 at 17:47 UTC

    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.
      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.