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

I have an object, "My::Class", that creates objects of a second type "My::Class::Temps", and stores references to these as it is necessary for the first 'collection' object to adjust the Temps as it is changed. Temps is a small class and may be created frequent and only used for a small block of code; once out of scope, there's no way to get back at what that Temps value is.

If I didn't have to store the references to Temps, it's well known that any Temps objects will be destroyed once they go out of scope, but that won't happen in this case. While Temps is small and should not drastically exhaust resources in terms of memory even if thousands are defined, I'd still rather avoid this situation, if not for this particular problem but for future situations of a smilar nature.

As it is right now, I'm providing a function to the end user that allows them to manually clear out the Temps. Icky, I know, but it does allow the end user that might be concered about memory usage to do something about it. If I can resolve this problem now, then I'll since drop this function to a 'do nothing' state for compatibility.

Is there a way to capture the point where an object is going out of scope but not necessarily being deleted, such that special actions can be taken?

-----------------------------------------------------
Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
"I can see my house from here!"
It's not what you know, but knowing how to find it if you don't know that's important

Replies are listed 'Best First'.
Re: Catching an object going out of scope
by princepawn (Parson) on Nov 11, 2001 at 18:57 UTC
    I have an object, "My::Class", that creates objects of a second type "My::Class::Temps"
    Ok, My::Class is a factory class for My::Class::Temps

    Is there a way to capture the point where an object is going out of scope but not necessarily being deleted, such that special actions can be taken?
    DESTROY {    } is the answer to this question in isolation but in order to automate destruction of this object automatically, you simply need to weaken the reference count. I thought gbarr had written something to do this but CPAN shows two others : Devel::WeakRef and WeakRef
      Just a remark to add.
      Weak references are available only in perl 5.6 or higher (production branch). There is no support of weakref in widespread 5.005_3 version of perl.

      In perl 5.005_3 you can't do just nothing about circular refs. The only thing you can do is give user a chance to release reference cycle manualy (by calling $o->release method for example).

Re: Catching an object going out of scope
by Biker (Priest) on Nov 11, 2001 at 21:44 UTC

    I'm puzzled.

    If "My::Class" is a factory class for "My::Class:Temps", then "My::Class" creates objects of class "My::Class::Temps" and saves references to them. Did I understand that part correctly?

    As a creator of these objects, shouldn't the "My::Class" object know that it's time to "kill" the "My::CLass:Temps" object and simply remove the reference to the object?

    f--k the world!!!!
    /dev/world has reached maximal mount count, check forced.

Re: Catching an object going out of scope
by chip (Curate) on Nov 13, 2001 at 23:47 UTC
    In the absence of weak refs, you can use the equivalent of soft references:

    my $TEMPID; my %TEMPS; package My::Class::Temps; sub lookup ($) { $TEMPS{+shift} } sub new { my $self = {}; $TEMPS{ self->{ID} = ++$TEMPID } = $self; $self; }

    Now you can store $self->{ID} and use lookup() to find the corresponding object. Such storage of a unique ID doesn't increase reference counts, so it's rather like a weak reference, albeit not nearly as convenient.

        -- Chip Salzenberg, Free-Floating Agent of Chaos

      I like this idea nicely, as the weak ref solutions previousy suggested only work under 5.6 and I'd like to keep a 5.005 solution usable.

      Extending this, I would suggest that I can now put in my DESTROY function for the Temps, not only a delete $TEMPS{ $self->{ID} };, but also something that goes back to the factory class that that ID is gone, though this step isn't really necessary.

      I believe that the only limitation here is that I couldn't have more than (whatever the maximum possible positive value is for an integer for perl & OS) iterators at the same time, but I very much that would be a problem.

      -----------------------------------------------------
      Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
      "I can see my house from here!"
      It's not what you know, but knowing how to find it if you don't know that's important

Re: Catching an object going out of scope
by fokat (Deacon) on Nov 12, 2001 at 21:20 UTC
    If I understand you correctly, you can store a reference to $self in each My::Class::Temp object. This will prevent the current garbage collector to claim the space of the object once it leaves scope.

    The problem is how do you destroy this object later... I guess you can't, because you no longer have references to it (it went out of scope).

    The answer to this last point, would be to keep a weak reference to the object. You should have good enough reasons to outweight the general ickiness in doing this tough :)

    You could then have a custom function that destroys the circular reference and then destroys the weak reference. At this stage, the garbage collector can reclaim your object's space as it went completely out of scope.

    Hope this helps.