At 00:10 -0600 10/30/03, Mike Pomraning wrote:
On Thu, 23 Oct 2003, Mike Pomraning wrote:

 [....] suggestions on how I might determine which DESTROY [of a shared,
 blessed ref] is the very last one?

Sorry to reply to my own post, but here's how I've attempted to identify the last DESTROY of a shared object:

  sub DESTROY {
    return unless threads::shared::_refcnt($_[0]) == 1;
    # if we're here, the shared object is going away for good.
    # time to release system resources, call XS deallocators, etc.
    }
  }

The only other approach I can think of is to do (ser|ted)ious inventorying via
CLONE, DESTROY and constructors, or a wrapped bless.  (I did see the
"[CAUTION] Thread-saving modules" not-a-bug thread from Jul 2002 before my
previous post, but this is not quite the same.)

The "inventory" approach is the one that Thread::Pool uses. But it may be simpler than you think:


There is a global that keeps the CLONE level:

our $cloned = 0;

Then this variable gets incremented with each clone:

sub CLONE { $cloned++ }


When an object gets created, it keeps the current cloned value with its information:


sub new {
     bless {cloned => $cloned},$_[0];
}


And then in DESTROY, you check whether they're still the same


sub DESTROY {
    return unless $_[0]->{'cloned'} == $cloned;
# other stuff
}


Multiple destruction of non-shared objects makes sense to me, as each becomes
a thread-local copy.  Multiple destruction of shared objects, however, does
not (though I think I understand the mechanics of why it happens).  Am I
looking at this issue the wrong way?

Maybe the above is already what you have, maybe it is simpler. It works for Thread::Pool.


By the way, Thread::Pool also contains:

return unless UNIVERSAL::isa( $_[0],__PACKAGE__ ); # ignore rogue DESTROYs

I'm not sure this is needed for 5.8.1 and above. But it was definitely needed for 5.8.0.


Hope this helps.


Liz

Reply via email to