--- Coro/Coro.pm 2001/12/10 21:18:28 1.45 +++ Coro/Coro.pm 2004/05/13 16:12:14 1.60 @@ -32,13 +32,15 @@ package Coro; -no warnings qw(uninitialized); +BEGIN { eval { require warnings } && warnings->unimport ("uninitialized") } use Coro::State; +use vars qw($idle $main $current); + use base Exporter; -$VERSION = 0.531; +$VERSION = 0.96; @EXPORT = qw(async cede schedule terminate current); %EXPORT_TAGS = ( @@ -85,7 +87,7 @@ =cut -our $main = new Coro; +$main = new Coro; =item $current (or as function: current) @@ -98,7 +100,7 @@ $main->{specific} = $current->{specific}; } -our $current = $main; +$current = $main; sub current() { $current } @@ -110,7 +112,7 @@ =cut # should be done using priorities :( -our $idle = new Coro sub { +$idle = new Coro sub { print STDERR "FATAL: deadlock detected\n"; exit(51); }; @@ -120,7 +122,7 @@ my @destroy; my $manager; $manager = new Coro sub { - while() { + while () { # by overwriting the state object with the manager we destroy it # while still being able to schedule this coroutine (in case it has # been readied multiple times. this is harmless since the manager @@ -130,6 +132,11 @@ my $coro = pop @destroy; $coro->{status} ||= []; $_->ready for @{delete $coro->{join} || []}; + + # the next line destroys the _coro_state, but keeps the + # process itself intact (we basically make it a zombie + # process that always runs the manager thread, so it's possible + # to transfer() to this process). $coro->{_coro_state} = $manager->{_coro_state}; } &schedule; @@ -157,9 +164,6 @@ print "@_\n"; } 1,2,3,4; -The coderef you submit MUST NOT be a closure that refers to variables -in an outer scope. This does NOT work. Pass arguments into it instead. - =cut sub async(&@) { @@ -187,17 +191,12 @@ =item terminate [arg...] -Terminates the current process. - -Future versions of this function will allow result arguments. +Terminates the current process with the given status values (see L). =cut sub terminate { - $current->{status} = [@_]; - $current->cancel; - &schedule; - die; # NORETURN + $current->cancel (@_); } =back @@ -236,23 +235,26 @@ =cut -=item $process->cancel +=item $process->cancel (arg...) -Like C, but terminates the specified process instead. +Temrinates the given process and makes it return the given arguments as +status (default: the empty list). =cut sub cancel { - push @destroy, $_[0]; + my $self = shift; + $self->{status} = [@_]; + push @destroy, $self; $manager->ready; - &schedule if $current == $_[0]; + &schedule if $current == $self; } =item $process->join Wait until the coroutine terminates and return any values given to the -C function. C can be called multiple times from multiple -processes. +C or C functions. C can be called multiple times +from multiple processes. =cut @@ -269,7 +271,7 @@ Sets (or gets, if the argument is missing) the priority of the process. Higher priority processes get run before lower priority -processes. Priorities are smalled signed integer (currently -4 .. +3), +processes. Priorities are small signed integers (currently -4 .. +3), that you can refer to using PRIO_xxx constants (use the import tag :prio to get then): @@ -327,17 +329,19 @@ =head1 BUGS/LIMITATIONS - - you must make very sure that no coro is still active on global destruction. - very bad things might happen otherwise (usually segfaults). - - this module is not thread-safe. You should only ever use this module from - the same thread (this requirement might be loosened in the future to - allow per-thread schedulers, but Coro::State does not yet allow this). + - you must make very sure that no coro is still active on global + destruction. very bad things might happen otherwise (usually segfaults). + + - this module is not thread-safe. You should only ever use this module + from the same thread (this requirement might be losened in the future + to allow per-thread schedulers, but Coro::State does not yet allow + this). =head1 SEE ALSO L, L, L, L, -L, L, L, L, -L, L. +L, L, L, L, +L, Handle>, L. =head1 AUTHOR