t/op/sort.t using test.pl
[p5sagit/p5-mst-13.2.git] / ext / threads / threads.pm
index 75d1412..e217dde 100755 (executable)
 package threads;
 
 use 5.008;
+
 use strict;
 use warnings;
-use Config;
-
-BEGIN {
-    unless ($Config{useithreads}) {
-       my @caller = caller(2);
-        die <<EOF;
-$caller[1] line $caller[2]:
 
-This Perl hasn't been configured and built properly for the threads
-module to work.  (The 'useithreads' configuration option hasn't been used.)
+our $VERSION = '1.24_01';
+my $XS_VERSION = $VERSION;
+$VERSION = eval $VERSION;
 
-Having threads support requires all of Perl and all of the XS modules in
-the Perl installation to be rebuilt, it is not just a question of adding
-the threads module.  (In other words, threaded and non-threaded Perls
-are binary incompatible.)
 
-If you want to the use the threads module, please contact the people
-who built your Perl.
-
-Cannot continue, aborting.
-EOF
+BEGIN {
+    # Verify this Perl supports threads
+    use Config;
+    if (! $Config{useithreads}) {
+        die("This Perl not built to support threads\n");
     }
-}
-
-use overload
-    '==' => \&equal,
-    'fallback' => 1;
 
-BEGIN {
-    warn "Warning, threads::shared has already been loaded. ".
-       "To enable shared variables for these modules 'use threads' ".
-       "must be called before any of those modules are loaded\n"
-               if($threads::shared::threads_shared);
+    # Declare that we have been loaded
+    $threads::threads = 1;
+
+    # Complain if 'threads' is loaded after 'threads::shared'
+    if ($threads::shared::threads_shared) {
+        warn <<'_MSG_';
+Warning, threads::shared has already been loaded.  To
+enable shared variables, 'use threads' must be called
+before threads::shared or any module that uses it.
+_MSG_
+   }
 }
 
-require Exporter;
-require DynaLoader;
+# Load the XS code
+require XSLoader;
+XSLoader::load('threads', $XS_VERSION);
 
-our @ISA = qw(Exporter DynaLoader);
 
-our %EXPORT_TAGS = ( all => [qw(yield)]);
+### Export ###
 
-our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
+sub import
+{
+    my $class = shift;   # Not used
 
-our @EXPORT = qw(
-async  
-);
-our $VERSION = '1.01';
+    # Exported subroutines
+    my @EXPORT = qw(async);
 
+    # Handle args
+    while (my $sym = shift) {
+        if ($sym =~ /all/) {
+            push(@EXPORT, qw(yield));
 
-# || 0 to ensure compatibility with previous versions
-sub equal { ($_[0]->tid == $_[1]->tid) || 0 }
-
-# use "goto" trick to avoid pad problems from 5.8.1, should also be faster
-sub async (&;@) { unshift @_,'threads'; goto &new }
+        } else {
+            push(@EXPORT, $sym);
+        }
+    }
 
-sub object {
-    return undef unless @_ > 1;
-    foreach (threads->list) {
-        return $_ if $_->tid == $_[1];
+    # Export subroutine names
+    my $caller = caller();
+    foreach my $sym (@EXPORT) {
+        no strict 'refs';
+        *{$caller.'::'.$sym} = \&{$sym};
     }
-    return undef;
 }
 
-$threads::threads = 1;
 
-bootstrap threads $VERSION;
+### Methods, etc. ###
 
-# why document 'new' then use 'create' in the tests!
-*create = \&new;
+# 'new' is an alias for 'create'
+*new = \&create;
 
-# Preloaded methods go here.
+# 'async' is a function alias for the 'threads->create()' method
+sub async (&;@)
+{
+    unshift(@_, 'threads');
+    # Use "goto" trick to avoid pad problems from 5.8.1 (fixed in 5.8.2)
+    goto &create;
+}
+
+# Thread object equality checking
+use overload (
+    '==' => \&equal,
+    '!=' => sub { ! equal(@_) },
+    'fallback' => 1
+);
 
 1;
+
 __END__
 
 =head1 NAME
 
-threads - Perl extension allowing use of interpreter based threads from perl
+threads - Perl interpreter-based threads
+
+=head1 VERSION
+
+This document describes threads version 1.24
 
 =head1 SYNOPSIS
 
-    use threads;
+    use threads ('yield');
 
     sub start_thread {
-       print "Thread started\n";
+        my @args = @_;
+        print "Thread started: @args\n";
     }
+    my $thread = threads->create('start_thread', 'argument');
+    $thread->join();
+
+    threads->create(sub { print("I am a thread\n"); })->join();
 
-    my $thread  = threads->create("start_thread","argument");
-    my $thread2 = $thread->create(sub { print "I am a thread"},"argument");
     my $thread3 = async { foreach (@files) { ... } };
+    $thread3->join();
+
+    # Invoke thread in list context so it can return a list
+    my ($thr) = threads->create(sub { return (qw/a b c/); });
+    my @results = $thr->join();
 
-    $thread->join();
     $thread->detach();
 
     $thread = threads->self();
-    $thread = threads->object( $tid );
+    $thread = threads->object($tid);
 
-    $thread->tid();
-    threads->tid();
-    threads->self->tid();
+    $tid = threads->tid();
+    $tid = threads->self->tid();
+    $tid = $thread->tid();
 
     threads->yield();
+    yield();
+
+    my @threads = threads->list();
+    my $thread_count = threads->list();
 
-    threads->list();
+    if ($thr1 == $thr2) {
+        ...
+    }
 
 =head1 DESCRIPTION
 
@@ -134,74 +159,158 @@ it the other way around.
 
 =over
 
-=item $thread = threads->create(function, LIST)
+=item $thr = threads->create(FUNCTION, ARGS)
+
+This will create a new thread that will begin execution with the specified
+entry point function, and give it the I<ARGS> list as parameters.  It will
+return the corresponding threads object, or C<undef> if thread creation failed.
+
+I<FUNCTION> may either be the name of a function, an anonymous subroutine, or
+a code ref.
+
+    my $thr = threads->create('func_name', ...);
+        # or
+    my $thr = threads->create(sub { ... }, ...);
+        # or
+    my $thr = threads->create(\&func, ...);
+
+The thread may be created in I<list> context, or I<scalar> context as follows:
+
+    # Create thread in list context
+    my ($thr) = threads->create(...);
+
+    # Create thread in scalar context
+    my $thr = threads->create(...);
+
+This has consequences for the C<-E<gt>join()> method describe below.
+
+Although a thread may be created in I<void> context, to do so you must
+I<chain> either the C<-E<gt>join()> or C<-E<gt>detach()> method to the
+C<-E<gt>create()> call:
+
+    threads->create(...)->join();
+
+The C<-E<gt>new()> method is an alias for C<-E<gt>create()>.
+
+=item $thr->join()
+
+This will wait for the corresponding thread to complete its execution.  When
+the thread finishes, C<-E<gt>join()> will return the return value(s) of the
+entry point function.
+
+The context (void, scalar or list) of the thread creation is also the
+context for C<-E<gt>join()>.  This means that if you intend to return an array
+from a thread, you must use C<my ($thr) = threads->create(...)>, and that
+if you intend to return a scalar, you must use C<my $thr = ...>:
 
-This will create a new thread with the entry point function and give
-it LIST as parameters.  It will return the corresponding threads
-object. The new() method is an alias for create().
+    # Create thread in list context
+    my ($thr1) = threads->create(sub {
+                                    my @results = qw(a b c);
+                                    return (@results);
+                                 };
+    # Retrieve list results from thread
+    my @res1 = $thr1->join();
 
-=item $thread->join
+    # Create thread in scalar context
+    my $thr2 = threads->create(sub {
+                                    my $result = 42;
+                                    return ($result);
+                                 };
+    # Retrieve scalar result from thread
+    my $res2 = $thr2->join();
 
-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.
+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 L<exit()|perlfunc/"exit EXPR">, or in the case
+of the main thread, reaches the end of the main program file.)
 
-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 C<my ($thread) = threads->new(...)>, and
-that if you intend to return a scalar, you must use C<my $thread = ...>.
+Calling C<-E<gt>join()> or C<-E<gt>detach()> on an already joined thread will
+cause an error to be thrown.
 
-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 $thr->detach()
 
+Makes the thread unjoinable, and causes any eventual return value to be
+discarded.
 
-=item $thread->detach
+Calling C<-E<gt>join()> or C<-E<gt>detach()> on an already detached thread
+will cause an error to be thrown.
 
-Will make the thread unjoinable, and cause any eventual return value
-to be discarded.
+=item threads->detach()
 
-=item threads->self
+Class method that allows a thread to detach itself.
 
-This will return the thread object for the current thread.
+=item threads->self()
 
-=item $thread->tid
+Class method that allows a thread to obtain its own I<threads> object.
 
-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.
+=item $thr->tid()
 
-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.
+Returns the ID of the thread.  Thread IDs are unique integers with the main
+thread in a program being 0, and incrementing by 1 for every thread created.
 
-=item threads->object( tid )
+=item threads->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.
+Class method that allows a thread to obtain its own ID.
 
-=item threads->yield();
+=item threads->object($tid)
+
+This will return the I<threads> object for the I<active> thread associated
+with the specified thread ID.  Returns C<undef> if there is no thread
+associated with the TID, if the thread is joined or detached, if no TID is
+specified or if 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<use threads qw(yield)> then use just a bare C<yield> in your
+You may do C<use threads qw(yield)>, and then just use C<yield()> in your
 code.
 
-=item threads->list();
+=item threads->list()
+
+In a list context, returns a list of all non-joined, non-detached I<threads>
+objects.  In a scalar context, returns a count of the same.
+
+=item $thr1->equal($thr2)
+
+Tests if two threads objects are the same thread or not.  This is overloaded
+to the more natural forms:
 
-This will return a list of all non joined, non detached threads.
+    if ($thr1 == $thr2) {
+        print("Threads are the same\n");
+    }
+    # or
+    if ($thr1 != $thr2) {
+        print("Threads differ\n");
+    }
+
+(Thread comparison is based on thread IDs.)
 
 =item async BLOCK;
 
 C<async> 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<async>
-returns a thread object.
+it.  This block is treated as an anonymous subroutine, and so must have a
+semi-colon after the closing brace.  Like C<threads->create()>, C<async>
+returns a I<threads> object.
+
+=item $thr->_handle()
+
+This I<private> method returns the memory location of the internal thread
+structure associated with a threads object.  For Win32, this is a pointer to
+the C<HANDLE> value returned by C<CreateThread> (i.e., C<HANDLE *>); for other
+platforms, it is a pointer to the C<pthread_t> structure used in the
+C<pthread_create> call (i.e., C<pthread_t *>.
+
+This method is of no use for general Perl threads programming.  Its intent is
+to provide other (XS-based) thread modules with the capability to access, and
+possibly manipulate, the underlying thread structure associated with a Perl
+thread.
+
+=item threads->_handle()
+
+Class method that allows a thread to obtain its own I<handle>.
 
 =back
 
@@ -209,7 +318,7 @@ returns a thread object.
 
 =over 4
 
-=item A thread exited while %d other threads were still running
+=item A thread exited while # 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
@@ -218,38 +327,30 @@ exit from the main thread.
 
 =back
 
-=head1 TODO
+=head1 ERRORS
 
-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.
+=over 4
 
-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.
+=item This Perl not built to support threads
 
-=head1 BUGS
+The particular copy of Perl that you're trying to use was not built using the
+C<useithreads> configuration option.
 
-=over
-
-=item Parent-Child threads.
+Having threads support requires all of Perl and all of the XS modules in the
+Perl installation to be rebuilt; it is not just a question of adding the
+L<threads> module (i.e., threaded and non-threaded Perls are binary
+incompatible.)
 
-On some platforms it might not be possible to destroy "parent"
-threads while there are still existing child "threads".
+=back
 
-This will possibly be fixed in later versions of perl.
-  
-=item tid is I32
+=head1 BUGS
 
-The thread id is a 32 bit integer, it can potentially overflow.
-This might be fixed in a later version of perl.
+=over
 
-=item Returning objects
+=item Parent-child threads
 
-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.
+On some platforms, it might not be possible to destroy I<parent> threads while
+there are still existing I<child> threads.
 
 =item Creating threads inside BEGIN blocks
 
@@ -264,38 +365,64 @@ If your Perl has been built with PERL_OLD_SIGNALS (one has
 to explicitly add that symbol to ccflags, see C<perl -V>),
 signal handling is not threadsafe.
 
-=item Detached threads on Windows
+=item Returning closures from threads
+
+Returning a closure from a thread does not work, usually crashing Perl in the
+process.
+
+=item Perl Bugs and the CPAN Version of L<threads>
 
-These aren't yet supported (as of perl 5.8.3), as they may lead to
-memory access violation problems.
+Support for threads extents beyond the code in this module (i.e.,
+F<threads.pm> and F<threads.xs>), and into the Perl iterpreter itself.  Older
+versions of Perl contain bugs that may manifest themselves despite using the
+latest version of L<threads> from CPAN.  There is no workaround for this other
+than upgrading to the lastest version of Perl.
+
+(Before you consider posting a bug report, please consult, and possibly post a
+message to the discussion forum to see if what you've encountered is a known
+problem.)
 
 =back
 
-=head1 AUTHOR and COPYRIGHT
+=head1 REQUIREMENTS
 
-Arthur Bergman E<lt>sky at nanisky.comE<gt>
+Perl 5.8.0 or later
 
-threads is released under the same license as Perl.
+=head1 SEE ALSO
 
-Thanks to
+L<threads> Discussion Forum on CPAN:
+L<http://www.cpanforum.com/dist/threads>
 
-Richard Soderberg E<lt>perl at crystalflame.netE<gt>
-Helping me out tons, trying to find reasons for races and other weird bugs!
+Annotated POD for L<threads>:
+L<http://annocpan.org/~JDHEDDEN/threads-1.24/shared.pm>
 
-Simon Cozens E<lt>simon at brecon.co.ukE<gt>
-Being there to answer zillions of annoying questions
+L<threads::shared>, L<perlthrtut>
 
-Rocco Caputo E<lt>troc at netrus.netE<gt>
+L<http://www.perl.com/pub/a/2002/06/11/threads.html> and
+L<http://www.perl.com/pub/a/2002/09/04/threads.html>
 
-Vipul Ved Prakash E<lt>mail at vipul.netE<gt>
-Helping with debugging.
+Perl threads mailing list:
+L<http://lists.cpan.org/showlist.cgi?name=iThreads>
 
-please join perl-ithreads@perl.org for more information
+=head1 AUTHOR
 
-=head1 SEE ALSO
+Artur Bergman E<lt>sky AT crucially DOT netE<gt>
+
+threads is released under the same license as Perl.
+
+CPAN version produced by Jerry D. Hedden <jdhedden AT cpan DOT org>
+
+=head1 ACKNOWLEDGEMENTS
+
+Richard Soderberg E<lt>perl AT crystalflame DOT netE<gt> -
+Helping me out tons, trying to find reasons for races and other weird bugs!
+
+Simon Cozens E<lt>simon AT brecon DOT co DOT ukE<gt> -
+Being there to answer zillions of annoying questions
+
+Rocco Caputo E<lt>troc AT netrus DOT netE<gt>
 
-L<threads::shared>, L<perlthrtut>, 
-L<http://www.perl.com/pub/a/2002/06/11/threads.html>,
-L<perlcall>, L<perlembed>, L<perlguts>
+Vipul Ved Prakash E<lt>mail AT vipul DOT netE<gt> -
+Helping with debugging
 
 =cut