--- Coro/Coro.pm 2011/05/12 23:55:39 1.297 +++ Coro/Coro.pm 2015/10/04 13:10:22 1.337 @@ -18,7 +18,6 @@ cede; # and again # use locking - use Coro::Semaphore; my $lock = new Coro::Semaphore; my $locked; @@ -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,12 +220,13 @@ when a thread is in a C method or an C for example) is safe. -Lastly, 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 b 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: +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 @@ -235,6 +235,28 @@ 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 @@ -262,12 +284,12 @@ 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 (but you cannot switch to other coroutines form those +might want to do (but you cannot switch to other coroutines from those code blocks): async { @@ -294,11 +316,12 @@ 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"; @@ -345,7 +368,7 @@ our $main; # main coro our $current; # current coro -our $VERSION = 5.372; +our $VERSION = 6.48; our @EXPORT = qw(async async_pool cede schedule terminate current unblock_sub rouse_cb rouse_wait); our %EXPORT_TAGS = ( @@ -360,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. @@ -631,14 +654,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 { @@ -646,7 +669,7 @@ # monopolise the process. Since it runs in a timesliced # environment, it will regularly cede to other threads. while () { } - }; + }; =item killall @@ -769,15 +792,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 @@ -793,11 +820,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 @@ -893,7 +921,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. +currently no way to remove a callback once added. =item $oldprio = $coro->prio ($newprio) @@ -930,7 +958,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 { @@ -995,7 +1023,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 @@ -1109,7 +1137,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 @@ -1125,14 +1153,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) = @_; @@ -1145,7 +1173,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 @@ -1274,10 +1303,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