ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Guard/README
Revision: 1.7
Committed: Sat Jul 2 00:38:44 2011 UTC (12 years, 10 months ago) by root
Branch: MAIN
CVS Tags: rel-1_023, rel-1_022, HEAD
Changes since 1.6: +8 -2 lines
Log Message:
1.022

File Contents

# Content
1 NAME
2 Guard - safe cleanup blocks
3
4 SYNOPSIS
5 use Guard;
6
7 # temporarily chdir to "/etc" directory, but make sure
8 # to go back to "/" no matter how myfun exits:
9 sub myfun {
10 scope_guard { chdir "/" };
11 chdir "/etc";
12
13 code_that_might_die_or_does_other_fun_stuff;
14 }
15
16 # create an object that, when the last reference to it is gone,
17 # invokes the given codeblock:
18 my $guard = guard { print "destroyed!\n" };
19 undef $guard; # probably destroyed here
20
21 DESCRIPTION
22 This module implements so-called "guards". A guard is something (usually
23 an object) that "guards" a resource, ensuring that it is cleaned up when
24 expected.
25
26 Specifically, this module supports two different types of guards: guard
27 objects, which execute a given code block when destroyed, and scoped
28 guards, which are tied to the scope exit.
29
30 FUNCTIONS
31 This module currently exports the "scope_guard" and "guard" functions by
32 default.
33
34 scope_guard BLOCK
35 scope_guard ($coderef)
36 Registers a block that is executed when the current scope (block,
37 function, method, eval etc.) is exited.
38
39 See the EXCEPTIONS section for an explanation of how exceptions
40 (i.e. "die") are handled inside guard blocks.
41
42 The description below sounds a bit complicated, but that's just
43 because "scope_guard" tries to get even corner cases "right": the
44 goal is to provide you with a rock solid clean up tool.
45
46 The behaviour is similar to this code fragment:
47
48 eval ... code following scope_guard ...
49 {
50 local $@;
51 eval BLOCK;
52 eval { $Guard::DIED->() } if $@;
53 }
54 die if $@;
55
56 Except it is much faster, and the whole thing gets executed even
57 when the BLOCK calls "exit", "goto", "last" or escapes via other
58 means.
59
60 If multiple BLOCKs are registered to the same scope, they will be
61 executed in reverse order. Other scope-related things such as
62 "local" are managed via the same mechanism, so variables "local"ised
63 *after* calling "scope_guard" will be restored when the guard runs.
64
65 Example: temporarily change the timezone for the current process,
66 ensuring it will be reset when the "if" scope is exited:
67
68 use Guard;
69 use POSIX ();
70
71 if ($need_to_switch_tz) {
72 # make sure we call tzset after $ENV{TZ} has been restored
73 scope_guard { POSIX::tzset };
74
75 # localise after the scope_guard, so it gets undone in time
76 local $ENV{TZ} = "Europe/London";
77 POSIX::tzset;
78
79 # do something with the new timezone
80 }
81
82 my $guard = guard BLOCK
83 my $guard = guard ($coderef)
84 Behaves the same as "scope_guard", except that instead of executing
85 the block on scope exit, it returns an object whose lifetime
86 determines when the BLOCK gets executed: when the last reference to
87 the object gets destroyed, the BLOCK gets executed as with
88 "scope_guard".
89
90 See the EXCEPTIONS section for an explanation of how exceptions
91 (i.e. "die") are handled inside guard blocks.
92
93 Example: acquire a Coro::Semaphore for a second by registering a
94 timer. The timer callback references the guard used to unlock it
95 again. (Please ignore the fact that "Coro::Semaphore" has a "guard"
96 method that does this already):
97
98 use Guard;
99 use Coro::AnyEvent;
100 use Coro::Semaphore;
101
102 my $sem = new Coro::Semaphore;
103
104 sub lock_for_a_second {
105 $sem->down;
106 my $guard = guard { $sem->up };
107
108 Coro::AnyEvent::sleep 1;
109
110 # $sem->up gets executed when returning
111 }
112
113 The advantage of doing this with a guard instead of simply calling
114 "$sem->down" in the callback is that you can opt not to create the
115 timer, or your code can throw an exception before it can create the
116 timer (or the thread gets canceled), or you can create multiple
117 timers or other event watchers and only when the last one gets
118 executed will the lock be unlocked. Using the "guard", you do not
119 have to worry about catching all the places where you have to unlock
120 the semaphore.
121
122 $guard->cancel
123 Calling this function will "disable" the guard object returned by
124 the "guard" function, i.e. it will free the BLOCK originally passed
125 to "guard "and will arrange for the BLOCK not to be executed.
126
127 This can be useful when you use "guard" to create a cleanup handler
128 to be called under fatal conditions and later decide it is no longer
129 needed.
130
131 EXCEPTIONS
132 Guard blocks should not normally throw exceptions (that is, "die").
133 After all, they are usually used to clean up after such exceptions.
134 However, if something truly exceptional is happening, a guard block
135 should of course be allowed to die. Also, programming errors are a large
136 source of exceptions, and the programmer certainly wants to know about
137 those.
138
139 Since in most cases, the block executing when the guard gets executed
140 does not know or does not care about the guard blocks, it makes little
141 sense to let containing code handle the exception.
142
143 Therefore, whenever a guard block throws an exception, it will be caught
144 by Guard, followed by calling the code reference stored in $Guard::DIED
145 (with $@ set to the actual exception), which is similar to how most
146 event loops handle this case.
147
148 The default for $Guard::DIED is to call "warn "$@"", i.e. the error is
149 printed as a warning and the program continues.
150
151 The $@ variable will be restored to its value before the guard call in
152 all cases, so guards will not disturb $@ in any way.
153
154 The code reference stored in $Guard::DIED should not die (behaviour is
155 not guaranteed, but right now, the exception will simply be ignored).
156
157 AUTHOR
158 Marc Lehmann <schmorp@schmorp.de>
159 http://home.schmorp.de/
160
161 THANKS
162 Thanks to Marco Maisenhelder, who reminded me of the $Guard::DIED
163 solution to the problem of exceptions.
164
165 SEE ALSO
166 Scope::Guard and Sub::ScopeFinalizer, which actually implement
167 dynamically scoped guards only, not the lexically scoped guards that
168 their documentation promises, and have a lot higher CPU, memory and
169 typing overhead.
170
171 Hook::Scope, which has apparently never been finished and can corrupt
172 memory when used.
173
174 Scope::Guard seems to have a big SEE ALSO section for even more modules
175 like it.
176