in reply to Re: Protecting External Data?!
in thread Protecting External Data?!

You haven't understood me. it's not that I don't want it to be GCed. I don't want it to be duplicated in the first place.

you see, if you do this in Perl:

my $x = 5; sub ct { threads->create(\&worker); }
then $x will be copied to the new thread. but if you do this:
sub ct { my $x = 5; threads->create(\&worker); }
$x won't be copied.

I thought that if I keep my SV outside of Perl, it just won't be accessable and won't be copied. apperently I am wrong.
So I need help protecting my SV against the almighty thread duplicator. how can I do it?

Replies are listed 'Best First'.
Re^3: Protecting External Data?!
by plobsing (Friar) on Dec 20, 2007 at 07:04 UTC
    perlmod has a nice description of how your modules can play nice with threads.
    It describes the CLONE_SKIP routine which you can add to your module to prevent cloning across threads.

    If you only want to not clone one of many instances, you could create a subclass Class::Foo::NoClone which is empty save for a sub CLONE_SKIP { 1 } and a @ISA = ('Class::Foo'); and rebless the specific instance into that.

    Also, are you sure that it won't clone the second $x? Its been a while since I've used threads. Where in the docs does it say that? I would assume they would be treated equally, both being lexical variables and all.

    Update: proof that the second $x is cloned
    use threads; use strict; use warnings; use PadWalker qw(peek_sub); sub thr { my $xref = peek_sub(\&run_test)->{'$x'}; print "\$xref in thr: $xref\n"; } sub run_test { my $x = 1; my $xref = \$x; print "\$xref before thr: $xref\n"; threads->create(\&thr)->join; $xref = \$x; print "\$xref after thr: $xref\n"; } run_test;
    Output (on perl v5.8.8 built for x86_64-linux-gnu-thread-multi):
    $xref before thr: SCALAR(0x6c51a0) $xref in thr: SCALAR(0x7584a0) $xref after thr: SCALAR(0x6c51a0)
      My first reaction was that you don't know what you are talking about. of course the PAD of the function will exists, and be copied to the new thread. the content of the PAD should not be copied.

      And then I tested it out:

      #!/usr/bin/perl -w use strict; use threads; sub thr { print "Thread running.. Done.\n"; } sub run_test { my $x = bless {}, 'Obj'; threads->create(\&thr)->join(); } sub Obj::DESTROY { print "Destroyed from thread ", threads->tid, "\n"; } run_test();
      and the output:
      Thread running.. Done. Destroyed from thread 1 Destroyed from thread 0
      So now I think that I don't know what I'm talking about.
      Why did Perl copied the $x? it is not a global, and was not passed as parameter. I just don't get it.

      If someone can point me to a relevant perldoc, I'll be greatefull.

      thank,
      Shmuel.

        from perlthrtut:

        The biggest difference between Perl ithreads and the old 5.005 style threading, or for that matter, to most other threading systems out there, is that by default, no data is shared. When a new Perl thread is created, all the data associated with the current thread is copied to the new thread, and is subsequently private to that new thread! This is similar in feel to what happens when a UNIX process forks, except that in this case, the data is just copied to a different part of memory within the same process rather than a real fork taking place.