Devel-Events-Objects
view release on metacpan or search on metacpan
lib/Devel/Events/Handler/ObjectTracker.pm view on Meta::CPAN
#!/usr/bin/perl
package Devel::Events::Handler::ObjectTracker;
use Moose;
with qw/Devel::Events::Handler/;
use Scalar::Util qw/refaddr weaken/;
use Tie::RefHash::Weak;
has live_objects => (
isa => "HashRef",
is => "ro",
default => sub {
tie my %hash, 'Tie::RefHash::Weak';
\%hash;
},
);
has object_to_class => (
isa => "HashRef",
is => "ro",
default => sub { +{} },
);
has class_counters => (
isa => "HashRef",
is => "ro",
default => sub { +{} },
);
sub new_event {
my ( $self, $type, @data ) = @_;
if ( $self->can( my $method = "handle_$type" ) ) { # FIXME pattern match? i want erlang =)
$self->$method( @data );
}
}
sub handle_object_bless {
my ( $self, %args ) = @_;
return unless $args{tracked}; # don't keep track of objects that can't be garbage collected (shared code refs for instance)
my $object = $args{object};
my $class = $args{class};
my $class_counters = $self->class_counters;
$class_counters->{$class}++;
if ( defined(my $old_class = $args{old_class}) ) {
# rebless
$class_counters->{$old_class}--;
} else {
# new object
my $entry = $self->event_to_entry( %args );
( tied %{ $self->live_objects } )->STORE( $object, $entry ); # FIXME hash access triggers overload +0
}
# we need this because in object_destroy it's not blessed anymore
#( tied %{ $self->object_to_class } )->STORE( $object, $class );
$self->object_to_class->{refaddr($object)} = $class;
}
sub event_to_entry {
my ( $self, %entry ) = @_;
weaken($entry{object});
return \%entry;
}
sub handle_object_destroy {
my ( $self, %args ) = @_;
my $object = $args{object};
if ( defined( my $class = delete($self->object_to_class->{refaddr($object)}) ) ) {
$self->class_counters->{$class}--;
}
}
__PACKAGE__;
__END__
=pod
=head1 NAME
Devel::Events::Handler::ObjectTracker - A L<Devel::Events> that tracks leaks
=head1 SYNOPSIS
use Devel::Events::Handler::ObjectTracker;
use Devel::Events::Generator::Objects;
my $tracker = Devel::Events::Handler::ObjectTracker->new();
my $gen = Devel::Events::Generator::Objects->new(
handler => $tracker,
);
$gen->enable(); # start generating events
$code->();
$gen->disable();
use Data::Dumper;
warn Dumper($tracker->live_objects);
=head1 DESCRIPTION
This object will keep track of every object created and every object destroyed
based on the C<object_bless> and C<object_destroy> events. Reblessing is
accounted for.
This handler doesn't perform any magical stuff,
L<Devel::Events::Generator::Objects> is responsible for raising the proper
events.
=head1 ATTRIBUTES
=over 4
=item live_objects
( run in 3.376 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )