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