use strict;
use warnings;
-our $VERSION = '1.44';
+our $VERSION = '1.71';
my $XS_VERSION = $VERSION;
$VERSION = eval $VERSION;
+# Verify this Perl supports threads
+require Config;
+if (! $Config::Config{useithreads}) {
+ die("This Perl not built to support threads\n");
+}
-BEGIN {
- # Verify this Perl supports threads
- use Config;
- if (! $Config{useithreads}) {
- die("This Perl not built to support threads\n");
- }
-
- # Complain if 'threads' is loaded after 'threads::shared'
- if ($threads::shared::threads_shared) {
- warn <<'_MSG_';
+# 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_
- }
}
-
# Declare that we have been loaded
$threads::threads = 1;
# Handle args
while (my $sym = shift) {
- if ($sym =~ /^stack/i) {
- threads->set_stack_size(shift);
-
- } elsif ($sym =~ /^exit/i) {
- my $flag = shift;
- $threads::thread_exit_only = $flag =~ /^thread/i;
+ if ($sym =~ /^(?:stack|exit)/i) {
+ if (defined(my $arg = shift)) {
+ if ($sym =~ /^stack/i) {
+ threads->set_stack_size($arg);
+ } else {
+ $threads::thread_exit_only = $arg =~ /^thread/i;
+ }
+ } else {
+ require Carp;
+ Carp::croak("threads: Missing argument for option: $sym");
+ }
} elsif ($sym =~ /^str/i) {
import overload ('""' => \&tid);
- } elsif ($sym =~ /(?:all|yield)/) {
+ } elsif ($sym =~ /^(?::all|yield)$/) {
push(@EXPORT, qw(yield));
} else {
# Class method only
if (ref($class)) {
require Carp;
- Carp::croak("Usage: threads->exit(status)");
+ Carp::croak('Usage: threads->exit(status)');
}
$class->set_thread_exit_only(1);
=head1 VERSION
-This document describes threads version 1.44
+This document describes threads version 1.71
=head1 SYNOPSIS
my $thr2 = async { foreach (@files) { ... } };
$thr2->join();
+ if (my $err = $thr2->error()) {
+ warn("Thread error: $err\n");
+ }
# Invoke thread in list context (implicit) so it can return a list
my ($thr) = threads->create(sub { return (qw/a b c/); });
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>.
+are by default thread local. To use shared variables one must also use
+L<threads::shared>:
+
+ use threads;
+ use 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
then using a threads object in a string or a string context (e.g., as a hash
key) will cause its ID to be used as the value:
- use threads qw(stringify);
+ use threads qw(stringify);
- my $thr = threads->create(...);
- print("Thread $thr started...\n"); # Prints out: Thread 1 started...
+ my $thr = threads->create(...);
+ print("Thread $thr started...\n"); # Prints out: Thread 1 started...
=item threads->object($tid)
returns a count of the same.
With a I<true> argument (using C<threads::running>), returns a list of all
-non-detached I<threads> objects that are still running.
+non-joined, non-detached I<threads> objects that are still running.
With a I<false> argument (using C<threads::joinable>), returns a list of all
non-joined, non-detached I<threads> objects that have finished running (i.e.,
C<async> creates a thread to execute the block immediately following
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>
+semicolon after the closing brace. Like C<threads-E<gt>create()>, C<async>
returns a I<threads> object.
+=item $thr->error()
+
+Threads are executed in an C<eval> context. This method will return C<undef>
+if the thread terminates I<normally>. Otherwise, it returns the value of
+C<$@> associated with the thread's execution status in its C<eval> context.
+
=item $thr->_handle()
This I<private> method returns the memory location of the internal thread
threads->exit() if threads->can('exit'); # Thread friendly
exit(status);
-=item use threads 'exit' => 'thread_only'
+=item use threads 'exit' => 'threads_only'
This globally overrides the default behavior of calling C<exit()> inside a
thread, and effectively causes such calls to behave the same as
=item $thr->set_thread_exit_only(boolean)
This can be used to change the I<exit thread only> behavior for a thread after
-it has been created. With a I<true> argument, C<exit()> will cause the only
-the thread to exit. With a I<false> argument, C<exit()> will terminate the
+it has been created. With a I<true> argument, C<exit()> will cause only the
+thread to exit. With a I<false> argument, C<exit()> will terminate the
application.
The I<main> thread is unaffected by this call.
=item threads->set_thread_exit_only(boolean)
-Class method for use inside a thread to changes its own behavior for
-C<exit()>.
+Class method for use inside a thread to change its own behavior for C<exit()>.
The I<main> thread is unaffected by this call.
=item $thr->is_running()
Returns true if a thread is still running (i.e., if its entry point function
-has not yet finished/exited).
+has not yet finished or exited).
=item $thr->is_joinable()
Returns true if the thread has finished running, is not detached and has not
-yet been joined. In other works, the thread is ready to be joined and will
-not I<block>.
+yet been joined. In other words, the thread is ready to be joined, and a call
+to C<$thr-E<gt>join()> will not I<block>.
=item $thr->is_detached()
Because thread creation and thread joining may occur in different contexts, it
may be desirable to state the context explicitly to the thread's entry point
-function. This may be done by calling C<-E<gt>create()> with a parameter hash
+function. This may be done by calling C<-E<gt>create()> with a hash reference
as the first argument:
my $thr = threads->create({'context' => 'list'}, \&foo);
In the above, the threads object is returned to the parent thread in scalar
context, and the thread's entry point function C<foo> will be called in list
-context such that the parent thread can receive a list from the C<-E<gt>join()>
-call. Similarly, if you need the threads object, but your thread will not be
+(array) context such that the parent thread can receive a list (array) from
+the C<-E<gt>join()> call. (C<'array'> is synonymous with C<'list'>.)
+
+Similarly, if you need the threads object, but your thread will not be
returning a value (i.e., I<void> context), you would do the following:
my $thr = threads->create({'context' => 'void'}, \&foo);
...
$thr->join();
-The context type may also be used as the I<key> in the parameter hash followed
+The context type may also be used as the I<key> in the hash reference followed
by a I<true> value:
threads->create({'scalar' => 1}, \&foo);
=head2 threads->wantarray()
-Class method to return the current thread's context. This is the same as
-running L<wantarray()|perlfunc/"wantarray"> in the current thread.
+Class method to return the current thread's context. This returns the same
+value as running L<wantarray()|perlfunc/"wantarray"> inside the current
+thread's entry point function.
=head1 THREAD STACK SIZE
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.
+Note that 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->create({'stack_size' => VALUE}, FUNCTION, ARGS)
-The stack size an individual threads may also be specified. This may be done
-by calling C<-E<gt>create()> with a parameter hash as the first argument:
+To specify a particular stack size for any individual thread, call
+C<-E<gt>create()> with a hash reference as the first argument:
my $thr = threads->create({'stack_size' => 32*4096}, \&foo, @args);
...
}
- # Create a semaphore and send it to a thread
+ # Create a semaphore and pass it to a thread
my $sema = Thread::Semaphore->new();
my $thr = threads->create('thr_func', $sema);
=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 terminated using C<die>.
+point function, or by using C<threads-E<gt>exit()>. For example, the thread
+may have terminated because of an error, or by using C<die>.
=item Using minimum thread stack size of #
=back
-=head1 BUGS
+=head1 BUGS AND LIMITATIONS
+
+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.
=over
+=item Thread-safe modules
+
+See L<perlmod/"Making your module threadsafe"> when creating modules that may
+be used in threaded applications, especially if those modules use non-Perl
+data, or XS code.
+
+=item Using non-thread-safe modules
+
+Unfortunately, you may encounter Perl modules that are not I<thread-safe>.
+For example, they may crash the Perl interpreter during execution, or may dump
+core on termination. Depending on the module and the requirements of your
+application, it may be possible to work around such difficulties.
+
+If the module will only be used inside a thread, you can try loading the
+module from inside the thread entry point function using C<require> (and
+C<import> if needed):
+
+ sub thr_func
+ {
+ require Unsafe::Module
+ # Unsafe::Module->import(...);
+
+ ....
+ }
+
+If the module is needed inside the I<main> thread, try modifying your
+application so that the module is loaded (again using C<require> and
+C<-E<gt>import()>) after any threads are started, and in such a way that no
+other threads are started afterwards.
+
+If the above does not work, or is not adequate for your application, then file
+a bug report on L<http://rt.cpan.org/Public/> against the problematic module.
+
+=item Current working directory
+
+On all platforms except MSWin32, the setting for the current working directory
+is shared among all threads such that changing it in one thread (e.g., using
+C<chdir()>) will affect all the threads in the application.
+
+On MSWin32, each thread maintains its own the current working directory
+setting.
+
+=item Environment variables
+
+Currently, on all platforms except MSWin32, all I<system> calls (e.g., using
+C<system()> or back-ticks) made from threads use the environment variable
+settings from the I<main> thread. In other words, changes made to C<%ENV> in
+a thread will not be visible in I<system> calls made by that thread.
+
+To work around this, set environment variables as part of the I<system> call.
+For example:
+
+ my $msg = 'hello';
+ system("FOO=$msg; echo \$FOO"); # Outputs 'hello' to STDOUT
+
+On MSWin32, each thread maintains its own set of environment variables.
+
=item Parent-child threads
On some platforms, it might not be possible to destroy I<parent> threads while
=over 4
-=item * Perl was been built with C<PERL_OLD_SIGNALS> (see C<perl -V>).
+=item * Perl has been built with C<PERL_OLD_SIGNALS> (see C<perl -V>).
=item * The environment variable C<PERL_SIGNALS> is set to C<unsafe> (see L<perlrun/"PERL_SIGNALS">).
(apparently harmless) warnings of leaked scalar, or all the way up to crashing
of the Perl interpreter.
+=item Returning objects from threads
+
+Returning objects from threads does not work. Depending on the classes
+involved, you may be able to work around this by returning a serialized
+version of the object (e.g., using L<Data::Dumper> or L<Storable>), and then
+reconstituting it in the joining thread. If you're using Perl 5.10.0 or
+later, and if the class supports L<shared objects|threads::shared/"OBJECTS">,
+you can pass them via L<shared queues| Thread::Queue>.
+
+=item END blocks in threads
+
+It is possible to add L<END blocks|perlmod/"BEGIN, UNITCHECK, CHECK, INIT and
+END"> to threads by using L<require|perlfunc/"require VERSION"> or
+L<eval|perlfunc/"eval EXPR"> with the appropriate code. These C<END> blocks
+will then be executed when the thread's interpreter is destroyed (i.e., either
+during a C<-E<gt>join()> call, or at program termination).
+
+However, calling any L<threads> methods in such an C<END> block will most
+likely I<fail> (e.g., the application may hang, or generate an error) due to
+mutexes that are needed to control functionality within the L<threads> module.
+
+For this reason, the use of C<END> blocks in threads is B<strongly>
+discouraged.
+
=item Perl Bugs and the CPAN Version of L<threads>
-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
+Support for threads extends beyond the code in this module (i.e.,
+F<threads.pm> and F<threads.xs>), and into the Perl interpreter 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.
+than upgrading to the latest 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.)
+Even with the latest version of Perl, it is known that certain constructs
+with threads may result in warning messages concerning leaked scalars or
+unreferenced scalars. However, such warnings are harmless, and may safely be
+ignored.
+
+You can search for L<threads> related bug reports at
+L<http://rt.cpan.org/Public/>. If needed submit any new bugs, problems,
+patches, etc. to: L<http://rt.cpan.org/Public/Dist/Display.html?Name=threads>
=back
L<http://www.cpanforum.com/dist/threads>
Annotated POD for L<threads>:
-L<http://annocpan.org/~JDHEDDEN/threads-1.44/threads.pm>
+L<http://annocpan.org/~JDHEDDEN/threads-1.71/threads.pm>
+
+Source repository:
+L<http://code.google.com/p/threads-shared/>
L<threads::shared>, L<perlthrtut>
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 LICENSE
+
+threads is released under the same license as Perl.
+
=head1 ACKNOWLEDGEMENTS
Richard Soderberg E<lt>perl AT crystalflame DOT netE<gt> -