ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro.pm
(Generate patch)

Comparing Coro/Coro.pm (file contents):
Revision 1.102 by root, Fri Dec 29 11:37:49 2006 UTC vs.
Revision 1.103 by root, Thu Jan 4 20:14:19 2007 UTC

141$idle = sub { 141$idle = sub {
142 require Carp; 142 require Carp;
143 Carp::croak ("FATAL: deadlock detected"); 143 Carp::croak ("FATAL: deadlock detected");
144}; 144};
145 145
146sub _cancel {
147 my ($self) = @_;
148
149 # free coroutine data and mark as destructed
150 $self->_destroy
151 or return;
152
153 # call all destruction callbacks
154 $_->(@{$self->{status}})
155 for @{(delete $self->{destroy_cb}) || []};
156}
157
146# this coroutine is necessary because a coroutine 158# this coroutine is necessary because a coroutine
147# cannot destroy itself. 159# cannot destroy itself.
148my @destroy; 160my @destroy;
161my $manager;
162
149my $manager; $manager = new Coro sub { 163$manager = new Coro sub {
150 while () { 164 while () {
151 # by overwriting the state object with the manager we destroy it 165 (shift @destroy)->_cancel
152 # while still being able to schedule this coroutine (in case it has
153 # been readied multiple times. this is harmless since the manager
154 # can be called as many times as neccessary and will always
155 # remove itself from the runqueue
156 while (@destroy) { 166 while @destroy;
157 my $coro = pop @destroy;
158 167
159 $coro->{status} ||= [];
160
161 $_->ready for @{(delete $coro->{join} ) || []};
162 $_->(@{$coro->{status}}) for @{(delete $coro->{destroy_cb}) || []};
163
164 # the next line destroys the coro state, but keeps the
165 # coroutine itself intact (we basically make it a zombie
166 # coroutine that always runs the manager thread, so it's possible
167 # to transfer() to this coroutine).
168 $coro->_clone_state_from ($manager);
169 }
170 &schedule; 168 &schedule;
171 } 169 }
172}; 170};
171
172$manager->prio (PRIO_MAX);
173 173
174# static methods. not really. 174# static methods. not really.
175 175
176=back 176=back
177 177
294Return wether the coroutine is currently the ready queue or not, 294Return wether the coroutine is currently the ready queue or not,
295 295
296=item $coroutine->cancel (arg...) 296=item $coroutine->cancel (arg...)
297 297
298Terminates the given coroutine and makes it return the given arguments as 298Terminates the given coroutine and makes it return the given arguments as
299status (default: the empty list). 299status (default: the empty list). Never returns if the coroutine is the
300current coroutine.
300 301
301=cut 302=cut
302 303
303sub cancel { 304sub cancel {
304 my $self = shift; 305 my $self = shift;
305 $self->{status} = [@_]; 306 $self->{status} = [@_];
307
308 if ($current == $self) {
306 push @destroy, $self; 309 push @destroy, $self;
307 $manager->ready; 310 $manager->ready;
308 &schedule if $current == $self; 311 &schedule while 1;
312 } else {
313 $self->_cancel;
314 }
309} 315}
310 316
311=item $coroutine->join 317=item $coroutine->join
312 318
313Wait until the coroutine terminates and return any values given to the 319Wait until the coroutine terminates and return any values given to the
316 322
317=cut 323=cut
318 324
319sub join { 325sub join {
320 my $self = shift; 326 my $self = shift;
327
321 unless ($self->{status}) { 328 unless ($self->{status}) {
322 push @{$self->{join}}, $current; 329 my $current = $current;
323 &schedule; 330
331 push @{$self->{destroy_cb}}, sub {
332 $current->ready;
333 undef $current;
334 };
335
336 &schedule while $current;
324 } 337 }
338
325 wantarray ? @{$self->{status}} : $self->{status}[0]; 339 wantarray ? @{$self->{status}} : $self->{status}[0];
326} 340}
327 341
328=item $coroutine->on_destroy (\&cb) 342=item $coroutine->on_destroy (\&cb)
329 343
390Returns the number of coroutines that are currently in the ready state, 404Returns the number of coroutines that are currently in the ready state,
391i.e. that can be swicthed to. The value C<0> means that the only runnable 405i.e. that can be swicthed to. The value C<0> means that the only runnable
392coroutine is the currently running one, so C<cede> would have no effect, 406coroutine is the currently running one, so C<cede> would have no effect,
393and C<schedule> would cause a deadlock unless there is an idle handler 407and C<schedule> would cause a deadlock unless there is an idle handler
394that wakes up some coroutines. 408that wakes up some coroutines.
409
410=item my $guard = Coro::guard { ... }
411
412This creates and returns a guard object. Nothing happens until the objetc
413gets destroyed, in which case the codeblock given as argument will be
414executed. This is useful to free locks or other resources in case of a
415runtime error or when the coroutine gets canceled, as in both cases the
416guard block will be executed. The guard object supports only one method,
417C<< ->cancel >>, which will keep the codeblock from being executed.
418
419Example: set some flag and clear it again when the coroutine gets canceled
420or the function returns:
421
422 sub do_something {
423 my $guard = Coro::guard { $busy = 0 };
424 $busy = 1;
425
426 # do something that requires $busy to be true
427 }
428
429=cut
430
431sub guard(&) {
432 bless \(my $cb = $_[0]), "Coro::guard"
433}
434
435sub Coro::guard::cancel {
436 ${$_[0]} = sub { };
437}
438
439sub Coro::guard::DESTROY {
440 ${$_[0]}->();
441}
442
395 443
396=item unblock_sub { ... } 444=item unblock_sub { ... }
397 445
398This utility function takes a BLOCK or code reference and "unblocks" it, 446This utility function takes a BLOCK or code reference and "unblocks" it,
399returning the new coderef. This means that the new coderef will return 447returning the new coderef. This means that the new coderef will return

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines