File Coverage

blib/lib/Async/Hooks/Ctl.pm
Criterion Covered Total %
statement 20 20 100.0
branch 4 4 100.0
condition 6 6 100.0
subroutine 7 7 100.0
pod 4 4 100.0
total 41 41 100.0


line stmt bran cond sub pod time code
1             package Async::Hooks::Ctl;
2             {
3             $Async::Hooks::Ctl::VERSION = '0.16';
4             }
5              
6             # ABSTRACT: Hook control object
7              
8 4     4   49230 use strict;
  4         9  
  4         144  
9 4     4   21 use warnings;
  4         7  
  4         1238  
10              
11             # $self is a arrayref with three positions:
12             # . first is a arrayref with hooks to call;
13             # . second is a arrayref with the arguments of each hook;
14             # . third is the cleanup sub: always called even when done().
15             #
16              
17 23   100 23 1 19926 sub new { return bless [undef, $_[1] || [], $_[2] || [], $_[3]], $_[0] }
      100        
18              
19 2     2 1 34 sub args { return $_[0][2] }
20              
21             # stop() or done() stops the chain
22             sub done {
23 7     7 1 417 my $ctl = $_[0];
24              
25 7         12 @{$ctl->[1]} = ();
  7         16  
26              
27 7         20 return $ctl->_cleanup(1);
28             }
29              
30             *stop = \&done;
31              
32              
33             # decline(), declined() or next() will call the next hook in the chain
34             sub decline {
35 48     48 1 11504 my $ctl = $_[0];
36              
37 48         81 my $hook = shift @{$ctl->[1]};
  48         134  
38 48 100       192 return $hook->($ctl, $ctl->[2]) if $hook;
39              
40 15         43 return $ctl->_cleanup(0);
41             }
42              
43             *declined = \&decline;
44             *next = \&declined;
45              
46              
47             # _cleanup ends the chain processing
48             sub _cleanup {
49 22     22   36 my ($ctl, $is_done) = @_;
50              
51 22 100       88 return unless my $cleanup = $ctl->[3];
52 11   100     63 return $cleanup->($ctl, $ctl->[2], $is_done || 0);
53             }
54              
55             1; # End of Async::Hooks::Ctl
56              
57              
58             __END__
59             =pod
60              
61             =head1 NAME
62              
63             Async::Hooks::Ctl - Hook control object
64              
65             =head1 VERSION
66              
67             version 0.16
68              
69             =head1 SYNOPSIS
70              
71             # inside a callback
72              
73             sub my_callback {
74             my $ctl = shift; # This is the Async::Hooks::Ctl object
75             my $args = shift; # Arguments for the hook
76              
77             $args = $ctl->args; # Args are also available with the args() method
78              
79             return $ctl->done; # no other callbacks are called
80             # ... or ...
81             return $ctl->decline; # call next callback
82             }
83              
84             =head1 DESCRIPTION
85              
86             A C<Async::Hooks::Ctl> object controls the sequence of invocation of
87             callbacks.
88              
89             Each callback receives two parameters: a C<Async::Hooks::Ctl> object,
90             and a arrayref with the hook arguments.
91              
92             Each callback must call one of the sequence control methods before
93             returning. Usually you just write:
94              
95             return $ctl->done();
96             # ... or ...
97             return $ctl->decline();
98              
99             If you know what you are doing, you can also do this:
100              
101             $ctl->decline();
102             # do other stuff here
103             return;
104              
105             But there are no guarantees that your code after the control method call
106             will be run at the end of the callback sequence.
107              
108             The important rule is that you must call one and only one of the control
109             methods per callback.
110              
111             The object provides two methods that control the invocation sequence,
112             C<decline()> and C<done()>. The C<done()> method will stop the sequence,
113             and no other callback will be called. The C<decline()> method will call
114             the next callback in the sequence.
115              
116             A cleanup callback can also be defined, and it will be called at the end
117             of all callbacks, or imediatly after C<done()>. This callback receives a
118             third argument, a flag C<$is_done>, that will be true if the chain
119             ended with a call to C<done()> or C<stop()>.
120              
121             The C<decline()> method can also be called as C<declined()> or
122             C<next()>. The C<done()> method can also be called as C<stop()>.
123              
124             =head1 METHODS
125              
126             =over
127              
128             =item CLASS->new($hooks, $args, $cleanup)
129              
130             The C<new()> constructor returns a C<Async::Hooks::Ctl> object. All
131             parameters are optional.
132              
133             =over
134              
135             =item * $hooks
136              
137             An arrayref with all the callbacks to call.
138              
139             =item * $args
140              
141             An arrayref with all the hook arguments.
142              
143             =item * $cleanup
144              
145             A coderef with the cleanup callback to use.
146              
147             =back
148              
149             =item $ctl->args()
150              
151             Returns the hook arguments.
152              
153             =item $ctl->decline()
154              
155             Calls the next callback in the hook sequence.
156              
157             If there are no callbacks remaining and if a cleanup callback was
158             defined, it will be called with the C<$is_done> flag as false.
159              
160             =item $ctl->declined()
161              
162             An alias to C<< $ctl->decline() >>.
163              
164             =item $ctl->next()
165              
166             An alias to C<< $ctl->decline() >>.
167              
168             =item $ctl->done()
169              
170             Stops the callback sequence. No other callbacks in the sequence will
171             be called.
172              
173             If a cleanup callback was defined, it will be called with the
174             C<$is_done> flag as true.
175              
176             =item $ctl->stop()
177              
178             An alias to C<< $ctl->done() >>.
179              
180             =back
181              
182             =head1 AUTHOR
183              
184             Pedro Melo <melo@cpan.org>
185              
186             =head1 COPYRIGHT AND LICENSE
187              
188             This software is Copyright (c) 2011 by Pedro Melo.
189              
190             This is free software, licensed under:
191              
192             The Artistic License 2.0 (GPL Compatible)
193              
194             =cut
195