[cc'd to internals to check a possible performance problem.]
Steven W McDougall wrote:
> > The more interesting case is this:
> >
> > #!/my/path/to/perl
> > sub foo_generator { my $a = shift; sub { print $a++ } }
> > my $foo = foo_generator(1);
> > $foo->();
> > Thread->new($foo);
>
> > Is $a shared between threads or not?
>
> $a is shared between threads.
> The anonymous subroutine is a closure.
> Closures work across threads.
That's a possibility, but it has severe implementation problems --
all closures must be treated as having shared variables. That makes
closures really expensive. The use of "our" vs. "my" for mutex locking
becomes (almost) useless.
> > Perhaps Thread->new should deep copy the code ref before executing
> > it? Deep copy lexicals but not globals? Deep copy anything that doesn't
> > already have a mutex lock?
>
> no no no...perlref.pod, Making References, item 4 says
>
> A reference to an anonymous subroutine can be created by using sub
> without a subname:
>
> $coderef = sub { print "Boink!\n" };
>
> ...no matter how many times you execute that particular line
> (unless you're in an eval("...")), $coderef will still have a
> reference to the same anonymous subroutine.)
>
> We can, and should, retain this behavior.
If I change the above code to:
#!/my/path/to/perl
sub foo_generator { our $a = shift; sub { print $a++ } }
###
my $foo = foo_generator(1);
$foo->();
Thread->new($foo);
then I'd expect $a to be shared. I'm not so sure otherwise -- the
performance cost might be too big.
- Ken