ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Guard/Guard.pm
Revision: 1.2
Committed: Sat Dec 13 17:49:12 2008 UTC (15 years, 5 months ago) by root
Branch: MAIN
Changes since 1.1: +10 -0 lines
Log Message:
fixes

File Contents

# Content
1 =head1 NAME
2
3 Guard - safe cleanup blocks
4
5 =head1 SYNOPSIS
6
7 use Guard;
8
9 =head1 DESCRIPTION
10
11 This module implements so-called "guards". A guard is something (usually
12 an object) that "guards" a resource, ensuring that it is cleaned up when
13 expected.
14
15 Specifically, this module supports two different types of guards: guard
16 objects, which execute a given code block when destroyed, and scoped
17 guards, which are tied to the scope exit.
18
19 =head1 FUNCTIONS
20
21 This module currently exports the C<scope_guard> and C<guard> functions by
22 default.
23
24 =over 4
25
26 =cut
27
28 package Guard;
29
30 BEGIN {
31 $VERSION = '0.01';
32 @ISA = qw(Exporter);
33 @EXPORT = qw(guard scope_guard cancel);
34
35 require Exporter;
36
37 require XSLoader;
38 XSLoader::load Guard, $VERSION;
39 }
40
41 our $DIED = sub { warn "$@" };
42
43 =item scope_guard BLOCK
44
45 Registers a block that is executed when the current scope (block,
46 function, method, eval etc.) is exited.
47
48 The description below sounds a bit complicated, but that's just because
49 C<scope_guard> tries to get even corner cases "right": the goal is to
50 provide you with a rock solid clean up tool.
51
52 This is similar to this code fragment:
53
54 eval ... code following scope_guard ...
55 {
56 local $@;
57 eval BLOCK;
58 eval { $Guard::DIED->() } if $@;
59 }
60 die if $@;
61
62 Except it is much faster, and the whole thing gets executed even when the
63 BLOCK calls C<exit>, C<goto>, C<last> or escapes via other means.
64
65 See B<EXCEPTIONS>, below, for an explanation of exception handling
66 (C<die>) within guard blocks.
67
68 Example: Temporarily change the directory to F</etc> and make sure it's
69 set back to F</> when the function returns:
70
71 sub dosomething {
72 scope_guard { chdir "/" };
73 chdir "/etc";
74
75 ...
76 }
77
78 =item my $guard = guard BLOCK
79
80 Behaves the same as C<scope_guard>, except that instead of executing
81 the block on scope exit, it returns an object whose lifetime determines
82 when the BLOCK gets executed: when the last reference to the object gets
83 destroyed, the BLOCK gets executed as with C<scope_guard>.
84
85 The returned object can be copied as many times as you want.
86
87 See B<EXCEPTIONS>, below, for an explanation of exception handling
88 (C<die>) within guard blocks.
89
90 Example: acquire a Coro::Semaphore for a second by registering a
91 timer. The timer callback references the guard used to unlock it again.
92
93 use AnyEvent;
94 use Coro::Semaphore;
95
96 my $sem = new Coro::Semaphore;
97
98 sub lock_1s {
99 $sem->down;
100 my $guard = guard { $sem->up };
101
102 my $timer;
103 $timer = AnyEvent->timer (after => 1, sub {
104 # do something
105 undef $sem;
106 undef $timer;
107 });
108 }
109
110 The advantage of doing this with a guard instead of simply calling C<<
111 $sem->down >> in the callback is that you can opt not to create the timer,
112 or your code can throw an exception before it can create the timer, or you
113 can create multiple timers or other event watchers and only when the last
114 one gets executed will the lock be unlocked.
115
116 =item Guard::cancel $guard
117
118 Calling this function will "disable" the guard object returned by the
119 C<guard> function, i.e. it will free the BLOCK originally passed to
120 C<guard >and will arrange for the BLOCK not to be executed.
121
122 This can be useful when you use C<guard> to create a fatal cleanup handler
123 and later decide it is no longer needed.
124
125 =cut
126
127 1;
128
129 =back
130
131 =head1 EXCEPTIONS
132
133 Guard blocks should not normally throw exceptions (e.g. C<die>), after
134 all, they are usually used to clean up after such exceptions. However, if
135 something truly exceptional is happening, a guard block should be allowed
136 to die. Also, programming errors are a large source of exceptions, and the
137 programmer certainly wants to know about those.
138
139 Since in most cases, the block executing when the guard gets executes does
140 not know or does not care about the guard blocks, it makes little sense to
141 let containing code handle the exception.
142
143 Therefore, whenever a guard block throws an exception, it will be caught,
144 and this module will call the code reference stored in C<$Guard::DIED>
145 (with C<$@> set to the actual exception), which is similar to how most
146 event loops handle this case.
147
148 The code reference stored in C<$Guard::DIED> should not die (behaviour is
149 not guaranteed, but right now, the exception will simply be ignored).
150
151 The default for C<$Guard::DIED> is to call C<warn "$@">.
152
153 =head1 AUTHOR
154
155 Marc Lehmann <schmorp@schmorp.de>
156 http://home.schmorp.de/
157
158 =head1 THANKS
159
160 To Marco Maisenhelder, who reminded me of the C<$Guard::DIED> solution to
161 the problem of exceptions.
162
163 =cut
164