--- cvsroot/Coro/Coro.pm 2011/05/06 21:15:17 1.294 +++ cvsroot/Coro/Coro.pm 2014/02/02 03:26:06 1.321 @@ -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,28 +197,66 @@ 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; }; - $coro->cancel; # an also accept values for ->join to retrieve + $coro->cancel; # also accepts values for ->join to retrieve -Cancellation I be dangerous - it's a bit like calling C -without actually exiting, and might leave C libraries and XS modules in -a weird state. Unlike other thread implementations, however, Coro is -exceptionally safe with regards to cancellation, as perl will always be -in a consistent state, and for those cases where you want to do truly -marvellous things with your coro while it is being cancelled, there is -even a C<< ->safe_cancel >> method. +Cancellation I be dangerous - it's a bit like calling C without +actually exiting, and might leave C libraries and XS modules in a weird +state. Unlike other thread implementations, however, Coro is exceptionally +safe with regards to cancellation, as perl will always be in a consistent +state, and for those cases where you want to do truly marvellous things +with your coro while it is being cancelled - that is, make sure all +cleanup code is executed from the thread being cancelled - there is even a +C<< ->safe_cancel >> method. So, cancelling a thread that runs in an XS event loop might not be the best idea, but any other combination that deals with perl only (cancelling 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 @@ -247,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"; @@ -275,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"; @@ -332,7 +368,7 @@ our $main; # main coro our $current; # current coro -our $VERSION = 5.372; +our $VERSION = 6.33; our @EXPORT = qw(async async_pool cede schedule terminate current unblock_sub rouse_cb rouse_wait); our %EXPORT_TAGS = ( @@ -347,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. @@ -714,6 +750,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 @@ -739,16 +792,20 @@ 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. -Sometimes it is safer to C<< ->throw >> an exception, or use C<< -->safe_cancel >>. - -The arguments are not copied, but instead will be referenced directly -(e.g. if you pass C<$var> and after the call change that variable, then -you might change the return values passed to e.g. C, so don't do -that). +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 >>. + +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 +change that variable, then you might change the return values passed to +e.g. C, so don't do that). The resources of the Coro are usually freed (or destructed) before this call returns, but this can be delayed for an indefinite amount of time, as @@ -762,24 +819,45 @@ cancellable state. 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 context -and can block if they wish. +- 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 +C. -A thread is safe-cancellable if it either hasn't been run yet, or -it has no C context attached and is inside an SLF function. +A thread is in a safe-cancellable state if it either hasn't been run yet, +or it has no C context attached and is inside an SLF function. The latter two basically mean that the thread isn't currently inside a -perl callback called from some C function (usually XS modules) and isn't -currently inside some C function itself. - -This call always returns true when it could cancel the thread, or croaks -with an error otherwise, so you can write things like this: +perl callback called from some C function (usually via some XS modules) +and isn't currently executing inside some C function itself (via Coro's XS +API). + +This call returns true when it could cancel the thread, or croaks with an +error otherwise (i.e. it either returns true or doesn't return at all). + +Why the weird interface? Well, there are two common models on how and +when to cancel things. In the first, you have the expectation that your +coro thread can be cancelled when you want to cancel it - if the thread +isn't cancellable, this would be a bug somewhere, so C<< ->safe_cancel >> +croaks to notify of the bug. + +In the second model you sometimes want to ask nicely to cancel a thread, +but if it's not a good time, well, then don't cancel. This can be done +relatively easy like this: if (! eval { $coro->safe_cancel }) { warn "unable to cancel thread: $@"; } +However, what you never should do is first try to cancel "safely" and +if that fails, cancel the "hard" way with C<< ->cancel >>. That makes +no sense: either you rely on being able to execute cleanup code in your +thread context, or you don't. If you do, then C<< ->safe_cancel >> is the +only way, and if you don't, then C<< ->cancel >> is always faster and more +direct. + =item $coro->schedule_to Puts the current coro to sleep (like C), but instead @@ -807,17 +885,18 @@ Coro will check for the exception each time a schedule-like-function returns, i.e. after each C, C, C<< Coro::Semaphore->down ->>, C<< Coro::Handle->readable >> and so on. Most of these functions -detect this case and return early in case an exception is pending. +>>, C<< Coro::Handle->readable >> and so on. Most of those functions (all +that are part of Coro itself) detect this case and return early in case an +exception is pending. The exception object will be thrown "as is" with the specified scalar in C<$@>, i.e. if it is a string, no line number or newline will be appended (unlike with C). -This can be used as a softer means than C to ask a coro to -end itself, although there is no guarantee that the exception will lead to -termination, and if the exception isn't caught it might well end the whole -program. +This can be used as a softer means than either C or Cto ask a coro to end itself, although there is no guarantee that the +exception will lead to termination, and if the exception isn't caught it +might well end the whole program. You might also think of C as being the moral equivalent of Cing a coro with a signal (in this case, a scalar). @@ -829,25 +908,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, @@ -856,15 +916,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) @@ -901,7 +953,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 { @@ -1080,7 +1132,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 @@ -1096,14 +1148,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) = @_; @@ -1116,7 +1168,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 @@ -1146,6 +1199,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