Your Monkness,
I apparently don't understand a scoping or access issue with trying to access my main program's variable from the thread subroutine. I have:
use strict;
use Thread;
my $time : shared;
my $t = Thread->new(\&listener,\$time);
while (1) {
$time = localtime;
print $time,"\n";
sleep 1;
}
sub listener {
my $time_ref = shift;
while (1) {
{
lock($$time_ref);
print "\tThread time: [$time]\n";
print "\tThread time: [$main::time]\n";
print "\tThread time: [$$time_ref]\n";
}
sleep 3;
}
}
Which prints out:
Wed Feb 9 08:06:02 2005
Thread time: []
Thread time: []
Thread time: []
Wed Feb 9 08:06:03 2005
Wed Feb 9 08:06:04 2005
Wed Feb 9 08:06:05 2005
Thread time: []
Thread time: []
Thread time: []
Wed Feb 9 08:06:06 2005
Indicating to me that the thread only sees the initial value like it has it's own copy. Is that right? How do I access the main threads $time var? Hmmmmm. | [reply] [d/l] [select] |
use strict;
use threads;
use threads::shared;
my $time : shared;
sub listener {
my $array_ref = shift;
while (1) {
{
lock $time;
print "\tThread time: [$time]\n";
}
{
lock($array_ref);
print "\tThread time: [@$array_ref]\n";
}
sleep 3;
}
}
my @array : shared;
my $t = threads->new( \&listener, \@array );
while (1) {
{ lock $time; $time = localtime; }
print $time,"\n";
{ lock @array; push @array, $time; }
sleep 1;
}
__END__
[16:09:17.53] P:\test>429405
Wed Feb 9 16:09:31 2005
Thread time: [Wed Feb 9 16:09:31 2005]
Thread time: []
Wed Feb 9 16:09:32 2005
Wed Feb 9 16:09:33 2005
Thread time: [Wed Feb 9 16:09:33 2005]
Thread time: [Wed Feb 9 16:09:31 2005 Wed Feb 9 16:09:32 200
+5 Wed Feb 9 16:09:33 2005]
Wed Feb 9 16:09:34 2005
Wed Feb 9 16:09:35 2005
Wed Feb 9 16:09:36 2005
Terminating on signal SIGINT(2)
I switched your code around a bit not because there was anything wrong with the ordering, but to allow me to demonstrate a couple of points.
I've stopped passing the scalar ref to the sub and am passing a reference to an array that is also updated in the main thread.
Because $time is visible to your listener() sub, it is accessible, via closure in the normal way, without being explicitly passed it to the thread.
The array however, was not existing when the sub was declared, so it must be passed explicitly.
Basically, all the normal perl scoping rules apply--once you are using the correct modules :) I should have mentioned that before. Sorry!
Examine what is said, not who speaks.
Silence betokens consent.
Love the truth but pardon error.
| [reply] [d/l] [select] |
I grovel. Must you be so simply clear? LOL Indeed, I had already figured out that I must not use 'Thread' but I didn't know why. Thanks for pointing it out. I had shifted to 'threads' and my code looked almost exactly like yours as I bagged the references and employed locking in both threads. Thanks also for pointing out that the array would not be known yet and must be 'blessed' so to speak. I have it working now, on to the next lesson. Seems the more I learn, the less I know.....grrrr!
| [reply] |
I thought I read somewhere that Perl internally made sure any shared data accessed by threads would be in a consistent state, no matter if you lock the shared variable or not. In fact, I seem to recall it said it was quite safe to have one thread push stuff onto a shared array (ie, a queue), and another shift stuff off the other end of it, safely without any locking.
Are you saying that on an SMP box the en-queue side might end up pushing garbage data onto the shared array, or that the de-queue side might read garbage data?
Obviously it's okay if the reader side doesn't see anything yet, so long it just thinks that queue is undefined (empty) and just sleeps a while and checks again later on...
| [reply] |
In my humility I guess I don't know the difference between 'Thread' and 'threads'. After shifting the code to use 'threads' and 'threads::shared', I am able to access my variable. What the heck is the 'Thread' module for then?
| [reply] |