File | /usr/local/lib/perl5/site_perl/5.10.1/Exception/Class.pm |
Statements Executed | 137 |
Statement Execution Time | 1.96ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 2.13ms | 16.5ms | BEGIN@7 | Exception::Class::
3 | 2 | 1 | 502µs | 708µs | _make_subclass | Exception::Class::
1 | 1 | 1 | 68µs | 807µs | import | Exception::Class::
1 | 1 | 1 | 26µs | 26µs | BEGIN@3 | Exception::Class::
1 | 1 | 1 | 18µs | 309µs | _make_parents | Exception::Class::
1 | 1 | 1 | 15µs | 30µs | BEGIN@168 | Exception::Class::
1 | 1 | 1 | 14µs | 57µs | BEGIN@8 | Exception::Class::
1 | 1 | 2 | 13µs | 13µs | CORE:sort (opcode) | Exception::Class::
1 | 1 | 1 | 11µs | 28µs | BEGIN@45 | Exception::Class::
1 | 1 | 1 | 11µs | 26µs | BEGIN@78 | Exception::Class::
1 | 1 | 1 | 7µs | 9µs | BEGIN@5 | Exception::Class::
1 | 1 | 1 | 6µs | 6µs | BEGIN@11 | Exception::Class::
3 | 1 | 2 | 4µs | 4µs | CORE:subst (opcode) | Exception::Class::
0 | 0 | 0 | 0s | 0s | Classes | Exception::Class::
0 | 0 | 0 | 0s | 0s | __ANON__[:169] | Exception::Class::
0 | 0 | 0 | 0s | 0s | caught | Exception::Class::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package Exception::Class; | ||||
2 | |||||
3 | 3 | 37µs | 1 | 26µ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 # spent 26µs making 1 call to Exception::Class::BEGIN@3 |
4 | |||||
5 | 3 | 25µs | 2 | 12µ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 # spent 9µs making 1 call to Exception::Class::BEGIN@5
# spent 2µs making 1 call to strict::import |
6 | |||||
7 | 3 | 152µs | 1 | 16.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 # spent 16.5ms making 1 call to Exception::Class::BEGIN@7 |
8 | 3 | 57µs | 2 | 99µ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 # spent 57µs making 1 call to Exception::Class::BEGIN@8
# spent 43µs making 1 call to Exporter::import |
9 | |||||
10 | 1 | 100ns | our $BASE_EXC_CLASS; | ||
11 | 1 | 187µs | 1 | 6µ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 # spent 6µs making 1 call to Exception::Class::BEGIN@11 |
12 | |||||
13 | 1 | 800ns | our $VERSION = '1.29'; | ||
14 | |||||
15 | 1 | 300ns | our %CLASSES; | ||
16 | |||||
17 | sub 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 | ||||
19 | 1 | 700ns | my $class = shift; | ||
20 | |||||
21 | 1 | 900ns | local $Exception::Class::Caller = caller(); | ||
22 | |||||
23 | 1 | 200ns | my %c; | ||
24 | |||||
25 | 1 | 100ns | my %needs_parent; | ||
26 | 1 | 3µs | while (my $subclass = shift) | ||
27 | { | ||||
28 | 3 | 2µs | my $def = ref $_[0] ? shift : {}; | ||
29 | 3 | 4µs | $def->{isa} = $def->{isa} ? ( ref $def->{isa} ? $def->{isa} : [$def->{isa}] ) : []; | ||
30 | |||||
31 | 3 | 3µs | $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 | 1 | 25µs | 1 | 13µs | foreach my $subclass ( sort { length $a <=> length $b } keys %c ) # spent 13µs making 1 call to Exception::Class::CORE:sort |
38 | { | ||||
39 | 3 | 1µs | my $def = $c{$subclass}; | ||
40 | |||||
41 | # We already made this one. | ||||
42 | 3 | 900ns | next if $CLASSES{$subclass}; | ||
43 | |||||
44 | { | ||||
45 | 6 | 213µs | 2 | 45µ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 # spent 28µs making 1 call to Exception::Class::BEGIN@45
# spent 17µs making 1 call to strict::unimport |
46 | 3 | 3µs | foreach my $parent (@{ $def->{isa} }) | ||
47 | { | ||||
48 | 2 | 6µs | unless ( keys %{"$parent\::"} ) | ||
49 | { | ||||
50 | 1 | 2µs | $needs_parent{$subclass} = { parents => $def->{isa}, | ||
51 | def => $def }; | ||||
52 | 1 | 800ns | next MAKE_CLASSES; | ||
53 | } | ||||
54 | } | ||||
55 | } | ||||
56 | |||||
57 | 2 | 6µs | 2 | 417µs | $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 | 1 | 7µs | foreach my $subclass (keys %needs_parent) | ||
63 | { | ||||
64 | # This will be used to spot circular references. | ||||
65 | 1 | 200ns | my %seen; | ||
66 | 1 | 4µs | 1 | 309µs | $class->_make_parents( \%needs_parent, $subclass, \%seen ); # spent 309µs making 1 call to Exception::Class::_make_parents |
67 | } | ||||
68 | } | ||||
69 | |||||
70 | sub _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 | ||||
72 | 1 | 600ns | my $class = shift; | ||
73 | 1 | 200ns | my $needs = shift; | ||
74 | 1 | 200ns | my $subclass = shift; | ||
75 | 1 | 100ns | my $seen = shift; | ||
76 | 1 | 200ns | my $child = shift; # Just for error messages. | ||
77 | |||||
78 | 3 | 466µs | 2 | 42µ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 # 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 | 1 | 600ns | unless exists $needs->{$subclass} || $CLASSES{$subclass} || keys %{"$subclass\::"}; | ||
88 | |||||
89 | 1 | 2µs | foreach my $c ( @{ $needs->{$subclass}{parents} } ) | ||
90 | { | ||||
91 | # It's been made | ||||
92 | 1 | 700ns | 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 | 1 | 4µs | return if $CLASSES{$subclass} || keys %{"$subclass\::"}; | ||
103 | |||||
104 | 1 | 6µs | 1 | 291µs | $class->_make_subclass( subclass => $subclass, # spent 291µs making 1 call to Exception::Class::_make_subclass |
105 | def => $needs->{$subclass}{def} ); | ||||
106 | } | ||||
107 | |||||
108 | sub _make_subclass | ||||
109 | { | ||||
110 | 3 | 1µs | my $class = shift; | ||
111 | 3 | 4µs | my %p = @_; | ||
112 | |||||
113 | 3 | 1µs | my $subclass = $p{subclass}; | ||
114 | 3 | 700ns | my $def = $p{def}; | ||
115 | |||||
116 | 3 | 300ns | my $isa; | ||
117 | 3 | 6µs | if ($def->{isa}) | ||
118 | { | ||||
119 | $isa = ref $def->{isa} ? join ' ', @{ $def->{isa} } : $def->{isa}; | ||||
120 | } | ||||
121 | 3 | 700ns | $isa ||= $BASE_EXC_CLASS; | ||
122 | |||||
123 | 3 | 700ns | my $version_name = 'VERSION'; | ||
124 | |||||
125 | 3 | 6µs | my $code = <<"EOPERL"; | ||
126 | package $subclass; | ||||
127 | |||||
128 | use base qw($isa); | ||||
129 | |||||
130 | our \$$version_name = '1.1'; | ||||
131 | |||||
132 | 1; | ||||
133 | |||||
134 | EOPERL | ||||
135 | |||||
136 | |||||
137 | 3 | 2µs | if ($def->{description}) | ||
138 | { | ||||
139 | 3 | 16µs | 3 | 4µs | (my $desc = $def->{description}) =~ s/([\\\'])/\\$1/g; # spent 4µs making 3 calls to Exception::Class::CORE:subst, avg 1µs/call |
140 | 3 | 5µs | $code .= <<"EOPERL"; | ||
141 | sub description | ||||
142 | { | ||||
143 | return '$desc'; | ||||
144 | } | ||||
145 | EOPERL | ||||
146 | } | ||||
147 | |||||
148 | 3 | 500ns | my @fields; | ||
149 | 3 | 2µs | if ( my $fields = $def->{fields} ) | ||
150 | { | ||||
151 | 2 | 12µs | 2 | 2µs | @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 | 2 | 11µs | join(", ", map { "'$_'" } @fields) . ") }\n\n"; | ||
156 | |||||
157 | 2 | 1µs | foreach my $field (@fields) | ||
158 | { | ||||
159 | 5 | 8µs | $code .= sprintf("sub %s { \$_[0]->{%s} }\n", $field, $field); | ||
160 | } | ||||
161 | } | ||||
162 | |||||
163 | 3 | 1µs | if ( my $alias = $def->{alias} ) | ||
164 | { | ||||
165 | die "Cannot make alias without caller" | ||||
166 | unless defined $Exception::Class::Caller; | ||||
167 | |||||
168 | 3 | 202µs | 2 | 44µ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 # 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 | |||||
172 | 3 | 435µs | 6 | 364µ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 | 3 | 400ns | die $@ if $@; | ||
175 | |||||
176 | 3 | 20µs | $CLASSES{$subclass} = 1; | ||
177 | } | ||||
178 | |||||
179 | sub 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 | |||||
189 | sub Classes { sort keys %Exception::Class::CLASSES } | ||||
190 | |||||
191 | 1 | 5µs | 1; | ||
192 | |||||
193 | __END__ | ||||
194 | |||||
195 | =head1 NAME | ||||
196 | |||||
197 | Exception::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 | |||||
246 | Exception::Class allows you to declare exception hierarchies in your | ||||
247 | modules in a "Java-esque" manner. | ||||
248 | |||||
249 | It features a simple interface allowing programmers to 'declare' | ||||
250 | exception classes at compile time. It also has a base exception | ||||
251 | class, L<Exception::Class::Base>, that can be easily extended. | ||||
252 | |||||
253 | It is designed to make structured exception handling simpler and | ||||
254 | better by encouraging people to use hierarchies of exceptions in their | ||||
255 | applications, as opposed to a single catch-all exception class. | ||||
256 | |||||
257 | This module does not implement any try/catch syntax. Please see the | ||||
258 | "OTHER EXCEPTION MODULES (try/catch syntax)" section for more | ||||
259 | information on how to get this syntax. | ||||
260 | |||||
261 | You will also want to look at the documentation for | ||||
262 | L<Exception::Class::Base>, which is the default base class for all | ||||
263 | exception objects created by this module. | ||||
264 | |||||
265 | =head1 DECLARING EXCEPTION CLASSES | ||||
266 | |||||
267 | Importing C<Exception::Class> allows you to automagically create | ||||
268 | L<Exception::Class::Base> subclasses. You can also create subclasses | ||||
269 | via the traditional means of defining your own subclass with C<@ISA>. | ||||
270 | These two methods may be easily combined, so that you could subclass | ||||
271 | an exception class defined via the automagic import, if you desired | ||||
272 | this. | ||||
273 | |||||
274 | The syntax for the magic declarations is as follows: | ||||
275 | |||||
276 | 'MANDATORY CLASS NAME' => \%optional_hashref | ||||
277 | |||||
278 | The hashref may contain the following options: | ||||
279 | |||||
280 | =over 4 | ||||
281 | |||||
282 | =item * isa | ||||
283 | |||||
284 | This is the class's parent class. If this isn't provided then the | ||||
285 | class name in C<$Exception::Class::BASE_EXC_CLASS> is assumed to be | ||||
286 | the parent (see below). | ||||
287 | |||||
288 | This parameter lets you create arbitrarily deep class hierarchies. | ||||
289 | This can be any other L<Exception::Class::Base> subclass in your | ||||
290 | declaration I<or> a subclass loaded from a module. | ||||
291 | |||||
292 | To change the default exception class you will need to change the | ||||
293 | value of C<$Exception::Class::BASE_EXC_CLASS> I<before> calling | ||||
294 | C<import()>. To do this simply do something like this: | ||||
295 | |||||
296 | BEGIN { $Exception::Class::BASE_EXC_CLASS = 'SomeExceptionClass'; } | ||||
297 | |||||
298 | If anyone can come up with a more elegant way to do this please let me | ||||
299 | know. | ||||
300 | |||||
301 | CAVEAT: If you want to automagically subclass an | ||||
302 | L<Exception::Class::Base> subclass loaded from a file, then you | ||||
303 | I<must> compile the class (via use or require or some other magic) | ||||
304 | I<before> you import C<Exception::Class> or you'll get a compile time | ||||
305 | error. | ||||
306 | |||||
307 | =item * fields | ||||
308 | |||||
309 | This allows you to define additional attributes for your exception | ||||
310 | class. Any field you define can be passed to the C<throw()> or | ||||
311 | C<new()> methods as additional parameters for the constructor. In | ||||
312 | addition, your exception object will have an accessor method for the | ||||
313 | fields you define. | ||||
314 | |||||
315 | This parameter can be either a scalar (for a single field) or an array | ||||
316 | reference if you need to define multiple fields. | ||||
317 | |||||
318 | Fields will be inherited by subclasses. | ||||
319 | |||||
320 | =item * alias | ||||
321 | |||||
322 | Specifying an alias causes this class to create a subroutine of the | ||||
323 | specified name in the I<caller's> namespace. Calling this subroutine | ||||
324 | is equivalent to calling C<< <class>->throw(@_) >> for the given | ||||
325 | exception class. | ||||
326 | |||||
327 | Besides convenience, using aliases also allows for additional compile | ||||
328 | time checking. If the alias is called I<without parentheses>, as in | ||||
329 | C<throw_fields "an error occurred">, then Perl checks for the | ||||
330 | existence of the C<throw_fields()> subroutine at compile time. If | ||||
331 | instead you do C<< ExceptionWithFields->throw(...) >>, then Perl | ||||
332 | checks the class name at runtime, meaning that typos may sneak | ||||
333 | through. | ||||
334 | |||||
335 | =item * description | ||||
336 | |||||
337 | Each exception class has a description method that returns a fixed | ||||
338 | string. This should describe the exception I<class> (as opposed to | ||||
339 | any particular exception object). This may be useful for debugging if | ||||
340 | you start catching exceptions you weren't expecting (particularly if | ||||
341 | someone forgot to document them) and you don't understand the error | ||||
342 | messages. | ||||
343 | |||||
344 | =back | ||||
345 | |||||
346 | The C<Exception::Class> magic attempts to detect circular class | ||||
347 | hierarchies and will die if it finds one. It also detects missing | ||||
348 | links in a chain, for example if you declare Bar to be a subclass of | ||||
349 | Foo and never declare Foo. | ||||
350 | |||||
351 | =head1 Catching Exceptions | ||||
352 | |||||
353 | C<Exception::Class> provides some syntactic sugar for catching | ||||
354 | exceptions 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 | |||||
364 | The C<caught()> method takes a class name and returns an exception | ||||
365 | object if the last thrown exception is of the given class, or a | ||||
366 | subclass of that class. If it is not given any arguments, it simply | ||||
367 | returns C<$@>. | ||||
368 | |||||
369 | You should B<always> make a copy of the exception object, rather than | ||||
370 | using C<$@> directly. This is necessary because if your C<cleanup()> | ||||
371 | function uses C<eval>, or calls something which uses it, then C<$@> is | ||||
372 | overwritten. Copying the exception preserves it for the call to | ||||
373 | C<do_something_with_exception()>. | ||||
374 | |||||
375 | Exception 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 | |||||
385 | Internally, the C<caught()> method will call C<isa()> on the exception | ||||
386 | object. You could make an exception "uncatchable" by overriding | ||||
387 | C<isa()> in that class like this: | ||||
388 | |||||
389 | package Exception::Uncatchable; | ||||
390 | |||||
391 | sub isa { shift->rethrow } | ||||
392 | |||||
393 | Of course, this only works if you always call | ||||
394 | C<< Exception::Class->caught() >> after an C<eval>. | ||||
395 | |||||
396 | =head1 USAGE RECOMMENDATION | ||||
397 | |||||
398 | If you're creating a complex system that throws lots of different | ||||
399 | types of exceptions, consider putting all the exception declarations | ||||
400 | in one place. For an app called Foo you might make a | ||||
401 | C<Foo::Exceptions> module and use that in all your code. This module | ||||
402 | could just contain the code to make C<Exception::Class> do its | ||||
403 | automagic class creation. Doing this allows you to more easily see | ||||
404 | what exceptions you have, and makes it easier to keep track of them. | ||||
405 | |||||
406 | This 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 | |||||
425 | You may want to create a real module to subclass | ||||
426 | L<Exception::Class::Base> as well, particularly if you want your | ||||
427 | exceptions to have more methods. | ||||
428 | |||||
429 | =head2 Subclassing Exception::Class::Base | ||||
430 | |||||
431 | As part of your usage of C<Exception::Class>, you may want to create | ||||
432 | your own base exception class which subclasses | ||||
433 | L<Exception::Class::Base>. You should feel free to subclass any of | ||||
434 | the methods documented above. For example, you may want to subclass | ||||
435 | C<new()> to add additional information to your exception objects. | ||||
436 | |||||
437 | =head1 Exception::Class FUNCTIONS | ||||
438 | |||||
439 | The C<Exception::Class> method offers one function, C<Classes()>, | ||||
440 | which is not exported. This method returns a list of the classes that | ||||
441 | have been created by calling the C<Exception::Class> import() method. | ||||
442 | Note that this is I<all> the subclasses that have been created, so it | ||||
443 | may include subclasses created by things like CPAN modules, etc. Also | ||||
444 | note that if you simply define a subclass via the normal Perl method | ||||
445 | of setting C<@ISA> or C<use base>, then your subclass will not be | ||||
446 | included. | ||||
447 | |||||
448 | =head1 OTHER EXCEPTION MODULES (try/catch syntax) | ||||
449 | |||||
450 | If you are interested in adding try/catch/finally syntactic sugar to | ||||
451 | your code then I recommend you check out U. Arun Kumar's C<Error.pm> | ||||
452 | module, which implements this syntax. It also includes its own base | ||||
453 | exception class, C<Error::Simple>. | ||||
454 | |||||
455 | If you would prefer to use the L<Exception::Class::Base> class | ||||
456 | included with this module, you'll have to add this to your code | ||||
457 | somewhere: | ||||
458 | |||||
459 | push @Exception::Class::Base::ISA, 'Error' | ||||
460 | unless Exception::Class::Base->isa('Error'); | ||||
461 | |||||
462 | It's a hack but apparently it works. | ||||
463 | |||||
464 | =head1 SUPPORT | ||||
465 | |||||
466 | Please submit bugs to the CPAN RT system at | ||||
467 | http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Exception%3A%3AClass or | ||||
468 | via email at bug-exception-class@rt.cpan.org. | ||||
469 | |||||
470 | =head1 DONATIONS | ||||
471 | |||||
472 | If you'd like to thank me for the work I've done on this module, | ||||
473 | please consider making a "donation" to me via PayPal. I spend a lot of | ||||
474 | free time creating free software, and would appreciate any support | ||||
475 | you'd care to offer. | ||||
476 | |||||
477 | Please note that B<I am not suggesting that you must do this> in order | ||||
478 | for me to continue working on this particular software. I will | ||||
479 | continue to do so, inasmuch as I have in the past, for as long as it | ||||
480 | interests me. | ||||
481 | |||||
482 | Similarly, a donation made in this way will probably not make me work | ||||
483 | on this software much more, unless I get so many donations that I can | ||||
484 | consider working on free software full time, which seems unlikely at | ||||
485 | best. | ||||
486 | |||||
487 | To donate, log into PayPal and send money to autarch@urth.org or use | ||||
488 | the button on this page: | ||||
489 | L<http://www.urth.org/~autarch/fs-donation.html> | ||||
490 | |||||
491 | =head1 AUTHOR | ||||
492 | |||||
493 | Dave Rolsky, E<gt>autarch@urth.orgE<lt> | ||||
494 | |||||
495 | =head1 COPYRIGHT | ||||
496 | |||||
497 | Copyright (c) 2000-2009 David Rolsky. All rights reserved. This | ||||
498 | program is free software; you can redistribute it and/or modify it | ||||
499 | under the same terms as Perl itself. | ||||
500 | |||||
501 | The full text of the license can be found in the LICENSE file included | ||||
502 | with 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 | |||||
# 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 |