--- cvsroot/Coro/README 2009/12/25 07:17:12 1.27 +++ cvsroot/Coro/README 2013/03/06 06:00:08 1.32 @@ -16,7 +16,6 @@ cede; # and again # use locking - use Coro::Semaphore; my $lock = new Coro::Semaphore; my $locked; @@ -40,14 +39,14 @@ Unlike the so-called "Perl threads" (which are not actually real threads but only the windows process emulation (see section of same name for - more details) ported to unix, and as such act as processes), Coro + more details) ported to UNIX, and as such act as processes), Coro provides a full shared address space, which makes communication between - threads very easy. And Coro's threads are fast, too: disabling the - Windows process emulation code in your perl and using Coro can easily - result in a two to four times speed increase for your programs. A - parallel matrix multiplication benchmark runs over 300 times faster on a - single core than perl's pseudo-threads on a quad core using all four - cores. + threads very easy. And coro threads are fast, too: disabling the Windows + process emulation code in your perl and using Coro can easily result in + a two to four times speed increase for your programs. A parallel matrix + multiplication benchmark (very communication-intensive) runs over 300 + times faster on a single core than perls pseudo-threads on a quad core + using all four cores. Coro achieves that by supporting multiple running interpreters that share data, which is especially useful to code pseudo-parallel processes @@ -64,10 +63,286 @@ See also the "SEE ALSO" section at the end of this document - the Coro module family is quite large. +CORO THREAD LIFE CYCLE + During the long and exciting (or not) life of a coro thread, it goes + through a number of states: + + 1. Creation + The first thing in the life of a coro thread is it's creation - + obviously. The typical way to create a thread is to call the "async + BLOCK" function: + + async { + # thread code goes here + }; + + You can also pass arguments, which are put in @_: + + async { + print $_[1]; # prints 2 + } 1, 2, 3; + + 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. + + "async" 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 "new" constructor with + a code-reference: + + new Coro sub { + # thread code goes here + }, @optional_arguments; + + This is quite similar to calling "async", but the important + difference is that the new thread is not put into the ready queue, + so the thread will not run until somebody puts it there. "async" is, + therefore, identical to this sequence: + + my $coro = new Coro sub { + # thread code goes here + }; + $coro->ready; + return $coro; + + 2. Startup + When a new coro thread is created, only a copy of the code reference + and the arguments are stored, no extra memory for stacks and so on + is allocated, keeping the coro thread in a low-memory state. + + Only when it actually starts executing will all the resources be + finally allocated. + + The optional arguments specified at coro creation are available in + @_, similar to function calls. + + 3. Running / Blocking + A lot can happen after the coro thread has started running. Quite + usually, it will not run to the end in one go (because you could use + a function instead), but it will give up the CPU regularly because + it waits for external events. + + As long as a coro thread runs, its Coro object is available in the + global variable $Coro::current. + + The low-level way to give up the CPU is to call the scheduler, which + selects a new coro thread to run: + + Coro::schedule; + + Since running threads are not in the ready queue, calling the + scheduler without doing anything else will block the coro thread + forever - you need to arrange either for the coro to put woken up + (readied) by some other event or some other thread, or you can put + it into the ready queue before scheduling: + + # this is exactly what Coro::cede does + $Coro::current->ready; + Coro::schedule; + + All the higher-level synchronisation methods (Coro::Semaphore, + Coro::rouse_*...) are actually implemented via "->ready" and + "Coro::schedule". + + While the coro thread is running it also might get assigned a + C-level thread, or the C-level thread might be unassigned from it, + as the Coro runtime wishes. A C-level thread needs to be assigned + when your perl thread calls into some C-level function and that + function in turn calls perl and perl then wants to switch + coroutines. This happens most often when you run an event loop and + block in the callback, or when perl itself calls some function such + as "AUTOLOAD" or methods via the "tie" mechanism. + + 4. Termination + Many threads actually terminate after some time. There are a number + of ways to terminate a coro thread, the simplest is returning from + the top-level code reference: + + async { + # after returning from here, the coro thread is terminated + }; + + async { + return if 0.5 < rand; # terminate a little earlier, maybe + print "got a chance to print this\n"; + # or here + }; + + Any values returned from the coroutine can be recovered using + "->join": + + my $coro = async { + "hello, world\n" # return a string + }; + + my $hello_world = $coro->join; + + print $hello_world; + + Another way to terminate is to call "Coro::terminate", which at any + subroutine call nesting level: + + async { + Coro::terminate "return value 1", "return value 2"; + }; + + Yet another way is to "->cancel" (or "->safe_cancel") the coro + thread from another thread: + + my $coro = async { + exit 1; + }; + + $coro->cancel; # also accepts values for ->join to retrieve + + Cancellation *can* be dangerous - it's a bit like calling "exit" + 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 "->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 "tie" method or an "AUTOLOAD" for + example) is safe. + + Last not least, a coro thread object that isn't referenced is + "->cancel"'ed automatically - just like other objects in Perl. This + is not such a common case, however - a running thread is referencedy + by $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 "async" + implements an endless loop, the $guard will not be cleaned up. + However, since the thread object returned by "async" is not stored + anywhere, the thread is initially referenced because it is in the + ready queue, when it runs it is referenced by $Coro::current, but + when it calls "schedule", it gets "cancel"ed 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... + + 5. Cleanup + Threads will allocate various resources. Most but not all will be + returned when a thread terminates, during clean-up. + + Cleanup is quite similar to throwing an uncaught exception: perl + will work it's way up through all subroutine calls and blocks. On + it's way, it will release all "my" variables, undo all "local"'s and + free any other resources truly local to the thread. + + So, a common way to free resources is to keep them referenced only + by my variables: + + async { + my $big_cache = new Cache ...; + }; + + If there are no other references, then the $big_cache object will be + freed when the thread terminates, regardless of how it does so. + + What it does "NOT" do is unlock any Coro::Semaphores or similar + resources, but that's where the "guard" methods come in handy: + + my $sem = new Coro::Semaphore; + + async { + my $lock_guard = $sem->guard; + # if we return, or die or get cancelled, here, + # then the semaphore will be "up"ed. + }; + + The "Guard::guard" function comes in handy for any custom cleanup + you might want to do (but you cannot switch to other coroutines from + those code blocks): + + async { + my $window = new Gtk2::Window "toplevel"; + # The window will not be cleaned up automatically, even when $window + # gets freed, so use a guard to ensure it's destruction + # in case of an error: + my $window_guard = Guard::guard { $window->destroy }; + + # we are safe here + }; + + Last not least, "local" can often be handy, too, e.g. when + temporarily replacing the coro thread description: + + sub myfunction { + local $Coro::current->{desc} = "inside myfunction(@_)"; + + # if we return or die here, the description will be restored + } + + 6. Viva La Zombie Muerte + 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. + + When there are no other references, it will simply be cleaned up and + freed. + + If there areany references, the Coro object will stay around, and + you can call "->join" as many times as you wish to retrieve the + result values: + + async { + print "hi\n"; + 1 + }; + + # run the async above, and free everything before returning + # from Coro::cede: + Coro::cede; + + { + my $coro = async { + print "hi\n"; + 1 + }; + + # run the async above, and clean up, but do not free the coro + # object: + Coro::cede; + + # optionally retrieve the result values + my @results = $coro->join; + + # now $coro goes out of scope, and presumably gets freed + }; + GLOBAL VARIABLES $Coro::main This variable stores the Coro object that represents the main - program. While you cna "ready" it and do most other things you can + program. While you can "ready" it and do most other things you can do to coro, it is mainly useful to compare again $Coro::current, to see whether you are running in the main program or not. @@ -94,8 +369,8 @@ to continue. This hook is overwritten by modules such as "Coro::EV" and - "Coro::AnyEvent" to wait on an external event that hopefully wake up - a coro so the scheduler can run it. + "Coro::AnyEvent" to wait on an external event that hopefully wakes + up a coro so the scheduler can run it. See Coro::EV or Coro::AnyEvent for examples of using this technique. @@ -205,7 +480,7 @@ terminate [arg...] Terminates the current coro with the given status values (see - cancel). + cancel). The values will not be copied, but referenced directly. Coro::on_enter BLOCK, Coro::on_leave BLOCK These function install enter and leave winders in the current scope. @@ -347,6 +622,22 @@ protect itself against spurious wakeups, and the one in the Coro family certainly do that. + $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. + + $state->is_zombie + Returns true iff the Coro object has been cancelled, i.e. it's + resources freed because they were "cancel"'ed, "terminate"'d, + "safe_cancel"'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". + $is_ready = $coro->is_ready Returns true iff the Coro object is in the ready queue. Unless the Coro object gets destroyed, it will eventually be scheduled by the @@ -362,9 +653,79 @@ Coros will not ever be scheduled. $coro->cancel (arg...) - Terminates the given Coro and makes it return the given arguments as - status (default: the empty list). Never returns if the Coro is the - current Coro. + Terminates the given Coro thread and makes it return the given + arguments as status (default: an empty list). Never returns if the + Coro is the current Coro. + + 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 its thread + context, things will not work. + + Any cleanup code being run (e.g. from "guard" blocks) will be run + without a thread context, and is not allowed to switch to other + threads. On the plus side, "->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 "->throw" an exception, or use + "->safe_cancel". + + The arguments to "->cancel" are not copied, but instead will be + referenced directly (e.g. if you pass $var and after the call change + that variable, then you might change the return values passed to + e.g. "join", 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 in some cases the manager thread has to run first to + actually destruct the Coro object. + + $coro->safe_cancel ($arg...) + Works mostly like "->cancel", but is inherently "safer", and + consequently, can fail with an exception in cases the thread is not + in a 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. "guard" 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 "cancel" or "terminate". + + 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 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 + "->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 "->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 "->safe_cancel" + is the only way, and if you don't, then "->cancel" is always faster + and more direct. $coro->schedule_to Puts the current coro to sleep (like "Coro::schedule"), but instead @@ -391,17 +752,17 @@ Coro will check for the exception each time a schedule-like-function returns, i.e. after each "schedule", "cede", "Coro::Semaphore->down", "Coro::Handle->readable" and so on. Most of - these functions detect this case and return early in case an - exception is pending. + 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 $@, i.e. if it is a string, no line number or newline will be appended (unlike with "die"). - This can be used as a softer means than "cancel" 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 "cancel" or + "safe_cancel "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. You might also think of "throw" as being the moral equivalent of "kill"ing a coro with a signal (in this case, a scalar). @@ -409,19 +770,24 @@ $coro->join Wait until the coro terminates and return any values given to the "terminate" or "cancel" functions. "join" can be called concurrently - from multiple coro, and all will be resumed and given the status + from multiple threads, and all will be resumed and given the status return once the $coro terminates. $coro->on_destroy (\&cb) - Registers a callback that is called when this coro gets destroyed, - but before it is joined. The callback gets passed the terminate + Registers a callback that is called when this coro thread gets + destroyed, that is, after it's resources have been freed but before + it is joined. The callback gets passed the terminate/cancel arguments, if any, and *must not* die, under any circumstances. + There can be any number of "on_destroy" callbacks per coro, and + there is no way currently to remove a callback once added. + $oldprio = $coro->prio ($newprio) - Sets (or gets, if the argument is missing) the priority of the coro. - Higher priority coro get run before lower priority coro. 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): + Sets (or gets, if the argument is missing) the priority of the coro + thread. Higher priority coro get run before lower priority coros. + 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): PRIO_MAX > PRIO_HIGH > PRIO_NORMAL > PRIO_LOW > PRIO_IDLE > PRIO_MIN 3 > 1 > 0 > -1 > -3 > -4 @@ -429,25 +795,37 @@ # set priority to HIGH current->prio (PRIO_HIGH); - The idle coro ($Coro::idle) always has a lower priority than any - existing coro. + The idle coro thread ($Coro::idle) always has a lower priority than + any existing coro. Changing the priority of the current coro will take effect - immediately, but changing the priority of coro in the ready queue + immediately, but changing the priority of a coro in the ready queue (but not running) will only take effect after the next schedule (of that coro). This is a bug that will be fixed in some future version. $newprio = $coro->nice ($change) Similar to "prio", but subtract the given value from the priority - (i.e. higher values mean lower priority, just as in unix). + (i.e. higher values mean lower priority, just as in UNIX's nice + command). $olddesc = $coro->desc ($newdesc) Sets (or gets in case the argument is missing) the description for - this coro. This is just a free-form string you can associate with a - coro. + this coro thread. This is just a free-form string you can associate + with a coro. This method simply sets the "$coro->{desc}" member to the given - string. You can modify this member directly if you wish. + string. You can modify this member directly if you wish, and in + fact, this is often preferred to indicate major processing states + that can then be seen for example in a Coro::Debug session: + + sub my_long_function { + local $Coro::current->{desc} = "now in my_long_function"; + ... + $Coro::current->{desc} = "my_long_function: phase 1"; + ... + $Coro::current->{desc} = "my_long_function: phase 2"; + ... + } GLOBAL FUNCTIONS Coro::nready @@ -474,7 +852,8 @@ reentrancy). This means you must not block within event callbacks, otherwise you might suffer from crashes or worse. The only event library currently known that is safe to use without "unblock_sub" is - EV. + EV (but 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 @@ -538,7 +917,7 @@ my $status = wait_for_child $pid; Coro offers two functions specifically designed to make this easy, - "Coro::rouse_cb" and "Coro::rouse_wait". + "rouse_cb" and "rouse_wait". The first function, "rouse_cb", generates and returns a callback that, when invoked, will save its arguments and notify the coro that created @@ -554,14 +933,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 "rouse_cb" and "rouse_wait" are not flexible enough, - you can roll your own, using "schedule": + you can roll your own, using "schedule" and "ready": sub wait_for_child($) { my ($pid) = @_; @@ -574,7 +953,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 @@ -598,6 +978,9 @@ processes, as having 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). + coro switching is not signal safe You must not switch to another coro from within a signal handler (only relevant with %SIG - most event libraries provide safe @@ -618,7 +1001,7 @@ Chip, it is probably not obvious to everybody). What follows is an ultra-condensed version of my talk about threads in - scripting languages given onthe perl workshop 2009: + scripting languages given on the perl workshop 2009: The so-called "ithreads" were originally implemented for two reasons: first, to (badly) emulate unix processes on native win32 perls, and