ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Guard/Guard.pm
(Generate patch)

Comparing Guard/Guard.pm (file contents):
Revision 1.1 by root, Sat Dec 13 17:37:22 2008 UTC vs.
Revision 1.4 by root, Sat Dec 13 18:34:18 2008 UTC

3Guard - safe cleanup blocks 3Guard - safe cleanup blocks
4 4
5=head1 SYNOPSIS 5=head1 SYNOPSIS
6 6
7 use Guard; 7 use Guard;
8
9 # temporarily chdir to "/etc" directory, but make sure
10 # to go back to "/" no matter how myfun exits:
11 sub dosomething {
12 scope_guard { chdir "/" };
13 chdir "/etc";
14
15 call_function_that_might_die_or_other_fun_stuff;
16 }
8 17
9=head1 DESCRIPTION 18=head1 DESCRIPTION
10 19
11This module implements so-called "guards". A guard is something (usually 20This module implements so-called "guards". A guard is something (usually
12an object) that "guards" a resource, ensuring that it is cleaned up when 21an object) that "guards" a resource, ensuring that it is cleaned up when
14 23
15Specifically, this module supports two different types of guards: guard 24Specifically, this module supports two different types of guards: guard
16objects, which execute a given code block when destroyed, and scoped 25objects, which execute a given code block when destroyed, and scoped
17guards, which are tied to the scope exit. 26guards, which are tied to the scope exit.
18 27
28=head1 FUNCTIONS
29
30This module currently exports the C<scope_guard> and C<guard> functions by
31default.
32
19=over 4 33=over 4
20 34
21=cut 35=cut
22 36
23package Guard; 37package Guard;
24 38
25BEGIN { 39BEGIN {
26 $VERSION = '0.01'; 40 $VERSION = '0.1';
27 @ISA = qw(Exporter); 41 @ISA = qw(Exporter);
28 @EXPORT = qw(guard scope_guard cancel); 42 @EXPORT = qw(guard scope_guard);
29 43
30 require Exporter; 44 require Exporter;
31 45
32 require XSLoader; 46 require XSLoader;
33 XSLoader::load Guard, $VERSION; 47 XSLoader::load Guard, $VERSION;
38=item scope_guard BLOCK 52=item scope_guard BLOCK
39 53
40Registers a block that is executed when the current scope (block, 54Registers a block that is executed when the current scope (block,
41function, method, eval etc.) is exited. 55function, method, eval etc.) is exited.
42 56
57The description below sounds a bit complicated, but that's just because
58C<scope_guard> tries to get even corner cases "right": the goal is to
59provide you with a rock solid clean up tool.
60
43This is similar to this code fragment: 61This is similar to this code fragment:
44 62
45 eval ... code following scope_guard ... 63 eval ... code following scope_guard ...
46 { 64 {
47 local $@; 65 local $@;
48 eval BLOCK; 66 eval BLOCK;
49 eval { $Guard::DIED->() } if $@; 67 eval { $Guard::DIED->() } if $@;
50 } 68 }
69 die if $@;
51 70
52Except it is much faster, and the whole thing gets executed even when the 71Except it is much faster, and the whole thing gets executed even when the
53BLOCK calls C<exit>, C<goto>, C<last> or escapes via other means. 72BLOCK calls C<exit>, C<goto>, C<last> or escapes via other means.
54 73
74If multiple BLOCKs are registered to the same scope, they will be executed
75in reverse order. Stuff like C<local> is managed via the same mechanism,
76so variables C<local>ised after calling C<scope_guard> will be restored
77when the guard runs.
78
55See B<EXCEPTIONS>, below, for an explanation of exception handling 79See B<EXCEPTIONS>, below, for an explanation of exception handling
56(C<die>) within guard blocks. 80(C<die>) within guard blocks.
57 81
58Example: Temporarily change the directory to F</etc> and make sure it's 82Example: temporarily change the timezone for the current process,
59set back to F</> when the function returns: 83ensuring it will be reset when the C<if> scope is exited:
60 84
61 sub dosomething { 85 use Guard;
62 scope_guard { chdir "/" }; 86 use POSIX ();
63 chdir "/etc";
64 87
65 ... 88 if ($need_to_switch_tz) {
89 # make sure we call tzset after $ENV{TZ} has been restored
90 scope_guard { POSIX::tzset };
91
92 # localise after the scope_guard, so it gets undone in time
93 local $ENV{TZ} = "Europe/London";
94 POSIX::tzset;
95
96 # do something with the new timezone
66 } 97 }
67 98
68=item my $guard = guard BLOCK 99=item my $guard = guard BLOCK
69 100
70Behaves the same as C<scope_guard>, except that instead of executing 101Behaves the same as C<scope_guard>, except that instead of executing

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines