ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Guard/Guard.pm
Revision: 1.1
Committed: Sat Dec 13 17:37:22 2008 UTC (15 years, 5 months ago) by root
Branch: MAIN
Log Message:
initial check-in

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