X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=ext%2Fthreads%2Fthreads.pm;h=22180ad5777a5d2977483f28d15792ffe417ca9c;hb=5735c168c62d0fa5cf526f0c7e7c97b069acef8f;hp=7a5a2740bb5b2ed1b33cbbca175c73a22dbdb5e1;hpb=68795e9367de98482c4a5830e6e94b51bd60f4e3;p=p5sagit%2Fp5-mst-13.2.git diff --git a/ext/threads/threads.pm b/ext/threads/threads.pm index 7a5a274..22180ad 100755 --- a/ext/threads/threads.pm +++ b/ext/threads/threads.pm @@ -1,15 +1,36 @@ package threads; -use 5.7.2; +use 5.008; use strict; use warnings; +use Config; + +BEGIN { + unless ($Config{useithreads}) { + my @caller = caller(2); + die < \&equal, 'fallback' => 1; -#use threads::Shared; - BEGIN { warn "Warning, threads::shared has already been loaded. ". "To enable shared variables for these modules 'use threads' ". @@ -22,19 +43,29 @@ require DynaLoader; our @ISA = qw(Exporter DynaLoader); -our %EXPORT_TAGS = ( all => [qw()]); +our %EXPORT_TAGS = ( all => [qw(yield)]); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw( - +async ); -our $VERSION = '0.05'; +our $VERSION = '1.06'; + +# || 0 to ensure compatibility with previous versions +sub equal { ($_[0]->tid == $_[1]->tid) || 0 } -sub equal { - return 1 if($_[0]->tid() == $_[1]->tid()); - return 0; +# use "goto" trick to avoid pad problems from 5.8.1 (fixed in 5.8.2) +# should also be faster +sub async (&;@) { unshift @_,'threads'; goto &new } + +sub object { + return undef unless @_ > 1; + foreach (threads->list) { + return $_ if $_->tid == $_[1]; + } + return undef; } $threads::threads = 1; @@ -55,33 +86,36 @@ threads - Perl extension allowing use of interpreter based threads from perl =head1 SYNOPSIS -use threads; + use threads; -sub start_thread { - print "Thread started\n"; -} + sub start_thread { + print "Thread started\n"; + } -my $thread = threads->new("start_thread","argument"); + my $thread = threads->create("start_thread","argument"); + my $thread2 = $thread->create(sub { print "I am a thread"},"argument"); + my $thread3 = async { foreach (@files) { ... } }; -$thread->new(sub { print "I am a thread"},"argument"); + $thread->join(); + $thread->detach(); -$thread->join(); + $thread = threads->self(); + $thread = threads->object( $tid ); -$thread->detach(); + $thread->tid(); + threads->tid(); + threads->self->tid(); -$thread = threads->self(); + threads->yield(); -threads->tid(); -threads->self->tid(); - -$thread->tid(); + threads->list(); =head1 DESCRIPTION Perl 5.6 introduced something called interpreter threads. Interpreter threads are different from "5005threads" (the thread model of Perl 5.005) by creating a new perl interpreter per thread and not sharing -any data or state between threads. +any data or state between threads by default. Prior to perl 5.8 this has only been available to people embedding perl and for emulating fork() on windows. @@ -91,67 +125,158 @@ important to note that variables are not shared between threads, all variables are per default thread local. To use shared variables one must use threads::shared. -It is also important to note that you preferably enable threads by -doing C as early as possible and that it is not possible -to enable threading inside an eval ""; In particular, if you are -intending to share variables with threads::shared, you must -C before you C and threads will emit -a warning if you do it the other way around. +It is also important to note that you must enable threads by doing +C as early as possible in the script itself and that it +is not possible to enable threading inside an C, C, +C, or C. In particular, if you are intending to share +variables with threads::shared, you must C before you +C and C will emit a warning if you do +it the other way around. =over -=item $thread = new(function, LIST) +=item $thread = threads->create(function, LIST) This will create a new thread with the entry point function and give it LIST as parameters. It will return the corresponding threads -object. - -create() is an alias to new. +object, or C if thread creation failed. The new() method is an +alias for create(). =item $thread->join -This will wait for the corresponding thread to join. When it finishes -join will return the return values of the entry point function. If a -thread has been detached, join will return without wait. +This will wait for the corresponding thread to join. When the thread +finishes, join() will return the return values of the entry point +function. If the thread has been detached, an error will be thrown. + +The context (scalar or list) of the thread creation is also the +context for join(). This means that if you intend to return an array +from a thread, you must use Cnew(...)>, and +that if you intend to return a scalar, you must use C. + +If the program exits without all other threads having been either +joined or detached, then a warning will be issued. (A program exits +either because one of its threads explicitly calls exit(), or in the +case of the main thread, reaches the end of the main program file.) + =item $thread->detach -Will throw away the return value from the thread and make it -non-joinable. +Will make the thread unjoinable, and cause any eventual return value +to be discarded. =item threads->self -This will return the object for the current thread. +This will return the thread object for the current thread. =item $thread->tid -This will return the id of the thread. threads->self->tid() is a -quick way to get current thread id. +This will return the id of the thread. Thread IDs are integers, with +the main thread in a program being 0. Currently Perl assigns a unique +tid to every thread ever created in your program, assigning the first +thread to be created a tid of 1, and increasing the tid by 1 for each +new thread that's created. + +NB the class method C<< threads->tid() >> is a quick way to get the +current thread id if you don't have your thread object handy. + +=item threads->object( tid ) + +This will return the thread object for the thread associated with the +specified tid. Returns undef if there is no thread associated with the tid +or no tid is specified or the specified tid is undef. + +=item threads->yield(); + +This is a suggestion to the OS to let this thread yield CPU time to other +threads. What actually happens is highly dependent upon the underlying +thread implementation. + +You may do C then use just a bare C in your +code. + +=item threads->list(); + +This will return a list of all non joined, non detached threads. + +=item async BLOCK; + +C creates a thread to execute the block immediately following +it. This block is treated as an anonymous sub, and so must have a +semi-colon after the closing brace. Like C<< threads->new >>, C +returns a thread object. =back +=head1 WARNINGS + +=over 4 + +=item A thread exited while %d other threads were still running + +A thread (not necessarily the main thread) exited while there were +still other threads running. Usually it's a good idea to first collect +the return values of the created threads by joining them, and only then +exit from the main thread. + +=back =head1 TODO +The current implementation of threads has been an attempt to get +a correct threading system working that could be built on, +and optimized, in newer versions of perl. + +Currently the overhead of creating a thread is rather large, +also the cost of returning values can be large. These are areas +were there most likely will be work done to optimize what data +that needs to be cloned. + +=head1 BUGS + =over -=item Fix so the return value is returned when you join. +=item Parent-Child threads. + +On some platforms it might not be possible to destroy "parent" +threads while there are still existing child "threads". + +This will possibly be fixed in later versions of perl. + +=item tid is I32 + +The thread id is a 32 bit integer, it can potentially overflow. +This might be fixed in a later version of perl. + +=item Returning objects + +When you return an object the entire stash that the object is blessed +as well. This will lead to a large memory usage. The ideal situation +would be to detect the original stash if it existed. -=item Add join_all. +=item Creating threads inside BEGIN blocks -=item Fix memory leaks! +Creating threads inside BEGIN blocks (or during the compilation phase +in general) does not work. (In Windows, trying to use fork() inside +BEGIN blocks is an equally losing proposition, since it has been +implemented in very much the same way as threads.) + +=item PERL_OLD_SIGNALS are not threadsafe, will not be. + +If your Perl has been built with PERL_OLD_SIGNALS (one has +to explicitly add that symbol to ccflags, see C), +signal handling is not threadsafe. =back =head1 AUTHOR and COPYRIGHT -Arthur Bergman Earthur at contiller.seE +Arthur Bergman Esky at nanisky.comE threads is released under the same license as Perl. Thanks to -Richard Soderberg Ers at crystalflame.netE +Richard Soderberg Eperl at crystalflame.netE Helping me out tons, trying to find reasons for races and other weird bugs! Simon Cozens Esimon at brecon.co.ukE @@ -164,19 +289,10 @@ Helping with debugging. please join perl-ithreads@perl.org for more information -=head1 BUGS - -=over - -=item creating a thread from within a thread is unsafe under win32 - -=item PERL_OLD_SIGNALS are not threadsafe, will not be. - - -=back - =head1 SEE ALSO -L, L, L, L, L +L, L, +L, +L, L, L =cut