X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=ext%2Fthreads%2Fshared%2Fshared.pm;h=83bd92cc579a1422d13413ee92980175523f84b4;hb=81f1a9214bd437d09b9e480cd1e7f6ac27ee2bcd;hp=d9fbcc3edb0bbfd6bdebe8fdb030c7561bee91cf;hpb=aaf3876db79bf446edd52bc20faf44047e53699e;p=p5sagit%2Fp5-mst-13.2.git diff --git a/ext/threads/shared/shared.pm b/ext/threads/shared/shared.pm index d9fbcc3..83bd92c 100644 --- a/ext/threads/shared/shared.pm +++ b/ext/threads/shared/shared.pm @@ -1,91 +1,50 @@ package threads::shared; - use strict; use warnings; use Config; -use Scalar::Util qw(weaken); -use attributes qw(reftype); -BEGIN { - if($Config{'useithreads'} && $Config::threads) { - *share = \&share_enabled; +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'}) { + *cond_wait = \&cond_wait_enabled; + *cond_signal = \&cond_signal_enabled; + *cond_broadcast = \&cond_broadcast_enabled; + require XSLoader; + XSLoader::load('threads::shared',$VERSION); +} +else { + *share = \&share_disabled; *cond_wait = \&cond_wait_disabled; *cond_signal = \&cond_signal_disabled; *cond_broadcast = \&cond_broadcast_disabled; - *unlock = \&unlock_disabled; - *lock = \&lock_disabled; - } else { - *share = \&share_enabled; - } } -require Exporter; -require DynaLoader; -our @ISA = qw(Exporter DynaLoader); - -our @EXPORT = qw(share cond_wait cond_broadcast cond_signal unlock lock); -our $VERSION = '0.01'; - -our %shared; sub cond_wait_disabled { return @_ }; sub cond_signal_disabled { return @_}; sub cond_broadcast_disabled { return @_}; -sub unlock_disabled { 1 }; -sub lock_disabled { 1 } sub share_disabled { return @_} -sub share_enabled (\[$@%]) { # \] - my $value = $_[0]; - my $ref = reftype($value); - if($ref eq 'SCALAR') { - my $obj = \threads::shared::sv->new($$value); - bless $obj, 'threads::shared::sv'; - $shared{$$obj} = $value; - weaken($shared{$$obj}); - } elsif($ref eq "ARRAY") { - tie @$value, 'threads::shared::av', $value; - } else { - die "You cannot share ref of type $_[0]\n"; - } -} +$threads::shared::threads_shared = 1; -sub CLONE { - return unless($_[0] eq "threads::shared"); - foreach my $ptr (keys %shared) { - if($ptr) { - thrcnt_inc($shared{$ptr}); - } - } -} +sub _thrcnt { 42 } -sub DESTROY { - my $self = shift; - delete($shared{$$self}); +sub threads::shared::tie::SPLICE +{ + die "Splice not implemented for shared arrays"; } -package threads::shared::sv; -use base 'threads::shared'; - -sub DESTROY {} - -package threads::shared::av; -use base 'threads::shared'; -use Scalar::Util qw(weaken); -sub TIEARRAY { - my $class = shift; - my $value = shift; - my $self = bless \threads::shared::av->new($value),'threads::shared::av'; - $shared{$self->ptr} = $value; - weaken($shared{$self->ptr}); - return $self; +sub UNIVERSAL::shared : ATTR { + my ($package, $symbol, $referent, $attr, $data, $phase) = @_; + share($referent); } -package threads::shared::hv; -use base 'threads::shared'; - -bootstrap threads::shared $VERSION; - __END__ =head1 NAME @@ -103,11 +62,11 @@ threads::shared - Perl extension for sharing data structures between threads my $bar = share([]); $hash{bar} = share({}); - lock(\%hash); - unlock(\%hash); + lock(%hash); + unlock(%hash); cond_wait($scalar); - cond_broadcast(\@array); - cond_signal($scalar); + cond_broadcast(@array); + cond_signal(%hash); =head1 DESCRIPTION @@ -115,13 +74,95 @@ 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. -=head2 EXPORT +=head1 EXPORT + +C, C, C, C, C, C + +=head1 FUNCTIONS + +=over 4 + +=item share VARIABLE + +C takes a value and marks it as shared, you can share a scalar, array, hash +scalar ref, array ref and hash ref, C will return the shared value. + +C will traverse up references exactly I level. +C is equivalent to C, while C is not. + +=item lock VARIABLE + +C places a lock on a variable until the lock goes out of scope. If +the variable is locked by another thread, the C call will block until +it's available. C is recursive, so multiple calls to C are +safe--the variable will remain locked until the outermost lock on the +variable goes out of scope or C is called enough times to match +the number of calls to . + +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, any other thread doing a C won't block. -share(), lock(), unlock(), cond_wait, cond_signal, cond_broadcast +C will traverse up references exactly I level. +C is equivalent to C, while C is not. + + +=item unlock VARIABLE + +C 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 but it can be usefull to reduce lock contention. + +C will traverse up references exactly I level. +C is equivalent to C, while C is not. + +=item cond_wait VARIABLE + +The C function takes a B variable as a parameter, +unlocks the variable, and blocks until another thread does a C +or C for that same locked variable. The variable that +C blocked on is relocked after the C is satisfied. +If there are multiple threads Cing on the same variable, all but +one will reblock waiting to reaquire the lock on the variable. (So if +you're only using C for synchronization, give up the lock as +soon as possible) + +It is important to note that the variable can be notified even if no +thread C or C 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. + +=item cond_signal VARIABLE + +The C function takes a B variable as a parameter and +unblocks one thread that's Cing on that variable. If more than +one thread is blocked in a C on that variable, only one (and +which one is indeterminate) will be unblocked. + +If there are no threads blocked in a C on the variable, the +signal is discarded. + +=item cond_broadcast VARIABLE + +The C function works similarly to C. +C, though, will unblock B the threads that are blocked +in a C on the locked variable, rather than only one. + + +=head1 NOTES + +threads::shared is designed to disable itself silently if threads are +not available. If you want access to threads, you must C +before you C. threads will emit a warning if you +use it after threads::shared. =head1 BUGS -Not stress tested! +C is not supported on shared references, in the current version +C 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. + Does not support splice on arrays! =head1 AUTHOR @@ -130,8 +171,15 @@ Arthur Bergman Earthur at contiller.seE threads::shared is released under the same license as Perl +Documentation borrowed from Thread.pm + =head1 SEE ALSO L L =cut + + + + +