use 5.007_003;
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 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
- }
-}
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(share cond_wait cond_broadcast cond_signal _refcnt _id _thrcnt);
our $VERSION = '0.90';
-use Attribute::Handlers;
-
-
-if ($Config{'useithreads'}) {
+if ($threads::threads) {
*cond_wait = \&cond_wait_enabled;
*cond_signal = \&cond_signal_enabled;
*cond_broadcast = \&cond_broadcast_enabled;
$threads::shared::threads_shared = 1;
-sub _thrcnt { 42 }
sub threads::shared::tie::SPLICE
{
die "Splice not implemented for shared arrays";
}
-sub UNIVERSAL::shared : ATTR {
- my ($package, $symbol, $referent, $attr, $data, $phase) = @_;
- share($referent);
-}
-
__END__
=head1 NAME
use threads;
use threads::shared;
- my($foo, @foo, %foo);
- share($foo);
- share(@foo);
+ my $var : shared;
+
+ my($scalar, @array, %hash);
+ share($scalar);
+ share(@array);
share(%hash);
- my $bar = share([]);
- $hash{bar} = share({});
+ my $bar = &share([]);
+ $hash{bar} = &share({});
+
+ { lock(%hash); ... }
- lock(%hash);
- unlock(%hash);
cond_wait($scalar);
cond_broadcast(@array);
cond_signal(%hash);
=head1 DESCRIPTION
-This modules allows you to share() variables. These variables will
-then be shared across different threads (and pseudoforks on
-win32). They are used together with the threads module.
+By default, variables are private to each thread, and each newly created
+thread gets a private copy of each existing variable. This module allows
+you to share variables across different threads (and pseudoforks on
+win32). It is used together with the threads module.
=head1 EXPORT
-C<share>, C<lock>, C<unlock>, C<cond_wait>, C<cond_signal>, C<cond_broadcast>
+C<share>, C<lock>, C<cond_wait>, C<cond_signal>, C<cond_broadcast>
+
+Note that if this module is imported when C<threads> has not yet been
+loaded, then these functions all become no-ops. This makes it possible to
+write modules that will work in both threaded and non-threaded
+environments.
=head1 FUNCTIONS
=item share VARIABLE
-C<share> takes a value and marks it as shared, you can share a scalar, array, hash
-scalar ref, array ref and hash ref, C<share> will return the shared value.
+C<share> takes a value and marks it as shared. You can share a scalar,
+array, hash, scalar ref, array ref or hash ref. C<share> will return
+the shared rvalue.
C<share> will traverse up references exactly I<one> level.
C<share(\$a)> is equivalent to C<share($a)>, while C<share(\\$a)> is not.
+A variable can also be marked as shared at compile time by using the
+C<shared> attribute: C<my $var : shared>.
+
+If you want to share a newly created reference unfortunately you
+need to use C<&share([])> and C<&share({})> syntax due to problems
+with Perl's prototyping.
+
=item lock VARIABLE
C<lock> places a lock on a variable until the lock goes out of scope. If
the variable is locked by another thread, the C<lock> call will block until
it's available. C<lock> is recursive, so multiple calls to C<lock> are
-safe--the variable will remain locked until the outermost lock on the
-variable goes out of scope or C<unlock> is called enough times to match
-the number of calls to <lock>.
+safe -- the variable will remain locked until the outermost lock on the
+variable goes out of scope.
If a container object, such as a hash or array, is locked, all the elements
of that container are not locked. For example, if a thread does a C<lock
C<lock> will traverse up references exactly I<one> level.
C<lock(\$a)> is equivalent to C<lock($a)>, while C<lock(\\$a)> is not.
-
-=item unlock VARIABLE
-
-C<unlock> takes a locked shared value and decrements the lock count.
-If the lock count is zero the variable is unlocked. It is not necessary
-to call C<unlock> but it can be usefull to reduce lock contention.
-
-C<unlock> will traverse up references exactly I<one> level.
-C<unlock(\$a)> is equivalent to C<unlock($a)>, while C<unlock(\\$a)> is not.
+Note that you cannot explicitly unlock a variable; you can only wait for
+the lock to go out of scope. If you need more fine-grained control, see
+L<threads::shared::semaphore>.
=item cond_wait VARIABLE
or C<cond_broadcast> for that same locked variable. The variable that
C<cond_wait> blocked on is relocked after the C<cond_wait> is satisfied.
If there are multiple threads C<cond_wait>ing on the same variable, all but
-one will reblock waiting to reaquire the lock on the variable. (So if
-you're only using C<cond_wait> for synchronization, give up the lock as
-soon as possible)
+one will reblock waiting to reacquire the lock on the variable. (So if
+you're only using C<cond_wait> for synchronisation, give up the lock as
+soon as possible). The two actions of unlocking the variable and entering
+the blocked wait state are atomic, The two actions of exiting from the
+blocked wait state and relocking the variable are not.
It is important to note that the variable can be notified even if no
thread C<cond_signal> or C<cond_broadcast> on the variable. It is therefore
important to check the value of the variable and go back to waiting if the
-requirment is not fullfilled.
+requirement is not fulfilled.
=item cond_signal VARIABLE
which one is indeterminate) will be unblocked.
If there are no threads blocked in a C<cond_wait> on the variable, the
-signal is discarded.
+signal is discarded. By always locking before signaling, you can (with
+care), avoid signaling before another thread has entered cond_wait().
+
+C<cond_signal> will normally generate a warning if you attempt to use it
+on an unlocked variable. On the rare occasions where doing this may be
+sensible, you can skip the warning with
+
+ { no warnings 'threads'; cond_signal($foo) }
=item cond_broadcast VARIABLE
C<cond_broadcast>, though, will unblock B<all> the threads that are blocked
in a C<cond_wait> on the locked variable, rather than only one.
+=back
=head1 NOTES
=head1 BUGS
-C<bless> is not supported on shared references, in the current version
+C<bless> is not supported on shared references. In the current version,
C<bless> will only bless the thread local reference and the blessing
-will not propagate to the other threads, this is expected to be implmented
-in the future.
+will not propagate to the other threads. This is expected to be
+implemented in a future version of Perl.
Does not support splice on arrays!
+Taking references to the elements of shared arrays and hashes does not
+autovivify the elements, and neither does slicing a shared array/hash
+over non-existent indices/keys autovivify the elements.
+
=head1 AUTHOR
Arthur Bergman E<lt>arthur at contiller.seE<gt>
threads::shared is released under the same license as Perl
-Documentation borrowed from Thread.pm
+Documentation borrowed from the old Thread.pm
=head1 SEE ALSO
-L<perl> L<threads>
+L<threads>, L<perlthrtut>, L<http://www.perl.com/pub/a/2002/06/11/threads.html>
=cut
-
-
-
-
-