… | |
… | |
8 | # to go back to "/" no matter how myfun exits: |
8 | # to go back to "/" no matter how myfun exits: |
9 | sub myfun { |
9 | sub myfun { |
10 | scope_guard { chdir "/" }; |
10 | scope_guard { chdir "/" }; |
11 | chdir "/etc"; |
11 | chdir "/etc"; |
12 | |
12 | |
13 | call_function_that_might_die_or_other_fun_stuff; |
13 | code_that_might_die_or_does_other_fun_stuff; |
14 | } |
14 | } |
15 | |
15 | |
16 | DESCRIPTION |
16 | DESCRIPTION |
17 | This module implements so-called "guards". A guard is something (usually |
17 | This module implements so-called "guards". A guard is something (usually |
18 | 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 |
… | |
… | |
129 | After all, they are usually used to clean up after such exceptions. |
129 | After all, they are usually used to clean up after such exceptions. |
130 | However, if something truly exceptional is happening, a guard block |
130 | However, if something truly exceptional is happening, a guard block |
131 | should be 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 |
132 | exceptions, and the programmer certainly wants to know about those. |
132 | exceptions, and the programmer certainly wants to know about those. |
133 | |
133 | |
134 | Since in most cases, the block executing when the guard gets executes |
134 | Since in most cases, the block executing when the guard gets executed |
135 | 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 |
136 | sense to let containing code handle the exception. |
136 | sense to let containing code handle the exception. |
137 | |
137 | |
138 | Therefore, whenever a guard block throws an exception, it will be |
138 | Therefore, whenever a guard block throws an exception, it will be |
139 | caught, and this module will call the code reference stored in |
139 | caught, followed by calling the code reference stored in $Guard::DIED |
140 | $Guard::DIED (with $@ set to the actual exception), which is similar to |
140 | (with $@ set to the actual exception), which is similar to how most |
141 | how most event loops handle this case. |
141 | event loops handle this case. |
142 | |
142 | |
143 | The default for $Guard::DIED is to call "warn "$@"". |
143 | The default for $Guard::DIED is to call "warn "$@"". |
144 | |
144 | |
145 | The $@ variable will be restored to its value before the guard call in |
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. |
146 | all cases, so guards will not disturb $@ in any way. |
… | |
… | |
154 | |
154 | |
155 | THANKS |
155 | THANKS |
156 | Thanks to Marco Maisenhelder, who reminded me of the $Guard::DIED |
156 | Thanks to Marco Maisenhelder, who reminded me of the $Guard::DIED |
157 | solution to the problem of exceptions. |
157 | solution to the problem of exceptions. |
158 | |
158 | |
|
|
159 | SEE ALSO |
|
|
160 | Scope::Guard and Sub::ScopeFinalizer, which actually implement dynamic, |
|
|
161 | not scoped guards, and have a lot higher CPU, memory and typing |
|
|
162 | overhead. |
|
|
163 | |
|
|
164 | Hook::Scope, which has apparently never been finished and corrupts |
|
|
165 | memory when used. |
|
|
166 | |