| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package AnyEvent::CallbackStack; | 
| 2 |  |  |  |  |  |  |  | 
| 3 |  |  |  |  |  |  |  | 
| 4 |  |  |  |  |  |  | our $VERSION = '0.11'; | 
| 5 |  |  |  |  |  |  |  | 
| 6 | 3 |  |  | 3 |  | 43174 | use utf8; | 
|  | 3 |  |  |  |  | 24 |  | 
|  | 3 |  |  |  |  | 12 |  | 
| 7 | 3 |  |  | 3 |  | 81 | use feature 'say'; | 
|  | 3 |  |  |  |  | 5 |  | 
|  | 3 |  |  |  |  | 253 |  | 
| 8 | 3 |  |  | 3 |  | 1253 | use common::sense; | 
|  | 3 |  |  |  |  | 23 |  | 
|  | 3 |  |  |  |  | 11 |  | 
| 9 | 3 |  |  | 3 |  | 1808 | use Data::Dumper::Simple; | 
|  | 3 |  |  |  |  | 81206 |  | 
|  | 3 |  |  |  |  | 14 |  | 
| 10 |  |  |  |  |  |  |  | 
| 11 | 3 |  |  | 3 |  | 212232 | use AnyEvent; | 
|  | 3 |  |  |  |  | 12605 |  | 
|  | 3 |  |  |  |  | 111 |  | 
| 12 | 3 |  |  | 3 |  | 19 | use constant DEBUG => $ENV{ANYEVENT_CALLBACKSTACK_DEBUG}; | 
|  | 3 |  |  |  |  | 3 |  | 
|  | 3 |  |  |  |  | 1897 |  | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  |  | 
| 15 |  |  |  |  |  |  | =encoding utf8 | 
| 16 |  |  |  |  |  |  |  | 
| 17 |  |  |  |  |  |  | =head1 NAME | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  | AnyEvent::CallbackStack - Turning endless nested Event-Based Callbacks into plain Sequential Style. And save your indents. | 
| 20 |  |  |  |  |  |  |  | 
| 21 |  |  |  |  |  |  | Convert nested callback into easy-to-read-write-and-maintain serial/procedural coding style by using Callback Stack. | 
| 22 |  |  |  |  |  |  |  | 
| 23 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 24 |  |  |  |  |  |  |  | 
| 25 |  |  |  |  |  |  | Use L with the following style. | 
| 26 |  |  |  |  |  |  |  | 
| 27 |  |  |  |  |  |  | use feature 'say'; | 
| 28 |  |  |  |  |  |  | use AnyEvent::CallbackStack; | 
| 29 |  |  |  |  |  |  |  | 
| 30 |  |  |  |  |  |  | my $cs = AnyEvent::CallbackStack->new(); | 
| 31 |  |  |  |  |  |  | $cs->start( %foo ); | 
| 32 |  |  |  |  |  |  |  | 
| 33 |  |  |  |  |  |  | $cs->add( sub { | 
| 34 |  |  |  |  |  |  | do_something; | 
| 35 |  |  |  |  |  |  | $cs->next( $bar, $yohoo ); | 
| 36 |  |  |  |  |  |  | }); | 
| 37 |  |  |  |  |  |  |  | 
| 38 |  |  |  |  |  |  | $cv = $cs->last; | 
| 39 |  |  |  |  |  |  | return $cv; | 
| 40 |  |  |  |  |  |  |  | 
| 41 |  |  |  |  |  |  | # or | 
| 42 |  |  |  |  |  |  |  | 
| 43 |  |  |  |  |  |  | http_get http://BlueT.org => sub { $cs->start($_[0]) }; | 
| 44 |  |  |  |  |  |  | $cs->add( sub { say $_[0]->recv; $cs->next } ); | 
| 45 |  |  |  |  |  |  | $cs->last->cb(sub { | 
| 46 |  |  |  |  |  |  | # do something after that | 
| 47 |  |  |  |  |  |  | # and maybe let me know someone's using my module :3 | 
| 48 |  |  |  |  |  |  | }); | 
| 49 |  |  |  |  |  |  |  | 
| 50 |  |  |  |  |  |  | # or | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  | $cs->add( sub { say 'I got the ball'; $cs->next( $_[0]->recv ); } ) | 
| 53 |  |  |  |  |  |  | print 'Your name please?: '; | 
| 54 |  |  |  |  |  |  | chomp(my $in = ); | 
| 55 |  |  |  |  |  |  | $cs->start($in); | 
| 56 |  |  |  |  |  |  | $cs->add( sub { say "Lucky you, $_[0]->recv" } ); | 
| 57 |  |  |  |  |  |  |  | 
| 58 |  |  |  |  |  |  | # or | 
| 59 |  |  |  |  |  |  |  | 
| 60 |  |  |  |  |  |  | my $cs = AE::CS; | 
| 61 |  |  |  |  |  |  |  | 
| 62 |  |  |  |  |  |  | =head1 METHODS | 
| 63 |  |  |  |  |  |  |  | 
| 64 |  |  |  |  |  |  | =head2 new | 
| 65 |  |  |  |  |  |  |  | 
| 66 |  |  |  |  |  |  | No paramater needed. | 
| 67 |  |  |  |  |  |  |  | 
| 68 |  |  |  |  |  |  | my $cs = new AnyEvent::CallbackStack; | 
| 69 |  |  |  |  |  |  |  | 
| 70 |  |  |  |  |  |  | =cut | 
| 71 |  |  |  |  |  |  |  | 
| 72 |  |  |  |  |  |  | sub new { | 
| 73 | 2 |  |  | 2 | 1 | 19 | my $class = shift; | 
| 74 |  |  |  |  |  |  |  | 
| 75 | 2 |  |  |  |  | 5 | my @cbq = (); | 
| 76 | 2 |  |  |  |  | 49 | push @cbq, AE::cv; | 
| 77 |  |  |  |  |  |  |  | 
| 78 | 2 |  |  |  |  | 6281 | my $self  = { | 
| 79 |  |  |  |  |  |  | cbq		=> \@cbq, | 
| 80 |  |  |  |  |  |  | current_step	=> 0, | 
| 81 |  |  |  |  |  |  | }; | 
| 82 |  |  |  |  |  |  |  | 
| 83 | 2 |  |  |  |  | 6 | bless ($self, $class); | 
| 84 | 2 |  |  |  |  | 4 | say 'NEW '.Dumper($self) if DEBUG; | 
| 85 |  |  |  |  |  |  |  | 
| 86 | 2 |  |  |  |  | 5 | return $self; | 
| 87 |  |  |  |  |  |  | } | 
| 88 |  |  |  |  |  |  |  | 
| 89 |  |  |  |  |  |  | =head2 start | 
| 90 |  |  |  |  |  |  |  | 
| 91 |  |  |  |  |  |  | Start and walk through the Callback Stack from step 0. | 
| 92 |  |  |  |  |  |  |  | 
| 93 |  |  |  |  |  |  | $cs->start( 'foo' ); | 
| 94 |  |  |  |  |  |  |  | 
| 95 |  |  |  |  |  |  | =cut | 
| 96 |  |  |  |  |  |  |  | 
| 97 |  |  |  |  |  |  | sub start { | 
| 98 | 2 |  |  | 2 | 1 | 58 | my $self = shift; | 
| 99 | 2 |  |  |  |  | 7 | $self->current_step(0); | 
| 100 |  |  |  |  |  |  |  | 
| 101 | 2 |  |  |  |  | 0 | say 'Start '.Dumper ($self) if DEBUG; | 
| 102 | 2 |  |  |  |  | 6 | $self->step($self->current_step, @_); | 
| 103 |  |  |  |  |  |  | } | 
| 104 |  |  |  |  |  |  |  | 
| 105 |  |  |  |  |  |  | =head2 add | 
| 106 |  |  |  |  |  |  |  | 
| 107 |  |  |  |  |  |  | Add (append) callback into the Callback Stack. | 
| 108 |  |  |  |  |  |  |  | 
| 109 |  |  |  |  |  |  | $cs->add( $code_ref ); | 
| 110 |  |  |  |  |  |  |  | 
| 111 |  |  |  |  |  |  | =cut | 
| 112 |  |  |  |  |  |  |  | 
| 113 |  |  |  |  |  |  | sub add { | 
| 114 | 2 |  |  | 2 | 1 | 60 | my $self = shift; | 
| 115 | 2 |  |  |  |  | 33 | $self->cbq(AE::cv); | 
| 116 |  |  |  |  |  |  |  | 
| 117 | 2 |  |  |  |  | 3 | say 'ADD '.Dumper ($self) if DEBUG; | 
| 118 |  |  |  |  |  |  |  | 
| 119 | 2 |  |  |  |  | 6 | ($self->cbq)[-2]->cb( shift ); | 
| 120 |  |  |  |  |  |  | } | 
| 121 |  |  |  |  |  |  |  | 
| 122 |  |  |  |  |  |  | =head2 next | 
| 123 |  |  |  |  |  |  |  | 
| 124 |  |  |  |  |  |  | Check out from the current step and pass value to the next callback in callback stack. | 
| 125 |  |  |  |  |  |  |  | 
| 126 |  |  |  |  |  |  | $cs->next( @result ); | 
| 127 |  |  |  |  |  |  |  | 
| 128 |  |  |  |  |  |  | IMPORTANT: | 
| 129 |  |  |  |  |  |  | Remember that only if you call this method, the next callback in stack will be triggered. | 
| 130 |  |  |  |  |  |  |  | 
| 131 |  |  |  |  |  |  | =cut | 
| 132 |  |  |  |  |  |  |  | 
| 133 |  |  |  |  |  |  | sub next { | 
| 134 | 1 |  |  | 1 | 1 | 850 | my $self = shift; | 
| 135 | 1 |  |  |  |  | 4 | $self->current_step( $self->current_step +1); | 
| 136 |  |  |  |  |  |  |  | 
| 137 | 1 |  |  |  |  | 1 | say 'NEXT $self->current_step '.Dumper ($self) if DEBUG; | 
| 138 |  |  |  |  |  |  |  | 
| 139 | 1 |  |  |  |  | 3 | $self->step($self->current_step, @_); | 
| 140 |  |  |  |  |  |  | } | 
| 141 |  |  |  |  |  |  |  | 
| 142 |  |  |  |  |  |  | =head2 last | 
| 143 |  |  |  |  |  |  |  | 
| 144 |  |  |  |  |  |  | Get the very last L object. | 
| 145 |  |  |  |  |  |  |  | 
| 146 |  |  |  |  |  |  | Usually it's called when you are writing a module and need to return it to your caller. | 
| 147 |  |  |  |  |  |  |  | 
| 148 |  |  |  |  |  |  | my $cv = $cs->last; | 
| 149 |  |  |  |  |  |  | # or | 
| 150 |  |  |  |  |  |  | return $cs->last; | 
| 151 |  |  |  |  |  |  |  | 
| 152 |  |  |  |  |  |  |  | 
| 153 |  |  |  |  |  |  | =cut | 
| 154 |  |  |  |  |  |  |  | 
| 155 |  |  |  |  |  |  | sub last { | 
| 156 | 1 |  |  | 1 | 1 | 14 | my $self = shift; | 
| 157 |  |  |  |  |  |  |  | 
| 158 | 1 |  |  |  |  | 2 | say 'LAST '.Dumper ($self) if DEBUG; | 
| 159 |  |  |  |  |  |  |  | 
| 160 | 1 |  |  |  |  | 2 | return ($self->cbq)[-1]; | 
| 161 |  |  |  |  |  |  | } | 
| 162 |  |  |  |  |  |  |  | 
| 163 |  |  |  |  |  |  | =head2 step | 
| 164 |  |  |  |  |  |  |  | 
| 165 |  |  |  |  |  |  | Experimental. | 
| 166 |  |  |  |  |  |  |  | 
| 167 |  |  |  |  |  |  | Start the callback flow from the specified step. | 
| 168 |  |  |  |  |  |  |  | 
| 169 |  |  |  |  |  |  | $cs->step( 3, @data ); | 
| 170 |  |  |  |  |  |  |  | 
| 171 |  |  |  |  |  |  | =cut | 
| 172 |  |  |  |  |  |  |  | 
| 173 |  |  |  |  |  |  | sub step { | 
| 174 | 3 |  |  | 3 | 1 | 4 | my $self = shift; | 
| 175 | 3 | 50 |  |  |  | 19 | $_[0] =~ /^\d+?$/ ? $self->current_step(shift) : die 'input is not a number in step()'; | 
| 176 |  |  |  |  |  |  |  | 
| 177 | 3 |  |  |  |  | 2 | say 'STEP '.Dumper ($self) if DEBUG; | 
| 178 |  |  |  |  |  |  |  | 
| 179 | 3 |  |  |  |  | 5 | ($self->cbq)[$self->current_step]->send( @_ ); | 
| 180 |  |  |  |  |  |  | } | 
| 181 |  |  |  |  |  |  |  | 
| 182 |  |  |  |  |  |  | =head2 cbq | 
| 183 |  |  |  |  |  |  |  | 
| 184 |  |  |  |  |  |  | Experimental. | 
| 185 |  |  |  |  |  |  |  | 
| 186 |  |  |  |  |  |  | Callback Queue Getter/Setter. | 
| 187 |  |  |  |  |  |  |  | 
| 188 |  |  |  |  |  |  | Don't use this directly unless you really know what you're doing. | 
| 189 |  |  |  |  |  |  |  | 
| 190 |  |  |  |  |  |  | my @cbq = $cs->cbq; | 
| 191 |  |  |  |  |  |  | $cs->cbq( AE::cv ); | 
| 192 |  |  |  |  |  |  |  | 
| 193 |  |  |  |  |  |  | =cut | 
| 194 |  |  |  |  |  |  |  | 
| 195 |  |  |  |  |  |  | sub cbq { | 
| 196 | 8 |  |  | 8 | 1 | 14 | my $self = shift; | 
| 197 | 8 | 100 |  |  |  | 17 | push @{$self->{'cbq'}}, @_ if @_; | 
|  | 2 |  |  |  |  | 7 |  | 
| 198 | 8 |  |  |  |  | 8 | return @{$self->{'cbq'}}; | 
|  | 8 |  |  |  |  | 35 |  | 
| 199 |  |  |  |  |  |  | } | 
| 200 |  |  |  |  |  |  |  | 
| 201 |  |  |  |  |  |  | =head2 current_step | 
| 202 |  |  |  |  |  |  |  | 
| 203 |  |  |  |  |  |  | Experimental. | 
| 204 |  |  |  |  |  |  |  | 
| 205 |  |  |  |  |  |  | 'Current Step Counter' Getter/Setter. | 
| 206 |  |  |  |  |  |  |  | 
| 207 |  |  |  |  |  |  | Don't use this directly unless you really know what you're doing. | 
| 208 |  |  |  |  |  |  |  | 
| 209 |  |  |  |  |  |  | my $curr_step = $cs->current_step; | 
| 210 |  |  |  |  |  |  | $cs->current_step( 0 ); | 
| 211 |  |  |  |  |  |  |  | 
| 212 |  |  |  |  |  |  | =cut | 
| 213 |  |  |  |  |  |  |  | 
| 214 |  |  |  |  |  |  | sub current_step { | 
| 215 | 13 |  |  | 13 | 1 | 11 | my $self = shift; | 
| 216 | 13 | 100 |  |  |  | 22 | $self->{'current_step'} = $_[0] if $_[0]; | 
| 217 | 13 |  |  |  |  | 25 | return $self->{'current_step'}; | 
| 218 |  |  |  |  |  |  | } | 
| 219 |  |  |  |  |  |  |  | 
| 220 |  |  |  |  |  |  | =head1 SHORTCUT AE::CS API | 
| 221 |  |  |  |  |  |  |  | 
| 222 |  |  |  |  |  |  | Inspired by AE. | 
| 223 |  |  |  |  |  |  | Starting with version 0.05, AnyEvent::CallbackStack officially supports a second, much | 
| 224 |  |  |  |  |  |  | simpler in name, API that is designed to reduce the typing. | 
| 225 |  |  |  |  |  |  |  | 
| 226 |  |  |  |  |  |  | There is No Magic like what AE has on reducing calling and memory overhead. | 
| 227 |  |  |  |  |  |  |  | 
| 228 |  |  |  |  |  |  | See the L manpage for details. | 
| 229 |  |  |  |  |  |  |  | 
| 230 |  |  |  |  |  |  | my $cs = AE::CS; | 
| 231 |  |  |  |  |  |  |  | 
| 232 |  |  |  |  |  |  | =cut | 
| 233 |  |  |  |  |  |  |  | 
| 234 |  |  |  |  |  |  | package AE::CS; | 
| 235 |  |  |  |  |  |  |  | 
| 236 |  |  |  |  |  |  | our $VERSION = $AnyEvent::CallbackStack::VERSION; | 
| 237 |  |  |  |  |  |  |  | 
| 238 |  |  |  |  |  |  | sub _reset() { | 
| 239 | 0 |  |  | 0 |  | 0 | eval q{ # poor man's autoloading {} | 
|  | 3 |  |  | 3 |  | 281 |  | 
| 240 |  |  |  |  |  |  | *AE::CS = sub { | 
| 241 |  |  |  |  |  |  | AnyEvent::CallbackStack->new | 
| 242 |  |  |  |  |  |  | }; | 
| 243 |  |  |  |  |  |  | }; | 
| 244 | 3 | 50 |  |  |  | 76 | die if $@; | 
| 245 |  |  |  |  |  |  | } | 
| 246 | 3 |  |  | 3 |  | 7 | BEGIN { _reset } | 
| 247 |  |  |  |  |  |  |  | 
| 248 |  |  |  |  |  |  |  | 
| 249 |  |  |  |  |  |  | =head1 AUTHOR | 
| 250 |  |  |  |  |  |  |  | 
| 251 |  |  |  |  |  |  | BlueT - Matthew Lien - 練喆明, C<<  >> | 
| 252 |  |  |  |  |  |  |  | 
| 253 |  |  |  |  |  |  | =head1 BUGS | 
| 254 |  |  |  |  |  |  |  | 
| 255 |  |  |  |  |  |  | Please report any bugs or feature requests to C, or through | 
| 256 |  |  |  |  |  |  | the web interface at L.  I will be notified, and then you'll | 
| 257 |  |  |  |  |  |  | automatically be notified of progress on your bug as I make changes. | 
| 258 |  |  |  |  |  |  |  | 
| 259 |  |  |  |  |  |  |  | 
| 260 |  |  |  |  |  |  |  | 
| 261 |  |  |  |  |  |  |  | 
| 262 |  |  |  |  |  |  | =head1 SUPPORT | 
| 263 |  |  |  |  |  |  |  | 
| 264 |  |  |  |  |  |  | You can find documentation for this module with the perldoc command. | 
| 265 |  |  |  |  |  |  |  | 
| 266 |  |  |  |  |  |  | perldoc AnyEvent::CallbackStack | 
| 267 |  |  |  |  |  |  |  | 
| 268 |  |  |  |  |  |  |  | 
| 269 |  |  |  |  |  |  | You can also look for information at: | 
| 270 |  |  |  |  |  |  |  | 
| 271 |  |  |  |  |  |  | =over 4 | 
| 272 |  |  |  |  |  |  |  | 
| 273 |  |  |  |  |  |  | =item * RT: CPAN's request tracker | 
| 274 |  |  |  |  |  |  |  | 
| 275 |  |  |  |  |  |  | L | 
| 276 |  |  |  |  |  |  |  | 
| 277 |  |  |  |  |  |  | =item * AnnoCPAN: Annotated CPAN documentation | 
| 278 |  |  |  |  |  |  |  | 
| 279 |  |  |  |  |  |  | L | 
| 280 |  |  |  |  |  |  |  | 
| 281 |  |  |  |  |  |  | =item * CPAN Ratings | 
| 282 |  |  |  |  |  |  |  | 
| 283 |  |  |  |  |  |  | L | 
| 284 |  |  |  |  |  |  |  | 
| 285 |  |  |  |  |  |  | =item * Search CPAN | 
| 286 |  |  |  |  |  |  |  | 
| 287 |  |  |  |  |  |  | L | 
| 288 |  |  |  |  |  |  |  | 
| 289 |  |  |  |  |  |  | =item * Launchpad | 
| 290 |  |  |  |  |  |  |  | 
| 291 |  |  |  |  |  |  | L | 
| 292 |  |  |  |  |  |  |  | 
| 293 |  |  |  |  |  |  | =item * GitHub | 
| 294 |  |  |  |  |  |  |  | 
| 295 |  |  |  |  |  |  | L | 
| 296 |  |  |  |  |  |  |  | 
| 297 |  |  |  |  |  |  | =back | 
| 298 |  |  |  |  |  |  |  | 
| 299 |  |  |  |  |  |  |  | 
| 300 |  |  |  |  |  |  | =head1 ACKNOWLEDGEMENTS | 
| 301 |  |  |  |  |  |  |  | 
| 302 |  |  |  |  |  |  |  | 
| 303 |  |  |  |  |  |  | =head1 LICENSE AND COPYRIGHT | 
| 304 |  |  |  |  |  |  |  | 
| 305 |  |  |  |  |  |  | Copyright 2012 BlueT - Matthew Lien - 練喆明. | 
| 306 |  |  |  |  |  |  |  | 
| 307 |  |  |  |  |  |  | This program is free software; you can redistribute it and/or modify it | 
| 308 |  |  |  |  |  |  | under the terms of either: the GNU General Public License as published | 
| 309 |  |  |  |  |  |  | by the Free Software Foundation; or the Artistic License. | 
| 310 |  |  |  |  |  |  |  | 
| 311 |  |  |  |  |  |  | See http://dev.perl.org/licenses/ for more information. | 
| 312 |  |  |  |  |  |  |  | 
| 313 |  |  |  |  |  |  |  | 
| 314 |  |  |  |  |  |  | =cut | 
| 315 |  |  |  |  |  |  |  | 
| 316 |  |  |  |  |  |  | 1; # End of AnyEvent::CallbackStack |