| Filename | /home/doy/perl5/perlbrew/perls/perl-5.10.1/lib/site_perl/5.10.1/Try/Tiny.pm |
| Statements | Executed 10636 statements in 58.6ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 486 | 4 | 4 | 45.6ms | 7.23s | Try::Tiny::try (recurses: max depth 4, inclusive time 2.01s) |
| 480 | 3 | 3 | 9.99ms | 9.99ms | Try::Tiny::catch |
| 1 | 1 | 1 | 69µs | 87µs | Try::Tiny::BEGIN@3 |
| 1 | 1 | 1 | 43µs | 43µs | Try::Tiny::BEGIN@8 |
| 1 | 1 | 1 | 42µs | 254µs | Try::Tiny::BEGIN@46 |
| 1 | 1 | 1 | 38µs | 354µs | Try::Tiny::BEGIN@6 |
| 0 | 0 | 0 | 0s | 0s | Try::Tiny::ScopeGuard::DESTROY |
| 0 | 0 | 0 | 0s | 0s | Try::Tiny::ScopeGuard::_new |
| 0 | 0 | 0 | 0s | 0s | Try::Tiny::finally |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package Try::Tiny; | ||||
| 2 | |||||
| 3 | 3 | 115µs | 2 | 105µs | # spent 87µs (69+18) within Try::Tiny::BEGIN@3 which was called:
# once (69µs+18µs) by Class::MOP::BEGIN@14 at line 3 # spent 87µs making 1 call to Try::Tiny::BEGIN@3
# spent 18µs making 1 call to strict::import |
| 4 | #use warnings; | ||||
| 5 | |||||
| 6 | 3 | 155µs | 2 | 669µs | # spent 354µs (38+316) within Try::Tiny::BEGIN@6 which was called:
# once (38µs+316µs) by Class::MOP::BEGIN@14 at line 6 # spent 354µs making 1 call to Try::Tiny::BEGIN@6
# spent 316µs making 1 call to vars::import |
| 7 | |||||
| 8 | # spent 43µs within Try::Tiny::BEGIN@8 which was called:
# once (43µs+0s) by Class::MOP::BEGIN@14 at line 11 | ||||
| 9 | 2 | 42µs | require Exporter; | ||
| 10 | @ISA = qw(Exporter); | ||||
| 11 | 1 | 447µs | 1 | 43µs | } # spent 43µs making 1 call to Try::Tiny::BEGIN@8 |
| 12 | |||||
| 13 | 1 | 4µs | $VERSION = "0.07"; | ||
| 14 | |||||
| 15 | 1 | 67µs | $VERSION = eval $VERSION; # spent 10µs executing statements in string eval | ||
| 16 | |||||
| 17 | 1 | 10µs | @EXPORT = @EXPORT_OK = qw(try catch finally); | ||
| 18 | |||||
| 19 | 1 | 4µs | $Carp::Internal{+__PACKAGE__}++; | ||
| 20 | |||||
| 21 | # Need to prototype as @ not $$ because of the way Perl evaluates the prototype. | ||||
| 22 | # Keeping it at $$ means you only ever get 1 sub because we need to eval in a list | ||||
| 23 | # context & not a scalar one | ||||
| 24 | |||||
| 25 | # spent 7.23s (45.6ms+7.18) within Try::Tiny::try which was called 486 times, avg 14.9ms/call:
# 256 times (24.2ms+-24.2ms) by Class::MOP::Attribute::_process_accessors at line 345 of Class/MOP/Attribute.pm, avg 0s/call
# 187 times (17.3ms+1.37s) by Class::MOP::Class::_post_add_attribute at line 794 of Class/MOP/Class.pm, avg 7.42ms/call
# 37 times (3.61ms+5.83s) by Class::MOP::load_first_existing_class at line 125 of Class/MOP.pm, avg 158ms/call
# 6 times (463µs+5.47ms) by Moose::Meta::Attribute::does at line 40 of Moose/Meta/Attribute.pm, avg 989µs/call | ||||
| 26 | 9659 | 45.1ms | my ( $try, @code_refs ) = @_; | ||
| 27 | |||||
| 28 | # we need to save this here, the eval block will be in scalar context due | ||||
| 29 | # to $failed | ||||
| 30 | my $wantarray = wantarray; | ||||
| 31 | |||||
| 32 | my ( $catch, @finally ); | ||||
| 33 | |||||
| 34 | # find labeled blocks in the argument list. | ||||
| 35 | # catch and finally tag the blocks by blessing a scalar reference to them. | ||||
| 36 | foreach my $code_ref (@code_refs) { | ||||
| 37 | next unless $code_ref; | ||||
| 38 | |||||
| 39 | my $ref = ref($code_ref); | ||||
| 40 | |||||
| 41 | if ( $ref eq 'Try::Tiny::Catch' ) { | ||||
| 42 | $catch = ${$code_ref}; | ||||
| 43 | } elsif ( $ref eq 'Try::Tiny::Finally' ) { | ||||
| 44 | push @finally, ${$code_ref}; | ||||
| 45 | } else { | ||||
| 46 | 3 | 1.10ms | 2 | 466µs | # spent 254µs (42+212) within Try::Tiny::BEGIN@46 which was called:
# once (42µs+212µs) by Class::MOP::BEGIN@14 at line 46 # spent 254µs making 1 call to Try::Tiny::BEGIN@46
# spent 212µs making 1 call to Exporter::import |
| 47 | confess("Unknown code ref type given '${ref}'. Check your usage & try again"); | ||||
| 48 | } | ||||
| 49 | } | ||||
| 50 | |||||
| 51 | # save the value of $@ so we can set $@ back to it in the beginning of the eval | ||||
| 52 | my $prev_error = $@; | ||||
| 53 | |||||
| 54 | my ( @ret, $error, $failed ); | ||||
| 55 | |||||
| 56 | # FIXME consider using local $SIG{__DIE__} to accumulate all errors. It's | ||||
| 57 | # not perfect, but we could provide a list of additional errors for | ||||
| 58 | # $catch->(); | ||||
| 59 | |||||
| 60 | { | ||||
| 61 | # localize $@ to prevent clobbering of previous value by a successful | ||||
| 62 | # eval. | ||||
| 63 | local $@; | ||||
| 64 | |||||
| 65 | # failed will be true if the eval dies, because 1 will not be returned | ||||
| 66 | # from the eval body | ||||
| 67 | $failed = not eval { | ||||
| 68 | $@ = $prev_error; | ||||
| 69 | |||||
| 70 | # evaluate the try block in the correct context | ||||
| 71 | 43 | 7.21s | if ( $wantarray ) { # spent 7.20s making 37 calls to Class::MOP::__ANON__[Class/MOP.pm:118], avg 195ms/call
# spent 5.47ms making 6 calls to Moose::Meta::Attribute::__ANON__[Moose/Meta/Attribute.pm:40], avg 911µs/call | ||
| 72 | @ret = $try->(); | ||||
| 73 | } elsif ( defined $wantarray ) { | ||||
| 74 | $ret[0] = $try->(); | ||||
| 75 | } else { | ||||
| 76 | 443 | 1.98s | $try->(); # spent 1.56s making 187 calls to Class::MOP::Class::__ANON__[Class/MOP/Class.pm:790], avg 8.33ms/call
# spent 422ms making 256 calls to Class::MOP::Attribute::__ANON__[Class/MOP/Attribute.pm:342], avg 1.65ms/call | ||
| 77 | }; | ||||
| 78 | |||||
| 79 | return 1; # properly set $fail to false | ||||
| 80 | }; | ||||
| 81 | |||||
| 82 | # copy $@ to $error; when we leave this scope, local $@ will revert $@ | ||||
| 83 | # back to its previous value | ||||
| 84 | $error = $@; | ||||
| 85 | } | ||||
| 86 | |||||
| 87 | # set up a scope guard to invoke the finally block at the end | ||||
| 88 | my @guards = | ||||
| 89 | map { Try::Tiny::ScopeGuard->_new($_, $failed ? $error : ()) } | ||||
| 90 | @finally; | ||||
| 91 | |||||
| 92 | # at this point $failed contains a true value if the eval died, even if some | ||||
| 93 | # destructor overwrote $@ as the eval was unwinding. | ||||
| 94 | if ( $failed ) { | ||||
| 95 | # if we got an error, invoke the catch block. | ||||
| 96 | if ( $catch ) { | ||||
| 97 | # This works like given($error), but is backwards compatible and | ||||
| 98 | # sets $_ in the dynamic scope for the body of C<$catch> | ||||
| 99 | for ($error) { | ||||
| 100 | 5 | 478µs | return $catch->($error); # spent 478µs making 5 calls to Class::MOP::__ANON__[Class/MOP.pm:125], avg 96µs/call | ||
| 101 | } | ||||
| 102 | |||||
| 103 | # in case when() was used without an explicit return, the C<for> | ||||
| 104 | # loop will be aborted and there's no useful return value | ||||
| 105 | } | ||||
| 106 | |||||
| 107 | return; | ||||
| 108 | } else { | ||||
| 109 | # no failure, $@ is back to what it was, everything is fine | ||||
| 110 | return $wantarray ? @ret : $ret[0]; | ||||
| 111 | } | ||||
| 112 | } | ||||
| 113 | |||||
| 114 | # spent 9.99ms within Try::Tiny::catch which was called 480 times, avg 21µs/call:
# 256 times (5.09ms+0s) by Class::MOP::Attribute::_process_accessors at line 345 of Class/MOP/Attribute.pm, avg 20µs/call
# 187 times (4.11ms+0s) by Class::MOP::Class::_post_add_attribute at line 794 of Class/MOP/Class.pm, avg 22µs/call
# 37 times (800µs+0s) by Class::MOP::load_first_existing_class at line 125 of Class/MOP.pm, avg 22µs/call | ||||
| 115 | 960 | 11.5ms | my ( $block, @rest ) = @_; | ||
| 116 | |||||
| 117 | return ( | ||||
| 118 | bless(\$block, 'Try::Tiny::Catch'), | ||||
| 119 | @rest, | ||||
| 120 | ); | ||||
| 121 | } | ||||
| 122 | |||||
| 123 | sub finally (&;@) { | ||||
| 124 | my ( $block, @rest ) = @_; | ||||
| 125 | |||||
| 126 | return ( | ||||
| 127 | bless(\$block, 'Try::Tiny::Finally'), | ||||
| 128 | @rest, | ||||
| 129 | ); | ||||
| 130 | } | ||||
| 131 | |||||
| 132 | { | ||||
| 133 | 1 | 5µs | package Try::Tiny::ScopeGuard; | ||
| 134 | |||||
| 135 | sub _new { | ||||
| 136 | shift; | ||||
| 137 | bless [ @_ ]; | ||||
| 138 | } | ||||
| 139 | |||||
| 140 | sub DESTROY { | ||||
| 141 | my @guts = @{ shift() }; | ||||
| 142 | my $code = shift @guts; | ||||
| 143 | $code->(@guts); | ||||
| 144 | } | ||||
| 145 | } | ||||
| 146 | |||||
| 147 | __PACKAGE__ | ||||
| 148 | |||||
| 149 | 1 | 18µs | __END__ |