Re: RFC from a newbie: Method References

2000-12-18 Thread Jeremy Howard

Michael G Schwern wrote:
 Hmmm... an object which contains a method reference which contains a
 referent to itself.

Yup. I don't know why some people think that circular references are complex
;-)

  Something like this would be nice in a class that creates method
  references--it would simply need to keep a list of referred objects, and
  have an explicit destructor that iterates through the references and
undefs
  them. Of course, calling the destructor would be optional where no
circular
  reference exists.

 Yes, you could keep a list/hash of what you created (as weak
 references) and explicitly destroy them but I don't think that
 would help.  Consider the following...

 following deleted...

 Which doesn't solve the problem... and I don't have any better ideas.

No, neither do I. So far I've been undef'ing method references semi-manually
(since there are specific event callback hooks in any widget, I just need to
undef these), but this isn't Lazy.

Maybe a flash of inspiration will come over Christmas...





Re: RFC from a newbie: Method References

2000-12-17 Thread Jeremy Howard

Michael G Schwern wrote:
 On Sun, Dec 17, 2000 at 12:11:01PM +1100, Jeremy Howard wrote:
  Something to be careful of--it's easy to create a circular reference
when
  using method pointers. As a result, neither the referrer nor referee
objects
  are ever destroyed.
 
  When using method references it's important that your class keeps track
of
  its references, and explicitly removes them when done to allow object
  destruction to occur. Perhaps this could be incorporated into
  Class::MethRef?

 Circular references make my brane hurt, but I don't think there's any
 circularlity here.  Once the method reference falls out of scope, so
 will its reference to the object.  Then the object will be garbage
 collected when it to falls out of scope.  The other way around, if the
 object falls out of scope first, the method reference will still work
 and the object will finally be destroyed when the meth ref goes away.
 The only snag is if you put the method reference on the object its
 refering to, that'll be circular.  I'll remember to document that caveat.

There's not necessarily any circular reference. The problem is that method
references are frequently used to implement event callbacks. This would
generally look something like this:

do {
my $a = new A;
my $b = new B;
$b-{on_click} = sub{$a-clicked($b);};
$b-do_click;
};
print "Out of scope\n";

package A;
sub clicked {my $self=shift;
  my $clicked_by = shift;
  print "I am clicked\n";
}
sub new {
  my $Proto = shift;
  my $Class = ref($Proto) || $Proto;
  my $Self = {};

  bless ($Self, $Class);
  return $Self;
}
sub DESTROY {print "bye A\n";}

package B;
sub do_click {
  my $self=shift;
  print "Clicking\n"; $self-{on_click}-();
}
sub new {
  my $Proto = shift;
  my $Class = ref($Proto) || $Proto;
  my $Self = {};

  bless ($Self, $Class);
  return $Self;
}
sub DESTROY {print "bye B\n";}


The problem is that in this case the destructors are not called immediately
after the objects go out of scope--this code prints:

Clicking
I am clicked
Out of scope
bye A
bye B


...which creates a memory leak in an event loop. The circular reference is
generally necessary, because the callback needs to know in what form the
click occurred (on object of class A in this case) and what widget was
clicked (an object of class B in this case). However, the circular reference
is not obvious at first glance--I've seen this kind of memory leak
frequently in mod_perl programs, for instance.

My objects that get method references always get an explicit destructor,
which removes all method references (which are tracked as they are created).
Something like this would be nice in a class that creates method
references--it would simply need to keep a list of referred objects, and
have an explicit destructor that iterates through the references and undefs
them. Of course, calling the destructor would be optional where no circular
reference exists.

Sorry this explanation isn't as clear as it should be--to many pints of
Guinness tonight ;-)





Re: RFC from a newbie: Method References

2000-12-16 Thread Michael G Schwern

On Fri, Dec 15, 2000 at 11:23:23PM -0800, Ian Hickson wrote:
 Having said that: The only feature that I really miss from Perl 5 is the
 lack of method pointers -- that is, references to functions in a package
 with an associated object.

Oh, that's easy.  Use a closure...

my $foo = Foo-new;
my $meth_ref = sub { $foo-method };
$methodref();

In fact, here's an example implementation...

package Class::MethRef;
use strict;

sub meth_ref {
my($proto, $method, @args) = @_;
return sub { $proto-$method(@args) };
}


So this...

my $meth_ref = $obj-meth_ref('foo', @some_stuff);
$meth_ref-();

is equivalent to this..

$obj-foo(@some_stuff);

You could even make the meth_ref take additional (or overriding) arguments.

Its a good idea, I'll put Class::MethRef on CPAN soon.


-- 
Michael G. Schwern   [EMAIL PROTECTED]http://www.pobox.com/~schwern/



Re: RFC from a newbie: Method References

2000-12-16 Thread Jeremy Howard

Michael G Schwern wrote:
 package Class::MethRef;
 use strict;

 sub meth_ref {
 my($proto, $method, @args) = @_;
 return sub { $proto-$method(@args) };
 }


 So this...

 my $meth_ref = $obj-meth_ref('foo', @some_stuff);
 $meth_ref-();

 is equivalent to this..

 $obj-foo(@some_stuff);

 You could even make the meth_ref take additional (or overriding)
arguments.

 Its a good idea, I'll put Class::MethRef on CPAN soon.

Something to be careful of--it's easy to create a circular reference when
using method pointers. As a result, neither the referrer nor referee objects
are ever destroyed.

When using method references it's important that your class keeps track of
its references, and explicitly removes them when done to allow object
destruction to occur. Perhaps this could be incorporated into
Class::MethRef?