Profile of Exception/Class.pm

← 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:38 2012

Filename | /home/ss5/perl5/perlbrew/perls/perl-5.14.1/lib/site_perl/5.14.1/Exception/Class.pm
Statements | Executed 263 statements in 8.63ms

Subroutines
Calls | P | F | Exclusive Time | Inclusive Time | Subroutine
--- | --- | --- | --- | --- | ---
1 | 1 | 1 | 6.03ms | 29.1ms | Exception::Class::::BEGIN@10Exception::Class::BEGIN@10
8 | 1 | 1 | 3.43ms | 6.92ms | Exception::Class::::_make_subclassException::Class::_make_subclass
1 | 1 | 1 | 428µs | 7.40ms | Exception::Class::::importException::Class::import
1 | 1 | 1 | 67µs | 67µs | Exception::Class::::BEGIN@6Exception::Class::BEGIN@6
8 | 1 | 1 | 62µs | 62µs | Exception::Class::::CORE:substException::Class::CORE:subst (opcode)
1 | 1 | 1 | 52µs | 52µs | Exception::Class::::CORE:sortException::Class::CORE:sort (opcode)
1 | 1 | 1 | 38µs | 186µs | Exception::Class::::BEGIN@11Exception::Class::BEGIN@11
1 | 1 | 1 | 36µs | 79µs | Exception::Class::::BEGIN@176Exception::Class::BEGIN@176
1 | 1 | 1 | 34µs | 34µs | Exception::Class::::BEGIN@2Exception::Class::BEGIN@2
1 | 1 | 1 | 34µs | 82µs | Exception::Class::::BEGIN@168Exception::Class::BEGIN@168
1 | 1 | 1 | 28µs | 41µs | Exception::Class::::BEGIN@8Exception::Class::BEGIN@8
1 | 1 | 1 | 27µs | 78µs | Exception::Class::::BEGIN@46Exception::Class::BEGIN@46
1 | 1 | 1 | 26µs | 64µs | Exception::Class::::BEGIN@79Exception::Class::BEGIN@79
1 | 1 | 1 | 15µs | 15µs | Exception::Class::::BEGIN@14Exception::Class::BEGIN@14
2 | 1 | 1 | 14µs | 14µs | Exception::Class::::CORE:substcontException::Class::CORE:substcont (opcode)
0 | 0 | 0 | 0s | 0s | Exception::Class::::ClassesException::Class::Classes
0 | 0 | 0 | 0s | 0s | Exception::Class::::__ANON__[:170]Exception::Class::__ANON__[:170]
0 | 0 | 0 | 0s | 0s | Exception::Class::::_make_parentsException::Class::_make_parents
0 | 0 | 0 | 0s | 0s | Exception::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
--- | --- | --- | --- | --- | ---
1 |  |  |  |  | package 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 {
3 | 1 | 31µs |  |  | $Exception::Class::VERSION = '1.32';
4 | 1 | 79µs | 1 | 34µs | } # spent 34µs making 1 call to Exception::Class::BEGIN@2
5 |  |  |  |  |
6 | 2 | 194µs | 1 | 67µ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 |  |  |  |  |
8 | 2 | 93µs | 2 | 54µ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 |  |  |  |  |
10 | 2 | 440µs | 1 | 29.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
11 | 2 | 180µs | 2 | 335µ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 |  |  |  |  |
13 | 1 | 800ns |  |  | our $BASE_EXC_CLASS;
14 | 1 | 537µs | 1 | 15µ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 |  |  |  |  |
16 | 1 | 900ns |  |  | our %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 {
19 | 78 | 444µ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 |  |  |  |  | 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!
38 |  |  |  |  | MAKE_CLASSES:
39 |  |  | 1 | 52µs | foreach my $subclass ( sort { length $a <=> length $b } keys %c ) { # spent 52µs making 1 call to Exception::Class::CORE:sort
40 |  |  |  |  | my $def = $c{$subclass};
41 |  |  |  |  |
42 |  |  |  |  | # We already made this one.
43 |  |  |  |  | next if $CLASSES{$subclass};
44 |  |  |  |  |
45 |  |  |  |  | {
46 | 2 | 655µs | 2 | 129µ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
47 |  |  |  |  | foreach my $parent ( @{ $def->{isa} } ) {
48 |  |  |  |  | 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(
59 |  |  | 8 | 6.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 |  |  |  |  |
72 |  |  |  |  | sub _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 |  |  |  |  |
79 | 2 | 1.66ms | 2 | 102µ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 {
115 | 164 | 2.15ms |  |  | 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";
130 |  |  |  |  | package $subclass;
131 |  |  |  |  |
132 |  |  |  |  | use base qw($isa);
133 |  |  |  |  |
134 |  |  |  |  | our \$$version_name = '1.1';
135 |  |  |  |  |
136 |  |  |  |  | 1;
137 |  |  |  |  |
138 |  |  |  |  | EOPERL
139 |  |  |  |  |
140 |  |  |  |  | if ( $def->{description} ) {
141 |  |  | 10 | 76µ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";
143 |  |  |  |  | sub description
144 |  |  |  |  | {
145 |  |  |  |  | return '$desc';
146 |  |  |  |  | }
147 |  |  |  |  | EOPERL
148 |  |  |  |  | }
149 |  |  |  |  |
150 |  |  |  |  | my @fields;
151 |  |  |  |  | if ( my $fields = $def->{fields} ) {
152 |  |  | 3 | 19µ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) {
160 |  |  |  |  | $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 |  |  |  |  |
168 | 2 | 499µs | 2 | 130µ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";
176 | 2 | 1.66ms | 2 | 122µ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 |  |  |  |  |
187 |  |  |  |  | sub caught {
188 |  |  |  |  | my $e = $@;
189 |  |  |  |  |
190 |  |  |  |  | return $e unless $_[1];
191 |  |  |  |  |
192 |  |  |  |  | return unless blessed($e) && $e->isa( $_[1] );
193 |  |  |  |  | return $e;
194 |  |  |  |  | }
195 |  |  |  |  |
196 |  |  |  |  | sub Classes { sort keys %Exception::Class::CLASSES }
197 |  |  |  |  |
198 | 1 | 13µs |  |  | 1;
199 |  |  |  |  |
200 |  |  |  |  | # ABSTRACT: A module that allows you to declare real exception classes in Perl
201 |  |  |  |  |
- - |  |  |  |  |
204 |  |  |  |  | =pod
205 |  |  |  |  |
206 |  |  |  |  | =head1 NAME
207 |  |  |  |  |
208 |  |  |  |  | Exception::Class - A module that allows you to declare real exception classes in Perl
209 |  |  |  |  |
210 |  |  |  |  | =head1 VERSION
211 |  |  |  |  |
212 |  |  |  |  | version 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 |  |  |  |  |
259 |  |  |  |  | Exception::Class allows you to declare exception hierarchies in your
260 |  |  |  |  | modules in a "Java-esque" manner.
261 |  |  |  |  |
262 |  |  |  |  | It features a simple interface allowing programmers to 'declare'
263 |  |  |  |  | exception classes at compile time. It also has a base exception
264 |  |  |  |  | class, L<Exception::Class::Base>, that can be easily extended.
265 |  |  |  |  |
266 |  |  |  |  | It is designed to make structured exception handling simpler and
267 |  |  |  |  | better by encouraging people to use hierarchies of exceptions in their
268 |  |  |  |  | applications, as opposed to a single catch-all exception class.
269 |  |  |  |  |
270 |  |  |  |  | This module does not implement any try/catch syntax. Please see the
271 |  |  |  |  | "OTHER EXCEPTION MODULES (try/catch syntax)" section for more
272 |  |  |  |  | information on how to get this syntax.
273 |  |  |  |  |
274 |  |  |  |  | You will also want to look at the documentation for
275 |  |  |  |  | L<Exception::Class::Base>, which is the default base class for all
276 |  |  |  |  | exception objects created by this module.
277 |  |  |  |  |
278 |  |  |  |  | =head1 DECLARING EXCEPTION CLASSES
279 |  |  |  |  |
280 |  |  |  |  | Importing C<Exception::Class> allows you to automagically create
281 |  |  |  |  | L<Exception::Class::Base> subclasses. You can also create subclasses
282 |  |  |  |  | via the traditional means of defining your own subclass with C<@ISA>.
283 |  |  |  |  | These two methods may be easily combined, so that you could subclass
284 |  |  |  |  | an exception class defined via the automagic import, if you desired
285 |  |  |  |  | this.
286 |  |  |  |  |
287 |  |  |  |  | The syntax for the magic declarations is as follows:
288 |  |  |  |  |
289 |  |  |  |  | 'MANDATORY CLASS NAME' => \%optional_hashref
290 |  |  |  |  |
291 |  |  |  |  | The hashref may contain the following options:
292 |  |  |  |  |
293 |  |  |  |  | =over 4
294 |  |  |  |  |
295 |  |  |  |  | =item * isa
296 |  |  |  |  |
297 |  |  |  |  | This is the class's parent class. If this isn't provided then the
298 |  |  |  |  | class name in C<$Exception::Class::BASE_EXC_CLASS> is assumed to be
299 |  |  |  |  | the parent (see below).
300 |  |  |  |  |
301 |  |  |  |  | This parameter lets you create arbitrarily deep class hierarchies.
302 |  |  |  |  | This can be any other L<Exception::Class::Base> subclass in your
303 |  |  |  |  | declaration I<or> a subclass loaded from a module.
304 |  |  |  |  |
305 |  |  |  |  | To change the default exception class you will need to change the
306 |  |  |  |  | value of C<$Exception::Class::BASE_EXC_CLASS> I<before> calling
307 |  |  |  |  | C<import()>. To do this simply do something like this:
308 |  |  |  |  |
309 |  |  |  |  | BEGIN { $Exception::Class::BASE_EXC_CLASS = 'SomeExceptionClass'; }
310 |  |  |  |  |
311 |  |  |  |  | If anyone can come up with a more elegant way to do this please let me
312 |  |  |  |  | know.
313 |  |  |  |  |
314 |  |  |  |  | CAVEAT: If you want to automagically subclass an
315 |  |  |  |  | L<Exception::Class::Base> subclass loaded from a file, then you
316 |  |  |  |  | I<must> compile the class (via use or require or some other magic)
317 |  |  |  |  | I<before> you import C<Exception::Class> or you'll get a compile time
318 |  |  |  |  | error.
319 |  |  |  |  |
320 |  |  |  |  | =item * fields
321 |  |  |  |  |
322 |  |  |  |  | This allows you to define additional attributes for your exception
323 |  |  |  |  | class. Any field you define can be passed to the C<throw()> or
324 |  |  |  |  | C<new()> methods as additional parameters for the constructor. In
325 |  |  |  |  | addition, your exception object will have an accessor method for the
326 |  |  |  |  | fields you define.
327 |  |  |  |  |
328 |  |  |  |  | This parameter can be either a scalar (for a single field) or an array
329 |  |  |  |  | reference if you need to define multiple fields.
330 |  |  |  |  |
331 |  |  |  |  | Fields will be inherited by subclasses.
332 |  |  |  |  |
333 |  |  |  |  | =item * alias
334 |  |  |  |  |
335 |  |  |  |  | Specifying an alias causes this class to create a subroutine of the
336 |  |  |  |  | specified name in the I<caller's> namespace. Calling this subroutine
337 |  |  |  |  | is equivalent to calling C<< <class>->throw(@_) >> for the given
338 |  |  |  |  | exception class.
339 |  |  |  |  |
340 |  |  |  |  | Besides convenience, using aliases also allows for additional compile
341 |  |  |  |  | time checking. If the alias is called I<without parentheses>, as in
342 |  |  |  |  | C<throw_fields "an error occurred">, then Perl checks for the
343 |  |  |  |  | existence of the C<throw_fields()> subroutine at compile time. If
344 |  |  |  |  | instead you do C<< ExceptionWithFields->throw(...) >>, then Perl
345 |  |  |  |  | checks the class name at runtime, meaning that typos may sneak
346 |  |  |  |  | through.
347 |  |  |  |  |
348 |  |  |  |  | =item * description
349 |  |  |  |  |
350 |  |  |  |  | Each exception class has a description method that returns a fixed
351 |  |  |  |  | string. This should describe the exception I<class> (as opposed to
352 |  |  |  |  | any particular exception object). This may be useful for debugging if
353 |  |  |  |  | you start catching exceptions you weren't expecting (particularly if
354 |  |  |  |  | someone forgot to document them) and you don't understand the error
355 |  |  |  |  | messages.
356 |  |  |  |  |
357 |  |  |  |  | =back
358 |  |  |  |  |
359 |  |  |  |  | The C<Exception::Class> magic attempts to detect circular class
360 |  |  |  |  | hierarchies and will die if it finds one. It also detects missing
361 |  |  |  |  | links in a chain, for example if you declare Bar to be a subclass of
362 |  |  |  |  | Foo and never declare Foo.
363 |  |  |  |  |
364 |  |  |  |  | =head1 Catching Exceptions
365 |  |  |  |  |
366 |  |  |  |  | C<Exception::Class> provides some syntactic sugar for catching
367 |  |  |  |  | exceptions 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 |  |  |  |  |
376 |  |  |  |  | The C<caught()> method takes a class name and returns an exception
377 |  |  |  |  | object if the last thrown exception is of the given class, or a
378 |  |  |  |  | subclass of that class. If it is not given any arguments, it simply
379 |  |  |  |  | returns C<$@>.
380 |  |  |  |  |
381 |  |  |  |  | You should B<always> make a copy of the exception object, rather than
382 |  |  |  |  | using C<$@> directly. This is necessary because if your C<cleanup()>
383 |  |  |  |  | function uses C<eval>, or calls something which uses it, then C<$@> is
384 |  |  |  |  | overwritten. Copying the exception preserves it for the call to
385 |  |  |  |  | C<do_something_with_exception()>.
386 |  |  |  |  |
387 |  |  |  |  | Exception 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 |  |  |  |  |
396 |  |  |  |  | Internally, the C<caught()> method will call C<isa()> on the exception
397 |  |  |  |  | object. You could make an exception "uncatchable" by overriding
398 |  |  |  |  | C<isa()> in that class like this:
399 |  |  |  |  |
400 |  |  |  |  | package Exception::Uncatchable;
401 |  |  |  |  |
402 |  |  |  |  | sub isa { shift->rethrow }
403 |  |  |  |  |
404 |  |  |  |  | Of course, this only works if you always call
405 |  |  |  |  | C<< Exception::Class->caught() >> after an C<eval>.
406 |  |  |  |  |
407 |  |  |  |  | =head1 USAGE RECOMMENDATION
408 |  |  |  |  |
409 |  |  |  |  | If you're creating a complex system that throws lots of different
410 |  |  |  |  | types of exceptions, consider putting all the exception declarations
411 |  |  |  |  | in one place. For an app called Foo you might make a
412 |  |  |  |  | C<Foo::Exceptions> module and use that in all your code. This module
413 |  |  |  |  | could just contain the code to make C<Exception::Class> do its
414 |  |  |  |  | automagic class creation. Doing this allows you to more easily see
415 |  |  |  |  | what exceptions you have, and makes it easier to keep track of them.
416 |  |  |  |  |
417 |  |  |  |  | This 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 |  |  |  |  |
440 |  |  |  |  | You may want to create a real module to subclass
441 |  |  |  |  | L<Exception::Class::Base> as well, particularly if you want your
442 |  |  |  |  | exceptions to have more methods.
443 |  |  |  |  |
444 |  |  |  |  | =head2 Subclassing Exception::Class::Base
445 |  |  |  |  |
446 |  |  |  |  | As part of your usage of C<Exception::Class>, you may want to create
447 |  |  |  |  | your own base exception class which subclasses
448 |  |  |  |  | L<Exception::Class::Base>. You should feel free to subclass any of
449 |  |  |  |  | the methods documented above. For example, you may want to subclass
450 |  |  |  |  | C<new()> to add additional information to your exception objects.
451 |  |  |  |  |
452 |  |  |  |  | =head1 Exception::Class FUNCTIONS
453 |  |  |  |  |
454 |  |  |  |  | The C<Exception::Class> method offers one function, C<Classes()>,
455 |  |  |  |  | which is not exported. This method returns a list of the classes that
456 |  |  |  |  | have been created by calling the C<Exception::Class> import() method.
457 |  |  |  |  | Note that this is I<all> the subclasses that have been created, so it
458 |  |  |  |  | may include subclasses created by things like CPAN modules, etc. Also
459 |  |  |  |  | note that if you simply define a subclass via the normal Perl method
460 |  |  |  |  | of setting C<@ISA> or C<use base>, then your subclass will not be
461 |  |  |  |  | included.
462 |  |  |  |  |
463 |  |  |  |  | =head1 OTHER EXCEPTION MODULES (try/catch syntax)
464 |  |  |  |  |
465 |  |  |  |  | If you are interested in adding try/catch/finally syntactic sugar to
466 |  |  |  |  | your code then I recommend you check out U. Arun Kumar's C<Error.pm>
467 |  |  |  |  | module, which implements this syntax. It also includes its own base
468 |  |  |  |  | exception class, C<Error::Simple>.
469 |  |  |  |  |
470 |  |  |  |  | If you would prefer to use the L<Exception::Class::Base> class
471 |  |  |  |  | included with this module, you'll have to add this to your code
472 |  |  |  |  | somewhere:
473 |  |  |  |  |
474 |  |  |  |  | push @Exception::Class::Base::ISA, 'Error'
475 |  |  |  |  | unless Exception::Class::Base->isa('Error');
476 |  |  |  |  |
477 |  |  |  |  | It's a hack but apparently it works.
478 |  |  |  |  |
479 |  |  |  |  | =head1 SUPPORT
480 |  |  |  |  |
481 |  |  |  |  | Please submit bugs to the CPAN RT system at
482 |  |  |  |  | http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Exception%3A%3AClass or
483 |  |  |  |  | via email at bug-exception-class@rt.cpan.org.
484 |  |  |  |  |
485 |  |  |  |  | =head1 DONATIONS
486 |  |  |  |  |
487 |  |  |  |  | If you'd like to thank me for the work I've done on this module,
488 |  |  |  |  | please consider making a "donation" to me via PayPal. I spend a lot of
489 |  |  |  |  | free time creating free software, and would appreciate any support
490 |  |  |  |  | you'd care to offer.
491 |  |  |  |  |
492 |  |  |  |  | Please note that B<I am not suggesting that you must do this> in order
493 |  |  |  |  | for me to continue working on this particular software. I will
494 |  |  |  |  | continue to do so, inasmuch as I have in the past, for as long as it
495 |  |  |  |  | interests me.
496 |  |  |  |  |
497 |  |  |  |  | Similarly, a donation made in this way will probably not make me work
498 |  |  |  |  | on this software much more, unless I get so many donations that I can
499 |  |  |  |  | consider working on free software full time, which seems unlikely at
500 |  |  |  |  | best.
501 |  |  |  |  |
502 |  |  |  |  | To donate, log into PayPal and send money to autarch@urth.org or use
503 |  |  |  |  | the button on this page:
504 |  |  |  |  | L<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 |  |  |  |  |
512 |  |  |  |  | This software is Copyright (c) 2010 by Dave Rolsky.
513 |  |  |  |  |
514 |  |  |  |  | This 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