[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

Reply via email to