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

# User Rev Content
1 root 1.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