use strict;
use warnings;
-our $VERSION = '1.34';
+our $VERSION = '1.57';
my $XS_VERSION = $VERSION;
$VERSION = eval $VERSION;
die("This Perl not built to support threads\n");
}
- # Declare that we have been loaded
- $threads::threads = 1;
-
# Complain if 'threads' is loaded after 'threads::shared'
if ($threads::shared::threads_shared) {
warn <<'_MSG_';
}
+# Declare that we have been loaded
+$threads::threads = 1;
+
# Load the XS code
require XSLoader;
XSLoader::load('threads', $XS_VERSION);
# Handle args
while (my $sym = shift) {
- if ($sym =~ /^stack/) {
+ if ($sym =~ /^stack/i) {
threads->set_stack_size(shift);
- } elsif ($sym =~ /all/) {
+ } elsif ($sym =~ /^exit/i) {
+ my $flag = shift;
+ $threads::thread_exit_only = $flag =~ /^thread/i;
+
+ } elsif ($sym =~ /^str/i) {
+ import overload ('""' => \&tid);
+
+ } elsif ($sym =~ /(?:all|yield)/) {
push(@EXPORT, qw(yield));
} else {
- push(@EXPORT, $sym);
+ require Carp;
+ Carp::croak("threads: Unknown import option: $sym");
}
}
### Methods, etc. ###
-# Our own exit function/method
+# Exit from a thread (only)
sub exit
{
- CORE::exit(0);
+ my ($class, $status) = @_;
+ if (! defined($status)) {
+ $status = 0;
+ }
+
+ # Class method only
+ if (ref($class)) {
+ require Carp;
+ Carp::croak("Usage: threads->exit(status)");
+ }
+
+ $class->set_thread_exit_only(1);
+ CORE::exit($status);
}
# 'Constant' args for threads->list()
=head1 VERSION
-This document describes threads version 1.34
+This document describes threads version 1.57
=head1 SYNOPSIS
- use threads ('yield', 'stack_size' => 64*4096);
+ use threads ('yield',
+ 'stack_size' => 64*4096,
+ 'exit' => 'threads_only',
+ 'stringify');
sub start_thread {
my @args = @_;
print('Thread started: ', join(' ', @args), "\n");
}
- my $thread = threads->create('start_thread', 'argument');
- $thread->join();
+ my $thr = threads->create('start_thread', 'argument');
+ $thr->join();
threads->create(sub { print("I am a thread\n"); })->join();
- my $thread3 = async { foreach (@files) { ... } };
- $thread3->join();
+ 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/); });
sub { return (qw/a b c/); });
my @results = $thr->join();
- $thread->detach();
+ $thr->detach();
- $thread = threads->self();
- $thread = threads->object($tid);
+ # Get a thread's object
+ $thr = threads->self();
+ $thr = threads->object($tid);
+ # Get a thread's ID
$tid = threads->tid();
- $tid = threads->self->tid();
- $tid = $thread->tid();
+ $tid = $thr->tid();
+ $tid = "$thr";
+ # Give other threads a chance to run
threads->yield();
yield();
+ # Lists of non-detached threads
my @threads = threads->list();
my $thread_count = threads->list();
my @running = threads->list(threads::running);
my @joinable = threads->list(threads::joinable);
+ # Test thread objects
if ($thr1 == $thr2) {
...
}
+ # Manage thread stack size
$stack_size = threads->get_stack_size();
$old_size = threads->set_stack_size(32*4096);
# Create a thread with a specific context and stack size
my $thr = threads->create({ 'context' => 'list',
- 'stack_size' => 32*4096 },
+ 'stack_size' => 32*4096,
+ 'exit' => 'thread_only' },
\&foo);
# Get thread's context
$thr->join();
}
+ # Send a signal to a thread
$thr->kill('SIGUSR1');
+ # Exit a thread
threads->exit();
=head1 DESCRIPTION
Class method that allows a thread to detach itself.
-=item threads->exit()
-
-The usual method for terminating a thread is to
-L<return()|perlfunc/"return EXPR"> from the entry point function with the
-appropriate return value(s).
-
-If needed, a thread can be exited at any time by calling
-C<threads-E<gt>exit()>. This will cause the thread to return C<undef> in a
-scalar context, or the empty list in a list context.
-
-Calling C<die()> in a thread indicates an abnormal exit for the thread. Any
-C<$SIG{__DIE__}> handler in the thread will be called first, and then the
-thread will exit with a warning message that will contain any arguments passed
-in the C<die()> call.
-
-Calling C<exit()> in a thread is discouraged, but is equivalent to calling
-C<threads-E<gt>exit()>.
-
-If the desired affect is to truly terminate the application from a thread,
-then use L<POSIX::_exit()|POSIX/"_exit">, if available.
-
=item threads->self()
Class method that allows a thread to obtain its own I<threads> object.
Class method that allows a thread to obtain its own ID.
+=item "$thr"
+
+If you add the C<stringify> import option to your C<use threads> declaration,
+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);
+
+ my $thr = threads->create(...);
+ print("Thread $thr started...\n"); # Prints out: Thread 1 started...
+
=item threads->object($tid)
This will return the I<threads> object for the I<active> thread associated
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.,
semi-colon after the closing brace. Like C<threads->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
=back
+=head1 EXITING A THREAD
+
+The usual method for terminating a thread is to
+L<return()|perlfunc/"return EXPR"> from the entry point function with the
+appropriate return value(s).
+
+=over
+
+=item threads->exit()
+
+If needed, a thread can be exited at any time by calling
+C<threads-E<gt>exit()>. This will cause the thread to return C<undef> in a
+scalar context, or the empty list in a list context.
+
+When called from the I<main> thread, this behaves the same as C<exit(0)>.
+
+=item threads->exit(status)
+
+When called from a thread, this behaves like C<threads-E<gt>exit()> (i.e., the
+exit status code is ignored).
+
+When called from the I<main> thread, this behaves the same as C<exit(status)>.
+
+=item die()
+
+Calling C<die()> in a thread indicates an abnormal exit for the thread. Any
+C<$SIG{__DIE__}> handler in the thread will be called first, and then the
+thread will exit with a warning message that will contain any arguments passed
+in the C<die()> call.
+
+=item exit(status)
+
+Calling L<exit()|perlfunc/"exit EXPR"> inside a thread causes the whole
+application to terminate. Because of this, the use of C<exit()> inside
+threaded code, or in modules that might be used in threaded applications, is
+strongly discouraged.
+
+If C<exit()> really is needed, then consider using the following:
+
+ threads->exit() if threads->can('exit'); # Thread friendly
+ exit(status);
+
+=item use threads 'exit' => 'thread_only'
+
+This globally overrides the default behavior of calling C<exit()> inside a
+thread, and effectively causes such calls to behave the same as
+C<threads-E<gt>exit()>. In other words, with this setting, calling C<exit()>
+causes only the thread to terminate.
+
+Because of its global effect, this setting should not be used inside modules
+or the like.
+
+The I<main> thread is unaffected by this setting.
+
+=item threads->create({'exit' => 'thread_only'}, ...)
+
+This overrides the default behavior of C<exit()> inside the newly created
+thread only.
+
+=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
+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()>.
+
+The I<main> thread is unaffected by this call.
+
+=back
+
=head1 THREAD STATE
The following boolean methods are useful in determining the I<state> of a
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"); };
+ $SIG{'KILL'} = sub { threads->exit(); };
...
}
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.
+Sending a signal to a terminated thread is ignored.
+
=head1 WARNINGS
=over 4
If the program exits without all threads having either been joined or
detached, then this warning will be issued.
-NOTE: This warning cannot be suppressed using C<no warnings 'threads';> as
-suggested below.
+NOTE: If the I<main> thread exits, then this warning cannot be suppressed
+using C<no warnings 'threads';> as suggested below.
=item Thread creation failed: pthread_create returned #
=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 a 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 Using non-threadsafe modules
+
+Unfortunately, you may encounter Perl modules are not I<threadsafe>. 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
+ # import Unsafe::Module ...;
+
+ ....
+ }
+
+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<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 Parent-child threads
On some platforms, it might not be possible to destroy I<parent> threads while
(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.
+
=item Perl Bugs and the CPAN Version of L<threads>
Support for threads extents beyond the code in this module (i.e.,
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 REQUIREMENTS
L<http://www.cpanforum.com/dist/threads>
Annotated POD for L<threads>:
-L<http://annocpan.org/~JDHEDDEN/threads-1.34/threads.pm>
+L<http://annocpan.org/~JDHEDDEN/threads-1.57/threads.pm>
L<threads::shared>, L<perlthrtut>