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