comparison lib/IMPL/Profiler/Memory.pm @ 407:c6e90e02dd17 ref20150831

renamed Lib->lib
author cin
date Fri, 04 Sep 2015 19:40:23 +0300
parents
children
comparison
equal deleted inserted replaced
406:f23fcb19d3c1 407:c6e90e02dd17
1 package IMPL::Profiler::Memory;
2
3 use strict;
4 use Carp qw(longmess shortmess);
5 use Scalar::Util qw(refaddr weaken isweak);
6
7 my %listeners;
8 my $trapped;
9
10 BEGIN {
11 $trapped = 0;
12 }
13
14 sub import {
15 if (not $trapped) {
16 *CORE::GLOBAL::bless = sub {
17 $_[1] |= caller unless $_[1];
18 my $ref = CORE::bless $_[0],$_[1];
19
20 $_->track($ref) foreach values %listeners;
21
22 return $ref;
23 };
24 $trapped = 1;
25 }
26 }
27
28 sub _ConnectListener {
29 my ($self,$listener) = @_;
30
31 die "Invalid listener" unless ref $listener;
32
33 $listeners{refaddr($listener)} = $listener;
34 }
35
36 sub _RemoveListener {
37 my ($self,$listener) = @_;
38
39 die "Invalid listener" unless ref $listener;
40
41 delete $listeners{refaddr($listener)};
42 }
43
44 sub Monitor {
45 my ($self,$code) = @_;
46
47 my $data = IMPL::Profiler::Memory::Data->new();
48
49 $data->Monitor($code);
50
51 return $data;
52 }
53
54 package IMPL::Profiler::Memory::Data;
55 use parent qw(IMPL::Object::Fields);
56
57 use Data::Dumper();
58 use Scalar::Util qw(refaddr weaken isweak);
59
60 use fields qw( objects counter);
61
62 sub CTOR {
63 my $this = shift;
64 $this->{objects} = [];
65 $this->{counter} = 0;
66 }
67
68 sub track {
69 my $i = scalar @{$_[0]->{objects}};
70 $_[0]->{objects}[$i] = $_[1];
71 weaken($_[0]->{objects}[$i]);
72 $_[0]->{counter} ++;
73 }
74
75 sub Purge {
76 my $this = shift;
77
78 return $this->{objects} = [ grep defined($_), @{$this->{objects}}];
79 }
80
81 sub Dump {
82 my $this = shift;
83 return Data::Dumper->Dump([$this->{objects}]);
84 }
85
86 sub isLeak {
87 my ($this) = @_;
88 $this->Purge();
89 return ( scalar(@{$this->{objects}}) > 0);
90 }
91
92 sub Monitor {
93 my ($this,$code) = @_;
94
95 die "A reference to a subroutine is required" unless ref $code;
96
97 IMPL::Profiler::Memory->_ConnectListener($this);
98 eval {
99 $code->();
100 };
101 my $err = $@;
102 IMPL::Profiler::Memory->_RemoveListener($this);
103
104 die $err if $err;
105
106 return;
107 }
108
109
110
111 1;