Thread signalling [REVISED]
[p5sagit/p5-mst-13.2.git] / ext / threads / threads.pm
index fdd9c01..5c63d80 100755 (executable)
@@ -1,49 +1,39 @@
 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.)
 
-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.)
+our $VERSION = '1.27';
+my $XS_VERSION = $VERSION;
+$VERSION = eval $VERSION;
 
-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_
+   }
 }
 
-our $VERSION = '1.17';
-
 
 # Load the XS code
 require XSLoader;
-XSLoader::load('threads', $VERSION);
+XSLoader::load('threads', $XS_VERSION);
 
 
 ### Export ###
@@ -57,7 +47,10 @@ sub import
 
     # Handle args
     while (my $sym = shift) {
-        if ($sym =~ /all/) {
+        if ($sym =~ /^stack/) {
+            threads->set_stack_size(shift);
+
+        } elsif ($sym =~ /all/) {
             push(@EXPORT, qw(yield));
 
         } else {
@@ -71,30 +64,33 @@ sub import
         no strict 'refs';
         *{$caller.'::'.$sym} = \&{$sym};
     }
+
+    # Set stack size via environment variable
+    if (exists($ENV{'PERL5_ITHREADS_STACK_SIZE'})) {
+        threads->set_stack_size($ENV{'PERL5_ITHREADS_STACK_SIZE'});
+    }
 }
 
 
 ### Methods, etc. ###
 
-# || 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 (fixed in 5.8.2)
-# should also be faster
-sub async (&;@) { unshift @_,'threads'; goto &new }
+# 'new' is an alias for 'create'
+*new = \&create;
 
-sub object {
-    return undef unless @_ > 1;
-    foreach (threads->list) {
-        return $_ if $_->tid == $_[1];
-    }
-    return undef;
+# '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;
 }
 
-$threads::threads = 1;
-
-# why document 'new' then use 'create' in the tests!
-*create = \&new;
+# Thread object equality checking
+use overload (
+    '==' => \&equal,
+    '!=' => sub { ! equal(@_) },
+    'fallback' => 1
+);
 
 1;
 
@@ -106,11 +102,11 @@ threads - Perl interpreter-based threads
 
 =head1 VERSION
 
-This document describes threads version 1.17
+This document describes threads version 1.27
 
 =head1 SYNOPSIS
 
-    use threads ('yield');
+    use threads ('yield', 'stack_size' => 64*4096);
 
     sub start_thread {
         my @args = @_;
@@ -141,33 +137,38 @@ This document describes threads version 1.17
     yield();
 
     my @threads = threads->list();
+    my $thread_count = threads->list();
 
     if ($thr1 == $thr2) {
         ...
     }
 
+    $stack_size = threads->get_stack_size();
+    $old_size = threads->set_stack_size(32*4096);
+
+    $thr->kill('SIGUSR1');
+
 =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 by default.
+Perl 5.6 introduced something called interpreter threads.  Interpreter threads
+are different from I<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 by default.
 
-Prior to perl 5.8 this has only been available to people embedding
-perl and for emulating fork() on windows.
+Prior to Perl 5.8, this has only been available to people embedding Perl, and
+for emulating fork() on Windows.
 
-The threads API is loosely based on the old Thread.pm API. It is very
-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.
+The I<threads> API is loosely based on the old Thread.pm API. It is very
+important to note that variables are not shared between threads, all variables
+are by default thread local.  To use shared variables one must use
+L<threads::shared>.
 
-It is also important to note that you must enable threads by doing
-C<use threads> as early as possible in the script itself and that it
-is not possible to enable threading inside an C<eval "">, C<do>,
-C<require>, or C<use>.  In particular, if you are intending to share
-variables with threads::shared, you must C<use threads> before you
-C<use threads::shared> and C<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<use
+threads> as early as possible in the script itself, and that it is not
+possible to enable threading inside an C<eval "">, C<do>, C<require>, or
+C<use>.  In particular, if you are intending to share variables with
+L<threads::shared>, you must C<use threads> before you C<use threads::shared>.
+(C<threads> will emit a warning if you do it the other way around.)
 
 =over
 
@@ -236,20 +237,24 @@ 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.)
 
-=item $thread->detach
+Calling C<-E<gt>join()> or C<-E<gt>detach()> on an already joined thread will
+cause an error to be thrown.
+
+=item $thr->detach()
 
-Will make the thread unjoinable, and cause any eventual return value
-to be discarded.
+Makes the thread unjoinable, and causes any eventual return value to be
+discarded.
 
-Calling C<-E<gt>join()> on a detached thread will cause an error to be thrown.
+Calling C<-E<gt>join()> or C<-E<gt>detach()> on an already detached thread
+will cause an error to be thrown.
 
 =item threads->detach()
 
 Class method that allows a thread to detach itself.
 
-=item threads->self
+=item threads->self()
 
-This will return the thread object for the current thread.
+Class method that allows a thread to obtain its own I<threads> object.
 
 =item $thr->tid()
 
@@ -267,57 +272,270 @@ 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();
+=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()
 
-This will return a list of all non joined, non detached threads.
+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 form:
+to the more natural forms:
 
     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
 
+=head1 THREAD STACK SIZE
+
+The default per-thread stack size for different platforms varies
+significantly, and is almost always far more than is needed for most
+applications.  On Win32, Perl's makefile explicitly sets the default stack to
+16 MB; on most other platforms, the system default is used, which again may be
+much larger than is needed.
+
+By tuning the stack size to more accurately reflect your application's needs,
+you may significantly reduce your application's memory usage, and increase the
+number of simultaneously running threads.
+
+N.B., on Windows, Address space allocation granularity is 64 KB, therefore,
+setting the stack smaller than that on Win32 Perl will not save any more
+memory.
+
+=over
+
+=item threads->get_stack_size();
+
+Returns the current default per-thread stack size.  The default is zero, which
+means the system default stack size is currently in use.
+
+=item $size = $thr->get_stack_size();
+
+Returns the stack size for a particular thread.  A return value of zero
+indicates the system default stack size was used for the thread.
+
+=item $old_size = threads->set_stack_size($new_size);
+
+Sets a new default per-thread stack size, and returns the previous setting.
+
+Some platforms have a minimum thread stack size.  Trying to set the stack size
+below this value will result in a warning, and the minimum stack size will be
+used.
+
+Some Linux platforms have a maximum stack size.  Setting too large of a stack
+size will cause thread creation to fail.
+
+If needed, C<$new_size> will be rounded up to the next multiple of the memory
+page size (usually 4096 or 8192).
+
+Threads created after the stack size is set will then either call
+C<pthread_attr_setstacksize()> I<(for pthreads platforms)>, or supply the
+stack size to C<CreateThread()> I<(for Win32 Perl)>.
+
+(Obviously, this call does not affect any currently extant threads.)
+
+=item use threads ('stack_size' => VALUE);
+
+This sets the default per-thread stack size at the start of the application.
+
+=item $ENV{'PERL5_ITHREADS_STACK_SIZE'}
+
+The default per-thread stack size may be set at the start of the application
+through the use of the environment variable C<PERL5_ITHREADS_STACK_SIZE>:
+
+    PERL5_ITHREADS_STACK_SIZE=1048576
+    export PERL5_ITHREADS_STACK_SIZE
+    perl -e'use threads; print(threads->get_stack_size(), "\n")'
+
+This value overrides any C<stack_size> parameter given to C<use threads>.  Its
+primary purpose is to permit setting the per-thread stack size for legacy
+threaded applications.
+
+=item threads->create({'stack_size' => VALUE}, FUNCTION, ARGS)
+
+This change to the thread creation method permits specifying the stack size
+for an individual thread.
+
+=item $thr2 = $thr1->create(FUNCTION, ARGS)
+
+This creates a new thread (C<$thr2>) that inherits the stack size from an
+existing thread (C<$thr1>).  This is shorthand for the following:
+
+    my $stack_size = $thr1->get_stack_size();
+    my $thr2 = threads->create({'stack_size' => $stack_size}, FUNCTION, ARGS);
+
+=back
+
+=head1 THREAD SIGNALLING
+
+If Perl has been compiled to use safe signals (i.e., was not built with
+C<PERL_OLD_SIGNALS> - see C<perl -V>), then signals may be sent and acted upon
+by individual threads.
+
+=over 4
+
+=item $thr->kill('SIG...');
+
+Sends the specified signal to the thread.  Signal names and (positive) signal
+numbers are the same as those supported by
+L<kill()|perlfunc/"kill SIGNAL, LIST">.  For example, 'SIGTERM', 'TERM' and
+(depending on the OS) 15 are all valid arguments to C<-E<gt>kill()>.
+
+Returns the thread object to allow for method chaining:
+
+    $thr->kill('SIG...')->join();
+
+=back
+
+Signal handlers need to be set up in the threads for the signals they are
+expected to act upon.  Here's an example for I<cancelling> a thread:
+
+    use threads;
+
+    # Suppress warning message when thread is 'killed'
+    no warnings 'threads';
+
+    sub thr_func
+    {
+        # Thread 'cancellation' signal handler
+        $SIG{'KILL'} = sub { die("Thread killed\n"); };
+
+        ...
+    }
+
+    # Create a thread
+    my $thr = threads->create('thr_func');
+
+    ...
+
+    # Signal the thread to terminate, and then detach
+    # it so that it will get cleaned up automatically
+    $thr->kill('KILL')->detach();
+
+Here's another example that uses a semaphore to provide I<suspend> and
+I<resume> capabilities:
+
+    use threads;
+    use Thread::Semaphore;
+
+    sub thr_func
+    {
+        my $sema = shift;
+
+        # Thread 'suspend/resume' signal handler
+        $SIG{'STOP'} = sub {
+            $sema->down();      # Thread suspended
+            $sema->up();        # Thread resumes
+        };
+
+        ...
+    }
+
+    # Create a semaphore and send it to a thread
+    my $sema = Thread::Semaphore->new();
+    my $thr = threads->create('thr_func', $sema);
+
+    # Suspend the thread
+    $sema->down();
+    $thr->kill('STOP');
+
+    ...
+
+    # Allow the thread to continue
+    $sema->up();
+
+CAVEAT:  Sending a signal to a thread does not disrupt the operation the
+thread is currently working on:  The signal will be acted upon after the
+current operation has completed.  For instance, if the thread is I<stuck> on
+an I/O call, sending it a signal will not cause the I/O call to be interrupted
+such that the signal is acted up immediately.
+
 =head1 WARNINGS
 
 =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 the return values
+of the created threads by joining them, and only then exit from the main
+thread.
+
+=item Thread creation failed: pthread_create returned #
 
-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.
+See the appropriate I<man> page for C<pthread_create> to determine the actual
+cause for the failure.
+
+=item Thread # terminated abnormally: ...
+
+A thread terminated in some manner other than just returning from its entry
+point function.  For example, the thread may have exited via C<die>.
+
+=item Using minimum thread stack size of #
+
+Some platforms have a minimum thread stack size.  Trying to set the stack size
+below this value will result in the above warning, and the stack size will be
+set to the minimum.
+
+=item Thread creation failed: pthread_attr_setstacksize(I<SIZE>) returned 22
+
+The specified I<SIZE> exceeds the system's maximum stack size.  Use a smaller
+value for the stack size.
 
 =back
 
+If needed, thread warnings can be suppressed by using:
+
+    no warnings 'threads';
+
+in the appropriate scope.
+
 =head1 ERRORS
 
 =over 4
 
-=item This Perl hasn't been configured and built properly for the threads...
+=item This Perl not built to support threads
 
 The particular copy of Perl that you're trying to use was not built using the
 C<useithreads> configuration option.
@@ -327,34 +545,46 @@ 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.)
 
+=item Cannot change stack size of an existing thread
+
+The stack size of currently extant threads cannot be changed, therefore, the
+following results in the above error:
+
+    $thr->set_stack_size($size);
+
+=item Cannot signal other threads without safe signals
+
+The particular copy of Perl that you're trying to use was built using
+C<PERL_OLD_SIGNALS>.  As a result, the C<-E<gt>kill()> signalling method
+cannot be used.
+
+=item Unrecognized signal name: ...
+
+The particular copy of Perl that you're trying to use does not support the
+specified signal being used in a C<-E<gt>kill()> call.
+
 =back
 
 =head1 BUGS
 
 =over
 
-=item Parent-Child threads.
-
-On some platforms it might not be possible to destroy "parent"
-threads while there are still existing child "threads".
+=item Parent-child threads
 
-=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.
+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
 
-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.)
+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<perl -V>),
-signal handling is not threadsafe.
+If your Perl has been built with PERL_OLD_SIGNALS (one has to explicitly add
+that symbol to I<ccflags>, see C<perl -V>), signal handling is not threadsafe.
 
 =item Returning closures from threads
 
@@ -385,7 +615,7 @@ L<threads> Discussion Forum on CPAN:
 L<http://www.cpanforum.com/dist/threads>
 
 Annotated POD for L<threads>:
-L<http://annocpan.org/~JDHEDDEN/threads-1.17/shared.pm>
+L<http://annocpan.org/~JDHEDDEN/threads-1.27/shared.pm>
 
 L<threads::shared>, L<perlthrtut>
 
@@ -395,6 +625,9 @@ L<http://www.perl.com/pub/a/2002/09/04/threads.html>
 Perl threads mailing list:
 L<http://lists.cpan.org/showlist.cgi?name=iThreads>
 
+Stack size discussion:
+L<http://www.perlmonks.org/?node_id=532956>
+
 =head1 AUTHOR
 
 Artur Bergman E<lt>sky AT crucially DOT netE<gt>
@@ -416,4 +649,7 @@ Rocco Caputo E<lt>troc AT netrus DOT netE<gt>
 Vipul Ved Prakash E<lt>mail AT vipul DOT netE<gt> -
 Helping with debugging
 
+Dean Arnold E<lt>darnold AT presicient DOT comE<gt> -
+Stack size API
+
 =cut