spacepille has asked for the wisdom of the Perl Monks concerning the following question:

Hello dear,
I'm getting troubles in XS modules when i use threads. In addition to MY_CXT i need a clean destructor for system resources like file handles, that are not clonable. The following example does exactly the same (bad thing) like my XS modules do. A new thread is created before the previous thread detachs. CLONE is called correctly, but DESTROY is called to less. Is it a bug or do i wrong? Please help.
#!/usr/local/bin/perl use threads; use Time::HiRes qw/usleep/; while( 1 ) { my $class = Class->new(); threads->create( \&thread_sub, $class ); usleep 200_000; } sub thread_sub { my( $class ) = @_; usleep 400_000; threads->self->detach; } 1; package Class; use threads::shared; our %MY_CXT : shared = (); our $CXT_ID : shared = 0; sub new { my $pkg = shift; my $this = {}; $this->{'shared'} = &share( {} ), $this->{'shared'}{'refcnt'} = 1; lock( %MY_CXT ); $this->{'id'} = ++ $CXT_ID; $MY_CXT{$this->{'id'}} = $this->{'shared'}; bless $this, $pkg; } sub CLONE { my $this = shift; # not applicable lock( %MY_CXT ); while( my( $k, $v ) = each %MY_CXT ) { $v->{'refcnt'} ++; print "CLONE: id $k, refcnt $v->{'refcnt'}\n"; } } sub DESTROY { my $this = shift; my $shared = $this->{'shared'}; $shared->{'refcnt'} --; print "DESTROY: id $this->{'id'}, refcnt $shared->{'refcnt'}\n"; if( $shared->{'refcnt'} <= 0 ) { lock( %MY_CXT ); delete $MY_CXT{$this->{'id'}}; } } 1;

Replies are listed 'Best First'.
Re: CLONE/DESTROY want work at all??
by tilly (Archbishop) on May 21, 2009 at 18:24 UTC
    Every time you clone a thread, it walks through the %MY_CXT structure and increments counts on everything in there. When a thread exits it gets DESTROYed only once - in the thread that was running. Therefore every thread gets CLONED many times, and DESTROYed only once. This adds up to many more CLONEs than DESTROYs.
      Since CLONE deals with the package and DESTROY deals with the object, it's not possible to get a module threadsafe, when it uses shared stuff?
        What makes you think it is not threadsafe?

        It is doing what you are asking for. You have a global structure. As each thread spawns, it walks the whole global structure, while locking appropriately. If you don't want it to walk the whole global structure don't.

        If that is not what you meant to ask for, then don't ask for that.

        In general with threads I strongly recommend having the simplest possible design. And then thinking through consequences very, very carefully. Because things will interact in unexpected ways. And when you've got multiple threads (or processes) around whose interactions with you are all mixed up, you can easily get very, very confused.

Re: CLONE/DESTROY want work at all??
by Wiggins (Hermit) on May 21, 2009 at 18:25 UTC
    Somewhere in my Perl threads research, I came across a warning that Threads and Objects don't play well together; unless the Object documentation says that it is specifically crafted to work with threads. Unfortunately, it didn't go into what "special crafting" was needed.

    It is always better to have seen your target for yourself, rather than depend upon someone else's description.