… | |
… | |
149 | for @{ delete $self->{_on_destroy} || [] }; |
149 | for @{ delete $self->{_on_destroy} || [] }; |
150 | } |
150 | } |
151 | |
151 | |
152 | # this coroutine is necessary because a coroutine |
152 | # this coroutine is necessary because a coroutine |
153 | # cannot destroy itself. |
153 | # cannot destroy itself. |
154 | my @destroy; |
154 | our @destroy; |
155 | my $manager; |
155 | our $manager; |
156 | |
156 | |
157 | $manager = new Coro sub { |
157 | $manager = new Coro sub { |
158 | while () { |
158 | while () { |
159 | (shift @destroy)->_cancel |
159 | (shift @destroy)->_cancel |
160 | while @destroy; |
160 | while @destroy; |
… | |
… | |
340 | program calls this function, there will be some one-time resource leak. |
340 | program calls this function, there will be some one-time resource leak. |
341 | |
341 | |
342 | =cut |
342 | =cut |
343 | |
343 | |
344 | sub terminate { |
344 | sub terminate { |
345 | $current->cancel (@_); |
345 | $current->{_status} = [@_]; |
|
|
346 | push @destroy, $current; |
|
|
347 | $manager->ready; |
|
|
348 | do { &schedule } while 1; |
346 | } |
349 | } |
347 | |
350 | |
348 | sub killall { |
351 | sub killall { |
349 | for (Coro::State::list) { |
352 | for (Coro::State::list) { |
350 | $_->cancel |
353 | $_->cancel |
… | |
… | |
371 | See C<async> and C<Coro::State::new> for additional info about the |
374 | See C<async> and C<Coro::State::new> for additional info about the |
372 | coroutine environment. |
375 | coroutine environment. |
373 | |
376 | |
374 | =cut |
377 | =cut |
375 | |
378 | |
376 | sub _run_coro { |
379 | sub _terminate { |
377 | terminate &{+shift}; |
380 | terminate &{+shift}; |
378 | } |
|
|
379 | |
|
|
380 | sub new { |
|
|
381 | my $class = shift; |
|
|
382 | |
|
|
383 | $class->SUPER::new (\&_run_coro, @_) |
|
|
384 | } |
381 | } |
385 | |
382 | |
386 | =item $success = $coroutine->ready |
383 | =item $success = $coroutine->ready |
387 | |
384 | |
388 | Put the given coroutine into the end of its ready queue (there is one |
385 | Put the given coroutine into the end of its ready queue (there is one |
… | |
… | |
405 | |
402 | |
406 | =cut |
403 | =cut |
407 | |
404 | |
408 | sub cancel { |
405 | sub cancel { |
409 | my $self = shift; |
406 | my $self = shift; |
410 | $self->{_status} = [@_]; |
|
|
411 | |
407 | |
412 | if ($current == $self) { |
408 | if ($current == $self) { |
413 | push @destroy, $self; |
409 | terminate @_; |
414 | $manager->ready; |
|
|
415 | &schedule while 1; |
|
|
416 | } else { |
410 | } else { |
|
|
411 | $self->{_status} = [@_]; |
417 | $self->_cancel; |
412 | $self->_cancel; |
418 | } |
413 | } |
419 | } |
414 | } |
420 | |
415 | |
421 | =item $coroutine->throw ([$scalar]) |
416 | =item $coroutine->throw ([$scalar]) |