← Index
NYTProf Performance Profile   « block view • line view • sub view »
For bin/dpath
  Run on Tue Jun 5 15:31:33 2012
Reported on Tue Jun 5 15:31:43 2012

Filename/home/ss5/perl5/perlbrew/perls/perl-5.14.1/lib/site_perl/5.14.1/Exception/Class.pm
StatementsExecuted 263 statements in 8.63ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
1116.03ms29.1msException::Class::::BEGIN@10Exception::Class::BEGIN@10
8113.43ms6.92msException::Class::::_make_subclassException::Class::_make_subclass
111428µs7.40msException::Class::::importException::Class::import
11167µs67µsException::Class::::BEGIN@6Exception::Class::BEGIN@6
81162µs62µsException::Class::::CORE:substException::Class::CORE:subst (opcode)
11152µs52µsException::Class::::CORE:sortException::Class::CORE:sort (opcode)
11138µs186µsException::Class::::BEGIN@11Exception::Class::BEGIN@11
11136µs79µsException::Class::::BEGIN@176Exception::Class::BEGIN@176
11134µs34µsException::Class::::BEGIN@2Exception::Class::BEGIN@2
11134µs82µsException::Class::::BEGIN@168Exception::Class::BEGIN@168
11128µs41µsException::Class::::BEGIN@8Exception::Class::BEGIN@8
11127µs78µsException::Class::::BEGIN@46Exception::Class::BEGIN@46
11126µs64µsException::Class::::BEGIN@79Exception::Class::BEGIN@79
11115µs15µsException::Class::::BEGIN@14Exception::Class::BEGIN@14
21114µs14µsException::Class::::CORE:substcontException::Class::CORE:substcont (opcode)
0000s0sException::Class::::ClassesException::Class::Classes
0000s0sException::Class::::__ANON__[:170]Exception::Class::__ANON__[:170]
0000s0sException::Class::::_make_parentsException::Class::_make_parents
0000s0sException::Class::::caughtException::Class::caught
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1package Exception::Class;
2
# spent 34µs within Exception::Class::BEGIN@2 which was called: # once (34µs+0s) by Iterator::BEGIN@22 at line 4
BEGIN {
3131µs $Exception::Class::VERSION = '1.32';
4179µs134µs}
# spent 34µs making 1 call to Exception::Class::BEGIN@2
5
62194µs167µs
# spent 67µs within Exception::Class::BEGIN@6 which was called: # once (67µs+0s) by Iterator::BEGIN@22 at line 6
use 5.008001;
# spent 67µs making 1 call to Exception::Class::BEGIN@6
7
8293µs254µs
# spent 41µs (28+13) within Exception::Class::BEGIN@8 which was called: # once (28µs+13µs) by Iterator::BEGIN@22 at line 8
use strict;
# spent 41µs making 1 call to Exception::Class::BEGIN@8 # spent 13µs making 1 call to strict::import
9
102440µs129.1ms
# spent 29.1ms (6.03+23.0) within Exception::Class::BEGIN@10 which was called: # once (6.03ms+23.0ms) by Iterator::BEGIN@22 at line 10
use Exception::Class::Base;
# spent 29.1ms making 1 call to Exception::Class::BEGIN@10
112180µs2335µs
# spent 186µs (38+148) within Exception::Class::BEGIN@11 which was called: # once (38µs+148µs) by Iterator::BEGIN@22 at line 11
use Scalar::Util qw(blessed);
# spent 186µs making 1 call to Exception::Class::BEGIN@11 # spent 148µs making 1 call to Exporter::import
12
131800nsour $BASE_EXC_CLASS;
141537µs115µs
# spent 15µs within Exception::Class::BEGIN@14 which was called: # once (15µs+0s) by Iterator::BEGIN@22 at line 14
BEGIN { $BASE_EXC_CLASS ||= 'Exception::Class::Base'; }
# spent 15µs making 1 call to Exception::Class::BEGIN@14
15
161900nsour %CLASSES;
17
18
# spent 7.40ms (428µs+6.98) within Exception::Class::import which was called: # once (428µs+6.98ms) by Iterator::BEGIN@22 at line 23 of Iterator.pm
sub import {
197146µs my $class = shift;
20
21 local $Exception::Class::Caller = caller();
22
23 my %c;
24
25 my %needs_parent;
262477µs while ( my $subclass = shift ) {
27 my $def = ref $_[0] ? shift : {};
28 $def->{isa}
29 = $def->{isa}
30 ? ( ref $def->{isa} ? $def->{isa} : [ $def->{isa} ] )
31 : [];
32
33 $c{$subclass} = $def;
34 }
35
36 # We need to sort by length because if we check for keys in the
37 # Foo::Bar:: stash, this creates a "Bar::" key in the Foo:: stash!
38MAKE_CLASSES:
39152µs foreach my $subclass ( sort { length $a <=> length $b } keys %c ) {
# spent 52µs making 1 call to Exception::Class::CORE:sort
4032131µs my $def = $c{$subclass};
41
42 # We already made this one.
43 next if $CLASSES{$subclass};
44
45 {
462655µs2129µs
# spent 78µs (27+51) within Exception::Class::BEGIN@46 which was called: # once (27µs+51µs) by Iterator::BEGIN@22 at line 46
no strict 'refs';
# spent 78µs making 1 call to Exception::Class::BEGIN@46 # spent 51µs making 1 call to strict::unimport
47838µs foreach my $parent ( @{ $def->{isa} } ) {
48752µs unless ( keys %{"$parent\::"} ) {
49 $needs_parent{$subclass} = {
50 parents => $def->{isa},
51 def => $def
52 };
53 next MAKE_CLASSES;
54 }
55 }
56 }
57
58 $class->_make_subclass(
5986.92ms subclass => $subclass,
# spent 6.92ms making 8 calls to Exception::Class::_make_subclass, avg 865µs/call
60 def => $def || {},
61 );
62 }
63
64 foreach my $subclass ( keys %needs_parent ) {
65
66 # This will be used to spot circular references.
67 my %seen;
68 $class->_make_parents( \%needs_parent, $subclass, \%seen );
69 }
70}
71
72sub _make_parents {
73 my $class = shift;
74 my $needs = shift;
75 my $subclass = shift;
76 my $seen = shift;
77 my $child = shift; # Just for error messages.
78
7921.66ms2102µs
# spent 64µs (26+38) within Exception::Class::BEGIN@79 which was called: # once (26µs+38µs) by Iterator::BEGIN@22 at line 79
no strict 'refs';
# spent 64µs making 1 call to Exception::Class::BEGIN@79 # spent 38µs making 1 call to strict::unimport
80
81 # What if someone makes a typo in specifying their 'isa' param?
82 # This should catch it. Either it's been made because it didn't
83 # have missing parents OR it's in our hash as needing a parent.
84 # If neither of these is true then the _only_ place it is
85 # mentioned is in the 'isa' param for some other class, which is
86 # not a good enough reason to make a new class.
87 die
88 "Class $subclass appears to be a typo as it is only specified in the 'isa' param for $child\n"
89 unless exists $needs->{$subclass}
90 || $CLASSES{$subclass}
91 || keys %{"$subclass\::"};
92
93 foreach my $c ( @{ $needs->{$subclass}{parents} } ) {
94
95 # It's been made
96 next if $CLASSES{$c} || keys %{"$c\::"};
97
98 die "There appears to be some circularity involving $subclass\n"
99 if $seen->{$subclass};
100
101 $seen->{$subclass} = 1;
102
103 $class->_make_parents( $needs, $c, $seen, $subclass );
104 }
105
106 return if $CLASSES{$subclass} || keys %{"$subclass\::"};
107
108 $class->_make_subclass(
109 subclass => $subclass,
110 def => $needs->{$subclass}{def}
111 );
112}
113
114
# spent 6.92ms (3.43+3.49) within Exception::Class::_make_subclass which was called 8 times, avg 865µs/call: # 8 times (3.43ms+3.49ms) by Exception::Class::import at line 59, avg 865µs/call
sub _make_subclass {
1151361.79ms my $class = shift;
116 my %p = @_;
117
118 my $subclass = $p{subclass};
119 my $def = $p{def};
120
121 my $isa;
122 if ( $def->{isa} ) {
123 $isa = ref $def->{isa} ? join ' ', @{ $def->{isa} } : $def->{isa};
124 }
125 $isa ||= $BASE_EXC_CLASS;
126
127 my $version_name = 'VERSION';
128
129 my $code = <<"EOPERL";
130package $subclass;
131
132use base qw($isa);
133
134our \$$version_name = '1.1';
135
1361;
137
138EOPERL
139
14016226µs if ( $def->{description} ) {
1411076µs ( my $desc = $def->{description} ) =~ s/([\\\'])/\\$1/g;
# spent 62µs making 8 calls to Exception::Class::CORE:subst, avg 8µs/call # spent 14µs making 2 calls to Exception::Class::CORE:substcont, avg 7µs/call
142 $code .= <<"EOPERL";
143sub description
144{
145 return '$desc';
146}
147EOPERL
148 }
149
150 my @fields;
151997µs if ( my $fields = $def->{fields} ) {
152319µs @fields = UNIVERSAL::isa( $fields, 'ARRAY' ) ? @$fields : $fields;
# spent 19µs making 3 calls to UNIVERSAL::isa, avg 6µs/call
153
154 $code
155 .= "sub Fields { return (\$_[0]->SUPER::Fields, "
156 . join( ", ", map {"'$_'"} @fields )
157 . ") }\n\n";
158
159 foreach my $field (@fields) {
160330µs $code .= sprintf( "sub %s { \$_[0]->{%s} }\n", $field, $field );
161 }
162 }
163
164 if ( my $alias = $def->{alias} ) {
165 die "Cannot make alias without caller"
166 unless defined $Exception::Class::Caller;
167
1682499µs2130µs
# spent 82µs (34+48) within Exception::Class::BEGIN@168 which was called: # once (34µs+48µs) by Iterator::BEGIN@22 at line 168
no strict 'refs';
# spent 82µs making 1 call to Exception::Class::BEGIN@168 # spent 48µs making 1 call to strict::unimport
169 *{"$Exception::Class::Caller\::$alias"}
170 = sub { $subclass->throw(@_) };
171 }
172
173 if ( my $defaults = $def->{defaults} ) {
174 $code
175 .= "sub _defaults { return shift->SUPER::_defaults, our \%_DEFAULTS }\n";
17621.66ms2122µs
# spent 79µs (36+43) within Exception::Class::BEGIN@176 which was called: # once (36µs+43µs) by Iterator::BEGIN@22 at line 176
no strict 'refs';
# spent 79µs making 1 call to Exception::Class::BEGIN@176 # spent 43µs making 1 call to strict::unimport
177 *{"$subclass\::_DEFAULTS"} = {%$defaults};
178 }
179
180 eval $code;
# spent 299µs executing statements in string eval
# includes 37µs spent executing 1 call to 4 subs defined therein. # spent 296µs executing statements in string eval
# includes 57µs spent executing 1 call to 4 subs defined therein. # spent 290µs executing statements in string eval
# includes 44µs spent executing 1 call to 4 subs defined therein. # spent 195µs executing statements in string eval
# includes 41µs spent executing 1 call to 2 subs defined therein. # spent 171µs executing statements in string eval
# includes 46µs spent executing 1 call to 2 subs defined therein. # spent 161µs executing statements in string eval
# includes 41µs spent executing 1 call to 2 subs defined therein. # spent 153µs executing statements in string eval
# includes 60µs spent executing 1 call to 2 subs defined therein. # spent 149µs executing statements in string eval
# includes 39µs spent executing 1 call to 2 subs defined therein.
181
182 die $@ if $@;
183
184 $CLASSES{$subclass} = 1;
185}
186
187sub caught {
188 my $e = $@;
189
190 return $e unless $_[1];
191
192 return unless blessed($e) && $e->isa( $_[1] );
193 return $e;
194}
195
196sub Classes { sort keys %Exception::Class::CLASSES }
197
198113µs1;
199
200# ABSTRACT: A module that allows you to declare real exception classes in Perl
201
- -
204=pod
205
206=head1 NAME
207
208Exception::Class - A module that allows you to declare real exception classes in Perl
209
210=head1 VERSION
211
212version 1.32
213
214=head1 SYNOPSIS
215
216 use Exception::Class (
217 'MyException',
218
219 'AnotherException' => { isa => 'MyException' },
220
221 'YetAnotherException' => {
222 isa => 'AnotherException',
223 description => 'These exceptions are related to IPC'
224 },
225
226 'ExceptionWithFields' => {
227 isa => 'YetAnotherException',
228 fields => [ 'grandiosity', 'quixotic' ],
229 alias => 'throw_fields',
230 },
231 );
232
233 # try
234 eval { MyException->throw( error => 'I feel funny.' ) };
235
236 my $e;
237
238 # catch
239 if ( $e = Exception::Class->caught('MyException') ) {
240 warn $e->error, "\n", $e->trace->as_string, "\n";
241 warn join ' ', $e->euid, $e->egid, $e->uid, $e->gid, $e->pid, $e->time;
242
243 exit;
244 }
245 elsif ( $e = Exception::Class->caught('ExceptionWithFields') ) {
246 $e->quixotic ? do_something_wacky() : do_something_sane();
247 }
248 else {
249 $e = Exception::Class->caught();
250 ref $e ? $e->rethrow : die $e;
251 }
252
253 # use an alias - without parens subroutine name is checked at
254 # compile time
255 throw_fields error => "No strawberry", grandiosity => "quite a bit";
256
257=head1 DESCRIPTION
258
259Exception::Class allows you to declare exception hierarchies in your
260modules in a "Java-esque" manner.
261
262It features a simple interface allowing programmers to 'declare'
263exception classes at compile time. It also has a base exception
264class, L<Exception::Class::Base>, that can be easily extended.
265
266It is designed to make structured exception handling simpler and
267better by encouraging people to use hierarchies of exceptions in their
268applications, as opposed to a single catch-all exception class.
269
270This module does not implement any try/catch syntax. Please see the
271"OTHER EXCEPTION MODULES (try/catch syntax)" section for more
272information on how to get this syntax.
273
274You will also want to look at the documentation for
275L<Exception::Class::Base>, which is the default base class for all
276exception objects created by this module.
277
278=head1 DECLARING EXCEPTION CLASSES
279
280Importing C<Exception::Class> allows you to automagically create
281L<Exception::Class::Base> subclasses. You can also create subclasses
282via the traditional means of defining your own subclass with C<@ISA>.
283These two methods may be easily combined, so that you could subclass
284an exception class defined via the automagic import, if you desired
285this.
286
287The syntax for the magic declarations is as follows:
288
289'MANDATORY CLASS NAME' => \%optional_hashref
290
291The hashref may contain the following options:
292
293=over 4
294
295=item * isa
296
297This is the class's parent class. If this isn't provided then the
298class name in C<$Exception::Class::BASE_EXC_CLASS> is assumed to be
299the parent (see below).
300
301This parameter lets you create arbitrarily deep class hierarchies.
302This can be any other L<Exception::Class::Base> subclass in your
303declaration I<or> a subclass loaded from a module.
304
305To change the default exception class you will need to change the
306value of C<$Exception::Class::BASE_EXC_CLASS> I<before> calling
307C<import()>. To do this simply do something like this:
308
309 BEGIN { $Exception::Class::BASE_EXC_CLASS = 'SomeExceptionClass'; }
310
311If anyone can come up with a more elegant way to do this please let me
312know.
313
314CAVEAT: If you want to automagically subclass an
315L<Exception::Class::Base> subclass loaded from a file, then you
316I<must> compile the class (via use or require or some other magic)
317I<before> you import C<Exception::Class> or you'll get a compile time
318error.
319
320=item * fields
321
322This allows you to define additional attributes for your exception
323class. Any field you define can be passed to the C<throw()> or
324C<new()> methods as additional parameters for the constructor. In
325addition, your exception object will have an accessor method for the
326fields you define.
327
328This parameter can be either a scalar (for a single field) or an array
329reference if you need to define multiple fields.
330
331Fields will be inherited by subclasses.
332
333=item * alias
334
335Specifying an alias causes this class to create a subroutine of the
336specified name in the I<caller's> namespace. Calling this subroutine
337is equivalent to calling C<< <class>->throw(@_) >> for the given
338exception class.
339
340Besides convenience, using aliases also allows for additional compile
341time checking. If the alias is called I<without parentheses>, as in
342C<throw_fields "an error occurred">, then Perl checks for the
343existence of the C<throw_fields()> subroutine at compile time. If
344instead you do C<< ExceptionWithFields->throw(...) >>, then Perl
345checks the class name at runtime, meaning that typos may sneak
346through.
347
348=item * description
349
350Each exception class has a description method that returns a fixed
351string. This should describe the exception I<class> (as opposed to
352any particular exception object). This may be useful for debugging if
353you start catching exceptions you weren't expecting (particularly if
354someone forgot to document them) and you don't understand the error
355messages.
356
357=back
358
359The C<Exception::Class> magic attempts to detect circular class
360hierarchies and will die if it finds one. It also detects missing
361links in a chain, for example if you declare Bar to be a subclass of
362Foo and never declare Foo.
363
364=head1 Catching Exceptions
365
366C<Exception::Class> provides some syntactic sugar for catching
367exceptions in a safe manner:
368
369 eval {...};
370
371 if ( my $e = Exception::Class->caught('My::Error') ) {
372 cleanup();
373 do_something_with_exception($e);
374 }
375
376The C<caught()> method takes a class name and returns an exception
377object if the last thrown exception is of the given class, or a
378subclass of that class. If it is not given any arguments, it simply
379returns C<$@>.
380
381You should B<always> make a copy of the exception object, rather than
382using C<$@> directly. This is necessary because if your C<cleanup()>
383function uses C<eval>, or calls something which uses it, then C<$@> is
384overwritten. Copying the exception preserves it for the call to
385C<do_something_with_exception()>.
386
387Exception objects also provide a caught method so you can write:
388
389 if ( my $e = My::Error->caught() ) {
390 cleanup();
391 do_something_with_exception($e);
392 }
393
394=head2 Uncatchable Exceptions
395
396Internally, the C<caught()> method will call C<isa()> on the exception
397object. You could make an exception "uncatchable" by overriding
398C<isa()> in that class like this:
399
400 package Exception::Uncatchable;
401
402 sub isa { shift->rethrow }
403
404Of course, this only works if you always call
405C<< Exception::Class->caught() >> after an C<eval>.
406
407=head1 USAGE RECOMMENDATION
408
409If you're creating a complex system that throws lots of different
410types of exceptions, consider putting all the exception declarations
411in one place. For an app called Foo you might make a
412C<Foo::Exceptions> module and use that in all your code. This module
413could just contain the code to make C<Exception::Class> do its
414automagic class creation. Doing this allows you to more easily see
415what exceptions you have, and makes it easier to keep track of them.
416
417This might look something like this:
418
419 package Foo::Bar::Exceptions;
420
421 use Exception::Class (
422 Foo::Bar::Exception::Senses =>
423 { description => 'sense-related exception' },
424
425 Foo::Bar::Exception::Smell => {
426 isa => 'Foo::Bar::Exception::Senses',
427 fields => 'odor',
428 description => 'stinky!'
429 },
430
431 Foo::Bar::Exception::Taste => {
432 isa => 'Foo::Bar::Exception::Senses',
433 fields => [ 'taste', 'bitterness' ],
434 description => 'like, gag me with a spoon!'
435 },
436
437 ...
438 );
439
440You may want to create a real module to subclass
441L<Exception::Class::Base> as well, particularly if you want your
442exceptions to have more methods.
443
444=head2 Subclassing Exception::Class::Base
445
446As part of your usage of C<Exception::Class>, you may want to create
447your own base exception class which subclasses
448L<Exception::Class::Base>. You should feel free to subclass any of
449the methods documented above. For example, you may want to subclass
450C<new()> to add additional information to your exception objects.
451
452=head1 Exception::Class FUNCTIONS
453
454The C<Exception::Class> method offers one function, C<Classes()>,
455which is not exported. This method returns a list of the classes that
456have been created by calling the C<Exception::Class> import() method.
457Note that this is I<all> the subclasses that have been created, so it
458may include subclasses created by things like CPAN modules, etc. Also
459note that if you simply define a subclass via the normal Perl method
460of setting C<@ISA> or C<use base>, then your subclass will not be
461included.
462
463=head1 OTHER EXCEPTION MODULES (try/catch syntax)
464
465If you are interested in adding try/catch/finally syntactic sugar to
466your code then I recommend you check out U. Arun Kumar's C<Error.pm>
467module, which implements this syntax. It also includes its own base
468exception class, C<Error::Simple>.
469
470If you would prefer to use the L<Exception::Class::Base> class
471included with this module, you'll have to add this to your code
472somewhere:
473
474 push @Exception::Class::Base::ISA, 'Error'
475 unless Exception::Class::Base->isa('Error');
476
477It's a hack but apparently it works.
478
479=head1 SUPPORT
480
481Please submit bugs to the CPAN RT system at
482http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Exception%3A%3AClass or
483via email at bug-exception-class@rt.cpan.org.
484
485=head1 DONATIONS
486
487If you'd like to thank me for the work I've done on this module,
488please consider making a "donation" to me via PayPal. I spend a lot of
489free time creating free software, and would appreciate any support
490you'd care to offer.
491
492Please note that B<I am not suggesting that you must do this> in order
493for me to continue working on this particular software. I will
494continue to do so, inasmuch as I have in the past, for as long as it
495interests me.
496
497Similarly, a donation made in this way will probably not make me work
498on this software much more, unless I get so many donations that I can
499consider working on free software full time, which seems unlikely at
500best.
501
502To donate, log into PayPal and send money to autarch@urth.org or use
503the button on this page:
504L<http://www.urth.org/~autarch/fs-donation.html>
505
506=head1 AUTHOR
507
508 Dave Rolsky <autarch@urth.org>
509
510=head1 COPYRIGHT AND LICENSE
511
512This software is Copyright (c) 2010 by Dave Rolsky.
513
514This is free software, licensed under:
515
516 The Artistic License 2.0
517
518=cut
519
520
521__END__
 
# spent 52µs within Exception::Class::CORE:sort which was called: # once (52µs+0s) by Exception::Class::import at line 39
sub Exception::Class::CORE:sort; # opcode
# spent 62µs within Exception::Class::CORE:subst which was called 8 times, avg 8µs/call: # 8 times (62µs+0s) by Exception::Class::_make_subclass at line 141, avg 8µs/call
sub Exception::Class::CORE:subst; # opcode
# spent 14µs within Exception::Class::CORE:substcont which was called 2 times, avg 7µs/call: # 2 times (14µs+0s) by Exception::Class::_make_subclass at line 141, avg 7µs/call
sub Exception::Class::CORE:substcont; # opcode