Filename | /Users/ap13/perl5/lib/perl5/Try/Tiny.pm |
Statements | Executed 32861 statements in 34.4ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1285 | 11 | 7 | 24.9ms | 444ms | try (recurses: max depth 3, inclusive time 518ms) | Try::Tiny::
1285 | 11 | 7 | 4.18ms | 4.18ms | catch | Try::Tiny::
1 | 1 | 1 | 1.49ms | 23.6ms | BEGIN@144 | Try::Tiny::ScopeGuard::
1 | 1 | 1 | 78µs | 1.40ms | BEGIN@18 | Try::Tiny::
1 | 1 | 1 | 32µs | 62µs | BEGIN@12 | Try::Tiny::
1 | 1 | 1 | 17µs | 17µs | BEGIN@6 | Try::Tiny::
1 | 1 | 1 | 15µs | 84µs | BEGIN@15 | Try::Tiny::
1 | 1 | 1 | 13µs | 36µs | BEGIN@9 | Try::Tiny::
1 | 1 | 1 | 13µs | 20µs | BEGIN@10 | Try::Tiny::
1 | 1 | 1 | 13µs | 13µs | BEGIN@2 | Try::Tiny::
0 | 0 | 0 | 0s | 0s | DESTROY | Try::Tiny::ScopeGuard::
0 | 0 | 0 | 0s | 0s | _new | Try::Tiny::ScopeGuard::
0 | 0 | 0 | 0s | 0s | __ANON__[:18] | Try::Tiny::
0 | 0 | 0 | 0s | 0s | finally | Try::Tiny::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package Try::Tiny; | ||||
2 | # spent 13µs within Try::Tiny::BEGIN@2 which was called:
# once (13µs+0s) by Module::Implementation::BEGIN@10 at line 4 | ||||
3 | 1 | 7µs | $Try::Tiny::AUTHORITY = 'cpan:NUFFIN'; | ||
4 | 1 | 38µs | 1 | 13µs | } # spent 13µs making 1 call to Try::Tiny::BEGIN@2 |
5 | 1 | 700ns | $Try::Tiny::VERSION = '0.22'; | ||
6 | 2 | 78µs | 1 | 17µs | # spent 17µs within Try::Tiny::BEGIN@6 which was called:
# once (17µs+0s) by Module::Implementation::BEGIN@10 at line 6 # spent 17µs making 1 call to Try::Tiny::BEGIN@6 |
7 | # ABSTRACT: minimal try/catch with proper preservation of $@ | ||||
8 | |||||
9 | 2 | 41µs | 2 | 58µs | # spent 36µs (13+23) within Try::Tiny::BEGIN@9 which was called:
# once (13µs+23µs) by Module::Implementation::BEGIN@10 at line 9 # spent 36µs making 1 call to Try::Tiny::BEGIN@9
# spent 23µs making 1 call to strict::import |
10 | 2 | 46µs | 2 | 27µs | # spent 20µs (13+7) within Try::Tiny::BEGIN@10 which was called:
# once (13µs+7µs) by Module::Implementation::BEGIN@10 at line 10 # spent 20µs making 1 call to Try::Tiny::BEGIN@10
# spent 7µs making 1 call to warnings::import |
11 | |||||
12 | 3 | 113µs | 3 | 91µs | # spent 62µs (32+30) within Try::Tiny::BEGIN@12 which was called:
# once (32µs+30µs) by Module::Implementation::BEGIN@10 at line 12 # spent 62µs making 1 call to Try::Tiny::BEGIN@12
# spent 15µs making 1 call to Exporter::import
# spent 15µs making 1 call to UNIVERSAL::VERSION |
13 | 1 | 2µs | our @EXPORT = our @EXPORT_OK = qw(try catch finally); | ||
14 | |||||
15 | 2 | 86µs | 2 | 153µs | # spent 84µs (15+69) within Try::Tiny::BEGIN@15 which was called:
# once (15µs+69µs) by Module::Implementation::BEGIN@10 at line 15 # spent 84µs making 1 call to Try::Tiny::BEGIN@15
# spent 69µs making 1 call to Exporter::import |
16 | 1 | 1µs | $Carp::Internal{+__PACKAGE__}++; | ||
17 | |||||
18 | 1 | 745µs | 1 | 1.40ms | # spent 1.40ms (78µs+1.33) within Try::Tiny::BEGIN@18 which was called:
# once (78µs+1.33ms) by Module::Implementation::BEGIN@10 at line 18 # spent 1.40ms making 1 call to Try::Tiny::BEGIN@18 # spent 200µs executing statements in string eval # includes 499µs spent executing 1 call to 1 sub defined therein. |
19 | |||||
20 | # Need to prototype as @ not $$ because of the way Perl evaluates the prototype. | ||||
21 | # Keeping it at $$ means you only ever get 1 sub because we need to eval in a list | ||||
22 | # context & not a scalar one | ||||
23 | |||||
24 | # spent 444ms (24.9+419) within Try::Tiny::try which was called 1285 times, avg 345µs/call:
# 394 times (6.63ms+31.0ms) by Class::MOP::Attribute::_process_accessors at line 423 of Class/MOP/Attribute.pm, avg 96µs/call
# 320 times (6.28ms+328ms) by Class::MOP::Class::_post_add_attribute at line 904 of Class/MOP/Class.pm, avg 1.05ms/call
# 207 times (3.69ms+-3.69ms) by Moose::Meta::Method::Accessor::_compile_code at line 41 of Moose/Meta/Method/Accessor.pm, avg 0s/call
# 195 times (4.44ms+-4.44ms) by Class::MOP::Method::Accessor::_generate_reader_method_inline at line 169 of Class/MOP/Method/Accessor.pm, avg 0s/call
# 71 times (1.69ms+-1.69ms) by Class::MOP::Method::Accessor::_generate_accessor_method_inline at line 127 of Class/MOP/Method/Accessor.pm, avg 0s/call
# 46 times (1.10ms+64.8ms) by Class::MOP::Method::Constructor::_generate_constructor_method_inline at line 115 of Class/MOP/Method/Constructor.pm, avg 1.43ms/call
# 23 times (417µs+-417µs) by Class::MOP::Method::Accessor::_generate_predicate_method_inline at line 230 of Class/MOP/Method/Accessor.pm, avg 0s/call
# 16 times (378µs+3.12ms) by Moose::Meta::Method::Destructor::_initialize_body at line 100 of Moose/Meta/Method/Destructor.pm, avg 219µs/call
# 8 times (160µs+-160µs) by Class::MOP::Method::Accessor::_generate_clearer_method_inline at line 258 of Class/MOP/Method/Accessor.pm, avg 0s/call
# 3 times (53µs+-53µs) by Class::MOP::Method::Accessor::_generate_writer_method_inline at line 202 of Class/MOP/Method/Accessor.pm, avg 0s/call
# 2 times (87µs+1.89ms) by Module::Implementation::_load_implementation at line 90 of Module/Implementation.pm, avg 989µs/call | ||||
25 | 1285 | 857µs | my ( $try, @code_refs ) = @_; | ||
26 | |||||
27 | # we need to save this here, the eval block will be in scalar context due | ||||
28 | # to $failed | ||||
29 | 1285 | 281µs | my $wantarray = wantarray; | ||
30 | |||||
31 | # work around perl bug by explicitly initializing these, due to the likelyhood | ||||
32 | # this will be used in global destruction (perl rt#119311) | ||||
33 | 1285 | 362µs | my ( $catch, @finally ) = (); | ||
34 | |||||
35 | # find labeled blocks in the argument list. | ||||
36 | # catch and finally tag the blocks by blessing a scalar reference to them. | ||||
37 | 1285 | 877µs | foreach my $code_ref (@code_refs) { | ||
38 | |||||
39 | 1285 | 1.71ms | if ( ref($code_ref) eq 'Try::Tiny::Catch' ) { | ||
40 | 1285 | 149µs | croak 'A try() may not be followed by multiple catch() blocks' | ||
41 | if $catch; | ||||
42 | 1285 | 454µs | $catch = ${$code_ref}; | ||
43 | } elsif ( ref($code_ref) eq 'Try::Tiny::Finally' ) { | ||||
44 | push @finally, ${$code_ref}; | ||||
45 | } else { | ||||
46 | croak( | ||||
47 | 'try() encountered an unexpected argument (' | ||||
48 | . ( defined $code_ref ? $code_ref : 'undef' ) | ||||
49 | . ') - perhaps a missing semi-colon before or' | ||||
50 | ); | ||||
51 | } | ||||
52 | } | ||||
53 | |||||
54 | # FIXME consider using local $SIG{__DIE__} to accumulate all errors. It's | ||||
55 | # not perfect, but we could provide a list of additional errors for | ||||
56 | # $catch->(); | ||||
57 | |||||
58 | # name the blocks if we have Sub::Name installed | ||||
59 | 1285 | 874µs | my $caller = caller; | ||
60 | 1285 | 6.10ms | 1285 | 3.51ms | subname("${caller}::try {...} " => $try); # spent 3.51ms making 1285 calls to Sub::Name::subname, avg 3µs/call |
61 | 1285 | 4.34ms | 1285 | 2.25ms | subname("${caller}::catch {...} " => $catch) if $catch; # spent 2.25ms making 1285 calls to Sub::Name::subname, avg 2µs/call |
62 | 1285 | 660µs | subname("${caller}::finally {...} " => $_) foreach @finally; | ||
63 | |||||
64 | # save the value of $@ so we can set $@ back to it in the beginning of the eval | ||||
65 | # and restore $@ after the eval finishes | ||||
66 | 1285 | 339µs | my $prev_error = $@; | ||
67 | |||||
68 | 1285 | 244µs | my ( @ret, $error ); | ||
69 | |||||
70 | # failed will be true if the eval dies, because 1 will not be returned | ||||
71 | # from the eval body | ||||
72 | 1285 | 806µs | my $failed = not eval { | ||
73 | 1285 | 158µs | $@ = $prev_error; | ||
74 | |||||
75 | # evaluate the try block in the correct context | ||||
76 | 1285 | 3.02ms | 569 | 330ms | if ( $wantarray ) { # spent 179ms making 300 calls to Class::MOP::Method::Accessor::try {...} , avg 596µs/call
# spent 83.7ms making 207 calls to Moose::Meta::Method::Accessor::try {...} , avg 404µs/call
# spent 64.5ms making 46 calls to Class::MOP::Method::Constructor::try {...} , avg 1.40ms/call
# spent 3.03ms making 16 calls to Moose::Meta::Method::Destructor::try {...} , avg 189µs/call |
77 | @ret = $try->(); | ||||
78 | } elsif ( defined $wantarray ) { | ||||
79 | $ret[0] = $try->(); | ||||
80 | } else { | ||||
81 | 716 | 834µs | 716 | 601ms | $try->(); # spent 327ms making 320 calls to Class::MOP::Class::try {...} , avg 1.02ms/call
# spent 272ms making 394 calls to Class::MOP::Attribute::try {...} , avg 691µs/call
# spent 1.86ms making 2 calls to Module::Implementation::try {...} , avg 931µs/call |
82 | }; | ||||
83 | |||||
84 | 1285 | 490µs | return 1; # properly set $fail to false | ||
85 | }; | ||||
86 | |||||
87 | # preserve the current error and reset the original value of $@ | ||||
88 | 1285 | 187µs | $error = $@; | ||
89 | 1285 | 157µs | $@ = $prev_error; | ||
90 | |||||
91 | # set up a scope guard to invoke the finally block at the end | ||||
92 | my @guards = | ||||
93 | 1285 | 693µs | map { Try::Tiny::ScopeGuard->_new($_, $failed ? $error : ()) } | ||
94 | @finally; | ||||
95 | |||||
96 | # at this point $failed contains a true value if the eval died, even if some | ||||
97 | # destructor overwrote $@ as the eval was unwinding. | ||||
98 | 1285 | 227µs | if ( $failed ) { | ||
99 | # if we got an error, invoke the catch block. | ||||
100 | if ( $catch ) { | ||||
101 | # This works like given($error), but is backwards compatible and | ||||
102 | # sets $_ in the dynamic scope for the body of C<$catch> | ||||
103 | for ($error) { | ||||
104 | return $catch->($error); | ||||
105 | } | ||||
106 | |||||
107 | # in case when() was used without an explicit return, the C<for> | ||||
108 | # loop will be aborted and there's no useful return value | ||||
109 | } | ||||
110 | |||||
111 | return; | ||||
112 | } else { | ||||
113 | # no failure, $@ is back to what it was, everything is fine | ||||
114 | 1285 | 3.94ms | return $wantarray ? @ret : $ret[0]; | ||
115 | } | ||||
116 | } | ||||
117 | |||||
118 | # spent 4.18ms within Try::Tiny::catch which was called 1285 times, avg 3µs/call:
# 394 times (1.18ms+0s) by Class::MOP::Attribute::_process_accessors at line 423 of Class/MOP/Attribute.pm, avg 3µs/call
# 320 times (1.26ms+0s) by Class::MOP::Class::_post_add_attribute at line 904 of Class/MOP/Class.pm, avg 4µs/call
# 207 times (580µs+0s) by Moose::Meta::Method::Accessor::_compile_code at line 41 of Moose/Meta/Method/Accessor.pm, avg 3µs/call
# 195 times (536µs+0s) by Class::MOP::Method::Accessor::_generate_reader_method_inline at line 169 of Class/MOP/Method/Accessor.pm, avg 3µs/call
# 71 times (204µs+0s) by Class::MOP::Method::Accessor::_generate_accessor_method_inline at line 127 of Class/MOP/Method/Accessor.pm, avg 3µs/call
# 46 times (226µs+0s) by Class::MOP::Method::Constructor::_generate_constructor_method_inline at line 115 of Class/MOP/Method/Constructor.pm, avg 5µs/call
# 23 times (58µs+0s) by Class::MOP::Method::Accessor::_generate_predicate_method_inline at line 230 of Class/MOP/Method/Accessor.pm, avg 3µs/call
# 16 times (84µs+0s) by Moose::Meta::Method::Destructor::_initialize_body at line 100 of Moose/Meta/Method/Destructor.pm, avg 5µs/call
# 8 times (20µs+0s) by Class::MOP::Method::Accessor::_generate_clearer_method_inline at line 258 of Class/MOP/Method/Accessor.pm, avg 2µs/call
# 3 times (8µs+0s) by Class::MOP::Method::Accessor::_generate_writer_method_inline at line 202 of Class/MOP/Method/Accessor.pm, avg 3µs/call
# 2 times (30µs+0s) by Module::Implementation::_load_implementation at line 90 of Module/Implementation.pm, avg 15µs/call | ||||
119 | 1285 | 743µs | my ( $block, @rest ) = @_; | ||
120 | |||||
121 | 1285 | 149µs | croak 'Useless bare catch()' unless wantarray; | ||
122 | |||||
123 | return ( | ||||
124 | 1285 | 4.26ms | bless(\$block, 'Try::Tiny::Catch'), | ||
125 | @rest, | ||||
126 | ); | ||||
127 | } | ||||
128 | |||||
129 | sub finally (&;@) { | ||||
130 | my ( $block, @rest ) = @_; | ||||
131 | |||||
132 | croak 'Useless bare finally()' unless wantarray; | ||||
133 | |||||
134 | return ( | ||||
135 | bless(\$block, 'Try::Tiny::Finally'), | ||||
136 | @rest, | ||||
137 | ); | ||||
138 | } | ||||
139 | |||||
140 | { | ||||
141 | 1 | 500ns | package # hide from PAUSE | ||
142 | Try::Tiny::ScopeGuard; | ||||
143 | |||||
144 | 2 | 343µs | 2 | 23.6ms | # spent 23.6ms (1.49+22.1) within Try::Tiny::ScopeGuard::BEGIN@144 which was called:
# once (1.49ms+22.1ms) by Module::Implementation::BEGIN@10 at line 144 # spent 23.6ms making 1 call to Try::Tiny::ScopeGuard::BEGIN@144
# spent 52µs making 1 call to constant::import |
145 | |||||
146 | sub _new { | ||||
147 | shift; | ||||
148 | bless [ @_ ]; | ||||
149 | } | ||||
150 | |||||
151 | sub DESTROY { | ||||
152 | my ($code, @args) = @{ $_[0] }; | ||||
153 | |||||
154 | local $@ if UNSTABLE_DOLLARAT; | ||||
155 | eval { | ||||
156 | $code->(@args); | ||||
157 | 1; | ||||
158 | } or do { | ||||
159 | warn | ||||
160 | "Execution of finally() block $code resulted in an exception, which " | ||||
161 | . '*CAN NOT BE PROPAGATED* due to fundamental limitations of Perl. ' | ||||
162 | . 'Your program will continue as if this event never took place. ' | ||||
163 | . "Original exception text follows:\n\n" | ||||
164 | . (defined $@ ? $@ : '$@ left undefined...') | ||||
165 | . "\n" | ||||
166 | ; | ||||
167 | } | ||||
168 | } | ||||
169 | } | ||||
170 | |||||
171 | __PACKAGE__ | ||||
172 | |||||
173 | 1 | 7µs | __END__ |