Yes that works. Unintuatively, an unshared array of references to shared scalars does the trick:
#! perl -slw
use strict;
use threads qw[ yield ];
use threads::shared;
sub thread {
my $tid = threads->tid;
my $refSem = shift;
while( 1 ) {
warn( "$tid: locking sem\n" );
lock( $$refSem );
warn( "$tid: waiting sem\n" );
cond_wait( $$refSem );
print "$tid: got: $$refSem";
warn( "$tid: yielding\n" );
yield;
warn( "$tid: looping\n" );
}
}
our $T ||= 2;
my @sems = map{ my $var :shared; \$var } 0 .. $T;
my @threads = map{
threads->create( \&thread, $sems[ $_ ] );
} 1 .. $T;
while( 1 ) {
my $value = int( rand 1000 );
my $thread = 1 + int rand( $T );
my $refSem = $sems[ $thread ];
warn( "0: locking sem for thread $thread\n" );
lock( $$refSem );
warn( "0: Setting sem[ $thread ] to $value\n" );
$$refSem = $value;
warn( "0: signalling sem[ $thread ]\n" );
cond_signal( $$refSem );
warn( "0: Sleeping\n" );
yield;
}
Shame there isn't a less clumsy way to allocate an array of shared scalars than:
my @sems = map{ my $var :shared; \$var } 0 .. $T;
It's also high time that the "documented limitation" (BUG!):
share() allows you to share($hashref->{key}) without giving any error message. But the $hashref->{key} is not shared, causing the error "locking can only be used on shared values" to occur when you attempt to lock($hasref->{key}).
that also affects array elements was fixed.
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.
|