--- cvsroot/Coro/Coro.pm 2011/05/10 19:55:48 1.295 +++ cvsroot/Coro/Coro.pm 2016/06/26 21:46:03 1.343 @@ -18,7 +18,6 @@ cede; # and again # use locking - use Coro::Semaphore; my $lock = new Coro::Semaphore; my $locked; @@ -92,9 +91,9 @@ This creates a new coro thread and puts it into the ready queue, meaning it will run as soon as the CPU is free for it. -C will return a coro object - you can store this for future -reference or ignore it, the thread itself will keep a reference to it's -thread object - threads are alive on their own. +C will return a Coro object - you can store this for future +reference or ignore it - a thread that is running, ready to run or waiting +for some event is alive on it's own. Another way to create a thread is to call the C constructor with a code-reference: @@ -133,7 +132,7 @@ instead), but it will give up the CPU regularly because it waits for external events. -As long as a coro thread runs, it's coro object is available in the global +As long as a coro thread runs, its Coro object is available in the global variable C<$Coro::current>. The low-level way to give up the CPU is to call the scheduler, which @@ -198,8 +197,8 @@ Coro::terminate "return value 1", "return value 2"; }; -And yet another way is to C<< ->cancel >> (or C<< ->safe_cancel >>) the -coro thread from another thread: +Yet another way is to C<< ->cancel >> (or C<< ->safe_cancel >>) the coro +thread from another thread: my $coro = async { exit 1; @@ -221,6 +220,43 @@ when a thread is in a C method or an C for example) is safe. +Last not least, a coro thread object that isn't referenced is C<< +->cancel >>'ed automatically - just like other objects in Perl. This +is not such a common case, however - a running thread is referencedy by +C<$Coro::current>, a thread ready to run is referenced by the ready queue, +a thread waiting on a lock or semaphore is referenced by being in some +wait list and so on. But a thread that isn't in any of those queues gets +cancelled: + + async { + schedule; # cede to other coros, don't go into the ready queue + }; + + cede; + # now the async above is destroyed, as it is not referenced by anything. + +A slightly embellished example might make it clearer: + + async { + my $guard = Guard::guard { print "destroyed\n" }; + schedule while 1; + }; + + cede; + +Superficially one might not expect any output - since the C +implements an endless loop, the C<$guard> will not be cleaned up. However, +since the thread object returned by C is not stored anywhere, the +thread is initially referenced because it is in the ready queue, when it +runs it is referenced by C<$Coro::current>, but when it calls C, +it gets Ced causing the guard object to be destroyed (see the next +section), and printing it's message. + +If this seems a bit drastic, remember that this only happens when nothing +references the thread anymore, which means there is no way to further +execute it, ever. The only options at this point are leaking the thread, +or cleaning it up, which brings us to... + =item 5. Cleanup Threads will allocate various resources. Most but not all will be returned @@ -248,12 +284,13 @@ async { my $lock_guard = $sem->guard; - # if we reutrn, or die or get cancelled, here, + # if we return, or die or get cancelled, here, # then the semaphore will be "up"ed. }; The C function comes in handy for any custom cleanup you -might want to do: +might want to do (but you cannot switch to other coroutines from those +code blocks): async { my $window = new Gtk2::Window "toplevel"; @@ -276,17 +313,15 @@ =item 6. Viva La Zombie Muerte -Even after a thread has terminated and cleaned up it's resources, the coro -object still is there and stores the return values of the thread. Only in -this state will the coro object be "reference counted" in the normal perl -sense: the thread code keeps a reference to it when it is active, but not -after it has terminated. +Even after a thread has terminated and cleaned up its resources, the Coro +object still is there and stores the return values of the thread. -The means the coro object gets freed automatically when the thread has -terminated and cleaned up and there arenot other references. +When there are no other references, it will simply be cleaned up and +freed. -If there are, the coro object will stay around, and you can call C<< -->join >> as many times as you wish to retrieve the result values: +If there areany references, the Coro object will stay around, and you +can call C<< ->join >> as many times as you wish to retrieve the result +values: async { print "hi\n"; @@ -333,7 +368,7 @@ our $main; # main coro our $current; # current coro -our $VERSION = 5.372; +our $VERSION = 6.511; our @EXPORT = qw(async async_pool cede schedule terminate current unblock_sub rouse_cb rouse_wait); our %EXPORT_TAGS = ( @@ -348,7 +383,7 @@ =item $Coro::main This variable stores the Coro object that represents the main -program. While you cna C it and do most other things you can do to +program. While you can C it and do most other things you can do to coro, it is mainly useful to compare again C<$Coro::current>, to see whether you are running in the main program or not. @@ -465,12 +500,13 @@ which somehow defeats the purpose of pooling (but is fine in the exceptional case). -The priority will be reset to C<0> after each run, tracing will be -disabled, the description will be reset and the default output filehandle -gets restored, so you can change all these. Otherwise the coro will -be re-used "as-is": most notably if you change other per-coro global -stuff such as C<$/> you I revert that change, which is most -simply done by using local as in: C<< local $/ >>. +The priority will be reset to C<0> after each run, all C calls +will be undone, tracing will be disabled, the description will be reset +and the default output filehandle gets restored, so you can change all +these. Otherwise the coro will be re-used "as-is": most notably if you +change other per-coro global stuff such as C<$/> you I revert +that change, which is most simply done by using local as in: C<< local $/ +>>. The idle pool size is limited to C<8> idle coros (this can be adjusted by changing $Coro::POOL_SIZE), but there can be as many non-idle @@ -619,14 +655,14 @@ $SIG{VTALRM} = sub { cede }; # and then start the interval timer Time::HiRes::setitimer &Time::HiRes::ITIMER_VIRTUAL, 0.01, 0.01; - }; + }; Coro::on_leave { # on leaving the thread, we stop the interval timer again Time::HiRes::setitimer &Time::HiRes::ITIMER_VIRTUAL, 0, 0; - }; + }; &{+shift}; - } + } # use like this: timeslice { @@ -634,7 +670,7 @@ # monopolise the process. Since it runs in a timesliced # environment, it will regularly cede to other threads. while () { } - }; + }; =item killall @@ -715,6 +751,23 @@ against spurious wakeups, and the one in the Coro family certainly do that. +=item $state->is_new + +Returns true iff this Coro object is "new", i.e. has never been run +yet. Those states basically consist of only the code reference to call and +the arguments, but consumes very little other resources. New states will +automatically get assigned a perl interpreter when they are transfered to. + +=item $state->is_zombie + +Returns true iff the Coro object has been cancelled, i.e. +it's resources freed because they were C'ed, C'd, +C'ed or simply went out of scope. + +The name "zombie" stems from UNIX culture, where a process that has +exited and only stores and exit status and no other resources is called a +"zombie". + =item $is_ready = $coro->is_ready Returns true iff the Coro object is in the ready queue. Unless the Coro @@ -740,15 +793,19 @@ This is a rather brutal way to free a coro, with some limitations - if the thread is inside a C callback that doesn't expect to be canceled, bad things can happen, or if the cancelled thread insists on running -complicated cleanup handlers that rely on it'S thread context, things will +complicated cleanup handlers that rely on its thread context, things will not work. -Any cleanup code being run (e.g. from C blocks) will be run without -a thread context, and is not allowed to switch to other threads. On the -plus side, C<< ->cancel >> will always clean up the thread, no matter -what. If your cleanup code is complex or you want to avoid cancelling a -C-thread that doesn't know how to clean up itself, it can be better to C<< -->throw >> an exception, or use C<< ->safe_cancel >>. +Any cleanup code being run (e.g. from C blocks, destructors and so +on) will be run without a thread context, and is not allowed to switch +to other threads. A common mistake is to call C<< ->cancel >> from a +destructor called by die'ing inside the thread to be cancelled for +example. + +On the plus side, C<< ->cancel >> will always clean up the thread, no +matter what. If your cleanup code is complex or you want to avoid +cancelling a C-thread that doesn't know how to clean up itself, it can be +better to C<< ->throw >> an exception, or use C<< ->safe_cancel >>. The arguments to C<< ->cancel >> are not copied, but instead will be referenced directly (e.g. if you pass C<$var> and after the call @@ -764,11 +821,12 @@ Works mostly like C<< ->cancel >>, but is inherently "safer", and consequently, can fail with an exception in cases the thread is not in a -cancellable state. +cancellable state. Essentially, C<< ->safe_cancel >> is a C<< ->cancel >> +with extra checks before canceling. -This method works a bit like throwing an exception that cannot be caught -- specifically, it will clean up the thread from within itself, so -all cleanup handlers (e.g. C blocks) are run with full thread +It works a bit like throwing an exception that cannot be caught - +specifically, it will clean up the thread from within itself, so all +cleanup handlers (e.g. C blocks) are run with full thread context and can block if they wish. The downside is that there is no guarantee that the thread can be cancelled when you call this method, and therefore, it might fail. It is also considerably slower than C or @@ -856,25 +914,6 @@ from multiple threads, and all will be resumed and given the status return once the C<$coro> terminates. -=cut - -sub join { - my $self = shift; - - unless ($self->{_status}) { - my $current = $current; - - push @{$self->{_on_destroy}}, sub { - $current->ready; - undef $current; - }; - - &schedule while $current; - } - - wantarray ? @{$self->{_status}} : $self->{_status}[0] -} - =item $coro->on_destroy (\&cb) Registers a callback that is called when this coro thread gets destroyed, @@ -883,15 +922,7 @@ not> die, under any circumstances. There can be any number of C callbacks per coro, and there is -no way currently to remove a callback once added. - -=cut - -sub on_destroy { - my ($self, $cb) = @_; - - push @{ $self->{_on_destroy} }, $cb; -} +currently no way to remove a callback once added. =item $oldprio = $coro->prio ($newprio) @@ -928,7 +959,7 @@ This method simply sets the C<< $coro->{desc} >> member to the given string. You can modify this member directly if you wish, and in fact, this -is often preferred to indicate major processing states that cna then be +is often preferred to indicate major processing states that can then be seen for example in a L session: sub my_long_function { @@ -993,7 +1024,7 @@ you might still run into deadlocks if all event loops are blocked). Coro will try to catch you when you block in the event loop -("FATAL:$Coro::IDLE blocked itself"), but this is just best effort and +("FATAL: $Coro::idle blocked itself"), but this is just best effort and only works when you do not run your own event loop. This function allows your callbacks to block by executing them in another @@ -1107,7 +1138,7 @@ my $status = wait_for_child $pid; Coro offers two functions specifically designed to make this easy, -C and C. +C and C. The first function, C, generates and returns a callback that, when invoked, will save its arguments and notify the coro that @@ -1123,14 +1154,14 @@ sub wait_for_child($) { my ($pid) = @_; - my $watcher = AnyEvent->child (pid => $pid, cb => Coro::rouse_cb); + my $watcher = AnyEvent->child (pid => $pid, cb => rouse_cb); - my ($rpid, $rstatus) = Coro::rouse_wait; + my ($rpid, $rstatus) = rouse_wait; $rstatus } In the case where C and C are not flexible enough, -you can roll your own, using C: +you can roll your own, using C and C: sub wait_for_child($) { my ($pid) = @_; @@ -1143,7 +1174,8 @@ # pass a closure to ->child my $watcher = AnyEvent->child (pid => $pid, cb => sub { $rstatus = $_[1]; # remember rstatus - $done = 1; # mark $rstatus as valud + $done = 1; # mark $rstatus as valid + $current->ready; # wake up the waiting thread }); # wait until the closure has been called @@ -1173,6 +1205,9 @@ the windows process emulation enabled under unix roughly halves perl performance, even when not used. +Attempts to use threads created in another emulated process will crash +("cleanly", with a null pointer exception). + =item coro switching is not signal safe You must not switch to another coro from within a signal handler (only @@ -1269,10 +1304,10 @@ Low level Configuration, Thread Environment, Continuations: L. -=head1 AUTHOR +=head1 AUTHOR/SUPPORT/CONTACT - Marc Lehmann - http://home.schmorp.de/ + Marc A. Lehmann + http://software.schmorp.de/pkg/Coro.html =cut