← Index
NYTProf Performance Profile   « block view • line view • sub view »
For 01.HTTP.t
  Run on Tue May 4 15:25:55 2010
Reported on Tue May 4 15:26:05 2010

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